diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc1b9dc..1dae6a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,8 +36,8 @@ jobs: version: "${{ matrix.NXF_VER }}" - name: Run pipeline with test data - # TODO nf-core: You can customise CI pipeline run tests as required - # For example: adding multiple test runs with different parameters - # Remember that you can parallelise this by using strategy.matrix + # The bundled assets/stub/ inputs are truncated placeholders, not real data, so this + # is a DAG/wiring check via each module's stub block rather than a data test. + # -entry OFFTARGET and -entry TRAIN are covered separately by offtarget-ci.yml. run: | - nextflow run ${GITHUB_WORKSPACE} -profile test,docker --outdir ./results + nextflow run ${GITHUB_WORKSPACE} -profile test,docker -stub-run --outdir ./results diff --git a/.github/workflows/offtarget-ci.yml b/.github/workflows/offtarget-ci.yml new file mode 100644 index 0000000..60d6eca --- /dev/null +++ b/.github/workflows/offtarget-ci.yml @@ -0,0 +1,148 @@ +name: offtarget CI +# Exercises the -entry OFFTARGET workflow that the default nf-core CI does not cover: +# 1. stub run — DAG wiring for all three modes (paired / wgs_only / ecs_only) +# 2. glue tests — the ECS<->WGS join logic (tests/test_offtarget_glue.py) +# 3. nf-test — REAL process bodies in the real container, on KB-sized fixtures +# +# (1) and (3) are complementary and neither replaces the other: a stub run only `touch`es +# outputs, so it proves the DAG connects but executes no line of bin/*.py; nf-test runs the +# actual command, so it catches a module passing a flag the script does not accept. +on: + push: + branches: + - dev + - "feat/offtarget-**" + pull_request: + paths: + - "workflows/offtarget.nf" + - "subworkflows/local/**" + - "modules/local/**" + - "bin/**" + - "tests/**" + - "conf/stub.config" + - "nf-test.config" + - "assets/offtarget_samplesheet_template.csv" + - ".github/workflows/offtarget-ci.yml" + +env: + NXF_ANSI_LOG: false + +concurrency: + group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" + cancel-in-progress: true + +jobs: + stub: + name: OFFTARGET stub run (DAG wiring, all modes) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Nextflow + uses: nf-core/setup-nextflow@v1 + with: + # pin a stable release: the repo config's check_max() doesn't parse under the + # 26.x edge that "latest-everything" now resolves to. + version: "25.10.4" + + # stub blocks only `touch` their outputs, so no container/data is needed — this is a + # pure wiring check. Derive single-arm sheets from the template to hit every mode. + - name: Build per-mode samplesheets + run: | + SS=assets/offtarget_samplesheet_template.csv + head -1 "$SS" | tee ss_wgs.csv > ss_ecs.csv + grep -iE ',wgs,' "$SS" >> ss_wgs.csv + grep -iE ',ecs,' "$SS" >> ss_ecs.csv + + - name: Stub run — paired + run: nextflow run . -entry OFFTARGET -profile stub -stub-run --input "$SS" --outdir out_paired + env: + SS: assets/offtarget_samplesheet_template.csv + - name: Stub run — wgs_only + run: nextflow run . -entry OFFTARGET -profile stub -stub-run --input ss_wgs.csv --outdir out_wgs + - name: Stub run — ecs_only + run: nextflow run . -entry OFFTARGET -profile stub -stub-run --input ss_ecs.csv --outdir out_ecs + # ecs rows with a spacer but no target_file auto-generate the hotspot VCF (once per guide) + - name: Stub run — ecs target_file auto-wire from spacer + run: | + nextflow run . -entry OFFTARGET -profile stub -stub-run \ + --input assets/stub/offtarget_autowire.csv --fasta assets/stub/tiny.fa --outdir out_autowire + + hotspots-stub: + name: HOTSPOTS stub run (gRNA -> targets DAG wiring) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Nextflow + uses: nf-core/setup-nextflow@v1 + with: + version: "25.10.4" + + # stub blocks only `touch`/`printf` their outputs, so no container/genome is needed. + # Point --fasta at the tiny committed fixture (the real /storage2 reference is absent on CI). + - name: Stub run — Cas-OFFinder only (default) + run: | + nextflow run . -entry HOTSPOTS -profile stub -stub-run \ + --input assets/grna_samplesheet_template.csv \ + --fasta assets/stub/tiny.fa --outdir out_hotspots + - name: Stub run — with CRISPRme enabled + run: | + mkdir -p crisprme_idx + nextflow run . -entry HOTSPOTS -profile stub -stub-run \ + --input assets/grna_samplesheet_template.csv \ + --fasta assets/stub/tiny.fa --run_crisprme --crisprme_index_dir crisprme_idx \ + --outdir out_hotspots_cme + + glue-tests: + name: OFFTARGET glue-logic + combiner unit tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + # the glue scripts are pure-pandas; a clean checkout has no repo-root vendored dirs to shadow. + # scikit-learn is needed by bin/offtarget_metrics.py (PR-AUC / ROC-AUC); the + # off-target container pins 1.8.0, but here any recent version is fine since + # nothing unpickles a model in these tests. + - name: Install test deps + run: python -m pip install --quiet pandas matplotlib pytest openpyxl scikit-learn + + - name: Run glue + combiner tests + run: python -m pytest -q tests/test_offtarget_glue.py tests/test_combine_offtarget.py + + nf-test: + name: nf-test (real process bodies, real container) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Nextflow + uses: nf-core/setup-nextflow@v1 + with: + version: "25.10.4" + + # Installed straight from the vendor rather than via an action, so this step does + # not depend on a third-party action's input schema. The trailing argument pins + # the version; drop it to track latest (not recommended for a reproducible CI). + - name: Install nf-test + run: | + curl -fsSL https://code.askimed.com/install/nf-test | bash -s 0.9.5 + sudo mv nf-test /usr/local/bin/ + nf-test version + + # ghcr.io/dhslab/docker-scge-offtarget is publicly readable, so no login is needed. + # Pull it up front: a first-use pull inside a process makes a timeout look like a + # test failure, and the image is shared by every test here. + - name: Pre-pull the off-target container + run: docker pull ghcr.io/dhslab/docker-scge-offtarget:260710 + + # Fixtures are ~6 KB (tests/fixtures/), so this is a couple of minutes on a 2-CPU + # runner. `stub` supplies the params profile — it nulls the /storage2 DRAGEN paths + # that workflows/scge.nf validates at parse time — while `docker` supplies the + # engine. Neither implies -stub-run; the process bodies really execute. + - name: Run nf-test + run: nf-test test --profile stub,docker --verbose diff --git a/.gitignore b/.gitignore index 5533f03..c3a7f37 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,112 @@ +# ============================================================================= +# nf-core-scge — .gitignore +# Pattern-based. Root-anchored (leading /) entries are one-off local files that +# are intentionally kept out of git; delete or commit them deliberately. +# ============================================================================= + +# ---- Agent / tooling scratch ---- +# Claude Code keeps per-repo settings AND full worktree checkouts under .claude/ +# (each with its own .nextflow logs and work dirs) — hundreds of MB that must never +# be swept into a commit by `git add -A`. +.claude/ + +# ---- nf-test ---- +# nf-test writes a per-test scratch .nf file into the REPO ROOT (one per test id) and +# keeps its work dir in .nf-test/. Both are build artifacts of a test run, and there +# are ~100 of the scratch files after a full suite. +.nf-test/ +.nf-test-*.nf +.nf-test.log + +# ---- Nextflow runtime ---- .nextflow* work/ -data/ results/ -.DS_Store +results*/ +null/ +nxf-tmp.* + +# ---- Data & large / generated inputs ---- +data/ +logs/ testing/ testing* +mastersheets/ +test_output/ +test_results* +test_logs/ +test_mastersheets/ +test_null/ + +# ---- Python (vendored envs, caches, build metadata) ---- +__pycache__/ *.pyc -.dir_bash_history +*.dist-info/ +*.libs/ +.pytest_cache/ +# local test venv/cache created by run_offtarget_tests.sh +.offtarget_testenv*/ +.offtarget_testcache/ + +# ---- Scheduler / process logs ---- +*.log +*.err + +# ---- OS / editor ---- +.DS_Store +/.dir_bash_history + +# ---- Local-only files: not part of the pipeline ---- +/CLAUDE.md +/REPO_INVENTORY.md +/DEBUGGING_REPORT.md +/to_commit.md +/pipeline_explanation.txt +/Groovy vs. Shell in Nextflow.txt +/minimal.config +/flowchart.dot +/extracted_indels.json +/versions.yml +/build.sh +/nextflow +/-e +/s +/err.txt +/AAVS1site14_WTcas9-DNA.scge_report_ml.html +/AAVS1site14_WTcas9-DNA.scge_report_og.html +/analysis_samples.csv +/mastersheet.*.csv +/offtarget_samplesheet_aavs1.csv +/mock_dragen_dir/ +/aavs1_ml_testing/ +/training_data/ +/run.sh +/run_all.sh +/run_test.sh +/run_offtarget_aavs1.sh +/test_syntax.nf +/test_versions.nf + +# ---- Legacy CRISPR-ML scripts / models (deprecated; see REPO_INVENTORY.md) ---- +bin/*.bak +bin/build_from_curated_tsv.py +bin/build_training_from_tsv.py +bin/convert_targets.pl +bin/train_aavs1_v3.sh +bin/train_aavs1_v3_lsf.sh +bin/tsv_to_vcf.py +assets/NO_*.csv +assets/NO_*.tsv +assets/empty*.txt +assets/all_samples_mastersheet.csv +assets/ecs_samples_mastersheet.csv +assets/models/crispr_model_*.pkl +assets/models/crispr_model_*_cv_summary.csv +assets/stub/AAVS1_site14.targets.csv +assets/stub/aavs1site14_samplesheet.csv + +# ---- nf-core plugin cache ---- +subworkflows/nf-core/utils_nfschema_plugin/ + +# ---- Large committed-doc screenshots ---- +docs/images/Screenshot*.png diff --git a/README.md b/README.md index 9484164..87622ec 100644 --- a/README.md +++ b/README.md @@ -1,121 +1,214 @@

- nf-core/scge + nf-core/scge

-[![GitHub Actions CI Status](https://github.com/nf-core/scge/workflows/nf-core%20CI/badge.svg)](https://github.com/nf-core/scge/actions?query=workflow%3A%22nf-core+CI%22) -[![GitHub Actions Linting Status](https://github.com/nf-core/scge/workflows/nf-core%20linting/badge.svg)](https://github.com/nf-core/scge/actions?query=workflow%3A%22nf-core+linting%22)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/scge/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A523.04.0-23aa62.svg)](https://www.nextflow.io/) -[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) -[![Launch on Nextflow Tower](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Nextflow%20Tower-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/scge) - -[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23scge-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/scge)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) ## Introduction -**nf-core/scge** is a bioinformatics pipeline that ... - - - - - - -1. Runs tumor normal dragen -2. Get Indels -3. Get Transgene Junctions -4. Annotate Transgene Variants -5. Annotate sv, cnv, hard-filtered vcf -6. Makes vep to tsv file -7. Makes scge report +**dhslab/nf-core-scge** is a Nextflow DSL2 pipeline for **somatic cell genome editing (SCGE)** +analysis. It takes tumor (edited) / normal (unedited) sequencing through DRAGEN alignment +(optional) and characterises the consequences of CRISPR editing: on/off-target edits, +transgene integration, and genome-wide structural and copy-number changes, then compiles a +per-sample HTML report. It is built for the WashU RIS clusters (Compute1/LSF, Compute2/SLURM) +and AWS Batch. + +The pipeline has **two entry points**: + +1. **`SCGE`** (default) — the full per-sample analysis and report. +2. **`OFFTARGET`** (`-entry OFFTARGET`) — a two-assay (ECS + WGS) investigation arm: a WGS hotspot + edit-confirmation model trained on error-corrected ECS truth, plus a genome-wide, PoN-filtered + worklist. Validated end-to-end on a real AAVS1 run: the on-target is recovered from WGS alone, as + is the one confirmed off-target we have (PLCB2 chr12:32,679,410, 90% VAF). Real off-targets are + rare and high-VAF in both cohorts, so a sub-5% floor is unproven — trust WGS-only calls at + hotspots **≥5% VAF**. Full details in [`docs/OFFTARGET.md`](docs/OFFTARGET.md); how to run it, the + landmines and the open threads are in [`docs/HANDOFF.md`](docs/HANDOFF.md). + +## Pipeline summary + +**Default `SCGE` workflow** (`workflows/scge.nf`): + +1. **DRAGEN** tumor/normal alignment + small-variant / SV / CNV calling *(optional; `--run_alignment false` to skip)* +2. **VEP** annotation of SNVs/indels, SVs, and CNVs → TSV +3. **Off-target editing** detection at nominated sites (`GET_INDELS`) +4. **Transgene** integration-junction identification and annotation +5. **CNA / BAF** plots and a **Circos** genome overview +6. **Report**: results compiled to JSON (`COMPILE_REPORT_JSON`) and rendered to HTML (Quarto) +7. **MultiQC** aggregate QC + +![SCGE analysis DAG](docs/images/scge_analysis_DAG.jpg) + +**`OFFTARGET` workflow** (`workflows/offtarget.nf`): `ECS_INDELS` (error-corrected truth VAF at +hotspots) + `WGS_WORKLIST` → `PON_OFFTARGET_FILTER` (genome-wide, homology-free, Panel-of-Normals +filtered worklist) → per-hotspot WGS scoring → `training.tsv` (WGS features × ECS VAF) → a +recall-vs-VAF curve and a reconciled report. Full details in +[`docs/OFFTARGET.md`](docs/OFFTARGET.md). + + + + Unified CRISPR Off-Target Workflow metro map + ## Usage -To run at dragen step, prepare a samplesheet with the following columns: +### Default SCGE pipeline -`dragen_samplesheet.csv`: +**Alignment + analysis** — samplesheet with one tumor and one normal row per case (shared `uid`): ```csv id,uid,sample_type,fastq_list,hotspot_file -tumor_sample_1,tumor_sample_1,tumor,/path/to/fastqlist,/path/to/hotspot_1 -normal_sample,tumor_sample_1,normal,/path/to/fastqlist,/path/to/hotspot_1 -tumor_sample_2,tumor_sample_2,tumor,/path/to/fastqlist,/path/to/hotspot_2 -normal_sample,tumor_sample_2,normal,/path/to/fastqlist,/path/to/hotspot_2 +tumor_sample_1,case1,tumor,/path/to/fastq_list.csv,/path/to/hotspot.csv +normal_sample_1,case1,normal,/path/to/fastq_list.csv,/path/to/hotspot.csv ``` -The hotspot file is optional. - -To run the pipeline from the analysis step: prepare a samplesheet with the following columns: - -`analysis_samplesheet.csv`: +**Analysis only** (`--run_alignment false`) — **the low-barrier on-ramp: no DRAGEN license or +FPGA hardware required.** If you already have DRAGEN output directories (from a prior run, a core, +or a collaborator), point at them and the pipeline runs only the annotation/report half. Use a +plain container profile (`docker`/`singularity`/`apptainer`) — the `dragen4`/`dragenaws` profiles +are needed **only** when actually aligning. ```csv -id,dragen_path,hotspot_file -sample1,/path/to/dragen_output/sample1,/path/to/hotspot_1 -sample2,/path/to/dragen_output/sample2,/path/to/hotspot_2 +id,dragen_path,target_file +sample1,/path/to/dragen_output/sample1,/path/to/sample1.targets.vcf ``` - -Now, you can run the pipeline using: - ```bash -nextflow run dhslab/nf-core-scge \ - -profile ris, \ - --input /path/to/samplesheet \ - --outdir +# analysis only — no DRAGEN needed: +nextflow run . -profile ris2,apptainer \ + --input mastersheet.csv --run_alignment false \ + --outdir ./results ``` -#### Additional arguments: ---hotspot_bed - /path/to/hotspot.bed +**Alignment + analysis** — requires a DRAGEN license + reference; add the DRAGEN profile: +```bash +nextflow run . -profile ris,dragen4 \ + --input mastersheet.csv \ + --outdir ./results +``` -> [!WARNING] -> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; -> see [docs](https://nf-co.re/usage/configuration#custom-configuration-files). +Compute profiles: `-profile ris` (Compute1/LSF) or `ris2` (Compute2/SLURM), plus a container +engine (`apptainer`/`singularity`/`docker`); add `dragen4` (local DRAGEN) or `dragenaws` (AWS +DRAGEN) **only when aligning**. `-profile stub` gives a dependency-free dry run. -For more details and further functionality, please refer to the [usage documentation](https://nf-co.re/scge/usage) and the [parameter documentation](https://nf-co.re/scge/parameters). +### Automated review of off-target calls -## Pipeline output +The default pipeline now shortlists its own off-target calls instead of handing you every site +that clears the gate. On the 25-sample CAR-T WGS cohort this took the review queue from **238 +sites to 62, keeping all 61 real edits** (precision 0.256 → 0.984). -To see the results of an example test run with a full size dataset refer to the [results](https://nf-co.re/scge/results) tab on the nf-core website pipeline page. -For more details about the output files and reports, please refer to the -[output documentation](https://nf-co.re/scge/output). +Six rules — matched control clean, indel near a PAM position, several distinct indel lengths, +not background noise, not in a repeat, not on a known systematic-noise locus. Results land in +`/review/`: -## Credits +``` +review_queue.tsv the sites to actually look at +review_queue_all.tsv every gated site + why_dropped (audit trail) +bnd_review_queue.tsv the same triage applied to breakends +snapshots/ one pileup image per site: edited on top, matched control below +bnd_snapshots/ one image per breakend JUNCTION: the rearranged segment to scale over + both breakpoints, edited over matched control, junction reads highlighted +``` -nf-core/scge was originally written by Nidhi. +Breakends get their own triage and their own figures. Note that a queue *row* is not an event — +the caller reports each junction from both ends with a few bp of jitter, so the CAR-T cohort's 25 +rows are **8 junctions**, and on this cohort every one is a multi-cut **inversion** — the +segment between two cuts flipped and re-ligated, not excised. See +[`docs/OFFTARGET.md`](docs/OFFTARGET.md#breakends). -We thank the following people for their extensive assistance in the development of this pipeline: +**No panel of normals is needed.** Rule 4 is a beta-binomial test against each sample's *own* +unedited control (`review_noise_model`, default `matched`), so a single-sample submission with one +matched normal gets the same filtering a 32-sample cohort did — measured equal on the CAR-T cohort +at **precision 0.877, 64/64 confirmed edits retained** (PoN-only arm vs 32×single-sample arm). +The **production** configuration — rule 1 on, matched AQ, caller-derived cut distance — scores +**0.889 with 8 rejected**, also at 64/64. Both are rows of the same experiment table; quote 0.889 +for what ships and 0.877 for the no-cohort equivalence, and always say which. Full docs: +[`docs/OFFTARGET.md`](docs/OFFTARGET.md), measurements in +[`docs/NOISE_MODEL_EXPERIMENT.md`](docs/NOISE_MODEL_EXPERIMENT.md). - +### Unified CRISPR Off-Target Workflow -## Contributions and Support +> This is a **separate arm** (`-entry OFFTARGET`) from the review filter above, which runs on the +> default analysis path. Both are current; they solve different problems. -If you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md). +```bash +# RIS Compute2 (SLURM + Apptainer) — the validated path. One wrapper for any cohort: +sbatch run_offtarget.sh --input --outdir [--snapshots] -For further information or help, don't hesitate to get in touch on the [Slack `#scge` channel](https://nfcore.slack.com/channels/scge) (you can join with [this invite](https://nf-co.re/join/slack)). +# or directly (from a node that can sbatch, not the interactive exec node): +nextflow run . -entry OFFTARGET -profile ris2,apptainer \ + --input offtarget_samplesheet.csv \ + --outdir ./results_offtarget -resume +``` -## Citations +On RIS Compute1 (LSF) run `nextflow run . -entry OFFTARGET -profile ris` under `bsub`. Samplesheet +`sample,datatype{ecs|wgs},guide,edited_cram,control_cram,target_file,vcf` — template at +`assets/offtarget_samplesheet_template.csv`. When `-entry OFFTARGET` is given, the default SCGE +workflow does not run. Full docs: [`docs/OFFTARGET.md`](docs/OFFTARGET.md). + +**Retrain the shape model** from a paired run's `training.tsv` with the separate `TRAIN` entry — +`nextflow run . -entry TRAIN --input results_offtarget/offtarget/training.tsv --outdir results` → +`results/train/wgs_shape_model.pkl`, then deploy via `--offtarget_shape_model`. See the docs. + +Add `--offtarget_snapshots true` to render an IGV-style **edited-vs-normal** read pileup for every +LIKELY EDIT (into `/offtarget/snapshots/`) — by-eye verification straight from the CRAM: + +![tumor vs normal pileup snapshot](docs/images/offtarget_snapshot_example.png) + +## Key parameters + +| Parameter | Default | Description | +|---|---|---| +| `--input` | — | samplesheet / mastersheet CSV (required) | +| `--outdir` | — | output directory (required) | +| `--run_alignment` / `--run_analysis` | `true` / `true` | toggle the DRAGEN and analysis halves | +| `--fasta` | hg38 + transgene FASTA on storage2 | reference (with the CAR/transgene contig) | +| `--transgene_name` | `PLVM_CD19_CARv4_cd34` | transgene contig name in the reference | +| `--crispr_model` | `assets/models/site14_site5_combined_model.pkl` | model for `GET_INDELS` edit classification | +| `--off_target_threshold` | `1.0` | ML score threshold for off-target calls | +| `--vepcache` | VEP113 cache on storage2 | VEP annotation cache | +| `--offtarget_shape_model` | `assets/models/wgs_shape_model.pkl` | pileup shape ranker (OFFTARGET arm) | +| `--offtarget_min_af` / `--offtarget_min_span` | `0.05` / `8` | WGS candidate AF floor / coverage gate | +| `--offtarget_hi_score` / `--offtarget_target_recall` | `0.60` / `0.80` | recall-curve detection threshold / target | + +## Containers + +| Purpose | Image | +|---|---| +| Default SCGE analysis (incl. CRISPR_ML edit classification, `GET_INDELS` `--crispr_model`) | `ghcr.io/dhslab/docker-scge:latest` | +| Off-target ML (`-entry OFFTARGET`: ECS truth + WGS scoring/training) | `ghcr.io/dhslab/docker-scge-offtarget:260710` | +| Variant annotation (VEP) | `ghcr.io/dhslab/docker-vep_release113:250810` | +| Report rendering (Quarto) | `ghcr.io/dhslab/docker-quarto-chromoseq:latest` | +| DRAGEN alignment / calling | via `task.ext.dragen_container` (`dragen4` / `dragenaws` profile) | + +The CRISPR_ML edit classifier has no separate image — it runs inside `docker-scge:latest`. Nextflow +itself runs inside `ghcr.io/dhslab/docker-baseimage:latest` on RIS. + +## Testing + +- **Python glue-script tests** (no CRAM/model needed): `pytest tests/` — run with an interpreter + that has `pandas` (e.g. inside `docker-scge`). Covers the OFFTARGET ECS⋈WGS join, the + recall-vs-VAF logic, and the coordinate-mismatch guardrail. +- **Nextflow dry run**: `nextflow run . -profile stub --input --outdir ./stub` (or add + `-entry OFFTARGET`). Requires Java 17+ (present in the RIS container). - - +## Credits - +dhslab/nf-core-scge was originally written by Nidhi and is developed and maintained by the +[Spencer Lab](https://www.davidspencerlab.org/) (Washington University in St. Louis). Built with the +[nf-core](https://nf-co.re) framework. -An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file. +## Citations -You can cite the `nf-core` publication as follows: +Tool and data references are listed in [`CITATIONS.md`](CITATIONS.md). If you use the nf-core +framework, please cite: > **The nf-core framework for community-curated bioinformatics pipelines.** -> -> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen. -> -> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x). +> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, +> Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen. +> _Nat Biotechnol._ 2020. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x). diff --git a/analysis_mastersheet.csv b/analysis_mastersheet.csv new file mode 100644 index 0000000..31b7578 --- /dev/null +++ b/analysis_mastersheet.csv @@ -0,0 +1,2 @@ +id,dragen_path +EZH1-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/EZH1-KO-DNA/dragen diff --git a/assets/NO_FILE b/assets/NO_FILE new file mode 100644 index 0000000..e69de29 diff --git a/assets/NO_IDT b/assets/NO_IDT new file mode 100644 index 0000000..e69de29 diff --git a/assets/accessory_files/hematopoietic_gene_hotspots.bed b/assets/accessory_files/hematopoietic_gene_hotspots.bed new file mode 100644 index 0000000..2da8b5e --- /dev/null +++ b/assets/accessory_files/hematopoietic_gene_hotspots.bed @@ -0,0 +1,496 @@ +chr1 1806472 1806540 GNB1 MSHD_genes|ENSG00000078369|ENST00000378609|exon_6|1787331|1825453|-1 +chr1 1815753 1815864 GNB1 MSHD_genes|ENSG00000078369|ENST00000378609|exon_5|1787331|1825453|-1 +chr1 36466356 36466829 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_17|36466357|36479496|-1 +chr1 36467227 36467313 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_16|36466357|36479496|-1 +chr1 36467555 36467653 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_15|36466357|36479496|-1 +chr1 36467819 36467964 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_14|36466357|36479496|-1 +chr1 36468072 36468223 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_13|36466357|36479496|-1 +chr1 36469153 36469259 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_12|36466357|36479496|-1 +chr1 36469649 36469842 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_11|36466357|36479496|-1 +chr1 36471430 36471648 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_10|36466357|36479496|-1 +chr1 36472063 36472141 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_9|36466357|36479496|-1 +chr1 36472235 36472393 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_8|36466357|36479496|-1 +chr1 36472514 36472688 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_7|36466357|36479496|-1 +chr1 36473432 36473624 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_6|36466357|36479496|-1 +chr1 36473761 36473889 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_5|36466357|36479496|-1 +chr1 36475374 36475675 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_4|36466357|36479496|-1 +chr1 36479430 36479496 CSF3R MSHD_genes|ENSG00000119535|ENST00000373106|exon_3|36466357|36479496|-1 +chr1 43349260 43349361 MPL MSHD_genes|ENSG00000117400|ENST00000372470|exon_10|43337849|43352772|1 +chr1 114709566 114709730 NRAS MSHD_genes|ENSG00000213281|ENST00000369535|exon_4|114708535|114716160|-1 +chr1 114713797 114713980 NRAS MSHD_genes|ENSG00000213281|ENST00000369535|exon_3|114708535|114716160|-1 +chr1 114716047 114716160 NRAS MSHD_genes|ENSG00000213281|ENST00000369535|exon_2|114708535|114716160|-1 +chr2 25234278 25234422 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_23|25234279|25313984|-1 +chr2 25235704 25235827 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_22|25234279|25313984|-1 +chr2 25236933 25237007 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_21|25234279|25313984|-1 +chr2 25239127 25239217 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_20|25234279|25313984|-1 +chr2 25240299 25240452 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_19|25234279|25313984|-1 +chr2 25240637 25240732 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_18|25234279|25313984|-1 +chr2 25241559 25241709 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_17|25234279|25313984|-1 +chr2 25243895 25243984 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_16|25234279|25313984|-1 +chr2 25244152 25244340 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_15|25234279|25313984|-1 +chr2 25244537 25244654 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_14|25234279|25313984|-1 +chr2 25245250 25245334 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_13|25234279|25313984|-1 +chr2 25246017 25246066 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_12|25234279|25313984|-1 +chr2 25246157 25246311 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_11|25234279|25313984|-1 +chr2 25246617 25246778 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_10|25234279|25313984|-1 +chr2 25247048 25247160 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_9|25234279|25313984|-1 +chr2 25247588 25247751 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_8|25234279|25313984|-1 +chr2 25248034 25248254 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_7|25234279|25313984|-1 +chr2 25274938 25275089 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_6|25234279|25313984|-1 +chr2 25275497 25275545 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_5|25234279|25313984|-1 +chr2 25282438 25282713 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_4|25234279|25313984|-1 +chr2 25300136 25300245 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_3|25234279|25313984|-1 +chr2 25313910 25313984 DNMT3A MSHD_genes|ENSG00000119772|ENST00000321117|exon_2|25234279|25313984|-1 +chr2 197392302 197392463 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_25|197392303|197434999|-1 +chr2 197392969 197393190 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_24|197392303|197434999|-1 +chr2 197396053 197396330 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_23|197392303|197434999|-1 +chr2 197397982 197398118 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_22|197392303|197434999|-1 +chr2 197398458 197398583 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_21|197392303|197434999|-1 +chr2 197400052 197400168 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_20|197392303|197434999|-1 +chr2 197400249 197400436 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_19|197392303|197434999|-1 +chr2 197400712 197400938 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_18|197392303|197434999|-1 +chr2 197401397 197401527 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_17|197392303|197434999|-1 +chr2 197401739 197401890 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_16|197392303|197434999|-1 +chr2 197401982 197402132 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_15|197392303|197434999|-1 +chr2 197402553 197402828 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_14|197392303|197434999|-1 +chr2 197402946 197403037 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_13|197392303|197434999|-1 +chr2 197403582 197403766 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_12|197392303|197434999|-1 +chr2 197405073 197405179 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_11|197392303|197434999|-1 +chr2 197405272 197405474 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_10|197392303|197434999|-1 +chr2 197407995 197408121 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_9|197392303|197434999|-1 +chr2 197408366 197408583 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_8|197392303|197434999|-1 +chr2 197409767 197410009 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_7|197392303|197434999|-1 +chr2 197416738 197416913 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_6|197392303|197434999|-1 +chr2 197418506 197418590 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_5|197392303|197434999|-1 +chr2 197420425 197420544 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_4|197392303|197434999|-1 +chr2 197421026 197421135 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_3|197392303|197434999|-1 +chr2 197423805 197423976 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_2|197392303|197434999|-1 +chr2 197434969 197434999 SF3B1 MSHD_genes|ENSG00000115524|ENST00000335508|exon_1|197392303|197434999|-1 +chr2 208248366 208248662 IDH1 MSHD_genes|ENSG00000138413|ENST00000345146|exon_4|208237079|208251551|-1 +chr3 128481018 128481320 GATA2 MSHD_genes|ENSG00000179348|ENST00000341105|exon_6|128481019|128487031|-1 +chr3 128481816 128481946 GATA2 MSHD_genes|ENSG00000179348|ENST00000341105|exon_5|128481019|128487031|-1 +chr3 128483857 128484007 GATA2 MSHD_genes|ENSG00000179348|ENST00000341105|exon_4|128481019|128487031|-1 +chr3 128485724 128486370 GATA2 MSHD_genes|ENSG00000179348|ENST00000341105|exon_3|128481019|128487031|-1 +chr3 128486800 128487031 GATA2 MSHD_genes|ENSG00000179348|ENST00000341105|exon_2|128481019|128487031|-1 +chr4 54695509 54695783 KIT MSHD_genes|ENSG00000157404|ENST00000288135|exon_2|54658015|54738557|1 +chr4 54723581 54723700 KIT MSHD_genes|ENSG00000157404|ENST00000288135|exon_8|54658015|54738557|1 +chr4 54725854 54726052 KIT MSHD_genes|ENSG00000157404|ENST00000288135|exon_9|54658015|54738557|1 +chr4 54727215 54727326 KIT MSHD_genes|ENSG00000157404|ENST00000288135|exon_10|54658015|54738557|1 +chr4 54727413 54727544 KIT MSHD_genes|ENSG00000157404|ENST00000288135|exon_11|54658015|54738557|1 +chr4 54728008 54728123 KIT MSHD_genes|ENSG00000157404|ENST00000288135|exon_13|54658015|54738557|1 +chr4 54733067 54733194 KIT MSHD_genes|ENSG00000157404|ENST00000288135|exon_17|54658015|54738557|1 +chr4 105233942 105237353 TET2 MSHD_genes|ENSG00000168769|ENST00000380013|exon_3|105233943|105276519|1 +chr4 105241336 105241431 TET2 MSHD_genes|ENSG00000168769|ENST00000380013|exon_4|105233943|105276519|1 +chr4 105242831 105242929 TET2 MSHD_genes|ENSG00000168769|ENST00000380013|exon_5|105233943|105276519|1 +chr4 105243567 105243780 TET2 MSHD_genes|ENSG00000168769|ENST00000380013|exon_6|105233943|105276519|1 +chr4 105259616 105259771 TET2 MSHD_genes|ENSG00000168769|ENST00000380013|exon_7|105233943|105276519|1 +chr4 105261756 105261850 TET2 MSHD_genes|ENSG00000168769|ENST00000380013|exon_8|105233943|105276519|1 +chr4 105269607 105269749 TET2 MSHD_genes|ENSG00000168769|ENST00000380013|exon_9|105233943|105276519|1 +chr4 105272561 105272920 TET2 MSHD_genes|ENSG00000168769|ENST00000380013|exon_10|105233943|105276519|1 +chr4 105275045 105276519 TET2 MSHD_genes|ENSG00000168769|ENST00000380013|exon_11|105233943|105276519|1 +chr5 171410524 171410565 NPM1 MSHD_genes|ENSG00000181163|ENST00000296930|exon_11|171387949|171410565|1 +chr5 177511790 177511929 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_17|177511791|177516945|-1 +chr5 177512093 177512208 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_16|177511791|177516945|-1 +chr5 177512319 177512395 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_15|177511791|177516945|-1 +chr5 177512493 177512647 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_14|177511791|177516945|-1 +chr5 177512777 177512878 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_13|177511791|177516945|-1 +chr5 177513008 177513084 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_12|177511791|177516945|-1 +chr5 177513350 177513486 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_11|177511791|177516945|-1 +chr5 177513682 177513849 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_10|177511791|177516945|-1 +chr5 177514698 177514839 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_9|177511791|177516945|-1 +chr5 177514913 177515071 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_8|177511791|177516945|-1 +chr5 177515183 177515260 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_7|177511791|177516945|-1 +chr5 177515682 177515823 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_6|177511791|177516945|-1 +chr5 177515926 177515991 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_5|177511791|177516945|-1 +chr5 177516116 177516195 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_4|177511791|177516945|-1 +chr5 177516285 177516449 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_3|177511791|177516945|-1 +chr5 177516722 177516837 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_2|177511791|177516945|-1 +chr5 177516916 177516945 DDX41 MSHD_genes|ENSG00000183258|ENST00000330503|exon_1|177511791|177516945|-1 +chr7 101817639 101817671 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_1|101817640|102249042|1 +chr7 101916112 101916227 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_2|101817640|102249042|1 +chr7 102028095 102028147 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_3|101817640|102249042|1 +chr7 102070336 102070419 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_4|101817640|102249042|1 +chr7 102097361 102097503 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_5|101817640|102249042|1 +chr7 102104333 102104461 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_6|101817640|102249042|1 +chr7 102111695 102111776 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_7|101817640|102249042|1 +chr7 102115204 102115275 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_8|101817640|102249042|1 +chr7 102158557 102158610 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_9|101817640|102249042|1 +chr7 102170443 102170552 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_10|101817640|102249042|1 +chr7 102178466 102178659 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_11|101817640|102249042|1 +chr7 102189810 102189873 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_12|101817640|102249042|1 +chr7 102193839 102193892 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_13|101817640|102249042|1 +chr7 102195504 102195605 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_14|101817640|102249042|1 +chr7 102196631 102197307 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_15|101817640|102249042|1 +chr7 102198799 102198869 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_16|101817640|102249042|1 +chr7 102200068 102200174 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_17|101817640|102249042|1 +chr7 102201357 102202206 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_18|101817640|102249042|1 +chr7 102204388 102204558 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_19|101817640|102249042|1 +chr7 102205111 102205172 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_20|101817640|102249042|1 +chr7 102227364 102227671 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_21|101817640|102249042|1 +chr7 102234049 102234242 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_22|101817640|102249042|1 +chr7 102239317 102239586 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_23|101817640|102249042|1 +chr7 102248409 102249042 CUX1 MSHD_genes|ENSG00000257923|ENST00000292535|exon_24|101817640|102249042|1 +chr7 140753272 140753395 BRAF MSHD_genes|ENSG00000157764|ENST00000646891|exon_15|140734597|140924703|-1 +chr7 148807645 148807708 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_20|148807646|148847298|-1 +chr7 148809068 148809157 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_19|148807646|148847298|-1 +chr7 148809307 148809392 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_18|148807646|148847298|-1 +chr7 148810330 148810416 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_17|148807646|148847298|-1 +chr7 148811622 148811722 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_16|148807646|148847298|-1 +chr7 148813956 148814139 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_15|148807646|148847298|-1 +chr7 148814911 148815041 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_14|148807646|148847298|-1 +chr7 148815503 148815548 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_13|148807646|148847298|-1 +chr7 148816681 148816780 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_12|148807646|148847298|-1 +chr7 148817219 148817393 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_11|148807646|148847298|-1 +chr7 148817874 148818119 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_10|148807646|148847298|-1 +chr7 148819593 148819689 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_9|148807646|148847298|-1 +chr7 148826451 148826634 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_8|148807646|148847298|-1 +chr7 148827161 148827268 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_7|148807646|148847298|-1 +chr7 148828737 148828882 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_6|148807646|148847298|-1 +chr7 148829725 148829850 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_5|148807646|148847298|-1 +chr7 148832631 148832752 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_4|148807646|148847298|-1 +chr7 148846467 148846600 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_3|148807646|148847298|-1 +chr7 148847179 148847298 EZH2 MSHD_genes|ENSG00000106462|ENST00000320356|exon_2|148807646|148847298|-1 +chr8 116847499 116847693 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_14|116847500|116866729|-1 +chr8 116848943 116849031 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_13|116847500|116866729|-1 +chr8 116850615 116850769 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_12|116847500|116866729|-1 +chr8 116851945 116852098 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_11|116847500|116866729|-1 +chr8 116852546 116852710 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_10|116847500|116866729|-1 +chr8 116854242 116854470 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_9|116847500|116866729|-1 +chr8 116856163 116856290 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_8|116847500|116866729|-1 +chr8 116856643 116856773 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_7|116847500|116866729|-1 +chr8 116857264 116857475 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_6|116847500|116866729|-1 +chr8 116858349 116858460 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_5|116847500|116866729|-1 +chr8 116861838 116861942 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_4|116847500|116866729|-1 +chr8 116863127 116863261 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_3|116847500|116866729|-1 +chr8 116866583 116866729 RAD21 MSHD_genes|ENSG00000164754|ENST00000297338|exon_2|116847500|116866729|-1 +chr8 127736593 127736625 MYC MSHD_genes|ENSG00000136997|ENST00000621592|exon_1|127736594|127740958|1 +chr8 127738245 127739021 MYC MSHD_genes|ENSG00000136997|ENST00000621592|exon_2|127736594|127740958|1 +chr8 127740393 127740958 MYC MSHD_genes|ENSG00000136997|ENST00000621592|exon_3|127736594|127740958|1 +chr9 5069922 5070054 JAK2 MSHD_genes|ENSG00000096968|ENST00000381652|exon_12|5021988|5126791|1 +chr9 5073695 5073787 JAK2 MSHD_genes|ENSG00000096968|ENST00000381652|exon_14|5021988|5126791|1 +chr9 136496070 136497560 NOTCH1 MSHD_genes|ENSG00000148400|ENST00000651671|exon_34|136496071|136545786|-1 +chr9 136502269 136502490 NOTCH1 MSHD_genes|ENSG00000148400|ENST00000651671|exon_28|136496071|136545786|-1 +chr9 136503179 136503332 NOTCH1 MSHD_genes|ENSG00000148400|ENST00000651671|exon_27|136496071|136545786|-1 +chr9 136504670 136505106 NOTCH1 MSHD_genes|ENSG00000148400|ENST00000651671|exon_26|136496071|136545786|-1 +chr10 110567816 110567833 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_1|110567817|110604302|1 +chr10 110568935 110569015 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_2|110567817|110604302|1 +chr10 110573704 110573747 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_3|110567817|110604302|1 +chr10 110575333 110575405 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_4|110567817|110604302|1 +chr10 110577418 110577494 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_5|110567817|110604302|1 +chr10 110577832 110577916 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_6|110567817|110604302|1 +chr10 110578625 110578708 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_7|110567817|110604302|1 +chr10 110580901 110581023 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_8|110567817|110604302|1 +chr10 110581920 110582100 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_9|110567817|110604302|1 +chr10 110582559 110582644 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_10|110567817|110604302|1 +chr10 110583381 110583550 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_11|110567817|110604302|1 +chr10 110583838 110583964 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_12|110567817|110604302|1 +chr10 110584180 110584398 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_13|110567817|110604302|1 +chr10 110589602 110589710 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_14|110567817|110604302|1 +chr10 110589889 110589993 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_15|110567817|110604302|1 +chr10 110590409 110590574 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_16|110567817|110604302|1 +chr10 110590988 110591134 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_17|110567817|110604302|1 +chr10 110593070 110593225 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_18|110567817|110604302|1 +chr10 110596395 110596552 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_19|110567817|110604302|1 +chr10 110598136 110598292 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_20|110567817|110604302|1 +chr10 110599651 110599814 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_21|110567817|110604302|1 +chr10 110600436 110600548 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_22|110567817|110604302|1 +chr10 110601019 110601132 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_23|110567817|110604302|1 +chr10 110601634 110601886 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_24|110567817|110604302|1 +chr10 110601963 110602180 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_25|110567817|110604302|1 +chr10 110602471 110602667 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_26|110567817|110604302|1 +chr10 110602822 110603004 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_27|110567817|110604302|1 +chr10 110603181 110603292 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_28|110567817|110604302|1 +chr10 110604228 110604302 SMC3 MSHD_genes|ENSG00000108055|ENST00000361804|exon_29|110567817|110604302|1 +chr11 32389057 32389181 WT1 MSHD_genes|ENSG00000184937|ENST00000452863|exon_10|32389058|32435360|-1 +chr11 32391969 32392066 WT1 MSHD_genes|ENSG00000184937|ENST00000452863|exon_9|32389058|32435360|-1 +chr11 32392663 32392757 WT1 MSHD_genes|ENSG00000184937|ENST00000452863|exon_8|32389058|32435360|-1 +chr11 32396254 32396409 WT1 MSHD_genes|ENSG00000184937|ENST00000452863|exon_7|32389058|32435360|-1 +chr11 32399945 32400046 WT1 MSHD_genes|ENSG00000184937|ENST00000452863|exon_6|32389058|32435360|-1 +chr11 32416487 32416542 WT1 MSHD_genes|ENSG00000184937|ENST00000452863|exon_5|32389058|32435360|-1 +chr11 32417574 32417656 WT1 MSHD_genes|ENSG00000184937|ENST00000452863|exon_4|32389058|32435360|-1 +chr11 32427953 32428060 WT1 MSHD_genes|ENSG00000184937|ENST00000452863|exon_3|32389058|32435360|-1 +chr11 32428494 32428621 WT1 MSHD_genes|ENSG00000184937|ENST00000452863|exon_2|32389058|32435360|-1 +chr11 32434697 32435360 WT1 MSHD_genes|ENSG00000184937|ENST00000452863|exon_1|32389058|32435360|-1 +chr11 118436512 118436946 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_1|118436513|118522172|1 +chr11 118468772 118468846 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_2|118436513|118522172|1 +chr11 118471659 118474317 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_3|118436513|118522172|1 +chr11 118476802 118476984 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_4|118436513|118522172|1 +chr11 118477964 118478203 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_5|118436513|118522172|1 +chr11 118480171 118480240 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_6|118436513|118522172|1 +chr11 118481712 118482094 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_7|118436513|118522172|1 +chr11 118482419 118482497 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_8|118436513|118522172|1 +chr11 118484180 118484316 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_9|118436513|118522172|1 +chr11 118484859 118484977 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_10|118436513|118522172|1 +chr11 118488611 118488762 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_11|118436513|118522172|1 +chr11 118489789 118489889 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_12|118436513|118522172|1 +chr11 118490126 118490251 KMT2A MSHD_genes|ENSG00000118058|ENST00000534358|exon_13|118436513|118522172|1 +chr11 119278163 119278299 CBL MSHD_genes|ENSG00000110395|ENST00000264033|exon_8|119206418|119299781|1 +chr11 119278507 119278715 CBL MSHD_genes|ENSG00000110395|ENST00000264033|exon_9|119206418|119299781|1 +chr12 11650127 11650162 ETV6 MSHD_genes|ENSG00000139083|ENST00000396373|exon_1|11650128|11891046|1 +chr12 11752447 11752581 ETV6 MSHD_genes|ENSG00000139083|ENST00000396373|exon_2|11650128|11891046|1 +chr12 11839137 11839306 ETV6 MSHD_genes|ENSG00000139083|ENST00000396373|exon_3|11650128|11891046|1 +chr12 11853424 11853563 ETV6 MSHD_genes|ENSG00000139083|ENST00000396373|exon_4|11650128|11891046|1 +chr12 11869421 11869971 ETV6 MSHD_genes|ENSG00000139083|ENST00000396373|exon_5|11650128|11891046|1 +chr12 11884442 11884589 ETV6 MSHD_genes|ENSG00000139083|ENST00000396373|exon_6|11650128|11891046|1 +chr12 11885923 11886028 ETV6 MSHD_genes|ENSG00000139083|ENST00000396373|exon_7|11650128|11891046|1 +chr12 11890938 11891046 ETV6 MSHD_genes|ENSG00000139083|ENST00000396373|exon_8|11650128|11891046|1 +chr12 22659011 22659156 ETNK1 MSHD_genes|ENSG00000139163|ENST00000266517|exon_3|22625431|22684954|1 +chr12 25227231 25227414 KRAS MSHD_genes|ENSG00000133703|ENST00000311936|exon_3|25209795|25245384|-1 +chr12 25245271 25245384 KRAS MSHD_genes|ENSG00000133703|ENST00000311936|exon_2|25209795|25245384|-1 +chr12 112450315 112450514 PTPN11 MSHD_genes|ENSG00000179295|ENST00000351677|exon_3|112419112|112504764|1 +chr12 112489021 112489177 PTPN11 MSHD_genes|ENSG00000179295|ENST00000351677|exon_13|112419112|112504764|1 +chr12 112502141 112502258 PTPN11 MSHD_genes|ENSG00000179295|ENST00000351677|exon_14|112419112|112504764|1 +chr13 28018464 28018591 FLT3 MSHD_genes|ENSG00000122025|ENST00000241453|exon_20|28004052|28100510|-1 +chr13 28027085 28027243 FLT3 MSHD_genes|ENSG00000122025|ENST00000241453|exon_17|28004052|28100510|-1 +chr13 28033884 28033993 FLT3 MSHD_genes|ENSG00000122025|ENST00000241453|exon_15|28004052|28100510|-1 +chr13 28034079 28034216 FLT3 MSHD_genes|ENSG00000122025|ENST00000241453|exon_14|28004052|28100510|-1 +chr13 28034298 28034409 FLT3 MSHD_genes|ENSG00000122025|ENST00000241453|exon_13|28004052|28100510|-1 +chr15 90088584 90088749 IDH2 MSHD_genes|ENSG00000182054|ENST00000330062|exon_4|90084266|90102390|-1 +chr17 1659838 1660003 PRPF8 MSHD_genes|ENSG00000174231|ENST00000304992|exon_31|1650802|1684571|-1 +chr17 1660429 1660580 PRPF8 MSHD_genes|ENSG00000174231|ENST00000304992|exon_30|1650802|1684571|-1 +chr17 7669608 7669692 TP53 MSHD_genes|ENSG00000141510|ENST00000269305|exon_11|7669609|7676594|-1 +chr17 7670606 7670717 TP53 MSHD_genes|ENSG00000141510|ENST00000269305|exon_10|7669609|7676594|-1 +chr17 7673532 7673610 TP53 MSHD_genes|ENSG00000141510|ENST00000269305|exon_9|7669609|7676594|-1 +chr17 7673698 7673839 TP53 MSHD_genes|ENSG00000141510|ENST00000269305|exon_8|7669609|7676594|-1 +chr17 7674178 7674292 TP53 MSHD_genes|ENSG00000141510|ENST00000269305|exon_7|7669609|7676594|-1 +chr17 7674856 7674973 TP53 MSHD_genes|ENSG00000141510|ENST00000269305|exon_6|7669609|7676594|-1 +chr17 7675050 7675238 TP53 MSHD_genes|ENSG00000141510|ENST00000269305|exon_5|7669609|7676594|-1 +chr17 7675991 7676274 TP53 MSHD_genes|ENSG00000141510|ENST00000269305|exon_4|7669609|7676594|-1 +chr17 7676379 7676405 TP53 MSHD_genes|ENSG00000141510|ENST00000269305|exon_3|7669609|7676594|-1 +chr17 7676518 7676594 TP53 MSHD_genes|ENSG00000141510|ENST00000269305|exon_2|7669609|7676594|-1 +chr17 31095309 31095371 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_1|31095310|31374155|1 +chr17 31155980 31156128 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_2|31095310|31374155|1 +chr17 31159007 31159095 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_3|31095310|31374155|1 +chr17 31163183 31163378 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_4|31095310|31374155|1 +chr17 31169888 31169999 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_5|31095310|31374155|1 +chr17 31181419 31181491 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_6|31095310|31374155|1 +chr17 31181707 31181787 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_7|31095310|31374155|1 +chr17 31182505 31182667 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_8|31095310|31374155|1 +chr17 31200419 31200597 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_9|31095310|31374155|1 +chr17 31201034 31201161 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_10|31095310|31374155|1 +chr17 31201408 31201487 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_11|31095310|31374155|1 +chr17 31206237 31206373 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_12|31095310|31374155|1 +chr17 31214448 31214587 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_13|31095310|31374155|1 +chr17 31219002 31219120 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_14|31095310|31374155|1 +chr17 31221847 31221931 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_15|31095310|31374155|1 +chr17 31223441 31223569 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_16|31095310|31374155|1 +chr17 31225092 31225252 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_17|31095310|31374155|1 +chr17 31226432 31226686 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_18|31095310|31374155|1 +chr17 31227215 31227293 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_19|31095310|31374155|1 +chr17 31227520 31227608 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_20|31095310|31374155|1 +chr17 31229022 31229467 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_21|31095310|31374155|1 +chr17 31229832 31229976 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_22|31095310|31374155|1 +chr17 31230257 31230384 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_23|31095310|31374155|1 +chr17 31230839 31230927 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_24|31095310|31374155|1 +chr17 31232070 31232191 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_25|31095310|31374155|1 +chr17 31232697 31232883 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_26|31095310|31374155|1 +chr17 31232999 31233215 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_27|31095310|31374155|1 +chr17 31235608 31235774 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_28|31095310|31374155|1 +chr17 31235915 31236023 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_29|31095310|31374155|1 +chr17 31248981 31249121 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_30|31095310|31374155|1 +chr17 31258341 31258504 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_32|31095310|31374155|1 +chr17 31259029 31259131 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_33|31095310|31374155|1 +chr17 31260366 31260517 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_34|31095310|31374155|1 +chr17 31261708 31261859 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_35|31095310|31374155|1 +chr17 31265226 31265341 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_36|31095310|31374155|1 +chr17 31325817 31326254 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_37|31095310|31374155|1 +chr17 31327496 31327841 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_38|31095310|31374155|1 +chr17 31330293 31330500 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_39|31095310|31374155|1 +chr17 31334835 31335033 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_40|31095310|31374155|1 +chr17 31336330 31336475 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_41|31095310|31374155|1 +chr17 31336632 31336916 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_42|31095310|31374155|1 +chr17 31337365 31337584 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_43|31095310|31374155|1 +chr17 31337816 31337882 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_44|31095310|31374155|1 +chr17 31338022 31338141 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_45|31095310|31374155|1 +chr17 31338701 31338807 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_46|31095310|31374155|1 +chr17 31340502 31340647 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_47|31095310|31374155|1 +chr17 31343006 31343137 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_48|31095310|31374155|1 +chr17 31349117 31349253 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_49|31095310|31374155|1 +chr17 31350180 31350320 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_50|31095310|31374155|1 +chr17 31352254 31352416 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_51|31095310|31374155|1 +chr17 31356457 31356584 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_52|31095310|31374155|1 +chr17 31356957 31357092 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_53|31095310|31374155|1 +chr17 31357266 31357371 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_54|31095310|31374155|1 +chr17 31358477 31358624 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_55|31095310|31374155|1 +chr17 31358966 31359017 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_56|31095310|31374155|1 +chr17 31360484 31360705 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_57|31095310|31374155|1 +chr17 31374010 31374155 NF1 MSHD_genes|ENSG00000196712|ENST00000358273|exon_58|31095310|31374155|1 +chr17 31937246 31937522 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_1|31937247|31999003|1 +chr17 31940283 31940334 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_2|31937247|31999003|1 +chr17 31940419 31940488 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_3|31937247|31999003|1 +chr17 31947614 31947687 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_4|31937247|31999003|1 +chr17 31966144 31966198 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_5|31937247|31999003|1 +chr17 31973143 31973233 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_6|31937247|31999003|1 +chr17 31975479 31975715 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_7|31937247|31999003|1 +chr17 31976518 31976616 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_8|31937247|31999003|1 +chr17 31982996 31983106 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_9|31937247|31999003|1 +chr17 31988317 31988499 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_10|31937247|31999003|1 +chr17 31993239 31993335 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_11|31937247|31999003|1 +chr17 31993862 31994010 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_12|31937247|31999003|1 +chr17 31994561 31994723 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_13|31937247|31999003|1 +chr17 31995561 31995764 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_14|31937247|31999003|1 +chr17 31996795 31996879 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_15|31937247|31999003|1 +chr17 31998655 31999003 SUZ12 MSHD_genes|ENSG00000178691|ENST00000322652|exon_16|31937247|31999003|1 +chr17 42207555 42207730 STAT5B MSHD_genes|ENSG00000173757|ENST00000293328|exon_16|42201738|42232127|-1 +chr17 42210168 42210303 STAT5B MSHD_genes|ENSG00000173757|ENST00000293328|exon_15|42201738|42232127|-1 +chr17 42210400 42210499 STAT5B MSHD_genes|ENSG00000173757|ENST00000293328|exon_14|42201738|42232127|-1 +chr17 42322279 42322496 STAT3 MSHD_genes|ENSG00000168610|ENST00000264657|exon_21|42315745|42348516|-1 +chr17 42323001 42323145 STAT3 MSHD_genes|ENSG00000168610|ENST00000264657|exon_20|42315745|42348516|-1 +chr17 42323257 42323356 STAT3 MSHD_genes|ENSG00000168610|ENST00000264657|exon_19|42315745|42348516|-1 +chr17 44210318 44211152 UBTF MSHD_genes|ENSG00000108312|ENST00000436088|exon_13|44207242|44218229|-1 +chr17 60662992 60663552 PPM1D MSHD_genes|ENSG00000170836|ENST00000305921|exon_6|60600415|60663552|1 +chr17 76736796 76737160 SRSF2 MSHD_genes|ENSG00000161547|ENST00000359995|exon_1|76736161|76737160|-1 +chr18 44949878 44953342 SETBP1 MSHD_genes|ENSG00000152217|ENST00000649279|exon_4|44701347|45063698|1 +chr19 12943710 12943913 CALR MSHD_genes|ENSG00000179218|ENST00000316448|exon_9|12938680|12943913|1 +chr19 33301337 33302414 CEBPA MSHD_genes|ENSG00000245848|ENST00000498907|exon_1|33301338|33302414|-1 +chr20 32358775 32358834 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_1|32358776|32437338|1 +chr20 32366381 32366468 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_2|32358776|32437338|1 +chr20 32367724 32367731 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_3|32358776|32437338|1 +chr20 32369012 32369125 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_4|32358776|32437338|1 +chr20 32428125 32428250 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_5|32358776|32437338|1 +chr20 32428322 32428424 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_6|32358776|32437338|1 +chr20 32429335 32429433 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_7|32358776|32437338|1 +chr20 32429898 32430055 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_8|32358776|32437338|1 +chr20 32431318 32431486 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_9|32358776|32437338|1 +chr20 32431580 32431681 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_10|32358776|32437338|1 +chr20 32432877 32432987 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_11|32358776|32437338|1 +chr20 32433281 32433919 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_12|32358776|32437338|1 +chr20 32434429 32437338 ASXL1 MSHD_genes|ENSG00000171456|ENST00000375687|exon_13|32358776|32437338|1 +chr21 34792134 34792612 RUNX1 MSHD_genes|ENSG00000159216|ENST00000675419|exon_9|34792135|35048899|-1 +chr21 34799298 34799464 RUNX1 MSHD_genes|ENSG00000159216|ENST00000675419|exon_8|34792135|35048899|-1 +chr21 34834407 34834603 RUNX1 MSHD_genes|ENSG00000159216|ENST00000675419|exon_7|34792135|35048899|-1 +chr21 34859471 34859580 RUNX1 MSHD_genes|ENSG00000159216|ENST00000675419|exon_6|34792135|35048899|-1 +chr21 34880554 34880715 RUNX1 MSHD_genes|ENSG00000159216|ENST00000675419|exon_5|34792135|35048899|-1 +chr21 34886840 34887098 RUNX1 MSHD_genes|ENSG00000159216|ENST00000675419|exon_4|34792135|35048899|-1 +chr21 34892922 34892965 RUNX1 MSHD_genes|ENSG00000159216|ENST00000675419|exon_3|34792135|35048899|-1 +chr21 35048839 35048899 RUNX1 MSHD_genes|ENSG00000159216|ENST00000675419|exon_2|34792135|35048899|-1 +chr21 43094652 43094790 U2AF1 MSHD_genes|ENSG00000160201|ENST00000291552|exon_6|43093102|43107494|-1 +chr21 43104312 43104404 U2AF1 MSHD_genes|ENSG00000160201|ENST00000291552|exon_2|43093102|43107494|-1 +chr22 28687896 28687988 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_15|28687897|28734721|-1 +chr22 28689132 28689217 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_14|28687897|28734721|-1 +chr22 28694029 28694119 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_13|28687897|28734721|-1 +chr22 28695124 28695244 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_12|28687897|28734721|-1 +chr22 28695707 28695875 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_11|28687897|28734721|-1 +chr22 28696898 28696989 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_10|28687897|28734721|-1 +chr22 28699835 28699939 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_9|28687897|28734721|-1 +chr22 28703502 28703568 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_8|28687897|28734721|-1 +chr22 28710003 28710061 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_7|28687897|28734721|-1 +chr22 28711906 28712019 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_6|28687897|28734721|-1 +chr22 28719392 28719487 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_5|28687897|28734721|-1 +chr22 28724974 28725126 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_4|28687897|28734721|-1 +chr22 28725240 28725369 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_3|28687897|28734721|-1 +chr22 28734400 28734721 CHEK2 MSHD_genes|ENSG00000183765|ENST00000404276|exon_2|28687897|28734721|-1 +chrX 15321505 15321774 PIGA MSHD_genes|ENSG00000165195|ENST00000333590|exon_6|15321506|15331930|-1 +chrX 15324662 15324873 PIGA MSHD_genes|ENSG00000165195|ENST00000333590|exon_5|15321506|15331930|-1 +chrX 15325017 15325154 PIGA MSHD_genes|ENSG00000165195|ENST00000333590|exon_4|15321506|15331930|-1 +chrX 15325911 15326048 PIGA MSHD_genes|ENSG00000165195|ENST00000333590|exon_3|15321506|15331930|-1 +chrX 15331213 15331930 PIGA MSHD_genes|ENSG00000165195|ENST00000333590|exon_2|15321506|15331930|-1 +chrX 15790495 15790538 ZRSR2 MSHD_genes|ENSG00000169249|ENST00000307771|exon_1|15790496|15823242|1 +chrX 15790931 15791015 ZRSR2 MSHD_genes|ENSG00000169249|ENST00000307771|exon_2|15790496|15823242|1 +chrX 15799869 15799955 ZRSR2 MSHD_genes|ENSG00000169249|ENST00000307771|exon_3|15790496|15823242|1 +chrX 15803685 15803798 ZRSR2 MSHD_genes|ENSG00000169249|ENST00000307771|exon_4|15790496|15823242|1 +chrX 15804108 15804199 ZRSR2 MSHD_genes|ENSG00000169249|ENST00000307771|exon_5|15790496|15823242|1 +chrX 15808230 15808273 ZRSR2 MSHD_genes|ENSG00000169249|ENST00000307771|exon_6|15790496|15823242|1 +chrX 15809197 15809320 ZRSR2 MSHD_genes|ENSG00000169249|ENST00000307771|exon_7|15790496|15823242|1 +chrX 15815674 15815892 ZRSR2 MSHD_genes|ENSG00000169249|ENST00000307771|exon_8|15790496|15823242|1 +chrX 15818584 15818644 ZRSR2 MSHD_genes|ENSG00000169249|ENST00000307771|exon_9|15790496|15823242|1 +chrX 15820204 15820318 ZRSR2 MSHD_genes|ENSG00000169249|ENST00000307771|exon_10|15790496|15823242|1 +chrX 15822728 15823242 ZRSR2 MSHD_genes|ENSG00000169249|ENST00000307771|exon_11|15790496|15823242|1 +chrX 40052108 40052402 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_15|40052109|40077929|-1 +chrX 40053883 40054044 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_14|40052109|40077929|-1 +chrX 40054253 40054335 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_13|40052109|40077929|-1 +chrX 40055365 40055515 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_12|40052109|40077929|-1 +chrX 40057152 40057323 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_11|40052109|40077929|-1 +chrX 40062136 40062395 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_10|40052109|40077929|-1 +chrX 40062743 40063073 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_9|40052109|40077929|-1 +chrX 40063605 40063954 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_8|40052109|40077929|-1 +chrX 40064333 40064601 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_7|40052109|40077929|-1 +chrX 40070970 40071161 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_6|40052109|40077929|-1 +chrX 40071634 40071692 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_5|40052109|40077929|-1 +chrX 40072346 40075182 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_4|40052109|40077929|-1 +chrX 40076451 40076534 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_3|40052109|40077929|-1 +chrX 40077841 40077929 BCOR MSHD_genes|ENSG00000183337|ENST00000378444|exon_2|40052109|40077929|-1 +chrX 47199045 47199108 UBA1 MSHD_genes|ENSG00000130985|ENST00000335972|exon_3|47198803|47214929|1 +chrX 48791109 48791331 GATA1 MSHD_genes|ENSG00000102145|ENST00000376670|exon_2|48791110|48794164|1 +chrX 48791841 48792223 GATA1 MSHD_genes|ENSG00000102145|ENST00000376670|exon_3|48791110|48794164|1 +chrX 48792320 48792470 GATA1 MSHD_genes|ENSG00000102145|ENST00000376670|exon_4|48791110|48794164|1 +chrX 48793169 48793299 GATA1 MSHD_genes|ENSG00000102145|ENST00000376670|exon_5|48791110|48794164|1 +chrX 48793790 48794164 GATA1 MSHD_genes|ENSG00000102145|ENST00000376670|exon_6|48791110|48794164|1 +chrX 53380102 53380188 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_25|53380103|53422600|-1 +chrX 53380617 53380732 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_24|53380103|53422600|-1 +chrX 53381015 53381089 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_23|53380103|53422600|-1 +chrX 53382229 53382385 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_22|53380103|53422600|-1 +chrX 53382503 53382662 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_21|53380103|53422600|-1 +chrX 53383094 53383255 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_20|53380103|53422600|-1 +chrX 53394775 53394890 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_19|53380103|53422600|-1 +chrX 53396224 53396382 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_18|53380103|53422600|-1 +chrX 53396469 53396619 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_17|53380103|53422600|-1 +chrX 53399586 53399732 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_16|53380103|53422600|-1 +chrX 53403563 53403674 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_15|53380103|53422600|-1 +chrX 53403774 53403895 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_14|53380103|53422600|-1 +chrX 53405009 53405151 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_13|53380103|53422600|-1 +chrX 53405242 53405393 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_12|53380103|53422600|-1 +chrX 53405490 53405674 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_11|53380103|53422600|-1 +chrX 53405768 53405958 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_10|53380103|53422600|-1 +chrX 53409059 53409271 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_9|53380103|53422600|-1 +chrX 53409418 53409505 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_8|53380103|53422600|-1 +chrX 53411758 53411903 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_7|53380103|53422600|-1 +chrX 53411992 53412255 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_6|53380103|53422600|-1 +chrX 53412897 53413140 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_5|53380103|53422600|-1 +chrX 53413229 53413437 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_4|53380103|53422600|-1 +chrX 53414755 53414872 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_3|53380103|53422600|-1 +chrX 53414978 53415171 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_2|53380103|53422600|-1 +chrX 53422489 53422600 SMC1A MSHD_genes|ENSG00000072501|ENST00000322213|exon_1|53380103|53422600|-1 +chrX 124022627 124022673 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_3|124022628|124100597|1 +chrX 124025837 124025920 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_4|124022628|124100597|1 +chrX 124030958 124031127 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_5|124022628|124100597|1 +chrX 124037524 124037625 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_6|124022628|124100597|1 +chrX 124042566 124042647 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_7|124022628|124100597|1 +chrX 124045161 124045370 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_8|124022628|124100597|1 +chrX 124047351 124047507 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_9|124022628|124100597|1 +chrX 124049002 124049080 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_10|124022628|124100597|1 +chrX 124050183 124050311 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_11|124022628|124100597|1 +chrX 124051118 124051221 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_12|124022628|124100597|1 +chrX 124051312 124051396 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_13|124022628|124100597|1 +chrX 124056125 124056237 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_14|124022628|124100597|1 +chrX 124057863 124057979 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_15|124022628|124100597|1 +chrX 124061221 124061343 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_16|124022628|124100597|1 +chrX 124061768 124061876 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_17|124022628|124100597|1 +chrX 124062899 124062996 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_18|124022628|124100597|1 +chrX 124063113 124063207 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_19|124022628|124100597|1 +chrX 124063845 124064053 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_20|124022628|124100597|1 +chrX 124065873 124065948 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_21|124022628|124100597|1 +chrX 124066172 124066264 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_22|124022628|124100597|1 +chrX 124066353 124066438 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_23|124022628|124100597|1 +chrX 124068561 124068658 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_24|124022628|124100597|1 +chrX 124071146 124071325 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_25|124022628|124100597|1 +chrX 124076329 124076473 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_26|124022628|124100597|1 +chrX 124077954 124078060 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_27|124022628|124100597|1 +chrX 124081377 124081530 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_28|124022628|124100597|1 +chrX 124083418 124083551 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_29|124022628|124100597|1 +chrX 124086544 124086772 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_30|124022628|124100597|1 +chrX 124090572 124090766 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_31|124022628|124100597|1 +chrX 124094015 124094146 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_33|124022628|124100597|1 +chrX 124095369 124095451 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_34|124022628|124100597|1 +chrX 124100571 124100597 STAG2 MSHD_genes|ENSG00000101972|ENST00000371145|exon_35|124022628|124100597|1 +chrX 130005231 130005319 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_2|130005232|130056136|1 +chrX 130012575 130012670 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_3|130005232|130056136|1 +chrX 130012947 130016215 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_4|130005232|130056136|1 +chrX 130020982 130021152 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_5|130005232|130056136|1 +chrX 130022894 130022979 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_6|130005232|130056136|1 +chrX 130024987 130025381 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_7|130005232|130056136|1 +chrX 130028632 130028863 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_8|130005232|130056136|1 +chrX 130037364 130037535 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_10|130005232|130056136|1 +chrX 130039134 130039284 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_11|130005232|130056136|1 +chrX 130050714 130050796 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_12|130005232|130056136|1 +chrX 130051857 130052018 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_13|130005232|130056136|1 +chrX 130055851 130056136 BCORL1 MSHD_genes|ENSG00000085185|ENST00000540052|exon_14|130005232|130056136|1 +chrX 134377617 134377757 PHF6 MSHD_genes|ENSG00000156531|ENST00000370803|exon_2|134377618|134425330|1 +chrX 134378002 134378108 PHF6 MSHD_genes|ENSG00000156531|ENST00000370803|exon_3|134377618|134425330|1 +chrX 134393498 134393636 PHF6 MSHD_genes|ENSG00000156531|ENST00000370803|exon_4|134377618|134425330|1 +chrX 134393906 134393954 PHF6 MSHD_genes|ENSG00000156531|ENST00000370803|exon_5|134377618|134425330|1 +chrX 134413488 134413659 PHF6 MSHD_genes|ENSG00000156531|ENST00000370803|exon_6|134377618|134425330|1 +chrX 134413820 134413968 PHF6 MSHD_genes|ENSG00000156531|ENST00000370803|exon_7|134377618|134425330|1 +chrX 134415013 134415122 PHF6 MSHD_genes|ENSG00000156531|ENST00000370803|exon_8|134377618|134425330|1 +chrX 134417166 134417304 PHF6 MSHD_genes|ENSG00000156531|ENST00000370803|exon_9|134377618|134425330|1 +chrX 134425198 134425332 PHF6 MSHD_genes|ENSG00000156531|ENST00000370803|exon_10|134377618|134425330|1 diff --git a/assets/grna_samplesheet_template.csv b/assets/grna_samplesheet_template.csv new file mode 100644 index 0000000..9285f5d --- /dev/null +++ b/assets/grna_samplesheet_template.csv @@ -0,0 +1,3 @@ +guide_id,spacer,pam,idt +AAVS1_site14,GGGGCCACTAGGGACAGGAT,NGG, +PLCB2_KO,GACTGGCTGACGTCGACATC,NGG, diff --git a/assets/models/wgs_shape_model.pkl b/assets/models/wgs_shape_model.pkl new file mode 100755 index 0000000..70414f3 Binary files /dev/null and b/assets/models/wgs_shape_model.pkl differ diff --git a/assets/offtarget_pon.tsv b/assets/offtarget_pon.tsv new file mode 100644 index 0000000..8bc99a1 --- /dev/null +++ b/assets/offtarget_pon.tsv @@ -0,0 +1,31461 @@ +chrom pos n_donors max_indel_reads max_indel_fraction blacklisted +chr1 103308 0 0 0.0 0 +chr1 279874 0 0 0.0 0 +chr1 365389 0 0 0.0 0 +chr1 366821 0 0 0.0 0 +chr1 373364 0 0 0.0 0 +chr1 413778 0 0 0.0 0 +chr1 594453 0 0 0.0 0 +chr1 595885 0 0 0.0 0 +chr1 601618 0 0 0.0 0 +chr1 649532 0 0 0.0 0 +chr1 848899 0 0 0.0 0 +chr1 898143 0 0 0.0 0 +chr1 901114 0 0 0.0 0 +chr1 940905 0 0 0.0 0 +chr1 982176 0 0 0.0 0 +chr1 1081568 0 0 0.0 0 +chr1 1118101 0 0 0.0 0 +chr1 1133182 0 0 0.0 0 +chr1 1138327 0 0 0.0 0 +chr1 1158007 0 0 0.0 0 +chr1 1169042 0 0 0.0 0 +chr1 1173567 0 0 0.0 0 +chr1 1180356 0 0 0.0 0 +chr1 1214551 0 0 0.0 0 +chr1 1253653 0 0 0.0 0 +chr1 1310716 0 0 0.0 0 +chr1 1321991 0 0 0.0 0 +chr1 1341686 0 0 0.0 0 +chr1 1353065 0 0 0.0 0 +chr1 1355013 0 0 0.0 0 +chr1 1383004 0 0 0.0 0 +chr1 1518734 0 0 0.0 0 +chr1 1578442 0 0 0.0 0 +chr1 1583794 0 0 0.0 0 +chr1 1666487 0 0 0.0 0 +chr1 1835793 0 0 0.0 0 +chr1 1936660 0 0 0.0 0 +chr1 1939622 0 0 0.0 0 +chr1 2043206 0 0 0.0 0 +chr1 2055577 0 0 0.0 0 +chr1 2064862 0 0 0.0 0 +chr1 2146248 0 0 0.0 0 +chr1 2164675 0 0 0.0 0 +chr1 2196493 0 0 0.0 0 +chr1 2309499 0 0 0.0 0 +chr1 2340878 0 0 0.0 0 +chr1 2409949 0 0 0.0 0 +chr1 2412874 0 0 0.0 0 +chr1 2434447 0 0 0.0 0 +chr1 2452001 0 0 0.0 0 +chr1 2474558 0 0 0.0 0 +chr1 2518522 0 0 0.0 0 +chr1 2542420 0 0 0.0 0 +chr1 2784138 0 0 0.0 0 +chr1 2814186 0 0 0.0 0 +chr1 2846978 0 0 0.0 0 +chr1 2920558 0 0 0.0 0 +chr1 2949494 0 0 0.0 0 +chr1 2972378 0 0 0.0 0 +chr1 3018872 0 0 0.0 0 +chr1 3023538 0 0 0.0 0 +chr1 3029566 0 0 0.0 0 +chr1 3058730 0 0 0.0 0 +chr1 3062056 0 0 0.0 0 +chr1 3092435 0 0 0.0 0 +chr1 3145026 0 0 0.0 0 +chr1 3163530 0 0 0.0 0 +chr1 3219105 0 0 0.0 0 +chr1 3290139 0 0 0.0 0 +chr1 3317493 0 0 0.0 0 +chr1 3356092 0 0 0.0 0 +chr1 3362209 0 0 0.0 0 +chr1 3430009 0 1 0.0147 0 +chr1 3509156 0 0 0.0 0 +chr1 3540822 0 0 0.0 0 +chr1 3756540 0 0 0.0 0 +chr1 3771632 0 1 0.0127 0 +chr1 3787898 0 0 0.0 0 +chr1 3851180 0 0 0.0 0 +chr1 3891171 0 0 0.0 0 +chr1 3892914 0 0 0.0 0 +chr1 3997101 0 0 0.0 0 +chr1 4150807 0 0 0.0 0 +chr1 4266171 0 0 0.0 0 +chr1 4297994 0 0 0.0 0 +chr1 4348241 0 0 0.0 0 +chr1 4537961 0 0 0.0 0 +chr1 4541228 0 0 0.0 0 +chr1 4647144 0 0 0.0 0 +chr1 4664631 0 0 0.0 0 +chr1 4740710 0 0 0.0 0 +chr1 4771068 0 0 0.0 0 +chr1 4789856 0 0 0.0 0 +chr1 4826732 0 0 0.0 0 +chr1 4879066 0 0 0.0 0 +chr1 4940835 0 0 0.0 0 +chr1 4951317 0 0 0.0 0 +chr1 4967322 0 0 0.0 0 +chr1 4978878 0 0 0.0 0 +chr1 5113410 0 0 0.0 0 +chr1 5254171 0 0 0.0 0 +chr1 5273191 0 0 0.0 0 +chr1 5294639 0 0 0.0 0 +chr1 5325449 0 0 0.0 0 +chr1 5332602 0 0 0.0 0 +chr1 5350032 0 0 0.0 0 +chr1 5506869 0 0 0.0 0 +chr1 5528139 0 0 0.0 0 +chr1 5567057 0 0 0.0 0 +chr1 5593667 0 0 0.0 0 +chr1 5648848 0 0 0.0 0 +chr1 5685438 0 0 0.0 0 +chr1 5862742 0 0 0.0 0 +chr1 5880118 0 0 0.0 0 +chr1 5943539 0 0 0.0 0 +chr1 5954062 0 0 0.0 0 +chr1 5969081 0 0 0.0 0 +chr1 6016285 0 0 0.0 0 +chr1 6127095 0 0 0.0 0 +chr1 6167022 0 0 0.0 0 +chr1 6212975 0 0 0.0 0 +chr1 6254992 0 0 0.0 0 +chr1 6257436 0 1 0.0132 0 +chr1 6350522 0 0 0.0 0 +chr1 6501599 0 0 0.0 0 +chr1 6557887 0 0 0.0 0 +chr1 6578402 0 0 0.0 0 +chr1 6624137 0 0 0.0 0 +chr1 6625537 0 0 0.0 0 +chr1 6695852 0 0 0.0 0 +chr1 7314362 0 1 0.0167 0 +chr1 7330146 0 0 0.0 0 +chr1 7425801 0 0 0.0 0 +chr1 7434574 0 0 0.0 0 +chr1 7520594 0 0 0.0 0 +chr1 7584270 0 0 0.0 0 +chr1 7590582 0 0 0.0 0 +chr1 7868790 0 0 0.0 0 +chr1 7875510 0 0 0.0 0 +chr1 7884734 0 0 0.0 0 +chr1 7955828 0 0 0.0 0 +chr1 7982248 0 0 0.0 0 +chr1 8070830 0 1 0.0118 0 +chr1 8077852 0 0 0.0 0 +chr1 8166851 0 0 0.0 0 +chr1 8350125 0 0 0.0 0 +chr1 8374384 1 3 0.0349 1 +chr1 8432298 0 0 0.0 0 +chr1 8531328 0 0 0.0 0 +chr1 8572725 0 0 0.0 0 +chr1 8708144 0 0 0.0 0 +chr1 8737493 0 0 0.0 0 +chr1 8789726 0 0 0.0 0 +chr1 8898147 0 0 0.0 0 +chr1 9166670 0 0 0.0 0 +chr1 9327979 0 0 0.0 0 +chr1 9372333 0 0 0.0 0 +chr1 9382613 0 0 0.0 0 +chr1 9449173 0 0 0.0 0 +chr1 9511056 0 0 0.0 0 +chr1 9602041 0 0 0.0 0 +chr1 9642848 0 0 0.0 0 +chr1 9908467 0 0 0.0 0 +chr1 9920357 0 0 0.0 0 +chr1 9946134 0 0 0.0 0 +chr1 10067651 0 0 0.0 0 +chr1 10068720 0 0 0.0 0 +chr1 10312358 0 0 0.0 0 +chr1 10533827 0 0 0.0 0 +chr1 10561172 0 0 0.0 0 +chr1 10646439 0 0 0.0 0 +chr1 10660543 0 0 0.0 0 +chr1 10739543 0 0 0.0 0 +chr1 10782119 0 0 0.0 0 +chr1 10834960 0 0 0.0 0 +chr1 10990499 0 0 0.0 0 +chr1 11074040 0 0 0.0 0 +chr1 11145113 0 0 0.0 0 +chr1 11205911 0 1 0.0256 0 +chr1 11236400 0 0 0.0 0 +chr1 11395425 0 0 0.0 0 +chr1 11427349 0 0 0.0 0 +chr1 11469804 0 0 0.0 0 +chr1 11473603 0 0 0.0 0 +chr1 11560197 0 0 0.0 0 +chr1 11572813 0 0 0.0 0 +chr1 11583936 0 0 0.0 0 +chr1 11628616 0 0 0.0 0 +chr1 11646671 0 0 0.0 0 +chr1 11721879 0 0 0.0 0 +chr1 11810492 0 0 0.0 0 +chr1 11869191 0 0 0.0 0 +chr1 11877975 0 0 0.0 0 +chr1 11907015 0 0 0.0 0 +chr1 11950440 0 0 0.0 0 +chr1 11958030 0 0 0.0 0 +chr1 11979010 0 0 0.0 0 +chr1 12071930 0 0 0.0 0 +chr1 12109961 0 0 0.0 0 +chr1 12203502 0 0 0.0 0 +chr1 12221582 0 0 0.0 0 +chr1 12316870 0 0 0.0 0 +chr1 12429735 0 1 0.0217 0 +chr1 12477835 0 0 0.0 0 +chr1 12630601 0 0 0.0 0 +chr1 12722840 0 0 0.0 0 +chr1 12837222 0 0 0.0 0 +chr1 13120810 0 1 0.013 0 +chr1 13374846 0 0 0.0 0 +chr1 13512629 0 0 0.0 0 +chr1 13612092 0 0 0.0 0 +chr1 13745319 0 0 0.0 0 +chr1 13811580 0 0 0.0 0 +chr1 13915697 0 0 0.0 0 +chr1 13962120 0 0 0.0 0 +chr1 13981849 0 0 0.0 0 +chr1 14043092 0 0 0.0 0 +chr1 14094167 0 1 0.0278 0 +chr1 14160012 0 0 0.0 0 +chr1 14182245 0 0 0.0 0 +chr1 14373385 0 0 0.0 0 +chr1 14449121 0 0 0.0 0 +chr1 14492510 0 0 0.0 0 +chr1 14713517 0 0 0.0 0 +chr1 14737954 0 0 0.0 0 +chr1 14798121 0 0 0.0 0 +chr1 14930587 0 0 0.0 0 +chr1 14962298 0 0 0.0 0 +chr1 14981556 0 0 0.0 0 +chr1 15028127 0 0 0.0 0 +chr1 15030312 0 0 0.0 0 +chr1 15042784 0 0 0.0 0 +chr1 15095694 0 0 0.0 0 +chr1 15123433 0 0 0.0 0 +chr1 15196837 0 0 0.0 0 +chr1 15221196 0 0 0.0 0 +chr1 15288122 0 0 0.0 0 +chr1 15324109 0 0 0.0 0 +chr1 15393729 0 0 0.0 0 +chr1 15401795 0 0 0.0 0 +chr1 15416207 0 0 0.0 0 +chr1 15452173 0 0 0.0 0 +chr1 15537112 0 1 0.0204 0 +chr1 15573758 0 0 0.0 0 +chr1 15666586 0 0 0.0 0 +chr1 15829685 0 1 0.0143 0 +chr1 15994165 0 0 0.0 0 +chr1 16091450 0 0 0.0 0 +chr1 16097779 0 0 0.0 0 +chr1 16188164 0 0 0.0 0 +chr1 16229950 0 1 0.0189 0 +chr1 16243330 0 0 0.0 0 +chr1 16267632 0 0 0.0 0 +chr1 16482730 0 0 0.0 0 +chr1 16483818 0 0 0.0 0 +chr1 16630474 0 0 0.0 0 +chr1 16727002 0 0 0.0 0 +chr1 16762706 0 0 0.0 0 +chr1 16939565 0 0 0.0 0 +chr1 16960988 0 0 0.0 0 +chr1 16984604 0 0 0.0 0 +chr1 16993675 0 0 0.0 0 +chr1 17027459 0 0 0.0 0 +chr1 17070514 0 0 0.0 0 +chr1 17106364 0 0 0.0 0 +chr1 17149536 0 0 0.0 0 +chr1 17156443 0 0 0.0 0 +chr1 17202763 0 0 0.0 0 +chr1 17250794 0 0 0.0 0 +chr1 17254075 0 0 0.0 0 +chr1 17286111 0 0 0.0 0 +chr1 17377103 0 0 0.0 0 +chr1 17468474 0 0 0.0 0 +chr1 17502579 0 0 0.0 0 +chr1 17528671 0 0 0.0 0 +chr1 17564842 0 0 0.0 0 +chr1 17575640 0 0 0.0 0 +chr1 17789904 0 0 0.0 0 +chr1 17958339 0 0 0.0 0 +chr1 18034968 0 0 0.0 0 +chr1 18283447 0 0 0.0 0 +chr1 18303972 0 0 0.0 0 +chr1 18308045 0 0 0.0 0 +chr1 18383732 0 0 0.0 0 +chr1 18414472 0 0 0.0 0 +chr1 18436345 0 0 0.0 0 +chr1 18439690 0 0 0.0 0 +chr1 18500552 0 0 0.0 0 +chr1 18514373 0 0 0.0 0 +chr1 18528642 0 0 0.0 0 +chr1 18569542 0 0 0.0 0 +chr1 18583458 0 0 0.0 0 +chr1 18637628 0 0 0.0 0 +chr1 18682728 0 0 0.0 0 +chr1 18699480 0 1 0.0263 0 +chr1 18730381 0 0 0.0 0 +chr1 18740429 0 0 0.0 0 +chr1 18760860 0 0 0.0 0 +chr1 18806088 0 0 0.0 0 +chr1 18828798 0 0 0.0 0 +chr1 18860068 0 0 0.0 0 +chr1 18947243 0 0 0.0 0 +chr1 19033583 0 0 0.0 0 +chr1 19065274 0 0 0.0 0 +chr1 19242446 0 0 0.0 0 +chr1 19300183 0 0 0.0 0 +chr1 19303500 0 0 0.0 0 +chr1 19306680 0 0 0.0 0 +chr1 19317049 0 0 0.0 0 +chr1 19334928 0 0 0.0 0 +chr1 19370010 0 0 0.0 0 +chr1 19397710 0 0 0.0 0 +chr1 19406132 0 0 0.0 0 +chr1 19418619 0 0 0.0 0 +chr1 19625533 0 0 0.0 0 +chr1 19676965 0 1 0.0175 0 +chr1 19831157 0 0 0.0 0 +chr1 19940720 0 0 0.0 0 +chr1 19976752 0 0 0.0 0 +chr1 19997980 0 0 0.0 0 +chr1 20021963 0 0 0.0 0 +chr1 20030139 0 0 0.0 0 +chr1 20292244 0 0 0.0 0 +chr1 20296386 0 0 0.0 0 +chr1 20391459 0 0 0.0 0 +chr1 20440852 0 0 0.0 0 +chr1 20534413 0 0 0.0 0 +chr1 20701781 0 0 0.0 0 +chr1 20718179 0 0 0.0 0 +chr1 20842195 0 0 0.0 0 +chr1 20850745 0 0 0.0 0 +chr1 20886602 0 1 0.0175 0 +chr1 21040039 0 0 0.0 0 +chr1 21147974 0 0 0.0 0 +chr1 21285009 0 0 0.0 0 +chr1 21418264 0 0 0.0 0 +chr1 21437224 0 0 0.0 0 +chr1 21495354 0 0 0.0 0 +chr1 21702456 0 0 0.0 0 +chr1 21716952 0 0 0.0 0 +chr1 21720228 0 0 0.0 0 +chr1 21763962 0 0 0.0 0 +chr1 21858050 0 0 0.0 0 +chr1 21881393 0 0 0.0 0 +chr1 21881565 0 0 0.0 0 +chr1 22030527 0 0 0.0 0 +chr1 22095894 0 0 0.0 0 +chr1 22163903 0 0 0.0 0 +chr1 22277928 0 0 0.0 0 +chr1 22451046 0 0 0.0 0 +chr1 22532874 0 0 0.0 0 +chr1 22540981 0 0 0.0 0 +chr1 22541421 0 0 0.0 0 +chr1 22545376 0 0 0.0 0 +chr1 22821865 0 0 0.0 0 +chr1 22886127 0 0 0.0 0 +chr1 22936142 0 0 0.0 0 +chr1 22999408 0 0 0.0 0 +chr1 23389808 0 0 0.0 0 +chr1 23437762 0 0 0.0 0 +chr1 23453152 0 0 0.0 0 +chr1 23598630 0 0 0.0 0 +chr1 23930584 0 0 0.0 0 +chr1 23933409 0 0 0.0 0 +chr1 23960531 0 0 0.0 0 +chr1 24069872 0 0 0.0 0 +chr1 24093018 0 0 0.0 0 +chr1 24130938 0 0 0.0 0 +chr1 24149645 0 0 0.0 0 +chr1 24155765 0 0 0.0 0 +chr1 24215052 0 0 0.0 0 +chr1 24255509 0 0 0.0 0 +chr1 24279084 0 0 0.0 0 +chr1 24339010 0 0 0.0 0 +chr1 24529165 0 0 0.0 0 +chr1 24640410 0 0 0.0 0 +chr1 24857642 0 0 0.0 0 +chr1 24898924 0 0 0.0 0 +chr1 24921185 0 0 0.0 0 +chr1 24948692 0 0 0.0 0 +chr1 24955371 0 0 0.0 0 +chr1 24957716 0 0 0.0 0 +chr1 24959850 0 0 0.0 0 +chr1 25024749 0 0 0.0 0 +chr1 25034356 0 0 0.0 0 +chr1 25043214 0 0 0.0 0 +chr1 25051465 0 0 0.0 0 +chr1 25054347 0 2 0.3333 0 +chr1 25065894 0 0 0.0 0 +chr1 25096014 0 0 0.0 0 +chr1 25173559 0 0 0.0 0 +chr1 25230683 0 0 0.0 0 +chr1 25308625 0 0 0.0 0 +chr1 25318093 0 0 0.0 0 +chr1 25374336 0 0 0.0 0 +chr1 25545248 0 0 0.0 0 +chr1 25569108 0 0 0.0 0 +chr1 25578310 0 0 0.0 0 +chr1 25612025 0 0 0.0 0 +chr1 25614040 0 0 0.0 0 +chr1 25659348 0 0 0.0 0 +chr1 25682314 0 0 0.0 0 +chr1 25691541 0 0 0.0 0 +chr1 25735884 0 0 0.0 0 +chr1 25775698 0 0 0.0 0 +chr1 25844779 0 0 0.0 0 +chr1 25949301 0 0 0.0 0 +chr1 26188022 0 0 0.0 0 +chr1 26291592 0 0 0.0 0 +chr1 26413726 0 0 0.0 0 +chr1 26417494 0 0 0.0 0 +chr1 26464979 0 0 0.0 0 +chr1 26542621 0 0 0.0 0 +chr1 26573376 0 0 0.0 0 +chr1 26692475 0 0 0.0 0 +chr1 26701078 0 0 0.0 0 +chr1 26814845 0 0 0.0 0 +chr1 26823879 0 0 0.0 0 +chr1 26828975 0 0 0.0 0 +chr1 26909760 0 0 0.0 0 +chr1 26980164 0 0 0.0 0 +chr1 27092910 0 0 0.0 0 +chr1 27113828 0 0 0.0 0 +chr1 27122434 0 0 0.0 0 +chr1 27137257 0 0 0.0 0 +chr1 27152913 0 0 0.0 0 +chr1 27179178 0 0 0.0 0 +chr1 27213886 0 0 0.0 0 +chr1 27256955 0 0 0.0 0 +chr1 27284160 0 0 0.0 0 +chr1 27301535 0 0 0.0 0 +chr1 27328096 0 0 0.0 0 +chr1 27332154 0 0 0.0 0 +chr1 27396088 0 0 0.0 0 +chr1 27508061 0 1 0.0189 0 +chr1 27551637 0 0 0.0 0 +chr1 27577011 0 0 0.0 0 +chr1 27589959 0 0 0.0 0 +chr1 27598867 0 0 0.0 0 +chr1 27626924 0 0 0.0 0 +chr1 27729348 0 1 0.0196 0 +chr1 27836002 0 1 0.0137 0 +chr1 27940742 0 0 0.0 0 +chr1 28049321 0 0 0.0 0 +chr1 28101427 0 0 0.0 0 +chr1 28121565 0 0 0.0 0 +chr1 28128481 0 0 0.0 0 +chr1 28136674 0 0 0.0 0 +chr1 28158201 0 0 0.0 0 +chr1 28223141 0 0 0.0 0 +chr1 28290925 0 0 0.0 0 +chr1 28579944 0 0 0.0 0 +chr1 28580333 0 1 0.0357 0 +chr1 28602383 0 0 0.0 0 +chr1 28636774 0 0 0.0 0 +chr1 28702533 0 0 0.0 0 +chr1 29085679 0 0 0.0 0 +chr1 29459531 0 0 0.0 0 +chr1 29463048 0 0 0.0 0 +chr1 29564562 0 0 0.0 0 +chr1 29566906 0 0 0.0 0 +chr1 29570708 0 0 0.0 0 +chr1 29723894 0 0 0.0 0 +chr1 29751147 0 0 0.0 0 +chr1 29892872 0 0 0.0 0 +chr1 29953750 0 0 0.0 0 +chr1 30064556 0 0 0.0 0 +chr1 30151506 0 0 0.0 0 +chr1 30247445 0 0 0.0 0 +chr1 30256346 0 0 0.0 0 +chr1 30273024 0 0 0.0 0 +chr1 30273372 0 0 0.0 0 +chr1 30356662 0 0 0.0 0 +chr1 30444634 0 0 0.0 0 +chr1 30600346 0 0 0.0 0 +chr1 30735353 0 0 0.0 0 +chr1 30806206 0 0 0.0 0 +chr1 30859268 0 0 0.0 0 +chr1 30880238 0 0 0.0 0 +chr1 30884535 0 0 0.0 0 +chr1 30937202 0 0 0.0 0 +chr1 30943206 0 0 0.0 0 +chr1 30967223 0 0 0.0 0 +chr1 30968495 0 1 0.0145 0 +chr1 30983491 0 1 0.0233 0 +chr1 31084464 0 0 0.0 0 +chr1 31221246 0 0 0.0 0 +chr1 31388475 0 0 0.0 0 +chr1 31433736 0 0 0.0 0 +chr1 31454563 0 0 0.0 0 +chr1 31468110 0 0 0.0 0 +chr1 31471512 0 0 0.0 0 +chr1 31627133 0 0 0.0 0 +chr1 31661195 0 0 0.0 0 +chr1 31667325 0 0 0.0 0 +chr1 31697164 0 0 0.0 0 +chr1 31715257 0 0 0.0 0 +chr1 31964716 0 0 0.0 0 +chr1 31972422 0 0 0.0 0 +chr1 32221116 0 0 0.0 0 +chr1 32342849 0 0 0.0 0 +chr1 32378807 0 0 0.0 0 +chr1 32394132 0 0 0.0 0 +chr1 32395526 0 0 0.0 0 +chr1 32825941 0 0 0.0 0 +chr1 32931203 0 0 0.0 0 +chr1 32994434 0 0 0.0 0 +chr1 33006302 0 0 0.0 0 +chr1 33031480 0 0 0.0 0 +chr1 33065806 0 0 0.0 0 +chr1 33115080 0 0 0.0 0 +chr1 33179023 0 0 0.0 0 +chr1 33297057 0 0 0.0 0 +chr1 33322987 0 0 0.0 0 +chr1 33377385 0 0 0.0 0 +chr1 33406044 0 0 0.0 0 +chr1 33460179 0 0 0.0 0 +chr1 33479732 0 0 0.0 0 +chr1 33863971 0 0 0.0 0 +chr1 33869716 0 0 0.0 0 +chr1 33915908 0 0 0.0 0 +chr1 33952866 0 0 0.0 0 +chr1 33964886 0 0 0.0 0 +chr1 34076526 0 0 0.0 0 +chr1 34161713 0 0 0.0 0 +chr1 34217714 0 0 0.0 0 +chr1 34330798 0 0 0.0 0 +chr1 34602390 0 0 0.0 0 +chr1 34644633 0 0 0.0 0 +chr1 34672053 0 0 0.0 0 +chr1 34692121 0 0 0.0 0 +chr1 34695815 0 0 0.0 0 +chr1 34700467 0 0 0.0 0 +chr1 34734692 0 0 0.0 0 +chr1 34853641 0 0 0.0 0 +chr1 34884679 0 0 0.0 0 +chr1 35027327 0 0 0.0 0 +chr1 35047519 0 0 0.0 0 +chr1 35062801 0 0 0.0 0 +chr1 35117867 0 0 0.0 0 +chr1 35147937 0 1 0.0161 0 +chr1 35411976 0 0 0.0 0 +chr1 35433837 0 0 0.0 0 +chr1 35457344 0 0 0.0 0 +chr1 35628756 0 0 0.0 0 +chr1 35853583 0 0 0.0 0 +chr1 35892665 0 0 0.0 0 +chr1 35974928 0 1 0.0159 0 +chr1 35989765 0 0 0.0 0 +chr1 36240295 0 0 0.0 0 +chr1 36251365 0 0 0.0 0 +chr1 36514068 0 0 0.0 0 +chr1 36650018 0 0 0.0 0 +chr1 36690119 0 0 0.0 0 +chr1 36760886 0 0 0.0 0 +chr1 36823662 0 0 0.0 0 +chr1 36853022 0 0 0.0 0 +chr1 36922030 0 0 0.0 0 +chr1 36987192 0 0 0.0 0 +chr1 37008260 0 0 0.0 0 +chr1 37045207 0 0 0.0 0 +chr1 37051570 0 0 0.0 0 +chr1 37097882 0 0 0.0 0 +chr1 37143565 0 0 0.0 0 +chr1 37213828 0 0 0.0 0 +chr1 37234517 0 0 0.0 0 +chr1 37240421 0 0 0.0 0 +chr1 37315215 0 0 0.0 0 +chr1 37325974 0 0 0.0 0 +chr1 37357322 0 0 0.0 0 +chr1 37416053 0 0 0.0 0 +chr1 37453058 0 0 0.0 0 +chr1 37480320 0 0 0.0 0 +chr1 37481641 0 0 0.0 0 +chr1 37536357 0 0 0.0 0 +chr1 37544879 0 0 0.0 0 +chr1 37594910 0 0 0.0 0 +chr1 37598228 0 0 0.0 0 +chr1 37737927 1 7 0.35 1 +chr1 37743323 0 0 0.0 0 +chr1 37764622 0 0 0.0 0 +chr1 38049564 0 0 0.0 0 +chr1 38285340 0 0 0.0 0 +chr1 38290321 0 0 0.0 0 +chr1 38295283 0 0 0.0 0 +chr1 38356425 0 0 0.0 0 +chr1 38381611 0 0 0.0 0 +chr1 38532304 0 0 0.0 0 +chr1 38596033 0 0 0.0 0 +chr1 38733935 0 0 0.0 0 +chr1 38779319 0 0 0.0 0 +chr1 38837025 0 0 0.0 0 +chr1 38997438 0 0 0.0 0 +chr1 39024078 0 2 0.0299 0 +chr1 39033845 0 0 0.0 0 +chr1 39213297 0 0 0.0 0 +chr1 39248647 0 0 0.0 0 +chr1 39287399 0 0 0.0 0 +chr1 39307384 0 0 0.0 0 +chr1 39482976 0 0 0.0 0 +chr1 39489827 0 0 0.0 0 +chr1 39623790 0 0 0.0 0 +chr1 39651125 0 0 0.0 0 +chr1 39694493 0 0 0.0 0 +chr1 39832462 0 0 0.0 0 +chr1 39844394 0 0 0.0 0 +chr1 39876394 0 0 0.0 0 +chr1 39903632 0 0 0.0 0 +chr1 39933869 0 0 0.0 0 +chr1 39936151 0 0 0.0 0 +chr1 39951914 0 0 0.0 0 +chr1 39973741 0 0 0.0 0 +chr1 40021649 0 0 0.0 0 +chr1 40211831 0 0 0.0 0 +chr1 40252512 0 0 0.0 0 +chr1 40376431 0 0 0.0 0 +chr1 40467648 0 0 0.0 0 +chr1 40631032 0 0 0.0 0 +chr1 40931746 0 1 0.0139 0 +chr1 40998566 0 0 0.0 0 +chr1 41015925 0 0 0.0 0 +chr1 41041175 0 0 0.0 0 +chr1 41368067 0 0 0.0 0 +chr1 41381200 0 0 0.0 0 +chr1 41394978 0 0 0.0 0 +chr1 41410278 0 0 0.0 0 +chr1 41448137 0 0 0.0 0 +chr1 41561377 0 0 0.0 0 +chr1 41597193 0 0 0.0 0 +chr1 41782298 0 0 0.0 0 +chr1 42051864 0 0 0.0 0 +chr1 42088260 0 0 0.0 0 +chr1 42197493 0 0 0.0 0 +chr1 42262057 0 0 0.0 0 +chr1 42352551 0 0 0.0 0 +chr1 42408682 0 0 0.0 0 +chr1 42688783 0 0 0.0 0 +chr1 42912246 0 0 0.0 0 +chr1 42932830 0 0 0.0 0 +chr1 43025078 0 0 0.0 0 +chr1 43087692 0 1 0.0192 0 +chr1 43121695 0 0 0.0 0 +chr1 43330914 0 0 0.0 0 +chr1 43340375 0 0 0.0 0 +chr1 43494240 0 0 0.0 0 +chr1 43529456 0 0 0.0 0 +chr1 43590598 0 0 0.0 0 +chr1 43606913 0 0 0.0 0 +chr1 43642653 0 0 0.0 0 +chr1 43654438 1 4 0.05 1 +chr1 43674880 0 0 0.0 0 +chr1 43705051 0 0 0.0 0 +chr1 43738793 0 0 0.0 0 +chr1 43860604 0 0 0.0 0 +chr1 43992198 0 0 0.0 0 +chr1 44207139 0 0 0.0 0 +chr1 44496652 0 0 0.0 0 +chr1 44547571 0 0 0.0 0 +chr1 44574053 0 0 0.0 0 +chr1 44601234 0 0 0.0 0 +chr1 44616737 0 0 0.0 0 +chr1 44622884 0 0 0.0 0 +chr1 44654232 0 0 0.0 0 +chr1 44693577 0 0 0.0 0 +chr1 44762460 0 0 0.0 0 +chr1 44803158 0 0 0.0 0 +chr1 44807880 0 0 0.0 0 +chr1 44893909 0 0 0.0 0 +chr1 45000454 0 1 0.0185 0 +chr1 45092102 0 0 0.0 0 +chr1 45140178 0 0 0.0 0 +chr1 45566796 0 0 0.0 0 +chr1 45621271 0 0 0.0 0 +chr1 45837144 0 0 0.0 0 +chr1 45875832 0 0 0.0 0 +chr1 45989256 0 0 0.0 0 +chr1 46024841 0 1 0.0156 0 +chr1 46061536 0 0 0.0 0 +chr1 46133354 0 0 0.0 0 +chr1 46167667 0 0 0.0 0 +chr1 46314947 0 0 0.0 0 +chr1 46336041 0 0 0.0 0 +chr1 46420271 0 0 0.0 0 +chr1 46436869 0 0 0.0 0 +chr1 46510647 0 0 0.0 0 +chr1 46541168 0 0 0.0 0 +chr1 46615895 0 0 0.0 0 +chr1 46632270 0 0 0.0 0 +chr1 46771949 0 0 0.0 0 +chr1 46817325 0 0 0.0 0 +chr1 46820520 0 0 0.0 0 +chr1 46947400 0 0 0.0 0 +chr1 46953577 0 0 0.0 0 +chr1 46956152 0 0 0.0 0 +chr1 47007308 0 0 0.0 0 +chr1 47079173 0 0 0.0 0 +chr1 47269248 0 0 0.0 0 +chr1 47400191 0 0 0.0 0 +chr1 47538879 0 1 0.0149 0 +chr1 47577324 0 0 0.0 0 +chr1 47634601 0 0 0.0 0 +chr1 47680927 0 0 0.0 0 +chr1 47807814 0 0 0.0 0 +chr1 47816317 0 0 0.0 0 +chr1 47833898 0 0 0.0 0 +chr1 47869696 0 0 0.0 0 +chr1 47876452 0 0 0.0 0 +chr1 47957086 0 0 0.0 0 +chr1 48069866 0 0 0.0 0 +chr1 48190200 0 0 0.0 0 +chr1 48496171 0 0 0.0 0 +chr1 48501407 0 0 0.0 0 +chr1 48519688 0 0 0.0 0 +chr1 48586812 0 0 0.0 0 +chr1 48636858 0 0 0.0 0 +chr1 48670766 0 0 0.0 0 +chr1 48760610 0 0 0.0 0 +chr1 48783235 0 0 0.0 0 +chr1 48854548 0 0 0.0 0 +chr1 48951652 0 0 0.0 0 +chr1 49328124 0 0 0.0 0 +chr1 49424079 0 0 0.0 0 +chr1 49666540 0 0 0.0 0 +chr1 49693817 0 1 0.0333 0 +chr1 50017861 0 0 0.0 0 +chr1 50171257 0 0 0.0 0 +chr1 50208054 0 0 0.0 0 +chr1 50317840 0 0 0.0 0 +chr1 50409006 0 0 0.0 0 +chr1 50509824 0 0 0.0 0 +chr1 50588626 0 0 0.0 0 +chr1 50591601 0 0 0.0 0 +chr1 50663525 0 0 0.0 0 +chr1 50689508 0 0 0.0 0 +chr1 50976680 0 0 0.0 0 +chr1 51032753 0 0 0.0 0 +chr1 51169010 0 0 0.0 0 +chr1 51172834 0 0 0.0 0 +chr1 51289424 0 0 0.0 0 +chr1 51535349 0 0 0.0 0 +chr1 51887222 0 0 0.0 0 +chr1 52026512 0 0 0.0 0 +chr1 52043737 0 0 0.0 0 +chr1 52083737 0 0 0.0 0 +chr1 52400127 0 0 0.0 0 +chr1 52414649 0 0 0.0 0 +chr1 52447958 0 0 0.0 0 +chr1 52466009 0 0 0.0 0 +chr1 52601873 0 0 0.0 0 +chr1 52668942 0 0 0.0 0 +chr1 52857738 0 0 0.0 0 +chr1 52963941 0 0 0.0 0 +chr1 53078364 0 2 0.0435 0 +chr1 53084170 0 0 0.0 0 +chr1 53091080 0 0 0.0 0 +chr1 53113447 0 0 0.0 0 +chr1 53168923 0 0 0.0 0 +chr1 53314748 0 0 0.0 0 +chr1 53321020 0 0 0.0 0 +chr1 53323230 0 0 0.0 0 +chr1 53365388 0 0 0.0 0 +chr1 53550800 0 0 0.0 0 +chr1 53628929 0 0 0.0 0 +chr1 53678544 0 0 0.0 0 +chr1 53720670 0 0 0.0 0 +chr1 53743681 0 0 0.0 0 +chr1 53889542 0 0 0.0 0 +chr1 53980122 0 0 0.0 0 +chr1 54043373 0 0 0.0 0 +chr1 54267231 0 0 0.0 0 +chr1 54668703 0 0 0.0 0 +chr1 54754934 0 0 0.0 0 +chr1 54777615 0 0 0.0 0 +chr1 54805301 0 0 0.0 0 +chr1 54814634 0 0 0.0 0 +chr1 54848449 0 0 0.0 0 +chr1 54944817 1 41 0.6721 1 +chr1 55048171 0 0 0.0 0 +chr1 55053123 0 0 0.0 0 +chr1 55077406 0 0 0.0 0 +chr1 55193393 0 0 0.0 0 +chr1 55322499 0 0 0.0 0 +chr1 55500054 0 0 0.0 0 +chr1 55577817 0 0 0.0 0 +chr1 55607674 0 0 0.0 0 +chr1 55723771 0 0 0.0 0 +chr1 55786856 0 0 0.0 0 +chr1 55843840 0 0 0.0 0 +chr1 55994665 0 0 0.0 0 +chr1 56131749 0 0 0.0 0 +chr1 56253738 0 0 0.0 0 +chr1 56267793 0 0 0.0 0 +chr1 56294206 0 0 0.0 0 +chr1 56315967 0 0 0.0 0 +chr1 56334182 0 0 0.0 0 +chr1 56377682 0 0 0.0 0 +chr1 56407551 0 0 0.0 0 +chr1 56526127 0 0 0.0 0 +chr1 56711708 0 0 0.0 0 +chr1 56745057 0 0 0.0 0 +chr1 56924917 0 0 0.0 0 +chr1 56931686 0 0 0.0 0 +chr1 56963492 0 0 0.0 0 +chr1 57006302 0 0 0.0 0 +chr1 57018944 0 0 0.0 0 +chr1 57234889 0 0 0.0 0 +chr1 57537299 0 0 0.0 0 +chr1 57637693 0 0 0.0 0 +chr1 57741663 0 0 0.0 0 +chr1 57815914 0 0 0.0 0 +chr1 58020596 0 0 0.0 0 +chr1 58037375 0 0 0.0 0 +chr1 58054558 0 0 0.0 0 +chr1 58356175 0 0 0.0 0 +chr1 58363329 0 0 0.0 0 +chr1 58463877 0 0 0.0 0 +chr1 58476401 0 0 0.0 0 +chr1 58556759 0 0 0.0 0 +chr1 58586023 0 0 0.0 0 +chr1 58716220 0 0 0.0 0 +chr1 58738201 0 0 0.0 0 +chr1 58822410 0 0 0.0 0 +chr1 58873917 0 0 0.0 0 +chr1 59006622 0 0 0.0 0 +chr1 59015593 0 0 0.0 0 +chr1 59022238 0 0 0.0 0 +chr1 59112798 0 0 0.0 0 +chr1 59151240 0 0 0.0 0 +chr1 59217028 0 0 0.0 0 +chr1 59229723 0 0 0.0 0 +chr1 59485983 0 0 0.0 0 +chr1 59639981 0 0 0.0 0 +chr1 59673195 0 0 0.0 0 +chr1 59677347 0 0 0.0 0 +chr1 59697035 0 0 0.0 0 +chr1 59881746 0 0 0.0 0 +chr1 60225200 0 0 0.0 0 +chr1 60319220 0 0 0.0 0 +chr1 60486958 0 0 0.0 0 +chr1 60749281 0 0 0.0 0 +chr1 60967849 0 0 0.0 0 +chr1 61358312 1 42 0.7636 1 +chr1 61405298 0 0 0.0 0 +chr1 61408076 0 0 0.0 0 +chr1 61450593 0 0 0.0 0 +chr1 61476802 0 0 0.0 0 +chr1 61578692 0 0 0.0 0 +chr1 61602563 0 0 0.0 0 +chr1 61640914 0 0 0.0 0 +chr1 61983702 0 0 0.0 0 +chr1 62065001 0 0 0.0 0 +chr1 62169146 0 0 0.0 0 +chr1 62305133 0 1 0.0312 0 +chr1 62359219 0 0 0.0 0 +chr1 62412702 0 0 0.0 0 +chr1 62738396 0 0 0.0 0 +chr1 62899805 0 0 0.0 0 +chr1 62980166 0 0 0.0 0 +chr1 62983779 0 0 0.0 0 +chr1 63350550 0 0 0.0 0 +chr1 63361241 0 0 0.0 0 +chr1 63440834 0 0 0.0 0 +chr1 63507182 0 0 0.0 0 +chr1 63579460 0 0 0.0 0 +chr1 63595002 0 0 0.0 0 +chr1 63657859 0 0 0.0 0 +chr1 63747254 0 0 0.0 0 +chr1 63871782 0 0 0.0 0 +chr1 63996885 0 1 0.0244 0 +chr1 64060662 0 0 0.0 0 +chr1 64078641 0 0 0.0 0 +chr1 64296501 0 0 0.0 0 +chr1 64333846 0 0 0.0 0 +chr1 64335678 0 0 0.0 0 +chr1 64377651 0 0 0.0 0 +chr1 64391991 0 0 0.0 0 +chr1 64494792 0 1 0.0227 0 +chr1 64557045 0 0 0.0 0 +chr1 64580838 0 0 0.0 0 +chr1 64584610 0 0 0.0 0 +chr1 64724218 0 0 0.0 0 +chr1 64846827 0 0 0.0 0 +chr1 65129346 0 0 0.0 0 +chr1 65149278 0 0 0.0 0 +chr1 65153114 0 0 0.0 0 +chr1 65217581 0 0 0.0 0 +chr1 65285932 0 0 0.0 0 +chr1 65409675 0 0 0.0 0 +chr1 65505042 0 0 0.0 0 +chr1 65743507 1 64 0.7619 1 +chr1 65792198 0 0 0.0 0 +chr1 66103184 0 0 0.0 0 +chr1 66124015 0 0 0.0 0 +chr1 66183198 0 0 0.0 0 +chr1 66204130 0 0 0.0 0 +chr1 66217119 0 0 0.0 0 +chr1 66293816 0 0 0.0 0 +chr1 66371828 0 0 0.0 0 +chr1 66402556 0 0 0.0 0 +chr1 66509753 2 26 0.6 1 +chr1 66593032 0 0 0.0 0 +chr1 66617816 0 0 0.0 0 +chr1 66677669 0 0 0.0 0 +chr1 66693179 0 0 0.0 0 +chr1 66722592 0 0 0.0 0 +chr1 66757011 0 0 0.0 0 +chr1 66787910 0 0 0.0 0 +chr1 66951390 0 0 0.0 0 +chr1 67101242 0 0 0.0 0 +chr1 67234235 0 0 0.0 0 +chr1 67336472 0 0 0.0 0 +chr1 67712051 0 0 0.0 0 +chr1 67881235 0 0 0.0 0 +chr1 67982293 0 0 0.0 0 +chr1 68126854 0 0 0.0 0 +chr1 68132614 0 0 0.0 0 +chr1 68264822 0 0 0.0 0 +chr1 68376011 0 0 0.0 0 +chr1 68455365 0 0 0.0 0 +chr1 68547916 0 0 0.0 0 +chr1 68551156 0 0 0.0 0 +chr1 68597427 0 0 0.0 0 +chr1 68740838 0 0 0.0 0 +chr1 68775394 0 0 0.0 0 +chr1 68917370 0 0 0.0 0 +chr1 68985271 0 0 0.0 0 +chr1 68985641 0 0 0.0 0 +chr1 69005714 0 0 0.0 0 +chr1 69057195 0 0 0.0 0 +chr1 69251651 0 0 0.0 0 +chr1 69339627 0 0 0.0 0 +chr1 69561855 0 0 0.0 0 +chr1 69625679 0 0 0.0 0 +chr1 69637578 0 0 0.0 0 +chr1 69671196 0 0 0.0 0 +chr1 70007110 0 0 0.0 0 +chr1 70050801 0 0 0.0 0 +chr1 70244754 0 0 0.0 0 +chr1 70369899 0 0 0.0 0 +chr1 70372937 0 0 0.0 0 +chr1 70457871 0 0 0.0 0 +chr1 70515881 0 0 0.0 0 +chr1 70555080 0 0 0.0 0 +chr1 70768332 0 0 0.0 0 +chr1 70897586 0 0 0.0 0 +chr1 70954089 0 0 0.0 0 +chr1 71064864 0 0 0.0 0 +chr1 71129985 0 0 0.0 0 +chr1 71142481 0 0 0.0 0 +chr1 71177594 0 0 0.0 0 +chr1 71179524 0 0 0.0 0 +chr1 71271499 0 0 0.0 0 +chr1 71367108 0 0 0.0 0 +chr1 71375105 0 0 0.0 0 +chr1 71424700 0 0 0.0 0 +chr1 71580306 0 0 0.0 0 +chr1 71585351 0 0 0.0 0 +chr1 71799436 0 0 0.0 0 +chr1 72051423 0 0 0.0 0 +chr1 72074530 0 0 0.0 0 +chr1 72228411 0 0 0.0 0 +chr1 72491604 0 0 0.0 0 +chr1 72918529 0 0 0.0 0 +chr1 73148700 0 0 0.0 0 +chr1 73205543 0 0 0.0 0 +chr1 73357622 0 0 0.0 0 +chr1 73481529 0 0 0.0 0 +chr1 73576945 0 0 0.0 0 +chr1 73789261 0 0 0.0 0 +chr1 73964049 0 0 0.0 0 +chr1 74134392 0 0 0.0 0 +chr1 74293385 0 0 0.0 0 +chr1 74399894 0 0 0.0 0 +chr1 74637728 0 0 0.0 0 +chr1 74700867 0 0 0.0 0 +chr1 74834906 0 0 0.0 0 +chr1 74835889 0 0 0.0 0 +chr1 74920637 0 0 0.0 0 +chr1 75505469 0 0 0.0 0 +chr1 75535595 0 0 0.0 0 +chr1 76044913 0 0 0.0 0 +chr1 76072172 0 0 0.0 0 +chr1 76084458 0 0 0.0 0 +chr1 76114104 0 0 0.0 0 +chr1 76198451 0 0 0.0 0 +chr1 76247790 0 0 0.0 0 +chr1 76301324 0 0 0.0 0 +chr1 76592519 0 0 0.0 0 +chr1 76627165 0 0 0.0 0 +chr1 76700930 0 0 0.0 0 +chr1 76768355 0 0 0.0 0 +chr1 76779110 0 0 0.0 0 +chr1 76961657 0 0 0.0 0 +chr1 76976368 0 0 0.0 0 +chr1 76981861 0 0 0.0 0 +chr1 77011333 0 0 0.0 0 +chr1 77047118 0 0 0.0 0 +chr1 77063235 0 0 0.0 0 +chr1 77084704 0 1 0.0227 0 +chr1 77138532 0 0 0.0 0 +chr1 77140345 0 0 0.0 0 +chr1 77167535 0 0 0.0 0 +chr1 77300664 0 0 0.0 0 +chr1 77599045 0 0 0.0 0 +chr1 77732350 0 0 0.0 0 +chr1 78065387 0 0 0.0 0 +chr1 78118729 0 0 0.0 0 +chr1 78237164 0 0 0.0 0 +chr1 78492751 0 0 0.0 0 +chr1 78619557 0 0 0.0 0 +chr1 78693345 0 0 0.0 0 +chr1 78824847 0 0 0.0 0 +chr1 78884822 0 0 0.0 0 +chr1 78915399 0 0 0.0 0 +chr1 79000616 0 0 0.0 0 +chr1 79286261 0 0 0.0 0 +chr1 79410625 0 0 0.0 0 +chr1 79431132 0 0 0.0 0 +chr1 79549112 0 0 0.0 0 +chr1 79736753 0 1 0.0137 0 +chr1 79874105 0 0 0.0 0 +chr1 79883543 0 0 0.0 0 +chr1 80051747 0 0 0.0 0 +chr1 80086673 0 0 0.0 0 +chr1 80194881 0 0 0.0 0 +chr1 80307802 0 0 0.0 0 +chr1 80440995 0 0 0.0 0 +chr1 80470553 0 0 0.0 0 +chr1 80645161 0 0 0.0 0 +chr1 80824813 0 0 0.0 0 +chr1 80850986 0 0 0.0 0 +chr1 80909522 0 0 0.0 0 +chr1 80912810 0 0 0.0 0 +chr1 80973641 0 0 0.0 0 +chr1 81315905 0 0 0.0 0 +chr1 81344277 0 0 0.0 0 +chr1 81392172 0 0 0.0 0 +chr1 81502338 0 0 0.0 0 +chr1 81517896 0 0 0.0 0 +chr1 81618718 0 0 0.0 0 +chr1 81637425 0 0 0.0 0 +chr1 81715227 0 0 0.0 0 +chr1 81744557 0 0 0.0 0 +chr1 82046465 0 0 0.0 0 +chr1 82349050 0 0 0.0 0 +chr1 82446433 0 0 0.0 0 +chr1 82621495 0 0 0.0 0 +chr1 83054626 0 0 0.0 0 +chr1 83068377 0 0 0.0 0 +chr1 83078371 0 0 0.0 0 +chr1 83153401 0 0 0.0 0 +chr1 83168301 0 0 0.0 0 +chr1 83221276 0 0 0.0 0 +chr1 83307001 0 0 0.0 0 +chr1 83413061 0 0 0.0 0 +chr1 83591526 0 0 0.0 0 +chr1 83719703 0 0 0.0 0 +chr1 83806099 0 0 0.0 0 +chr1 84143016 0 0 0.0 0 +chr1 84153900 0 0 0.0 0 +chr1 84224417 0 0 0.0 0 +chr1 84325350 0 0 0.0 0 +chr1 84433946 0 0 0.0 0 +chr1 84475900 0 0 0.0 0 +chr1 84481063 0 0 0.0 0 +chr1 84708753 0 0 0.0 0 +chr1 84766738 0 0 0.0 0 +chr1 84881212 0 0 0.0 0 +chr1 84883310 0 0 0.0 0 +chr1 84915941 0 0 0.0 0 +chr1 85124974 0 0 0.0 0 +chr1 85303789 0 0 0.0 0 +chr1 85308221 0 0 0.0 0 +chr1 85456358 0 0 0.0 0 +chr1 85479556 0 0 0.0 0 +chr1 85551129 0 0 0.0 0 +chr1 85557673 0 0 0.0 0 +chr1 85619610 0 0 0.0 0 +chr1 85659722 0 0 0.0 0 +chr1 85823854 0 0 0.0 0 +chr1 85914831 0 0 0.0 0 +chr1 85938969 0 0 0.0 0 +chr1 86139241 0 0 0.0 0 +chr1 86325620 0 1 0.0294 0 +chr1 86484642 0 0 0.0 0 +chr1 86527303 0 0 0.0 0 +chr1 86608961 0 0 0.0 0 +chr1 86639306 0 0 0.0 0 +chr1 86840541 0 0 0.0 0 +chr1 86976378 0 0 0.0 0 +chr1 87151193 0 0 0.0 0 +chr1 87160635 0 0 0.0 0 +chr1 87573172 0 0 0.0 0 +chr1 87781310 0 0 0.0 0 +chr1 88022079 0 0 0.0 0 +chr1 88035706 0 0 0.0 0 +chr1 88151367 0 0 0.0 0 +chr1 88155980 0 0 0.0 0 +chr1 88162657 0 0 0.0 0 +chr1 88178200 0 0 0.0 0 +chr1 88195669 0 0 0.0 0 +chr1 88314417 0 0 0.0 0 +chr1 88470569 0 0 0.0 0 +chr1 88483122 0 0 0.0 0 +chr1 88836591 0 0 0.0 0 +chr1 88926089 0 0 0.0 0 +chr1 89033874 0 0 0.0 0 +chr1 89042616 0 0 0.0 0 +chr1 89043809 0 0 0.0 0 +chr1 89044382 0 0 0.0 0 +chr1 89072167 0 0 0.0 0 +chr1 89230079 0 0 0.0 0 +chr1 89266552 0 0 0.0 0 +chr1 89375068 0 1 0.0156 0 +chr1 89387184 0 0 0.0 0 +chr1 89405323 0 0 0.0 0 +chr1 89447269 0 0 0.0 0 +chr1 89507268 0 0 0.0 0 +chr1 89557617 0 0 0.0 0 +chr1 89558474 0 0 0.0 0 +chr1 89561982 0 0 0.0 0 +chr1 89727204 0 0 0.0 0 +chr1 89788954 0 0 0.0 0 +chr1 89804882 0 0 0.0 0 +chr1 89833333 0 0 0.0 0 +chr1 89859603 0 0 0.0 0 +chr1 89895208 0 0 0.0 0 +chr1 89974377 0 0 0.0 0 +chr1 90156297 0 0 0.0 0 +chr1 90236131 0 0 0.0 0 +chr1 90247830 1 6 0.1071 1 +chr1 90357978 0 0 0.0 0 +chr1 90481248 0 0 0.0 0 +chr1 90718589 0 0 0.0 0 +chr1 90942732 0 0 0.0 0 +chr1 91011930 0 0 0.0 0 +chr1 91050479 0 0 0.0 0 +chr1 91120505 0 0 0.0 0 +chr1 91152467 0 0 0.0 0 +chr1 91197966 0 0 0.0 0 +chr1 91364498 0 0 0.0 0 +chr1 91620316 0 0 0.0 0 +chr1 91621752 0 0 0.0 0 +chr1 91632401 0 0 0.0 0 +chr1 91661356 0 1 0.0141 0 +chr1 91869296 0 0 0.0 0 +chr1 92096786 0 0 0.0 0 +chr1 92218421 0 0 0.0 0 +chr1 92388794 0 0 0.0 0 +chr1 92411003 0 0 0.0 0 +chr1 92670708 0 0 0.0 0 +chr1 92691580 0 0 0.0 0 +chr1 92708949 0 0 0.0 0 +chr1 92768405 0 0 0.0 0 +chr1 92950087 0 0 0.0 0 +chr1 92995080 0 0 0.0 0 +chr1 93016737 0 0 0.0 0 +chr1 93275797 0 0 0.0 0 +chr1 93474555 0 0 0.0 0 +chr1 93526320 0 0 0.0 0 +chr1 93566533 0 0 0.0 0 +chr1 93588147 0 0 0.0 0 +chr1 93628580 0 0 0.0 0 +chr1 93757764 0 0 0.0 0 +chr1 93849330 0 0 0.0 0 +chr1 94026761 0 0 0.0 0 +chr1 94042818 0 0 0.0 0 +chr1 94103821 0 0 0.0 0 +chr1 94213273 0 0 0.0 0 +chr1 94399873 0 0 0.0 0 +chr1 94439558 0 0 0.0 0 +chr1 94575194 0 0 0.0 0 +chr1 94606108 0 0 0.0 0 +chr1 94667501 0 0 0.0 0 +chr1 94671178 0 0 0.0 0 +chr1 94735043 0 0 0.0 0 +chr1 94742551 0 0 0.0 0 +chr1 94774584 0 0 0.0 0 +chr1 94916631 0 0 0.0 0 +chr1 95008845 0 0 0.0 0 +chr1 95231064 0 0 0.0 0 +chr1 95232182 0 0 0.0 0 +chr1 95252202 0 0 0.0 0 +chr1 95300389 0 0 0.0 0 +chr1 95348744 0 0 0.0 0 +chr1 95389015 0 0 0.0 0 +chr1 95483207 0 0 0.0 0 +chr1 95491868 0 0 0.0 0 +chr1 95525169 0 0 0.0 0 +chr1 95548508 0 0 0.0 0 +chr1 95763802 0 0 0.0 0 +chr1 95840154 0 0 0.0 0 +chr1 95915592 0 0 0.0 0 +chr1 95988220 0 0 0.0 0 +chr1 96148140 0 0 0.0 0 +chr1 96204094 0 0 0.0 0 +chr1 96211667 0 0 0.0 0 +chr1 96336117 0 0 0.0 0 +chr1 96545833 0 0 0.0 0 +chr1 96612292 0 0 0.0 0 +chr1 96674774 0 0 0.0 0 +chr1 96676516 0 0 0.0 0 +chr1 96966714 0 0 0.0 0 +chr1 97421267 0 0 0.0 0 +chr1 97496931 0 0 0.0 0 +chr1 97896479 0 0 0.0 0 +chr1 97933462 0 0 0.0 0 +chr1 98125940 0 0 0.0 0 +chr1 98215707 0 0 0.0 0 +chr1 98546454 0 0 0.0 0 +chr1 98619304 0 0 0.0 0 +chr1 98643538 0 0 0.0 0 +chr1 99003966 0 0 0.0 0 +chr1 99105393 0 0 0.0 0 +chr1 99164799 0 0 0.0 0 +chr1 99650336 0 1 0.0476 0 +chr1 99653906 0 0 0.0 0 +chr1 99700636 0 0 0.0 0 +chr1 99858581 0 0 0.0 0 +chr1 100031909 0 0 0.0 0 +chr1 100200758 0 0 0.0 0 +chr1 100249722 0 0 0.0 0 +chr1 100305075 0 0 0.0 0 +chr1 100313605 0 0 0.0 0 +chr1 100408800 0 0 0.0 0 +chr1 100641564 0 0 0.0 0 +chr1 100879779 0 0 0.0 0 +chr1 100985349 0 0 0.0 0 +chr1 101147504 0 0 0.0 0 +chr1 101188548 0 0 0.0 0 +chr1 101419570 0 0 0.0 0 +chr1 101507007 0 0 0.0 0 +chr1 101534867 0 0 0.0 0 +chr1 101589212 0 0 0.0 0 +chr1 102488798 0 0 0.0 0 +chr1 102524420 0 0 0.0 0 +chr1 102551693 0 0 0.0 0 +chr1 102914483 0 0 0.0 0 +chr1 103050884 0 0 0.0 0 +chr1 103113901 0 0 0.0 0 +chr1 103218069 0 0 0.0 0 +chr1 103276035 0 0 0.0 0 +chr1 103525956 0 0 0.0 0 +chr1 104135901 0 0 0.0 0 +chr1 104260132 0 0 0.0 0 +chr1 104347293 0 0 0.0 0 +chr1 104587227 0 0 0.0 0 +chr1 104658754 0 0 0.0 0 +chr1 104968409 0 0 0.0 0 +chr1 105258781 0 0 0.0 0 +chr1 105570148 0 0 0.0 0 +chr1 105622986 0 0 0.0 0 +chr1 105631243 0 1 0.0172 0 +chr1 105801856 0 0 0.0 0 +chr1 105935019 0 0 0.0 0 +chr1 106195433 0 0 0.0 0 +chr1 106527469 0 0 0.0 0 +chr1 106875038 0 0 0.0 0 +chr1 107105041 0 0 0.0 0 +chr1 107600732 0 0 0.0 0 +chr1 108228323 0 0 0.0 0 +chr1 108308464 0 0 0.0 0 +chr1 108331916 0 0 0.0 0 +chr1 108385916 0 0 0.0 0 +chr1 108466022 0 0 0.0 0 +chr1 108471039 0 0 0.0 0 +chr1 108720566 0 0 0.0 0 +chr1 108786635 0 0 0.0 0 +chr1 108817914 0 0 0.0 0 +chr1 109114525 0 0 0.0 0 +chr1 109168741 0 0 0.0 0 +chr1 109323027 0 0 0.0 0 +chr1 109364005 0 0 0.0 0 +chr1 109389887 0 0 0.0 0 +chr1 109430808 0 0 0.0 0 +chr1 109454400 0 0 0.0 0 +chr1 109501653 0 0 0.0 0 +chr1 109562749 0 0 0.0 0 +chr1 109620402 0 0 0.0 0 +chr1 109769041 0 0 0.0 0 +chr1 109819800 0 1 0.0141 0 +chr1 109918775 0 0 0.0 0 +chr1 110212076 0 0 0.0 0 +chr1 110357941 0 0 0.0 0 +chr1 110410586 0 0 0.0 0 +chr1 110444148 0 0 0.0 0 +chr1 110484874 0 0 0.0 0 +chr1 110533310 0 0 0.0 0 +chr1 110588089 0 0 0.0 0 +chr1 110681772 0 0 0.0 0 +chr1 111123003 0 0 0.0 0 +chr1 111135780 0 0 0.0 0 +chr1 111202979 0 0 0.0 0 +chr1 111207090 0 0 0.0 0 +chr1 111238333 0 0 0.0 0 +chr1 111292132 0 0 0.0 0 +chr1 111457238 0 0 0.0 0 +chr1 111482819 0 0 0.0 0 +chr1 111599742 0 0 0.0 0 +chr1 111737632 0 0 0.0 0 +chr1 111788690 0 0 0.0 0 +chr1 111893823 0 0 0.0 0 +chr1 111894497 0 0 0.0 0 +chr1 112030729 0 0 0.0 0 +chr1 112037862 0 0 0.0 0 +chr1 112135855 0 0 0.0 0 +chr1 112138146 0 0 0.0 0 +chr1 112143005 0 0 0.0 0 +chr1 112332620 0 0 0.0 0 +chr1 112376282 0 0 0.0 0 +chr1 112389183 0 0 0.0 0 +chr1 112500032 0 0 0.0 0 +chr1 112513857 0 0 0.0 0 +chr1 112813066 0 0 0.0 0 +chr1 112856088 0 0 0.0 0 +chr1 112935383 0 1 0.0147 0 +chr1 113194801 0 0 0.0 0 +chr1 113206514 0 0 0.0 0 +chr1 113218138 0 1 0.0233 0 +chr1 113279576 0 0 0.0 0 +chr1 113340166 0 0 0.0 0 +chr1 113715060 0 0 0.0 0 +chr1 113744278 0 0 0.0 0 +chr1 113835878 0 0 0.0 0 +chr1 114011081 0 0 0.0 0 +chr1 114012453 0 0 0.0 0 +chr1 114033060 0 0 0.0 0 +chr1 114043906 0 0 0.0 0 +chr1 114282292 0 0 0.0 0 +chr1 114846589 0 0 0.0 0 +chr1 114983767 0 0 0.0 0 +chr1 115019312 0 0 0.0 0 +chr1 115274062 0 0 0.0 0 +chr1 115328775 0 0 0.0 0 +chr1 115329878 0 0 0.0 0 +chr1 115388615 0 0 0.0 0 +chr1 115389132 0 0 0.0 0 +chr1 115466745 0 0 0.0 0 +chr1 115549099 0 0 0.0 0 +chr1 115576151 0 0 0.0 0 +chr1 115623419 0 0 0.0 0 +chr1 115651406 0 0 0.0 0 +chr1 115720665 0 0 0.0 0 +chr1 115738446 0 0 0.0 0 +chr1 115917727 0 0 0.0 0 +chr1 116289961 0 0 0.0 0 +chr1 116294188 0 0 0.0 0 +chr1 116343664 0 0 0.0 0 +chr1 116502405 0 0 0.0 0 +chr1 116645736 0 0 0.0 0 +chr1 116706795 0 0 0.0 0 +chr1 116721245 0 0 0.0 0 +chr1 116756829 0 0 0.0 0 +chr1 116942350 0 0 0.0 0 +chr1 116963222 0 0 0.0 0 +chr1 116992612 0 0 0.0 0 +chr1 117118032 0 0 0.0 0 +chr1 117285673 1 3 0.0353 1 +chr1 117329724 0 0 0.0 0 +chr1 117533263 0 0 0.0 0 +chr1 117585113 0 0 0.0 0 +chr1 117633728 0 0 0.0 0 +chr1 117637431 0 0 0.0 0 +chr1 117653016 0 0 0.0 0 +chr1 117685621 0 0 0.0 0 +chr1 117708445 0 0 0.0 0 +chr1 117744406 0 0 0.0 0 +chr1 118128705 0 0 0.0 0 +chr1 118148685 0 0 0.0 0 +chr1 118210640 0 0 0.0 0 +chr1 118218798 0 0 0.0 0 +chr1 118233968 0 0 0.0 0 +chr1 118268292 1 3 0.0455 1 +chr1 118527258 0 0 0.0 0 +chr1 118667715 0 0 0.0 0 +chr1 118783574 0 0 0.0 0 +chr1 118876428 0 0 0.0 0 +chr1 118991008 0 0 0.0 0 +chr1 118992110 0 0 0.0 0 +chr1 119181656 0 0 0.0 0 +chr1 119219144 0 0 0.0 0 +chr1 119545137 0 0 0.0 0 +chr1 119852776 0 0 0.0 0 +chr1 119853575 0 0 0.0 0 +chr1 119881025 0 0 0.0 0 +chr1 120040795 0 0 0.0 0 +chr1 120201037 0 0 0.0 0 +chr1 120415923 0 0 0.0 0 +chr1 120433819 0 0 0.0 0 +chr1 120697337 0 0 0.0 0 +chr1 120752835 0 0 0.0 0 +chr1 120880142 0 0 0.0 0 +chr1 120966450 0 0 0.0 0 +chr1 121234485 0 0 0.0 0 +chr1 121280640 0 0 0.0 0 +chr1 121360471 0 0 0.0 0 +chr1 121374119 0 0 0.0 0 +chr1 121478306 0 0 0.0 0 +chr1 121559827 0 0 0.0 0 +chr1 124983005 0 0 0.0 0 +chr1 124997567 0 0 0.0 0 +chr1 124997909 0 0 0.0 0 +chr1 125042834 0 0 0.0 0 +chr1 125047753 0 0 0.0 0 +chr1 143330418 0 0 0.0 0 +chr1 143440069 0 0 0.0 0 +chr1 143575422 0 0 0.0 0 +chr1 143582584 0 0 0.0 0 +chr1 143619556 0 0 0.0 0 +chr1 143644732 0 0 0.0 0 +chr1 143747706 0 0 0.0 0 +chr1 144022107 0 0 0.0 0 +chr1 144054586 0 0 0.0 0 +chr1 144125445 0 0 0.0 0 +chr1 144155991 0 0 0.0 0 +chr1 144265681 0 0 0.0 0 +chr1 144442839 0 0 0.0 0 +chr1 144460743 0 0 0.0 0 +chr1 144700696 0 0 0.0 0 +chr1 144810393 0 0 0.0 0 +chr1 144840022 0 0 0.0 0 +chr1 144905927 0 0 0.0 0 +chr1 144919587 0 0 0.0 0 +chr1 144999345 0 0 0.0 0 +chr1 145045856 0 0 0.0 0 +chr1 145408006 0 0 0.0 0 +chr1 145424676 0 0 0.0 0 +chr1 145520020 0 0 0.0 0 +chr1 145622058 0 0 0.0 0 +chr1 145656015 0 0 0.0 0 +chr1 145749469 0 0 0.0 0 +chr1 145977908 0 0 0.0 0 +chr1 146200177 0 0 0.0 0 +chr1 146589645 0 0 0.0 0 +chr1 146633718 0 0 0.0 0 +chr1 146778426 0 0 0.0 0 +chr1 146829109 0 0 0.0 0 +chr1 146957425 0 0 0.0 0 +chr1 147092935 0 0 0.0 0 +chr1 147106802 0 0 0.0 0 +chr1 147156760 0 0 0.0 0 +chr1 147319528 0 0 0.0 0 +chr1 147340781 0 0 0.0 0 +chr1 147342076 0 0 0.0 0 +chr1 147481623 0 0 0.0 0 +chr1 147517514 0 0 0.0 0 +chr1 147539985 0 0 0.0 0 +chr1 147855140 0 0 0.0 0 +chr1 147889353 0 0 0.0 0 +chr1 147942443 0 0 0.0 0 +chr1 147978706 0 0 0.0 0 +chr1 148129731 0 0 0.0 0 +chr1 148417698 0 0 0.0 0 +chr1 148650897 0 0 0.0 0 +chr1 148812477 0 0 0.0 0 +chr1 149084851 0 0 0.0 0 +chr1 149102629 0 0 0.0 0 +chr1 149317761 0 0 0.0 0 +chr1 149420131 0 0 0.0 0 +chr1 149658187 0 0 0.0 0 +chr1 149800575 0 0 0.0 0 +chr1 149841120 0 0 0.0 0 +chr1 149841426 0 0 0.0 0 +chr1 149852387 0 0 0.0 0 +chr1 149852692 0 0 0.0 0 +chr1 149934898 0 0 0.0 0 +chr1 150157477 0 1 0.0123 0 +chr1 150208182 0 0 0.0 0 +chr1 150267933 0 0 0.0 0 +chr1 150527202 0 0 0.0 0 +chr1 150667314 0 0 0.0 0 +chr1 150845502 0 0 0.0 0 +chr1 150877873 0 0 0.0 0 +chr1 150925965 0 0 0.0 0 +chr1 151058424 0 0 0.0 0 +chr1 151138543 0 0 0.0 0 +chr1 151161636 0 0 0.0 0 +chr1 151169746 0 0 0.0 0 +chr1 151465321 0 0 0.0 0 +chr1 151696390 0 0 0.0 0 +chr1 151702165 0 0 0.0 0 +chr1 151845702 0 0 0.0 0 +chr1 152001502 0 0 0.0 0 +chr1 152012915 0 0 0.0 0 +chr1 152404739 0 0 0.0 0 +chr1 152478380 0 0 0.0 0 +chr1 152495865 0 0 0.0 0 +chr1 152505751 0 0 0.0 0 +chr1 152531365 0 0 0.0 0 +chr1 152544901 0 0 0.0 0 +chr1 152646967 0 0 0.0 0 +chr1 152796654 0 0 0.0 0 +chr1 152806719 0 0 0.0 0 +chr1 153107042 0 0 0.0 0 +chr1 153309529 0 0 0.0 0 +chr1 153439450 0 0 0.0 0 +chr1 153505926 0 0 0.0 0 +chr1 153667941 0 0 0.0 0 +chr1 153779523 0 0 0.0 0 +chr1 153853316 0 0 0.0 0 +chr1 153968478 0 0 0.0 0 +chr1 154102321 0 0 0.0 0 +chr1 154326672 0 0 0.0 0 +chr1 154421882 0 0 0.0 0 +chr1 154447970 0 0 0.0 0 +chr1 154468288 0 0 0.0 0 +chr1 154476236 0 0 0.0 0 +chr1 154489111 0 0 0.0 0 +chr1 154529960 0 0 0.0 0 +chr1 154661421 0 0 0.0 0 +chr1 154663823 0 0 0.0 0 +chr1 154680645 0 1 0.0217 0 +chr1 154720666 0 0 0.0 0 +chr1 154966397 1 3 0.0357 1 +chr1 155011723 0 0 0.0 0 +chr1 155014178 0 0 0.0 0 +chr1 155065254 0 0 0.0 0 +chr1 155080706 0 0 0.0 0 +chr1 155115075 0 0 0.0 0 +chr1 155148527 0 1 0.0127 0 +chr1 155258112 0 0 0.0 0 +chr1 155324043 0 0 0.0 0 +chr1 155614810 0 0 0.0 0 +chr1 155621290 0 0 0.0 0 +chr1 155750673 0 0 0.0 0 +chr1 156100524 0 0 0.0 0 +chr1 156160954 0 0 0.0 0 +chr1 156372758 0 0 0.0 0 +chr1 156420122 0 0 0.0 0 +chr1 156476078 0 1 0.0109 0 +chr1 156485166 0 0 0.0 0 +chr1 156531951 0 0 0.0 0 +chr1 156596763 0 0 0.0 0 +chr1 156609017 0 0 0.0 0 +chr1 156621793 0 0 0.0 0 +chr1 156732574 0 0 0.0 0 +chr1 156805016 0 0 0.0 0 +chr1 156840770 0 0 0.0 0 +chr1 156938535 0 0 0.0 0 +chr1 156961618 0 0 0.0 0 +chr1 157025035 0 0 0.0 0 +chr1 157176069 0 0 0.0 0 +chr1 157226082 0 0 0.0 0 +chr1 157294518 0 0 0.0 0 +chr1 157309447 0 0 0.0 0 +chr1 157376655 0 0 0.0 0 +chr1 157460459 0 0 0.0 0 +chr1 157485950 0 0 0.0 0 +chr1 157496450 0 0 0.0 0 +chr1 157524398 0 0 0.0 0 +chr1 157560546 0 0 0.0 0 +chr1 157573503 0 0 0.0 0 +chr1 157695449 0 0 0.0 0 +chr1 157802035 0 0 0.0 0 +chr1 157918070 0 0 0.0 0 +chr1 157990629 0 0 0.0 0 +chr1 158009723 0 0 0.0 0 +chr1 158022852 0 1 0.0213 0 +chr1 158049547 0 0 0.0 0 +chr1 158283908 0 0 0.0 0 +chr1 158336951 0 0 0.0 0 +chr1 158596898 0 0 0.0 0 +chr1 158657097 0 0 0.0 0 +chr1 158791869 0 0 0.0 0 +chr1 159057021 0 0 0.0 0 +chr1 159090936 0 0 0.0 0 +chr1 159095949 0 0 0.0 0 +chr1 159301739 0 0 0.0 0 +chr1 159423031 0 0 0.0 0 +chr1 159473050 0 0 0.0 0 +chr1 159477798 0 0 0.0 0 +chr1 159539082 0 0 0.0 0 +chr1 159562507 0 0 0.0 0 +chr1 159665661 0 0 0.0 0 +chr1 159683521 0 0 0.0 0 +chr1 159819777 0 0 0.0 0 +chr1 159863487 0 0 0.0 0 +chr1 159866773 0 0 0.0 0 +chr1 159895218 0 0 0.0 0 +chr1 160033726 0 0 0.0 0 +chr1 160072010 0 0 0.0 0 +chr1 160077391 0 0 0.0 0 +chr1 160146976 0 0 0.0 0 +chr1 160173882 0 0 0.0 0 +chr1 160351430 0 0 0.0 0 +chr1 160435781 0 0 0.0 0 +chr1 160452713 0 0 0.0 0 +chr1 160538974 0 0 0.0 0 +chr1 160664701 0 0 0.0 0 +chr1 160730410 0 0 0.0 0 +chr1 160862596 0 0 0.0 0 +chr1 161280696 0 0 0.0 0 +chr1 161293853 0 0 0.0 0 +chr1 161312775 0 0 0.0 0 +chr1 161510079 0 0 0.0 0 +chr1 161591403 0 0 0.0 0 +chr1 161673234 0 0 0.0 0 +chr1 161676059 0 0 0.0 0 +chr1 161767705 0 0 0.0 0 +chr1 161800767 0 0 0.0 0 +chr1 161924341 0 0 0.0 0 +chr1 161989235 0 0 0.0 0 +chr1 162075582 0 0 0.0 0 +chr1 162105637 0 0 0.0 0 +chr1 162143102 0 0 0.0 0 +chr1 162216812 0 0 0.0 0 +chr1 162224943 0 0 0.0 0 +chr1 162234116 0 0 0.0 0 +chr1 162278802 0 0 0.0 0 +chr1 162298674 0 0 0.0 0 +chr1 162442833 0 0 0.0 0 +chr1 162449037 0 0 0.0 0 +chr1 162566557 0 0 0.0 0 +chr1 162592834 0 0 0.0 0 +chr1 162673344 0 0 0.0 0 +chr1 162754399 0 0 0.0 0 +chr1 162830157 0 0 0.0 0 +chr1 162857493 0 1 0.0244 0 +chr1 162937190 0 0 0.0 0 +chr1 163050267 0 0 0.0 0 +chr1 163052746 0 0 0.0 0 +chr1 163071782 0 0 0.0 0 +chr1 163112820 0 0 0.0 0 +chr1 163132696 0 0 0.0 0 +chr1 163190905 0 0 0.0 0 +chr1 163199851 0 0 0.0 0 +chr1 163396594 0 0 0.0 0 +chr1 163541742 0 0 0.0 0 +chr1 163820016 0 0 0.0 0 +chr1 163881307 0 0 0.0 0 +chr1 163888530 0 0 0.0 0 +chr1 163977925 0 0 0.0 0 +chr1 164126239 0 0 0.0 0 +chr1 164171446 0 0 0.0 0 +chr1 164263048 0 0 0.0 0 +chr1 164342307 0 0 0.0 0 +chr1 164401912 0 0 0.0 0 +chr1 164599155 0 0 0.0 0 +chr1 164667673 1 36 0.5143 1 +chr1 164848046 0 0 0.0 0 +chr1 164864392 0 0 0.0 0 +chr1 164889751 0 0 0.0 0 +chr1 164932838 0 0 0.0 0 +chr1 165325556 0 0 0.0 0 +chr1 165368271 0 0 0.0 0 +chr1 165512726 0 0 0.0 0 +chr1 165783289 0 0 0.0 0 +chr1 165797606 0 0 0.0 0 +chr1 165934870 0 0 0.0 0 +chr1 165948504 0 0 0.0 0 +chr1 165960192 0 0 0.0 0 +chr1 166057856 0 0 0.0 0 +chr1 166089346 0 0 0.0 0 +chr1 166111202 0 0 0.0 0 +chr1 166140701 0 0 0.0 0 +chr1 166148808 0 0 0.0 0 +chr1 166286590 0 0 0.0 0 +chr1 166409772 0 0 0.0 0 +chr1 166429320 0 0 0.0 0 +chr1 166435756 0 0 0.0 0 +chr1 166551755 0 0 0.0 0 +chr1 166819698 0 0 0.0 0 +chr1 166844613 0 0 0.0 0 +chr1 166910522 0 0 0.0 0 +chr1 166948966 0 0 0.0 0 +chr1 167020486 0 0 0.0 0 +chr1 167056009 0 0 0.0 0 +chr1 167078670 0 0 0.0 0 +chr1 167244370 0 0 0.0 0 +chr1 167366032 0 0 0.0 0 +chr1 167489221 0 0 0.0 0 +chr1 167589262 0 0 0.0 0 +chr1 167823650 0 0 0.0 0 +chr1 167911600 0 1 0.0294 0 +chr1 168083371 0 0 0.0 0 +chr1 168327210 0 0 0.0 0 +chr1 168394256 0 0 0.0 0 +chr1 168455268 0 0 0.0 0 +chr1 168462614 0 0 0.0 0 +chr1 168599872 0 0 0.0 0 +chr1 168854884 0 1 0.025 0 +chr1 168978733 0 0 0.0 0 +chr1 169017294 0 0 0.0 0 +chr1 169061159 0 0 0.0 0 +chr1 169181932 0 0 0.0 0 +chr1 169199140 0 0 0.0 0 +chr1 169356407 0 0 0.0 0 +chr1 169487656 0 0 0.0 0 +chr1 169904573 0 0 0.0 0 +chr1 170027363 0 0 0.0 0 +chr1 170120514 0 0 0.0 0 +chr1 170131576 0 0 0.0 0 +chr1 170249581 0 0 0.0 0 +chr1 170369144 0 0 0.0 0 +chr1 170426751 0 0 0.0 0 +chr1 170464740 0 0 0.0 0 +chr1 170614400 0 0 0.0 0 +chr1 170732293 0 0 0.0 0 +chr1 170736597 0 0 0.0 0 +chr1 170913554 0 0 0.0 0 +chr1 171055833 0 0 0.0 0 +chr1 171222579 0 0 0.0 0 +chr1 171262328 0 0 0.0 0 +chr1 171304659 0 0 0.0 0 +chr1 171359827 0 0 0.0 0 +chr1 171420554 0 0 0.0 0 +chr1 171430973 0 0 0.0 0 +chr1 171804496 0 0 0.0 0 +chr1 171919876 0 0 0.0 0 +chr1 171943377 0 0 0.0 0 +chr1 171989686 0 0 0.0 0 +chr1 171995461 0 0 0.0 0 +chr1 172025094 0 0 0.0 0 +chr1 172187006 0 0 0.0 0 +chr1 172425332 0 0 0.0 0 +chr1 172443790 0 0 0.0 0 +chr1 172456073 0 0 0.0 0 +chr1 172466807 0 0 0.0 0 +chr1 172681310 0 0 0.0 0 +chr1 172733252 0 0 0.0 0 +chr1 172821327 0 0 0.0 0 +chr1 172893097 0 0 0.0 0 +chr1 173100261 0 0 0.0 0 +chr1 173148669 0 0 0.0 0 +chr1 173185096 0 0 0.0 0 +chr1 173218334 0 0 0.0 0 +chr1 173439982 0 0 0.0 0 +chr1 173449703 0 0 0.0 0 +chr1 173460578 0 0 0.0 0 +chr1 173640845 0 0 0.0 0 +chr1 173675369 0 0 0.0 0 +chr1 173718496 0 0 0.0 0 +chr1 173963399 0 0 0.0 0 +chr1 174000520 0 0 0.0 0 +chr1 174124678 0 0 0.0 0 +chr1 174172914 0 0 0.0 0 +chr1 174194692 0 0 0.0 0 +chr1 174334256 0 0 0.0 0 +chr1 174361700 0 0 0.0 0 +chr1 174529913 0 0 0.0 0 +chr1 174538268 0 0 0.0 0 +chr1 174711772 0 0 0.0 0 +chr1 174732851 0 0 0.0 0 +chr1 174733581 0 2 0.0299 0 +chr1 174777424 0 0 0.0 0 +chr1 174793454 0 0 0.0 0 +chr1 174977167 0 0 0.0 0 +chr1 175187997 0 0 0.0 0 +chr1 175251111 0 1 0.0118 0 +chr1 175267808 0 0 0.0 0 +chr1 175466786 0 0 0.0 0 +chr1 175598872 0 0 0.0 0 +chr1 175638546 0 0 0.0 0 +chr1 175691953 0 0 0.0 0 +chr1 175794554 0 0 0.0 0 +chr1 175826478 0 0 0.0 0 +chr1 175831051 0 0 0.0 0 +chr1 175843227 0 0 0.0 0 +chr1 175847673 1 44 0.55 1 +chr1 175885807 0 0 0.0 0 +chr1 176207073 0 0 0.0 0 +chr1 176229418 0 0 0.0 0 +chr1 176242646 0 0 0.0 0 +chr1 176262877 0 0 0.0 0 +chr1 176340509 0 0 0.0 0 +chr1 176476956 0 0 0.0 0 +chr1 176503786 0 0 0.0 0 +chr1 176558824 0 0 0.0 0 +chr1 176707096 0 0 0.0 0 +chr1 176714864 0 0 0.0 0 +chr1 176872738 0 0 0.0 0 +chr1 176878265 0 0 0.0 0 +chr1 176885476 0 0 0.0 0 +chr1 176953823 0 0 0.0 0 +chr1 177049842 0 0 0.0 0 +chr1 177064488 0 0 0.0 0 +chr1 177085885 0 0 0.0 0 +chr1 177095489 0 0 0.0 0 +chr1 177142140 0 0 0.0 0 +chr1 177181648 0 0 0.0 0 +chr1 177221799 0 0 0.0 0 +chr1 177251481 0 0 0.0 0 +chr1 177269269 0 0 0.0 0 +chr1 177359330 0 1 0.0149 0 +chr1 177373820 0 0 0.0 0 +chr1 177377701 0 0 0.0 0 +chr1 177447246 0 0 0.0 0 +chr1 177589366 0 0 0.0 0 +chr1 177632489 0 0 0.0 0 +chr1 177722177 0 0 0.0 0 +chr1 177743981 0 0 0.0 0 +chr1 177771183 0 0 0.0 0 +chr1 177883798 0 0 0.0 0 +chr1 177905960 0 0 0.0 0 +chr1 177906344 0 0 0.0 0 +chr1 178080575 0 0 0.0 0 +chr1 178211794 0 0 0.0 0 +chr1 178362404 0 0 0.0 0 +chr1 178386993 0 0 0.0 0 +chr1 178559910 0 1 0.0167 0 +chr1 178717166 0 0 0.0 0 +chr1 178782212 0 0 0.0 0 +chr1 178806840 0 0 0.0 0 +chr1 178913003 0 0 0.0 0 +chr1 178969415 0 0 0.0 0 +chr1 179015570 0 0 0.0 0 +chr1 179087981 0 0 0.0 0 +chr1 179109416 0 0 0.0 0 +chr1 179201528 0 0 0.0 0 +chr1 179416340 0 0 0.0 0 +chr1 179526907 0 0 0.0 0 +chr1 179637316 0 0 0.0 0 +chr1 179821447 0 0 0.0 0 +chr1 179854192 0 0 0.0 0 +chr1 179932061 0 0 0.0 0 +chr1 180117621 0 0 0.0 0 +chr1 180128594 0 0 0.0 0 +chr1 180185687 0 0 0.0 0 +chr1 180334396 0 0 0.0 0 +chr1 180434858 0 0 0.0 0 +chr1 180597122 0 0 0.0 0 +chr1 180778640 0 0 0.0 0 +chr1 180844692 0 0 0.0 0 +chr1 180941428 0 0 0.0 0 +chr1 181121630 0 0 0.0 0 +chr1 181169446 0 0 0.0 0 +chr1 181171739 0 0 0.0 0 +chr1 181176544 0 0 0.0 0 +chr1 181298489 0 0 0.0 0 +chr1 181378749 0 1 0.0145 0 +chr1 181408940 0 0 0.0 0 +chr1 181483081 0 0 0.0 0 +chr1 181506422 0 0 0.0 0 +chr1 181582976 0 0 0.0 0 +chr1 181591847 0 0 0.0 0 +chr1 181592855 0 0 0.0 0 +chr1 181618686 0 0 0.0 0 +chr1 181773657 0 0 0.0 0 +chr1 181795122 0 0 0.0 0 +chr1 181883070 0 0 0.0 0 +chr1 181924253 0 0 0.0 0 +chr1 181987232 0 0 0.0 0 +chr1 182060568 0 0 0.0 0 +chr1 182132523 0 0 0.0 0 +chr1 182169213 0 0 0.0 0 +chr1 182189311 0 0 0.0 0 +chr1 182343973 0 0 0.0 0 +chr1 182527614 0 0 0.0 0 +chr1 182706250 0 0 0.0 0 +chr1 182735888 0 0 0.0 0 +chr1 182764420 0 1 0.0182 0 +chr1 183087265 0 0 0.0 0 +chr1 183088616 0 0 0.0 0 +chr1 183108298 0 0 0.0 0 +chr1 183181319 0 0 0.0 0 +chr1 183227567 0 0 0.0 0 +chr1 183395492 0 0 0.0 0 +chr1 183593620 0 0 0.0 0 +chr1 183692531 0 0 0.0 0 +chr1 183696120 0 0 0.0 0 +chr1 183719525 0 0 0.0 0 +chr1 183745673 0 1 0.0139 0 +chr1 183764933 0 0 0.0 0 +chr1 183862622 0 0 0.0 0 +chr1 183863253 0 0 0.0 0 +chr1 183912239 0 0 0.0 0 +chr1 184190915 0 0 0.0 0 +chr1 184207184 0 0 0.0 0 +chr1 184224665 0 0 0.0 0 +chr1 184289653 0 0 0.0 0 +chr1 184320952 0 0 0.0 0 +chr1 184448875 0 0 0.0 0 +chr1 184555246 0 0 0.0 0 +chr1 184615254 0 0 0.0 0 +chr1 184636017 0 0 0.0 0 +chr1 184698742 0 0 0.0 0 +chr1 184823536 0 0 0.0 0 +chr1 184851998 0 0 0.0 0 +chr1 184880051 0 0 0.0 0 +chr1 185014328 0 0 0.0 0 +chr1 185026498 0 0 0.0 0 +chr1 185217106 0 0 0.0 0 +chr1 185608797 0 0 0.0 0 +chr1 185775086 0 0 0.0 0 +chr1 185800107 0 0 0.0 0 +chr1 185933554 0 1 0.0208 0 +chr1 186086432 0 0 0.0 0 +chr1 186204804 0 0 0.0 0 +chr1 186219124 0 0 0.0 0 +chr1 186438544 0 0 0.0 0 +chr1 186644502 0 0 0.0 0 +chr1 186744759 0 0 0.0 0 +chr1 186746339 0 0 0.0 0 +chr1 186757254 0 0 0.0 0 +chr1 186946463 0 0 0.0 0 +chr1 187044974 0 0 0.0 0 +chr1 187397667 0 0 0.0 0 +chr1 187442121 0 0 0.0 0 +chr1 187468341 0 0 0.0 0 +chr1 187499771 0 0 0.0 0 +chr1 187808733 0 0 0.0 0 +chr1 187969396 0 0 0.0 0 +chr1 187979940 0 0 0.0 0 +chr1 188025193 0 0 0.0 0 +chr1 188041609 0 0 0.0 0 +chr1 188088907 0 0 0.0 0 +chr1 188142109 0 1 0.0303 0 +chr1 188151784 0 0 0.0 0 +chr1 188160590 0 0 0.0 0 +chr1 188186286 0 0 0.0 0 +chr1 188210389 0 0 0.0 0 +chr1 188306850 0 0 0.0 0 +chr1 188336726 0 0 0.0 0 +chr1 188338652 0 0 0.0 0 +chr1 188349702 0 0 0.0 0 +chr1 188609923 0 0 0.0 0 +chr1 188940824 0 0 0.0 0 +chr1 189123678 0 1 0.0189 0 +chr1 189272754 0 0 0.0 0 +chr1 189330550 0 0 0.0 0 +chr1 189358423 0 0 0.0 0 +chr1 189540383 0 0 0.0 0 +chr1 189628457 0 0 0.0 0 +chr1 189826177 0 0 0.0 0 +chr1 190418724 0 0 0.0 0 +chr1 190635172 0 0 0.0 0 +chr1 190926891 0 0 0.0 0 +chr1 191024351 0 0 0.0 0 +chr1 191065063 0 0 0.0 0 +chr1 191193574 0 0 0.0 0 +chr1 191235991 0 0 0.0 0 +chr1 191297712 0 0 0.0 0 +chr1 191324524 0 0 0.0 0 +chr1 191344310 0 0 0.0 0 +chr1 191616335 0 0 0.0 0 +chr1 191657467 0 0 0.0 0 +chr1 191674777 0 0 0.0 0 +chr1 191804034 0 0 0.0 0 +chr1 191912188 0 0 0.0 0 +chr1 192105960 0 0 0.0 0 +chr1 192340246 0 0 0.0 0 +chr1 192347078 0 0 0.0 0 +chr1 192448486 0 1 0.0164 0 +chr1 192762377 0 0 0.0 0 +chr1 192877164 0 0 0.0 0 +chr1 192919406 0 0 0.0 0 +chr1 192988303 0 0 0.0 0 +chr1 193001725 0 0 0.0 0 +chr1 193211111 0 0 0.0 0 +chr1 193237037 0 1 0.0312 0 +chr1 193404566 0 0 0.0 0 +chr1 193456978 0 0 0.0 0 +chr1 193472595 0 0 0.0 0 +chr1 193586867 0 0 0.0 0 +chr1 193645265 0 0 0.0 0 +chr1 193779949 0 0 0.0 0 +chr1 193956203 0 0 0.0 0 +chr1 194184254 0 0 0.0 0 +chr1 194370825 0 0 0.0 0 +chr1 194408707 0 0 0.0 0 +chr1 194432026 0 0 0.0 0 +chr1 194509735 0 0 0.0 0 +chr1 194622558 0 0 0.0 0 +chr1 194819287 0 0 0.0 0 +chr1 194878464 0 0 0.0 0 +chr1 194917762 0 0 0.0 0 +chr1 194974116 0 0 0.0 0 +chr1 195053114 0 0 0.0 0 +chr1 195094821 0 0 0.0 0 +chr1 195310638 0 0 0.0 0 +chr1 195491695 0 1 0.0238 0 +chr1 195547049 0 0 0.0 0 +chr1 195672175 0 0 0.0 0 +chr1 195837548 0 0 0.0 0 +chr1 196001413 0 0 0.0 0 +chr1 196058739 0 0 0.0 0 +chr1 196231239 0 0 0.0 0 +chr1 196621786 0 0 0.0 0 +chr1 196734127 0 0 0.0 0 +chr1 196764154 0 0 0.0 0 +chr1 196829534 0 0 0.0 0 +chr1 197136300 0 0 0.0 0 +chr1 197306959 0 0 0.0 0 +chr1 197355409 0 0 0.0 0 +chr1 197355901 0 0 0.0 0 +chr1 197743772 0 0 0.0 0 +chr1 197767917 0 0 0.0 0 +chr1 197917991 0 0 0.0 0 +chr1 198053374 0 0 0.0 0 +chr1 198158842 0 0 0.0 0 +chr1 198527004 0 0 0.0 0 +chr1 198550494 0 0 0.0 0 +chr1 198626741 0 1 0.0213 0 +chr1 198643597 0 0 0.0 0 +chr1 198696758 0 0 0.0 0 +chr1 199172087 0 0 0.0 0 +chr1 199208815 0 0 0.0 0 +chr1 199573324 0 0 0.0 0 +chr1 199677347 0 0 0.0 0 +chr1 199751448 0 0 0.0 0 +chr1 199778787 0 0 0.0 0 +chr1 199981190 0 0 0.0 0 +chr1 200081213 0 0 0.0 0 +chr1 200129696 0 0 0.0 0 +chr1 200207050 0 0 0.0 0 +chr1 200262752 0 0 0.0 0 +chr1 200339417 0 0 0.0 0 +chr1 200493116 0 0 0.0 0 +chr1 200580324 0 0 0.0 0 +chr1 200617688 0 0 0.0 0 +chr1 200637043 0 0 0.0 0 +chr1 200671026 0 0 0.0 0 +chr1 200811236 0 0 0.0 0 +chr1 200837296 0 0 0.0 0 +chr1 200932508 0 0 0.0 0 +chr1 200976943 0 0 0.0 0 +chr1 200993399 0 0 0.0 0 +chr1 201089627 0 0 0.0 0 +chr1 201124264 0 0 0.0 0 +chr1 201126364 0 0 0.0 0 +chr1 201196007 0 0 0.0 0 +chr1 201258994 0 0 0.0 0 +chr1 201268254 0 0 0.0 0 +chr1 201299039 0 0 0.0 0 +chr1 201321110 0 0 0.0 0 +chr1 201469578 0 0 0.0 0 +chr1 201476870 0 0 0.0 0 +chr1 201505595 0 0 0.0 0 +chr1 201584801 0 0 0.0 0 +chr1 201594546 0 0 0.0 0 +chr1 201602000 0 0 0.0 0 +chr1 201604859 0 0 0.0 0 +chr1 201629504 0 0 0.0 0 +chr1 201629953 0 0 0.0 0 +chr1 201633058 0 0 0.0 0 +chr1 201678879 0 0 0.0 0 +chr1 201712727 0 0 0.0 0 +chr1 201718763 0 0 0.0 0 +chr1 202038698 0 1 0.0143 0 +chr1 202249556 0 0 0.0 0 +chr1 202270792 0 0 0.0 0 +chr1 202448658 0 0 0.0 0 +chr1 202630291 0 0 0.0 0 +chr1 202680433 0 0 0.0 0 +chr1 202727464 0 1 0.0196 0 +chr1 202842353 0 0 0.0 0 +chr1 203017086 0 0 0.0 0 +chr1 203132365 0 0 0.0 0 +chr1 203137259 0 0 0.0 0 +chr1 203183874 0 0 0.0 0 +chr1 203244552 0 0 0.0 0 +chr1 203326933 0 0 0.0 0 +chr1 203461281 0 0 0.0 0 +chr1 203515996 0 0 0.0 0 +chr1 203569434 0 0 0.0 0 +chr1 203578082 0 0 0.0 0 +chr1 203596730 0 0 0.0 0 +chr1 203639052 0 0 0.0 0 +chr1 203723629 0 0 0.0 0 +chr1 203779412 0 0 0.0 0 +chr1 203994839 0 0 0.0 0 +chr1 204013371 0 0 0.0 0 +chr1 204056367 0 0 0.0 0 +chr1 204083771 0 0 0.0 0 +chr1 204118798 0 0 0.0 0 +chr1 204129810 0 0 0.0 0 +chr1 204355136 0 0 0.0 0 +chr1 204360434 0 0 0.0 0 +chr1 204403136 0 0 0.0 0 +chr1 204404123 0 0 0.0 0 +chr1 204416527 0 0 0.0 0 +chr1 204683697 0 0 0.0 0 +chr1 204701889 0 0 0.0 0 +chr1 204772716 0 0 0.0 0 +chr1 204915206 0 0 0.0 0 +chr1 204920926 0 0 0.0 0 +chr1 204948424 0 0 0.0 0 +chr1 204986052 0 0 0.0 0 +chr1 205028636 0 0 0.0 0 +chr1 205049480 0 0 0.0 0 +chr1 205091376 0 0 0.0 0 +chr1 205239039 0 0 0.0 0 +chr1 205292797 0 0 0.0 0 +chr1 205322349 0 0 0.0 0 +chr1 205373174 0 0 0.0 0 +chr1 205398678 0 0 0.0 0 +chr1 205444080 0 0 0.0 0 +chr1 205464100 0 0 0.0 0 +chr1 205569295 0 0 0.0 0 +chr1 205706032 0 0 0.0 0 +chr1 205793477 0 0 0.0 0 +chr1 205802262 0 0 0.0 0 +chr1 205879904 0 0 0.0 0 +chr1 205880375 0 0 0.0 0 +chr1 205891254 0 0 0.0 0 +chr1 206035606 0 0 0.0 0 +chr1 206119145 0 0 0.0 0 +chr1 206253044 0 0 0.0 0 +chr1 206299116 0 0 0.0 0 +chr1 206379179 0 0 0.0 0 +chr1 206392837 0 0 0.0 0 +chr1 206412642 1 29 0.4754 1 +chr1 206584057 0 0 0.0 0 +chr1 206598166 0 0 0.0 0 +chr1 206634689 0 0 0.0 0 +chr1 206735099 0 0 0.0 0 +chr1 206773171 0 0 0.0 0 +chr1 206806306 0 0 0.0 0 +chr1 206826378 0 0 0.0 0 +chr1 206912033 0 0 0.0 0 +chr1 206912907 0 0 0.0 0 +chr1 206955859 0 0 0.0 0 +chr1 206962377 0 0 0.0 0 +chr1 206968630 0 0 0.0 0 +chr1 206993495 0 0 0.0 0 +chr1 207106533 0 0 0.0 0 +chr1 207462398 0 0 0.0 0 +chr1 207665147 0 0 0.0 0 +chr1 207678632 0 0 0.0 0 +chr1 207895793 0 0 0.0 0 +chr1 207904408 0 0 0.0 0 +chr1 208033447 0 0 0.0 0 +chr1 208069075 0 0 0.0 0 +chr1 208086640 0 0 0.0 0 +chr1 208089987 0 0 0.0 0 +chr1 208165146 0 0 0.0 0 +chr1 208239537 0 0 0.0 0 +chr1 208246525 0 0 0.0 0 +chr1 208248367 0 0 0.0 0 +chr1 208322822 0 0 0.0 0 +chr1 208336064 0 0 0.0 0 +chr1 208337515 0 0 0.0 0 +chr1 208427193 0 0 0.0 0 +chr1 208514029 0 0 0.0 0 +chr1 208528257 0 0 0.0 0 +chr1 208541000 0 0 0.0 0 +chr1 208624554 0 0 0.0 0 +chr1 208697111 0 0 0.0 0 +chr1 208792513 0 0 0.0 0 +chr1 208835792 0 0 0.0 0 +chr1 208864456 0 0 0.0 0 +chr1 208886524 0 0 0.0 0 +chr1 209043006 0 0 0.0 0 +chr1 209047796 0 0 0.0 0 +chr1 209182813 0 0 0.0 0 +chr1 209206267 0 0 0.0 0 +chr1 209257228 0 0 0.0 0 +chr1 209412667 0 0 0.0 0 +chr1 209473298 0 0 0.0 0 +chr1 209523963 0 0 0.0 0 +chr1 209541271 0 0 0.0 0 +chr1 209571045 0 0 0.0 0 +chr1 209795205 0 0 0.0 0 +chr1 209858657 0 0 0.0 0 +chr1 209873485 0 0 0.0 0 +chr1 209903016 0 0 0.0 0 +chr1 210022780 0 0 0.0 0 +chr1 210058709 0 0 0.0 0 +chr1 210070020 0 0 0.0 0 +chr1 210268186 0 0 0.0 0 +chr1 210295820 0 0 0.0 0 +chr1 210302647 0 0 0.0 0 +chr1 210358908 0 0 0.0 0 +chr1 210598245 0 0 0.0 0 +chr1 210747266 0 0 0.0 0 +chr1 211041465 0 0 0.0 0 +chr1 211499450 0 0 0.0 0 +chr1 211521128 0 0 0.0 0 +chr1 211689017 0 0 0.0 0 +chr1 211703116 0 0 0.0 0 +chr1 211831514 0 0 0.0 0 +chr1 211848186 0 0 0.0 0 +chr1 212041484 0 1 0.0385 0 +chr1 212497595 0 0 0.0 0 +chr1 212615392 0 0 0.0 0 +chr1 212640153 0 0 0.0 0 +chr1 212640677 0 0 0.0 0 +chr1 212843920 0 0 0.0 0 +chr1 213394347 0 0 0.0 0 +chr1 213553570 0 0 0.0 0 +chr1 213679570 0 0 0.0 0 +chr1 213696836 0 0 0.0 0 +chr1 213712385 0 0 0.0 0 +chr1 213772770 0 0 0.0 0 +chr1 213869917 0 0 0.0 0 +chr1 213905375 0 0 0.0 0 +chr1 213906111 0 0 0.0 0 +chr1 213906518 0 0 0.0 0 +chr1 214099183 0 0 0.0 0 +chr1 214140644 0 0 0.0 0 +chr1 214198084 0 0 0.0 0 +chr1 214306513 0 0 0.0 0 +chr1 214400287 0 0 0.0 0 +chr1 214434334 0 0 0.0 0 +chr1 214658041 0 0 0.0 0 +chr1 214855465 0 0 0.0 0 +chr1 214939844 0 0 0.0 0 +chr1 215096417 0 0 0.0 0 +chr1 215118034 0 0 0.0 0 +chr1 215181599 0 0 0.0 0 +chr1 215325401 0 0 0.0 0 +chr1 215389416 0 0 0.0 0 +chr1 215691533 0 0 0.0 0 +chr1 215809978 0 0 0.0 0 +chr1 215917854 0 0 0.0 0 +chr1 215982336 0 0 0.0 0 +chr1 216001373 0 0 0.0 0 +chr1 216023246 0 0 0.0 0 +chr1 216228452 0 0 0.0 0 +chr1 216242508 0 0 0.0 0 +chr1 216285528 0 0 0.0 0 +chr1 216378145 0 0 0.0 0 +chr1 216514883 0 0 0.0 0 +chr1 216519403 0 0 0.0 0 +chr1 216711533 0 0 0.0 0 +chr1 216730259 0 0 0.0 0 +chr1 216775888 0 0 0.0 0 +chr1 216777627 0 0 0.0 0 +chr1 216841381 0 0 0.0 0 +chr1 216941051 0 0 0.0 0 +chr1 217105866 0 0 0.0 0 +chr1 217179030 0 0 0.0 0 +chr1 217248208 0 0 0.0 0 +chr1 217260965 0 0 0.0 0 +chr1 217321909 0 0 0.0 0 +chr1 217373114 0 0 0.0 0 +chr1 217379958 0 0 0.0 0 +chr1 217580934 0 0 0.0 0 +chr1 217655529 0 0 0.0 0 +chr1 217677531 0 0 0.0 0 +chr1 217826262 0 0 0.0 0 +chr1 217881803 0 0 0.0 0 +chr1 217969725 0 0 0.0 0 +chr1 218105982 0 1 0.0167 0 +chr1 218203098 0 0 0.0 0 +chr1 218217100 0 0 0.0 0 +chr1 218340080 0 0 0.0 0 +chr1 218342856 0 0 0.0 0 +chr1 218442655 1 9 0.1667 1 +chr1 218448374 0 0 0.0 0 +chr1 218733652 0 0 0.0 0 +chr1 218753499 0 0 0.0 0 +chr1 219078508 0 0 0.0 0 +chr1 219081889 0 0 0.0 0 +chr1 219100822 0 0 0.0 0 +chr1 219147509 0 0 0.0 0 +chr1 219294350 0 0 0.0 0 +chr1 219409763 0 0 0.0 0 +chr1 219697369 0 0 0.0 0 +chr1 219723580 0 0 0.0 0 +chr1 219746332 0 0 0.0 0 +chr1 219817408 0 0 0.0 0 +chr1 220112056 0 0 0.0 0 +chr1 220364911 0 0 0.0 0 +chr1 220745173 0 0 0.0 0 +chr1 220781912 0 0 0.0 0 +chr1 220843389 0 0 0.0 0 +chr1 220864660 0 0 0.0 0 +chr1 221012303 0 0 0.0 0 +chr1 221023635 0 0 0.0 0 +chr1 221026629 0 0 0.0 0 +chr1 221073409 0 0 0.0 0 +chr1 221334093 0 0 0.0 0 +chr1 221356887 0 0 0.0 0 +chr1 221419291 0 0 0.0 0 +chr1 221512277 0 0 0.0 0 +chr1 221603003 1 37 0.5286 1 +chr1 221905261 0 1 0.0169 0 +chr1 221952595 0 0 0.0 0 +chr1 222028562 0 0 0.0 0 +chr1 222113918 0 1 0.0233 0 +chr1 222188139 0 0 0.0 0 +chr1 222212694 0 0 0.0 0 +chr1 222548348 0 0 0.0 0 +chr1 222839483 0 0 0.0 0 +chr1 222967075 0 0 0.0 0 +chr1 222972955 0 0 0.0 0 +chr1 222994283 0 0 0.0 0 +chr1 223011763 0 0 0.0 0 +chr1 223042165 0 0 0.0 0 +chr1 223208286 0 0 0.0 0 +chr1 223240455 0 0 0.0 0 +chr1 223276478 0 0 0.0 0 +chr1 223292555 0 0 0.0 0 +chr1 223464183 0 0 0.0 0 +chr1 223669724 0 0 0.0 0 +chr1 223731867 0 0 0.0 0 +chr1 223919315 0 0 0.0 0 +chr1 224138389 0 0 0.0 0 +chr1 224265743 0 0 0.0 0 +chr1 224352779 0 0 0.0 0 +chr1 224396389 0 0 0.0 0 +chr1 224552007 0 0 0.0 0 +chr1 224702355 0 0 0.0 0 +chr1 224844006 0 0 0.0 0 +chr1 224878583 0 0 0.0 0 +chr1 224928986 0 1 0.0192 0 +chr1 224953738 0 0 0.0 0 +chr1 225081990 0 0 0.0 0 +chr1 225210303 0 0 0.0 0 +chr1 225217187 0 0 0.0 0 +chr1 225271807 0 0 0.0 0 +chr1 225352871 0 0 0.0 0 +chr1 225597230 0 0 0.0 0 +chr1 225605674 0 0 0.0 0 +chr1 225722190 0 0 0.0 0 +chr1 225831856 0 0 0.0 0 +chr1 225844698 0 0 0.0 0 +chr1 225878155 0 0 0.0 0 +chr1 226005926 0 0 0.0 0 +chr1 226019927 0 0 0.0 0 +chr1 226404328 0 0 0.0 0 +chr1 226414465 0 0 0.0 0 +chr1 226455384 0 0 0.0 0 +chr1 226635667 0 0 0.0 0 +chr1 226644691 0 0 0.0 0 +chr1 226652750 0 0 0.0 0 +chr1 226779049 0 0 0.0 0 +chr1 226809888 0 0 0.0 0 +chr1 226877923 0 0 0.0 0 +chr1 226904157 0 0 0.0 0 +chr1 227102444 0 0 0.0 0 +chr1 227210639 0 0 0.0 0 +chr1 227255555 0 0 0.0 0 +chr1 227392047 0 0 0.0 0 +chr1 227474190 0 0 0.0 0 +chr1 227663650 0 0 0.0 0 +chr1 227699922 0 0 0.0 0 +chr1 227701593 0 0 0.0 0 +chr1 227721961 0 0 0.0 0 +chr1 227879804 0 2 0.0286 0 +chr1 227904780 0 0 0.0 0 +chr1 228037048 0 0 0.0 0 +chr1 228050485 0 0 0.0 0 +chr1 228064338 0 0 0.0 0 +chr1 228144876 0 0 0.0 0 +chr1 228160994 0 0 0.0 0 +chr1 228162669 0 0 0.0 0 +chr1 228207618 0 0 0.0 0 +chr1 228207785 0 0 0.0 0 +chr1 228220149 0 0 0.0 0 +chr1 228294539 0 0 0.0 0 +chr1 228307866 0 0 0.0 0 +chr1 228311291 0 0 0.0 0 +chr1 228337560 0 0 0.0 0 +chr1 228375952 0 0 0.0 0 +chr1 228424342 0 0 0.0 0 +chr1 228445794 0 0 0.0 0 +chr1 228850900 0 0 0.0 0 +chr1 228876137 0 0 0.0 0 +chr1 228930757 0 0 0.0 0 +chr1 228992171 0 0 0.0 0 +chr1 229286078 0 0 0.0 0 +chr1 229302362 0 0 0.0 0 +chr1 229335071 0 0 0.0 0 +chr1 229510093 0 0 0.0 0 +chr1 229782480 0 0 0.0 0 +chr1 229810219 0 0 0.0 0 +chr1 229896431 0 0 0.0 0 +chr1 230016954 0 0 0.0 0 +chr1 230141246 0 0 0.0 0 +chr1 230143264 0 0 0.0 0 +chr1 230160087 0 0 0.0 0 +chr1 230398904 0 0 0.0 0 +chr1 230464517 0 0 0.0 0 +chr1 230541975 0 0 0.0 0 +chr1 230584293 1 4 0.0588 1 +chr1 230703169 0 0 0.0 0 +chr1 230706329 0 1 0.0152 0 +chr1 230811753 0 0 0.0 0 +chr1 230835736 0 0 0.0 0 +chr1 231095965 0 0 0.0 0 +chr1 231099660 0 0 0.0 0 +chr1 231211160 0 0 0.0 0 +chr1 231221326 0 0 0.0 0 +chr1 231252227 0 0 0.0 0 +chr1 231299421 0 0 0.0 0 +chr1 231302463 0 0 0.0 0 +chr1 231352151 0 1 0.0278 0 +chr1 231429639 0 0 0.0 0 +chr1 231752953 0 1 0.0143 0 +chr1 231769976 0 0 0.0 0 +chr1 231816678 0 0 0.0 0 +chr1 231851388 0 0 0.0 0 +chr1 232049577 0 0 0.0 0 +chr1 232084935 0 0 0.0 0 +chr1 232149757 0 0 0.0 0 +chr1 232299752 0 0 0.0 0 +chr1 232359721 0 0 0.0 0 +chr1 232486012 0 0 0.0 0 +chr1 232502961 0 0 0.0 0 +chr1 232561696 0 0 0.0 0 +chr1 232593618 0 1 0.0189 0 +chr1 232615465 0 0 0.0 0 +chr1 232847422 0 0 0.0 0 +chr1 232939272 0 0 0.0 0 +chr1 232946225 0 0 0.0 0 +chr1 233001824 0 0 0.0 0 +chr1 233016330 0 0 0.0 0 +chr1 233127278 0 0 0.0 0 +chr1 233147156 0 0 0.0 0 +chr1 233226025 0 0 0.0 0 +chr1 233358226 0 0 0.0 0 +chr1 233518874 0 0 0.0 0 +chr1 233636877 0 0 0.0 0 +chr1 233678102 0 0 0.0 0 +chr1 233806473 0 0 0.0 0 +chr1 233836030 0 0 0.0 0 +chr1 233884579 0 0 0.0 0 +chr1 233885712 0 0 0.0 0 +chr1 233972186 0 0 0.0 0 +chr1 234070801 0 0 0.0 0 +chr1 234401474 0 0 0.0 0 +chr1 234498420 0 0 0.0 0 +chr1 234508993 0 0 0.0 0 +chr1 234587034 0 0 0.0 0 +chr1 234617731 0 0 0.0 0 +chr1 234671479 0 0 0.0 0 +chr1 234718807 0 0 0.0 0 +chr1 234735436 0 0 0.0 0 +chr1 234819830 0 0 0.0 0 +chr1 234888772 0 0 0.0 0 +chr1 234963682 0 0 0.0 0 +chr1 234981457 0 1 0.0175 0 +chr1 235018654 0 0 0.0 0 +chr1 235073551 0 0 0.0 0 +chr1 235160449 0 0 0.0 0 +chr1 235188433 0 0 0.0 0 +chr1 235260715 0 0 0.0 0 +chr1 235310796 0 0 0.0 0 +chr1 235503865 0 0 0.0 0 +chr1 235549599 0 0 0.0 0 +chr1 235580287 0 0 0.0 0 +chr1 235694316 0 0 0.0 0 +chr1 235757432 0 0 0.0 0 +chr1 235916196 0 0 0.0 0 +chr1 236009963 0 0 0.0 0 +chr1 236082105 0 0 0.0 0 +chr1 236117765 0 0 0.0 0 +chr1 236460009 0 0 0.0 0 +chr1 236469154 0 0 0.0 0 +chr1 236636274 0 0 0.0 0 +chr1 236716143 0 0 0.0 0 +chr1 236736289 0 0 0.0 0 +chr1 236766295 0 0 0.0 0 +chr1 236801673 0 0 0.0 0 +chr1 237089839 0 0 0.0 0 +chr1 237169558 1 39 0.4815 1 +chr1 237175989 0 0 0.0 0 +chr1 237264963 0 0 0.0 0 +chr1 237309643 0 0 0.0 0 +chr1 237324913 0 0 0.0 0 +chr1 237595336 0 0 0.0 0 +chr1 237679240 0 0 0.0 0 +chr1 237838669 2 53 0.9815 1 +chr1 237843340 0 0 0.0 0 +chr1 237920389 0 0 0.0 0 +chr1 238123010 0 0 0.0 0 +chr1 238372953 0 0 0.0 0 +chr1 238595670 0 0 0.0 0 +chr1 238648493 0 0 0.0 0 +chr1 238678213 0 0 0.0 0 +chr1 239090404 0 0 0.0 0 +chr1 239116178 0 0 0.0 0 +chr1 239242929 0 0 0.0 0 +chr1 239324745 0 0 0.0 0 +chr1 239494593 0 0 0.0 0 +chr1 239636694 0 0 0.0 0 +chr1 239793097 0 0 0.0 0 +chr1 239793260 0 0 0.0 0 +chr1 239815738 0 0 0.0 0 +chr1 239868982 0 0 0.0 0 +chr1 239872126 0 0 0.0 0 +chr1 239875995 0 0 0.0 0 +chr1 239981865 0 0 0.0 0 +chr1 240112225 0 0 0.0 0 +chr1 240145207 0 0 0.0 0 +chr1 240189397 0 0 0.0 0 +chr1 240254494 0 0 0.0 0 +chr1 240420682 0 0 0.0 0 +chr1 240439400 0 0 0.0 0 +chr1 240633559 0 0 0.0 0 +chr1 240634621 0 0 0.0 0 +chr1 240690852 0 0 0.0 0 +chr1 240715313 0 0 0.0 0 +chr1 241137657 0 0 0.0 0 +chr1 241297314 0 0 0.0 0 +chr1 241430271 0 0 0.0 0 +chr1 241430820 0 0 0.0 0 +chr1 241707718 0 0 0.0 0 +chr1 241832364 0 0 0.0 0 +chr1 241889373 0 0 0.0 0 +chr1 241971791 0 0 0.0 0 +chr1 241992544 0 0 0.0 0 +chr1 242232057 0 0 0.0 0 +chr1 242718962 0 0 0.0 0 +chr1 242745097 0 0 0.0 0 +chr1 242912208 0 0 0.0 0 +chr1 243022063 0 0 0.0 0 +chr1 243323254 0 0 0.0 0 +chr1 243328163 0 0 0.0 0 +chr1 243520112 0 0 0.0 0 +chr1 243897942 0 0 0.0 0 +chr1 243907400 0 0 0.0 0 +chr1 244008236 0 0 0.0 0 +chr1 244010320 0 0 0.0 0 +chr1 244112639 0 0 0.0 0 +chr1 244142227 0 0 0.0 0 +chr1 244187489 0 0 0.0 0 +chr1 244230794 0 0 0.0 0 +chr1 244244335 0 0 0.0 0 +chr1 244432757 0 0 0.0 0 +chr1 244434630 0 0 0.0 0 +chr1 244477940 0 1 0.0233 0 +chr1 244486526 0 0 0.0 0 +chr1 244705734 0 0 0.0 0 +chr1 244814332 0 0 0.0 0 +chr1 244834861 0 0 0.0 0 +chr1 244860614 0 0 0.0 0 +chr1 244862993 0 0 0.0 0 +chr1 245122303 0 0 0.0 0 +chr1 245154405 0 0 0.0 0 +chr1 245180715 0 0 0.0 0 +chr1 245184398 0 0 0.0 0 +chr1 245290115 0 0 0.0 0 +chr1 245333666 0 0 0.0 0 +chr1 245466001 0 0 0.0 0 +chr1 245483636 0 0 0.0 0 +chr1 245555543 0 0 0.0 0 +chr1 245685238 0 0 0.0 0 +chr1 245922791 0 0 0.0 0 +chr1 246009987 1 14 0.8235 1 +chr1 246081863 0 0 0.0 0 +chr1 246109424 0 0 0.0 0 +chr1 246216262 2 11 0.275 1 +chr1 246314579 0 0 0.0 0 +chr1 246482512 0 0 0.0 0 +chr1 246523509 0 0 0.0 0 +chr1 246539324 0 0 0.0 0 +chr1 246552577 0 0 0.0 0 +chr1 246702072 0 0 0.0 0 +chr1 246811792 0 0 0.0 0 +chr1 246951247 0 0 0.0 0 +chr1 247247083 0 1 0.0278 0 +chr1 247435638 0 0 0.0 0 +chr1 247491507 0 0 0.0 0 +chr1 247531285 0 0 0.0 0 +chr1 247532128 0 0 0.0 0 +chr1 247551540 0 0 0.0 0 +chr1 247635021 0 0 0.0 0 +chr1 247782778 1 33 0.4521 1 +chr1 247867931 0 0 0.0 0 +chr1 247869844 0 0 0.0 0 +chr1 248002782 0 0 0.0 0 +chr1 248053932 0 0 0.0 0 +chr1 248103650 0 0 0.0 0 +chr1 248189794 0 0 0.0 0 +chr1 248370217 0 0 0.0 0 +chr1 248487216 0 0 0.0 0 +chr1 248513179 0 0 0.0 0 +chr1 248534884 0 0 0.0 0 +chr1 248560868 0 0 0.0 0 +chr1 248711903 0 0 0.0 0 +chr1 248814482 0 0 0.0 0 +chr1 248854921 0 0 0.0 0 +chr10 25892 0 0 0.0 0 +chr10 278427 1 28 0.9655 1 +chr10 313682 0 0 0.0 0 +chr10 380929 0 0 0.0 0 +chr10 383032 0 0 0.0 0 +chr10 517845 0 0 0.0 0 +chr10 571775 0 0 0.0 0 +chr10 629526 0 0 0.0 0 +chr10 653843 0 0 0.0 0 +chr10 813535 0 0 0.0 0 +chr10 968576 1 27 0.3506 1 +chr10 1011616 0 0 0.0 0 +chr10 1057576 0 0 0.0 0 +chr10 1150921 0 0 0.0 0 +chr10 1159537 0 0 0.0 0 +chr10 1250092 0 0 0.0 0 +chr10 1355392 0 0 0.0 0 +chr10 1422872 0 0 0.0 0 +chr10 1572946 0 0 0.0 0 +chr10 1656346 0 0 0.0 0 +chr10 1864727 0 0 0.0 0 +chr10 1877395 0 0 0.0 0 +chr10 2048328 0 0 0.0 0 +chr10 2070689 0 0 0.0 0 +chr10 2100765 0 0 0.0 0 +chr10 2207738 0 0 0.0 0 +chr10 2336039 0 0 0.0 0 +chr10 2360651 2 59 0.8939 1 +chr10 2602559 0 0 0.0 0 +chr10 2623339 0 0 0.0 0 +chr10 2778332 0 0 0.0 0 +chr10 2791527 0 0 0.0 0 +chr10 2804578 0 0 0.0 0 +chr10 2830124 0 0 0.0 0 +chr10 2999601 0 0 0.0 0 +chr10 3109040 0 0 0.0 0 +chr10 3118714 0 0 0.0 0 +chr10 3303965 0 0 0.0 0 +chr10 3680622 0 0 0.0 0 +chr10 3793475 0 0 0.0 0 +chr10 3845563 0 0 0.0 0 +chr10 3856772 0 0 0.0 0 +chr10 4075302 0 0 0.0 0 +chr10 4103574 0 0 0.0 0 +chr10 4169638 0 0 0.0 0 +chr10 4183492 0 0 0.0 0 +chr10 4307211 0 0 0.0 0 +chr10 4416650 0 0 0.0 0 +chr10 4456265 0 0 0.0 0 +chr10 4524014 0 0 0.0 0 +chr10 4632389 0 0 0.0 0 +chr10 4637907 0 0 0.0 0 +chr10 5230178 0 0 0.0 0 +chr10 5309785 0 0 0.0 0 +chr10 5596341 0 0 0.0 0 +chr10 5752532 0 0 0.0 0 +chr10 5768724 0 0 0.0 0 +chr10 5862865 0 0 0.0 0 +chr10 6177143 0 0 0.0 0 +chr10 6448814 0 0 0.0 0 +chr10 6467861 0 0 0.0 0 +chr10 6520117 0 0 0.0 0 +chr10 6604332 0 0 0.0 0 +chr10 6778649 0 0 0.0 0 +chr10 6840555 0 0 0.0 0 +chr10 6886074 0 0 0.0 0 +chr10 6958482 0 0 0.0 0 +chr10 7001494 0 0 0.0 0 +chr10 7194053 0 0 0.0 0 +chr10 7288132 0 0 0.0 0 +chr10 7329537 0 0 0.0 0 +chr10 7352367 0 0 0.0 0 +chr10 7365296 0 0 0.0 0 +chr10 7398256 0 0 0.0 0 +chr10 7410458 0 0 0.0 0 +chr10 7418376 0 0 0.0 0 +chr10 7498229 0 0 0.0 0 +chr10 7584925 0 0 0.0 0 +chr10 7617663 0 0 0.0 0 +chr10 7621857 0 0 0.0 0 +chr10 7744311 0 0 0.0 0 +chr10 7745153 0 0 0.0 0 +chr10 7783538 0 0 0.0 0 +chr10 7865098 0 0 0.0 0 +chr10 7951637 0 0 0.0 0 +chr10 8371087 0 0 0.0 0 +chr10 8656756 0 0 0.0 0 +chr10 8878883 0 0 0.0 0 +chr10 8898074 0 0 0.0 0 +chr10 9265191 0 0 0.0 0 +chr10 9273222 0 0 0.0 0 +chr10 9343373 0 0 0.0 0 +chr10 9348993 0 0 0.0 0 +chr10 9437369 0 0 0.0 0 +chr10 9665612 0 0 0.0 0 +chr10 9803045 0 0 0.0 0 +chr10 9903389 0 0 0.0 0 +chr10 10022637 0 0 0.0 0 +chr10 10145590 0 2 0.0274 0 +chr10 10190262 0 0 0.0 0 +chr10 10304271 0 0 0.0 0 +chr10 10309366 0 0 0.0 0 +chr10 10706911 0 1 0.0175 0 +chr10 10967442 0 0 0.0 0 +chr10 11004247 0 0 0.0 0 +chr10 11009383 0 0 0.0 0 +chr10 11069663 0 0 0.0 0 +chr10 11121078 0 0 0.0 0 +chr10 11122224 0 0 0.0 0 +chr10 11141759 0 0 0.0 0 +chr10 11233869 0 0 0.0 0 +chr10 11275313 0 0 0.0 0 +chr10 11327595 0 0 0.0 0 +chr10 11476438 0 0 0.0 0 +chr10 11496911 0 0 0.0 0 +chr10 11583344 0 0 0.0 0 +chr10 11600119 0 0 0.0 0 +chr10 11626223 0 1 0.0179 0 +chr10 11712839 0 0 0.0 0 +chr10 11801978 0 0 0.0 0 +chr10 11810084 0 0 0.0 0 +chr10 11813766 0 0 0.0 0 +chr10 11857502 0 0 0.0 0 +chr10 11896718 0 0 0.0 0 +chr10 12019130 0 0 0.0 0 +chr10 12078539 0 0 0.0 0 +chr10 12251314 0 0 0.0 0 +chr10 12360464 0 0 0.0 0 +chr10 12561589 0 0 0.0 0 +chr10 12611884 0 0 0.0 0 +chr10 12629784 0 0 0.0 0 +chr10 12649715 0 0 0.0 0 +chr10 12721859 0 0 0.0 0 +chr10 12834171 0 0 0.0 0 +chr10 12918981 0 1 0.0161 0 +chr10 12983035 0 0 0.0 0 +chr10 12983544 0 0 0.0 0 +chr10 13020614 0 0 0.0 0 +chr10 13150946 0 0 0.0 0 +chr10 13161222 0 0 0.0 0 +chr10 13197009 0 0 0.0 0 +chr10 13211717 0 0 0.0 0 +chr10 13274503 0 0 0.0 0 +chr10 13309320 0 0 0.0 0 +chr10 13334810 0 0 0.0 0 +chr10 13462785 0 0 0.0 0 +chr10 13553587 0 0 0.0 0 +chr10 13687477 0 0 0.0 0 +chr10 13725309 0 0 0.0 0 +chr10 13734102 0 0 0.0 0 +chr10 13750530 0 0 0.0 0 +chr10 13756626 0 0 0.0 0 +chr10 13791149 0 0 0.0 0 +chr10 13791861 0 0 0.0 0 +chr10 13797389 0 0 0.0 0 +chr10 13827101 0 0 0.0 0 +chr10 13929321 0 0 0.0 0 +chr10 13991529 0 0 0.0 0 +chr10 13998317 0 0 0.0 0 +chr10 14015966 0 0 0.0 0 +chr10 14058764 0 0 0.0 0 +chr10 14214582 0 0 0.0 0 +chr10 14285525 0 0 0.0 0 +chr10 14312916 0 0 0.0 0 +chr10 14316055 0 0 0.0 0 +chr10 14496607 0 0 0.0 0 +chr10 14660979 0 0 0.0 0 +chr10 14758684 0 0 0.0 0 +chr10 14825217 0 0 0.0 0 +chr10 14917218 0 0 0.0 0 +chr10 14926627 0 0 0.0 0 +chr10 15085313 0 0 0.0 0 +chr10 15107232 0 0 0.0 0 +chr10 15241457 0 0 0.0 0 +chr10 15358682 0 0 0.0 0 +chr10 15391810 0 0 0.0 0 +chr10 15426436 0 0 0.0 0 +chr10 15517282 0 0 0.0 0 +chr10 15749322 0 0 0.0 0 +chr10 16033860 0 0 0.0 0 +chr10 16406139 0 0 0.0 0 +chr10 16498860 0 0 0.0 0 +chr10 16516821 0 0 0.0 0 +chr10 16734993 0 0 0.0 0 +chr10 16770135 0 0 0.0 0 +chr10 16877828 0 0 0.0 0 +chr10 17151348 0 0 0.0 0 +chr10 17258684 0 0 0.0 0 +chr10 17314811 0 0 0.0 0 +chr10 17327669 0 0 0.0 0 +chr10 17454755 0 0 0.0 0 +chr10 17713031 0 0 0.0 0 +chr10 17714547 0 0 0.0 0 +chr10 17913674 0 0 0.0 0 +chr10 17943410 0 0 0.0 0 +chr10 17956662 0 0 0.0 0 +chr10 17963426 0 0 0.0 0 +chr10 18102444 0 0 0.0 0 +chr10 18323604 0 0 0.0 0 +chr10 18362963 0 0 0.0 0 +chr10 18564152 0 0 0.0 0 +chr10 18566698 0 0 0.0 0 +chr10 18571845 0 0 0.0 0 +chr10 18595191 0 0 0.0 0 +chr10 18619566 0 0 0.0 0 +chr10 18656256 0 0 0.0 0 +chr10 18717102 0 0 0.0 0 +chr10 18809776 0 0 0.0 0 +chr10 18935664 0 0 0.0 0 +chr10 19231268 0 0 0.0 0 +chr10 19374709 0 0 0.0 0 +chr10 19509919 0 1 0.02 0 +chr10 19648585 0 0 0.0 0 +chr10 19653924 0 0 0.0 0 +chr10 19756776 0 0 0.0 0 +chr10 19827792 0 0 0.0 0 +chr10 20106137 0 0 0.0 0 +chr10 20141264 0 0 0.0 0 +chr10 20147464 0 0 0.0 0 +chr10 20183733 0 0 0.0 0 +chr10 20253951 0 0 0.0 0 +chr10 20296692 0 0 0.0 0 +chr10 20350902 0 0 0.0 0 +chr10 20411877 0 0 0.0 0 +chr10 20597539 0 0 0.0 0 +chr10 21058343 0 0 0.0 0 +chr10 21119226 0 1 0.0244 0 +chr10 21162872 0 0 0.0 0 +chr10 21166606 0 0 0.0 0 +chr10 21277443 0 0 0.0 0 +chr10 21297077 0 0 0.0 0 +chr10 21478834 0 0 0.0 0 +chr10 21561334 0 0 0.0 0 +chr10 21779476 0 0 0.0 0 +chr10 21826769 0 0 0.0 0 +chr10 22110694 0 0 0.0 0 +chr10 22162350 0 0 0.0 0 +chr10 22165683 1 4 0.1026 1 +chr10 22453615 0 0 0.0 0 +chr10 22453790 0 0 0.0 0 +chr10 22581310 0 0 0.0 0 +chr10 22677601 0 0 0.0 0 +chr10 22682361 0 0 0.0 0 +chr10 22761866 0 0 0.0 0 +chr10 22914367 0 0 0.0 0 +chr10 22955829 0 0 0.0 0 +chr10 23077287 0 0 0.0 0 +chr10 23428521 0 0 0.0 0 +chr10 23470373 0 0 0.0 0 +chr10 23539321 0 0 0.0 0 +chr10 23610920 0 0 0.0 0 +chr10 23678708 0 0 0.0 0 +chr10 23687353 0 0 0.0 0 +chr10 23835371 0 0 0.0 0 +chr10 23870162 0 0 0.0 0 +chr10 23952567 0 0 0.0 0 +chr10 23992514 0 0 0.0 0 +chr10 24039005 0 0 0.0 0 +chr10 24059668 0 0 0.0 0 +chr10 24215535 0 0 0.0 0 +chr10 24474169 0 0 0.0 0 +chr10 24718001 0 0 0.0 0 +chr10 24750498 0 1 0.0204 0 +chr10 24775709 0 0 0.0 0 +chr10 24783537 0 0 0.0 0 +chr10 24787473 0 0 0.0 0 +chr10 24805326 0 1 0.0278 0 +chr10 24815869 0 0 0.0 0 +chr10 24822188 0 0 0.0 0 +chr10 24988971 0 0 0.0 0 +chr10 25120341 0 0 0.0 0 +chr10 25143799 1 26 0.4 1 +chr10 25214636 0 0 0.0 0 +chr10 25329478 0 0 0.0 0 +chr10 25341934 0 0 0.0 0 +chr10 25354608 0 0 0.0 0 +chr10 25434086 0 0 0.0 0 +chr10 25483453 0 0 0.0 0 +chr10 25638473 0 0 0.0 0 +chr10 25643823 0 0 0.0 0 +chr10 25812830 0 0 0.0 0 +chr10 25903457 0 0 0.0 0 +chr10 26102714 0 0 0.0 0 +chr10 26228540 0 0 0.0 0 +chr10 26379167 0 0 0.0 0 +chr10 26582057 0 0 0.0 0 +chr10 26641555 0 0 0.0 0 +chr10 26939865 0 0 0.0 0 +chr10 26968387 0 0 0.0 0 +chr10 27382556 0 0 0.0 0 +chr10 27506759 0 0 0.0 0 +chr10 27587611 0 0 0.0 0 +chr10 27588166 0 0 0.0 0 +chr10 27616828 0 0 0.0 0 +chr10 27776703 0 0 0.0 0 +chr10 28054721 0 0 0.0 0 +chr10 28128378 0 0 0.0 0 +chr10 28314217 0 0 0.0 0 +chr10 28423607 0 0 0.0 0 +chr10 28549160 1 21 0.525 1 +chr10 28551114 0 0 0.0 0 +chr10 28625275 0 0 0.0 0 +chr10 28678895 0 0 0.0 0 +chr10 28857152 0 0 0.0 0 +chr10 29174718 0 0 0.0 0 +chr10 29321996 0 0 0.0 0 +chr10 29342982 0 0 0.0 0 +chr10 29408952 0 0 0.0 0 +chr10 29440595 0 0 0.0 0 +chr10 29476200 0 0 0.0 0 +chr10 29520483 0 0 0.0 0 +chr10 29612158 0 0 0.0 0 +chr10 29733296 0 0 0.0 0 +chr10 29777824 0 0 0.0 0 +chr10 29815100 0 0 0.0 0 +chr10 29925601 0 0 0.0 0 +chr10 30055852 0 1 0.0147 0 +chr10 30134376 0 2 0.0204 0 +chr10 30186125 0 0 0.0 0 +chr10 30208196 0 0 0.0 0 +chr10 30330837 0 0 0.0 0 +chr10 30361018 0 0 0.0 0 +chr10 30454633 0 0 0.0 0 +chr10 30580039 0 1 0.02 0 +chr10 30583974 0 0 0.0 0 +chr10 30605526 0 0 0.0 0 +chr10 30730493 0 0 0.0 0 +chr10 30812779 0 0 0.0 0 +chr10 30818674 0 0 0.0 0 +chr10 30847426 0 0 0.0 0 +chr10 30861110 0 0 0.0 0 +chr10 31006105 0 0 0.0 0 +chr10 31029623 0 0 0.0 0 +chr10 31056190 0 0 0.0 0 +chr10 31177819 0 0 0.0 0 +chr10 31297509 0 0 0.0 0 +chr10 31466956 0 0 0.0 0 +chr10 31516420 0 0 0.0 0 +chr10 31825487 0 0 0.0 0 +chr10 31913166 0 0 0.0 0 +chr10 32068988 0 0 0.0 0 +chr10 32150705 0 0 0.0 0 +chr10 32490723 0 0 0.0 0 +chr10 32514450 0 0 0.0 0 +chr10 32548191 0 0 0.0 0 +chr10 33155103 0 0 0.0 0 +chr10 33180797 0 0 0.0 0 +chr10 33184277 0 0 0.0 0 +chr10 33202177 0 0 0.0 0 +chr10 33398831 0 0 0.0 0 +chr10 33482820 0 0 0.0 0 +chr10 33500074 0 0 0.0 0 +chr10 33525135 0 0 0.0 0 +chr10 33661974 0 0 0.0 0 +chr10 33966962 0 0 0.0 0 +chr10 34072545 0 0 0.0 0 +chr10 34079729 0 0 0.0 0 +chr10 34081636 0 0 0.0 0 +chr10 34093424 0 0 0.0 0 +chr10 34152271 0 0 0.0 0 +chr10 34213551 0 0 0.0 0 +chr10 34625257 0 0 0.0 0 +chr10 35117366 0 0 0.0 0 +chr10 35288509 0 0 0.0 0 +chr10 35451500 0 0 0.0 0 +chr10 35511414 0 0 0.0 0 +chr10 35517148 0 0 0.0 0 +chr10 35517535 0 0 0.0 0 +chr10 35542601 0 0 0.0 0 +chr10 35575177 0 0 0.0 0 +chr10 35621848 0 0 0.0 0 +chr10 35642247 0 0 0.0 0 +chr10 35785105 0 0 0.0 0 +chr10 35903551 0 0 0.0 0 +chr10 35987479 0 0 0.0 0 +chr10 35989588 0 0 0.0 0 +chr10 35997577 0 0 0.0 0 +chr10 36048742 0 0 0.0 0 +chr10 36083334 0 0 0.0 0 +chr10 36328961 0 0 0.0 0 +chr10 36661052 0 0 0.0 0 +chr10 36689313 0 0 0.0 0 +chr10 36722087 0 0 0.0 0 +chr10 36898211 0 0 0.0 0 +chr10 37390507 0 0 0.0 0 +chr10 37390675 0 0 0.0 0 +chr10 37433849 0 0 0.0 0 +chr10 37554069 0 0 0.0 0 +chr10 37666378 0 0 0.0 0 +chr10 37673688 0 0 0.0 0 +chr10 37705381 0 0 0.0 0 +chr10 37792023 0 0 0.0 0 +chr10 37822120 0 0 0.0 0 +chr10 37942990 0 0 0.0 0 +chr10 37944241 0 0 0.0 0 +chr10 37945580 0 0 0.0 0 +chr10 38132140 0 0 0.0 0 +chr10 38162377 0 0 0.0 0 +chr10 38272892 0 0 0.0 0 +chr10 38489085 0 0 0.0 0 +chr10 38599080 0 0 0.0 0 +chr10 38651685 0 0 0.0 0 +chr10 38660029 0 0 0.0 0 +chr10 38700881 0 0 0.0 0 +chr10 38731589 0 0 0.0 0 +chr10 38763642 0 0 0.0 0 +chr10 38853481 0 0 0.0 0 +chr10 38865836 0 0 0.0 0 +chr10 38912520 1 10 0.2941 1 +chr10 38920146 0 0 0.0 0 +chr10 39103525 0 0 0.0 0 +chr10 39175554 0 0 0.0 0 +chr10 39176259 0 0 0.0 0 +chr10 39210303 0 0 0.0 0 +chr10 39211795 0 0 0.0 0 +chr10 39213854 0 0 0.0 0 +chr10 39327687 0 0 0.0 0 +chr10 39331140 0 0 0.0 0 +chr10 39418227 0 0 0.0 0 +chr10 39461819 0 0 0.0 0 +chr10 39517369 0 0 0.0 0 +chr10 40003871 0 0 0.0 0 +chr10 41766528 0 0 0.0 0 +chr10 41805978 0 0 0.0 0 +chr10 41912596 0 0 0.0 0 +chr10 42263085 0 0 0.0 0 +chr10 42299486 0 0 0.0 0 +chr10 42309025 0 0 0.0 0 +chr10 42728446 0 0 0.0 0 +chr10 42757655 0 0 0.0 0 +chr10 42862508 0 0 0.0 0 +chr10 42892478 0 0 0.0 0 +chr10 42971160 0 0 0.0 0 +chr10 43036608 0 0 0.0 0 +chr10 43036766 0 1 0.02 0 +chr10 43059240 0 0 0.0 0 +chr10 43066070 0 0 0.0 0 +chr10 43071514 0 0 0.0 0 +chr10 43109390 0 0 0.0 0 +chr10 43113663 0 0 0.0 0 +chr10 43122173 0 0 0.0 0 +chr10 43136570 0 0 0.0 0 +chr10 43201357 0 0 0.0 0 +chr10 43214716 0 0 0.0 0 +chr10 43237034 0 0 0.0 0 +chr10 43355833 0 0 0.0 0 +chr10 43372644 0 0 0.0 0 +chr10 43702269 0 0 0.0 0 +chr10 43749258 0 0 0.0 0 +chr10 43788403 0 0 0.0 0 +chr10 43870449 0 0 0.0 0 +chr10 43889841 0 0 0.0 0 +chr10 43969343 0 0 0.0 0 +chr10 43970639 0 0 0.0 0 +chr10 44064274 0 0 0.0 0 +chr10 44106060 0 0 0.0 0 +chr10 44284129 0 0 0.0 0 +chr10 44352804 0 0 0.0 0 +chr10 44559731 0 0 0.0 0 +chr10 44761335 0 0 0.0 0 +chr10 44822328 0 0 0.0 0 +chr10 44833531 0 0 0.0 0 +chr10 44926465 0 0 0.0 0 +chr10 44961570 0 0 0.0 0 +chr10 44982365 0 0 0.0 0 +chr10 45024267 0 0 0.0 0 +chr10 45112445 0 0 0.0 0 +chr10 45232048 0 0 0.0 0 +chr10 45342346 0 0 0.0 0 +chr10 45359600 0 0 0.0 0 +chr10 45424919 0 0 0.0 0 +chr10 45475530 0 0 0.0 0 +chr10 45522848 0 0 0.0 0 +chr10 45532098 0 0 0.0 0 +chr10 45557390 0 0 0.0 0 +chr10 45605885 0 0 0.0 0 +chr10 45813458 0 0 0.0 0 +chr10 45992094 0 0 0.0 0 +chr10 46047348 0 0 0.0 0 +chr10 46055431 0 0 0.0 0 +chr10 46091935 0 0 0.0 0 +chr10 46145637 0 0 0.0 0 +chr10 46266478 0 0 0.0 0 +chr10 46271201 0 0 0.0 0 +chr10 46321852 0 0 0.0 0 +chr10 46498051 0 0 0.0 0 +chr10 46544181 0 0 0.0 0 +chr10 46568887 0 0 0.0 0 +chr10 46639942 0 0 0.0 0 +chr10 46698267 0 0 0.0 0 +chr10 46852104 0 0 0.0 0 +chr10 46886994 0 0 0.0 0 +chr10 46953457 0 0 0.0 0 +chr10 47075899 0 0 0.0 0 +chr10 47134659 0 0 0.0 0 +chr10 47141866 0 0 0.0 0 +chr10 47409541 0 0 0.0 0 +chr10 47449972 0 0 0.0 0 +chr10 47642123 0 0 0.0 0 +chr10 47701739 0 0 0.0 0 +chr10 47772916 0 0 0.0 0 +chr10 47886579 0 0 0.0 0 +chr10 48098397 0 0 0.0 0 +chr10 48164887 0 0 0.0 0 +chr10 48234372 0 0 0.0 0 +chr10 48245323 0 0 0.0 0 +chr10 48331255 0 0 0.0 0 +chr10 48334315 0 0 0.0 0 +chr10 48515574 0 0 0.0 0 +chr10 48550550 0 0 0.0 0 +chr10 48605961 0 0 0.0 0 +chr10 48639620 0 0 0.0 0 +chr10 48686141 0 0 0.0 0 +chr10 48738562 0 0 0.0 0 +chr10 48766476 0 0 0.0 0 +chr10 48833746 0 0 0.0 0 +chr10 49010078 0 0 0.0 0 +chr10 49059413 0 0 0.0 0 +chr10 49062386 0 0 0.0 0 +chr10 49145490 0 0 0.0 0 +chr10 49172870 0 0 0.0 0 +chr10 49227409 0 0 0.0 0 +chr10 49268522 0 0 0.0 0 +chr10 49270905 0 0 0.0 0 +chr10 49301879 0 0 0.0 0 +chr10 49336659 0 0 0.0 0 +chr10 49365742 0 0 0.0 0 +chr10 49417494 0 0 0.0 0 +chr10 49428144 0 0 0.0 0 +chr10 49571231 0 0 0.0 0 +chr10 49652477 0 0 0.0 0 +chr10 49746277 0 0 0.0 0 +chr10 49768907 0 0 0.0 0 +chr10 49810376 0 0 0.0 0 +chr10 49968556 0 0 0.0 0 +chr10 50185078 0 0 0.0 0 +chr10 50222083 0 0 0.0 0 +chr10 50421393 0 0 0.0 0 +chr10 50427660 0 0 0.0 0 +chr10 50536014 0 0 0.0 0 +chr10 50541600 0 0 0.0 0 +chr10 50569119 0 0 0.0 0 +chr10 50605059 0 0 0.0 0 +chr10 50703831 0 0 0.0 0 +chr10 50756971 0 0 0.0 0 +chr10 50852597 0 0 0.0 0 +chr10 50968616 0 0 0.0 0 +chr10 51019391 0 0 0.0 0 +chr10 51124485 0 0 0.0 0 +chr10 51154316 0 0 0.0 0 +chr10 51405579 0 0 0.0 0 +chr10 51427932 0 0 0.0 0 +chr10 51482704 0 0 0.0 0 +chr10 51717756 0 0 0.0 0 +chr10 51735914 2 5 0.625 1 +chr10 52320811 0 0 0.0 0 +chr10 52348068 0 0 0.0 0 +chr10 52421230 0 0 0.0 0 +chr10 52591799 0 0 0.0 0 +chr10 52735658 0 0 0.0 0 +chr10 52770656 0 0 0.0 0 +chr10 52786724 0 0 0.0 0 +chr10 52818028 0 0 0.0 0 +chr10 52890611 0 0 0.0 0 +chr10 52894248 0 0 0.0 0 +chr10 52951565 0 0 0.0 0 +chr10 53331320 0 1 0.0175 0 +chr10 53370938 0 0 0.0 0 +chr10 53484774 0 0 0.0 0 +chr10 53535229 0 0 0.0 0 +chr10 53626998 0 0 0.0 0 +chr10 53661207 0 0 0.0 0 +chr10 53776463 0 0 0.0 0 +chr10 53831267 0 0 0.0 0 +chr10 53991180 0 0 0.0 0 +chr10 54096262 0 0 0.0 0 +chr10 54123571 0 0 0.0 0 +chr10 54367520 0 0 0.0 0 +chr10 54391764 0 0 0.0 0 +chr10 54610279 0 0 0.0 0 +chr10 54680547 0 0 0.0 0 +chr10 54854440 0 0 0.0 0 +chr10 54920653 0 0 0.0 0 +chr10 55038651 0 1 0.0256 0 +chr10 55257106 0 0 0.0 0 +chr10 55372310 0 0 0.0 0 +chr10 55400450 0 0 0.0 0 +chr10 55589405 0 0 0.0 0 +chr10 55759616 0 0 0.0 0 +chr10 56010981 0 0 0.0 0 +chr10 56438333 0 0 0.0 0 +chr10 56456367 0 0 0.0 0 +chr10 56456986 0 0 0.0 0 +chr10 56525508 0 1 0.0227 0 +chr10 56575493 0 0 0.0 0 +chr10 56897486 0 0 0.0 0 +chr10 56930857 0 0 0.0 0 +chr10 57036883 0 0 0.0 0 +chr10 57038560 0 0 0.0 0 +chr10 57508578 0 0 0.0 0 +chr10 57643992 0 0 0.0 0 +chr10 57875053 0 0 0.0 0 +chr10 57953493 0 0 0.0 0 +chr10 57988991 0 0 0.0 0 +chr10 58008121 0 0 0.0 0 +chr10 58127015 0 0 0.0 0 +chr10 58299723 0 0 0.0 0 +chr10 58336083 0 0 0.0 0 +chr10 58579265 0 0 0.0 0 +chr10 58866473 0 0 0.0 0 +chr10 58942516 0 0 0.0 0 +chr10 58982991 0 0 0.0 0 +chr10 59070345 0 0 0.0 0 +chr10 59118889 0 0 0.0 0 +chr10 59746594 0 0 0.0 0 +chr10 59756882 0 0 0.0 0 +chr10 59825349 0 0 0.0 0 +chr10 59840868 0 0 0.0 0 +chr10 59916268 0 0 0.0 0 +chr10 59995659 0 0 0.0 0 +chr10 60063547 0 0 0.0 0 +chr10 60173726 0 0 0.0 0 +chr10 60356159 0 0 0.0 0 +chr10 60660768 0 0 0.0 0 +chr10 60731942 0 0 0.0 0 +chr10 61008190 0 0 0.0 0 +chr10 61144503 0 0 0.0 0 +chr10 61325567 1 26 0.4 1 +chr10 61341660 0 0 0.0 0 +chr10 61396247 0 0 0.0 0 +chr10 61559440 0 0 0.0 0 +chr10 61613254 0 0 0.0 0 +chr10 61639147 0 0 0.0 0 +chr10 61898784 0 0 0.0 0 +chr10 61967604 0 0 0.0 0 +chr10 62150124 0 0 0.0 0 +chr10 62269633 0 0 0.0 0 +chr10 62290613 0 0 0.0 0 +chr10 62444364 0 0 0.0 0 +chr10 62489850 0 0 0.0 0 +chr10 62761175 0 0 0.0 0 +chr10 63184942 0 0 0.0 0 +chr10 63449837 0 0 0.0 0 +chr10 63456691 0 0 0.0 0 +chr10 63740136 0 0 0.0 0 +chr10 63893068 0 0 0.0 0 +chr10 63980721 0 0 0.0 0 +chr10 63998125 0 0 0.0 0 +chr10 64107478 0 0 0.0 0 +chr10 64234028 0 0 0.0 0 +chr10 64441650 0 0 0.0 0 +chr10 64443695 0 0 0.0 0 +chr10 64450758 0 0 0.0 0 +chr10 64548857 0 0 0.0 0 +chr10 64668580 0 0 0.0 0 +chr10 64776621 0 0 0.0 0 +chr10 64785922 0 0 0.0 0 +chr10 64999002 0 0 0.0 0 +chr10 65161493 0 0 0.0 0 +chr10 65174024 0 0 0.0 0 +chr10 65455938 0 0 0.0 0 +chr10 65713648 0 0 0.0 0 +chr10 65746593 0 0 0.0 0 +chr10 65912761 0 0 0.0 0 +chr10 66188844 0 1 0.0143 0 +chr10 66536106 0 0 0.0 0 +chr10 66565718 0 0 0.0 0 +chr10 66582002 0 0 0.0 0 +chr10 66670490 0 0 0.0 0 +chr10 66679997 0 1 0.0133 0 +chr10 66976979 0 0 0.0 0 +chr10 67000907 0 0 0.0 0 +chr10 67087781 0 0 0.0 0 +chr10 67328557 0 0 0.0 0 +chr10 67843245 0 0 0.0 0 +chr10 67866383 0 0 0.0 0 +chr10 67885916 1 24 0.48 1 +chr10 68045642 0 0 0.0 0 +chr10 68094818 0 0 0.0 0 +chr10 68177271 0 0 0.0 0 +chr10 68208011 0 0 0.0 0 +chr10 68424672 0 0 0.0 0 +chr10 68473566 0 0 0.0 0 +chr10 68650793 0 0 0.0 0 +chr10 68746471 0 0 0.0 0 +chr10 68778302 0 0 0.0 0 +chr10 68840236 0 0 0.0 0 +chr10 68868069 0 0 0.0 0 +chr10 68870806 0 0 0.0 0 +chr10 68884827 0 0 0.0 0 +chr10 69034598 0 0 0.0 0 +chr10 69041720 0 0 0.0 0 +chr10 69197070 0 0 0.0 0 +chr10 69275025 0 0 0.0 0 +chr10 69316151 0 0 0.0 0 +chr10 69413885 0 0 0.0 0 +chr10 69435028 0 0 0.0 0 +chr10 69435539 0 0 0.0 0 +chr10 69507928 0 0 0.0 0 +chr10 69567053 0 0 0.0 0 +chr10 69578271 0 0 0.0 0 +chr10 69618832 0 0 0.0 0 +chr10 69683368 0 0 0.0 0 +chr10 69815479 0 0 0.0 0 +chr10 69862038 0 0 0.0 0 +chr10 69892879 0 0 0.0 0 +chr10 69898269 0 0 0.0 0 +chr10 69926052 0 0 0.0 0 +chr10 69956632 0 0 0.0 0 +chr10 70045466 0 0 0.0 0 +chr10 70102065 0 0 0.0 0 +chr10 70464861 0 0 0.0 0 +chr10 70518493 0 0 0.0 0 +chr10 70593834 0 0 0.0 0 +chr10 70678896 0 0 0.0 0 +chr10 70701388 0 0 0.0 0 +chr10 70702416 0 0 0.0 0 +chr10 70703906 0 0 0.0 0 +chr10 70723723 0 0 0.0 0 +chr10 70743982 0 0 0.0 0 +chr10 70780643 0 0 0.0 0 +chr10 70798213 0 0 0.0 0 +chr10 70807185 0 0 0.0 0 +chr10 70920984 0 0 0.0 0 +chr10 70956511 0 0 0.0 0 +chr10 70974051 0 0 0.0 0 +chr10 71014272 0 0 0.0 0 +chr10 71173241 0 0 0.0 0 +chr10 71178196 0 0 0.0 0 +chr10 71222984 0 0 0.0 0 +chr10 71428925 0 0 0.0 0 +chr10 71474109 0 0 0.0 0 +chr10 71481594 0 0 0.0 0 +chr10 71491129 0 0 0.0 0 +chr10 71617322 0 0 0.0 0 +chr10 71625168 0 0 0.0 0 +chr10 71740210 0 0 0.0 0 +chr10 71785988 0 0 0.0 0 +chr10 71914673 0 0 0.0 0 +chr10 71921042 0 0 0.0 0 +chr10 71931651 0 0 0.0 0 +chr10 71991226 0 0 0.0 0 +chr10 72024186 0 0 0.0 0 +chr10 72026226 0 0 0.0 0 +chr10 72054955 0 0 0.0 0 +chr10 72070848 0 0 0.0 0 +chr10 72079842 0 0 0.0 0 +chr10 72276584 0 0 0.0 0 +chr10 72336555 0 0 0.0 0 +chr10 72725219 0 0 0.0 0 +chr10 72732640 0 0 0.0 0 +chr10 72735481 0 0 0.0 0 +chr10 72776142 0 1 0.0147 0 +chr10 72806531 0 0 0.0 0 +chr10 72847236 0 0 0.0 0 +chr10 72990396 0 0 0.0 0 +chr10 72990862 0 0 0.0 0 +chr10 73022348 0 0 0.0 0 +chr10 73319479 0 0 0.0 0 +chr10 73324217 0 0 0.0 0 +chr10 73575879 0 0 0.0 0 +chr10 73865885 0 0 0.0 0 +chr10 73937807 0 0 0.0 0 +chr10 74347710 0 0 0.0 0 +chr10 74497547 0 0 0.0 0 +chr10 74649598 1 13 0.1646 1 +chr10 74651136 0 0 0.0 0 +chr10 74712801 0 0 0.0 0 +chr10 74721568 0 0 0.0 0 +chr10 74816189 0 0 0.0 0 +chr10 75133044 0 0 0.0 0 +chr10 75185900 0 0 0.0 0 +chr10 75249367 0 0 0.0 0 +chr10 75297073 0 0 0.0 0 +chr10 75343553 0 0 0.0 0 +chr10 75370119 0 0 0.0 0 +chr10 75895687 0 0 0.0 0 +chr10 75939239 0 0 0.0 0 +chr10 75959383 0 0 0.0 0 +chr10 76013343 0 0 0.0 0 +chr10 76126529 0 0 0.0 0 +chr10 76185183 0 0 0.0 0 +chr10 76231467 0 0 0.0 0 +chr10 76352993 0 0 0.0 0 +chr10 76494531 0 0 0.0 0 +chr10 76521841 0 0 0.0 0 +chr10 76939762 0 0 0.0 0 +chr10 76949384 0 0 0.0 0 +chr10 76966276 0 0 0.0 0 +chr10 76967157 0 0 0.0 0 +chr10 77000228 0 0 0.0 0 +chr10 77267287 0 0 0.0 0 +chr10 77378957 0 0 0.0 0 +chr10 77462785 0 0 0.0 0 +chr10 77599630 0 0 0.0 0 +chr10 77778710 0 0 0.0 0 +chr10 78071624 0 0 0.0 0 +chr10 78130090 0 0 0.0 0 +chr10 78135487 0 0 0.0 0 +chr10 78137280 0 0 0.0 0 +chr10 78185549 0 0 0.0 0 +chr10 78187649 0 0 0.0 0 +chr10 78251034 0 0 0.0 0 +chr10 78255244 0 0 0.0 0 +chr10 78270085 0 0 0.0 0 +chr10 78320266 0 0 0.0 0 +chr10 78336205 0 0 0.0 0 +chr10 78359532 0 0 0.0 0 +chr10 78522112 0 0 0.0 0 +chr10 78622605 0 0 0.0 0 +chr10 78734121 0 0 0.0 0 +chr10 78802756 0 0 0.0 0 +chr10 78865718 0 0 0.0 0 +chr10 78866421 0 0 0.0 0 +chr10 78877891 0 0 0.0 0 +chr10 78896592 0 0 0.0 0 +chr10 78915609 0 0 0.0 0 +chr10 78923707 0 0 0.0 0 +chr10 79011847 0 0 0.0 0 +chr10 79075225 0 0 0.0 0 +chr10 79082015 0 0 0.0 0 +chr10 79104385 0 0 0.0 0 +chr10 79104721 0 0 0.0 0 +chr10 79144342 0 0 0.0 0 +chr10 79168193 0 0 0.0 0 +chr10 79177613 0 0 0.0 0 +chr10 79193193 0 0 0.0 0 +chr10 79337970 0 0 0.0 0 +chr10 79438907 0 0 0.0 0 +chr10 79491424 0 0 0.0 0 +chr10 79571684 0 0 0.0 0 +chr10 79770144 0 0 0.0 0 +chr10 79868829 0 0 0.0 0 +chr10 80051276 0 0 0.0 0 +chr10 80089680 0 1 0.0132 0 +chr10 80161170 0 0 0.0 0 +chr10 80315769 0 0 0.0 0 +chr10 80357819 0 0 0.0 0 +chr10 80369005 0 0 0.0 0 +chr10 80417389 0 0 0.0 0 +chr10 80469476 0 0 0.0 0 +chr10 80599648 0 0 0.0 0 +chr10 80802566 0 0 0.0 0 +chr10 80816376 0 0 0.0 0 +chr10 80841620 0 0 0.0 0 +chr10 80988059 0 0 0.0 0 +chr10 81026026 0 0 0.0 0 +chr10 81205643 0 0 0.0 0 +chr10 81279233 0 0 0.0 0 +chr10 81287691 0 0 0.0 0 +chr10 81417534 0 0 0.0 0 +chr10 81612924 0 0 0.0 0 +chr10 81831741 0 0 0.0 0 +chr10 81843561 0 0 0.0 0 +chr10 81898358 0 0 0.0 0 +chr10 81937845 0 0 0.0 0 +chr10 82247121 0 0 0.0 0 +chr10 82393761 0 0 0.0 0 +chr10 82394462 0 0 0.0 0 +chr10 82468239 0 0 0.0 0 +chr10 82477754 0 0 0.0 0 +chr10 82610146 0 0 0.0 0 +chr10 82724534 0 0 0.0 0 +chr10 82833926 0 0 0.0 0 +chr10 83074896 0 0 0.0 0 +chr10 83660979 0 0 0.0 0 +chr10 83752698 0 0 0.0 0 +chr10 83834158 0 0 0.0 0 +chr10 83861171 0 0 0.0 0 +chr10 83879006 0 0 0.0 0 +chr10 83915600 0 0 0.0 0 +chr10 84034326 0 0 0.0 0 +chr10 84146422 0 0 0.0 0 +chr10 84295559 0 0 0.0 0 +chr10 84299539 0 0 0.0 0 +chr10 84393566 0 0 0.0 0 +chr10 84408680 0 0 0.0 0 +chr10 84415892 0 0 0.0 0 +chr10 84510567 0 0 0.0 0 +chr10 84584759 0 0 0.0 0 +chr10 84815831 0 0 0.0 0 +chr10 84885640 0 0 0.0 0 +chr10 84918913 0 0 0.0 0 +chr10 84925554 0 0 0.0 0 +chr10 84997463 0 0 0.0 0 +chr10 85101307 0 0 0.0 0 +chr10 85120803 0 0 0.0 0 +chr10 85136206 0 0 0.0 0 +chr10 85149398 0 0 0.0 0 +chr10 85222496 0 0 0.0 0 +chr10 85385090 0 0 0.0 0 +chr10 85585045 0 0 0.0 0 +chr10 85777051 0 0 0.0 0 +chr10 85867179 0 0 0.0 0 +chr10 86020579 0 0 0.0 0 +chr10 86058988 0 0 0.0 0 +chr10 86349000 0 0 0.0 0 +chr10 86847606 0 0 0.0 0 +chr10 86882722 0 0 0.0 0 +chr10 86884716 0 0 0.0 0 +chr10 87017880 0 0 0.0 0 +chr10 87292293 0 0 0.0 0 +chr10 87445681 0 0 0.0 0 +chr10 87530495 0 0 0.0 0 +chr10 87548924 0 0 0.0 0 +chr10 87557346 0 0 0.0 0 +chr10 87566461 0 0 0.0 0 +chr10 87623040 0 0 0.0 0 +chr10 87848267 0 0 0.0 0 +chr10 87887678 0 0 0.0 0 +chr10 88097497 0 0 0.0 0 +chr10 88270197 0 0 0.0 0 +chr10 88303145 0 0 0.0 0 +chr10 88312298 0 0 0.0 0 +chr10 88326216 0 0 0.0 0 +chr10 88329314 0 0 0.0 0 +chr10 88397978 0 0 0.0 0 +chr10 88616537 0 0 0.0 0 +chr10 88617520 0 0 0.0 0 +chr10 88647531 0 0 0.0 0 +chr10 88744537 0 0 0.0 0 +chr10 88937589 0 0 0.0 0 +chr10 89134740 0 0 0.0 0 +chr10 89154940 0 0 0.0 0 +chr10 89207225 0 0 0.0 0 +chr10 89341048 0 0 0.0 0 +chr10 89352644 0 0 0.0 0 +chr10 89555293 0 0 0.0 0 +chr10 89556978 0 0 0.0 0 +chr10 89690618 0 0 0.0 0 +chr10 89815323 0 0 0.0 0 +chr10 89941143 0 0 0.0 0 +chr10 89951348 0 0 0.0 0 +chr10 89951902 0 0 0.0 0 +chr10 90163324 0 0 0.0 0 +chr10 90306193 0 0 0.0 0 +chr10 90403217 0 0 0.0 0 +chr10 90563433 0 0 0.0 0 +chr10 90685539 0 0 0.0 0 +chr10 90738365 0 0 0.0 0 +chr10 90924192 0 0 0.0 0 +chr10 91081460 0 0 0.0 0 +chr10 91167138 1 53 0.8154 1 +chr10 91185245 0 0 0.0 0 +chr10 91232814 0 0 0.0 0 +chr10 91577057 0 0 0.0 0 +chr10 91658186 0 0 0.0 0 +chr10 91812555 0 0 0.0 0 +chr10 91860970 0 0 0.0 0 +chr10 92074583 0 0 0.0 0 +chr10 92297620 0 1 0.0149 0 +chr10 92378636 0 0 0.0 0 +chr10 92417940 0 0 0.0 0 +chr10 92774812 0 0 0.0 0 +chr10 93065160 0 0 0.0 0 +chr10 93225847 0 0 0.0 0 +chr10 93446286 0 0 0.0 0 +chr10 93494788 0 1 0.0217 0 +chr10 93595511 0 0 0.0 0 +chr10 93664252 0 0 0.0 0 +chr10 93706810 0 0 0.0 0 +chr10 94015593 0 0 0.0 0 +chr10 94097983 0 0 0.0 0 +chr10 94128843 0 0 0.0 0 +chr10 94139713 0 0 0.0 0 +chr10 94179767 0 0 0.0 0 +chr10 94459502 0 0 0.0 0 +chr10 94482199 0 0 0.0 0 +chr10 94574305 0 0 0.0 0 +chr10 94668567 0 0 0.0 0 +chr10 94693352 0 0 0.0 0 +chr10 94743883 0 0 0.0 0 +chr10 94783300 0 0 0.0 0 +chr10 95057945 0 0 0.0 0 +chr10 95093316 0 0 0.0 0 +chr10 95096430 0 0 0.0 0 +chr10 95168845 0 0 0.0 0 +chr10 95204932 0 0 0.0 0 +chr10 95310860 0 0 0.0 0 +chr10 95327198 0 0 0.0 0 +chr10 95445083 3 35 0.4861 1 +chr10 95461335 0 0 0.0 0 +chr10 95515843 0 0 0.0 0 +chr10 95569230 0 0 0.0 0 +chr10 95745918 0 0 0.0 0 +chr10 95925895 0 0 0.0 0 +chr10 96075308 0 0 0.0 0 +chr10 96174868 0 0 0.0 0 +chr10 96373894 0 0 0.0 0 +chr10 96463191 0 0 0.0 0 +chr10 96632476 0 0 0.0 0 +chr10 96645410 0 0 0.0 0 +chr10 96672119 0 0 0.0 0 +chr10 96679285 0 0 0.0 0 +chr10 96765560 0 0 0.0 0 +chr10 96859939 0 0 0.0 0 +chr10 97022235 0 0 0.0 0 +chr10 97027045 0 0 0.0 0 +chr10 97032757 1 32 0.3765 1 +chr10 97120908 0 0 0.0 0 +chr10 97311799 0 0 0.0 0 +chr10 97419783 0 0 0.0 0 +chr10 97811434 0 0 0.0 0 +chr10 97834619 0 0 0.0 0 +chr10 97893368 0 0 0.0 0 +chr10 98050495 0 0 0.0 0 +chr10 98109241 0 0 0.0 0 +chr10 98301538 0 0 0.0 0 +chr10 98421624 0 0 0.0 0 +chr10 98528258 0 0 0.0 0 +chr10 98605941 0 0 0.0 0 +chr10 98815549 0 0 0.0 0 +chr10 98966546 0 0 0.0 0 +chr10 99068182 0 0 0.0 0 +chr10 99099873 0 0 0.0 0 +chr10 99133034 0 0 0.0 0 +chr10 99196103 0 0 0.0 0 +chr10 99265607 0 0 0.0 0 +chr10 99326899 0 0 0.0 0 +chr10 99330880 0 0 0.0 0 +chr10 99385500 0 0 0.0 0 +chr10 99569114 0 0 0.0 0 +chr10 99599493 0 0 0.0 0 +chr10 99699349 0 0 0.0 0 +chr10 99975972 0 0 0.0 0 +chr10 100151852 0 0 0.0 0 +chr10 100197405 0 0 0.0 0 +chr10 100603439 0 0 0.0 0 +chr10 100701211 0 0 0.0 0 +chr10 100709848 0 0 0.0 0 +chr10 100913701 0 0 0.0 0 +chr10 100970019 0 0 0.0 0 +chr10 100999666 0 0 0.0 0 +chr10 101017001 0 0 0.0 0 +chr10 101052038 0 0 0.0 0 +chr10 101533373 0 0 0.0 0 +chr10 101582121 0 0 0.0 0 +chr10 101860632 0 0 0.0 0 +chr10 101972037 0 0 0.0 0 +chr10 102100912 0 0 0.0 0 +chr10 102124907 0 0 0.0 0 +chr10 102128706 0 0 0.0 0 +chr10 102229898 0 0 0.0 0 +chr10 102286806 0 0 0.0 0 +chr10 102398197 0 0 0.0 0 +chr10 102495854 0 0 0.0 0 +chr10 102534611 0 0 0.0 0 +chr10 102768479 0 0 0.0 0 +chr10 102793658 0 0 0.0 0 +chr10 102919985 0 0 0.0 0 +chr10 103104423 0 0 0.0 0 +chr10 103397817 0 0 0.0 0 +chr10 103433529 0 0 0.0 0 +chr10 103445416 0 0 0.0 0 +chr10 103568134 0 0 0.0 0 +chr10 103654488 0 0 0.0 0 +chr10 103659189 0 0 0.0 0 +chr10 103669281 0 0 0.0 0 +chr10 103728093 0 0 0.0 0 +chr10 103739144 0 0 0.0 0 +chr10 103791098 0 0 0.0 0 +chr10 103925795 0 0 0.0 0 +chr10 104070190 0 0 0.0 0 +chr10 104105283 0 0 0.0 0 +chr10 104219620 0 0 0.0 0 +chr10 104323570 0 0 0.0 0 +chr10 104348641 0 1 0.0135 0 +chr10 104434142 0 0 0.0 0 +chr10 104542928 0 0 0.0 0 +chr10 104655799 0 0 0.0 0 +chr10 104677809 0 0 0.0 0 +chr10 104681311 3 64 0.881 1 +chr10 104778220 0 0 0.0 0 +chr10 104791024 0 0 0.0 0 +chr10 104871084 0 0 0.0 0 +chr10 104876643 0 0 0.0 0 +chr10 104971895 0 0 0.0 0 +chr10 105002387 0 0 0.0 0 +chr10 105047899 0 0 0.0 0 +chr10 105073397 0 0 0.0 0 +chr10 105090921 0 0 0.0 0 +chr10 105364137 0 0 0.0 0 +chr10 105367760 0 0 0.0 0 +chr10 105402806 0 0 0.0 0 +chr10 105511450 0 0 0.0 0 +chr10 105680308 0 0 0.0 0 +chr10 105775076 0 0 0.0 0 +chr10 105850187 0 0 0.0 0 +chr10 105954598 0 1 0.0154 0 +chr10 106207196 0 0 0.0 0 +chr10 106380929 0 0 0.0 0 +chr10 106494654 0 0 0.0 0 +chr10 106951437 0 0 0.0 0 +chr10 107082449 0 1 0.0156 0 +chr10 107190350 0 0 0.0 0 +chr10 107336886 0 0 0.0 0 +chr10 107340655 0 0 0.0 0 +chr10 107385309 0 0 0.0 0 +chr10 107432050 0 0 0.0 0 +chr10 107535768 0 0 0.0 0 +chr10 107667735 0 0 0.0 0 +chr10 107698662 0 0 0.0 0 +chr10 107737712 0 0 0.0 0 +chr10 107792345 0 0 0.0 0 +chr10 107816880 0 0 0.0 0 +chr10 107828914 0 0 0.0 0 +chr10 107852115 0 0 0.0 0 +chr10 107916409 0 0 0.0 0 +chr10 107950904 0 0 0.0 0 +chr10 107995350 0 0 0.0 0 +chr10 108039662 0 0 0.0 0 +chr10 108202292 0 0 0.0 0 +chr10 108488001 0 0 0.0 0 +chr10 108609589 0 0 0.0 0 +chr10 108614226 0 0 0.0 0 +chr10 108615093 0 0 0.0 0 +chr10 108643490 0 0 0.0 0 +chr10 108817750 0 0 0.0 0 +chr10 108842196 0 0 0.0 0 +chr10 108849311 0 0 0.0 0 +chr10 108892498 0 0 0.0 0 +chr10 109181732 0 1 0.0143 0 +chr10 109368443 0 0 0.0 0 +chr10 109387532 0 0 0.0 0 +chr10 109427183 0 0 0.0 0 +chr10 109601880 0 0 0.0 0 +chr10 109654626 0 0 0.0 0 +chr10 109690932 0 1 0.0217 0 +chr10 109852848 0 0 0.0 0 +chr10 110016443 0 0 0.0 0 +chr10 110035581 0 0 0.0 0 +chr10 110055350 0 0 0.0 0 +chr10 110089487 0 0 0.0 0 +chr10 110160311 0 0 0.0 0 +chr10 110282604 0 0 0.0 0 +chr10 110333774 0 0 0.0 0 +chr10 110344902 0 0 0.0 0 +chr10 110500312 0 0 0.0 0 +chr10 110678589 0 1 0.012 0 +chr10 110805781 0 0 0.0 0 +chr10 110817163 0 0 0.0 0 +chr10 110887713 0 0 0.0 0 +chr10 110890579 0 0 0.0 0 +chr10 111108145 0 0 0.0 0 +chr10 111116066 0 1 0.0135 0 +chr10 111157032 0 0 0.0 0 +chr10 111186503 0 0 0.0 0 +chr10 111332825 0 0 0.0 0 +chr10 111394259 0 0 0.0 0 +chr10 111434115 0 0 0.0 0 +chr10 111485862 0 0 0.0 0 +chr10 111558412 0 0 0.0 0 +chr10 111563728 1 3 0.0652 1 +chr10 111637975 0 0 0.0 0 +chr10 111825228 0 0 0.0 0 +chr10 111904674 0 0 0.0 0 +chr10 111978431 0 0 0.0 0 +chr10 112079663 0 0 0.0 0 +chr10 112198773 0 0 0.0 0 +chr10 112269783 0 0 0.0 0 +chr10 112299745 0 0 0.0 0 +chr10 112309201 0 0 0.0 0 +chr10 112356745 0 0 0.0 0 +chr10 112398859 0 0 0.0 0 +chr10 112533193 0 0 0.0 0 +chr10 112557847 0 0 0.0 0 +chr10 112599034 0 0 0.0 0 +chr10 112614376 0 0 0.0 0 +chr10 112737934 0 0 0.0 0 +chr10 112743595 0 0 0.0 0 +chr10 112773577 0 0 0.0 0 +chr10 112874935 0 0 0.0 0 +chr10 112908689 0 0 0.0 0 +chr10 112958724 0 0 0.0 0 +chr10 113081171 0 1 0.0156 0 +chr10 113157636 0 0 0.0 0 +chr10 113325018 0 0 0.0 0 +chr10 113354067 0 0 0.0 0 +chr10 113363033 0 0 0.0 0 +chr10 113588350 0 0 0.0 0 +chr10 113601066 0 0 0.0 0 +chr10 113623213 0 0 0.0 0 +chr10 113644711 0 0 0.0 0 +chr10 113952362 0 0 0.0 0 +chr10 114076861 0 0 0.0 0 +chr10 114245588 0 2 0.0263 0 +chr10 114288855 0 0 0.0 0 +chr10 114296358 0 0 0.0 0 +chr10 114379873 0 0 0.0 0 +chr10 114473645 0 0 0.0 0 +chr10 114475313 0 0 0.0 0 +chr10 114517398 0 0 0.0 0 +chr10 114530874 0 0 0.0 0 +chr10 114592722 0 0 0.0 0 +chr10 114599381 0 0 0.0 0 +chr10 114657236 0 0 0.0 0 +chr10 114809973 0 0 0.0 0 +chr10 114871358 0 0 0.0 0 +chr10 114871652 0 0 0.0 0 +chr10 115007122 0 0 0.0 0 +chr10 115116263 0 0 0.0 0 +chr10 115521842 0 1 0.0179 0 +chr10 115522318 0 0 0.0 0 +chr10 115616960 0 0 0.0 0 +chr10 115763628 0 0 0.0 0 +chr10 115881475 0 0 0.0 0 +chr10 115950467 0 0 0.0 0 +chr10 116109837 0 0 0.0 0 +chr10 116111781 0 0 0.0 0 +chr10 116113937 0 0 0.0 0 +chr10 116309260 0 0 0.0 0 +chr10 116406668 0 0 0.0 0 +chr10 116444085 0 0 0.0 0 +chr10 116533881 0 0 0.0 0 +chr10 116622015 0 0 0.0 0 +chr10 116738948 0 0 0.0 0 +chr10 116871285 0 0 0.0 0 +chr10 116905127 0 0 0.0 0 +chr10 117000244 0 0 0.0 0 +chr10 117011363 0 0 0.0 0 +chr10 117088829 0 0 0.0 0 +chr10 117404556 0 0 0.0 0 +chr10 117613220 0 0 0.0 0 +chr10 117671417 0 0 0.0 0 +chr10 117679134 0 0 0.0 0 +chr10 117732442 0 0 0.0 0 +chr10 117763773 0 0 0.0 0 +chr10 117879798 0 1 0.0125 0 +chr10 117904530 0 0 0.0 0 +chr10 118099099 0 0 0.0 0 +chr10 118352329 0 0 0.0 0 +chr10 118386541 0 0 0.0 0 +chr10 118450516 0 0 0.0 0 +chr10 118603454 0 0 0.0 0 +chr10 118652145 0 0 0.0 0 +chr10 118660320 0 0 0.0 0 +chr10 118762922 0 0 0.0 0 +chr10 118764186 0 0 0.0 0 +chr10 118772244 0 0 0.0 0 +chr10 118800773 0 0 0.0 0 +chr10 119008790 0 0 0.0 0 +chr10 119009013 0 0 0.0 0 +chr10 119280121 0 0 0.0 0 +chr10 119450268 0 0 0.0 0 +chr10 119513718 0 0 0.0 0 +chr10 119748003 0 0 0.0 0 +chr10 119771990 0 0 0.0 0 +chr10 120146638 0 0 0.0 0 +chr10 120188664 0 0 0.0 0 +chr10 120283469 0 0 0.0 0 +chr10 120459702 0 0 0.0 0 +chr10 120764739 0 0 0.0 0 +chr10 120811397 0 0 0.0 0 +chr10 120841958 0 0 0.0 0 +chr10 120865847 0 0 0.0 0 +chr10 120889648 0 0 0.0 0 +chr10 121025568 0 0 0.0 0 +chr10 121047412 0 0 0.0 0 +chr10 121133958 0 0 0.0 0 +chr10 121211278 0 0 0.0 0 +chr10 121271201 0 0 0.0 0 +chr10 121458558 0 0 0.0 0 +chr10 121476379 0 0 0.0 0 +chr10 121617139 0 0 0.0 0 +chr10 121633504 0 0 0.0 0 +chr10 121655520 0 0 0.0 0 +chr10 121805454 0 0 0.0 0 +chr10 122091893 0 0 0.0 0 +chr10 122159563 0 0 0.0 0 +chr10 122240222 0 0 0.0 0 +chr10 122242440 0 1 0.0179 0 +chr10 122252398 0 0 0.0 0 +chr10 122270442 0 0 0.0 0 +chr10 122281932 0 0 0.0 0 +chr10 122346617 0 0 0.0 0 +chr10 122399401 0 0 0.0 0 +chr10 122419913 0 0 0.0 0 +chr10 122503259 0 0 0.0 0 +chr10 122505305 0 0 0.0 0 +chr10 122537470 0 0 0.0 0 +chr10 122587574 0 0 0.0 0 +chr10 122590384 0 0 0.0 0 +chr10 122625172 0 0 0.0 0 +chr10 122675050 0 0 0.0 0 +chr10 122880955 0 0 0.0 0 +chr10 122886786 0 0 0.0 0 +chr10 122934873 0 0 0.0 0 +chr10 123058804 0 0 0.0 0 +chr10 123072691 0 0 0.0 0 +chr10 123132107 0 0 0.0 0 +chr10 123213593 0 0 0.0 0 +chr10 123413645 0 0 0.0 0 +chr10 123456957 0 0 0.0 0 +chr10 123548612 0 0 0.0 0 +chr10 123554620 0 0 0.0 0 +chr10 123559543 0 0 0.0 0 +chr10 123573789 0 0 0.0 0 +chr10 123601627 0 0 0.0 0 +chr10 123816301 0 0 0.0 0 +chr10 123821457 0 0 0.0 0 +chr10 123861580 0 0 0.0 0 +chr10 123891997 0 0 0.0 0 +chr10 123953608 0 0 0.0 0 +chr10 123980291 0 0 0.0 0 +chr10 124102279 0 0 0.0 0 +chr10 124128190 0 0 0.0 0 +chr10 124132592 0 1 0.025 0 +chr10 124269020 0 0 0.0 0 +chr10 124300769 0 0 0.0 0 +chr10 124352113 0 0 0.0 0 +chr10 124354010 0 0 0.0 0 +chr10 124393395 0 0 0.0 0 +chr10 124441848 0 0 0.0 0 +chr10 124497891 0 0 0.0 0 +chr10 124510994 0 0 0.0 0 +chr10 124518443 0 0 0.0 0 +chr10 124627729 0 1 0.0294 0 +chr10 124639644 0 0 0.0 0 +chr10 124733704 0 0 0.0 0 +chr10 124939295 0 0 0.0 0 +chr10 124996821 0 0 0.0 0 +chr10 125131399 0 0 0.0 0 +chr10 125147370 0 0 0.0 0 +chr10 125184273 0 0 0.0 0 +chr10 125188694 0 0 0.0 0 +chr10 125193653 0 0 0.0 0 +chr10 125340574 0 0 0.0 0 +chr10 125408436 0 0 0.0 0 +chr10 125410087 0 0 0.0 0 +chr10 125439670 0 0 0.0 0 +chr10 125447338 0 0 0.0 0 +chr10 125472151 0 0 0.0 0 +chr10 125519421 0 0 0.0 0 +chr10 125574832 0 0 0.0 0 +chr10 125674730 0 0 0.0 0 +chr10 125793344 0 0 0.0 0 +chr10 125803089 0 0 0.0 0 +chr10 125821824 0 0 0.0 0 +chr10 125900286 0 0 0.0 0 +chr10 125952940 0 0 0.0 0 +chr10 126016311 0 0 0.0 0 +chr10 126064532 0 0 0.0 0 +chr10 126066056 0 0 0.0 0 +chr10 126123750 0 0 0.0 0 +chr10 126126221 0 0 0.0 0 +chr10 126215185 0 0 0.0 0 +chr10 126483553 0 0 0.0 0 +chr10 126519150 0 0 0.0 0 +chr10 126551642 0 1 0.0154 0 +chr10 126713779 0 0 0.0 0 +chr10 126735149 0 0 0.0 0 +chr10 126850947 0 0 0.0 0 +chr10 126890572 0 0 0.0 0 +chr10 126893145 0 1 0.0159 0 +chr10 126905031 0 0 0.0 0 +chr10 126907368 0 0 0.0 0 +chr10 126928436 0 0 0.0 0 +chr10 127007442 0 0 0.0 0 +chr10 127431626 0 0 0.0 0 +chr10 127439644 0 0 0.0 0 +chr10 127828236 0 0 0.0 0 +chr10 127841484 0 0 0.0 0 +chr10 127969059 0 0 0.0 0 +chr10 128002167 0 0 0.0 0 +chr10 128251564 0 0 0.0 0 +chr10 128281032 0 0 0.0 0 +chr10 128382408 0 0 0.0 0 +chr10 128568198 0 0 0.0 0 +chr10 128632331 0 0 0.0 0 +chr10 128711428 0 0 0.0 0 +chr10 128818005 0 0 0.0 0 +chr10 128858235 0 0 0.0 0 +chr10 128964262 0 0 0.0 0 +chr10 129011970 0 0 0.0 0 +chr10 129101860 0 0 0.0 0 +chr10 129112063 0 0 0.0 0 +chr10 129462578 0 0 0.0 0 +chr10 129521498 0 0 0.0 0 +chr10 129864753 0 0 0.0 0 +chr10 130017687 0 0 0.0 0 +chr10 130061434 0 0 0.0 0 +chr10 130078428 0 0 0.0 0 +chr10 130126524 0 0 0.0 0 +chr10 130136552 0 0 0.0 0 +chr10 130186674 0 0 0.0 0 +chr10 130189792 0 1 0.0135 0 +chr10 130261905 0 0 0.0 0 +chr10 130266608 0 0 0.0 0 +chr10 130391173 0 0 0.0 0 +chr10 130464920 0 0 0.0 0 +chr10 130490413 0 0 0.0 0 +chr10 130544563 0 0 0.0 0 +chr10 130577401 0 0 0.0 0 +chr10 130678224 0 0 0.0 0 +chr10 130696224 0 0 0.0 0 +chr10 130774561 0 0 0.0 0 +chr10 130837244 0 0 0.0 0 +chr10 131034953 0 0 0.0 0 +chr10 131178313 0 0 0.0 0 +chr10 131246688 0 0 0.0 0 +chr10 131337223 0 0 0.0 0 +chr10 131406488 0 0 0.0 0 +chr10 131413733 0 0 0.0 0 +chr10 131461000 0 0 0.0 0 +chr10 131483104 0 0 0.0 0 +chr10 131511778 0 0 0.0 0 +chr10 131580725 0 0 0.0 0 +chr10 131585918 0 0 0.0 0 +chr10 131692749 0 0 0.0 0 +chr10 131703392 0 0 0.0 0 +chr10 131704109 0 0 0.0 0 +chr10 131708059 0 0 0.0 0 +chr10 131727133 0 0 0.0 0 +chr10 131782099 0 0 0.0 0 +chr10 131983222 0 0 0.0 0 +chr10 131988345 0 0 0.0 0 +chr10 132041308 0 0 0.0 0 +chr10 132061926 0 0 0.0 0 +chr10 132076438 0 1 0.0156 0 +chr10 132096465 0 0 0.0 0 +chr10 132132728 0 0 0.0 0 +chr10 132181880 0 0 0.0 0 +chr10 132187248 0 0 0.0 0 +chr10 132196707 0 1 0.0182 0 +chr10 132254568 0 0 0.0 0 +chr10 132254777 0 0 0.0 0 +chr10 132336098 0 0 0.0 0 +chr10 132355367 0 1 0.0233 0 +chr10 132358835 0 1 1.0 0 +chr10 132471478 0 0 0.0 0 +chr10 132540423 0 0 0.0 0 +chr10 132654484 0 0 0.0 0 +chr10 132707869 0 0 0.0 0 +chr10 132730516 0 0 0.0 0 +chr10 132740985 0 0 0.0 0 +chr10 132812177 0 0 0.0 0 +chr10 132862043 0 0 0.0 0 +chr10 132899985 0 0 0.0 0 +chr10 132989727 0 0 0.0 0 +chr10 133077623 0 0 0.0 0 +chr10 133248661 0 0 0.0 0 +chr10 133462866 0 0 0.0 0 +chr10 133510438 0 0 0.0 0 +chr10_GL383545v1_alt 144202 0 0 0.0 0 +chr10_GL383546v1_alt 56815 0 0 0.0 0 +chr10_GL383546v1_alt 200431 0 0 0.0 0 +chr10_GL383546v1_alt 265750 0 0 0.0 0 +chr10_KI270824v1_alt 145641 0 0 0.0 0 +chr11 211459 0 0 0.0 0 +chr11 285156 0 0 0.0 0 +chr11 297569 1 3 0.0556 1 +chr11 344349 0 0 0.0 0 +chr11 384670 0 0 0.0 0 +chr11 410471 0 0 0.0 0 +chr11 412701 1 28 0.7 1 +chr11 451033 0 0 0.0 0 +chr11 478033 0 0 0.0 0 +chr11 533267 0 0 0.0 0 +chr11 555079 0 0 0.0 0 +chr11 561981 0 0 0.0 0 +chr11 606264 0 0 0.0 0 +chr11 719693 0 0 0.0 0 +chr11 748810 0 1 0.0114 0 +chr11 769171 0 0 0.0 0 +chr11 811823 0 0 0.0 0 +chr11 922921 0 0 0.0 0 +chr11 1039065 1 28 0.35 1 +chr11 1070969 0 0 0.0 0 +chr11 1096295 0 0 0.0 0 +chr11 1099657 0 0 0.0 0 +chr11 1219583 0 0 0.0 0 +chr11 1224956 0 0 0.0 0 +chr11 1297127 0 0 0.0 0 +chr11 1347706 0 0 0.0 0 +chr11 1407280 0 0 0.0 0 +chr11 1427304 0 0 0.0 0 +chr11 1459218 0 0 0.0 0 +chr11 1483362 0 0 0.0 0 +chr11 1500723 0 0 0.0 0 +chr11 1571398 0 1 0.0125 0 +chr11 1581934 0 0 0.0 0 +chr11 1740690 0 0 0.0 0 +chr11 1767623 0 0 0.0 0 +chr11 1832079 0 0 0.0 0 +chr11 1891632 0 0 0.0 0 +chr11 1919990 0 0 0.0 0 +chr11 1924858 0 0 0.0 0 +chr11 1999985 0 0 0.0 0 +chr11 2002631 0 0 0.0 0 +chr11 2033988 0 0 0.0 0 +chr11 2069555 0 0 0.0 0 +chr11 2368269 0 0 0.0 0 +chr11 2372593 0 0 0.0 0 +chr11 2373853 0 0 0.0 0 +chr11 2383316 0 0 0.0 0 +chr11 2415341 0 0 0.0 0 +chr11 2498555 0 0 0.0 0 +chr11 2522866 0 0 0.0 0 +chr11 2561128 0 0 0.0 0 +chr11 2585479 0 0 0.0 0 +chr11 2663876 0 0 0.0 0 +chr11 2740521 0 0 0.0 0 +chr11 2748302 0 0 0.0 0 +chr11 2791211 0 0 0.0 0 +chr11 2907152 0 0 0.0 0 +chr11 2929784 0 0 0.0 0 +chr11 3110176 0 0 0.0 0 +chr11 3137938 0 0 0.0 0 +chr11 3149209 0 0 0.0 0 +chr11 3209309 0 0 0.0 0 +chr11 3221158 0 0 0.0 0 +chr11 3246036 0 0 0.0 0 +chr11 3354600 0 0 0.0 0 +chr11 3383065 0 0 0.0 0 +chr11 3418421 0 0 0.0 0 +chr11 3422836 0 0 0.0 0 +chr11 3480271 0 0 0.0 0 +chr11 3510297 0 0 0.0 0 +chr11 3553862 0 0 0.0 0 +chr11 3623002 0 0 0.0 0 +chr11 3664932 0 0 0.0 0 +chr11 3665553 0 0 0.0 0 +chr11 3687182 0 0 0.0 0 +chr11 3763263 0 0 0.0 0 +chr11 3792876 0 0 0.0 0 +chr11 3816651 0 0 0.0 0 +chr11 3846165 0 0 0.0 0 +chr11 4019985 0 0 0.0 0 +chr11 4179058 0 0 0.0 0 +chr11 4221379 0 0 0.0 0 +chr11 4389343 0 0 0.0 0 +chr11 4418346 0 0 0.0 0 +chr11 4458386 0 0 0.0 0 +chr11 4503292 0 0 0.0 0 +chr11 4651295 0 0 0.0 0 +chr11 4699258 0 0 0.0 0 +chr11 4826091 0 0 0.0 0 +chr11 4873454 0 0 0.0 0 +chr11 4924829 0 0 0.0 0 +chr11 5059674 0 0 0.0 0 +chr11 5170488 0 0 0.0 0 +chr11 5518510 0 0 0.0 0 +chr11 5795577 0 0 0.0 0 +chr11 5897686 0 0 0.0 0 +chr11 5938181 0 0 0.0 0 +chr11 5991949 0 0 0.0 0 +chr11 6015752 0 0 0.0 0 +chr11 6025438 0 0 0.0 0 +chr11 6137622 0 1 0.0182 0 +chr11 6336419 0 0 0.0 0 +chr11 6384478 0 0 0.0 0 +chr11 6455075 0 0 0.0 0 +chr11 6465842 0 0 0.0 0 +chr11 6468802 0 0 0.0 0 +chr11 6481118 0 0 0.0 0 +chr11 6489320 0 0 0.0 0 +chr11 6565519 0 0 0.0 0 +chr11 6667021 0 0 0.0 0 +chr11 6676150 0 1 0.0217 0 +chr11 6939825 0 0 0.0 0 +chr11 6954536 0 0 0.0 0 +chr11 7084554 0 0 0.0 0 +chr11 7181710 0 0 0.0 0 +chr11 7216431 0 0 0.0 0 +chr11 7249277 0 0 0.0 0 +chr11 7282477 0 0 0.0 0 +chr11 7435478 0 0 0.0 0 +chr11 7471301 0 0 0.0 0 +chr11 7541542 0 0 0.0 0 +chr11 7691782 0 0 0.0 0 +chr11 7754321 0 0 0.0 0 +chr11 7755784 0 0 0.0 0 +chr11 7786422 0 0 0.0 0 +chr11 7851556 0 0 0.0 0 +chr11 8031720 0 0 0.0 0 +chr11 8081661 0 0 0.0 0 +chr11 8097944 0 0 0.0 0 +chr11 8116807 0 0 0.0 0 +chr11 8251571 0 0 0.0 0 +chr11 8316088 0 0 0.0 0 +chr11 8358053 0 0 0.0 0 +chr11 8907153 0 0 0.0 0 +chr11 8924614 0 0 0.0 0 +chr11 8938061 0 0 0.0 0 +chr11 9050327 0 0 0.0 0 +chr11 9169923 0 0 0.0 0 +chr11 9320990 0 0 0.0 0 +chr11 9364042 0 0 0.0 0 +chr11 9383313 0 0 0.0 0 +chr11 9394618 0 0 0.0 0 +chr11 9406264 0 0 0.0 0 +chr11 9489692 0 0 0.0 0 +chr11 9684606 0 0 0.0 0 +chr11 10105919 0 0 0.0 0 +chr11 10259016 0 0 0.0 0 +chr11 10309384 0 0 0.0 0 +chr11 10325411 0 0 0.0 0 +chr11 10655181 0 0 0.0 0 +chr11 10689748 0 0 0.0 0 +chr11 10858369 0 0 0.0 0 +chr11 10898649 0 0 0.0 0 +chr11 11292512 0 0 0.0 0 +chr11 11384708 0 0 0.0 0 +chr11 11486836 0 0 0.0 0 +chr11 11492398 0 0 0.0 0 +chr11 11531874 0 0 0.0 0 +chr11 11567822 0 0 0.0 0 +chr11 11569642 0 0 0.0 0 +chr11 11571966 0 0 0.0 0 +chr11 11654161 0 0 0.0 0 +chr11 11781317 0 0 0.0 0 +chr11 11808019 0 0 0.0 0 +chr11 11819420 0 0 0.0 0 +chr11 11918184 0 0 0.0 0 +chr11 12346133 0 0 0.0 0 +chr11 12352969 0 0 0.0 0 +chr11 12384887 0 0 0.0 0 +chr11 12442955 1 22 0.4783 1 +chr11 12513255 0 0 0.0 0 +chr11 12516643 0 0 0.0 0 +chr11 12553740 0 0 0.0 0 +chr11 12709122 0 0 0.0 0 +chr11 12792570 0 0 0.0 0 +chr11 12938969 0 0 0.0 0 +chr11 12967370 0 0 0.0 0 +chr11 13129734 0 0 0.0 0 +chr11 13156251 0 0 0.0 0 +chr11 13222169 0 0 0.0 0 +chr11 13380975 0 0 0.0 0 +chr11 13427519 0 0 0.0 0 +chr11 13733709 0 0 0.0 0 +chr11 13826226 0 0 0.0 0 +chr11 13857032 0 0 0.0 0 +chr11 14036032 0 0 0.0 0 +chr11 14053019 0 0 0.0 0 +chr11 14090017 0 0 0.0 0 +chr11 14096657 0 0 0.0 0 +chr11 14124227 0 0 0.0 0 +chr11 14134906 0 0 0.0 0 +chr11 14233021 0 0 0.0 0 +chr11 14262744 0 0 0.0 0 +chr11 14361177 0 0 0.0 0 +chr11 14402484 0 0 0.0 0 +chr11 14424783 0 0 0.0 0 +chr11 14588583 0 0 0.0 0 +chr11 14669434 0 1 0.0238 0 +chr11 15040951 0 0 0.0 0 +chr11 15118475 0 0 0.0 0 +chr11 15135518 0 0 0.0 0 +chr11 15152794 0 0 0.0 0 +chr11 15172734 0 0 0.0 0 +chr11 15226544 0 0 0.0 0 +chr11 15237834 0 0 0.0 0 +chr11 15374937 0 0 0.0 0 +chr11 15423495 0 0 0.0 0 +chr11 15513460 0 0 0.0 0 +chr11 15666491 0 0 0.0 0 +chr11 15671252 0 0 0.0 0 +chr11 15675355 0 0 0.0 0 +chr11 15704945 0 0 0.0 0 +chr11 15820539 0 0 0.0 0 +chr11 15855476 0 0 0.0 0 +chr11 15882014 0 0 0.0 0 +chr11 15903153 0 0 0.0 0 +chr11 15905070 0 0 0.0 0 +chr11 15913502 0 0 0.0 0 +chr11 15940309 0 0 0.0 0 +chr11 16066803 0 0 0.0 0 +chr11 16604187 0 0 0.0 0 +chr11 16633576 0 0 0.0 0 +chr11 16760047 0 0 0.0 0 +chr11 16814083 0 0 0.0 0 +chr11 16872648 0 0 0.0 0 +chr11 16930239 0 0 0.0 0 +chr11 17008242 0 0 0.0 0 +chr11 17131314 0 0 0.0 0 +chr11 17154365 0 0 0.0 0 +chr11 17205878 0 0 0.0 0 +chr11 17223656 0 0 0.0 0 +chr11 17226807 0 0 0.0 0 +chr11 17364455 0 0 0.0 0 +chr11 17387099 0 0 0.0 0 +chr11 17407155 0 0 0.0 0 +chr11 17449364 0 1 0.0208 0 +chr11 17521791 0 0 0.0 0 +chr11 17570317 0 0 0.0 0 +chr11 17671510 0 0 0.0 0 +chr11 17781715 0 0 0.0 0 +chr11 17782597 0 0 0.0 0 +chr11 18013912 0 0 0.0 0 +chr11 18041335 0 0 0.0 0 +chr11 18332412 0 0 0.0 0 +chr11 18455857 2 15 0.5 1 +chr11 18488399 0 0 0.0 0 +chr11 18600903 0 0 0.0 0 +chr11 18626979 0 0 0.0 0 +chr11 18645213 0 0 0.0 0 +chr11 18796057 0 0 0.0 0 +chr11 18817369 0 0 0.0 0 +chr11 18936629 0 0 0.0 0 +chr11 19048669 0 0 0.0 0 +chr11 19071426 0 0 0.0 0 +chr11 19244769 0 0 0.0 0 +chr11 19247778 0 0 0.0 0 +chr11 19277545 0 0 0.0 0 +chr11 19285075 0 0 0.0 0 +chr11 19315128 0 0 0.0 0 +chr11 19315476 0 0 0.0 0 +chr11 19412215 0 0 0.0 0 +chr11 19494106 0 0 0.0 0 +chr11 19514388 0 0 0.0 0 +chr11 19526870 0 0 0.0 0 +chr11 19564156 0 0 0.0 0 +chr11 19639225 0 0 0.0 0 +chr11 19669404 0 0 0.0 0 +chr11 19729404 0 0 0.0 0 +chr11 19874913 0 0 0.0 0 +chr11 20036740 0 0 0.0 0 +chr11 20476477 0 0 0.0 0 +chr11 20545686 0 0 0.0 0 +chr11 20646880 0 0 0.0 0 +chr11 20707653 0 0 0.0 0 +chr11 20771754 0 0 0.0 0 +chr11 21084717 0 0 0.0 0 +chr11 21295029 0 0 0.0 0 +chr11 21393097 0 0 0.0 0 +chr11 21466791 0 0 0.0 0 +chr11 21806231 0 0 0.0 0 +chr11 21901740 0 0 0.0 0 +chr11 22187655 0 0 0.0 0 +chr11 22456897 0 0 0.0 0 +chr11 22541094 0 0 0.0 0 +chr11 22602944 0 0 0.0 0 +chr11 22748177 0 0 0.0 0 +chr11 22864353 0 2 0.1 0 +chr11 22929201 0 0 0.0 0 +chr11 22976104 0 0 0.0 0 +chr11 23034179 0 0 0.0 0 +chr11 23103152 0 0 0.0 0 +chr11 23563204 0 0 0.0 0 +chr11 23869671 0 0 0.0 0 +chr11 23982314 0 0 0.0 0 +chr11 24085824 0 0 0.0 0 +chr11 24115743 0 0 0.0 0 +chr11 24364300 0 0 0.0 0 +chr11 24527231 0 0 0.0 0 +chr11 24819429 0 0 0.0 0 +chr11 24921418 0 0 0.0 0 +chr11 25186192 0 0 0.0 0 +chr11 25377697 0 0 0.0 0 +chr11 25405924 0 0 0.0 0 +chr11 25475518 0 0 0.0 0 +chr11 25552564 0 0 0.0 0 +chr11 25571160 0 0 0.0 0 +chr11 25762454 0 0 0.0 0 +chr11 25941620 0 0 0.0 0 +chr11 26004803 0 0 0.0 0 +chr11 26343505 0 0 0.0 0 +chr11 26437374 0 0 0.0 0 +chr11 26595891 0 0 0.0 0 +chr11 26619700 0 0 0.0 0 +chr11 26640524 0 0 0.0 0 +chr11 26657611 0 0 0.0 0 +chr11 26671599 0 0 0.0 0 +chr11 26831738 0 0 0.0 0 +chr11 26865267 0 0 0.0 0 +chr11 27186087 0 0 0.0 0 +chr11 27232598 0 0 0.0 0 +chr11 27359725 0 0 0.0 0 +chr11 27371248 0 0 0.0 0 +chr11 27727822 0 0 0.0 0 +chr11 27827213 0 1 0.0185 0 +chr11 27844005 0 0 0.0 0 +chr11 27938184 0 0 0.0 0 +chr11 28229413 0 0 0.0 0 +chr11 28554671 0 0 0.0 0 +chr11 28896385 0 0 0.0 0 +chr11 29233030 0 0 0.0 0 +chr11 29316460 0 0 0.0 0 +chr11 29318329 0 0 0.0 0 +chr11 29414711 0 2 0.04 0 +chr11 29429676 0 0 0.0 0 +chr11 29688758 0 0 0.0 0 +chr11 29707687 0 0 0.0 0 +chr11 29929655 0 0 0.0 0 +chr11 29935650 0 0 0.0 0 +chr11 30189579 0 0 0.0 0 +chr11 30332574 0 0 0.0 0 +chr11 30466766 0 0 0.0 0 +chr11 30633733 0 0 0.0 0 +chr11 30703779 0 0 0.0 0 +chr11 30920119 0 0 0.0 0 +chr11 30931060 0 0 0.0 0 +chr11 30970983 0 0 0.0 0 +chr11 30978544 0 0 0.0 0 +chr11 31095632 0 0 0.0 0 +chr11 31179239 0 0 0.0 0 +chr11 31213478 0 0 0.0 0 +chr11 31230516 0 0 0.0 0 +chr11 31259108 0 0 0.0 0 +chr11 31334695 0 0 0.0 0 +chr11 31411011 0 0 0.0 0 +chr11 31535949 0 0 0.0 0 +chr11 31595573 0 0 0.0 0 +chr11 31982492 0 0 0.0 0 +chr11 32041416 0 0 0.0 0 +chr11 32138899 0 0 0.0 0 +chr11 32161065 0 0 0.0 0 +chr11 32203611 0 0 0.0 0 +chr11 32205771 0 0 0.0 0 +chr11 32398102 0 0 0.0 0 +chr11 32565814 0 0 0.0 0 +chr11 32738741 0 0 0.0 0 +chr11 32747692 0 0 0.0 0 +chr11 32793142 0 0 0.0 0 +chr11 33040915 0 0 0.0 0 +chr11 33124359 0 0 0.0 0 +chr11 33378597 0 0 0.0 0 +chr11 33404282 0 0 0.0 0 +chr11 33456571 0 0 0.0 0 +chr11 33571878 0 0 0.0 0 +chr11 33816597 0 0 0.0 0 +chr11 33899783 0 0 0.0 0 +chr11 33934568 0 0 0.0 0 +chr11 33940999 0 0 0.0 0 +chr11 33944967 0 0 0.0 0 +chr11 33945672 0 0 0.0 0 +chr11 34138584 0 0 0.0 0 +chr11 34150506 0 0 0.0 0 +chr11 34199270 0 0 0.0 0 +chr11 34280167 0 0 0.0 0 +chr11 34320685 0 0 0.0 0 +chr11 34338941 0 0 0.0 0 +chr11 34341022 0 0 0.0 0 +chr11 34410579 0 0 0.0 0 +chr11 34420993 0 0 0.0 0 +chr11 34455477 0 0 0.0 0 +chr11 34461355 0 0 0.0 0 +chr11 34486602 0 0 0.0 0 +chr11 34551373 0 0 0.0 0 +chr11 34555458 0 0 0.0 0 +chr11 34681052 0 0 0.0 0 +chr11 34837750 0 0 0.0 0 +chr11 34896816 0 0 0.0 0 +chr11 34947986 0 0 0.0 0 +chr11 35079457 0 0 0.0 0 +chr11 35179179 0 0 0.0 0 +chr11 35340213 0 0 0.0 0 +chr11 35349260 0 0 0.0 0 +chr11 35363890 0 0 0.0 0 +chr11 35364994 0 0 0.0 0 +chr11 35404647 0 0 0.0 0 +chr11 35449449 0 0 0.0 0 +chr11 35456627 0 0 0.0 0 +chr11 35461280 0 0 0.0 0 +chr11 35530374 0 0 0.0 0 +chr11 35724066 0 0 0.0 0 +chr11 35819528 0 0 0.0 0 +chr11 35893041 0 0 0.0 0 +chr11 36070014 0 0 0.0 0 +chr11 36132860 0 0 0.0 0 +chr11 36153028 0 0 0.0 0 +chr11 36238445 0 0 0.0 0 +chr11 36341417 0 0 0.0 0 +chr11 36345452 0 0 0.0 0 +chr11 36383039 0 0 0.0 0 +chr11 36402725 0 0 0.0 0 +chr11 36454867 0 0 0.0 0 +chr11 36607934 0 0 0.0 0 +chr11 36665388 0 0 0.0 0 +chr11 36701634 0 0 0.0 0 +chr11 36712090 0 0 0.0 0 +chr11 36786381 0 0 0.0 0 +chr11 37043342 0 0 0.0 0 +chr11 37240869 0 0 0.0 0 +chr11 37464159 0 0 0.0 0 +chr11 37542998 0 0 0.0 0 +chr11 37550220 0 0 0.0 0 +chr11 37577197 0 0 0.0 0 +chr11 37702802 0 0 0.0 0 +chr11 37817210 0 0 0.0 0 +chr11 37920207 0 0 0.0 0 +chr11 38035424 0 1 0.0278 0 +chr11 38048911 0 0 0.0 0 +chr11 38192616 0 0 0.0 0 +chr11 38487266 0 0 0.0 0 +chr11 38579507 0 0 0.0 0 +chr11 38843495 0 0 0.0 0 +chr11 38921187 0 0 0.0 0 +chr11 38926568 0 0 0.0 0 +chr11 39038837 0 0 0.0 0 +chr11 39137413 0 0 0.0 0 +chr11 39256906 0 0 0.0 0 +chr11 39300658 0 0 0.0 0 +chr11 39343313 0 0 0.0 0 +chr11 39451585 0 0 0.0 0 +chr11 39543419 0 0 0.0 0 +chr11 39559318 0 0 0.0 0 +chr11 39702788 0 0 0.0 0 +chr11 39810804 0 0 0.0 0 +chr11 39909051 0 0 0.0 0 +chr11 39942438 0 0 0.0 0 +chr11 40005708 0 0 0.0 0 +chr11 40103795 0 0 0.0 0 +chr11 40104186 0 0 0.0 0 +chr11 40192744 0 0 0.0 0 +chr11 40249094 0 0 0.0 0 +chr11 40255252 0 0 0.0 0 +chr11 40306378 0 0 0.0 0 +chr11 40375531 0 0 0.0 0 +chr11 40398390 0 0 0.0 0 +chr11 40612030 0 0 0.0 0 +chr11 40637840 0 0 0.0 0 +chr11 40668822 0 0 0.0 0 +chr11 41073477 0 0 0.0 0 +chr11 41139836 0 0 0.0 0 +chr11 41239073 0 0 0.0 0 +chr11 41692252 0 0 0.0 0 +chr11 41935274 0 0 0.0 0 +chr11 42032947 0 0 0.0 0 +chr11 42206180 0 0 0.0 0 +chr11 42211894 0 0 0.0 0 +chr11 42385505 0 0 0.0 0 +chr11 42416366 0 0 0.0 0 +chr11 42562535 0 0 0.0 0 +chr11 42562934 0 0 0.0 0 +chr11 42641343 0 0 0.0 0 +chr11 42711732 0 0 0.0 0 +chr11 42715817 0 0 0.0 0 +chr11 42824069 0 1 0.0159 0 +chr11 42826621 0 1 0.0286 0 +chr11 43012774 0 0 0.0 0 +chr11 43156744 0 0 0.0 0 +chr11 43163841 0 0 0.0 0 +chr11 43384378 0 0 0.0 0 +chr11 43465233 0 0 0.0 0 +chr11 43570468 0 0 0.0 0 +chr11 43685249 0 0 0.0 0 +chr11 43925595 0 0 0.0 0 +chr11 43942331 0 0 0.0 0 +chr11 43945782 0 0 0.0 0 +chr11 44002341 0 0 0.0 0 +chr11 44057425 0 0 0.0 0 +chr11 44067040 0 0 0.0 0 +chr11 44183209 0 0 0.0 0 +chr11 44269619 0 0 0.0 0 +chr11 44280897 0 0 0.0 0 +chr11 44329250 0 0 0.0 0 +chr11 44337967 0 0 0.0 0 +chr11 44496438 0 0 0.0 0 +chr11 44497083 0 1 0.0128 0 +chr11 44535146 0 0 0.0 0 +chr11 44648878 0 0 0.0 0 +chr11 44670881 0 0 0.0 0 +chr11 44718388 0 0 0.0 0 +chr11 44726658 0 0 0.0 0 +chr11 44773764 0 0 0.0 0 +chr11 45017118 0 0 0.0 0 +chr11 45127618 0 0 0.0 0 +chr11 45141785 0 0 0.0 0 +chr11 45251716 0 0 0.0 0 +chr11 45304293 0 0 0.0 0 +chr11 45407423 0 0 0.0 0 +chr11 45456436 0 0 0.0 0 +chr11 45561947 0 0 0.0 0 +chr11 45563268 0 0 0.0 0 +chr11 45681723 0 0 0.0 0 +chr11 45692512 0 0 0.0 0 +chr11 45714763 0 0 0.0 0 +chr11 45750429 0 0 0.0 0 +chr11 45890038 0 0 0.0 0 +chr11 45920917 0 0 0.0 0 +chr11 45971323 0 0 0.0 0 +chr11 46125410 0 0 0.0 0 +chr11 46146854 0 0 0.0 0 +chr11 46211888 0 0 0.0 0 +chr11 46342608 0 0 0.0 0 +chr11 46739161 0 0 0.0 0 +chr11 47111143 0 0 0.0 0 +chr11 47272200 0 0 0.0 0 +chr11 47352836 0 0 0.0 0 +chr11 47364545 0 0 0.0 0 +chr11 47471392 0 0 0.0 0 +chr11 47617107 0 0 0.0 0 +chr11 47821836 0 1 0.0149 0 +chr11 47845549 0 0 0.0 0 +chr11 47984206 0 0 0.0 0 +chr11 48038322 0 0 0.0 0 +chr11 48084927 0 0 0.0 0 +chr11 48400368 0 0 0.0 0 +chr11 48475043 0 0 0.0 0 +chr11 48494590 0 0 0.0 0 +chr11 48501706 0 0 0.0 0 +chr11 48533192 0 0 0.0 0 +chr11 48569189 0 0 0.0 0 +chr11 48586315 0 0 0.0 0 +chr11 48945327 0 0 0.0 0 +chr11 48978510 0 0 0.0 0 +chr11 49157916 0 0 0.0 0 +chr11 49450953 0 0 0.0 0 +chr11 49455750 0 0 0.0 0 +chr11 49745363 0 0 0.0 0 +chr11 49761417 0 0 0.0 0 +chr11 49836126 0 0 0.0 0 +chr11 49839688 0 0 0.0 0 +chr11 49947502 0 0 0.0 0 +chr11 49950191 0 0 0.0 0 +chr11 49963767 0 0 0.0 0 +chr11 49965431 0 0 0.0 0 +chr11 50139987 0 0 0.0 0 +chr11 50338557 0 0 0.0 0 +chr11 50469423 0 0 0.0 0 +chr11 50475484 0 0 0.0 0 +chr11 50501642 0 0 0.0 0 +chr11 50509005 1 37 0.4805 1 +chr11 50560198 0 0 0.0 0 +chr11 50622761 0 0 0.0 0 +chr11 50628458 0 0 0.0 0 +chr11 50743156 0 0 0.0 0 +chr11 50766146 0 0 0.0 0 +chr11 50804153 0 0 0.0 0 +chr11 52605735 0 0 0.0 0 +chr11 54391073 0 0 0.0 0 +chr11 54586597 0 0 0.0 0 +chr11 54611481 0 0 0.0 0 +chr11 54624606 0 0 0.0 0 +chr11 54645949 0 0 0.0 0 +chr11 54687919 0 0 0.0 0 +chr11 54762314 0 0 0.0 0 +chr11 54797052 0 0 0.0 0 +chr11 54868906 0 0 0.0 0 +chr11 54884363 0 0 0.0 0 +chr11 54888110 0 0 0.0 0 +chr11 54896918 0 0 0.0 0 +chr11 54924786 0 0 0.0 0 +chr11 54981473 0 0 0.0 0 +chr11 55002493 0 0 0.0 0 +chr11 55005574 0 0 0.0 0 +chr11 55008972 0 0 0.0 0 +chr11 55095303 0 0 0.0 0 +chr11 55221155 0 0 0.0 0 +chr11 55295099 0 0 0.0 0 +chr11 55298637 0 0 0.0 0 +chr11 55323585 0 0 0.0 0 +chr11 55467483 0 0 0.0 0 +chr11 55567989 0 0 0.0 0 +chr11 55627901 0 0 0.0 0 +chr11 55666442 0 0 0.0 0 +chr11 55888624 0 0 0.0 0 +chr11 56025229 0 0 0.0 0 +chr11 56033417 0 0 0.0 0 +chr11 56170835 0 0 0.0 0 +chr11 56180393 0 0 0.0 0 +chr11 56220332 0 0 0.0 0 +chr11 56433154 0 0 0.0 0 +chr11 56436086 0 0 0.0 0 +chr11 56566097 0 0 0.0 0 +chr11 56724910 0 0 0.0 0 +chr11 56823951 0 0 0.0 0 +chr11 57236754 0 0 0.0 0 +chr11 57341594 0 0 0.0 0 +chr11 57349751 0 1 0.0196 0 +chr11 57364873 0 0 0.0 0 +chr11 57434368 0 0 0.0 0 +chr11 57474172 0 0 0.0 0 +chr11 57481973 0 0 0.0 0 +chr11 57484559 0 0 0.0 0 +chr11 57487890 0 0 0.0 0 +chr11 57614058 0 0 0.0 0 +chr11 57649355 0 0 0.0 0 +chr11 57701594 0 0 0.0 0 +chr11 57778630 0 0 0.0 0 +chr11 57840839 0 0 0.0 0 +chr11 58060207 0 0 0.0 0 +chr11 58066012 0 0 0.0 0 +chr11 58484241 0 0 0.0 0 +chr11 58803421 0 0 0.0 0 +chr11 58809722 0 0 0.0 0 +chr11 58868373 0 0 0.0 0 +chr11 58935159 0 0 0.0 0 +chr11 59102993 0 0 0.0 0 +chr11 59257328 0 0 0.0 0 +chr11 59266890 0 0 0.0 0 +chr11 59303239 0 0 0.0 0 +chr11 59323564 0 0 0.0 0 +chr11 59443780 0 0 0.0 0 +chr11 59490741 0 0 0.0 0 +chr11 59559470 0 0 0.0 0 +chr11 59619959 0 0 0.0 0 +chr11 59631540 0 0 0.0 0 +chr11 59809969 0 0 0.0 0 +chr11 60020265 0 0 0.0 0 +chr11 60095019 0 0 0.0 0 +chr11 60161976 0 0 0.0 0 +chr11 60208093 0 0 0.0 0 +chr11 60288246 0 0 0.0 0 +chr11 60306694 0 0 0.0 0 +chr11 60409862 1 26 0.5 1 +chr11 60464509 0 0 0.0 0 +chr11 60685149 0 0 0.0 0 +chr11 60734656 0 0 0.0 0 +chr11 60767733 0 1 0.0169 0 +chr11 60772484 0 0 0.0 0 +chr11 60855023 0 0 0.0 0 +chr11 60890827 0 0 0.0 0 +chr11 60923031 0 0 0.0 0 +chr11 61175401 0 0 0.0 0 +chr11 61194483 0 0 0.0 0 +chr11 61346677 0 0 0.0 0 +chr11 61388670 0 0 0.0 0 +chr11 61398738 0 0 0.0 0 +chr11 61404719 0 0 0.0 0 +chr11 61444282 0 0 0.0 0 +chr11 61480337 0 0 0.0 0 +chr11 61562805 0 0 0.0 0 +chr11 61588335 0 0 0.0 0 +chr11 61607211 0 0 0.0 0 +chr11 61636418 0 0 0.0 0 +chr11 61701678 0 0 0.0 0 +chr11 61736139 0 0 0.0 0 +chr11 61865089 0 1 0.0217 0 +chr11 61890923 0 0 0.0 0 +chr11 61957083 0 0 0.0 0 +chr11 62051243 0 0 0.0 0 +chr11 62139181 0 0 0.0 0 +chr11 62187268 0 0 0.0 0 +chr11 62310737 0 0 0.0 0 +chr11 62333705 0 0 0.0 0 +chr11 62372058 0 0 0.0 0 +chr11 62540482 0 0 0.0 0 +chr11 62547839 0 0 0.0 0 +chr11 62613692 0 0 0.0 0 +chr11 62677092 0 0 0.0 0 +chr11 62691007 0 0 0.0 0 +chr11 62747533 0 0 0.0 0 +chr11 62807600 0 0 0.0 0 +chr11 62840193 0 0 0.0 0 +chr11 62851931 0 0 0.0 0 +chr11 63261127 0 0 0.0 0 +chr11 63264213 0 0 0.0 0 +chr11 63274862 0 0 0.0 0 +chr11 63494051 0 0 0.0 0 +chr11 63516134 0 0 0.0 0 +chr11 63671343 0 0 0.0 0 +chr11 63677686 0 0 0.0 0 +chr11 63696590 0 0 0.0 0 +chr11 63765556 0 0 0.0 0 +chr11 63827588 0 0 0.0 0 +chr11 63956493 0 0 0.0 0 +chr11 63969498 0 0 0.0 0 +chr11 64006221 0 0 0.0 0 +chr11 64110742 0 0 0.0 0 +chr11 64123183 0 0 0.0 0 +chr11 64199432 0 0 0.0 0 +chr11 64414899 0 0 0.0 0 +chr11 64434013 0 0 0.0 0 +chr11 64562315 0 0 0.0 0 +chr11 64583166 0 0 0.0 0 +chr11 64767846 0 0 0.0 0 +chr11 64857056 0 0 0.0 0 +chr11 64971704 0 0 0.0 0 +chr11 65065104 0 0 0.0 0 +chr11 65078397 0 0 0.0 0 +chr11 65143712 0 0 0.0 0 +chr11 65410908 0 0 0.0 0 +chr11 65427537 0 0 0.0 0 +chr11 65497193 0 0 0.0 0 +chr11 65719160 0 0 0.0 0 +chr11 65798175 0 0 0.0 0 +chr11 65958970 0 0 0.0 0 +chr11 66043753 0 0 0.0 0 +chr11 66116308 0 0 0.0 0 +chr11 66246905 0 0 0.0 0 +chr11 66375139 0 0 0.0 0 +chr11 66471360 0 0 0.0 0 +chr11 66538026 0 0 0.0 0 +chr11 66579757 0 0 0.0 0 +chr11 66687363 0 0 0.0 0 +chr11 66859033 0 0 0.0 0 +chr11 66969579 0 0 0.0 0 +chr11 67149392 0 0 0.0 0 +chr11 67188015 0 1 0.0172 0 +chr11 67197023 0 0 0.0 0 +chr11 67263486 0 0 0.0 0 +chr11 67286870 0 0 0.0 0 +chr11 67365552 0 0 0.0 0 +chr11 67376391 0 0 0.0 0 +chr11 67481184 1 40 0.6061 1 +chr11 67525447 0 0 0.0 0 +chr11 67627031 0 0 0.0 0 +chr11 67679549 0 0 0.0 0 +chr11 67715496 0 0 0.0 0 +chr11 67786051 0 0 0.0 0 +chr11 67852046 0 0 0.0 0 +chr11 67923748 0 0 0.0 0 +chr11 67932619 0 0 0.0 0 +chr11 67982192 0 0 0.0 0 +chr11 68012968 0 0 0.0 0 +chr11 68025542 0 0 0.0 0 +chr11 68524177 0 0 0.0 0 +chr11 68669683 0 0 0.0 0 +chr11 68716025 0 0 0.0 0 +chr11 68913373 0 0 0.0 0 +chr11 69104762 0 0 0.0 0 +chr11 69167930 0 0 0.0 0 +chr11 69239114 0 1 0.0238 0 +chr11 69254244 0 0 0.0 0 +chr11 69307422 0 0 0.0 0 +chr11 69327671 0 1 0.0208 0 +chr11 69351412 0 0 0.0 0 +chr11 69523836 0 0 0.0 0 +chr11 69665426 0 0 0.0 0 +chr11 69791915 0 0 0.0 0 +chr11 69865391 0 0 0.0 0 +chr11 69867796 0 0 0.0 0 +chr11 69975727 0 0 0.0 0 +chr11 70121042 0 0 0.0 0 +chr11 70280038 0 0 0.0 0 +chr11 70377280 0 0 0.0 0 +chr11 70482907 0 0 0.0 0 +chr11 70500339 0 0 0.0 0 +chr11 70569810 0 0 0.0 0 +chr11 70571391 0 0 0.0 0 +chr11 70608234 0 0 0.0 0 +chr11 70707972 0 0 0.0 0 +chr11 70740167 0 0 0.0 0 +chr11 71061712 0 0 0.0 0 +chr11 71070863 0 0 0.0 0 +chr11 71181255 0 0 0.0 0 +chr11 71201798 0 0 0.0 0 +chr11 71220461 0 0 0.0 0 +chr11 71271738 0 0 0.0 0 +chr11 71308520 0 0 0.0 0 +chr11 71359805 0 0 0.0 0 +chr11 71432969 0 0 0.0 0 +chr11 71437993 0 0 0.0 0 +chr11 71439578 0 0 0.0 0 +chr11 71441590 0 0 0.0 0 +chr11 71589303 0 0 0.0 0 +chr11 71663290 0 0 0.0 0 +chr11 71672200 0 0 0.0 0 +chr11 71691103 0 0 0.0 0 +chr11 71712480 0 0 0.0 0 +chr11 71742556 0 0 0.0 0 +chr11 71791597 0 0 0.0 0 +chr11 71990264 0 0 0.0 0 +chr11 72083685 0 0 0.0 0 +chr11 72097537 0 0 0.0 0 +chr11 72513565 0 0 0.0 0 +chr11 72516996 0 0 0.0 0 +chr11 72736488 0 0 0.0 0 +chr11 72817702 0 0 0.0 0 +chr11 72865746 0 0 0.0 0 +chr11 72962138 0 0 0.0 0 +chr11 73073366 0 0 0.0 0 +chr11 73171051 0 0 0.0 0 +chr11 73173203 0 0 0.0 0 +chr11 73264223 0 0 0.0 0 +chr11 73317491 0 0 0.0 0 +chr11 73472686 0 0 0.0 0 +chr11 73517777 0 0 0.0 0 +chr11 73565716 0 0 0.0 0 +chr11 73626071 0 0 0.0 0 +chr11 73631749 0 0 0.0 0 +chr11 73637824 0 0 0.0 0 +chr11 73996404 0 0 0.0 0 +chr11 74162670 0 0 0.0 0 +chr11 74244967 0 0 0.0 0 +chr11 74361279 0 0 0.0 0 +chr11 74550496 0 0 0.0 0 +chr11 74574854 0 0 0.0 0 +chr11 74675320 0 0 0.0 0 +chr11 74730230 0 0 0.0 0 +chr11 74932881 0 0 0.0 0 +chr11 74959893 0 0 0.0 0 +chr11 75120149 0 0 0.0 0 +chr11 75230927 0 0 0.0 0 +chr11 75338077 0 0 0.0 0 +chr11 75395358 0 0 0.0 0 +chr11 75395970 0 0 0.0 0 +chr11 75441610 0 0 0.0 0 +chr11 75465538 0 0 0.0 0 +chr11 75482118 0 0 0.0 0 +chr11 75497241 0 0 0.0 0 +chr11 75518349 0 0 0.0 0 +chr11 75564670 0 0 0.0 0 +chr11 75571248 0 0 0.0 0 +chr11 75636704 0 0 0.0 0 +chr11 75707946 0 0 0.0 0 +chr11 75744311 0 0 0.0 0 +chr11 75767639 0 0 0.0 0 +chr11 75792357 0 0 0.0 0 +chr11 75863946 0 0 0.0 0 +chr11 76006001 0 0 0.0 0 +chr11 76140664 0 0 0.0 0 +chr11 76193987 0 0 0.0 0 +chr11 76196346 0 0 0.0 0 +chr11 76275043 0 0 0.0 0 +chr11 76289479 0 0 0.0 0 +chr11 76314535 0 0 0.0 0 +chr11 76445525 0 0 0.0 0 +chr11 76599328 0 0 0.0 0 +chr11 76626459 0 0 0.0 0 +chr11 76630737 0 0 0.0 0 +chr11 76659757 0 0 0.0 0 +chr11 76660321 0 0 0.0 0 +chr11 76661433 0 0 0.0 0 +chr11 76756996 0 0 0.0 0 +chr11 76788661 0 0 0.0 0 +chr11 76987200 0 0 0.0 0 +chr11 77158126 0 0 0.0 0 +chr11 77180283 1 37 0.5286 1 +chr11 77200550 0 0 0.0 0 +chr11 77223167 0 0 0.0 0 +chr11 77263789 0 0 0.0 0 +chr11 77342105 0 0 0.0 0 +chr11 77355247 0 0 0.0 0 +chr11 77465923 0 0 0.0 0 +chr11 77646120 0 0 0.0 0 +chr11 78037188 0 0 0.0 0 +chr11 78107736 0 0 0.0 0 +chr11 78109961 0 0 0.0 0 +chr11 78113469 0 0 0.0 0 +chr11 78197426 0 0 0.0 0 +chr11 78217870 0 0 0.0 0 +chr11 78347693 0 0 0.0 0 +chr11 78497808 0 0 0.0 0 +chr11 78571552 0 0 0.0 0 +chr11 78604225 0 0 0.0 0 +chr11 78633316 0 0 0.0 0 +chr11 78807855 0 0 0.0 0 +chr11 78903571 0 0 0.0 0 +chr11 78909812 0 0 0.0 0 +chr11 78950234 0 0 0.0 0 +chr11 79023077 0 0 0.0 0 +chr11 79031850 0 0 0.0 0 +chr11 79054945 0 0 0.0 0 +chr11 79074925 0 0 0.0 0 +chr11 79081899 0 0 0.0 0 +chr11 79200892 0 0 0.0 0 +chr11 79225114 0 0 0.0 0 +chr11 79239878 0 0 0.0 0 +chr11 79307502 0 0 0.0 0 +chr11 79372249 0 0 0.0 0 +chr11 79474253 0 0 0.0 0 +chr11 79612983 0 0 0.0 0 +chr11 79781357 0 0 0.0 0 +chr11 79803431 0 0 0.0 0 +chr11 79841133 0 0 0.0 0 +chr11 79881034 0 0 0.0 0 +chr11 79881882 0 0 0.0 0 +chr11 80096301 0 0 0.0 0 +chr11 80372260 0 0 0.0 0 +chr11 80485791 0 0 0.0 0 +chr11 80516267 0 0 0.0 0 +chr11 80517193 0 0 0.0 0 +chr11 80525015 0 0 0.0 0 +chr11 80626825 0 0 0.0 0 +chr11 80738079 0 0 0.0 0 +chr11 80745476 0 0 0.0 0 +chr11 80798084 0 0 0.0 0 +chr11 80924873 0 0 0.0 0 +chr11 80958746 0 0 0.0 0 +chr11 80974612 0 0 0.0 0 +chr11 81063971 0 0 0.0 0 +chr11 81290598 0 0 0.0 0 +chr11 81504497 0 0 0.0 0 +chr11 81594324 0 0 0.0 0 +chr11 82013232 0 0 0.0 0 +chr11 82168354 0 0 0.0 0 +chr11 82176872 0 0 0.0 0 +chr11 82325177 0 0 0.0 0 +chr11 82334951 0 0 0.0 0 +chr11 82514694 0 0 0.0 0 +chr11 82585219 0 0 0.0 0 +chr11 82667362 0 0 0.0 0 +chr11 82696234 0 0 0.0 0 +chr11 82700999 0 0 0.0 0 +chr11 82795781 0 0 0.0 0 +chr11 82818583 0 0 0.0 0 +chr11 82940791 0 0 0.0 0 +chr11 83021193 0 0 0.0 0 +chr11 83227410 0 0 0.0 0 +chr11 83258876 0 0 0.0 0 +chr11 83383821 0 0 0.0 0 +chr11 83511520 0 0 0.0 0 +chr11 83680588 0 0 0.0 0 +chr11 83715032 0 0 0.0 0 +chr11 83782338 0 0 0.0 0 +chr11 83793378 0 0 0.0 0 +chr11 83895894 0 0 0.0 0 +chr11 84005245 0 0 0.0 0 +chr11 84194825 0 0 0.0 0 +chr11 84518752 0 0 0.0 0 +chr11 84552388 0 0 0.0 0 +chr11 84625966 0 0 0.0 0 +chr11 84806631 0 0 0.0 0 +chr11 84857761 0 0 0.0 0 +chr11 85115828 0 0 0.0 0 +chr11 85121140 0 0 0.0 0 +chr11 85129657 0 0 0.0 0 +chr11 85262564 0 0 0.0 0 +chr11 85319704 0 0 0.0 0 +chr11 85343115 0 0 0.0 0 +chr11 85372079 0 0 0.0 0 +chr11 85396122 0 0 0.0 0 +chr11 85415939 0 0 0.0 0 +chr11 85461718 0 0 0.0 0 +chr11 85496323 0 0 0.0 0 +chr11 85507781 0 0 0.0 0 +chr11 85692200 0 0 0.0 0 +chr11 85949121 0 0 0.0 0 +chr11 86045392 0 0 0.0 0 +chr11 86254580 0 0 0.0 0 +chr11 86314330 0 0 0.0 0 +chr11 86350528 0 0 0.0 0 +chr11 86452593 0 0 0.0 0 +chr11 86490228 0 0 0.0 0 +chr11 86541438 0 0 0.0 0 +chr11 86579340 0 0 0.0 0 +chr11 86628124 0 0 0.0 0 +chr11 86668605 0 0 0.0 0 +chr11 86802792 0 0 0.0 0 +chr11 86924876 0 0 0.0 0 +chr11 87018563 0 0 0.0 0 +chr11 87134380 0 1 0.0133 0 +chr11 87307221 0 0 0.0 0 +chr11 87328249 0 0 0.0 0 +chr11 87403045 0 0 0.0 0 +chr11 87633855 0 0 0.0 0 +chr11 87892139 0 0 0.0 0 +chr11 87924922 0 0 0.0 0 +chr11 88123274 0 0 0.0 0 +chr11 88197782 0 0 0.0 0 +chr11 88229816 0 0 0.0 0 +chr11 88725176 0 0 0.0 0 +chr11 88731400 0 0 0.0 0 +chr11 88771378 0 0 0.0 0 +chr11 88867578 0 0 0.0 0 +chr11 89246031 0 0 0.0 0 +chr11 89443347 0 0 0.0 0 +chr11 89491181 0 0 0.0 0 +chr11 89790630 0 0 0.0 0 +chr11 89854583 0 0 0.0 0 +chr11 89858154 0 0 0.0 0 +chr11 89986356 0 0 0.0 0 +chr11 89989930 0 0 0.0 0 +chr11 90099919 0 0 0.0 0 +chr11 90119714 0 0 0.0 0 +chr11 90156650 0 0 0.0 0 +chr11 90330783 0 0 0.0 0 +chr11 90466344 0 0 0.0 0 +chr11 90497444 0 0 0.0 0 +chr11 90701308 0 0 0.0 0 +chr11 90733902 0 0 0.0 0 +chr11 90825358 0 0 0.0 0 +chr11 90864185 0 0 0.0 0 +chr11 91596147 0 0 0.0 0 +chr11 91608889 0 0 0.0 0 +chr11 91741861 0 0 0.0 0 +chr11 91925398 0 0 0.0 0 +chr11 91991307 0 0 0.0 0 +chr11 91996993 0 0 0.0 0 +chr11 92035679 0 0 0.0 0 +chr11 92359390 0 0 0.0 0 +chr11 92386714 0 0 0.0 0 +chr11 92437802 0 0 0.0 0 +chr11 92459381 0 0 0.0 0 +chr11 92507943 0 0 0.0 0 +chr11 92543875 0 0 0.0 0 +chr11 92590505 0 1 0.04 0 +chr11 92648584 0 0 0.0 0 +chr11 92851090 0 0 0.0 0 +chr11 92909945 0 0 0.0 0 +chr11 92948261 0 0 0.0 0 +chr11 93053811 0 0 0.0 0 +chr11 93163188 0 0 0.0 0 +chr11 93232829 0 0 0.0 0 +chr11 93532431 0 0 0.0 0 +chr11 93542203 0 0 0.0 0 +chr11 93685532 0 2 0.0222 0 +chr11 93910369 0 0 0.0 0 +chr11 94009235 0 0 0.0 0 +chr11 94021100 0 0 0.0 0 +chr11 94023009 0 0 0.0 0 +chr11 94185286 0 0 0.0 0 +chr11 94488209 0 0 0.0 0 +chr11 94563399 0 0 0.0 0 +chr11 94593555 0 0 0.0 0 +chr11 94747404 0 0 0.0 0 +chr11 95149995 0 0 0.0 0 +chr11 95278192 0 0 0.0 0 +chr11 95297579 0 0 0.0 0 +chr11 95365944 0 0 0.0 0 +chr11 95540512 0 0 0.0 0 +chr11 95545103 0 0 0.0 0 +chr11 95949628 0 0 0.0 0 +chr11 95950815 0 1 0.02 0 +chr11 95963238 0 0 0.0 0 +chr11 96287991 0 0 0.0 0 +chr11 96297466 0 0 0.0 0 +chr11 96352289 0 0 0.0 0 +chr11 96561576 0 0 0.0 0 +chr11 96792837 0 0 0.0 0 +chr11 96848270 0 0 0.0 0 +chr11 96871218 0 0 0.0 0 +chr11 96980647 0 0 0.0 0 +chr11 96998862 0 0 0.0 0 +chr11 97121063 0 0 0.0 0 +chr11 97269094 0 0 0.0 0 +chr11 97630446 0 0 0.0 0 +chr11 97755184 0 0 0.0 0 +chr11 97759522 0 0 0.0 0 +chr11 97805279 0 0 0.0 0 +chr11 97917055 0 0 0.0 0 +chr11 98018120 0 0 0.0 0 +chr11 98226864 0 0 0.0 0 +chr11 98514168 0 0 0.0 0 +chr11 98695111 0 0 0.0 0 +chr11 98704556 0 0 0.0 0 +chr11 98722100 0 0 0.0 0 +chr11 98842990 0 0 0.0 0 +chr11 98934167 0 0 0.0 0 +chr11 99135853 0 0 0.0 0 +chr11 99409648 0 0 0.0 0 +chr11 99534743 0 0 0.0 0 +chr11 99555354 0 0 0.0 0 +chr11 99656900 0 0 0.0 0 +chr11 99722790 0 0 0.0 0 +chr11 99738153 0 0 0.0 0 +chr11 99773778 0 0 0.0 0 +chr11 99888860 0 0 0.0 0 +chr11 99921227 0 0 0.0 0 +chr11 99946539 0 0 0.0 0 +chr11 99977573 0 0 0.0 0 +chr11 100098925 0 0 0.0 0 +chr11 100122181 0 0 0.0 0 +chr11 100147599 0 0 0.0 0 +chr11 100366613 0 0 0.0 0 +chr11 100819235 0 0 0.0 0 +chr11 100839920 0 0 0.0 0 +chr11 100939040 0 0 0.0 0 +chr11 100982385 0 0 0.0 0 +chr11 101047157 0 0 0.0 0 +chr11 101048672 0 0 0.0 0 +chr11 101209904 0 0 0.0 0 +chr11 101369677 0 0 0.0 0 +chr11 101435518 0 0 0.0 0 +chr11 101439261 0 0 0.0 0 +chr11 101541411 0 0 0.0 0 +chr11 101594545 0 0 0.0 0 +chr11 101618870 0 0 0.0 0 +chr11 101709885 0 0 0.0 0 +chr11 101772748 0 0 0.0 0 +chr11 101822893 0 0 0.0 0 +chr11 101839464 0 0 0.0 0 +chr11 101846922 0 0 0.0 0 +chr11 101847026 0 0 0.0 0 +chr11 102018056 0 0 0.0 0 +chr11 102077984 0 0 0.0 0 +chr11 102193817 1 10 0.1316 1 +chr11 102360961 0 0 0.0 0 +chr11 102392603 0 0 0.0 0 +chr11 102864223 0 0 0.0 0 +chr11 102866373 0 0 0.0 0 +chr11 103061352 0 0 0.0 0 +chr11 103267109 0 0 0.0 0 +chr11 103491037 0 0 0.0 0 +chr11 103661783 1 38 0.5846 1 +chr11 103737289 0 0 0.0 0 +chr11 103829788 0 0 0.0 0 +chr11 103910870 0 0 0.0 0 +chr11 104012742 0 0 0.0 0 +chr11 104150354 0 0 0.0 0 +chr11 104290127 0 0 0.0 0 +chr11 104327663 0 0 0.0 0 +chr11 104429824 0 0 0.0 0 +chr11 104626379 0 0 0.0 0 +chr11 104913692 0 0 0.0 0 +chr11 105061364 0 0 0.0 0 +chr11 105081928 0 0 0.0 0 +chr11 105098517 0 0 0.0 0 +chr11 105100719 0 0 0.0 0 +chr11 105242133 0 0 0.0 0 +chr11 105243508 0 0 0.0 0 +chr11 105702956 0 0 0.0 0 +chr11 105789987 0 0 0.0 0 +chr11 105985880 0 1 0.0233 0 +chr11 106242480 0 0 0.0 0 +chr11 106413033 0 0 0.0 0 +chr11 106573570 0 0 0.0 0 +chr11 106696185 0 0 0.0 0 +chr11 106716186 0 0 0.0 0 +chr11 106737374 0 0 0.0 0 +chr11 106772212 0 0 0.0 0 +chr11 106924761 0 1 0.012 0 +chr11 107031843 0 0 0.0 0 +chr11 107143107 0 0 0.0 0 +chr11 107149865 0 0 0.0 0 +chr11 107276803 0 0 0.0 0 +chr11 107309293 0 0 0.0 0 +chr11 107565493 0 0 0.0 0 +chr11 107601978 0 0 0.0 0 +chr11 107624986 0 0 0.0 0 +chr11 107651816 0 0 0.0 0 +chr11 107754595 0 0 0.0 0 +chr11 107884702 0 0 0.0 0 +chr11 107884920 0 0 0.0 0 +chr11 107896181 0 0 0.0 0 +chr11 108213868 0 0 0.0 0 +chr11 108222729 0 0 0.0 0 +chr11 108269321 0 0 0.0 0 +chr11 108442140 0 0 0.0 0 +chr11 108513016 0 0 0.0 0 +chr11 108552570 0 0 0.0 0 +chr11 108683406 0 0 0.0 0 +chr11 108693093 0 0 0.0 0 +chr11 108754268 0 0 0.0 0 +chr11 108864076 0 0 0.0 0 +chr11 108909288 0 0 0.0 0 +chr11 109074946 0 0 0.0 0 +chr11 109227073 0 0 0.0 0 +chr11 109265419 0 0 0.0 0 +chr11 109304565 0 0 0.0 0 +chr11 109328206 0 0 0.0 0 +chr11 109378005 0 0 0.0 0 +chr11 109499804 0 0 0.0 0 +chr11 109535598 0 0 0.0 0 +chr11 109619764 0 0 0.0 0 +chr11 109627323 0 0 0.0 0 +chr11 109653799 0 0 0.0 0 +chr11 109830540 0 0 0.0 0 +chr11 109869400 0 0 0.0 0 +chr11 110159296 0 0 0.0 0 +chr11 110222430 0 0 0.0 0 +chr11 110276812 0 0 0.0 0 +chr11 110355575 0 0 0.0 0 +chr11 110361692 0 0 0.0 0 +chr11 110386209 0 0 0.0 0 +chr11 110396789 0 0 0.0 0 +chr11 110424782 0 0 0.0 0 +chr11 110535876 0 0 0.0 0 +chr11 110942992 0 0 0.0 0 +chr11 110984152 0 0 0.0 0 +chr11 111027253 0 0 0.0 0 +chr11 111067762 0 0 0.0 0 +chr11 111082942 0 0 0.0 0 +chr11 111237173 0 0 0.0 0 +chr11 111410743 0 0 0.0 0 +chr11 111426200 0 0 0.0 0 +chr11 111580430 0 0 0.0 0 +chr11 111592228 0 0 0.0 0 +chr11 111800122 0 0 0.0 0 +chr11 111833798 0 0 0.0 0 +chr11 111910831 0 0 0.0 0 +chr11 112280752 0 0 0.0 0 +chr11 112578137 0 0 0.0 0 +chr11 112661634 0 0 0.0 0 +chr11 112763514 0 0 0.0 0 +chr11 112774368 0 0 0.0 0 +chr11 112808549 0 0 0.0 0 +chr11 112835606 0 0 0.0 0 +chr11 112857738 0 0 0.0 0 +chr11 112910893 0 0 0.0 0 +chr11 112943907 0 0 0.0 0 +chr11 112963715 0 0 0.0 0 +chr11 113069506 0 0 0.0 0 +chr11 113096134 0 0 0.0 0 +chr11 113287414 0 0 0.0 0 +chr11 113306804 0 0 0.0 0 +chr11 113310231 0 0 0.0 0 +chr11 113347350 0 0 0.0 0 +chr11 113358787 0 0 0.0 0 +chr11 113435242 0 0 0.0 0 +chr11 113490056 0 0 0.0 0 +chr11 113558939 0 0 0.0 0 +chr11 113707216 0 0 0.0 0 +chr11 113894499 0 0 0.0 0 +chr11 113899037 0 0 0.0 0 +chr11 113983240 0 0 0.0 0 +chr11 113995177 0 0 0.0 0 +chr11 114035133 0 0 0.0 0 +chr11 114040173 0 0 0.0 0 +chr11 114137606 0 1 0.0179 0 +chr11 114198795 0 0 0.0 0 +chr11 114281456 0 1 0.0189 0 +chr11 114488450 0 0 0.0 0 +chr11 114659578 0 0 0.0 0 +chr11 114760252 0 0 0.0 0 +chr11 114814256 0 0 0.0 0 +chr11 114846583 0 0 0.0 0 +chr11 114932720 0 0 0.0 0 +chr11 114969565 0 0 0.0 0 +chr11 114998514 0 0 0.0 0 +chr11 115088454 0 0 0.0 0 +chr11 115120580 0 0 0.0 0 +chr11 115124929 0 0 0.0 0 +chr11 115127517 0 0 0.0 0 +chr11 115129550 0 0 0.0 0 +chr11 115136318 0 0 0.0 0 +chr11 115153114 0 0 0.0 0 +chr11 115222827 0 0 0.0 0 +chr11 115270592 0 0 0.0 0 +chr11 115444006 0 0 0.0 0 +chr11 115552371 0 0 0.0 0 +chr11 115700217 0 0 0.0 0 +chr11 115936152 0 0 0.0 0 +chr11 115952568 0 0 0.0 0 +chr11 116086924 0 0 0.0 0 +chr11 116088247 0 1 0.0189 0 +chr11 116107418 0 0 0.0 0 +chr11 116117915 0 0 0.0 0 +chr11 116131139 0 0 0.0 0 +chr11 116139675 0 0 0.0 0 +chr11 116252901 0 0 0.0 0 +chr11 116358208 0 0 0.0 0 +chr11 116377590 0 0 0.0 0 +chr11 116540303 0 0 0.0 0 +chr11 116601255 0 0 0.0 0 +chr11 116636762 0 0 0.0 0 +chr11 116639513 0 0 0.0 0 +chr11 116646245 0 0 0.0 0 +chr11 116660675 0 0 0.0 0 +chr11 116679164 0 0 0.0 0 +chr11 116688472 0 0 0.0 0 +chr11 117095418 0 0 0.0 0 +chr11 117126515 0 0 0.0 0 +chr11 117221019 0 0 0.0 0 +chr11 117224007 0 0 0.0 0 +chr11 117311087 0 0 0.0 0 +chr11 117359733 0 0 0.0 0 +chr11 117433391 0 0 0.0 0 +chr11 117461472 0 0 0.0 0 +chr11 117512099 0 0 0.0 0 +chr11 117524445 0 0 0.0 0 +chr11 117556366 0 0 0.0 0 +chr11 117718927 0 0 0.0 0 +chr11 117753661 0 0 0.0 0 +chr11 118095948 0 0 0.0 0 +chr11 118111330 0 0 0.0 0 +chr11 118135353 0 0 0.0 0 +chr11 118178021 0 0 0.0 0 +chr11 118207661 0 0 0.0 0 +chr11 118257689 0 0 0.0 0 +chr11 118352140 0 0 0.0 0 +chr11 118532935 0 0 0.0 0 +chr11 118534361 0 0 0.0 0 +chr11 118687927 0 0 0.0 0 +chr11 118759944 0 0 0.0 0 +chr11 118788659 0 0 0.0 0 +chr11 118907618 0 0 0.0 0 +chr11 118959613 0 0 0.0 0 +chr11 119198838 0 0 0.0 0 +chr11 119296922 0 1 0.0189 0 +chr11 119381505 0 0 0.0 0 +chr11 119579022 0 0 0.0 0 +chr11 119616367 0 0 0.0 0 +chr11 119658115 0 0 0.0 0 +chr11 119702950 0 0 0.0 0 +chr11 119742615 0 0 0.0 0 +chr11 119792449 0 0 0.0 0 +chr11 119897279 0 0 0.0 0 +chr11 119933419 0 0 0.0 0 +chr11 120099832 0 0 0.0 0 +chr11 120184622 0 0 0.0 0 +chr11 120212809 0 0 0.0 0 +chr11 120296789 0 0 0.0 0 +chr11 120453221 0 0 0.0 0 +chr11 120486152 0 0 0.0 0 +chr11 120524386 0 0 0.0 0 +chr11 120555535 0 0 0.0 0 +chr11 120574483 0 0 0.0 0 +chr11 120785101 0 0 0.0 0 +chr11 120825714 0 0 0.0 0 +chr11 120849267 0 0 0.0 0 +chr11 120896790 0 0 0.0 0 +chr11 121351130 0 0 0.0 0 +chr11 121374086 0 0 0.0 0 +chr11 121410929 0 0 0.0 0 +chr11 121493863 0 0 0.0 0 +chr11 121517934 0 0 0.0 0 +chr11 121521406 0 0 0.0 0 +chr11 121644318 0 0 0.0 0 +chr11 121648272 0 0 0.0 0 +chr11 121651121 0 0 0.0 0 +chr11 121758458 0 0 0.0 0 +chr11 121855766 0 0 0.0 0 +chr11 121963632 0 0 0.0 0 +chr11 122094214 0 0 0.0 0 +chr11 122105751 0 0 0.0 0 +chr11 122269177 0 0 0.0 0 +chr11 122321425 0 0 0.0 0 +chr11 122460962 0 0 0.0 0 +chr11 122536498 0 0 0.0 0 +chr11 122601354 0 0 0.0 0 +chr11 122648752 0 0 0.0 0 +chr11 122654373 0 0 0.0 0 +chr11 122666093 0 0 0.0 0 +chr11 122817432 0 0 0.0 0 +chr11 122951444 0 0 0.0 0 +chr11 123022139 0 0 0.0 0 +chr11 123067360 0 0 0.0 0 +chr11 123097293 0 0 0.0 0 +chr11 123361351 0 0 0.0 0 +chr11 123497297 0 0 0.0 0 +chr11 123510843 0 0 0.0 0 +chr11 123525267 0 0 0.0 0 +chr11 123572269 0 0 0.0 0 +chr11 123725624 0 0 0.0 0 +chr11 123833844 0 0 0.0 0 +chr11 123885286 0 0 0.0 0 +chr11 123939854 0 0 0.0 0 +chr11 123971697 0 0 0.0 0 +chr11 124155038 0 0 0.0 0 +chr11 124185835 0 0 0.0 0 +chr11 124203813 0 0 0.0 0 +chr11 124445631 0 0 0.0 0 +chr11 124524209 0 0 0.0 0 +chr11 124813094 0 0 0.0 0 +chr11 124934385 0 0 0.0 0 +chr11 125032723 0 0 0.0 0 +chr11 125254175 0 0 0.0 0 +chr11 125326639 0 0 0.0 0 +chr11 125399219 0 0 0.0 0 +chr11 125702226 0 0 0.0 0 +chr11 125725099 0 0 0.0 0 +chr11 125766811 0 0 0.0 0 +chr11 126034205 0 0 0.0 0 +chr11 126092340 0 0 0.0 0 +chr11 126160913 0 1 0.0143 0 +chr11 126421527 0 0 0.0 0 +chr11 126446506 0 0 0.0 0 +chr11 126460341 0 0 0.0 0 +chr11 126517862 0 0 0.0 0 +chr11 126535531 0 0 0.0 0 +chr11 126557004 0 0 0.0 0 +chr11 126587785 0 0 0.0 0 +chr11 126592605 0 0 0.0 0 +chr11 126639881 0 0 0.0 0 +chr11 126724216 0 0 0.0 0 +chr11 126735043 0 0 0.0 0 +chr11 126862850 0 0 0.0 0 +chr11 126942285 0 1 0.0217 0 +chr11 127003174 0 0 0.0 0 +chr11 127068860 0 0 0.0 0 +chr11 127118719 0 0 0.0 0 +chr11 127279478 0 0 0.0 0 +chr11 127281041 0 0 0.0 0 +chr11 127427912 0 0 0.0 0 +chr11 127581170 0 1 0.0145 0 +chr11 127606108 0 0 0.0 0 +chr11 127619669 1 21 0.4468 1 +chr11 127683478 0 0 0.0 0 +chr11 127898577 0 0 0.0 0 +chr11 127903973 0 0 0.0 0 +chr11 127925870 0 0 0.0 0 +chr11 127929988 0 0 0.0 0 +chr11 128021895 0 0 0.0 0 +chr11 128172918 0 0 0.0 0 +chr11 128196862 0 0 0.0 0 +chr11 128290566 0 1 0.0137 0 +chr11 128329107 0 0 0.0 0 +chr11 128333375 0 0 0.0 0 +chr11 128423039 0 0 0.0 0 +chr11 128586063 0 0 0.0 0 +chr11 128648892 0 0 0.0 0 +chr11 128705148 0 0 0.0 0 +chr11 128810343 0 0 0.0 0 +chr11 128913493 0 0 0.0 0 +chr11 129113026 0 0 0.0 0 +chr11 129156383 0 0 0.0 0 +chr11 129206958 0 0 0.0 0 +chr11 129400481 0 0 0.0 0 +chr11 129403281 0 0 0.0 0 +chr11 129443904 0 0 0.0 0 +chr11 129552588 0 0 0.0 0 +chr11 129640956 0 0 0.0 0 +chr11 129750811 0 0 0.0 0 +chr11 129941951 0 1 0.0159 0 +chr11 130135628 0 0 0.0 0 +chr11 130250058 0 0 0.0 0 +chr11 130296707 0 0 0.0 0 +chr11 130380947 0 0 0.0 0 +chr11 130410058 0 0 0.0 0 +chr11 130605672 0 0 0.0 0 +chr11 130632613 0 0 0.0 0 +chr11 130801867 0 0 0.0 0 +chr11 130830283 0 0 0.0 0 +chr11 130868644 0 0 0.0 0 +chr11 131067876 0 0 0.0 0 +chr11 131131686 0 0 0.0 0 +chr11 131134280 0 0 0.0 0 +chr11 131181222 0 0 0.0 0 +chr11 131226272 0 0 0.0 0 +chr11 131322450 0 0 0.0 0 +chr11 131344211 0 0 0.0 0 +chr11 131512957 0 0 0.0 0 +chr11 131667736 0 0 0.0 0 +chr11 131695585 0 0 0.0 0 +chr11 131728186 0 0 0.0 0 +chr11 131825354 0 0 0.0 0 +chr11 131902230 0 0 0.0 0 +chr11 131932338 0 0 0.0 0 +chr11 131995372 0 0 0.0 0 +chr11 132144975 0 0 0.0 0 +chr11 132146365 0 0 0.0 0 +chr11 132164840 0 0 0.0 0 +chr11 132258526 0 0 0.0 0 +chr11 132281549 0 0 0.0 0 +chr11 132294155 0 0 0.0 0 +chr11 132384287 0 0 0.0 0 +chr11 132452001 0 1 0.025 0 +chr11 132502773 0 0 0.0 0 +chr11 132517371 0 0 0.0 0 +chr11 132547968 0 0 0.0 0 +chr11 132551053 0 0 0.0 0 +chr11 132579314 0 0 0.0 0 +chr11 132643075 0 0 0.0 0 +chr11 132719626 0 0 0.0 0 +chr11 132738820 0 0 0.0 0 +chr11 132861606 0 0 0.0 0 +chr11 132885596 0 0 0.0 0 +chr11 133016416 0 0 0.0 0 +chr11 133102989 0 1 0.025 0 +chr11 133149120 0 0 0.0 0 +chr11 133178021 0 0 0.0 0 +chr11 133273413 0 0 0.0 0 +chr11 133350155 0 1 0.0256 0 +chr11 133359979 0 0 0.0 0 +chr11 133376439 0 0 0.0 0 +chr11 133713920 0 0 0.0 0 +chr11 133809470 0 0 0.0 0 +chr11 133832415 0 0 0.0 0 +chr11 133885111 0 0 0.0 0 +chr11 133956424 0 0 0.0 0 +chr11 133994091 0 0 0.0 0 +chr11 134268282 0 0 0.0 0 +chr11 134294590 0 0 0.0 0 +chr11 134342901 0 0 0.0 0 +chr11 134394087 0 0 0.0 0 +chr11 134463701 0 0 0.0 0 +chr11 134746397 0 0 0.0 0 +chr11 134772440 0 0 0.0 0 +chr11 134849028 0 0 0.0 0 +chr11 134940660 0 0 0.0 0 +chr11_GL383547v1_alt 15786 0 0 0.0 0 +chr11_JH159137v1_alt 141792 0 0 0.0 0 +chr11_KI270721v1_random 55167 0 0 0.0 0 +chr11_KI270721v1_random 57813 0 0 0.0 0 +chr11_KI270721v1_random 89177 0 0 0.0 0 +chr11_KI270826v1_alt 75429 0 0 0.0 0 +chr11_KI270826v1_alt 164240 0 0 0.0 0 +chr11_KI270827v1_alt 2639 0 0 0.0 0 +chr11_KI270829v1_alt 83071 0 0 0.0 0 +chr11_KI270830v1_alt 53635 0 0 0.0 0 +chr11_KI270831v1_alt 139370 0 0 0.0 0 +chr11_KI270831v1_alt 161898 0 0 0.0 0 +chr11_KI270832v1_alt 84718 0 0 0.0 0 +chr11_KI270832v1_alt 136157 0 0 0.0 0 +chr11_KI270903v1_alt 47925 0 0 0.0 0 +chr11_KI270903v1_alt 214435 0 0 0.0 0 +chr11_KI270927v1_alt 113458 0 0 0.0 0 +chr12 114010 0 0 0.0 0 +chr12 139785 0 0 0.0 0 +chr12 157930 0 0 0.0 0 +chr12 220373 0 0 0.0 0 +chr12 343615 0 0 0.0 0 +chr12 494550 0 0 0.0 0 +chr12 510735 0 0 0.0 0 +chr12 628814 0 0 0.0 0 +chr12 635476 0 0 0.0 0 +chr12 723621 0 0 0.0 0 +chr12 878467 0 0 0.0 0 +chr12 883829 0 0 0.0 0 +chr12 910939 0 0 0.0 0 +chr12 913782 0 0 0.0 0 +chr12 968198 0 0 0.0 0 +chr12 970867 0 0 0.0 0 +chr12 1050315 0 0 0.0 0 +chr12 1179298 0 0 0.0 0 +chr12 1487210 0 0 0.0 0 +chr12 1589819 0 0 0.0 0 +chr12 1905079 0 0 0.0 0 +chr12 1966359 0 0 0.0 0 +chr12 2057139 0 0 0.0 0 +chr12 2096028 0 0 0.0 0 +chr12 2219955 0 0 0.0 0 +chr12 2348862 0 0 0.0 0 +chr12 2364756 0 0 0.0 0 +chr12 2387136 0 0 0.0 0 +chr12 2427556 2 26 0.4727 1 +chr12 2571195 0 0 0.0 0 +chr12 2617651 0 0 0.0 0 +chr12 2697951 0 0 0.0 0 +chr12 2736756 0 0 0.0 0 +chr12 2963043 0 0 0.0 0 +chr12 2998020 0 0 0.0 0 +chr12 3044011 0 0 0.0 0 +chr12 3168914 0 0 0.0 0 +chr12 3243772 0 0 0.0 0 +chr12 3300700 0 0 0.0 0 +chr12 3459029 0 1 0.0263 0 +chr12 3578484 0 0 0.0 0 +chr12 3633676 0 0 0.0 0 +chr12 3731659 0 0 0.0 0 +chr12 3910279 0 0 0.0 0 +chr12 4049525 0 0 0.0 0 +chr12 4220773 0 0 0.0 0 +chr12 4291004 0 0 0.0 0 +chr12 4413021 0 0 0.0 0 +chr12 4426064 0 0 0.0 0 +chr12 4665267 0 0 0.0 0 +chr12 4897818 0 0 0.0 0 +chr12 4998442 0 0 0.0 0 +chr12 5194225 0 0 0.0 0 +chr12 5202866 0 0 0.0 0 +chr12 5215202 0 0 0.0 0 +chr12 5387382 0 0 0.0 0 +chr12 5402936 0 0 0.0 0 +chr12 5571497 0 0 0.0 0 +chr12 5584367 0 0 0.0 0 +chr12 5681096 0 0 0.0 0 +chr12 5834958 0 0 0.0 0 +chr12 6022004 0 0 0.0 0 +chr12 6038676 0 0 0.0 0 +chr12 6133762 0 0 0.0 0 +chr12 6163237 0 0 0.0 0 +chr12 6200019 0 0 0.0 0 +chr12 6297349 0 0 0.0 0 +chr12 6372416 0 0 0.0 0 +chr12 6440881 0 0 0.0 0 +chr12 6453529 0 0 0.0 0 +chr12 6571175 0 0 0.0 0 +chr12 6579369 0 0 0.0 0 +chr12 6654816 0 0 0.0 0 +chr12 6821882 0 0 0.0 0 +chr12 6870778 0 0 0.0 0 +chr12 6906380 0 0 0.0 0 +chr12 6945625 0 0 0.0 0 +chr12 6951968 0 0 0.0 0 +chr12 6980304 0 0 0.0 0 +chr12 6984242 0 0 0.0 0 +chr12 6999006 0 0 0.0 0 +chr12 7190388 0 0 0.0 0 +chr12 7264051 0 0 0.0 0 +chr12 7824012 0 0 0.0 0 +chr12 8065863 0 0 0.0 0 +chr12 8088958 0 0 0.0 0 +chr12 8122401 0 0 0.0 0 +chr12 8153756 0 0 0.0 0 +chr12 8289175 0 0 0.0 0 +chr12 8309019 0 0 0.0 0 +chr12 8319542 0 0 0.0 0 +chr12 8354302 0 0 0.0 0 +chr12 8366095 0 0 0.0 0 +chr12 8466500 0 0 0.0 0 +chr12 8610529 0 0 0.0 0 +chr12 8628185 0 0 0.0 0 +chr12 8908675 0 0 0.0 0 +chr12 8932391 0 0 0.0 0 +chr12 9157126 0 0 0.0 0 +chr12 9258838 0 0 0.0 0 +chr12 9311435 0 0 0.0 0 +chr12 9339925 0 0 0.0 0 +chr12 9420371 0 0 0.0 0 +chr12 9468910 0 0 0.0 0 +chr12 9621241 0 0 0.0 0 +chr12 9632556 0 0 0.0 0 +chr12 9739594 0 0 0.0 0 +chr12 9764703 0 0 0.0 0 +chr12 9893006 0 0 0.0 0 +chr12 10296442 0 0 0.0 0 +chr12 10378612 0 0 0.0 0 +chr12 10643180 0 0 0.0 0 +chr12 10928423 0 0 0.0 0 +chr12 10987636 0 0 0.0 0 +chr12 11150670 0 0 0.0 0 +chr12 11267261 0 0 0.0 0 +chr12 11273947 0 0 0.0 0 +chr12 11459396 0 0 0.0 0 +chr12 11471062 0 0 0.0 0 +chr12 11580723 0 0 0.0 0 +chr12 11731030 0 0 0.0 0 +chr12 11745149 0 0 0.0 0 +chr12 11747321 0 0 0.0 0 +chr12 12094761 0 0 0.0 0 +chr12 12359076 0 0 0.0 0 +chr12 12569097 0 1 0.02 0 +chr12 12788926 0 0 0.0 0 +chr12 12878821 0 0 0.0 0 +chr12 13042024 0 0 0.0 0 +chr12 13085775 0 1 0.0115 0 +chr12 13176897 0 0 0.0 0 +chr12 13343935 0 0 0.0 0 +chr12 13416462 0 0 0.0 0 +chr12 13484992 0 0 0.0 0 +chr12 13529956 0 0 0.0 0 +chr12 13752850 0 0 0.0 0 +chr12 13941589 0 0 0.0 0 +chr12 13988278 0 0 0.0 0 +chr12 14080275 0 0 0.0 0 +chr12 14217444 0 0 0.0 0 +chr12 14292341 0 0 0.0 0 +chr12 14424769 0 0 0.0 0 +chr12 14425097 0 0 0.0 0 +chr12 14491031 0 0 0.0 0 +chr12 14735562 0 0 0.0 0 +chr12 14789633 0 0 0.0 0 +chr12 14831730 0 0 0.0 0 +chr12 14908715 0 0 0.0 0 +chr12 15619589 0 0 0.0 0 +chr12 15972517 0 0 0.0 0 +chr12 16060750 0 0 0.0 0 +chr12 16234477 0 0 0.0 0 +chr12 16269374 0 0 0.0 0 +chr12 16313866 0 0 0.0 0 +chr12 16426235 0 0 0.0 0 +chr12 16570505 0 0 0.0 0 +chr12 16729614 0 0 0.0 0 +chr12 17135598 0 0 0.0 0 +chr12 17472050 0 0 0.0 0 +chr12 17723829 0 0 0.0 0 +chr12 17743154 0 0 0.0 0 +chr12 17920209 0 0 0.0 0 +chr12 18024663 0 0 0.0 0 +chr12 18034827 0 0 0.0 0 +chr12 18057931 0 0 0.0 0 +chr12 18134920 0 0 0.0 0 +chr12 18218888 0 0 0.0 0 +chr12 18272285 0 0 0.0 0 +chr12 18278510 0 0 0.0 0 +chr12 18761242 0 0 0.0 0 +chr12 18768673 0 0 0.0 0 +chr12 18786086 0 0 0.0 0 +chr12 18923327 0 0 0.0 0 +chr12 19005271 0 0 0.0 0 +chr12 19230716 0 0 0.0 0 +chr12 19322393 0 0 0.0 0 +chr12 19423437 0 0 0.0 0 +chr12 19539426 0 0 0.0 0 +chr12 19590656 0 0 0.0 0 +chr12 19638991 0 0 0.0 0 +chr12 19794470 0 0 0.0 0 +chr12 19799569 0 0 0.0 0 +chr12 19818999 0 0 0.0 0 +chr12 19894638 0 0 0.0 0 +chr12 20201558 0 0 0.0 0 +chr12 20293856 0 0 0.0 0 +chr12 20336481 0 0 0.0 0 +chr12 20402888 0 0 0.0 0 +chr12 20453102 0 0 0.0 0 +chr12 20469096 0 1 0.0233 0 +chr12 20509228 0 0 0.0 0 +chr12 20533575 0 0 0.0 0 +chr12 20680194 0 0 0.0 0 +chr12 20765559 0 1 0.0227 0 +chr12 20820553 0 0 0.0 0 +chr12 20987938 0 0 0.0 0 +chr12 21425071 0 0 0.0 0 +chr12 21583674 0 0 0.0 0 +chr12 21590423 0 0 0.0 0 +chr12 21638344 0 0 0.0 0 +chr12 21683122 0 0 0.0 0 +chr12 21787014 0 0 0.0 0 +chr12 21827108 0 0 0.0 0 +chr12 21983883 0 0 0.0 0 +chr12 21996300 0 0 0.0 0 +chr12 22194781 0 1 0.02 0 +chr12 22307639 0 0 0.0 0 +chr12 22366230 0 0 0.0 0 +chr12 22452822 0 0 0.0 0 +chr12 22971328 0 0 0.0 0 +chr12 22974011 0 0 0.0 0 +chr12 23026534 0 0 0.0 0 +chr12 23195155 0 0 0.0 0 +chr12 23712311 0 0 0.0 0 +chr12 23746819 0 0 0.0 0 +chr12 23749869 0 0 0.0 0 +chr12 23863108 0 0 0.0 0 +chr12 23940856 0 0 0.0 0 +chr12 23993586 0 0 0.0 0 +chr12 24017932 0 0 0.0 0 +chr12 24191911 0 0 0.0 0 +chr12 24356679 0 0 0.0 0 +chr12 24393785 0 0 0.0 0 +chr12 24466943 0 0 0.0 0 +chr12 24624929 0 0 0.0 0 +chr12 24775011 0 0 0.0 0 +chr12 24780530 0 0 0.0 0 +chr12 24903529 0 0 0.0 0 +chr12 25069866 0 0 0.0 0 +chr12 25115329 0 0 0.0 0 +chr12 25303256 0 0 0.0 0 +chr12 25446737 0 0 0.0 0 +chr12 25518535 0 0 0.0 0 +chr12 25665740 0 0 0.0 0 +chr12 25671785 0 0 0.0 0 +chr12 25818475 0 0 0.0 0 +chr12 25827899 0 0 0.0 0 +chr12 25864691 0 0 0.0 0 +chr12 25961313 0 0 0.0 0 +chr12 26100328 0 0 0.0 0 +chr12 26232225 0 0 0.0 0 +chr12 26434468 0 0 0.0 0 +chr12 26504907 0 0 0.0 0 +chr12 26507570 0 0 0.0 0 +chr12 26728044 0 0 0.0 0 +chr12 26792920 0 0 0.0 0 +chr12 26819524 0 0 0.0 0 +chr12 26974764 0 0 0.0 0 +chr12 27033433 0 0 0.0 0 +chr12 27097627 0 0 0.0 0 +chr12 27466206 0 0 0.0 0 +chr12 27540639 0 0 0.0 0 +chr12 27642385 0 0 0.0 0 +chr12 27713403 0 0 0.0 0 +chr12 27814588 0 0 0.0 0 +chr12 28059982 0 0 0.0 0 +chr12 28079511 0 0 0.0 0 +chr12 28230176 0 0 0.0 0 +chr12 28313714 0 0 0.0 0 +chr12 28418180 0 0 0.0 0 +chr12 28516162 0 0 0.0 0 +chr12 28540925 0 0 0.0 0 +chr12 28726191 0 0 0.0 0 +chr12 28784258 0 0 0.0 0 +chr12 28881567 0 0 0.0 0 +chr12 28894022 0 0 0.0 0 +chr12 29166473 0 0 0.0 0 +chr12 29453293 0 0 0.0 0 +chr12 29495205 0 0 0.0 0 +chr12 29757519 0 0 0.0 0 +chr12 30124796 0 0 0.0 0 +chr12 30296427 0 0 0.0 0 +chr12 30486013 0 0 0.0 0 +chr12 30604455 0 0 0.0 0 +chr12 30605007 0 0 0.0 0 +chr12 30616979 0 0 0.0 0 +chr12 30629890 0 0 0.0 0 +chr12 30663092 0 0 0.0 0 +chr12 30711581 0 0 0.0 0 +chr12 30824085 0 1 0.0192 0 +chr12 30870817 0 0 0.0 0 +chr12 30884471 0 0 0.0 0 +chr12 30884707 0 0 0.0 0 +chr12 30894349 0 0 0.0 0 +chr12 30895713 0 0 0.0 0 +chr12 30950141 0 0 0.0 0 +chr12 31031875 0 0 0.0 0 +chr12 31032976 0 0 0.0 0 +chr12 31102128 1 14 0.4242 1 +chr12 31176089 0 0 0.0 0 +chr12 31219229 0 0 0.0 0 +chr12 31242099 0 0 0.0 0 +chr12 31490652 0 0 0.0 0 +chr12 31570370 0 0 0.0 0 +chr12 31680659 0 0 0.0 0 +chr12 31784891 0 0 0.0 0 +chr12 31815385 0 0 0.0 0 +chr12 31940976 0 0 0.0 0 +chr12 32060030 0 0 0.0 0 +chr12 32233042 0 0 0.0 0 +chr12 32281476 0 0 0.0 0 +chr12 32301094 0 0 0.0 0 +chr12 32328759 0 0 0.0 0 +chr12 32357546 0 0 0.0 0 +chr12 32361914 0 0 0.0 0 +chr12 32429338 0 0 0.0 0 +chr12 32434847 0 0 0.0 0 +chr12 32437579 0 0 0.0 0 +chr12 32617898 0 0 0.0 0 +chr12 32679413 0 0 0.0 0 +chr12 32699649 0 0 0.0 0 +chr12 32809255 0 0 0.0 0 +chr12 32816702 0 0 0.0 0 +chr12 33179895 0 0 0.0 0 +chr12 33239964 0 0 0.0 0 +chr12 33558235 0 0 0.0 0 +chr12 33595228 0 0 0.0 0 +chr12 33698242 0 0 0.0 0 +chr12 33914739 0 0 0.0 0 +chr12 33920670 0 0 0.0 0 +chr12 33978563 0 0 0.0 0 +chr12 34084108 0 0 0.0 0 +chr12 34100532 0 0 0.0 0 +chr12 34147768 0 0 0.0 0 +chr12 34214960 0 0 0.0 0 +chr12 34267820 0 0 0.0 0 +chr12 34293196 0 0 0.0 0 +chr12 34431867 0 0 0.0 0 +chr12 34450126 0 0 0.0 0 +chr12 34450954 0 0 0.0 0 +chr12 34493588 0 0 0.0 0 +chr12 34607333 0 0 0.0 0 +chr12 37276233 0 0 0.0 0 +chr12 37293253 0 0 0.0 0 +chr12 37311098 0 0 0.0 0 +chr12 37342117 0 0 0.0 0 +chr12 37410317 0 0 0.0 0 +chr12 37412524 0 0 0.0 0 +chr12 37416762 0 0 0.0 0 +chr12 37572712 0 0 0.0 0 +chr12 37604629 0 0 0.0 0 +chr12 37639698 0 0 0.0 0 +chr12 37682482 0 0 0.0 0 +chr12 37686699 0 0 0.0 0 +chr12 37730095 0 0 0.0 0 +chr12 37762574 0 0 0.0 0 +chr12 37913300 0 0 0.0 0 +chr12 38106460 0 0 0.0 0 +chr12 38177085 0 0 0.0 0 +chr12 38186159 0 0 0.0 0 +chr12 38223770 0 0 0.0 0 +chr12 38270561 0 0 0.0 0 +chr12 38279238 0 0 0.0 0 +chr12 38587607 0 0 0.0 0 +chr12 38732093 0 0 0.0 0 +chr12 38797430 0 0 0.0 0 +chr12 38869110 0 0 0.0 0 +chr12 38898909 0 0 0.0 0 +chr12 39181793 0 0 0.0 0 +chr12 39412474 0 0 0.0 0 +chr12 39695082 0 0 0.0 0 +chr12 39921383 0 0 0.0 0 +chr12 39943625 0 0 0.0 0 +chr12 40049647 0 0 0.0 0 +chr12 40229565 0 0 0.0 0 +chr12 40388066 0 0 0.0 0 +chr12 40872433 0 0 0.0 0 +chr12 41075274 0 0 0.0 0 +chr12 41087893 0 0 0.0 0 +chr12 41304720 0 0 0.0 0 +chr12 41310859 0 0 0.0 0 +chr12 41345459 0 0 0.0 0 +chr12 41358458 0 0 0.0 0 +chr12 41393830 0 0 0.0 0 +chr12 41464766 0 0 0.0 0 +chr12 41557887 0 0 0.0 0 +chr12 41784251 0 0 0.0 0 +chr12 41832824 0 0 0.0 0 +chr12 41870823 0 0 0.0 0 +chr12 41984209 0 0 0.0 0 +chr12 42136593 0 0 0.0 0 +chr12 42287585 0 0 0.0 0 +chr12 42409716 0 1 0.0167 0 +chr12 42576808 0 0 0.0 0 +chr12 42632680 0 0 0.0 0 +chr12 42708485 0 0 0.0 0 +chr12 43034810 0 1 0.0278 0 +chr12 43170729 0 0 0.0 0 +chr12 43309596 0 0 0.0 0 +chr12 43403625 0 0 0.0 0 +chr12 43435565 0 0 0.0 0 +chr12 43500330 0 0 0.0 0 +chr12 43640783 0 0 0.0 0 +chr12 43757570 0 0 0.0 0 +chr12 43838327 0 0 0.0 0 +chr12 43864273 0 0 0.0 0 +chr12 43917507 0 0 0.0 0 +chr12 43947013 0 0 0.0 0 +chr12 43965400 0 0 0.0 0 +chr12 43987029 0 0 0.0 0 +chr12 44193796 0 0 0.0 0 +chr12 44248064 0 0 0.0 0 +chr12 44448039 0 0 0.0 0 +chr12 44579288 0 0 0.0 0 +chr12 44668808 0 0 0.0 0 +chr12 44696711 0 0 0.0 0 +chr12 44712863 0 0 0.0 0 +chr12 44915955 0 0 0.0 0 +chr12 45016031 0 0 0.0 0 +chr12 45528119 0 0 0.0 0 +chr12 45590819 0 0 0.0 0 +chr12 45666475 0 0 0.0 0 +chr12 45686102 0 0 0.0 0 +chr12 45768357 0 0 0.0 0 +chr12 45819419 0 0 0.0 0 +chr12 46087021 0 0 0.0 0 +chr12 46171911 0 0 0.0 0 +chr12 46378023 0 0 0.0 0 +chr12 46441668 0 0 0.0 0 +chr12 46470987 0 0 0.0 0 +chr12 46518493 0 0 0.0 0 +chr12 46519965 0 0 0.0 0 +chr12 46618363 0 0 0.0 0 +chr12 46704452 0 0 0.0 0 +chr12 46843952 0 0 0.0 0 +chr12 46864815 0 0 0.0 0 +chr12 46919851 0 0 0.0 0 +chr12 46986297 0 0 0.0 0 +chr12 47019323 0 0 0.0 0 +chr12 47105836 0 0 0.0 0 +chr12 47152599 0 0 0.0 0 +chr12 47278272 0 0 0.0 0 +chr12 47307576 0 0 0.0 0 +chr12 47424671 0 0 0.0 0 +chr12 47448199 0 0 0.0 0 +chr12 47525881 0 0 0.0 0 +chr12 47526458 0 0 0.0 0 +chr12 47528933 0 0 0.0 0 +chr12 47557892 0 0 0.0 0 +chr12 47740793 0 0 0.0 0 +chr12 47777317 0 0 0.0 0 +chr12 47842186 0 0 0.0 0 +chr12 48044037 0 0 0.0 0 +chr12 48137749 0 0 0.0 0 +chr12 48144849 0 0 0.0 0 +chr12 48225812 0 0 0.0 0 +chr12 48330703 0 0 0.0 0 +chr12 48434643 0 0 0.0 0 +chr12 48445098 0 0 0.0 0 +chr12 48473970 0 0 0.0 0 +chr12 48671020 0 0 0.0 0 +chr12 48695936 0 0 0.0 0 +chr12 48737078 0 0 0.0 0 +chr12 48745500 0 0 0.0 0 +chr12 48850777 0 0 0.0 0 +chr12 48855468 0 0 0.0 0 +chr12 49010154 0 0 0.0 0 +chr12 49092587 0 0 0.0 0 +chr12 49102356 0 0 0.0 0 +chr12 49127592 0 0 0.0 0 +chr12 49245294 0 0 0.0 0 +chr12 49289543 0 0 0.0 0 +chr12 49349177 0 0 0.0 0 +chr12 49503845 0 0 0.0 0 +chr12 49546567 0 0 0.0 0 +chr12 49587045 0 0 0.0 0 +chr12 49648313 0 0 0.0 0 +chr12 49659937 0 0 0.0 0 +chr12 49771048 0 0 0.0 0 +chr12 49780128 0 0 0.0 0 +chr12 49944996 0 0 0.0 0 +chr12 50602396 0 0 0.0 0 +chr12 50640819 0 1 0.0159 0 +chr12 50692595 0 0 0.0 0 +chr12 50906618 0 0 0.0 0 +chr12 50921248 0 0 0.0 0 +chr12 50944053 0 0 0.0 0 +chr12 50964440 0 0 0.0 0 +chr12 51000413 0 0 0.0 0 +chr12 51011947 0 0 0.0 0 +chr12 51079520 0 0 0.0 0 +chr12 51086291 0 0 0.0 0 +chr12 51098673 0 0 0.0 0 +chr12 51306554 0 0 0.0 0 +chr12 51345832 0 0 0.0 0 +chr12 51355359 0 0 0.0 0 +chr12 51360893 0 0 0.0 0 +chr12 51387070 0 0 0.0 0 +chr12 51499549 0 0 0.0 0 +chr12 51546970 0 0 0.0 0 +chr12 51577843 0 0 0.0 0 +chr12 51730292 0 0 0.0 0 +chr12 51748774 0 0 0.0 0 +chr12 51775530 0 0 0.0 0 +chr12 51821382 0 0 0.0 0 +chr12 51903486 0 0 0.0 0 +chr12 51913106 0 0 0.0 0 +chr12 51976358 0 0 0.0 0 +chr12 52000521 0 0 0.0 0 +chr12 52135315 0 0 0.0 0 +chr12 52171462 0 0 0.0 0 +chr12 52210415 0 0 0.0 0 +chr12 52253856 0 0 0.0 0 +chr12 52328012 0 0 0.0 0 +chr12 52366054 0 0 0.0 0 +chr12 52378266 0 0 0.0 0 +chr12 52432082 0 0 0.0 0 +chr12 52532567 0 0 0.0 0 +chr12 52584088 0 0 0.0 0 +chr12 52591535 0 0 0.0 0 +chr12 52646044 0 0 0.0 0 +chr12 52672958 0 0 0.0 0 +chr12 52684899 0 0 0.0 0 +chr12 52716588 0 0 0.0 0 +chr12 52747746 0 0 0.0 0 +chr12 52764847 0 0 0.0 0 +chr12 52808828 0 0 0.0 0 +chr12 52832674 0 0 0.0 0 +chr12 52839300 0 0 0.0 0 +chr12 52910613 0 0 0.0 0 +chr12 52926058 0 0 0.0 0 +chr12 53040129 0 0 0.0 0 +chr12 53092001 0 0 0.0 0 +chr12 53154794 0 0 0.0 0 +chr12 53234611 0 0 0.0 0 +chr12 53338927 0 1 0.0204 0 +chr12 53517032 0 1 0.012 0 +chr12 53588111 0 0 0.0 0 +chr12 53596055 0 0 0.0 0 +chr12 53729090 0 0 0.0 0 +chr12 53736198 0 0 0.0 0 +chr12 53765207 0 0 0.0 0 +chr12 53856011 0 0 0.0 0 +chr12 53917460 0 0 0.0 0 +chr12 53952101 0 0 0.0 0 +chr12 53961298 0 0 0.0 0 +chr12 53975123 0 1 0.0303 0 +chr12 54031742 0 0 0.0 0 +chr12 54236028 0 0 0.0 0 +chr12 54379845 0 0 0.0 0 +chr12 54417357 0 0 0.0 0 +chr12 54537319 0 0 0.0 0 +chr12 54564784 0 0 0.0 0 +chr12 54575772 0 0 0.0 0 +chr12 54696700 0 1 0.0217 0 +chr12 54752911 0 0 0.0 0 +chr12 54840198 0 0 0.0 0 +chr12 54918745 0 0 0.0 0 +chr12 55010723 0 0 0.0 0 +chr12 55052192 0 0 0.0 0 +chr12 55057578 0 0 0.0 0 +chr12 55436942 0 0 0.0 0 +chr12 55647464 0 0 0.0 0 +chr12 55695712 0 0 0.0 0 +chr12 55722454 0 0 0.0 0 +chr12 55725046 0 0 0.0 0 +chr12 55828346 0 0 0.0 0 +chr12 55870245 0 0 0.0 0 +chr12 56035876 0 0 0.0 0 +chr12 56160319 0 0 0.0 0 +chr12 56205671 0 0 0.0 0 +chr12 56453037 0 0 0.0 0 +chr12 56558722 0 0 0.0 0 +chr12 56688770 0 0 0.0 0 +chr12 56924147 0 0 0.0 0 +chr12 56990720 0 1 0.0286 0 +chr12 57133899 0 1 0.0256 0 +chr12 57191020 0 0 0.0 0 +chr12 57206414 0 0 0.0 0 +chr12 57240479 0 0 0.0 0 +chr12 57489107 0 0 0.0 0 +chr12 57599178 0 0 0.0 0 +chr12 57656132 0 0 0.0 0 +chr12 57697611 0 0 0.0 0 +chr12 57756618 0 0 0.0 0 +chr12 57800379 0 0 0.0 0 +chr12 57811310 0 0 0.0 0 +chr12 57822866 0 0 0.0 0 +chr12 58118764 0 0 0.0 0 +chr12 58358005 0 0 0.0 0 +chr12 58656502 0 0 0.0 0 +chr12 58744051 0 0 0.0 0 +chr12 58938284 0 0 0.0 0 +chr12 58939620 0 0 0.0 0 +chr12 59215396 0 0 0.0 0 +chr12 59268752 0 0 0.0 0 +chr12 59403454 0 0 0.0 0 +chr12 59565739 0 0 0.0 0 +chr12 59588214 0 0 0.0 0 +chr12 59622996 0 0 0.0 0 +chr12 59670346 0 0 0.0 0 +chr12 59691284 0 0 0.0 0 +chr12 59727075 0 0 0.0 0 +chr12 60234966 0 0 0.0 0 +chr12 60264488 0 0 0.0 0 +chr12 60745730 0 0 0.0 0 +chr12 60798889 0 0 0.0 0 +chr12 60936609 0 0 0.0 0 +chr12 60977205 0 0 0.0 0 +chr12 61071297 0 0 0.0 0 +chr12 61128502 0 1 0.0175 0 +chr12 61208874 0 0 0.0 0 +chr12 61389191 0 0 0.0 0 +chr12 61522972 0 0 0.0 0 +chr12 61546344 0 0 0.0 0 +chr12 61549821 0 0 0.0 0 +chr12 61575715 0 0 0.0 0 +chr12 61723858 0 0 0.0 0 +chr12 61734683 0 0 0.0 0 +chr12 61984155 0 0 0.0 0 +chr12 62083766 0 0 0.0 0 +chr12 62125129 0 0 0.0 0 +chr12 62140935 0 0 0.0 0 +chr12 62145372 0 0 0.0 0 +chr12 62260855 0 0 0.0 0 +chr12 62328354 0 0 0.0 0 +chr12 62392710 0 0 0.0 0 +chr12 62542578 0 0 0.0 0 +chr12 62636191 0 0 0.0 0 +chr12 62724385 0 0 0.0 0 +chr12 62885792 0 0 0.0 0 +chr12 62888812 0 0 0.0 0 +chr12 62904368 0 0 0.0 0 +chr12 63023372 0 0 0.0 0 +chr12 63167203 0 0 0.0 0 +chr12 63294296 0 0 0.0 0 +chr12 63313485 0 0 0.0 0 +chr12 63435021 0 0 0.0 0 +chr12 63511772 0 0 0.0 0 +chr12 63753185 0 0 0.0 0 +chr12 63824640 0 0 0.0 0 +chr12 63876279 0 0 0.0 0 +chr12 63891201 0 0 0.0 0 +chr12 63960882 0 0 0.0 0 +chr12 64087141 0 0 0.0 0 +chr12 64107907 0 0 0.0 0 +chr12 64112147 0 0 0.0 0 +chr12 64154130 0 0 0.0 0 +chr12 64160460 0 0 0.0 0 +chr12 64174344 0 1 0.0256 0 +chr12 64248629 0 0 0.0 0 +chr12 64276007 1 18 0.3913 1 +chr12 64293441 0 0 0.0 0 +chr12 64334845 0 0 0.0 0 +chr12 64343904 0 0 0.0 0 +chr12 64389994 0 0 0.0 0 +chr12 64682771 0 0 0.0 0 +chr12 64687985 0 1 0.0263 0 +chr12 64741275 0 0 0.0 0 +chr12 64981677 0 0 0.0 0 +chr12 65217034 0 0 0.0 0 +chr12 65230070 0 0 0.0 0 +chr12 65360215 0 0 0.0 0 +chr12 65463005 0 0 0.0 0 +chr12 65520420 0 0 0.0 0 +chr12 65714669 0 0 0.0 0 +chr12 66234565 0 0 0.0 0 +chr12 66296058 0 0 0.0 0 +chr12 66301058 0 0 0.0 0 +chr12 66308848 0 0 0.0 0 +chr12 66608593 0 0 0.0 0 +chr12 66647512 0 0 0.0 0 +chr12 66788612 0 0 0.0 0 +chr12 66965068 0 0 0.0 0 +chr12 66985579 0 0 0.0 0 +chr12 67089484 0 0 0.0 0 +chr12 67115747 0 0 0.0 0 +chr12 67156473 0 0 0.0 0 +chr12 67326449 0 0 0.0 0 +chr12 67348731 0 0 0.0 0 +chr12 67377655 0 0 0.0 0 +chr12 67469315 0 0 0.0 0 +chr12 67592739 0 0 0.0 0 +chr12 67841168 0 0 0.0 0 +chr12 67958488 0 0 0.0 0 +chr12 68020761 0 0 0.0 0 +chr12 68097549 0 0 0.0 0 +chr12 68171771 0 0 0.0 0 +chr12 68291139 0 0 0.0 0 +chr12 68456168 0 0 0.0 0 +chr12 68646389 0 0 0.0 0 +chr12 68793571 0 0 0.0 0 +chr12 69054162 0 0 0.0 0 +chr12 69094177 0 0 0.0 0 +chr12 69198451 0 0 0.0 0 +chr12 69246410 0 0 0.0 0 +chr12 69314628 0 0 0.0 0 +chr12 69442341 0 1 0.0179 0 +chr12 69566936 0 0 0.0 0 +chr12 69836146 0 0 0.0 0 +chr12 69950353 0 0 0.0 0 +chr12 69957482 0 0 0.0 0 +chr12 70206695 0 0 0.0 0 +chr12 70389087 0 0 0.0 0 +chr12 70409357 0 0 0.0 0 +chr12 70510886 0 0 0.0 0 +chr12 70678342 0 0 0.0 0 +chr12 71019062 0 0 0.0 0 +chr12 71027318 0 0 0.0 0 +chr12 71055332 0 0 0.0 0 +chr12 71151793 0 0 0.0 0 +chr12 71266450 0 0 0.0 0 +chr12 71358587 0 0 0.0 0 +chr12 71364434 0 0 0.0 0 +chr12 71476818 0 0 0.0 0 +chr12 71482563 0 0 0.0 0 +chr12 71804778 0 0 0.0 0 +chr12 71926669 0 0 0.0 0 +chr12 71975104 0 0 0.0 0 +chr12 72010663 0 0 0.0 0 +chr12 72048183 0 0 0.0 0 +chr12 72104821 0 0 0.0 0 +chr12 72114145 1 31 0.7561 1 +chr12 72280118 0 0 0.0 0 +chr12 72295341 0 0 0.0 0 +chr12 73171505 0 0 0.0 0 +chr12 73192173 0 0 0.0 0 +chr12 73299801 0 0 0.0 0 +chr12 73572688 0 0 0.0 0 +chr12 73799191 0 0 0.0 0 +chr12 74003969 0 0 0.0 0 +chr12 74105525 0 0 0.0 0 +chr12 74319961 0 0 0.0 0 +chr12 74488408 0 0 0.0 0 +chr12 74619849 0 0 0.0 0 +chr12 74727009 0 0 0.0 0 +chr12 74936788 0 0 0.0 0 +chr12 74979298 0 0 0.0 0 +chr12 75197823 0 0 0.0 0 +chr12 75204699 0 0 0.0 0 +chr12 75264623 0 0 0.0 0 +chr12 75297262 0 0 0.0 0 +chr12 75438074 0 0 0.0 0 +chr12 75443307 0 0 0.0 0 +chr12 75453522 0 0 0.0 0 +chr12 75466994 0 0 0.0 0 +chr12 75520856 0 0 0.0 0 +chr12 75533950 0 0 0.0 0 +chr12 75632483 0 0 0.0 0 +chr12 75719389 0 0 0.0 0 +chr12 75744601 0 0 0.0 0 +chr12 76068634 0 0 0.0 0 +chr12 76115154 0 0 0.0 0 +chr12 76169182 0 0 0.0 0 +chr12 76198230 0 0 0.0 0 +chr12 76268438 0 0 0.0 0 +chr12 76571454 0 0 0.0 0 +chr12 76908183 0 0 0.0 0 +chr12 77012349 0 0 0.0 0 +chr12 77071414 0 0 0.0 0 +chr12 77459256 0 0 0.0 0 +chr12 77524081 0 0 0.0 0 +chr12 77781820 0 0 0.0 0 +chr12 77897967 0 0 0.0 0 +chr12 77934668 0 0 0.0 0 +chr12 78039231 0 0 0.0 0 +chr12 78191966 0 0 0.0 0 +chr12 78285654 0 0 0.0 0 +chr12 78369692 0 0 0.0 0 +chr12 78624595 1 3 0.0448 1 +chr12 78642877 0 0 0.0 0 +chr12 78652518 0 0 0.0 0 +chr12 78889817 0 0 0.0 0 +chr12 78971365 0 0 0.0 0 +chr12 79021212 0 0 0.0 0 +chr12 79143489 0 0 0.0 0 +chr12 79249649 0 0 0.0 0 +chr12 79360454 0 0 0.0 0 +chr12 79438720 0 0 0.0 0 +chr12 79483106 0 0 0.0 0 +chr12 79484995 0 0 0.0 0 +chr12 79574239 0 0 0.0 0 +chr12 79777619 0 0 0.0 0 +chr12 80038203 0 0 0.0 0 +chr12 80386704 0 0 0.0 0 +chr12 80453649 0 0 0.0 0 +chr12 80462748 0 0 0.0 0 +chr12 80823152 0 0 0.0 0 +chr12 80915462 0 0 0.0 0 +chr12 80919631 0 0 0.0 0 +chr12 80986544 0 0 0.0 0 +chr12 81353345 0 0 0.0 0 +chr12 81455950 0 0 0.0 0 +chr12 81605169 0 0 0.0 0 +chr12 81611906 0 0 0.0 0 +chr12 81723764 0 0 0.0 0 +chr12 81768011 0 0 0.0 0 +chr12 81846698 0 0 0.0 0 +chr12 81860571 0 0 0.0 0 +chr12 81900794 0 0 0.0 0 +chr12 82043930 0 0 0.0 0 +chr12 82143805 0 0 0.0 0 +chr12 82321216 0 0 0.0 0 +chr12 82376114 0 0 0.0 0 +chr12 82565593 0 0 0.0 0 +chr12 82660272 0 0 0.0 0 +chr12 82937508 1 73 0.9359 1 +chr12 83232681 0 0 0.0 0 +chr12 83407910 0 0 0.0 0 +chr12 83444538 0 0 0.0 0 +chr12 83622052 0 0 0.0 0 +chr12 83714458 0 0 0.0 0 +chr12 83741298 0 0 0.0 0 +chr12 83858050 0 0 0.0 0 +chr12 83933078 0 0 0.0 0 +chr12 84028913 0 0 0.0 0 +chr12 84225632 0 0 0.0 0 +chr12 84559251 0 0 0.0 0 +chr12 84740753 0 1 0.0263 0 +chr12 84857411 0 0 0.0 0 +chr12 85148711 0 0 0.0 0 +chr12 85345819 0 0 0.0 0 +chr12 85353529 0 0 0.0 0 +chr12 85426704 0 0 0.0 0 +chr12 85488053 0 0 0.0 0 +chr12 85593619 0 0 0.0 0 +chr12 85729992 0 0 0.0 0 +chr12 85827921 0 0 0.0 0 +chr12 85842001 0 0 0.0 0 +chr12 85977204 0 0 0.0 0 +chr12 86062226 0 0 0.0 0 +chr12 86300110 0 0 0.0 0 +chr12 86590749 0 0 0.0 0 +chr12 86650721 0 0 0.0 0 +chr12 86675724 0 0 0.0 0 +chr12 86833690 0 0 0.0 0 +chr12 86965589 0 0 0.0 0 +chr12 87167206 0 0 0.0 0 +chr12 87247165 0 0 0.0 0 +chr12 87426260 0 0 0.0 0 +chr12 88046484 0 0 0.0 0 +chr12 88082584 0 0 0.0 0 +chr12 88117819 0 0 0.0 0 +chr12 88366550 0 0 0.0 0 +chr12 88454188 0 0 0.0 0 +chr12 88574333 0 0 0.0 0 +chr12 88574485 0 0 0.0 0 +chr12 88588500 0 0 0.0 0 +chr12 88639528 0 0 0.0 0 +chr12 88655825 0 0 0.0 0 +chr12 88782548 0 0 0.0 0 +chr12 89099333 0 0 0.0 0 +chr12 89206799 0 0 0.0 0 +chr12 89222870 0 0 0.0 0 +chr12 89263815 0 0 0.0 0 +chr12 89284363 0 0 0.0 0 +chr12 89364284 0 0 0.0 0 +chr12 89375223 0 0 0.0 0 +chr12 89382991 0 0 0.0 0 +chr12 89386757 0 0 0.0 0 +chr12 89507768 0 0 0.0 0 +chr12 89528445 0 0 0.0 0 +chr12 89617972 0 0 0.0 0 +chr12 89759629 0 0 0.0 0 +chr12 89873455 0 0 0.0 0 +chr12 89947571 0 0 0.0 0 +chr12 89997348 0 0 0.0 0 +chr12 90413429 0 0 0.0 0 +chr12 90464109 0 0 0.0 0 +chr12 90503445 0 0 0.0 0 +chr12 90813855 0 0 0.0 0 +chr12 91045374 0 0 0.0 0 +chr12 91074695 0 0 0.0 0 +chr12 91462716 0 0 0.0 0 +chr12 91545948 0 0 0.0 0 +chr12 91613672 0 0 0.0 0 +chr12 91741803 0 0 0.0 0 +chr12 91833257 0 0 0.0 0 +chr12 91960209 0 0 0.0 0 +chr12 91970938 0 0 0.0 0 +chr12 91978541 0 0 0.0 0 +chr12 92407215 0 0 0.0 0 +chr12 92516591 0 0 0.0 0 +chr12 92570273 0 0 0.0 0 +chr12 92763903 0 0 0.0 0 +chr12 92835672 0 0 0.0 0 +chr12 92879783 0 0 0.0 0 +chr12 92911658 0 1 0.0139 0 +chr12 93280119 0 0 0.0 0 +chr12 93340174 0 0 0.0 0 +chr12 93532517 0 0 0.0 0 +chr12 93833045 0 0 0.0 0 +chr12 93868882 0 0 0.0 0 +chr12 93900419 0 0 0.0 0 +chr12 93918587 0 0 0.0 0 +chr12 94008077 0 0 0.0 0 +chr12 94065105 0 0 0.0 0 +chr12 94226575 0 0 0.0 0 +chr12 94271996 0 0 0.0 0 +chr12 94574083 0 0 0.0 0 +chr12 94685383 0 0 0.0 0 +chr12 94713727 0 0 0.0 0 +chr12 94860659 0 0 0.0 0 +chr12 94892057 0 0 0.0 0 +chr12 94908709 0 0 0.0 0 +chr12 94915875 0 0 0.0 0 +chr12 94934216 0 0 0.0 0 +chr12 94948019 0 0 0.0 0 +chr12 94948590 0 0 0.0 0 +chr12 95228146 0 0 0.0 0 +chr12 95280064 0 0 0.0 0 +chr12 95313256 0 0 0.0 0 +chr12 95453668 0 0 0.0 0 +chr12 95455291 0 0 0.0 0 +chr12 95458798 0 0 0.0 0 +chr12 95892413 0 0 0.0 0 +chr12 96007419 0 0 0.0 0 +chr12 96141276 0 0 0.0 0 +chr12 96144473 0 0 0.0 0 +chr12 96660302 0 1 0.0244 0 +chr12 96717416 0 0 0.0 0 +chr12 96728959 0 0 0.0 0 +chr12 96739157 0 0 0.0 0 +chr12 96778864 0 0 0.0 0 +chr12 96894731 0 0 0.0 0 +chr12 97003821 0 0 0.0 0 +chr12 97009069 0 0 0.0 0 +chr12 97052739 0 0 0.0 0 +chr12 97532270 0 0 0.0 0 +chr12 97581684 0 0 0.0 0 +chr12 97731628 0 0 0.0 0 +chr12 97840106 0 0 0.0 0 +chr12 97867512 0 0 0.0 0 +chr12 97979767 0 0 0.0 0 +chr12 98155137 0 0 0.0 0 +chr12 98202827 0 0 0.0 0 +chr12 98243524 0 0 0.0 0 +chr12 98335782 0 0 0.0 0 +chr12 98342075 0 0 0.0 0 +chr12 98852219 0 0 0.0 0 +chr12 98917909 0 0 0.0 0 +chr12 99048577 0 0 0.0 0 +chr12 99048791 0 0 0.0 0 +chr12 99076742 0 0 0.0 0 +chr12 99106033 0 0 0.0 0 +chr12 99438382 0 0 0.0 0 +chr12 99601599 0 0 0.0 0 +chr12 99605910 0 0 0.0 0 +chr12 99810082 0 0 0.0 0 +chr12 100078449 0 0 0.0 0 +chr12 100210475 0 0 0.0 0 +chr12 100287309 0 0 0.0 0 +chr12 100352677 0 0 0.0 0 +chr12 100457158 0 1 0.037 0 +chr12 100491578 0 0 0.0 0 +chr12 100959300 0 0 0.0 0 +chr12 101062755 0 0 0.0 0 +chr12 101170784 0 0 0.0 0 +chr12 101856901 0 0 0.0 0 +chr12 101966555 0 0 0.0 0 +chr12 102005166 0 0 0.0 0 +chr12 102361479 0 0 0.0 0 +chr12 102534792 0 0 0.0 0 +chr12 102810129 0 0 0.0 0 +chr12 102856714 0 0 0.0 0 +chr12 102874851 0 0 0.0 0 +chr12 103190752 0 0 0.0 0 +chr12 103289009 0 0 0.0 0 +chr12 103383070 0 0 0.0 0 +chr12 103424979 0 0 0.0 0 +chr12 103510604 0 0 0.0 0 +chr12 103515552 0 0 0.0 0 +chr12 103543987 0 0 0.0 0 +chr12 103659960 0 0 0.0 0 +chr12 103671647 0 0 0.0 0 +chr12 103692649 3 37 0.9024 1 +chr12 103779873 0 0 0.0 0 +chr12 103856967 0 0 0.0 0 +chr12 103862927 0 0 0.0 0 +chr12 103963372 0 0 0.0 0 +chr12 104010284 0 0 0.0 0 +chr12 104216550 0 0 0.0 0 +chr12 104293409 0 0 0.0 0 +chr12 104295550 0 0 0.0 0 +chr12 104303989 0 0 0.0 0 +chr12 104393841 0 0 0.0 0 +chr12 104638784 0 0 0.0 0 +chr12 104732613 0 0 0.0 0 +chr12 104758914 0 0 0.0 0 +chr12 104768078 0 0 0.0 0 +chr12 105098670 0 0 0.0 0 +chr12 105130617 0 0 0.0 0 +chr12 105185128 0 0 0.0 0 +chr12 105274769 0 0 0.0 0 +chr12 105315384 0 0 0.0 0 +chr12 105382710 0 0 0.0 0 +chr12 105390399 0 0 0.0 0 +chr12 105512307 0 0 0.0 0 +chr12 105523221 1 25 0.431 1 +chr12 105544093 0 0 0.0 0 +chr12 105551436 0 0 0.0 0 +chr12 105845287 0 0 0.0 0 +chr12 105931348 0 0 0.0 0 +chr12 106040889 0 0 0.0 0 +chr12 106043065 0 0 0.0 0 +chr12 106079917 0 0 0.0 0 +chr12 106115350 0 0 0.0 0 +chr12 106202238 0 0 0.0 0 +chr12 106246911 0 0 0.0 0 +chr12 106308270 0 0 0.0 0 +chr12 106387925 0 0 0.0 0 +chr12 106395607 0 0 0.0 0 +chr12 106412167 0 0 0.0 0 +chr12 106451177 0 1 0.0141 0 +chr12 106464183 0 0 0.0 0 +chr12 106568405 0 0 0.0 0 +chr12 106631588 0 0 0.0 0 +chr12 106994953 0 0 0.0 0 +chr12 107007791 0 0 0.0 0 +chr12 107074228 0 0 0.0 0 +chr12 107119497 0 0 0.0 0 +chr12 107119665 0 0 0.0 0 +chr12 107192165 0 0 0.0 0 +chr12 107223024 0 0 0.0 0 +chr12 107225250 0 0 0.0 0 +chr12 107271487 0 0 0.0 0 +chr12 107439486 0 0 0.0 0 +chr12 107524027 0 0 0.0 0 +chr12 107558658 0 1 0.0167 0 +chr12 107579417 0 1 0.0172 0 +chr12 107699888 0 0 0.0 0 +chr12 107747998 0 0 0.0 0 +chr12 107827833 0 0 0.0 0 +chr12 107978877 0 0 0.0 0 +chr12 108093612 0 0 0.0 0 +chr12 108217169 0 0 0.0 0 +chr12 108360589 0 0 0.0 0 +chr12 108402760 0 0 0.0 0 +chr12 108644635 0 0 0.0 0 +chr12 108744673 0 0 0.0 0 +chr12 108745465 0 0 0.0 0 +chr12 108893143 0 0 0.0 0 +chr12 108972482 0 0 0.0 0 +chr12 109100770 0 0 0.0 0 +chr12 109132926 0 0 0.0 0 +chr12 109171115 0 0 0.0 0 +chr12 109286137 0 0 0.0 0 +chr12 109293256 0 0 0.0 0 +chr12 109458661 0 0 0.0 0 +chr12 109462873 0 0 0.0 0 +chr12 109463675 0 0 0.0 0 +chr12 109558259 0 0 0.0 0 +chr12 109593979 0 0 0.0 0 +chr12 109714789 0 0 0.0 0 +chr12 109786407 0 0 0.0 0 +chr12 109790385 0 0 0.0 0 +chr12 109805867 0 0 0.0 0 +chr12 109809613 0 0 0.0 0 +chr12 109813478 0 0 0.0 0 +chr12 109914945 0 0 0.0 0 +chr12 110457801 0 0 0.0 0 +chr12 110540650 0 0 0.0 0 +chr12 110563868 0 0 0.0 0 +chr12 110658952 0 0 0.0 0 +chr12 110685125 0 0 0.0 0 +chr12 110745857 0 0 0.0 0 +chr12 110824276 0 1 0.0286 0 +chr12 110861276 0 0 0.0 0 +chr12 111024367 0 0 0.0 0 +chr12 111044551 0 0 0.0 0 +chr12 111051182 0 0 0.0 0 +chr12 111165773 0 0 0.0 0 +chr12 111240376 0 0 0.0 0 +chr12 111304612 0 0 0.0 0 +chr12 111438134 0 0 0.0 0 +chr12 112209029 0 0 0.0 0 +chr12 112235089 0 0 0.0 0 +chr12 112295061 0 0 0.0 0 +chr12 112425689 0 0 0.0 0 +chr12 112725373 0 0 0.0 0 +chr12 112728873 0 0 0.0 0 +chr12 112757712 0 0 0.0 0 +chr12 112849310 0 0 0.0 0 +chr12 112878661 0 0 0.0 0 +chr12 112889341 0 0 0.0 0 +chr12 113021665 0 0 0.0 0 +chr12 113058943 0 0 0.0 0 +chr12 113115939 0 0 0.0 0 +chr12 113138904 0 0 0.0 0 +chr12 113236209 0 0 0.0 0 +chr12 113278235 0 0 0.0 0 +chr12 113295292 0 0 0.0 0 +chr12 113435471 0 0 0.0 0 +chr12 113436935 0 0 0.0 0 +chr12 113541718 0 0 0.0 0 +chr12 113638126 0 0 0.0 0 +chr12 113664024 0 0 0.0 0 +chr12 113747211 0 0 0.0 0 +chr12 113759977 0 0 0.0 0 +chr12 113797867 0 0 0.0 0 +chr12 113975186 0 0 0.0 0 +chr12 113979928 0 0 0.0 0 +chr12 113994063 0 0 0.0 0 +chr12 114032443 0 0 0.0 0 +chr12 114134744 0 0 0.0 0 +chr12 114443386 0 0 0.0 0 +chr12 114451113 0 0 0.0 0 +chr12 114476222 0 0 0.0 0 +chr12 114507000 0 0 0.0 0 +chr12 114730070 0 0 0.0 0 +chr12 114762105 0 0 0.0 0 +chr12 114985964 0 0 0.0 0 +chr12 115096213 0 0 0.0 0 +chr12 115108329 0 0 0.0 0 +chr12 115120614 0 0 0.0 0 +chr12 115159008 0 0 0.0 0 +chr12 115279052 0 0 0.0 0 +chr12 115474389 0 0 0.0 0 +chr12 115515376 0 0 0.0 0 +chr12 115604366 0 0 0.0 0 +chr12 115631747 0 0 0.0 0 +chr12 115730123 0 0 0.0 0 +chr12 115819775 0 0 0.0 0 +chr12 115821656 0 0 0.0 0 +chr12 115997905 0 0 0.0 0 +chr12 116014779 0 0 0.0 0 +chr12 116273027 0 0 0.0 0 +chr12 116281792 0 0 0.0 0 +chr12 116377323 0 0 0.0 0 +chr12 116548222 0 0 0.0 0 +chr12 116601206 0 0 0.0 0 +chr12 116616657 0 0 0.0 0 +chr12 116633947 0 0 0.0 0 +chr12 116635244 0 0 0.0 0 +chr12 116701056 0 0 0.0 0 +chr12 116710069 0 1 0.0143 0 +chr12 116714086 0 0 0.0 0 +chr12 116767934 0 0 0.0 0 +chr12 116855843 0 0 0.0 0 +chr12 116955992 0 0 0.0 0 +chr12 117071677 0 0 0.0 0 +chr12 117135995 0 0 0.0 0 +chr12 117201380 0 0 0.0 0 +chr12 117239888 0 0 0.0 0 +chr12 117309825 0 0 0.0 0 +chr12 117337836 0 0 0.0 0 +chr12 117395228 0 0 0.0 0 +chr12 117402692 0 0 0.0 0 +chr12 117582275 0 0 0.0 0 +chr12 117591002 0 1 0.0204 0 +chr12 117628511 0 0 0.0 0 +chr12 117685231 0 0 0.0 0 +chr12 117702057 0 0 0.0 0 +chr12 117721816 0 0 0.0 0 +chr12 117848844 1 68 0.8193 1 +chr12 117987337 0 0 0.0 0 +chr12 118070919 0 0 0.0 0 +chr12 118102761 0 0 0.0 0 +chr12 118179330 0 0 0.0 0 +chr12 118208005 0 0 0.0 0 +chr12 118415071 0 0 0.0 0 +chr12 118450036 0 0 0.0 0 +chr12 118504731 0 0 0.0 0 +chr12 118524348 0 0 0.0 0 +chr12 118621668 0 0 0.0 0 +chr12 118663177 0 0 0.0 0 +chr12 118690715 0 0 0.0 0 +chr12 118774568 0 0 0.0 0 +chr12 118896066 0 0 0.0 0 +chr12 118917877 0 0 0.0 0 +chr12 118970536 0 0 0.0 0 +chr12 118992276 0 0 0.0 0 +chr12 118996672 0 0 0.0 0 +chr12 119060966 0 0 0.0 0 +chr12 119072621 1 27 0.3971 1 +chr12 119110109 0 0 0.0 0 +chr12 119110337 0 0 0.0 0 +chr12 119154371 0 0 0.0 0 +chr12 119277539 0 0 0.0 0 +chr12 119465239 0 0 0.0 0 +chr12 119684203 0 0 0.0 0 +chr12 119743305 0 0 0.0 0 +chr12 119809632 0 0 0.0 0 +chr12 119890492 0 0 0.0 0 +chr12 119939839 0 0 0.0 0 +chr12 120104308 0 0 0.0 0 +chr12 120238968 0 0 0.0 0 +chr12 120302984 0 0 0.0 0 +chr12 120309950 0 0 0.0 0 +chr12 120362300 0 0 0.0 0 +chr12 120501054 0 0 0.0 0 +chr12 120547420 0 0 0.0 0 +chr12 120779260 0 0 0.0 0 +chr12 121093549 0 0 0.0 0 +chr12 121162555 0 0 0.0 0 +chr12 121205657 0 0 0.0 0 +chr12 121324792 0 0 0.0 0 +chr12 121404888 0 0 0.0 0 +chr12 121452884 0 0 0.0 0 +chr12 121479105 0 0 0.0 0 +chr12 121522167 0 0 0.0 0 +chr12 121527880 0 0 0.0 0 +chr12 121534548 0 0 0.0 0 +chr12 121549601 0 0 0.0 0 +chr12 121561367 0 0 0.0 0 +chr12 121564005 0 0 0.0 0 +chr12 121614747 0 0 0.0 0 +chr12 121635080 0 1 0.0213 0 +chr12 121652495 0 0 0.0 0 +chr12 121846261 0 0 0.0 0 +chr12 121898297 0 0 0.0 0 +chr12 122096065 0 0 0.0 0 +chr12 122189754 0 0 0.0 0 +chr12 122527149 0 0 0.0 0 +chr12 122527305 0 0 0.0 0 +chr12 122738107 0 0 0.0 0 +chr12 122780955 0 0 0.0 0 +chr12 122952539 0 0 0.0 0 +chr12 123012005 0 0 0.0 0 +chr12 123218116 0 0 0.0 0 +chr12 123233832 0 0 0.0 0 +chr12 123294716 0 0 0.0 0 +chr12 123338439 0 0 0.0 0 +chr12 123395401 0 0 0.0 0 +chr12 123396107 0 0 0.0 0 +chr12 123401843 0 0 0.0 0 +chr12 123429251 0 0 0.0 0 +chr12 123546716 0 0 0.0 0 +chr12 123591233 0 0 0.0 0 +chr12 123614298 0 0 0.0 0 +chr12 123644092 0 0 0.0 0 +chr12 123784759 0 0 0.0 0 +chr12 123876193 0 0 0.0 0 +chr12 123894218 0 0 0.0 0 +chr12 124172709 0 1 0.0154 0 +chr12 124188459 0 0 0.0 0 +chr12 124211211 0 0 0.0 0 +chr12 124329927 0 0 0.0 0 +chr12 124348803 0 0 0.0 0 +chr12 124355712 0 0 0.0 0 +chr12 124365288 0 0 0.0 0 +chr12 124379939 0 0 0.0 0 +chr12 124398797 0 0 0.0 0 +chr12 124404090 0 0 0.0 0 +chr12 124425632 0 0 0.0 0 +chr12 124591052 0 0 0.0 0 +chr12 124676452 0 0 0.0 0 +chr12 124680143 0 0 0.0 0 +chr12 124738528 0 0 0.0 0 +chr12 124756840 0 0 0.0 0 +chr12 125058572 0 0 0.0 0 +chr12 125123002 0 0 0.0 0 +chr12 125123337 0 0 0.0 0 +chr12 125250093 0 0 0.0 0 +chr12 125252120 0 0 0.0 0 +chr12 125314537 0 0 0.0 0 +chr12 125464246 0 0 0.0 0 +chr12 125494652 0 0 0.0 0 +chr12 125583327 0 0 0.0 0 +chr12 125651253 0 0 0.0 0 +chr12 125676866 0 0 0.0 0 +chr12 125699631 0 0 0.0 0 +chr12 125746377 0 0 0.0 0 +chr12 125782688 0 0 0.0 0 +chr12 125802432 0 0 0.0 0 +chr12 125854971 0 0 0.0 0 +chr12 125930376 0 0 0.0 0 +chr12 126123622 0 0 0.0 0 +chr12 126319061 0 0 0.0 0 +chr12 126360081 0 0 0.0 0 +chr12 126435217 0 0 0.0 0 +chr12 126449335 1 36 0.507 1 +chr12 126459978 0 0 0.0 0 +chr12 126512553 0 0 0.0 0 +chr12 126642011 0 0 0.0 0 +chr12 126664922 0 0 0.0 0 +chr12 126837860 0 0 0.0 0 +chr12 126873990 0 0 0.0 0 +chr12 127222973 0 0 0.0 0 +chr12 127254081 0 2 0.0408 0 +chr12 127294544 0 0 0.0 0 +chr12 127311636 0 0 0.0 0 +chr12 127385685 0 0 0.0 0 +chr12 127516081 0 0 0.0 0 +chr12 127607500 0 0 0.0 0 +chr12 127714831 0 0 0.0 0 +chr12 127756914 0 0 0.0 0 +chr12 127817173 0 1 0.0192 0 +chr12 128003935 0 0 0.0 0 +chr12 128011526 0 0 0.0 0 +chr12 128198635 0 0 0.0 0 +chr12 128383877 0 0 0.0 0 +chr12 128390541 0 0 0.0 0 +chr12 128528108 0 0 0.0 0 +chr12 128607457 0 0 0.0 0 +chr12 128619987 0 0 0.0 0 +chr12 128657907 0 0 0.0 0 +chr12 128740739 0 0 0.0 0 +chr12 128742259 0 0 0.0 0 +chr12 128889516 0 0 0.0 0 +chr12 129045106 1 4 0.0519 1 +chr12 129072926 0 0 0.0 0 +chr12 129099660 0 0 0.0 0 +chr12 129110278 0 0 0.0 0 +chr12 129148962 0 0 0.0 0 +chr12 129185141 0 0 0.0 0 +chr12 129293192 0 0 0.0 0 +chr12 129553905 0 0 0.0 0 +chr12 129582375 0 0 0.0 0 +chr12 129662178 0 0 0.0 0 +chr12 129921366 0 0 0.0 0 +chr12 130024323 0 0 0.0 0 +chr12 130029419 0 0 0.0 0 +chr12 130044398 0 0 0.0 0 +chr12 130192563 0 1 0.0164 0 +chr12 130244956 0 0 0.0 0 +chr12 130283607 0 0 0.0 0 +chr12 130409893 0 0 0.0 0 +chr12 130416059 0 0 0.0 0 +chr12 130502581 0 0 0.0 0 +chr12 130513655 0 0 0.0 0 +chr12 130567583 0 0 0.0 0 +chr12 130612464 0 0 0.0 0 +chr12 130661581 0 0 0.0 0 +chr12 130671021 0 0 0.0 0 +chr12 130679977 0 0 0.0 0 +chr12 130781347 0 0 0.0 0 +chr12 130868912 0 0 0.0 0 +chr12 130902467 0 0 0.0 0 +chr12 130903181 0 0 0.0 0 +chr12 131013933 0 0 0.0 0 +chr12 131025783 0 0 0.0 0 +chr12 131041374 0 1 0.0217 0 +chr12 131074116 0 0 0.0 0 +chr12 131089275 0 0 0.0 0 +chr12 131097120 0 0 0.0 0 +chr12 131184610 0 0 0.0 0 +chr12 131309548 0 0 0.0 0 +chr12 131316415 0 0 0.0 0 +chr12 131364502 0 0 0.0 0 +chr12 131380360 0 0 0.0 0 +chr12 131404130 1 26 0.5 1 +chr12 131416365 0 0 0.0 0 +chr12 131560900 0 0 0.0 0 +chr12 131578435 0 0 0.0 0 +chr12 131649564 0 0 0.0 0 +chr12 131778116 0 0 0.0 0 +chr12 131807907 0 0 0.0 0 +chr12 131833084 0 0 0.0 0 +chr12 131833510 0 0 0.0 0 +chr12 131844314 0 0 0.0 0 +chr12 132050819 0 0 0.0 0 +chr12 132096135 0 0 0.0 0 +chr12 132115991 0 0 0.0 0 +chr12 132141703 0 0 0.0 0 +chr12 132197177 0 0 0.0 0 +chr12 132201948 0 0 0.0 0 +chr12 132204010 0 0 0.0 0 +chr12 132270624 0 0 0.0 0 +chr12 132351182 0 0 0.0 0 +chr12 132374013 0 0 0.0 0 +chr12 132394066 0 0 0.0 0 +chr12 132394264 0 0 0.0 0 +chr12 132430045 0 0 0.0 0 +chr12 132490710 0 0 0.0 0 +chr12 132674017 0 0 0.0 0 +chr12 132762339 0 0 0.0 0 +chr12 132804317 0 0 0.0 0 +chr12 133056592 0 0 0.0 0 +chr12 133086231 0 0 0.0 0 +chr12 133137869 0 1 0.0133 0 +chr12 133138501 0 0 0.0 0 +chr12 133173224 0 0 0.0 0 +chr12 133190960 1 40 0.4598 1 +chr12 133223401 0 1 0.0169 0 +chr12_GL383549v1_alt 56862 0 0 0.0 0 +chr12_GL383551v1_alt 138925 0 0 0.0 0 +chr12_GL383552v1_alt 9019 0 0 0.0 0 +chr12_GL383552v1_alt 43367 0 0 0.0 0 +chr12_GL877875v1_alt 108025 0 0 0.0 0 +chr12_GL877876v1_alt 186342 0 0 0.0 0 +chr12_GL877876v1_alt 381323 0 0 0.0 0 +chr12_KI270834v1_alt 49684 0 0 0.0 0 +chr12_KI270835v1_alt 66882 0 0 0.0 0 +chr12_KI270835v1_alt 132893 0 0 0.0 0 +chr12_KI270836v1_alt 17880 0 0 0.0 0 +chr12_KI270904v1_alt 186329 0 0 0.0 0 +chr12_KI270904v1_alt 462224 0 0 0.0 0 +chr12_KI270904v1_alt 468910 0 0 0.0 0 +chr13 16053423 0 0 0.0 0 +chr13 16111052 0 0 0.0 0 +chr13 16114480 0 0 0.0 0 +chr13 16117909 0 0 0.0 0 +chr13 16124758 0 0 0.0 0 +chr13 16128184 0 0 0.0 0 +chr13 16131613 0 0 0.0 0 +chr13 16135039 0 0 0.0 0 +chr13 16141888 0 0 0.0 0 +chr13 16145316 0 0 0.0 0 +chr13 16148743 0 0 0.0 0 +chr13 16152169 0 0 0.0 0 +chr13 16155594 0 0 0.0 0 +chr13 16162446 0 0 0.0 0 +chr13 16166999 0 0 0.0 0 +chr13 16173850 0 0 0.0 0 +chr13 16180699 0 0 0.0 0 +chr13 16184124 0 0 0.0 0 +chr13 16190975 0 0 0.0 0 +chr13 16197825 0 0 0.0 0 +chr13 16201250 0 0 0.0 0 +chr13 16204675 0 0 0.0 0 +chr13 16208101 0 0 0.0 0 +chr13 16214951 0 0 0.0 0 +chr13 16218375 0 0 0.0 0 +chr13 16221799 0 0 0.0 0 +chr13 16225224 0 0 0.0 0 +chr13 18427698 0 0 0.0 0 +chr13 18542511 0 0 0.0 0 +chr13 18747916 0 0 0.0 0 +chr13 18878456 0 0 0.0 0 +chr13 19074144 0 0 0.0 0 +chr13 19216003 0 0 0.0 0 +chr13 19323583 0 0 0.0 0 +chr13 19424756 0 0 0.0 0 +chr13 19568526 0 0 0.0 0 +chr13 19813921 0 0 0.0 0 +chr13 19955073 0 0 0.0 0 +chr13 20056564 0 0 0.0 0 +chr13 20137411 0 0 0.0 0 +chr13 20270379 0 0 0.0 0 +chr13 20319087 0 1 0.0137 0 +chr13 20483423 0 1 0.0227 0 +chr13 20502978 0 0 0.0 0 +chr13 20512294 0 0 0.0 0 +chr13 20620790 0 0 0.0 0 +chr13 20739945 0 0 0.0 0 +chr13 20902137 0 0 0.0 0 +chr13 20968559 0 1 0.0127 0 +chr13 20999317 0 0 0.0 0 +chr13 21022238 0 0 0.0 0 +chr13 21080356 0 0 0.0 0 +chr13 21204569 0 0 0.0 0 +chr13 21233288 0 0 0.0 0 +chr13 21410731 0 0 0.0 0 +chr13 21522981 0 0 0.0 0 +chr13 21708577 0 0 0.0 0 +chr13 21796538 0 0 0.0 0 +chr13 21801324 0 0 0.0 0 +chr13 21952842 0 0 0.0 0 +chr13 22177271 0 0 0.0 0 +chr13 22239757 0 0 0.0 0 +chr13 22296031 0 0 0.0 0 +chr13 22366769 0 0 0.0 0 +chr13 22466061 0 0 0.0 0 +chr13 22609534 0 0 0.0 0 +chr13 22679513 0 0 0.0 0 +chr13 22774240 0 0 0.0 0 +chr13 22805134 0 0 0.0 0 +chr13 22813761 0 0 0.0 0 +chr13 22867103 0 0 0.0 0 +chr13 22934937 0 0 0.0 0 +chr13 22955709 0 0 0.0 0 +chr13 23465874 0 0 0.0 0 +chr13 23498515 0 0 0.0 0 +chr13 23503275 0 0 0.0 0 +chr13 23566384 0 0 0.0 0 +chr13 23578220 0 0 0.0 0 +chr13 23668213 0 0 0.0 0 +chr13 23673668 0 0 0.0 0 +chr13 23683300 0 0 0.0 0 +chr13 23705304 0 0 0.0 0 +chr13 23797532 0 0 0.0 0 +chr13 23883732 0 1 0.0135 0 +chr13 24129796 0 0 0.0 0 +chr13 24213103 0 0 0.0 0 +chr13 24352520 0 0 0.0 0 +chr13 24380791 0 0 0.0 0 +chr13 24471023 0 0 0.0 0 +chr13 24502973 0 0 0.0 0 +chr13 24933133 0 0 0.0 0 +chr13 24937986 0 0 0.0 0 +chr13 25093308 0 0 0.0 0 +chr13 25134016 0 0 0.0 0 +chr13 25150592 0 0 0.0 0 +chr13 25158582 0 0 0.0 0 +chr13 25288226 0 0 0.0 0 +chr13 25407742 0 0 0.0 0 +chr13 25496542 0 1 0.0154 0 +chr13 25510051 0 0 0.0 0 +chr13 25593510 0 0 0.0 0 +chr13 25627156 0 0 0.0 0 +chr13 25687283 0 0 0.0 0 +chr13 25695358 0 0 0.0 0 +chr13 25880601 0 0 0.0 0 +chr13 26029515 0 0 0.0 0 +chr13 26057548 0 0 0.0 0 +chr13 26144883 0 0 0.0 0 +chr13 26189657 0 0 0.0 0 +chr13 26231170 0 0 0.0 0 +chr13 26481276 0 0 0.0 0 +chr13 26532106 0 0 0.0 0 +chr13 26535181 0 0 0.0 0 +chr13 26673243 0 0 0.0 0 +chr13 26696293 0 0 0.0 0 +chr13 26716453 0 0 0.0 0 +chr13 26787800 0 0 0.0 0 +chr13 26790044 0 0 0.0 0 +chr13 27069120 0 0 0.0 0 +chr13 27118803 0 0 0.0 0 +chr13 27125878 0 0 0.0 0 +chr13 27260953 0 0 0.0 0 +chr13 27309445 0 0 0.0 0 +chr13 27310963 0 0 0.0 0 +chr13 27614322 0 0 0.0 0 +chr13 27621572 0 0 0.0 0 +chr13 27693172 0 0 0.0 0 +chr13 27974134 0 0 0.0 0 +chr13 28111605 0 0 0.0 0 +chr13 28161549 0 0 0.0 0 +chr13 28514060 0 0 0.0 0 +chr13 28579318 0 1 0.0185 0 +chr13 28585936 0 0 0.0 0 +chr13 28700566 0 0 0.0 0 +chr13 28717070 0 0 0.0 0 +chr13 28726320 0 0 0.0 0 +chr13 28742501 0 0 0.0 0 +chr13 28792575 0 2 0.0328 0 +chr13 28795237 0 0 0.0 0 +chr13 28872137 0 0 0.0 0 +chr13 29038351 0 0 0.0 0 +chr13 29117865 0 0 0.0 0 +chr13 29222882 0 0 0.0 0 +chr13 29229318 0 0 0.0 0 +chr13 29232429 0 0 0.0 0 +chr13 29354276 0 1 0.0333 0 +chr13 29455653 0 0 0.0 0 +chr13 29490636 0 0 0.0 0 +chr13 29601542 0 1 0.0182 0 +chr13 29636529 0 0 0.0 0 +chr13 29665865 0 0 0.0 0 +chr13 29703269 0 0 0.0 0 +chr13 29771554 0 0 0.0 0 +chr13 29844583 0 0 0.0 0 +chr13 30155761 0 0 0.0 0 +chr13 30276292 0 0 0.0 0 +chr13 30314146 0 0 0.0 0 +chr13 30501207 0 1 0.0164 0 +chr13 30513937 0 0 0.0 0 +chr13 30617901 0 0 0.0 0 +chr13 30727600 0 0 0.0 0 +chr13 30798415 0 0 0.0 0 +chr13 30845343 0 0 0.0 0 +chr13 30865992 0 0 0.0 0 +chr13 30871797 0 0 0.0 0 +chr13 30881256 0 0 0.0 0 +chr13 30936498 0 0 0.0 0 +chr13 31017231 0 0 0.0 0 +chr13 31037810 0 0 0.0 0 +chr13 31052716 0 0 0.0 0 +chr13 31173001 0 0 0.0 0 +chr13 31269676 0 0 0.0 0 +chr13 31464968 0 0 0.0 0 +chr13 31469162 0 0 0.0 0 +chr13 31547623 0 0 0.0 0 +chr13 31594576 0 0 0.0 0 +chr13 31717829 0 0 0.0 0 +chr13 31719401 0 0 0.0 0 +chr13 31725319 0 0 0.0 0 +chr13 31849550 0 0 0.0 0 +chr13 32031466 0 0 0.0 0 +chr13 32080482 0 0 0.0 0 +chr13 32097304 0 0 0.0 0 +chr13 32481280 0 0 0.0 0 +chr13 32600818 0 0 0.0 0 +chr13 32660485 1 67 0.9571 1 +chr13 32669177 0 0 0.0 0 +chr13 32723903 0 0 0.0 0 +chr13 32726171 2 22 0.8 1 +chr13 32769796 0 0 0.0 0 +chr13 32794120 0 0 0.0 0 +chr13 32801966 0 0 0.0 0 +chr13 32825215 0 0 0.0 0 +chr13 32857242 0 0 0.0 0 +chr13 32950802 0 0 0.0 0 +chr13 33124351 0 0 0.0 0 +chr13 33177086 0 0 0.0 0 +chr13 33203410 0 0 0.0 0 +chr13 33230833 0 0 0.0 0 +chr13 33234037 0 0 0.0 0 +chr13 33241803 0 0 0.0 0 +chr13 33267134 0 0 0.0 0 +chr13 33295053 0 0 0.0 0 +chr13 33315182 0 0 0.0 0 +chr13 33418814 0 0 0.0 0 +chr13 33577624 0 1 0.0238 0 +chr13 33583152 0 0 0.0 0 +chr13 33647274 0 0 0.0 0 +chr13 33696314 0 0 0.0 0 +chr13 33918849 0 0 0.0 0 +chr13 33955132 0 0 0.0 0 +chr13 33960686 3 69 0.8718 1 +chr13 34054640 0 0 0.0 0 +chr13 34122201 0 0 0.0 0 +chr13 34244896 0 0 0.0 0 +chr13 34356421 0 0 0.0 0 +chr13 34400583 0 0 0.0 0 +chr13 34431333 0 0 0.0 0 +chr13 34509786 0 0 0.0 0 +chr13 34674129 0 0 0.0 0 +chr13 34792284 0 0 0.0 0 +chr13 34864818 0 0 0.0 0 +chr13 35156927 0 0 0.0 0 +chr13 35270750 0 0 0.0 0 +chr13 35335478 0 0 0.0 0 +chr13 35372347 0 0 0.0 0 +chr13 35534404 0 0 0.0 0 +chr13 35579600 0 0 0.0 0 +chr13 35771906 0 0 0.0 0 +chr13 35862439 0 0 0.0 0 +chr13 35981391 0 0 0.0 0 +chr13 36026128 0 0 0.0 0 +chr13 36129390 0 0 0.0 0 +chr13 36261803 0 0 0.0 0 +chr13 36262119 0 0 0.0 0 +chr13 36385727 0 0 0.0 0 +chr13 36394401 0 0 0.0 0 +chr13 36644643 0 0 0.0 0 +chr13 36726894 0 0 0.0 0 +chr13 36762189 0 0 0.0 0 +chr13 36924105 0 0 0.0 0 +chr13 37117191 0 0 0.0 0 +chr13 37181890 0 0 0.0 0 +chr13 37392239 0 0 0.0 0 +chr13 37448453 0 0 0.0 0 +chr13 37461377 0 0 0.0 0 +chr13 37467161 0 0 0.0 0 +chr13 37481361 0 0 0.0 0 +chr13 37532101 1 5 0.0926 1 +chr13 37538794 0 0 0.0 0 +chr13 38104628 0 0 0.0 0 +chr13 38140862 0 0 0.0 0 +chr13 38215554 0 0 0.0 0 +chr13 38231420 0 0 0.0 0 +chr13 38252609 0 0 0.0 0 +chr13 38299271 0 0 0.0 0 +chr13 38330187 0 0 0.0 0 +chr13 38463033 0 0 0.0 0 +chr13 38556315 0 0 0.0 0 +chr13 38569580 0 0 0.0 0 +chr13 38713576 0 0 0.0 0 +chr13 38749710 0 0 0.0 0 +chr13 38763798 0 0 0.0 0 +chr13 39137765 0 0 0.0 0 +chr13 39210632 0 0 0.0 0 +chr13 39489527 1 19 0.2603 1 +chr13 39572095 0 0 0.0 0 +chr13 39798834 0 0 0.0 0 +chr13 40198645 0 1 0.0227 0 +chr13 40231615 0 0 0.0 0 +chr13 40238361 0 0 0.0 0 +chr13 40240691 0 0 0.0 0 +chr13 40491165 0 0 0.0 0 +chr13 40491674 0 0 0.0 0 +chr13 40756720 0 0 0.0 0 +chr13 41225360 0 0 0.0 0 +chr13 41247769 0 0 0.0 0 +chr13 41315144 0 0 0.0 0 +chr13 41350041 0 0 0.0 0 +chr13 41356108 0 0 0.0 0 +chr13 41520951 0 0 0.0 0 +chr13 41573672 0 0 0.0 0 +chr13 41966712 0 0 0.0 0 +chr13 42072856 0 0 0.0 0 +chr13 42213045 0 0 0.0 0 +chr13 42413124 0 0 0.0 0 +chr13 42438809 0 0 0.0 0 +chr13 42626730 0 0 0.0 0 +chr13 42653204 0 0 0.0 0 +chr13 42725659 0 0 0.0 0 +chr13 42759997 0 0 0.0 0 +chr13 42776822 0 0 0.0 0 +chr13 42901674 0 0 0.0 0 +chr13 43036540 0 0 0.0 0 +chr13 43137605 0 0 0.0 0 +chr13 43152498 0 0 0.0 0 +chr13 43191363 0 0 0.0 0 +chr13 43296191 0 0 0.0 0 +chr13 43306071 0 0 0.0 0 +chr13 43342055 0 0 0.0 0 +chr13 43375917 0 0 0.0 0 +chr13 43416966 0 0 0.0 0 +chr13 43659380 0 0 0.0 0 +chr13 44012261 0 0 0.0 0 +chr13 44015472 0 0 0.0 0 +chr13 44063055 0 0 0.0 0 +chr13 44095859 0 0 0.0 0 +chr13 44116371 0 0 0.0 0 +chr13 44138805 0 1 0.02 0 +chr13 44186370 0 0 0.0 0 +chr13 44221675 0 0 0.0 0 +chr13 44324668 0 0 0.0 0 +chr13 44437506 1 32 0.4571 1 +chr13 44612565 0 0 0.0 0 +chr13 44674963 1 28 0.3944 1 +chr13 44676716 0 0 0.0 0 +chr13 44727987 0 1 0.02 0 +chr13 44731708 0 0 0.0 0 +chr13 44732173 0 0 0.0 0 +chr13 44859918 0 0 0.0 0 +chr13 44994522 0 0 0.0 0 +chr13 45054870 0 0 0.0 0 +chr13 45105362 0 0 0.0 0 +chr13 45194015 0 0 0.0 0 +chr13 45230465 0 0 0.0 0 +chr13 45375524 0 0 0.0 0 +chr13 45402597 0 0 0.0 0 +chr13 45459335 0 0 0.0 0 +chr13 45527429 0 0 0.0 0 +chr13 45721846 0 0 0.0 0 +chr13 45757751 0 0 0.0 0 +chr13 45772177 0 0 0.0 0 +chr13 45822015 0 0 0.0 0 +chr13 45983020 0 0 0.0 0 +chr13 45990132 0 0 0.0 0 +chr13 46017814 0 1 0.0333 0 +chr13 46037283 0 0 0.0 0 +chr13 46105708 0 0 0.0 0 +chr13 46369519 0 0 0.0 0 +chr13 46679692 0 0 0.0 0 +chr13 46682276 0 0 0.0 0 +chr13 46700798 0 0 0.0 0 +chr13 46745970 0 0 0.0 0 +chr13 46771960 0 0 0.0 0 +chr13 46954179 0 0 0.0 0 +chr13 47114000 0 0 0.0 0 +chr13 47157242 0 0 0.0 0 +chr13 47184935 0 0 0.0 0 +chr13 47257087 0 0 0.0 0 +chr13 47529528 0 0 0.0 0 +chr13 47576683 0 0 0.0 0 +chr13 48073030 0 0 0.0 0 +chr13 48280928 0 0 0.0 0 +chr13 48512018 0 0 0.0 0 +chr13 48570034 0 0 0.0 0 +chr13 48778125 0 0 0.0 0 +chr13 48858012 0 0 0.0 0 +chr13 48888816 0 0 0.0 0 +chr13 48944476 0 0 0.0 0 +chr13 48951049 0 0 0.0 0 +chr13 49107458 0 0 0.0 0 +chr13 49162457 0 0 0.0 0 +chr13 49166185 0 0 0.0 0 +chr13 49239414 0 0 0.0 0 +chr13 49259732 0 0 0.0 0 +chr13 49267348 0 0 0.0 0 +chr13 49304302 0 0 0.0 0 +chr13 49332291 0 0 0.0 0 +chr13 49348092 0 0 0.0 0 +chr13 49554855 0 0 0.0 0 +chr13 49672398 0 0 0.0 0 +chr13 49942358 0 0 0.0 0 +chr13 50294266 0 0 0.0 0 +chr13 50329326 0 0 0.0 0 +chr13 50421538 0 0 0.0 0 +chr13 50446183 0 0 0.0 0 +chr13 50542253 0 0 0.0 0 +chr13 50606411 0 0 0.0 0 +chr13 50650771 0 0 0.0 0 +chr13 50821094 0 0 0.0 0 +chr13 51044786 0 0 0.0 0 +chr13 51047530 0 0 0.0 0 +chr13 51118807 0 0 0.0 0 +chr13 51162267 0 0 0.0 0 +chr13 51179458 0 0 0.0 0 +chr13 51232582 0 0 0.0 0 +chr13 51241996 0 0 0.0 0 +chr13 51289112 0 0 0.0 0 +chr13 51487027 0 0 0.0 0 +chr13 51596852 0 0 0.0 0 +chr13 51801813 0 0 0.0 0 +chr13 51838425 0 0 0.0 0 +chr13 51965289 0 0 0.0 0 +chr13 51969900 0 0 0.0 0 +chr13 51970141 0 0 0.0 0 +chr13 52029106 0 0 0.0 0 +chr13 52330121 0 0 0.0 0 +chr13 52348429 0 0 0.0 0 +chr13 52415903 1 3 0.0411 1 +chr13 52595305 0 0 0.0 0 +chr13 52629511 0 0 0.0 0 +chr13 52768742 0 0 0.0 0 +chr13 52887737 0 0 0.0 0 +chr13 53026685 0 0 0.0 0 +chr13 53068365 0 0 0.0 0 +chr13 53105904 0 0 0.0 0 +chr13 53121485 0 0 0.0 0 +chr13 53135070 0 1 0.02 0 +chr13 53155534 0 0 0.0 0 +chr13 53203992 0 0 0.0 0 +chr13 53222516 0 0 0.0 0 +chr13 53269192 0 0 0.0 0 +chr13 53312109 0 0 0.0 0 +chr13 53613634 0 0 0.0 0 +chr13 53818421 0 0 0.0 0 +chr13 54265229 0 0 0.0 0 +chr13 54714461 0 0 0.0 0 +chr13 54775054 0 0 0.0 0 +chr13 54919838 0 0 0.0 0 +chr13 55157097 0 0 0.0 0 +chr13 55516056 0 0 0.0 0 +chr13 55732540 0 0 0.0 0 +chr13 55778476 0 0 0.0 0 +chr13 56162058 0 0 0.0 0 +chr13 56301742 0 0 0.0 0 +chr13 56368861 0 0 0.0 0 +chr13 56468512 0 0 0.0 0 +chr13 56587215 0 0 0.0 0 +chr13 56610565 0 0 0.0 0 +chr13 56892430 0 0 0.0 0 +chr13 57042101 0 0 0.0 0 +chr13 57644599 0 0 0.0 0 +chr13 57870102 0 0 0.0 0 +chr13 57908909 0 0 0.0 0 +chr13 57930921 0 0 0.0 0 +chr13 59177766 0 0 0.0 0 +chr13 59407933 0 0 0.0 0 +chr13 59535354 0 0 0.0 0 +chr13 59606076 0 0 0.0 0 +chr13 59619387 0 0 0.0 0 +chr13 59627991 0 0 0.0 0 +chr13 60172245 0 0 0.0 0 +chr13 60467327 0 0 0.0 0 +chr13 60488132 0 0 0.0 0 +chr13 60637939 0 0 0.0 0 +chr13 60688408 0 0 0.0 0 +chr13 61076700 0 0 0.0 0 +chr13 61299013 0 0 0.0 0 +chr13 61421126 0 0 0.0 0 +chr13 61484046 0 0 0.0 0 +chr13 61928305 0 0 0.0 0 +chr13 62399003 0 0 0.0 0 +chr13 62738230 0 0 0.0 0 +chr13 62799058 0 0 0.0 0 +chr13 62959199 0 0 0.0 0 +chr13 63045836 0 0 0.0 0 +chr13 63187464 0 0 0.0 0 +chr13 63730134 0 0 0.0 0 +chr13 63774379 0 0 0.0 0 +chr13 63901739 0 0 0.0 0 +chr13 64124192 0 0 0.0 0 +chr13 64386364 0 1 0.0278 0 +chr13 64426035 0 0 0.0 0 +chr13 64516224 0 0 0.0 0 +chr13 64542915 0 0 0.0 0 +chr13 64546732 0 0 0.0 0 +chr13 64685605 0 0 0.0 0 +chr13 64788425 0 0 0.0 0 +chr13 64827494 0 0 0.0 0 +chr13 65102518 0 0 0.0 0 +chr13 65109204 0 0 0.0 0 +chr13 65368187 0 0 0.0 0 +chr13 65467471 0 0 0.0 0 +chr13 65508542 0 0 0.0 0 +chr13 65559246 0 0 0.0 0 +chr13 65716304 0 0 0.0 0 +chr13 65780235 0 0 0.0 0 +chr13 65796464 0 0 0.0 0 +chr13 65804120 0 0 0.0 0 +chr13 65830486 0 0 0.0 0 +chr13 65926972 0 0 0.0 0 +chr13 65963238 0 0 0.0 0 +chr13 65963693 0 0 0.0 0 +chr13 66071094 0 0 0.0 0 +chr13 66130488 0 0 0.0 0 +chr13 66138651 0 0 0.0 0 +chr13 66147104 0 0 0.0 0 +chr13 66460796 0 0 0.0 0 +chr13 66579893 0 0 0.0 0 +chr13 66627300 0 0 0.0 0 +chr13 66916230 0 0 0.0 0 +chr13 66932565 0 0 0.0 0 +chr13 66976424 0 0 0.0 0 +chr13 67567883 0 0 0.0 0 +chr13 67588633 0 0 0.0 0 +chr13 67651365 0 0 0.0 0 +chr13 67785860 0 0 0.0 0 +chr13 67858510 0 0 0.0 0 +chr13 67924717 0 0 0.0 0 +chr13 68100847 0 0 0.0 0 +chr13 68146848 0 0 0.0 0 +chr13 68198169 0 0 0.0 0 +chr13 68199970 0 0 0.0 0 +chr13 68227497 0 0 0.0 0 +chr13 68371270 0 0 0.0 0 +chr13 68463630 0 0 0.0 0 +chr13 68524317 0 0 0.0 0 +chr13 68856860 0 0 0.0 0 +chr13 68898688 0 0 0.0 0 +chr13 69024603 0 0 0.0 0 +chr13 69140256 0 0 0.0 0 +chr13 69349174 0 0 0.0 0 +chr13 69483176 0 0 0.0 0 +chr13 69523961 0 0 0.0 0 +chr13 69556576 0 0 0.0 0 +chr13 69652735 0 0 0.0 0 +chr13 69739776 0 0 0.0 0 +chr13 70020941 0 0 0.0 0 +chr13 70080862 0 0 0.0 0 +chr13 70095516 0 0 0.0 0 +chr13 70249382 0 0 0.0 0 +chr13 70426045 0 0 0.0 0 +chr13 70639148 0 0 0.0 0 +chr13 70650122 0 0 0.0 0 +chr13 70661924 0 0 0.0 0 +chr13 70728647 0 0 0.0 0 +chr13 71137974 0 0 0.0 0 +chr13 71231794 0 0 0.0 0 +chr13 71347983 0 0 0.0 0 +chr13 71357339 0 0 0.0 0 +chr13 71377092 0 0 0.0 0 +chr13 71502870 0 0 0.0 0 +chr13 71605934 0 0 0.0 0 +chr13 71613494 0 0 0.0 0 +chr13 71691227 0 0 0.0 0 +chr13 71733604 0 0 0.0 0 +chr13 72123126 0 0 0.0 0 +chr13 72259948 0 0 0.0 0 +chr13 72284983 0 0 0.0 0 +chr13 72374662 0 0 0.0 0 +chr13 72377070 1 33 0.569 1 +chr13 72460460 0 0 0.0 0 +chr13 72524350 0 0 0.0 0 +chr13 72556891 0 0 0.0 0 +chr13 72574616 0 0 0.0 0 +chr13 72647324 0 0 0.0 0 +chr13 73025877 0 0 0.0 0 +chr13 73194516 0 0 0.0 0 +chr13 73227398 0 0 0.0 0 +chr13 73234495 0 0 0.0 0 +chr13 73354040 0 0 0.0 0 +chr13 73438595 0 0 0.0 0 +chr13 73490611 0 0 0.0 0 +chr13 73596985 0 0 0.0 0 +chr13 73638581 0 0 0.0 0 +chr13 73845937 0 0 0.0 0 +chr13 73846346 0 0 0.0 0 +chr13 73942193 0 0 0.0 0 +chr13 74078732 0 0 0.0 0 +chr13 74208930 0 0 0.0 0 +chr13 74452851 0 0 0.0 0 +chr13 74517557 0 0 0.0 0 +chr13 74718411 0 0 0.0 0 +chr13 74839217 0 0 0.0 0 +chr13 74895431 0 0 0.0 0 +chr13 74921164 0 0 0.0 0 +chr13 74959749 0 0 0.0 0 +chr13 75010427 0 0 0.0 0 +chr13 75149136 0 0 0.0 0 +chr13 75214842 0 0 0.0 0 +chr13 75570961 0 0 0.0 0 +chr13 76018444 0 0 0.0 0 +chr13 76060655 0 0 0.0 0 +chr13 76138184 0 0 0.0 0 +chr13 76210243 0 0 0.0 0 +chr13 76312716 2 6 0.1818 1 +chr13 76334423 0 0 0.0 0 +chr13 76592218 0 0 0.0 0 +chr13 76612562 0 0 0.0 0 +chr13 76780030 0 0 0.0 0 +chr13 77093642 0 0 0.0 0 +chr13 77180143 0 0 0.0 0 +chr13 77206249 0 0 0.0 0 +chr13 77333597 0 0 0.0 0 +chr13 77341349 0 0 0.0 0 +chr13 77577873 0 0 0.0 0 +chr13 77594513 0 0 0.0 0 +chr13 77760852 0 0 0.0 0 +chr13 78156955 0 1 0.025 0 +chr13 78203534 0 0 0.0 0 +chr13 78222202 0 0 0.0 0 +chr13 78356539 0 0 0.0 0 +chr13 78454876 0 0 0.0 0 +chr13 78685736 0 0 0.0 0 +chr13 78922552 0 0 0.0 0 +chr13 78923092 0 0 0.0 0 +chr13 78943303 0 0 0.0 0 +chr13 78967532 0 0 0.0 0 +chr13 79168115 0 0 0.0 0 +chr13 79210245 0 0 0.0 0 +chr13 79407528 0 0 0.0 0 +chr13 79889651 0 0 0.0 0 +chr13 79925957 0 0 0.0 0 +chr13 80289648 0 0 0.0 0 +chr13 80365325 0 0 0.0 0 +chr13 80577510 0 0 0.0 0 +chr13 80590675 0 0 0.0 0 +chr13 80642378 0 0 0.0 0 +chr13 81026393 0 0 0.0 0 +chr13 81026654 0 0 0.0 0 +chr13 81031180 0 0 0.0 0 +chr13 81151223 0 0 0.0 0 +chr13 81424139 0 0 0.0 0 +chr13 81464861 0 0 0.0 0 +chr13 81758615 0 0 0.0 0 +chr13 82080242 0 0 0.0 0 +chr13 82143077 0 0 0.0 0 +chr13 82544025 0 0 0.0 0 +chr13 82637037 0 0 0.0 0 +chr13 82708287 0 0 0.0 0 +chr13 82750234 0 0 0.0 0 +chr13 83255520 0 0 0.0 0 +chr13 83654154 0 0 0.0 0 +chr13 83757316 0 0 0.0 0 +chr13 84050774 0 0 0.0 0 +chr13 84362971 0 0 0.0 0 +chr13 84507622 0 0 0.0 0 +chr13 84539800 0 0 0.0 0 +chr13 84561314 0 0 0.0 0 +chr13 84590121 0 0 0.0 0 +chr13 84606134 0 0 0.0 0 +chr13 84606380 0 0 0.0 0 +chr13 84621544 0 0 0.0 0 +chr13 84693158 0 0 0.0 0 +chr13 84756687 0 0 0.0 0 +chr13 84924113 0 0 0.0 0 +chr13 84931923 0 0 0.0 0 +chr13 85012725 0 0 0.0 0 +chr13 85062686 0 0 0.0 0 +chr13 85066186 0 0 0.0 0 +chr13 85354231 0 0 0.0 0 +chr13 85403515 0 0 0.0 0 +chr13 85685617 0 0 0.0 0 +chr13 85711766 0 0 0.0 0 +chr13 85917068 0 0 0.0 0 +chr13 86043964 0 0 0.0 0 +chr13 86097064 0 0 0.0 0 +chr13 86162604 0 0 0.0 0 +chr13 86533404 0 0 0.0 0 +chr13 87069253 1 24 0.4444 1 +chr13 87314006 0 0 0.0 0 +chr13 87327483 0 0 0.0 0 +chr13 87416469 0 0 0.0 0 +chr13 87564866 0 0 0.0 0 +chr13 87598030 0 0 0.0 0 +chr13 87811752 0 0 0.0 0 +chr13 87864730 0 0 0.0 0 +chr13 88123574 0 0 0.0 0 +chr13 88127152 0 0 0.0 0 +chr13 88189128 0 0 0.0 0 +chr13 88409566 0 1 0.0196 0 +chr13 88649500 0 0 0.0 0 +chr13 88819696 0 0 0.0 0 +chr13 89010747 0 0 0.0 0 +chr13 89223568 0 0 0.0 0 +chr13 89368243 0 0 0.0 0 +chr13 89433472 0 1 0.0182 0 +chr13 89536476 0 0 0.0 0 +chr13 89618399 0 0 0.0 0 +chr13 89774759 0 0 0.0 0 +chr13 89830468 0 0 0.0 0 +chr13 89951907 0 0 0.0 0 +chr13 90011479 0 0 0.0 0 +chr13 90029230 0 0 0.0 0 +chr13 90070931 0 0 0.0 0 +chr13 90104425 0 0 0.0 0 +chr13 90125175 0 0 0.0 0 +chr13 90173152 0 0 0.0 0 +chr13 90813485 0 0 0.0 0 +chr13 90895089 0 0 0.0 0 +chr13 90980183 0 0 0.0 0 +chr13 91110433 0 0 0.0 0 +chr13 91162167 0 0 0.0 0 +chr13 91180768 0 0 0.0 0 +chr13 91193867 0 0 0.0 0 +chr13 91227558 0 0 0.0 0 +chr13 91233722 0 0 0.0 0 +chr13 91312371 0 0 0.0 0 +chr13 91686181 0 0 0.0 0 +chr13 91759017 0 0 0.0 0 +chr13 91831903 0 0 0.0 0 +chr13 91869973 0 0 0.0 0 +chr13 91878508 0 0 0.0 0 +chr13 92249732 0 0 0.0 0 +chr13 92362989 0 0 0.0 0 +chr13 92363556 0 0 0.0 0 +chr13 92369468 0 0 0.0 0 +chr13 92416769 0 0 0.0 0 +chr13 92509440 0 0 0.0 0 +chr13 92586150 0 0 0.0 0 +chr13 92932572 0 0 0.0 0 +chr13 93118307 0 0 0.0 0 +chr13 93366216 0 0 0.0 0 +chr13 93540206 0 0 0.0 0 +chr13 93869672 0 0 0.0 0 +chr13 94132058 0 0 0.0 0 +chr13 94212915 0 0 0.0 0 +chr13 94266262 0 0 0.0 0 +chr13 94486643 0 0 0.0 0 +chr13 94636244 0 0 0.0 0 +chr13 94839923 0 0 0.0 0 +chr13 94854200 0 0 0.0 0 +chr13 94883486 0 0 0.0 0 +chr13 94963771 0 0 0.0 0 +chr13 95243963 0 0 0.0 0 +chr13 95316547 0 0 0.0 0 +chr13 95371545 0 1 0.0116 0 +chr13 95513128 0 0 0.0 0 +chr13 95877338 0 0 0.0 0 +chr13 95921411 0 0 0.0 0 +chr13 95959595 0 0 0.0 0 +chr13 96052338 0 0 0.0 0 +chr13 96142584 0 0 0.0 0 +chr13 96152008 0 0 0.0 0 +chr13 96173952 0 0 0.0 0 +chr13 96186559 0 1 0.0127 0 +chr13 96240851 0 0 0.0 0 +chr13 96271497 0 0 0.0 0 +chr13 96321249 0 0 0.0 0 +chr13 96399664 0 0 0.0 0 +chr13 96474044 0 0 0.0 0 +chr13 96511112 0 0 0.0 0 +chr13 96643598 0 0 0.0 0 +chr13 96739477 0 0 0.0 0 +chr13 96850157 0 0 0.0 0 +chr13 96999141 0 0 0.0 0 +chr13 97063199 0 0 0.0 0 +chr13 97116882 0 0 0.0 0 +chr13 97154717 0 1 0.0256 0 +chr13 97183754 0 0 0.0 0 +chr13 97341318 0 0 0.0 0 +chr13 97435939 0 0 0.0 0 +chr13 97471279 0 0 0.0 0 +chr13 97761242 0 0 0.0 0 +chr13 97837102 0 1 0.0244 0 +chr13 97838044 0 0 0.0 0 +chr13 98016026 0 0 0.0 0 +chr13 98021114 0 0 0.0 0 +chr13 98095086 0 0 0.0 0 +chr13 98160373 0 0 0.0 0 +chr13 98290531 0 0 0.0 0 +chr13 98437929 1 76 0.8736 1 +chr13 98522760 0 0 0.0 0 +chr13 98815574 0 1 0.0303 0 +chr13 98839305 0 0 0.0 0 +chr13 98840784 0 0 0.0 0 +chr13 98871461 0 0 0.0 0 +chr13 98946798 0 0 0.0 0 +chr13 98949501 0 0 0.0 0 +chr13 98979537 0 0 0.0 0 +chr13 99353883 0 0 0.0 0 +chr13 99515604 0 0 0.0 0 +chr13 99536776 0 0 0.0 0 +chr13 99587980 0 0 0.0 0 +chr13 99602571 0 0 0.0 0 +chr13 99702257 0 0 0.0 0 +chr13 99804938 0 0 0.0 0 +chr13 99869140 0 0 0.0 0 +chr13 99886205 0 0 0.0 0 +chr13 99951367 0 0 0.0 0 +chr13 100193244 0 0 0.0 0 +chr13 100259085 0 0 0.0 0 +chr13 100577736 0 0 0.0 0 +chr13 100602139 0 0 0.0 0 +chr13 100621125 0 0 0.0 0 +chr13 100622391 0 0 0.0 0 +chr13 100630863 0 0 0.0 0 +chr13 100643306 0 0 0.0 0 +chr13 100758297 0 0 0.0 0 +chr13 100843358 0 0 0.0 0 +chr13 100877576 0 0 0.0 0 +chr13 100999639 0 0 0.0 0 +chr13 101022154 0 0 0.0 0 +chr13 101046799 0 0 0.0 0 +chr13 101054048 0 0 0.0 0 +chr13 101495310 0 0 0.0 0 +chr13 101572858 0 0 0.0 0 +chr13 101818378 0 0 0.0 0 +chr13 101952211 0 0 0.0 0 +chr13 102147684 0 0 0.0 0 +chr13 102182116 0 0 0.0 0 +chr13 102266385 0 0 0.0 0 +chr13 102372587 0 0 0.0 0 +chr13 102459580 0 0 0.0 0 +chr13 102486578 0 0 0.0 0 +chr13 102509928 0 0 0.0 0 +chr13 102583338 0 0 0.0 0 +chr13 102695072 0 0 0.0 0 +chr13 102797632 0 0 0.0 0 +chr13 103081493 0 0 0.0 0 +chr13 103088164 0 0 0.0 0 +chr13 103473367 0 0 0.0 0 +chr13 103536112 0 0 0.0 0 +chr13 103641548 0 0 0.0 0 +chr13 103727956 0 0 0.0 0 +chr13 103793787 0 0 0.0 0 +chr13 103829883 0 0 0.0 0 +chr13 103898194 0 0 0.0 0 +chr13 103912142 0 0 0.0 0 +chr13 104197203 0 0 0.0 0 +chr13 104213489 0 0 0.0 0 +chr13 104318679 0 0 0.0 0 +chr13 104522621 0 0 0.0 0 +chr13 104640535 0 0 0.0 0 +chr13 104675238 0 0 0.0 0 +chr13 104724474 0 0 0.0 0 +chr13 104854763 0 0 0.0 0 +chr13 105015398 0 0 0.0 0 +chr13 105160371 0 0 0.0 0 +chr13 105169006 0 0 0.0 0 +chr13 105185933 0 0 0.0 0 +chr13 105259093 0 0 0.0 0 +chr13 105282222 0 0 0.0 0 +chr13 105314931 0 0 0.0 0 +chr13 105458179 0 0 0.0 0 +chr13 105596732 0 0 0.0 0 +chr13 106036741 0 0 0.0 0 +chr13 106128823 0 0 0.0 0 +chr13 106133436 0 0 0.0 0 +chr13 106244421 0 0 0.0 0 +chr13 106279375 0 0 0.0 0 +chr13 106290619 0 0 0.0 0 +chr13 106369317 0 0 0.0 0 +chr13 106493102 0 0 0.0 0 +chr13 106518765 0 0 0.0 0 +chr13 106544937 0 1 0.0222 0 +chr13 106597271 0 0 0.0 0 +chr13 106721660 0 0 0.0 0 +chr13 106751118 0 0 0.0 0 +chr13 106758093 0 0 0.0 0 +chr13 106769807 0 0 0.0 0 +chr13 106830666 0 0 0.0 0 +chr13 106970097 0 0 0.0 0 +chr13 107227439 0 0 0.0 0 +chr13 107399238 0 0 0.0 0 +chr13 107445638 0 0 0.0 0 +chr13 107571698 0 0 0.0 0 +chr13 107924349 0 0 0.0 0 +chr13 107994692 0 1 0.0112 0 +chr13 108216908 0 0 0.0 0 +chr13 108218222 0 0 0.0 0 +chr13 108302232 0 0 0.0 0 +chr13 108396249 0 0 0.0 0 +chr13 108409160 0 0 0.0 0 +chr13 108448655 0 0 0.0 0 +chr13 108498402 0 0 0.0 0 +chr13 108548321 0 0 0.0 0 +chr13 108644315 0 0 0.0 0 +chr13 108697382 0 0 0.0 0 +chr13 108815493 0 0 0.0 0 +chr13 108845970 0 0 0.0 0 +chr13 108903889 0 0 0.0 0 +chr13 109132939 0 0 0.0 0 +chr13 109158546 0 0 0.0 0 +chr13 109273048 0 0 0.0 0 +chr13 109680606 0 0 0.0 0 +chr13 109732683 0 0 0.0 0 +chr13 109740698 0 0 0.0 0 +chr13 109910797 0 0 0.0 0 +chr13 109925508 0 0 0.0 0 +chr13 110010136 0 0 0.0 0 +chr13 110096698 0 0 0.0 0 +chr13 110116682 0 0 0.0 0 +chr13 110218783 0 0 0.0 0 +chr13 110241896 0 0 0.0 0 +chr13 110266312 0 0 0.0 0 +chr13 110354959 0 0 0.0 0 +chr13 110398443 0 0 0.0 0 +chr13 110411249 0 0 0.0 0 +chr13 110431747 0 0 0.0 0 +chr13 110440005 0 0 0.0 0 +chr13 110527734 0 0 0.0 0 +chr13 110625540 0 0 0.0 0 +chr13 110775814 0 0 0.0 0 +chr13 110807726 0 0 0.0 0 +chr13 110853168 0 0 0.0 0 +chr13 110888250 0 0 0.0 0 +chr13 110936276 0 0 0.0 0 +chr13 110977729 0 0 0.0 0 +chr13 111076151 0 0 0.0 0 +chr13 111097058 0 0 0.0 0 +chr13 111152916 0 0 0.0 0 +chr13 111302840 0 0 0.0 0 +chr13 111334493 0 0 0.0 0 +chr13 111366204 0 0 0.0 0 +chr13 111390219 0 0 0.0 0 +chr13 111453260 0 0 0.0 0 +chr13 111459049 0 0 0.0 0 +chr13 111472464 0 0 0.0 0 +chr13 111474584 0 0 0.0 0 +chr13 111491868 0 0 0.0 0 +chr13 111524613 0 0 0.0 0 +chr13 111543322 0 0 0.0 0 +chr13 111571832 0 0 0.0 0 +chr13 111671660 0 0 0.0 0 +chr13 111680958 0 0 0.0 0 +chr13 111756574 0 0 0.0 0 +chr13 111765851 0 0 0.0 0 +chr13 111853490 0 0 0.0 0 +chr13 111860823 0 0 0.0 0 +chr13 111861650 0 0 0.0 0 +chr13 111903714 0 0 0.0 0 +chr13 111973383 0 0 0.0 0 +chr13 112020075 0 0 0.0 0 +chr13 112120382 0 0 0.0 0 +chr13 112159104 0 0 0.0 0 +chr13 112166952 0 0 0.0 0 +chr13 112183134 0 0 0.0 0 +chr13 112184344 0 0 0.0 0 +chr13 112202541 0 0 0.0 0 +chr13 112209025 0 0 0.0 0 +chr13 112396821 0 0 0.0 0 +chr13 112446399 0 0 0.0 0 +chr13 112496351 0 0 0.0 0 +chr13 112555949 0 0 0.0 0 +chr13 112596129 0 0 0.0 0 +chr13 112624109 0 0 0.0 0 +chr13 112627405 0 0 0.0 0 +chr13 112752149 0 0 0.0 0 +chr13 112859567 0 0 0.0 0 +chr13 112880679 0 0 0.0 0 +chr13 112982701 0 0 0.0 0 +chr13 113027355 0 0 0.0 0 +chr13 113167984 0 0 0.0 0 +chr13 113188364 0 0 0.0 0 +chr13 113215310 0 0 0.0 0 +chr13 113216116 0 0 0.0 0 +chr13 113294071 0 0 0.0 0 +chr13 113306737 0 0 0.0 0 +chr13 113345500 0 0 0.0 0 +chr13 113371947 0 0 0.0 0 +chr13 113442801 0 0 0.0 0 +chr13 113585435 0 1 0.0196 0 +chr13 113595262 0 0 0.0 0 +chr13 113660194 0 0 0.0 0 +chr13 113792887 0 0 0.0 0 +chr13 113832235 0 0 0.0 0 +chr13 113833819 0 0 0.0 0 +chr13 113835559 0 0 0.0 0 +chr13 113842840 0 0 0.0 0 +chr13 113918442 0 0 0.0 0 +chr13 114009086 0 0 0.0 0 +chr13 114024400 0 0 0.0 0 +chr13 114051406 0 1 0.0213 0 +chr13 114268457 0 0 0.0 0 +chr13_KI270838v1_alt 19667 0 0 0.0 0 +chr13_KI270839v1_alt 145386 0 0 0.0 0 +chr13_KI270840v1_alt 51337 0 0 0.0 0 +chr13_KI270843v1_alt 87001 0 0 0.0 0 +chr14 16099627 0 0 0.0 0 +chr14 16100366 1 35 0.2713 1 +chr14 16102328 0 0 0.0 0 +chr14 16120631 0 0 0.0 0 +chr14 16171413 0 0 0.0 0 +chr14 16229043 0 0 0.0 0 +chr14 16232471 0 0 0.0 0 +chr14 16235900 0 0 0.0 0 +chr14 16242749 0 0 0.0 0 +chr14 16246175 0 0 0.0 0 +chr14 16249604 0 0 0.0 0 +chr14 16253030 0 0 0.0 0 +chr14 16259879 0 0 0.0 0 +chr14 16263307 0 0 0.0 0 +chr14 16266734 0 0 0.0 0 +chr14 16270160 0 0 0.0 0 +chr14 16273585 0 0 0.0 0 +chr14 16280437 0 0 0.0 0 +chr14 16284990 0 0 0.0 0 +chr14 16291841 0 0 0.0 0 +chr14 16298690 0 0 0.0 0 +chr14 16302115 0 0 0.0 0 +chr14 16308965 0 0 0.0 0 +chr14 16315816 0 0 0.0 0 +chr14 16319241 0 0 0.0 0 +chr14 16322666 0 0 0.0 0 +chr14 16326092 0 0 0.0 0 +chr14 16332942 0 0 0.0 0 +chr14 16336366 0 0 0.0 0 +chr14 16339790 0 0 0.0 0 +chr14 16343215 0 0 0.0 0 +chr14 18239790 0 0 0.0 0 +chr14 18243882 0 0 0.0 0 +chr14 18247123 0 0 0.0 0 +chr14 18299403 0 0 0.0 0 +chr14 18589026 0 0 0.0 0 +chr14 19055490 0 0 0.0 0 +chr14 19080453 0 0 0.0 0 +chr14 19112558 0 0 0.0 0 +chr14 19287432 0 0 0.0 0 +chr14 19344535 0 0 0.0 0 +chr14 20197643 0 0 0.0 0 +chr14 20409517 0 0 0.0 0 +chr14 20459498 0 0 0.0 0 +chr14 20473930 0 0 0.0 0 +chr14 20495272 0 0 0.0 0 +chr14 20550244 0 0 0.0 0 +chr14 20660844 0 0 0.0 0 +chr14 20681906 0 0 0.0 0 +chr14 20965527 0 0 0.0 0 +chr14 20967623 0 0 0.0 0 +chr14 21016821 0 0 0.0 0 +chr14 21065340 0 0 0.0 0 +chr14 21587428 0 0 0.0 0 +chr14 21642429 0 0 0.0 0 +chr14 21768407 0 0 0.0 0 +chr14 21871164 0 0 0.0 0 +chr14 21935298 0 0 0.0 0 +chr14 21958678 0 0 0.0 0 +chr14 21974833 0 0 0.0 0 +chr14 22014008 0 0 0.0 0 +chr14 22128331 0 0 0.0 0 +chr14 22313720 0 0 0.0 0 +chr14 22320848 0 0 0.0 0 +chr14 22547668 0 0 0.0 0 +chr14 22556992 0 0 0.0 0 +chr14 22606948 0 0 0.0 0 +chr14 22610878 0 0 0.0 0 +chr14 22620903 0 0 0.0 0 +chr14 22656261 0 0 0.0 0 +chr14 22665502 1 3 0.04 1 +chr14 22872264 0 0 0.0 0 +chr14 22917976 0 0 0.0 0 +chr14 23046327 0 0 0.0 0 +chr14 23379371 0 0 0.0 0 +chr14 23423795 0 0 0.0 0 +chr14 23476531 0 0 0.0 0 +chr14 23562508 0 0 0.0 0 +chr14 23612416 0 0 0.0 0 +chr14 23692345 0 0 0.0 0 +chr14 23706168 0 0 0.0 0 +chr14 23929104 0 0 0.0 0 +chr14 24065579 0 0 0.0 0 +chr14 24102461 0 0 0.0 0 +chr14 24182343 0 0 0.0 0 +chr14 24197366 0 0 0.0 0 +chr14 24338204 0 0 0.0 0 +chr14 24340920 0 0 0.0 0 +chr14 24366897 0 0 0.0 0 +chr14 24406329 0 0 0.0 0 +chr14 24411106 0 0 0.0 0 +chr14 24442193 0 0 0.0 0 +chr14 24473475 0 0 0.0 0 +chr14 24574771 0 0 0.0 0 +chr14 24654420 0 0 0.0 0 +chr14 24768745 0 0 0.0 0 +chr14 24788462 0 0 0.0 0 +chr14 24850293 0 0 0.0 0 +chr14 24945773 0 0 0.0 0 +chr14 24984857 0 0 0.0 0 +chr14 25128007 0 0 0.0 0 +chr14 25167952 0 0 0.0 0 +chr14 25179210 0 0 0.0 0 +chr14 25269007 0 0 0.0 0 +chr14 25387074 0 0 0.0 0 +chr14 25571020 0 0 0.0 0 +chr14 25617120 0 0 0.0 0 +chr14 25626190 0 0 0.0 0 +chr14 25776601 0 0 0.0 0 +chr14 25902915 0 0 0.0 0 +chr14 25944730 0 0 0.0 0 +chr14 25979452 0 0 0.0 0 +chr14 26049849 0 0 0.0 0 +chr14 26066552 0 0 0.0 0 +chr14 26134680 0 0 0.0 0 +chr14 26236813 0 0 0.0 0 +chr14 26280341 0 0 0.0 0 +chr14 26281736 0 0 0.0 0 +chr14 26574576 0 0 0.0 0 +chr14 26952243 0 0 0.0 0 +chr14 27021894 0 0 0.0 0 +chr14 27384489 0 0 0.0 0 +chr14 27449083 0 0 0.0 0 +chr14 27626744 0 0 0.0 0 +chr14 27629480 0 0 0.0 0 +chr14 27950138 0 0 0.0 0 +chr14 28324404 0 0 0.0 0 +chr14 28473349 0 0 0.0 0 +chr14 28535672 0 0 0.0 0 +chr14 28543625 0 0 0.0 0 +chr14 28756961 0 0 0.0 0 +chr14 28841721 0 0 0.0 0 +chr14 28886379 0 1 0.04 0 +chr14 28905805 0 0 0.0 0 +chr14 28916081 0 0 0.0 0 +chr14 29008954 0 0 0.0 0 +chr14 29155512 0 0 0.0 0 +chr14 29202095 0 0 0.0 0 +chr14 29394653 0 0 0.0 0 +chr14 29442090 0 0 0.0 0 +chr14 29500712 0 0 0.0 0 +chr14 29909380 0 0 0.0 0 +chr14 29960678 0 0 0.0 0 +chr14 30081032 0 0 0.0 0 +chr14 30114062 0 0 0.0 0 +chr14 30138687 0 0 0.0 0 +chr14 30160959 0 0 0.0 0 +chr14 30204013 0 0 0.0 0 +chr14 30568981 0 0 0.0 0 +chr14 30633676 0 0 0.0 0 +chr14 30716657 0 0 0.0 0 +chr14 30739821 0 0 0.0 0 +chr14 30743268 0 0 0.0 0 +chr14 31009988 0 0 0.0 0 +chr14 31072415 0 0 0.0 0 +chr14 31209405 0 0 0.0 0 +chr14 31494703 0 0 0.0 0 +chr14 31610162 0 0 0.0 0 +chr14 31900135 0 0 0.0 0 +chr14 31913066 0 0 0.0 0 +chr14 32273001 0 0 0.0 0 +chr14 32322573 0 0 0.0 0 +chr14 32412580 0 0 0.0 0 +chr14 32453214 0 0 0.0 0 +chr14 32473784 0 0 0.0 0 +chr14 32588705 0 0 0.0 0 +chr14 32651104 0 0 0.0 0 +chr14 32658074 0 0 0.0 0 +chr14 32907279 0 0 0.0 0 +chr14 32992443 0 0 0.0 0 +chr14 33135914 0 0 0.0 0 +chr14 33348039 0 0 0.0 0 +chr14 33364281 0 0 0.0 0 +chr14 33457302 0 0 0.0 0 +chr14 33563169 0 0 0.0 0 +chr14 33584346 0 0 0.0 0 +chr14 33821055 0 0 0.0 0 +chr14 34049675 0 0 0.0 0 +chr14 34081081 0 0 0.0 0 +chr14 34126435 0 0 0.0 0 +chr14 34337705 0 0 0.0 0 +chr14 34688971 0 0 0.0 0 +chr14 34878401 0 0 0.0 0 +chr14 34959395 0 0 0.0 0 +chr14 35093740 0 0 0.0 0 +chr14 35118561 0 0 0.0 0 +chr14 35122300 0 0 0.0 0 +chr14 35367320 0 0 0.0 0 +chr14 35615216 0 0 0.0 0 +chr14 35711365 0 0 0.0 0 +chr14 35768766 0 0 0.0 0 +chr14 35815857 0 0 0.0 0 +chr14 35829627 0 0 0.0 0 +chr14 35844057 0 0 0.0 0 +chr14 35918580 0 0 0.0 0 +chr14 36037745 0 0 0.0 0 +chr14 36054949 0 0 0.0 0 +chr14 36162079 0 0 0.0 0 +chr14 36174705 0 0 0.0 0 +chr14 36500553 0 0 0.0 0 +chr14 36634326 0 0 0.0 0 +chr14 36676244 0 0 0.0 0 +chr14 36737023 0 0 0.0 0 +chr14 36838182 0 0 0.0 0 +chr14 36841516 0 0 0.0 0 +chr14 36897817 0 0 0.0 0 +chr14 36936223 0 0 0.0 0 +chr14 36950954 0 0 0.0 0 +chr14 37086381 0 0 0.0 0 +chr14 37120944 0 0 0.0 0 +chr14 37174175 0 2 0.0299 0 +chr14 37203466 0 0 0.0 0 +chr14 37417918 0 0 0.0 0 +chr14 37492809 0 0 0.0 0 +chr14 37618692 0 0 0.0 0 +chr14 37628234 0 0 0.0 0 +chr14 37821330 0 0 0.0 0 +chr14 38028904 0 0 0.0 0 +chr14 38501822 0 0 0.0 0 +chr14 38922540 0 0 0.0 0 +chr14 39141545 0 0 0.0 0 +chr14 39377224 1 12 0.1446 1 +chr14 39463102 0 0 0.0 0 +chr14 39537301 0 0 0.0 0 +chr14 39656751 0 0 0.0 0 +chr14 39971408 0 0 0.0 0 +chr14 40007405 0 0 0.0 0 +chr14 40253209 0 0 0.0 0 +chr14 40445245 0 0 0.0 0 +chr14 40550106 0 0 0.0 0 +chr14 40558414 0 0 0.0 0 +chr14 40627886 0 0 0.0 0 +chr14 40654302 0 0 0.0 0 +chr14 40663525 0 0 0.0 0 +chr14 40667498 0 0 0.0 0 +chr14 40866588 0 0 0.0 0 +chr14 41104596 0 0 0.0 0 +chr14 41276626 0 0 0.0 0 +chr14 41521946 0 0 0.0 0 +chr14 41652064 0 0 0.0 0 +chr14 41690339 0 0 0.0 0 +chr14 41760384 0 0 0.0 0 +chr14 41772942 0 0 0.0 0 +chr14 41796750 0 0 0.0 0 +chr14 42052567 0 0 0.0 0 +chr14 42076294 0 0 0.0 0 +chr14 42148551 0 0 0.0 0 +chr14 42233727 0 0 0.0 0 +chr14 42303015 0 0 0.0 0 +chr14 42503982 0 0 0.0 0 +chr14 42617228 0 0 0.0 0 +chr14 42868184 0 0 0.0 0 +chr14 42922889 0 0 0.0 0 +chr14 42949706 0 0 0.0 0 +chr14 43209363 0 0 0.0 0 +chr14 43288144 0 0 0.0 0 +chr14 43405347 0 0 0.0 0 +chr14 43542280 0 0 0.0 0 +chr14 43577202 0 0 0.0 0 +chr14 43615427 0 0 0.0 0 +chr14 43858999 0 1 0.0167 0 +chr14 43936693 0 0 0.0 0 +chr14 44075371 0 0 0.0 0 +chr14 44232676 0 0 0.0 0 +chr14 44405979 0 0 0.0 0 +chr14 44521373 0 0 0.0 0 +chr14 44547629 0 0 0.0 0 +chr14 44558991 0 1 0.0179 0 +chr14 44560705 0 0 0.0 0 +chr14 44604929 0 0 0.0 0 +chr14 44626059 0 0 0.0 0 +chr14 44659823 0 0 0.0 0 +chr14 44668195 0 0 0.0 0 +chr14 44744803 0 0 0.0 0 +chr14 44964144 0 0 0.0 0 +chr14 45084311 0 0 0.0 0 +chr14 45354216 0 0 0.0 0 +chr14 45391977 0 0 0.0 0 +chr14 45603913 0 0 0.0 0 +chr14 45672820 0 0 0.0 0 +chr14 45731253 0 0 0.0 0 +chr14 45755919 0 0 0.0 0 +chr14 45939955 0 0 0.0 0 +chr14 45979087 0 0 0.0 0 +chr14 46123591 0 0 0.0 0 +chr14 46205249 1 38 0.8636 1 +chr14 46235453 0 0 0.0 0 +chr14 46263278 0 1 0.0256 0 +chr14 46438778 0 0 0.0 0 +chr14 46691974 0 0 0.0 0 +chr14 46692640 0 0 0.0 0 +chr14 46853354 0 0 0.0 0 +chr14 46860161 0 0 0.0 0 +chr14 47435579 0 1 0.0133 0 +chr14 47445433 0 0 0.0 0 +chr14 47651858 0 0 0.0 0 +chr14 47665929 0 0 0.0 0 +chr14 47673333 0 0 0.0 0 +chr14 47684677 0 0 0.0 0 +chr14 48236289 0 0 0.0 0 +chr14 48356896 0 0 0.0 0 +chr14 48727953 0 0 0.0 0 +chr14 48738625 0 0 0.0 0 +chr14 48902647 0 0 0.0 0 +chr14 49054934 0 0 0.0 0 +chr14 49062608 0 0 0.0 0 +chr14 49276006 0 0 0.0 0 +chr14 49299621 0 0 0.0 0 +chr14 49511654 0 0 0.0 0 +chr14 49879974 0 0 0.0 0 +chr14 49980648 0 0 0.0 0 +chr14 49998161 0 0 0.0 0 +chr14 50097564 0 0 0.0 0 +chr14 50304981 0 0 0.0 0 +chr14 50390268 0 0 0.0 0 +chr14 50574379 0 0 0.0 0 +chr14 50916736 0 0 0.0 0 +chr14 50954475 0 0 0.0 0 +chr14 51141623 0 0 0.0 0 +chr14 51287402 0 0 0.0 0 +chr14 51300407 0 0 0.0 0 +chr14 51356072 0 0 0.0 0 +chr14 51394011 0 0 0.0 0 +chr14 51411521 0 0 0.0 0 +chr14 51567267 0 0 0.0 0 +chr14 51570103 0 0 0.0 0 +chr14 51639193 0 0 0.0 0 +chr14 51719039 0 0 0.0 0 +chr14 51818780 0 0 0.0 0 +chr14 51819534 0 0 0.0 0 +chr14 51844460 0 0 0.0 0 +chr14 51897563 0 0 0.0 0 +chr14 51997216 0 0 0.0 0 +chr14 52051220 0 0 0.0 0 +chr14 53002306 0 0 0.0 0 +chr14 53054448 0 0 0.0 0 +chr14 53089816 0 1 0.0256 0 +chr14 53114012 0 0 0.0 0 +chr14 53217528 0 0 0.0 0 +chr14 53263654 0 0 0.0 0 +chr14 53271794 0 0 0.0 0 +chr14 53354620 0 0 0.0 0 +chr14 53693772 0 0 0.0 0 +chr14 53854381 0 0 0.0 0 +chr14 53873975 0 0 0.0 0 +chr14 54196763 0 0 0.0 0 +chr14 54240319 0 0 0.0 0 +chr14 54255678 0 0 0.0 0 +chr14 54277776 0 0 0.0 0 +chr14 54378713 0 0 0.0 0 +chr14 54462819 0 0 0.0 0 +chr14 54554729 0 0 0.0 0 +chr14 54645224 0 0 0.0 0 +chr14 54708448 0 0 0.0 0 +chr14 54782698 0 0 0.0 0 +chr14 54849700 0 0 0.0 0 +chr14 54891040 0 0 0.0 0 +chr14 54902155 0 0 0.0 0 +chr14 54979523 0 0 0.0 0 +chr14 55015446 0 0 0.0 0 +chr14 55273144 0 0 0.0 0 +chr14 55359325 0 0 0.0 0 +chr14 55439546 0 0 0.0 0 +chr14 55697705 0 0 0.0 0 +chr14 55713186 0 0 0.0 0 +chr14 55849443 0 0 0.0 0 +chr14 55865901 0 0 0.0 0 +chr14 55901108 0 0 0.0 0 +chr14 56074421 0 0 0.0 0 +chr14 56202061 0 0 0.0 0 +chr14 56214507 0 0 0.0 0 +chr14 56319716 0 0 0.0 0 +chr14 56432583 0 0 0.0 0 +chr14 56455654 0 0 0.0 0 +chr14 56542775 0 0 0.0 0 +chr14 56547495 0 0 0.0 0 +chr14 56720456 0 0 0.0 0 +chr14 56844247 0 0 0.0 0 +chr14 56909733 0 0 0.0 0 +chr14 57024605 0 0 0.0 0 +chr14 57061247 0 0 0.0 0 +chr14 57084920 0 0 0.0 0 +chr14 57246257 0 0 0.0 0 +chr14 57419280 0 0 0.0 0 +chr14 57544379 0 0 0.0 0 +chr14 57637594 0 0 0.0 0 +chr14 57740181 0 0 0.0 0 +chr14 57798169 0 1 0.0357 0 +chr14 57799792 0 0 0.0 0 +chr14 57803657 0 0 0.0 0 +chr14 58020709 0 0 0.0 0 +chr14 58123211 0 0 0.0 0 +chr14 58160276 0 0 0.0 0 +chr14 58300127 0 0 0.0 0 +chr14 58301617 0 0 0.0 0 +chr14 58318803 0 0 0.0 0 +chr14 58330079 0 0 0.0 0 +chr14 58346045 0 0 0.0 0 +chr14 58407616 0 0 0.0 0 +chr14 58521104 0 0 0.0 0 +chr14 58525853 0 0 0.0 0 +chr14 58744321 0 0 0.0 0 +chr14 58749078 0 0 0.0 0 +chr14 58983982 0 0 0.0 0 +chr14 59061292 0 0 0.0 0 +chr14 59089924 0 0 0.0 0 +chr14 59094623 0 0 0.0 0 +chr14 59191775 0 0 0.0 0 +chr14 59329006 0 0 0.0 0 +chr14 59536019 0 0 0.0 0 +chr14 59544528 0 0 0.0 0 +chr14 59704223 0 0 0.0 0 +chr14 59768168 0 0 0.0 0 +chr14 59939346 0 0 0.0 0 +chr14 59964060 0 0 0.0 0 +chr14 60051312 0 0 0.0 0 +chr14 60220527 0 0 0.0 0 +chr14 60244363 0 0 0.0 0 +chr14 60316545 0 0 0.0 0 +chr14 60470362 0 0 0.0 0 +chr14 60533888 0 0 0.0 0 +chr14 60629106 0 0 0.0 0 +chr14 60641013 0 0 0.0 0 +chr14 60681444 0 0 0.0 0 +chr14 60685318 0 0 0.0 0 +chr14 61048130 0 0 0.0 0 +chr14 61142230 0 0 0.0 0 +chr14 61145380 0 0 0.0 0 +chr14 61272713 0 0 0.0 0 +chr14 61340927 0 0 0.0 0 +chr14 61357689 0 0 0.0 0 +chr14 61534148 0 0 0.0 0 +chr14 61889182 0 0 0.0 0 +chr14 61918415 0 0 0.0 0 +chr14 62036314 0 0 0.0 0 +chr14 62066854 0 0 0.0 0 +chr14 62207466 0 0 0.0 0 +chr14 62213445 0 0 0.0 0 +chr14 62630451 0 0 0.0 0 +chr14 62774756 0 0 0.0 0 +chr14 62860871 0 1 0.0263 0 +chr14 62920341 0 0 0.0 0 +chr14 62929488 0 0 0.0 0 +chr14 63010559 0 0 0.0 0 +chr14 63051881 0 2 0.0351 0 +chr14 63144266 0 0 0.0 0 +chr14 63437440 0 0 0.0 0 +chr14 63533488 0 0 0.0 0 +chr14 63563127 0 0 0.0 0 +chr14 63756471 0 0 0.0 0 +chr14 63846689 0 1 0.0233 0 +chr14 63902023 0 0 0.0 0 +chr14 64019756 0 0 0.0 0 +chr14 64280639 0 0 0.0 0 +chr14 64454890 0 0 0.0 0 +chr14 64535488 0 0 0.0 0 +chr14 64655925 0 0 0.0 0 +chr14 64697965 0 0 0.0 0 +chr14 64717284 0 0 0.0 0 +chr14 64753197 0 0 0.0 0 +chr14 64826307 0 0 0.0 0 +chr14 64828230 0 0 0.0 0 +chr14 64945681 0 0 0.0 0 +chr14 64976846 0 0 0.0 0 +chr14 65140681 0 0 0.0 0 +chr14 65244704 0 0 0.0 0 +chr14 65538253 0 0 0.0 0 +chr14 65653200 0 0 0.0 0 +chr14 65728531 0 0 0.0 0 +chr14 65750333 0 0 0.0 0 +chr14 65766704 0 0 0.0 0 +chr14 65954813 0 0 0.0 0 +chr14 65992953 0 0 0.0 0 +chr14 66020773 0 0 0.0 0 +chr14 66108621 0 0 0.0 0 +chr14 66206777 0 0 0.0 0 +chr14 66225439 0 0 0.0 0 +chr14 66482095 0 0 0.0 0 +chr14 66523846 0 0 0.0 0 +chr14 66530317 0 0 0.0 0 +chr14 66832764 0 0 0.0 0 +chr14 67073162 0 0 0.0 0 +chr14 67113083 0 0 0.0 0 +chr14 67165695 0 0 0.0 0 +chr14 67172584 0 0 0.0 0 +chr14 67200001 0 1 0.0161 0 +chr14 67263825 1 34 0.4533 1 +chr14 67324850 0 0 0.0 0 +chr14 67517392 0 0 0.0 0 +chr14 67570082 0 0 0.0 0 +chr14 67624799 0 0 0.0 0 +chr14 67756696 0 0 0.0 0 +chr14 67808075 0 0 0.0 0 +chr14 67913512 0 0 0.0 0 +chr14 68208934 0 0 0.0 0 +chr14 68236155 0 0 0.0 0 +chr14 68298277 0 0 0.0 0 +chr14 68451024 0 0 0.0 0 +chr14 68612158 0 0 0.0 0 +chr14 68657897 0 0 0.0 0 +chr14 68702346 0 0 0.0 0 +chr14 68711661 0 1 0.0112 0 +chr14 68767347 0 0 0.0 0 +chr14 68898687 0 0 0.0 0 +chr14 68959146 0 0 0.0 0 +chr14 69085042 0 0 0.0 0 +chr14 69093250 0 0 0.0 0 +chr14 69177121 0 0 0.0 0 +chr14 69245129 0 0 0.0 0 +chr14 69658645 0 0 0.0 0 +chr14 69818069 0 0 0.0 0 +chr14 69827506 0 0 0.0 0 +chr14 69873771 0 0 0.0 0 +chr14 70115050 0 0 0.0 0 +chr14 70145022 0 0 0.0 0 +chr14 70218025 0 0 0.0 0 +chr14 70287409 0 0 0.0 0 +chr14 70443681 0 0 0.0 0 +chr14 70502181 0 0 0.0 0 +chr14 70528548 0 0 0.0 0 +chr14 70546295 0 0 0.0 0 +chr14 70717202 0 0 0.0 0 +chr14 70718587 0 0 0.0 0 +chr14 70720982 0 0 0.0 0 +chr14 70753783 0 0 0.0 0 +chr14 70840545 0 0 0.0 0 +chr14 70968214 0 0 0.0 0 +chr14 71030413 0 0 0.0 0 +chr14 71044248 0 0 0.0 0 +chr14 71054962 0 0 0.0 0 +chr14 71084717 0 0 0.0 0 +chr14 71135345 0 0 0.0 0 +chr14 71203592 0 0 0.0 0 +chr14 71212982 0 0 0.0 0 +chr14 71261770 0 0 0.0 0 +chr14 71484496 0 0 0.0 0 +chr14 71573622 0 0 0.0 0 +chr14 71630521 0 0 0.0 0 +chr14 71693906 0 0 0.0 0 +chr14 71749628 0 0 0.0 0 +chr14 71824785 0 0 0.0 0 +chr14 71834842 0 2 0.0317 0 +chr14 72056246 0 0 0.0 0 +chr14 72130305 0 0 0.0 0 +chr14 72160545 0 0 0.0 0 +chr14 72166602 0 0 0.0 0 +chr14 72189318 0 0 0.0 0 +chr14 72255345 0 0 0.0 0 +chr14 72332747 0 0 0.0 0 +chr14 72404374 0 0 0.0 0 +chr14 72439888 0 0 0.0 0 +chr14 72452257 0 0 0.0 0 +chr14 72536807 0 1 0.0135 0 +chr14 72551697 0 0 0.0 0 +chr14 72556969 0 0 0.0 0 +chr14 72647156 0 0 0.0 0 +chr14 72808650 0 0 0.0 0 +chr14 72809891 0 0 0.0 0 +chr14 72852795 0 0 0.0 0 +chr14 72925175 0 0 0.0 0 +chr14 72936628 0 0 0.0 0 +chr14 73031572 0 0 0.0 0 +chr14 73329557 0 0 0.0 0 +chr14 73363465 0 0 0.0 0 +chr14 73410156 0 0 0.0 0 +chr14 73512286 0 0 0.0 0 +chr14 73589945 0 0 0.0 0 +chr14 73747793 0 0 0.0 0 +chr14 74084808 0 0 0.0 0 +chr14 74403815 0 0 0.0 0 +chr14 74406334 0 0 0.0 0 +chr14 74461349 0 0 0.0 0 +chr14 74480268 0 0 0.0 0 +chr14 74594215 0 0 0.0 0 +chr14 74600277 0 0 0.0 0 +chr14 74616759 0 0 0.0 0 +chr14 74829710 0 0 0.0 0 +chr14 74942564 0 0 0.0 0 +chr14 75259320 0 0 0.0 0 +chr14 75266737 0 0 0.0 0 +chr14 75381282 0 0 0.0 0 +chr14 75419645 0 0 0.0 0 +chr14 75499280 0 0 0.0 0 +chr14 75522410 0 0 0.0 0 +chr14 75569753 0 0 0.0 0 +chr14 75612502 0 0 0.0 0 +chr14 75740643 0 0 0.0 0 +chr14 75955602 0 0 0.0 0 +chr14 76172256 0 0 0.0 0 +chr14 76211040 0 0 0.0 0 +chr14 76227257 0 0 0.0 0 +chr14 76445106 0 0 0.0 0 +chr14 76491786 0 0 0.0 0 +chr14 76498886 0 0 0.0 0 +chr14 76536208 0 0 0.0 0 +chr14 76692656 0 0 0.0 0 +chr14 76825446 0 0 0.0 0 +chr14 76967983 0 0 0.0 0 +chr14 77011552 0 0 0.0 0 +chr14 77013802 0 0 0.0 0 +chr14 77090014 0 0 0.0 0 +chr14 77251829 0 0 0.0 0 +chr14 77253339 0 0 0.0 0 +chr14 77380729 0 0 0.0 0 +chr14 77399732 0 0 0.0 0 +chr14 77737747 0 0 0.0 0 +chr14 78035917 0 0 0.0 0 +chr14 78191480 0 0 0.0 0 +chr14 78240852 0 0 0.0 0 +chr14 78425486 0 0 0.0 0 +chr14 78444843 0 0 0.0 0 +chr14 78450383 0 1 0.0182 0 +chr14 78587149 0 0 0.0 0 +chr14 78773406 0 0 0.0 0 +chr14 78910129 0 0 0.0 0 +chr14 78949432 0 0 0.0 0 +chr14 79033372 0 0 0.0 0 +chr14 79285538 0 0 0.0 0 +chr14 79294835 0 0 0.0 0 +chr14 79388172 0 0 0.0 0 +chr14 79504243 0 0 0.0 0 +chr14 80189688 0 0 0.0 0 +chr14 80200984 0 0 0.0 0 +chr14 80203767 0 0 0.0 0 +chr14 80284819 0 0 0.0 0 +chr14 80322210 0 0 0.0 0 +chr14 80339275 0 0 0.0 0 +chr14 80377142 0 0 0.0 0 +chr14 80463695 0 0 0.0 0 +chr14 80548526 0 0 0.0 0 +chr14 81072211 0 0 0.0 0 +chr14 81085741 0 0 0.0 0 +chr14 81093979 0 0 0.0 0 +chr14 81330286 0 0 0.0 0 +chr14 81446857 0 0 0.0 0 +chr14 81482964 0 0 0.0 0 +chr14 81540969 0 0 0.0 0 +chr14 81673245 0 0 0.0 0 +chr14 81810437 0 0 0.0 0 +chr14 81832752 0 0 0.0 0 +chr14 81843643 0 1 0.02 0 +chr14 81870960 0 0 0.0 0 +chr14 82202278 0 0 0.0 0 +chr14 82264022 0 0 0.0 0 +chr14 82440212 0 0 0.0 0 +chr14 82551823 0 0 0.0 0 +chr14 82569745 0 0 0.0 0 +chr14 82623766 0 0 0.0 0 +chr14 82743095 0 0 0.0 0 +chr14 82852902 0 0 0.0 0 +chr14 82872280 0 0 0.0 0 +chr14 83189620 0 0 0.0 0 +chr14 83320669 0 0 0.0 0 +chr14 83646215 0 0 0.0 0 +chr14 83719278 0 0 0.0 0 +chr14 84088896 0 0 0.0 0 +chr14 84479371 0 0 0.0 0 +chr14 84768434 0 0 0.0 0 +chr14 84833135 0 0 0.0 0 +chr14 85036834 0 0 0.0 0 +chr14 85227069 0 0 0.0 0 +chr14 85380797 0 0 0.0 0 +chr14 85477177 0 0 0.0 0 +chr14 85608139 0 0 0.0 0 +chr14 85614485 0 0 0.0 0 +chr14 85706298 0 0 0.0 0 +chr14 85776977 0 0 0.0 0 +chr14 85784139 0 0 0.0 0 +chr14 85813912 0 0 0.0 0 +chr14 86094497 0 0 0.0 0 +chr14 86237945 0 0 0.0 0 +chr14 86297851 0 0 0.0 0 +chr14 86528577 0 0 0.0 0 +chr14 86530856 0 0 0.0 0 +chr14 86563161 0 0 0.0 0 +chr14 86571292 0 0 0.0 0 +chr14 86579210 0 0 0.0 0 +chr14 86590756 0 0 0.0 0 +chr14 86857286 0 0 0.0 0 +chr14 86903434 0 0 0.0 0 +chr14 86999373 0 0 0.0 0 +chr14 87082709 0 0 0.0 0 +chr14 87136604 0 0 0.0 0 +chr14 87256986 0 0 0.0 0 +chr14 87320640 0 0 0.0 0 +chr14 87560102 0 0 0.0 0 +chr14 87600242 0 0 0.0 0 +chr14 87633221 0 0 0.0 0 +chr14 87639731 0 0 0.0 0 +chr14 87696648 0 0 0.0 0 +chr14 87702697 0 1 0.025 0 +chr14 87705212 0 0 0.0 0 +chr14 87732434 0 0 0.0 0 +chr14 87869006 0 1 0.0238 0 +chr14 87958773 0 0 0.0 0 +chr14 88001889 2 49 0.98 1 +chr14 88150630 0 0 0.0 0 +chr14 88153889 0 0 0.0 0 +chr14 88298626 0 0 0.0 0 +chr14 88336862 0 0 0.0 0 +chr14 88403735 0 0 0.0 0 +chr14 88404874 0 0 0.0 0 +chr14 88411241 0 0 0.0 0 +chr14 88452720 0 0 0.0 0 +chr14 88718207 0 0 0.0 0 +chr14 88789971 0 0 0.0 0 +chr14 88891045 0 0 0.0 0 +chr14 88902066 0 0 0.0 0 +chr14 89030679 0 0 0.0 0 +chr14 89036992 0 0 0.0 0 +chr14 89056626 0 0 0.0 0 +chr14 89104694 0 0 0.0 0 +chr14 89123410 0 0 0.0 0 +chr14 89175895 0 0 0.0 0 +chr14 89253685 0 0 0.0 0 +chr14 89330399 0 0 0.0 0 +chr14 89618138 0 0 0.0 0 +chr14 89705122 0 0 0.0 0 +chr14 89871798 0 0 0.0 0 +chr14 89974569 0 0 0.0 0 +chr14 89976390 0 0 0.0 0 +chr14 90010523 0 0 0.0 0 +chr14 90135738 0 0 0.0 0 +chr14 90302732 0 0 0.0 0 +chr14 90690095 0 0 0.0 0 +chr14 91083278 0 0 0.0 0 +chr14 91088113 0 0 0.0 0 +chr14 91197624 0 0 0.0 0 +chr14 91203584 0 0 0.0 0 +chr14 91218806 0 0 0.0 0 +chr14 91219467 0 0 0.0 0 +chr14 91224494 0 0 0.0 0 +chr14 91232057 0 0 0.0 0 +chr14 91248588 0 0 0.0 0 +chr14 91283860 0 0 0.0 0 +chr14 91296071 0 0 0.0 0 +chr14 91299517 0 0 0.0 0 +chr14 91300525 0 0 0.0 0 +chr14 91358306 0 0 0.0 0 +chr14 91430205 0 0 0.0 0 +chr14 91623281 0 0 0.0 0 +chr14 91819760 0 0 0.0 0 +chr14 91891247 0 0 0.0 0 +chr14 92066378 0 0 0.0 0 +chr14 92318727 0 0 0.0 0 +chr14 92368776 0 0 0.0 0 +chr14 92372445 0 0 0.0 0 +chr14 92387734 0 0 0.0 0 +chr14 92428416 0 0 0.0 0 +chr14 92511029 0 0 0.0 0 +chr14 92587675 0 0 0.0 0 +chr14 92616037 0 0 0.0 0 +chr14 92795926 0 0 0.0 0 +chr14 92861316 0 0 0.0 0 +chr14 92940196 0 0 0.0 0 +chr14 92946996 0 0 0.0 0 +chr14 93179717 0 0 0.0 0 +chr14 93183170 0 0 0.0 0 +chr14 93361484 1 60 0.6593 1 +chr14 93433532 1 4 0.0494 1 +chr14 93599846 0 0 0.0 0 +chr14 93653853 0 0 0.0 0 +chr14 93698747 0 0 0.0 0 +chr14 93724219 0 0 0.0 0 +chr14 93727618 0 0 0.0 0 +chr14 93841444 0 0 0.0 0 +chr14 93876418 0 0 0.0 0 +chr14 93893120 0 0 0.0 0 +chr14 93977388 0 0 0.0 0 +chr14 94094757 0 0 0.0 0 +chr14 94225728 0 0 0.0 0 +chr14 94289156 0 0 0.0 0 +chr14 94645990 0 0 0.0 0 +chr14 94729003 0 0 0.0 0 +chr14 94751113 0 0 0.0 0 +chr14 94825323 0 0 0.0 0 +chr14 94829160 0 0 0.0 0 +chr14 94837551 0 0 0.0 0 +chr14 94862222 0 0 0.0 0 +chr14 94914395 0 0 0.0 0 +chr14 94972353 0 0 0.0 0 +chr14 95072646 0 0 0.0 0 +chr14 95085567 0 0 0.0 0 +chr14 95101916 0 0 0.0 0 +chr14 95149590 0 0 0.0 0 +chr14 95185894 0 0 0.0 0 +chr14 95210994 0 0 0.0 0 +chr14 95234288 0 0 0.0 0 +chr14 95261773 0 0 0.0 0 +chr14 95370838 0 0 0.0 0 +chr14 95475279 0 0 0.0 0 +chr14 95512973 0 0 0.0 0 +chr14 95629075 0 0 0.0 0 +chr14 95862613 0 0 0.0 0 +chr14 95864836 0 0 0.0 0 +chr14 95877392 0 0 0.0 0 +chr14 95925066 0 0 0.0 0 +chr14 96059834 0 0 0.0 0 +chr14 96135186 0 0 0.0 0 +chr14 96220161 0 0 0.0 0 +chr14 96234255 0 0 0.0 0 +chr14 96246234 0 0 0.0 0 +chr14 96347612 0 0 0.0 0 +chr14 96437439 0 0 0.0 0 +chr14 96569886 0 0 0.0 0 +chr14 96617017 0 0 0.0 0 +chr14 96656856 0 0 0.0 0 +chr14 96684192 0 0 0.0 0 +chr14 96697165 0 0 0.0 0 +chr14 97185530 0 0 0.0 0 +chr14 97221168 0 0 0.0 0 +chr14 97278467 0 0 0.0 0 +chr14 97375903 0 0 0.0 0 +chr14 97469563 0 0 0.0 0 +chr14 97502114 0 0 0.0 0 +chr14 97530062 0 0 0.0 0 +chr14 97597316 0 0 0.0 0 +chr14 97635374 0 0 0.0 0 +chr14 97672727 0 0 0.0 0 +chr14 97769571 0 0 0.0 0 +chr14 97796698 0 0 0.0 0 +chr14 97826386 0 0 0.0 0 +chr14 97836657 0 0 0.0 0 +chr14 97878347 0 0 0.0 0 +chr14 97996923 0 0 0.0 0 +chr14 98063144 0 0 0.0 0 +chr14 98150356 0 0 0.0 0 +chr14 98258666 0 0 0.0 0 +chr14 98273686 0 0 0.0 0 +chr14 98295636 0 0 0.0 0 +chr14 98424797 0 0 0.0 0 +chr14 98449723 0 0 0.0 0 +chr14 98522102 0 0 0.0 0 +chr14 98633063 0 0 0.0 0 +chr14 98707564 0 0 0.0 0 +chr14 98721253 0 0 0.0 0 +chr14 98816659 0 0 0.0 0 +chr14 99016991 0 0 0.0 0 +chr14 99031653 0 0 0.0 0 +chr14 99134746 0 1 0.0132 0 +chr14 99140679 0 0 0.0 0 +chr14 99205810 0 0 0.0 0 +chr14 99317413 0 0 0.0 0 +chr14 99358739 0 0 0.0 0 +chr14 99565935 0 0 0.0 0 +chr14 99690383 0 0 0.0 0 +chr14 99755681 0 0 0.0 0 +chr14 99780158 0 0 0.0 0 +chr14 100295911 0 0 0.0 0 +chr14 100296180 0 0 0.0 0 +chr14 100384930 0 0 0.0 0 +chr14 100399836 0 0 0.0 0 +chr14 100417666 0 0 0.0 0 +chr14 100555774 0 0 0.0 0 +chr14 100602716 0 0 0.0 0 +chr14 100671768 0 0 0.0 0 +chr14 100681387 0 0 0.0 0 +chr14 100724976 0 0 0.0 0 +chr14 100765280 0 0 0.0 0 +chr14 100808938 0 0 0.0 0 +chr14 100899394 0 0 0.0 0 +chr14 101062500 0 1 0.0192 0 +chr14 101070261 0 0 0.0 0 +chr14 101179972 0 0 0.0 0 +chr14 101192231 0 0 0.0 0 +chr14 101301210 0 0 0.0 0 +chr14 101323965 0 0 0.0 0 +chr14 101331936 0 0 0.0 0 +chr14 101341264 0 0 0.0 0 +chr14 101362985 0 0 0.0 0 +chr14 101388467 0 0 0.0 0 +chr14 101446291 0 0 0.0 0 +chr14 101493462 0 0 0.0 0 +chr14 101580496 0 0 0.0 0 +chr14 101587050 0 0 0.0 0 +chr14 101636413 0 0 0.0 0 +chr14 101689452 0 0 0.0 0 +chr14 101799372 0 0 0.0 0 +chr14 101819321 0 0 0.0 0 +chr14 101934906 0 0 0.0 0 +chr14 101985800 0 0 0.0 0 +chr14 102169426 0 0 0.0 0 +chr14 102296490 0 0 0.0 0 +chr14 102298057 0 1 0.0189 0 +chr14 102411234 0 0 0.0 0 +chr14 102411852 0 0 0.0 0 +chr14 102538083 0 0 0.0 0 +chr14 102583785 0 0 0.0 0 +chr14 102717860 0 0 0.0 0 +chr14 102776755 1 30 0.4348 1 +chr14 102800454 0 0 0.0 0 +chr14 102933666 0 0 0.0 0 +chr14 103017887 0 0 0.0 0 +chr14 103091769 0 0 0.0 0 +chr14 103093792 0 0 0.0 0 +chr14 103234567 0 0 0.0 0 +chr14 103373081 0 0 0.0 0 +chr14 103500883 0 0 0.0 0 +chr14 103523128 0 0 0.0 0 +chr14 103554405 0 0 0.0 0 +chr14 103587416 0 0 0.0 0 +chr14 103651773 0 0 0.0 0 +chr14 103663678 0 0 0.0 0 +chr14 103676159 0 0 0.0 0 +chr14 103723135 0 0 0.0 0 +chr14 103759382 0 0 0.0 0 +chr14 103858708 0 0 0.0 0 +chr14 103972602 0 0 0.0 0 +chr14 104054703 0 0 0.0 0 +chr14 104160035 0 0 0.0 0 +chr14 104182753 0 0 0.0 0 +chr14 104201405 0 0 0.0 0 +chr14 104201528 0 0 0.0 0 +chr14 104209745 0 0 0.0 0 +chr14 104212776 0 0 0.0 0 +chr14 104223188 0 0 0.0 0 +chr14 104352793 0 1 0.013 0 +chr14 104423725 0 0 0.0 0 +chr14 104434233 0 1 0.0175 0 +chr14 104633253 0 0 0.0 0 +chr14 104692674 0 0 0.0 0 +chr14 104703654 0 0 0.0 0 +chr14 104708656 0 0 0.0 0 +chr14 104790444 0 0 0.0 0 +chr14 104808691 0 0 0.0 0 +chr14 104967310 0 0 0.0 0 +chr14 105032991 0 0 0.0 0 +chr14 105043662 0 0 0.0 0 +chr14 105084285 0 1 0.0139 0 +chr14 105118437 0 0 0.0 0 +chr14 105159265 0 0 0.0 0 +chr14 105214276 0 0 0.0 0 +chr14 105228787 0 0 0.0 0 +chr14 105264238 0 0 0.0 0 +chr14 105305985 0 0 0.0 0 +chr14 105327488 0 0 0.0 0 +chr14 105352453 0 0 0.0 0 +chr14 105412381 0 0 0.0 0 +chr14 105466911 0 0 0.0 0 +chr14 105527919 0 0 0.0 0 +chr14 105551112 0 0 0.0 0 +chr14 105599151 0 0 0.0 0 +chr14 105607192 0 0 0.0 0 +chr14 105619400 0 0 0.0 0 +chr14 105638646 0 0 0.0 0 +chr14 105662308 0 0 0.0 0 +chr14 105720879 0 0 0.0 0 +chr14 105735433 0 0 0.0 0 +chr14 105751602 0 0 0.0 0 +chr14 105763590 0 0 0.0 0 +chr14 105783202 0 0 0.0 0 +chr14 105811356 0 0 0.0 0 +chr14 105918502 0 0 0.0 0 +chr14 105920907 0 0 0.0 0 +chr14 106038008 0 0 0.0 0 +chr14 106158700 0 0 0.0 0 +chr14 106184076 0 0 0.0 0 +chr14 106239220 0 0 0.0 0 +chr14 106650902 0 0 0.0 0 +chr14 106734009 0 0 0.0 0 +chr14 106806262 0 0 0.0 0 +chr14 106871696 0 0 0.0 0 +chr14_GL000194v1_random 11224 0 0 0.0 0 +chr14_GL000194v1_random 14289 0 0 0.0 0 +chr14_GL000194v1_random 22972 0 0 0.0 0 +chr14_KI270722v1_random 81667 0 0 0.0 0 +chr14_KI270725v1_random 21991 0 0 0.0 0 +chr14_KI270725v1_random 59892 0 0 0.0 0 +chr14_KI270846v1_alt 18110 0 0 0.0 0 +chr14_KI270846v1_alt 74960 0 0 0.0 0 +chr14_KI270846v1_alt 87168 0 0 0.0 0 +chr14_KI270846v1_alt 106414 0 0 0.0 0 +chr14_KI270846v1_alt 130076 0 0 0.0 0 +chr14_KI270846v1_alt 203201 0 0 0.0 0 +chr14_KI270846v1_alt 219370 0 0 0.0 0 +chr14_KI270846v1_alt 231358 0 0 0.0 0 +chr14_KI270846v1_alt 250970 0 0 0.0 0 +chr14_KI270846v1_alt 279125 0 0 0.0 0 +chr14_KI270846v1_alt 386271 0 0 0.0 0 +chr14_KI270846v1_alt 388676 0 0 0.0 0 +chr14_KI270846v1_alt 626469 0 0 0.0 0 +chr14_KI270846v1_alt 651844 0 0 0.0 0 +chr14_KI270846v1_alt 1225687 0 0 0.0 0 +chr14_KI270847v1_alt 54758 0 0 0.0 0 +chr14_KI270847v1_alt 61557 0 0 0.0 0 +chr14_KI270847v1_alt 294278 0 0 0.0 0 +chr14_KI270847v1_alt 297732 0 0 0.0 0 +chr14_KI270847v1_alt 548093 0 0 0.0 0 +chr14_KI270847v1_alt 714408 0 0 0.0 0 +chr14_KI270847v1_alt 768414 0 0 0.0 0 +chr14_KI270847v1_alt 813309 0 0 0.0 0 +chr14_KI270847v1_alt 956005 0 0 0.0 0 +chr14_KI270847v1_alt 990980 0 0 0.0 0 +chr14_KI270847v1_alt 1209319 0 0 0.0 0 +chr14_KI270847v1_alt 1340290 0 0 0.0 0 +chr14_KI270847v1_alt 1403717 0 0 0.0 0 +chr15 17027602 0 0 0.0 0 +chr15 17034743 0 0 0.0 0 +chr15 17081558 0 0 0.0 0 +chr15 17082708 1 5 0.1064 1 +chr15 17083413 1 11 0.1549 1 +chr15 19798525 0 0 0.0 0 +chr15 19804327 0 0 0.0 0 +chr15 19971982 0 0 0.0 0 +chr15 20011417 0 0 0.0 0 +chr15 20119636 0 0 0.0 0 +chr15 20124754 0 0 0.0 0 +chr15 20165006 0 0 0.0 0 +chr15 20191781 0 0 0.0 0 +chr15 20241328 0 0 0.0 0 +chr15 20328800 0 0 0.0 0 +chr15 20416763 0 0 0.0 0 +chr15 20620512 0 0 0.0 0 +chr15 20629382 0 0 0.0 0 +chr15 20674750 0 0 0.0 0 +chr15 20763172 0 0 0.0 0 +chr15 20770436 0 0 0.0 0 +chr15 21018064 0 0 0.0 0 +chr15 21126174 0 0 0.0 0 +chr15 21131290 0 0 0.0 0 +chr15 21171540 0 0 0.0 0 +chr15 21243717 0 0 0.0 0 +chr15 21332245 0 0 0.0 0 +chr15 21339523 0 0 0.0 0 +chr15 22269337 0 0 0.0 0 +chr15 22371006 0 0 0.0 0 +chr15 22600710 0 0 0.0 0 +chr15 22816000 0 0 0.0 0 +chr15 22895840 0 0 0.0 0 +chr15 22942522 0 0 0.0 0 +chr15 23014689 0 0 0.0 0 +chr15 23420770 0 0 0.0 0 +chr15 23495678 0 0 0.0 0 +chr15 23636556 0 0 0.0 0 +chr15 23709279 0 0 0.0 0 +chr15 23800473 0 0 0.0 0 +chr15 23874228 0 0 0.0 0 +chr15 23929981 0 0 0.0 0 +chr15 23930339 0 0 0.0 0 +chr15 23931440 0 0 0.0 0 +chr15 23975370 0 0 0.0 0 +chr15 24004895 0 0 0.0 0 +chr15 24013470 0 0 0.0 0 +chr15 24139538 0 0 0.0 0 +chr15 24163661 0 0 0.0 0 +chr15 24167698 0 0 0.0 0 +chr15 24420897 0 1 0.0149 0 +chr15 24530500 0 0 0.0 0 +chr15 24555866 0 0 0.0 0 +chr15 24709612 0 0 0.0 0 +chr15 24768368 0 0 0.0 0 +chr15 24804144 0 0 0.0 0 +chr15 24949541 0 0 0.0 0 +chr15 25079296 0 0 0.0 0 +chr15 25188965 0 0 0.0 0 +chr15 25243289 0 0 0.0 0 +chr15 25389645 0 0 0.0 0 +chr15 25630782 0 0 0.0 0 +chr15 25650761 0 0 0.0 0 +chr15 25679512 0 0 0.0 0 +chr15 25702289 0 0 0.0 0 +chr15 25809900 0 0 0.0 0 +chr15 25837522 0 0 0.0 0 +chr15 25875924 0 0 0.0 0 +chr15 25986585 0 0 0.0 0 +chr15 26110825 0 0 0.0 0 +chr15 26164124 0 0 0.0 0 +chr15 26495931 0 0 0.0 0 +chr15 26550635 0 0 0.0 0 +chr15 26622233 0 0 0.0 0 +chr15 26913507 0 0 0.0 0 +chr15 26976203 0 0 0.0 0 +chr15 27018584 0 0 0.0 0 +chr15 27036375 0 0 0.0 0 +chr15 27223812 0 0 0.0 0 +chr15 27255317 0 0 0.0 0 +chr15 27418975 0 0 0.0 0 +chr15 27598389 0 0 0.0 0 +chr15 27628234 0 0 0.0 0 +chr15 27631889 0 0 0.0 0 +chr15 27748261 0 0 0.0 0 +chr15 28015231 0 0 0.0 0 +chr15 28695125 0 0 0.0 0 +chr15 28851029 0 0 0.0 0 +chr15 28870316 0 0 0.0 0 +chr15 28921706 0 0 0.0 0 +chr15 28977510 0 1 0.0167 0 +chr15 29002846 0 0 0.0 0 +chr15 29122573 0 0 0.0 0 +chr15 29200064 0 0 0.0 0 +chr15 29485308 0 0 0.0 0 +chr15 29681462 0 0 0.0 0 +chr15 29755403 0 0 0.0 0 +chr15 29767443 0 0 0.0 0 +chr15 30000497 0 0 0.0 0 +chr15 30022757 0 0 0.0 0 +chr15 30178178 0 0 0.0 0 +chr15 30324452 0 0 0.0 0 +chr15 30523311 0 0 0.0 0 +chr15 30755562 0 0 0.0 0 +chr15 30802337 0 0 0.0 0 +chr15 30895105 0 0 0.0 0 +chr15 30935888 0 0 0.0 0 +chr15 31075521 0 0 0.0 0 +chr15 31089354 0 0 0.0 0 +chr15 31105840 0 0 0.0 0 +chr15 31353226 0 0 0.0 0 +chr15 31355998 0 0 0.0 0 +chr15 31389931 0 0 0.0 0 +chr15 31397663 0 0 0.0 0 +chr15 31412904 0 0 0.0 0 +chr15 31650186 0 0 0.0 0 +chr15 31657999 0 0 0.0 0 +chr15 31674303 0 0 0.0 0 +chr15 31759176 0 0 0.0 0 +chr15 31806985 0 0 0.0 0 +chr15 32021294 0 0 0.0 0 +chr15 32206101 0 0 0.0 0 +chr15 32360490 0 0 0.0 0 +chr15 32484356 0 0 0.0 0 +chr15 32690494 0 0 0.0 0 +chr15 32903920 0 0 0.0 0 +chr15 33033124 1 36 0.4932 1 +chr15 33232623 1 35 0.9211 1 +chr15 33344072 0 0 0.0 0 +chr15 33526752 0 0 0.0 0 +chr15 33542225 0 0 0.0 0 +chr15 33640235 0 0 0.0 0 +chr15 33673979 0 0 0.0 0 +chr15 33798425 0 0 0.0 0 +chr15 33857142 0 0 0.0 0 +chr15 33870140 0 0 0.0 0 +chr15 34048219 0 0 0.0 0 +chr15 34048483 0 0 0.0 0 +chr15 34292756 0 0 0.0 0 +chr15 34338227 0 0 0.0 0 +chr15 34364076 0 0 0.0 0 +chr15 34468940 1 29 0.4754 1 +chr15 34652767 0 0 0.0 0 +chr15 34738701 0 0 0.0 0 +chr15 35135399 0 0 0.0 0 +chr15 35268377 0 0 0.0 0 +chr15 35393131 0 0 0.0 0 +chr15 35438425 0 0 0.0 0 +chr15 35595401 0 0 0.0 0 +chr15 35942860 0 1 0.0149 0 +chr15 35979933 0 0 0.0 0 +chr15 36002148 0 0 0.0 0 +chr15 36207404 0 0 0.0 0 +chr15 36210771 0 0 0.0 0 +chr15 36325486 0 0 0.0 0 +chr15 36502997 0 0 0.0 0 +chr15 36528348 0 0 0.0 0 +chr15 36743490 0 0 0.0 0 +chr15 36754748 0 0 0.0 0 +chr15 36950152 0 0 0.0 0 +chr15 37248469 0 0 0.0 0 +chr15 37329082 0 0 0.0 0 +chr15 37629825 0 0 0.0 0 +chr15 37652155 0 0 0.0 0 +chr15 37679595 0 0 0.0 0 +chr15 37812552 0 0 0.0 0 +chr15 37902748 0 0 0.0 0 +chr15 37981479 0 0 0.0 0 +chr15 38115221 0 0 0.0 0 +chr15 38141976 0 0 0.0 0 +chr15 38574998 0 0 0.0 0 +chr15 38606781 0 0 0.0 0 +chr15 38690207 0 0 0.0 0 +chr15 38712662 1 26 0.4 1 +chr15 38747607 0 0 0.0 0 +chr15 38778903 0 0 0.0 0 +chr15 38803342 0 0 0.0 0 +chr15 38806115 0 0 0.0 0 +chr15 38860160 0 0 0.0 0 +chr15 39035465 0 0 0.0 0 +chr15 39113090 0 0 0.0 0 +chr15 39176877 0 0 0.0 0 +chr15 39299662 0 0 0.0 0 +chr15 39302733 0 0 0.0 0 +chr15 39404008 0 0 0.0 0 +chr15 39429072 0 0 0.0 0 +chr15 39534703 0 0 0.0 0 +chr15 39588118 0 0 0.0 0 +chr15 39786394 0 0 0.0 0 +chr15 39811257 0 0 0.0 0 +chr15 39845992 0 0 0.0 0 +chr15 39892189 0 0 0.0 0 +chr15 39978954 0 0 0.0 0 +chr15 40016466 0 0 0.0 0 +chr15 40087171 0 0 0.0 0 +chr15 40107896 0 1 0.0182 0 +chr15 40138437 0 0 0.0 0 +chr15 40302582 0 0 0.0 0 +chr15 40387582 0 1 0.0294 0 +chr15 40432008 0 0 0.0 0 +chr15 40453819 0 0 0.0 0 +chr15 40467275 0 0 0.0 0 +chr15 40470195 0 0 0.0 0 +chr15 40471776 0 0 0.0 0 +chr15 40549571 0 0 0.0 0 +chr15 40567318 0 0 0.0 0 +chr15 40664591 0 0 0.0 0 +chr15 40770453 0 0 0.0 0 +chr15 40814574 0 0 0.0 0 +chr15 40826153 0 0 0.0 0 +chr15 40956932 0 0 0.0 0 +chr15 40963217 0 0 0.0 0 +chr15 41042856 0 0 0.0 0 +chr15 41269838 0 0 0.0 0 +chr15 41411513 0 0 0.0 0 +chr15 41442100 0 0 0.0 0 +chr15 41499270 0 1 0.0233 0 +chr15 41564751 0 0 0.0 0 +chr15 41740246 0 0 0.0 0 +chr15 41843555 0 1 0.0175 0 +chr15 41845361 0 0 0.0 0 +chr15 41847656 0 0 0.0 0 +chr15 41855237 0 0 0.0 0 +chr15 41969628 0 0 0.0 0 +chr15 41982549 0 0 0.0 0 +chr15 42156691 0 0 0.0 0 +chr15 42163329 0 0 0.0 0 +chr15 42301646 0 0 0.0 0 +chr15 42576392 0 0 0.0 0 +chr15 42638310 0 0 0.0 0 +chr15 42640939 0 0 0.0 0 +chr15 42722187 0 0 0.0 0 +chr15 42874138 0 0 0.0 0 +chr15 42928214 0 0 0.0 0 +chr15 42950341 0 0 0.0 0 +chr15 43103141 0 0 0.0 0 +chr15 43163028 0 0 0.0 0 +chr15 43275097 0 0 0.0 0 +chr15 43483892 0 0 0.0 0 +chr15 43500926 0 0 0.0 0 +chr15 43521716 0 0 0.0 0 +chr15 43556793 0 0 0.0 0 +chr15 43764858 0 0 0.0 0 +chr15 43789897 0 0 0.0 0 +chr15 43978813 0 0 0.0 0 +chr15 44319110 0 0 0.0 0 +chr15 44354766 0 0 0.0 0 +chr15 44572566 0 0 0.0 0 +chr15 44597615 0 0 0.0 0 +chr15 44711600 0 0 0.0 0 +chr15 44715512 0 0 0.0 0 +chr15 44816060 0 0 0.0 0 +chr15 44895831 0 0 0.0 0 +chr15 45027854 0 0 0.0 0 +chr15 45140984 0 0 0.0 0 +chr15 45160235 0 0 0.0 0 +chr15 45262553 0 0 0.0 0 +chr15 45369373 0 0 0.0 0 +chr15 45919541 0 0 0.0 0 +chr15 45921645 0 0 0.0 0 +chr15 45955188 0 0 0.0 0 +chr15 46103067 0 0 0.0 0 +chr15 46133022 0 0 0.0 0 +chr15 46208802 0 0 0.0 0 +chr15 46228215 0 0 0.0 0 +chr15 46370765 0 0 0.0 0 +chr15 46431010 0 0 0.0 0 +chr15 46527976 0 0 0.0 0 +chr15 46533096 0 0 0.0 0 +chr15 46681072 0 0 0.0 0 +chr15 46704072 0 0 0.0 0 +chr15 46808974 0 0 0.0 0 +chr15 46843821 0 0 0.0 0 +chr15 46963675 0 0 0.0 0 +chr15 47236981 0 0 0.0 0 +chr15 47270334 0 0 0.0 0 +chr15 47275062 0 0 0.0 0 +chr15 47328247 0 0 0.0 0 +chr15 47397238 0 0 0.0 0 +chr15 47470522 0 0 0.0 0 +chr15 47588813 0 0 0.0 0 +chr15 47603944 0 0 0.0 0 +chr15 47687699 0 0 0.0 0 +chr15 47731515 0 0 0.0 0 +chr15 47736946 0 0 0.0 0 +chr15 47785436 0 0 0.0 0 +chr15 47796975 0 0 0.0 0 +chr15 48091819 0 0 0.0 0 +chr15 48208574 0 0 0.0 0 +chr15 48261447 0 0 0.0 0 +chr15 48387016 0 0 0.0 0 +chr15 48455055 0 0 0.0 0 +chr15 48466100 0 0 0.0 0 +chr15 48523046 0 0 0.0 0 +chr15 48524467 0 0 0.0 0 +chr15 48526887 0 0 0.0 0 +chr15 48530495 0 0 0.0 0 +chr15 48588898 0 0 0.0 0 +chr15 48633813 0 0 0.0 0 +chr15 48752433 0 0 0.0 0 +chr15 48884066 0 0 0.0 0 +chr15 49133249 0 0 0.0 0 +chr15 49141191 0 0 0.0 0 +chr15 49201212 0 0 0.0 0 +chr15 49422093 0 1 0.037 0 +chr15 49721748 0 0 0.0 0 +chr15 49742247 0 0 0.0 0 +chr15 49966413 0 0 0.0 0 +chr15 49981121 0 0 0.0 0 +chr15 50026038 0 0 0.0 0 +chr15 50508288 0 0 0.0 0 +chr15 50533226 0 0 0.0 0 +chr15 50658460 0 0 0.0 0 +chr15 50707413 0 0 0.0 0 +chr15 50746828 0 0 0.0 0 +chr15 50884824 0 0 0.0 0 +chr15 50987723 0 0 0.0 0 +chr15 51098449 0 0 0.0 0 +chr15 51136970 0 0 0.0 0 +chr15 51211465 0 0 0.0 0 +chr15 51225074 0 0 0.0 0 +chr15 51317196 0 0 0.0 0 +chr15 51321071 0 0 0.0 0 +chr15 51383508 0 0 0.0 0 +chr15 51448978 0 0 0.0 0 +chr15 51473719 0 0 0.0 0 +chr15 51502158 0 0 0.0 0 +chr15 51691248 0 0 0.0 0 +chr15 51693062 0 0 0.0 0 +chr15 51711435 0 0 0.0 0 +chr15 51753585 0 0 0.0 0 +chr15 52150342 0 0 0.0 0 +chr15 52282014 0 0 0.0 0 +chr15 52336673 0 0 0.0 0 +chr15 52436882 0 0 0.0 0 +chr15 52552620 1 7 0.5385 1 +chr15 52623133 1 27 0.3857 1 +chr15 52673128 0 0 0.0 0 +chr15 52695407 0 0 0.0 0 +chr15 52709773 0 0 0.0 0 +chr15 52937784 0 0 0.0 0 +chr15 53076750 0 0 0.0 0 +chr15 53195777 0 0 0.0 0 +chr15 53442438 0 0 0.0 0 +chr15 53462825 0 1 0.0141 0 +chr15 53527182 0 0 0.0 0 +chr15 53749019 0 0 0.0 0 +chr15 53845083 0 0 0.0 0 +chr15 53845610 0 1 0.0208 0 +chr15 53963404 0 0 0.0 0 +chr15 54373396 0 0 0.0 0 +chr15 54386712 0 0 0.0 0 +chr15 54664723 0 0 0.0 0 +chr15 54720958 0 0 0.0 0 +chr15 54727591 0 0 0.0 0 +chr15 54801699 0 0 0.0 0 +chr15 55044104 0 0 0.0 0 +chr15 55191452 1 3 0.05 1 +chr15 55203727 0 0 0.0 0 +chr15 55254663 0 0 0.0 0 +chr15 55309608 0 0 0.0 0 +chr15 55375266 0 0 0.0 0 +chr15 55533921 0 0 0.0 0 +chr15 55572930 0 0 0.0 0 +chr15 55599713 0 0 0.0 0 +chr15 55860645 0 0 0.0 0 +chr15 56005822 1 17 0.4048 1 +chr15 56126080 0 0 0.0 0 +chr15 56217333 0 0 0.0 0 +chr15 56287188 0 0 0.0 0 +chr15 57148275 0 0 0.0 0 +chr15 57271331 0 0 0.0 0 +chr15 57351599 0 0 0.0 0 +chr15 57439211 0 0 0.0 0 +chr15 57501844 0 0 0.0 0 +chr15 57503651 0 0 0.0 0 +chr15 57549355 0 0 0.0 0 +chr15 57665458 0 0 0.0 0 +chr15 57676175 0 0 0.0 0 +chr15 57761370 0 0 0.0 0 +chr15 57819894 0 0 0.0 0 +chr15 57855541 0 0 0.0 0 +chr15 57857583 0 0 0.0 0 +chr15 57879895 0 0 0.0 0 +chr15 58097679 0 0 0.0 0 +chr15 58170184 0 0 0.0 0 +chr15 58449128 0 0 0.0 0 +chr15 58584405 0 0 0.0 0 +chr15 58588254 0 0 0.0 0 +chr15 58741738 0 0 0.0 0 +chr15 58784896 0 0 0.0 0 +chr15 58936132 0 0 0.0 0 +chr15 59010663 0 0 0.0 0 +chr15 59154906 0 0 0.0 0 +chr15 59160538 0 0 0.0 0 +chr15 59227099 0 0 0.0 0 +chr15 59333916 0 0 0.0 0 +chr15 59390499 0 0 0.0 0 +chr15 59393200 0 0 0.0 0 +chr15 59431060 0 0 0.0 0 +chr15 59434730 0 0 0.0 0 +chr15 59621246 0 0 0.0 0 +chr15 59871840 0 0 0.0 0 +chr15 59886140 0 0 0.0 0 +chr15 59892259 0 0 0.0 0 +chr15 59919691 0 0 0.0 0 +chr15 60098537 0 0 0.0 0 +chr15 60194484 0 0 0.0 0 +chr15 60229050 0 0 0.0 0 +chr15 60233053 0 0 0.0 0 +chr15 60427678 0 0 0.0 0 +chr15 60512427 0 0 0.0 0 +chr15 60525865 0 0 0.0 0 +chr15 60553110 0 0 0.0 0 +chr15 60770575 0 0 0.0 0 +chr15 60783332 0 0 0.0 0 +chr15 60825228 0 0 0.0 0 +chr15 60875903 0 0 0.0 0 +chr15 61102624 0 0 0.0 0 +chr15 61201251 0 0 0.0 0 +chr15 61405563 0 0 0.0 0 +chr15 61415044 0 0 0.0 0 +chr15 61576746 0 0 0.0 0 +chr15 61777433 0 0 0.0 0 +chr15 61780167 0 0 0.0 0 +chr15 61821728 0 0 0.0 0 +chr15 61965271 0 0 0.0 0 +chr15 62111354 0 0 0.0 0 +chr15 62158804 0 0 0.0 0 +chr15 62249734 0 0 0.0 0 +chr15 62411109 0 0 0.0 0 +chr15 62436596 0 0 0.0 0 +chr15 62550210 0 0 0.0 0 +chr15 62607602 0 0 0.0 0 +chr15 62625046 0 0 0.0 0 +chr15 62625202 0 0 0.0 0 +chr15 62838675 0 0 0.0 0 +chr15 62850712 0 0 0.0 0 +chr15 62897234 0 0 0.0 0 +chr15 62978145 0 0 0.0 0 +chr15 63091890 0 0 0.0 0 +chr15 63236525 0 0 0.0 0 +chr15 63385486 0 0 0.0 0 +chr15 63417459 0 1 0.025 0 +chr15 63420236 0 0 0.0 0 +chr15 63435377 0 0 0.0 0 +chr15 63694305 0 0 0.0 0 +chr15 63816934 0 0 0.0 0 +chr15 63868448 0 0 0.0 0 +chr15 64044613 0 0 0.0 0 +chr15 64375539 0 0 0.0 0 +chr15 64562143 0 0 0.0 0 +chr15 64730303 0 0 0.0 0 +chr15 64838824 0 0 0.0 0 +chr15 64897525 0 0 0.0 0 +chr15 65196326 0 0 0.0 0 +chr15 65426787 0 0 0.0 0 +chr15 65497017 0 0 0.0 0 +chr15 65553605 0 0 0.0 0 +chr15 65628086 0 0 0.0 0 +chr15 65791588 0 0 0.0 0 +chr15 65815169 0 0 0.0 0 +chr15 65851423 0 0 0.0 0 +chr15 65943933 0 0 0.0 0 +chr15 65961803 0 0 0.0 0 +chr15 65995539 0 0 0.0 0 +chr15 65996928 0 0 0.0 0 +chr15 66013155 0 0 0.0 0 +chr15 66310806 0 0 0.0 0 +chr15 66398743 0 0 0.0 0 +chr15 66517640 0 0 0.0 0 +chr15 66643838 0 0 0.0 0 +chr15 66685154 0 0 0.0 0 +chr15 66716618 0 0 0.0 0 +chr15 66717590 0 0 0.0 0 +chr15 66783250 0 0 0.0 0 +chr15 66968333 0 0 0.0 0 +chr15 66975036 0 0 0.0 0 +chr15 66996676 0 0 0.0 0 +chr15 67044289 0 0 0.0 0 +chr15 67146481 0 0 0.0 0 +chr15 67242513 0 0 0.0 0 +chr15 67289563 0 0 0.0 0 +chr15 67453508 0 0 0.0 0 +chr15 67485479 0 0 0.0 0 +chr15 67579005 0 0 0.0 0 +chr15 67693889 0 0 0.0 0 +chr15 67804195 0 0 0.0 0 +chr15 68193020 0 0 0.0 0 +chr15 68252598 0 0 0.0 0 +chr15 68317579 0 0 0.0 0 +chr15 68340849 0 0 0.0 0 +chr15 68342421 0 0 0.0 0 +chr15 68491361 0 0 0.0 0 +chr15 68510815 0 0 0.0 0 +chr15 68512051 0 0 0.0 0 +chr15 68628881 0 0 0.0 0 +chr15 68641769 0 0 0.0 0 +chr15 68645398 0 0 0.0 0 +chr15 68745427 0 0 0.0 0 +chr15 68755547 0 0 0.0 0 +chr15 68781429 0 0 0.0 0 +chr15 68812311 0 0 0.0 0 +chr15 68865405 0 0 0.0 0 +chr15 68879559 0 0 0.0 0 +chr15 69032231 0 0 0.0 0 +chr15 69106390 0 0 0.0 0 +chr15 69349283 0 0 0.0 0 +chr15 69393674 0 1 0.0256 0 +chr15 69530878 0 0 0.0 0 +chr15 69551303 0 0 0.0 0 +chr15 69747529 0 0 0.0 0 +chr15 69757720 0 0 0.0 0 +chr15 69821757 0 0 0.0 0 +chr15 69864841 0 0 0.0 0 +chr15 69922226 0 0 0.0 0 +chr15 69952457 0 0 0.0 0 +chr15 70002006 0 1 0.0185 0 +chr15 70104156 0 0 0.0 0 +chr15 70186944 0 0 0.0 0 +chr15 70246040 0 0 0.0 0 +chr15 70247858 0 0 0.0 0 +chr15 70254174 0 0 0.0 0 +chr15 70318732 0 0 0.0 0 +chr15 70459865 0 0 0.0 0 +chr15 70491572 0 0 0.0 0 +chr15 70492286 0 0 0.0 0 +chr15 70506338 0 0 0.0 0 +chr15 70703916 0 0 0.0 0 +chr15 70757927 0 0 0.0 0 +chr15 70791319 0 0 0.0 0 +chr15 70825521 0 0 0.0 0 +chr15 71099587 0 0 0.0 0 +chr15 71581082 0 0 0.0 0 +chr15 71594586 0 0 0.0 0 +chr15 71732101 0 0 0.0 0 +chr15 71739469 0 0 0.0 0 +chr15 72036403 0 0 0.0 0 +chr15 72078580 0 0 0.0 0 +chr15 72164208 0 0 0.0 0 +chr15 72175986 0 0 0.0 0 +chr15 72272861 0 0 0.0 0 +chr15 72281106 0 0 0.0 0 +chr15 72354517 0 0 0.0 0 +chr15 72387788 0 0 0.0 0 +chr15 72406007 0 0 0.0 0 +chr15 72752702 0 0 0.0 0 +chr15 72824571 0 0 0.0 0 +chr15 72899127 0 0 0.0 0 +chr15 72961318 0 0 0.0 0 +chr15 72962602 0 0 0.0 0 +chr15 73155332 0 0 0.0 0 +chr15 73337855 0 0 0.0 0 +chr15 73370503 0 1 0.0154 0 +chr15 73411081 0 1 0.0345 0 +chr15 73546248 0 0 0.0 0 +chr15 73584572 0 0 0.0 0 +chr15 73739786 0 0 0.0 0 +chr15 73799811 0 0 0.0 0 +chr15 73929643 0 0 0.0 0 +chr15 74148611 0 0 0.0 0 +chr15 74283420 0 0 0.0 0 +chr15 74305575 0 0 0.0 0 +chr15 74388184 0 0 0.0 0 +chr15 74613508 0 0 0.0 0 +chr15 74632612 0 0 0.0 0 +chr15 74690704 0 0 0.0 0 +chr15 74700000 0 0 0.0 0 +chr15 74711278 0 1 0.0233 0 +chr15 74887131 0 1 0.027 0 +chr15 74961307 0 0 0.0 0 +chr15 74994111 0 0 0.0 0 +chr15 75018659 0 1 0.0238 0 +chr15 75022519 0 0 0.0 0 +chr15 75061046 0 0 0.0 0 +chr15 75142964 0 0 0.0 0 +chr15 75203210 0 0 0.0 0 +chr15 75234660 0 0 0.0 0 +chr15 75555284 0 0 0.0 0 +chr15 75619399 0 0 0.0 0 +chr15 75660519 0 0 0.0 0 +chr15 75696927 0 0 0.0 0 +chr15 75745021 0 1 0.0238 0 +chr15 75866257 0 0 0.0 0 +chr15 75883083 0 0 0.0 0 +chr15 75945341 0 0 0.0 0 +chr15 76019202 0 0 0.0 0 +chr15 76153557 0 0 0.0 0 +chr15 76383789 0 0 0.0 0 +chr15 76583758 0 0 0.0 0 +chr15 76608300 0 0 0.0 0 +chr15 76625039 0 0 0.0 0 +chr15 76635532 0 0 0.0 0 +chr15 76761111 0 0 0.0 0 +chr15 76819467 0 0 0.0 0 +chr15 76829818 0 0 0.0 0 +chr15 76888028 0 0 0.0 0 +chr15 76975946 0 0 0.0 0 +chr15 76990553 0 0 0.0 0 +chr15 77096783 0 0 0.0 0 +chr15 77112365 0 0 0.0 0 +chr15 77286303 0 0 0.0 0 +chr15 77348151 0 0 0.0 0 +chr15 77464231 0 0 0.0 0 +chr15 77473881 0 0 0.0 0 +chr15 77573446 0 0 0.0 0 +chr15 77698976 0 0 0.0 0 +chr15 77890355 0 0 0.0 0 +chr15 77906264 0 0 0.0 0 +chr15 77912051 0 0 0.0 0 +chr15 77995344 0 0 0.0 0 +chr15 78082240 0 0 0.0 0 +chr15 78209393 0 0 0.0 0 +chr15 78238226 1 23 0.5227 1 +chr15 78309643 0 0 0.0 0 +chr15 78499834 0 0 0.0 0 +chr15 78601450 0 0 0.0 0 +chr15 78618525 0 0 0.0 0 +chr15 78619600 0 0 0.0 0 +chr15 78622192 0 0 0.0 0 +chr15 78774092 0 0 0.0 0 +chr15 78790979 0 0 0.0 0 +chr15 78791230 0 0 0.0 0 +chr15 78850480 0 0 0.0 0 +chr15 78979440 0 1 0.0147 0 +chr15 79042388 0 0 0.0 0 +chr15 79049437 0 0 0.0 0 +chr15 79158208 0 0 0.0 0 +chr15 79206232 0 1 0.0185 0 +chr15 79265521 0 0 0.0 0 +chr15 79417230 0 0 0.0 0 +chr15 79482234 0 0 0.0 0 +chr15 79518662 0 0 0.0 0 +chr15 79636057 0 0 0.0 0 +chr15 79672717 0 0 0.0 0 +chr15 79724766 0 0 0.0 0 +chr15 79732254 0 0 0.0 0 +chr15 79754560 0 0 0.0 0 +chr15 79780528 0 0 0.0 0 +chr15 79889760 0 0 0.0 0 +chr15 79923637 0 0 0.0 0 +chr15 80342912 0 0 0.0 0 +chr15 80415123 0 0 0.0 0 +chr15 80518915 0 0 0.0 0 +chr15 80615904 0 0 0.0 0 +chr15 80847540 0 0 0.0 0 +chr15 80895253 0 0 0.0 0 +chr15 81157370 0 0 0.0 0 +chr15 81268528 0 0 0.0 0 +chr15 81279526 0 0 0.0 0 +chr15 81281610 0 0 0.0 0 +chr15 81300168 0 0 0.0 0 +chr15 81359573 0 2 0.0294 0 +chr15 81591391 1 9 0.1607 1 +chr15 81777062 0 0 0.0 0 +chr15 81857760 0 0 0.0 0 +chr15 81878710 0 1 0.0323 0 +chr15 82032571 0 0 0.0 0 +chr15 82354747 0 0 0.0 0 +chr15 82514294 0 0 0.0 0 +chr15 82546748 0 0 0.0 0 +chr15 82572941 0 0 0.0 0 +chr15 82588640 0 0 0.0 0 +chr15 82662060 0 0 0.0 0 +chr15 82668072 0 0 0.0 0 +chr15 82726676 0 0 0.0 0 +chr15 82786357 0 0 0.0 0 +chr15 82798095 0 0 0.0 0 +chr15 83009600 0 0 0.0 0 +chr15 83094244 0 0 0.0 0 +chr15 83327824 0 0 0.0 0 +chr15 83529360 0 0 0.0 0 +chr15 83698671 0 0 0.0 0 +chr15 83797798 0 0 0.0 0 +chr15 83820798 0 0 0.0 0 +chr15 83918905 0 0 0.0 0 +chr15 83961660 0 0 0.0 0 +chr15 83963299 0 0 0.0 0 +chr15 83975767 0 0 0.0 0 +chr15 84105463 0 0 0.0 0 +chr15 84156495 0 0 0.0 0 +chr15 84157262 0 0 0.0 0 +chr15 84230480 0 0 0.0 0 +chr15 84345051 0 0 0.0 0 +chr15 84443103 0 0 0.0 0 +chr15 84552247 0 0 0.0 0 +chr15 84681993 0 0 0.0 0 +chr15 84706955 0 0 0.0 0 +chr15 84749216 0 0 0.0 0 +chr15 84772284 0 0 0.0 0 +chr15 84891315 0 0 0.0 0 +chr15 84922035 0 0 0.0 0 +chr15 84998199 0 0 0.0 0 +chr15 85006392 0 0 0.0 0 +chr15 85137598 0 0 0.0 0 +chr15 85235107 0 0 0.0 0 +chr15 85277820 0 0 0.0 0 +chr15 85326985 0 0 0.0 0 +chr15 85344345 0 0 0.0 0 +chr15 85380188 0 0 0.0 0 +chr15 85390449 0 0 0.0 0 +chr15 85432631 0 0 0.0 0 +chr15 85508608 0 0 0.0 0 +chr15 85562218 0 0 0.0 0 +chr15 85571477 0 0 0.0 0 +chr15 85605730 0 0 0.0 0 +chr15 85631731 0 0 0.0 0 +chr15 85736659 0 0 0.0 0 +chr15 85766072 0 0 0.0 0 +chr15 85769054 0 0 0.0 0 +chr15 85870515 0 0 0.0 0 +chr15 85914592 0 0 0.0 0 +chr15 86104086 0 0 0.0 0 +chr15 86219114 0 0 0.0 0 +chr15 86247776 0 0 0.0 0 +chr15 86264742 0 0 0.0 0 +chr15 86467343 0 0 0.0 0 +chr15 86518085 0 0 0.0 0 +chr15 86644290 0 0 0.0 0 +chr15 86692102 0 0 0.0 0 +chr15 86888658 0 0 0.0 0 +chr15 87085827 0 0 0.0 0 +chr15 87315600 0 1 0.0244 0 +chr15 87721432 0 0 0.0 0 +chr15 87725319 0 0 0.0 0 +chr15 87961764 0 0 0.0 0 +chr15 87966368 0 0 0.0 0 +chr15 88134070 0 0 0.0 0 +chr15 88170173 0 0 0.0 0 +chr15 88279374 0 0 0.0 0 +chr15 88347604 0 0 0.0 0 +chr15 88523137 0 0 0.0 0 +chr15 88531154 0 0 0.0 0 +chr15 88832394 0 0 0.0 0 +chr15 88842074 0 0 0.0 0 +chr15 89019747 0 0 0.0 0 +chr15 89239738 0 0 0.0 0 +chr15 89280448 0 0 0.0 0 +chr15 89366150 0 0 0.0 0 +chr15 89416297 0 0 0.0 0 +chr15 89486866 0 0 0.0 0 +chr15 89644445 0 0 0.0 0 +chr15 89713774 0 0 0.0 0 +chr15 89753393 0 0 0.0 0 +chr15 89817498 0 0 0.0 0 +chr15 89818576 0 0 0.0 0 +chr15 90036331 0 0 0.0 0 +chr15 90074153 0 0 0.0 0 +chr15 90116338 0 0 0.0 0 +chr15 90230785 0 0 0.0 0 +chr15 90231614 0 0 0.0 0 +chr15 90361134 0 0 0.0 0 +chr15 90551143 0 0 0.0 0 +chr15 90627402 0 0 0.0 0 +chr15 90779749 0 0 0.0 0 +chr15 90880359 0 0 0.0 0 +chr15 90938624 0 0 0.0 0 +chr15 91028106 0 0 0.0 0 +chr15 91071279 0 0 0.0 0 +chr15 91181175 0 0 0.0 0 +chr15 91247152 0 0 0.0 0 +chr15 91274954 0 0 0.0 0 +chr15 91415050 0 0 0.0 0 +chr15 91528765 0 0 0.0 0 +chr15 91634149 0 0 0.0 0 +chr15 91795605 0 0 0.0 0 +chr15 91901969 0 0 0.0 0 +chr15 92014539 0 0 0.0 0 +chr15 92048582 0 0 0.0 0 +chr15 92075340 0 0 0.0 0 +chr15 92182603 0 0 0.0 0 +chr15 92183786 0 0 0.0 0 +chr15 92188028 0 0 0.0 0 +chr15 92308100 0 0 0.0 0 +chr15 92592714 0 0 0.0 0 +chr15 92636603 0 0 0.0 0 +chr15 92644396 0 0 0.0 0 +chr15 92672682 0 0 0.0 0 +chr15 92796814 0 0 0.0 0 +chr15 92939594 0 0 0.0 0 +chr15 92942978 0 0 0.0 0 +chr15 93073204 0 0 0.0 0 +chr15 93277237 0 0 0.0 0 +chr15 93414296 0 0 0.0 0 +chr15 93415773 0 0 0.0 0 +chr15 93451081 0 0 0.0 0 +chr15 93470339 0 0 0.0 0 +chr15 93622116 0 0 0.0 0 +chr15 93654034 0 0 0.0 0 +chr15 93690252 0 0 0.0 0 +chr15 93778365 0 1 0.0175 0 +chr15 93820866 0 0 0.0 0 +chr15 93909571 0 1 0.0323 0 +chr15 93998603 0 0 0.0 0 +chr15 94037219 0 0 0.0 0 +chr15 94091144 0 0 0.0 0 +chr15 94144974 0 0 0.0 0 +chr15 94159443 0 0 0.0 0 +chr15 94169924 0 0 0.0 0 +chr15 94242015 0 0 0.0 0 +chr15 94302618 0 0 0.0 0 +chr15 94463341 0 0 0.0 0 +chr15 94548252 1 37 0.7255 1 +chr15 94639282 0 0 0.0 0 +chr15 95062161 0 0 0.0 0 +chr15 95067824 0 0 0.0 0 +chr15 95132963 0 0 0.0 0 +chr15 95243176 0 0 0.0 0 +chr15 95308307 0 0 0.0 0 +chr15 95347339 0 0 0.0 0 +chr15 95400385 0 0 0.0 0 +chr15 95562084 0 0 0.0 0 +chr15 95598052 0 0 0.0 0 +chr15 95625408 0 0 0.0 0 +chr15 95645394 0 0 0.0 0 +chr15 95749452 0 0 0.0 0 +chr15 95819996 0 0 0.0 0 +chr15 95839924 0 0 0.0 0 +chr15 95911241 0 0 0.0 0 +chr15 96226806 0 0 0.0 0 +chr15 96246433 0 0 0.0 0 +chr15 96378618 0 0 0.0 0 +chr15 96396773 0 0 0.0 0 +chr15 96431314 0 0 0.0 0 +chr15 96556754 0 0 0.0 0 +chr15 96603548 0 0 0.0 0 +chr15 96760798 0 0 0.0 0 +chr15 96805923 0 0 0.0 0 +chr15 96951842 0 0 0.0 0 +chr15 96964196 0 0 0.0 0 +chr15 97237978 0 0 0.0 0 +chr15 97321969 0 0 0.0 0 +chr15 97468307 0 0 0.0 0 +chr15 97572746 0 0 0.0 0 +chr15 97756341 0 0 0.0 0 +chr15 97793594 0 0 0.0 0 +chr15 97918063 0 0 0.0 0 +chr15 97957510 0 0 0.0 0 +chr15 98103226 0 0 0.0 0 +chr15 98146158 0 0 0.0 0 +chr15 98491188 0 0 0.0 0 +chr15 98604182 0 0 0.0 0 +chr15 98639547 0 0 0.0 0 +chr15 98758385 0 0 0.0 0 +chr15 98795840 0 0 0.0 0 +chr15 98825967 0 0 0.0 0 +chr15 98829172 0 0 0.0 0 +chr15 98882262 0 0 0.0 0 +chr15 98944474 0 0 0.0 0 +chr15 99005797 0 0 0.0 0 +chr15 99058000 0 0 0.0 0 +chr15 99132620 0 0 0.0 0 +chr15 99183061 0 0 0.0 0 +chr15 99383797 0 0 0.0 0 +chr15 99471601 0 0 0.0 0 +chr15 99524488 0 0 0.0 0 +chr15 99573666 0 0 0.0 0 +chr15 99749392 0 0 0.0 0 +chr15 99846507 0 1 0.0196 0 +chr15 99932043 0 0 0.0 0 +chr15 99976266 0 0 0.0 0 +chr15 100006152 0 0 0.0 0 +chr15 100064302 0 0 0.0 0 +chr15 100169618 0 0 0.0 0 +chr15 100196135 0 0 0.0 0 +chr15 100224952 0 0 0.0 0 +chr15 100234446 0 0 0.0 0 +chr15 100251157 0 0 0.0 0 +chr15 100270711 0 0 0.0 0 +chr15 100297973 0 0 0.0 0 +chr15 100332898 0 0 0.0 0 +chr15 100580117 0 0 0.0 0 +chr15 100646682 0 0 0.0 0 +chr15 100732844 0 0 0.0 0 +chr15 100761815 0 0 0.0 0 +chr15 100847520 0 0 0.0 0 +chr15 100884532 0 0 0.0 0 +chr15 101037412 0 0 0.0 0 +chr15 101041743 0 0 0.0 0 +chr15 101135201 0 0 0.0 0 +chr15 101234067 0 0 0.0 0 +chr15 101265932 0 0 0.0 0 +chr15 101307627 0 0 0.0 0 +chr15 101314563 0 0 0.0 0 +chr15 101314672 0 0 0.0 0 +chr15 101351174 0 0 0.0 0 +chr15 101369710 0 0 0.0 0 +chr15 101392122 0 0 0.0 0 +chr15 101432379 0 0 0.0 0 +chr15 101465311 1 72 0.8889 1 +chr15 101501334 0 0 0.0 0 +chr15 101503147 0 0 0.0 0 +chr15 101521638 0 0 0.0 0 +chr15 101527943 0 0 0.0 0 +chr15 101546606 0 0 0.0 0 +chr15 101775961 0 0 0.0 0 +chr15_GL383555v2_alt 53621 0 0 0.0 0 +chr15_GL383555v2_alt 87357 0 0 0.0 0 +chr15_GL383555v2_alt 88746 0 0 0.0 0 +chr15_KI270727v1_random 59515 0 0 0.0 0 +chr15_KI270727v1_random 66739 0 0 0.0 0 +chr15_KI270848v1_alt 39553 0 0 0.0 0 +chr15_KI270849v1_alt 34949 0 0 0.0 0 +chr15_KI270849v1_alt 38858 0 0 0.0 0 +chr15_KI270849v1_alt 140394 0 0 0.0 0 +chr15_KI270849v1_alt 185670 0 0 0.0 0 +chr15_KI270849v1_alt 227694 0 0 0.0 0 +chr15_KI270850v1_alt 64807 0 0 0.0 0 +chr15_KI270850v1_alt 143807 0 0 0.0 0 +chr15_KI270850v1_alt 303626 0 0 0.0 0 +chr15_KI270850v1_alt 335852 0 0 0.0 0 +chr15_KI270850v1_alt 377746 0 0 0.0 0 +chr15_KI270851v1_alt 15497 0 0 0.0 0 +chr15_KI270851v1_alt 245046 0 0 0.0 0 +chr15_KI270852v1_alt 1627 0 0 0.0 0 +chr15_KI270852v1_alt 90266 0 0 0.0 0 +chr15_KI270852v1_alt 97490 0 0 0.0 0 +chr15_KI270905v1_alt 970913 0 0 0.0 0 +chr15_KI270905v1_alt 1196661 0 0 0.0 0 +chr15_KI270905v1_alt 1252459 0 0 0.0 0 +chr15_KI270905v1_alt 1277795 0 0 0.0 0 +chr15_KI270905v1_alt 1475627 0 0 0.0 0 +chr15_KI270905v1_alt 1760804 0 0 0.0 0 +chr15_KI270905v1_alt 2051572 0 0 0.0 0 +chr15_KI270905v1_alt 2285687 0 0 0.0 0 +chr15_KI270905v1_alt 2307966 0 0 0.0 0 +chr15_KI270905v1_alt 2463127 0 0 0.0 0 +chr15_KI270905v1_alt 2609392 0 0 0.0 0 +chr15_KI270905v1_alt 3041287 0 0 0.0 0 +chr15_KI270905v1_alt 3088047 0 0 0.0 0 +chr15_KI270905v1_alt 3180833 0 0 0.0 0 +chr15_KI270905v1_alt 3361266 0 0 0.0 0 +chr15_KI270905v1_alt 3375101 0 0 0.0 0 +chr15_KI270905v1_alt 3391575 0 0 0.0 0 +chr15_KI270905v1_alt 3639044 0 0 0.0 0 +chr15_KI270905v1_alt 3641815 0 0 0.0 0 +chr15_KI270905v1_alt 3675768 0 0 0.0 0 +chr15_KI270905v1_alt 3683492 0 0 0.0 0 +chr15_KI270905v1_alt 3935338 0 0 0.0 0 +chr15_KI270905v1_alt 3943147 0 0 0.0 0 +chr15_KI270905v1_alt 3959451 0 0 0.0 0 +chr15_KI270905v1_alt 4491780 0 0 0.0 0 +chr15_KI270905v1_alt 4699465 0 0 0.0 0 +chr15_KI270905v1_alt 4905089 0 0 0.0 0 +chr15_KI270905v1_alt 5118405 0 0 0.0 0 +chr16 74394 0 0 0.0 0 +chr16 84544 0 0 0.0 0 +chr16 109380 0 0 0.0 0 +chr16 149286 0 0 0.0 0 +chr16 276573 0 0 0.0 0 +chr16 317998 0 0 0.0 0 +chr16 391376 0 0 0.0 0 +chr16 427405 0 0 0.0 0 +chr16 659509 0 0 0.0 0 +chr16 688200 0 0 0.0 0 +chr16 698409 0 0 0.0 0 +chr16 729945 0 0 0.0 0 +chr16 732190 0 0 0.0 0 +chr16 911938 0 0 0.0 0 +chr16 966232 0 0 0.0 0 +chr16 984543 0 0 0.0 0 +chr16 1048273 0 0 0.0 0 +chr16 1075529 0 0 0.0 0 +chr16 1284003 0 0 0.0 0 +chr16 1315980 0 0 0.0 0 +chr16 1332387 0 0 0.0 0 +chr16 1358540 0 0 0.0 0 +chr16 1368828 0 0 0.0 0 +chr16 1428553 0 0 0.0 0 +chr16 1469443 0 0 0.0 0 +chr16 1577106 0 0 0.0 0 +chr16 1661187 0 0 0.0 0 +chr16 1745328 0 0 0.0 0 +chr16 1902992 0 0 0.0 0 +chr16 1987097 1 43 0.4943 1 +chr16 2000084 0 0 0.0 0 +chr16 2033444 0 0 0.0 0 +chr16 2092013 0 0 0.0 0 +chr16 2154870 0 0 0.0 0 +chr16 2225266 0 0 0.0 0 +chr16 2275105 0 0 0.0 0 +chr16 2284236 0 0 0.0 0 +chr16 2299739 0 0 0.0 0 +chr16 2323806 0 0 0.0 0 +chr16 2329782 0 0 0.0 0 +chr16 2393039 0 0 0.0 0 +chr16 2422547 0 0 0.0 0 +chr16 2464072 0 0 0.0 0 +chr16 2591931 0 0 0.0 0 +chr16 2777498 0 0 0.0 0 +chr16 2882616 0 0 0.0 0 +chr16 2883438 0 0 0.0 0 +chr16 2920197 0 0 0.0 0 +chr16 3017576 0 0 0.0 0 +chr16 3056231 0 0 0.0 0 +chr16 3068070 0 0 0.0 0 +chr16 3076076 0 0 0.0 0 +chr16 3087672 0 0 0.0 0 +chr16 3171560 0 0 0.0 0 +chr16 3175965 0 0 0.0 0 +chr16 3204110 0 0 0.0 0 +chr16 3255859 0 0 0.0 0 +chr16 3405441 0 0 0.0 0 +chr16 3448930 0 0 0.0 0 +chr16 3561602 0 0 0.0 0 +chr16 3567229 0 0 0.0 0 +chr16 3569631 0 0 0.0 0 +chr16 3569659 0 0 0.0 0 +chr16 3787753 0 1 0.0222 0 +chr16 3858130 0 0 0.0 0 +chr16 3893941 0 0 0.0 0 +chr16 3966331 0 0 0.0 0 +chr16 3978025 0 0 0.0 0 +chr16 3992763 0 1 0.0164 0 +chr16 3999750 0 0 0.0 0 +chr16 4005015 0 0 0.0 0 +chr16 4059788 0 0 0.0 0 +chr16 4087292 0 0 0.0 0 +chr16 4110104 0 0 0.0 0 +chr16 4111223 0 0 0.0 0 +chr16 4115442 0 0 0.0 0 +chr16 4123773 0 0 0.0 0 +chr16 4146651 0 0 0.0 0 +chr16 4196322 0 1 0.0244 0 +chr16 4263692 0 0 0.0 0 +chr16 4269569 0 0 0.0 0 +chr16 4388576 0 0 0.0 0 +chr16 4419131 0 0 0.0 0 +chr16 4441481 0 0 0.0 0 +chr16 4451456 0 0 0.0 0 +chr16 4645279 0 0 0.0 0 +chr16 4672308 0 0 0.0 0 +chr16 4692932 0 0 0.0 0 +chr16 4698137 0 1 0.0123 0 +chr16 4902579 0 0 0.0 0 +chr16 4911395 0 0 0.0 0 +chr16 4973517 0 0 0.0 0 +chr16 5078684 0 0 0.0 0 +chr16 5093706 0 0 0.0 0 +chr16 5224262 0 0 0.0 0 +chr16 5317061 0 0 0.0 0 +chr16 5391703 0 0 0.0 0 +chr16 5435270 0 0 0.0 0 +chr16 5462044 0 0 0.0 0 +chr16 5508754 0 0 0.0 0 +chr16 5519344 0 0 0.0 0 +chr16 5605254 0 0 0.0 0 +chr16 5635405 0 0 0.0 0 +chr16 5638285 0 0 0.0 0 +chr16 5648410 0 0 0.0 0 +chr16 5659645 0 0 0.0 0 +chr16 5750149 0 0 0.0 0 +chr16 5820907 0 0 0.0 0 +chr16 5836487 0 0 0.0 0 +chr16 5950018 0 0 0.0 0 +chr16 6009961 0 0 0.0 0 +chr16 6050935 0 0 0.0 0 +chr16 6061134 0 0 0.0 0 +chr16 6143680 0 0 0.0 0 +chr16 6186517 0 0 0.0 0 +chr16 6234576 0 0 0.0 0 +chr16 6235877 0 0 0.0 0 +chr16 6329716 0 0 0.0 0 +chr16 6410099 0 0 0.0 0 +chr16 6518426 0 0 0.0 0 +chr16 6611408 0 0 0.0 0 +chr16 6612531 0 0 0.0 0 +chr16 6730935 0 0 0.0 0 +chr16 6956914 0 0 0.0 0 +chr16 6958176 0 0 0.0 0 +chr16 6960673 0 0 0.0 0 +chr16 7058961 0 0 0.0 0 +chr16 7068850 0 0 0.0 0 +chr16 7194818 0 0 0.0 0 +chr16 7312952 0 0 0.0 0 +chr16 7396419 0 0 0.0 0 +chr16 7482600 0 0 0.0 0 +chr16 7536378 0 0 0.0 0 +chr16 7649012 0 0 0.0 0 +chr16 7667158 0 0 0.0 0 +chr16 7735273 0 0 0.0 0 +chr16 7855014 0 0 0.0 0 +chr16 7915143 0 0 0.0 0 +chr16 7924311 0 0 0.0 0 +chr16 7976142 0 0 0.0 0 +chr16 7978107 0 0 0.0 0 +chr16 8080928 0 0 0.0 0 +chr16 8102424 0 0 0.0 0 +chr16 8271364 0 0 0.0 0 +chr16 8332699 0 0 0.0 0 +chr16 8370776 0 0 0.0 0 +chr16 8392645 0 0 0.0 0 +chr16 8462723 0 0 0.0 0 +chr16 8496811 0 0 0.0 0 +chr16 8517597 0 0 0.0 0 +chr16 8560770 0 0 0.0 0 +chr16 8565720 0 0 0.0 0 +chr16 8628103 0 0 0.0 0 +chr16 8682431 0 0 0.0 0 +chr16 8714776 0 0 0.0 0 +chr16 8864768 0 0 0.0 0 +chr16 8897619 0 0 0.0 0 +chr16 8943501 0 0 0.0 0 +chr16 9125427 0 0 0.0 0 +chr16 9136740 0 0 0.0 0 +chr16 9217813 0 0 0.0 0 +chr16 9308460 0 0 0.0 0 +chr16 9551701 0 0 0.0 0 +chr16 9558287 0 0 0.0 0 +chr16 9810811 0 0 0.0 0 +chr16 9893057 0 0 0.0 0 +chr16 10099870 0 0 0.0 0 +chr16 10217337 0 0 0.0 0 +chr16 10226728 0 0 0.0 0 +chr16 10270388 0 0 0.0 0 +chr16 10308161 0 2 0.05 0 +chr16 10356734 0 0 0.0 0 +chr16 10391297 0 0 0.0 0 +chr16 10489709 0 0 0.0 0 +chr16 10525602 0 0 0.0 0 +chr16 10565788 0 0 0.0 0 +chr16 10598893 0 0 0.0 0 +chr16 10641189 0 0 0.0 0 +chr16 10812734 0 0 0.0 0 +chr16 10833272 0 0 0.0 0 +chr16 10837130 0 0 0.0 0 +chr16 10934536 0 0 0.0 0 +chr16 10970536 0 0 0.0 0 +chr16 10979010 0 0 0.0 0 +chr16 10990707 0 0 0.0 0 +chr16 11049056 0 0 0.0 0 +chr16 11293958 0 0 0.0 0 +chr16 11307099 0 1 0.0154 0 +chr16 11393526 0 0 0.0 0 +chr16 11401046 0 0 0.0 0 +chr16 11417210 0 0 0.0 0 +chr16 11423670 0 0 0.0 0 +chr16 11497016 0 0 0.0 0 +chr16 11543763 0 0 0.0 0 +chr16 11557712 0 0 0.0 0 +chr16 11615936 0 0 0.0 0 +chr16 11626970 0 0 0.0 0 +chr16 11672995 0 0 0.0 0 +chr16 11740720 0 0 0.0 0 +chr16 12105787 0 0 0.0 0 +chr16 12288078 0 0 0.0 0 +chr16 12395858 0 0 0.0 0 +chr16 12526241 0 0 0.0 0 +chr16 12534709 0 0 0.0 0 +chr16 12560996 0 0 0.0 0 +chr16 12577231 0 0 0.0 0 +chr16 12592615 0 0 0.0 0 +chr16 12795721 0 0 0.0 0 +chr16 12948253 0 0 0.0 0 +chr16 13454021 0 0 0.0 0 +chr16 13460544 0 0 0.0 0 +chr16 13633203 0 0 0.0 0 +chr16 13664574 0 0 0.0 0 +chr16 13700294 0 0 0.0 0 +chr16 13765314 0 0 0.0 0 +chr16 13830027 0 0 0.0 0 +chr16 13858255 0 0 0.0 0 +chr16 13977441 0 0 0.0 0 +chr16 14012144 0 0 0.0 0 +chr16 14016833 0 0 0.0 0 +chr16 14242446 0 0 0.0 0 +chr16 14282043 0 1 0.02 0 +chr16 14885785 0 0 0.0 0 +chr16 14978907 0 0 0.0 0 +chr16 15055528 0 0 0.0 0 +chr16 15088241 0 0 0.0 0 +chr16 15297170 0 0 0.0 0 +chr16 15500160 0 0 0.0 0 +chr16 15505227 0 0 0.0 0 +chr16 15630742 0 0 0.0 0 +chr16 15650683 0 0 0.0 0 +chr16 15673197 0 1 0.0145 0 +chr16 15734950 0 1 0.0213 0 +chr16 15943752 0 0 0.0 0 +chr16 16039358 0 0 0.0 0 +chr16 16091245 0 0 0.0 0 +chr16 16155010 0 0 0.0 0 +chr16 16284429 0 0 0.0 0 +chr16 16458895 0 0 0.0 0 +chr16 16636487 0 0 0.0 0 +chr16 16691157 0 0 0.0 0 +chr16 16694925 0 0 0.0 0 +chr16 16785518 0 0 0.0 0 +chr16 16816338 0 0 0.0 0 +chr16 16873408 0 0 0.0 0 +chr16 17060641 0 0 0.0 0 +chr16 17230390 0 0 0.0 0 +chr16 17322081 0 0 0.0 0 +chr16 17335621 0 0 0.0 0 +chr16 17421558 0 0 0.0 0 +chr16 17538532 0 0 0.0 0 +chr16 17827032 0 0 0.0 0 +chr16 17841355 0 0 0.0 0 +chr16 17858866 0 0 0.0 0 +chr16 17872625 0 0 0.0 0 +chr16 17907991 0 0 0.0 0 +chr16 17918445 0 0 0.0 0 +chr16 17963286 0 0 0.0 0 +chr16 18016547 0 0 0.0 0 +chr16 18017318 0 0 0.0 0 +chr16 18033386 0 0 0.0 0 +chr16 18253023 0 0 0.0 0 +chr16 18427708 0 0 0.0 0 +chr16 18510244 0 0 0.0 0 +chr16 18664269 0 0 0.0 0 +chr16 18668044 0 0 0.0 0 +chr16 18836086 0 0 0.0 0 +chr16 18995681 0 0 0.0 0 +chr16 19142916 0 0 0.0 0 +chr16 19218599 0 0 0.0 0 +chr16 19340061 0 0 0.0 0 +chr16 19361790 0 0 0.0 0 +chr16 19486802 0 0 0.0 0 +chr16 19574847 0 0 0.0 0 +chr16 19704931 0 0 0.0 0 +chr16 19801566 0 0 0.0 0 +chr16 19855960 0 0 0.0 0 +chr16 20073343 0 0 0.0 0 +chr16 20331262 0 0 0.0 0 +chr16 20360887 0 0 0.0 0 +chr16 20374836 0 0 0.0 0 +chr16 20417908 0 0 0.0 0 +chr16 20747862 0 0 0.0 0 +chr16 20772287 0 0 0.0 0 +chr16 21113083 0 0 0.0 0 +chr16 21317224 0 0 0.0 0 +chr16 21532045 0 0 0.0 0 +chr16 21633955 0 0 0.0 0 +chr16 21740113 0 0 0.0 0 +chr16 21745528 0 0 0.0 0 +chr16 21767090 0 0 0.0 0 +chr16 21814399 0 0 0.0 0 +chr16 21954518 0 1 0.0118 0 +chr16 21982536 0 0 0.0 0 +chr16 22073764 0 0 0.0 0 +chr16 22145722 0 0 0.0 0 +chr16 22188288 0 0 0.0 0 +chr16 22213349 0 0 0.0 0 +chr16 22213873 0 0 0.0 0 +chr16 22297547 0 0 0.0 0 +chr16 22345676 0 0 0.0 0 +chr16 22556235 0 0 0.0 0 +chr16 22561651 0 0 0.0 0 +chr16 22732673 0 0 0.0 0 +chr16 22755994 0 0 0.0 0 +chr16 22826962 0 0 0.0 0 +chr16 22837237 0 0 0.0 0 +chr16 23021005 0 0 0.0 0 +chr16 23054143 0 0 0.0 0 +chr16 23103800 0 0 0.0 0 +chr16 23158721 0 0 0.0 0 +chr16 23202249 1 12 0.3333 1 +chr16 23268338 0 0 0.0 0 +chr16 23482692 0 0 0.0 0 +chr16 23533760 0 0 0.0 0 +chr16 23696687 0 0 0.0 0 +chr16 23702105 0 0 0.0 0 +chr16 23825919 0 0 0.0 0 +chr16 23880165 0 0 0.0 0 +chr16 23947379 0 0 0.0 0 +chr16 24001039 0 0 0.0 0 +chr16 24065845 0 0 0.0 0 +chr16 24133385 0 0 0.0 0 +chr16 24137659 0 0 0.0 0 +chr16 24242359 0 0 0.0 0 +chr16 24329201 0 0 0.0 0 +chr16 24396236 0 0 0.0 0 +chr16 24402006 0 0 0.0 0 +chr16 24516906 0 0 0.0 0 +chr16 24560830 0 0 0.0 0 +chr16 24776355 0 0 0.0 0 +chr16 25015836 0 0 0.0 0 +chr16 25178149 0 0 0.0 0 +chr16 25292550 0 0 0.0 0 +chr16 25325097 0 0 0.0 0 +chr16 25356472 0 0 0.0 0 +chr16 25444383 0 0 0.0 0 +chr16 25533792 0 0 0.0 0 +chr16 25844174 0 0 0.0 0 +chr16 25862626 0 0 0.0 0 +chr16 25896470 0 0 0.0 0 +chr16 25975383 0 0 0.0 0 +chr16 26012083 0 0 0.0 0 +chr16 26122813 0 0 0.0 0 +chr16 26140402 0 0 0.0 0 +chr16 26143469 0 0 0.0 0 +chr16 26649492 0 0 0.0 0 +chr16 26683833 0 0 0.0 0 +chr16 26806538 0 1 0.0152 0 +chr16 26888268 0 0 0.0 0 +chr16 26998803 0 0 0.0 0 +chr16 27036917 0 0 0.0 0 +chr16 27074358 0 0 0.0 0 +chr16 27201251 0 0 0.0 0 +chr16 27350152 0 0 0.0 0 +chr16 27361133 0 0 0.0 0 +chr16 27416842 0 0 0.0 0 +chr16 27478596 0 0 0.0 0 +chr16 27516763 0 0 0.0 0 +chr16 27623074 0 0 0.0 0 +chr16 27735333 0 0 0.0 0 +chr16 27829295 0 0 0.0 0 +chr16 27838116 0 0 0.0 0 +chr16 27921819 0 0 0.0 0 +chr16 28093838 0 0 0.0 0 +chr16 28108423 0 0 0.0 0 +chr16 28127180 0 1 0.02 0 +chr16 28208849 0 0 0.0 0 +chr16 28295790 0 0 0.0 0 +chr16 28494885 0 0 0.0 0 +chr16 28912661 0 0 0.0 0 +chr16 28976403 0 0 0.0 0 +chr16 28983687 0 0 0.0 0 +chr16 29082664 0 0 0.0 0 +chr16 29188357 0 0 0.0 0 +chr16 29230007 0 0 0.0 0 +chr16 29617459 0 0 0.0 0 +chr16 29877551 0 0 0.0 0 +chr16 29963560 0 0 0.0 0 +chr16 30094889 0 0 0.0 0 +chr16 30100891 0 0 0.0 0 +chr16 30482625 0 0 0.0 0 +chr16 30505842 0 0 0.0 0 +chr16 30519791 0 0 0.0 0 +chr16 30572042 0 0 0.0 0 +chr16 30784025 0 1 0.013 0 +chr16 30793576 0 0 0.0 0 +chr16 30886421 0 0 0.0 0 +chr16 30887673 0 0 0.0 0 +chr16 30906854 0 0 0.0 0 +chr16 30980996 0 0 0.0 0 +chr16 31094424 0 0 0.0 0 +chr16 31115742 0 0 0.0 0 +chr16 31134747 0 0 0.0 0 +chr16 31168856 0 0 0.0 0 +chr16 31383454 0 0 0.0 0 +chr16 31384243 0 0 0.0 0 +chr16 31505815 0 0 0.0 0 +chr16 31641843 0 1 0.0227 0 +chr16 31705410 0 0 0.0 0 +chr16 31707210 0 0 0.0 0 +chr16 31711997 0 0 0.0 0 +chr16 31998544 0 0 0.0 0 +chr16 32230730 0 0 0.0 0 +chr16 32319830 0 0 0.0 0 +chr16 32417100 0 0 0.0 0 +chr16 32489581 0 0 0.0 0 +chr16 32505509 0 0 0.0 0 +chr16 32598471 0 0 0.0 0 +chr16 32698704 0 0 0.0 0 +chr16 32919679 0 0 0.0 0 +chr16 32937000 0 0 0.0 0 +chr16 32942081 0 0 0.0 0 +chr16 33171694 0 0 0.0 0 +chr16 33281774 0 0 0.0 0 +chr16 33526116 0 0 0.0 0 +chr16 33624682 0 0 0.0 0 +chr16 33657992 0 0 0.0 0 +chr16 33690760 0 0 0.0 0 +chr16 33911725 0 0 0.0 0 +chr16 33916818 0 0 0.0 0 +chr16 33934192 0 0 0.0 0 +chr16 34062061 0 1 0.0189 0 +chr16 34151199 0 0 0.0 0 +chr16 34153620 0 0 0.0 0 +chr16 34154326 0 0 0.0 0 +chr16 34226081 0 0 0.0 0 +chr16 34623359 0 0 0.0 0 +chr16 34624385 0 0 0.0 0 +chr16 35177265 0 0 0.0 0 +chr16 35253001 0 0 0.0 0 +chr16 35357552 0 0 0.0 0 +chr16 35391310 0 0 0.0 0 +chr16 35514240 0 0 0.0 0 +chr16 35531573 0 0 0.0 0 +chr16 35629867 0 0 0.0 0 +chr16 35664142 0 0 0.0 0 +chr16 35753782 0 1 0.0204 0 +chr16 35755687 0 0 0.0 0 +chr16 35773698 0 0 0.0 0 +chr16 35788772 0 0 0.0 0 +chr16 35924874 0 0 0.0 0 +chr16 46490721 0 0 0.0 0 +chr16 46908904 0 0 0.0 0 +chr16 46922382 0 2 0.04 0 +chr16 46959600 0 0 0.0 0 +chr16 47004717 0 0 0.0 0 +chr16 47086249 0 0 0.0 0 +chr16 47097315 0 0 0.0 0 +chr16 47164996 0 0 0.0 0 +chr16 47274997 0 0 0.0 0 +chr16 47298672 0 0 0.0 0 +chr16 47386415 0 0 0.0 0 +chr16 47554387 0 0 0.0 0 +chr16 47822546 0 0 0.0 0 +chr16 47863931 0 0 0.0 0 +chr16 47871029 0 0 0.0 0 +chr16 47872504 0 0 0.0 0 +chr16 47875482 0 0 0.0 0 +chr16 47932794 0 0 0.0 0 +chr16 47959696 0 0 0.0 0 +chr16 48032333 0 0 0.0 0 +chr16 48125787 0 0 0.0 0 +chr16 48168368 0 0 0.0 0 +chr16 48251073 0 0 0.0 0 +chr16 48497406 0 0 0.0 0 +chr16 48520226 0 0 0.0 0 +chr16 48554952 0 0 0.0 0 +chr16 48672361 0 0 0.0 0 +chr16 48696383 0 0 0.0 0 +chr16 48832278 0 0 0.0 0 +chr16 48880616 0 0 0.0 0 +chr16 48883645 0 0 0.0 0 +chr16 49190226 0 0 0.0 0 +chr16 49199195 0 0 0.0 0 +chr16 49276478 0 0 0.0 0 +chr16 49307725 0 0 0.0 0 +chr16 49396607 0 0 0.0 0 +chr16 49456722 0 0 0.0 0 +chr16 49638735 0 0 0.0 0 +chr16 49655491 0 1 0.0213 0 +chr16 49680361 0 0 0.0 0 +chr16 49745794 0 0 0.0 0 +chr16 49750002 0 0 0.0 0 +chr16 49761503 0 0 0.0 0 +chr16 49787839 0 0 0.0 0 +chr16 49793762 0 1 0.0179 0 +chr16 49804656 0 0 0.0 0 +chr16 49885640 0 0 0.0 0 +chr16 49902378 0 0 0.0 0 +chr16 49906574 0 0 0.0 0 +chr16 49928162 0 0 0.0 0 +chr16 49939764 0 0 0.0 0 +chr16 50031017 0 1 0.0145 0 +chr16 50056306 0 0 0.0 0 +chr16 50215334 0 0 0.0 0 +chr16 50259839 0 0 0.0 0 +chr16 50293838 0 0 0.0 0 +chr16 50294989 0 0 0.0 0 +chr16 50307650 0 0 0.0 0 +chr16 50401878 0 0 0.0 0 +chr16 50456456 0 0 0.0 0 +chr16 50476505 0 0 0.0 0 +chr16 50507011 0 1 0.0204 0 +chr16 50544033 0 0 0.0 0 +chr16 50780968 0 0 0.0 0 +chr16 50864660 0 0 0.0 0 +chr16 50977577 0 0 0.0 0 +chr16 50982644 0 0 0.0 0 +chr16 51070250 0 0 0.0 0 +chr16 51073504 0 0 0.0 0 +chr16 51082776 0 0 0.0 0 +chr16 51133340 0 0 0.0 0 +chr16 51154661 1 4 0.0533 1 +chr16 51266403 0 0 0.0 0 +chr16 51266912 0 0 0.0 0 +chr16 51365429 0 0 0.0 0 +chr16 51394891 0 0 0.0 0 +chr16 51517068 0 0 0.0 0 +chr16 51621654 0 0 0.0 0 +chr16 51631884 0 0 0.0 0 +chr16 51747118 0 0 0.0 0 +chr16 51801930 0 0 0.0 0 +chr16 51815648 0 0 0.0 0 +chr16 51838341 0 0 0.0 0 +chr16 51877549 0 0 0.0 0 +chr16 51880277 0 0 0.0 0 +chr16 52070154 0 0 0.0 0 +chr16 52077742 0 0 0.0 0 +chr16 52080306 0 0 0.0 0 +chr16 52081335 0 0 0.0 0 +chr16 52081597 0 0 0.0 0 +chr16 52106925 0 0 0.0 0 +chr16 52268008 0 0 0.0 0 +chr16 52280119 0 0 0.0 0 +chr16 52310767 0 0 0.0 0 +chr16 52373653 0 0 0.0 0 +chr16 52382219 0 0 0.0 0 +chr16 52454608 0 0 0.0 0 +chr16 52471580 0 0 0.0 0 +chr16 52487934 0 0 0.0 0 +chr16 52512080 0 0 0.0 0 +chr16 52717562 0 0 0.0 0 +chr16 52730861 0 0 0.0 0 +chr16 52731777 0 0 0.0 0 +chr16 52742307 0 0 0.0 0 +chr16 52783208 0 0 0.0 0 +chr16 52949205 0 0 0.0 0 +chr16 53038703 0 0 0.0 0 +chr16 53092473 0 0 0.0 0 +chr16 53101529 0 0 0.0 0 +chr16 53128827 0 0 0.0 0 +chr16 53241845 0 0 0.0 0 +chr16 53247251 0 0 0.0 0 +chr16 53356677 0 0 0.0 0 +chr16 53357483 0 0 0.0 0 +chr16 53531045 0 0 0.0 0 +chr16 53565438 0 0 0.0 0 +chr16 53590743 0 0 0.0 0 +chr16 53602148 0 0 0.0 0 +chr16 53651076 0 0 0.0 0 +chr16 53879032 0 0 0.0 0 +chr16 53943336 0 0 0.0 0 +chr16 53979949 0 0 0.0 0 +chr16 54100874 0 0 0.0 0 +chr16 54131834 0 0 0.0 0 +chr16 54357344 0 0 0.0 0 +chr16 54361690 0 0 0.0 0 +chr16 54373749 0 0 0.0 0 +chr16 54466400 0 0 0.0 0 +chr16 54523055 0 0 0.0 0 +chr16 54545646 0 0 0.0 0 +chr16 54566407 0 0 0.0 0 +chr16 54612161 0 0 0.0 0 +chr16 54661246 0 0 0.0 0 +chr16 54662513 0 0 0.0 0 +chr16 54778090 0 0 0.0 0 +chr16 54791029 0 0 0.0 0 +chr16 54798712 0 0 0.0 0 +chr16 54800491 0 0 0.0 0 +chr16 54837620 0 0 0.0 0 +chr16 54854149 0 0 0.0 0 +chr16 55043580 0 0 0.0 0 +chr16 55132206 0 0 0.0 0 +chr16 55236703 0 0 0.0 0 +chr16 55344955 0 0 0.0 0 +chr16 55371286 0 0 0.0 0 +chr16 55393141 0 0 0.0 0 +chr16 55402455 0 0 0.0 0 +chr16 55466435 0 0 0.0 0 +chr16 55626848 0 0 0.0 0 +chr16 55703810 0 0 0.0 0 +chr16 55752443 0 0 0.0 0 +chr16 55876194 0 0 0.0 0 +chr16 55880481 0 0 0.0 0 +chr16 55919545 0 0 0.0 0 +chr16 55942664 0 0 0.0 0 +chr16 56115661 0 0 0.0 0 +chr16 56179115 0 0 0.0 0 +chr16 56201510 0 0 0.0 0 +chr16 56289715 0 0 0.0 0 +chr16 56331233 0 0 0.0 0 +chr16 56389753 0 0 0.0 0 +chr16 56607189 0 0 0.0 0 +chr16 56625616 0 0 0.0 0 +chr16 56733631 0 0 0.0 0 +chr16 56970115 0 0 0.0 0 +chr16 56986778 0 0 0.0 0 +chr16 57006540 0 0 0.0 0 +chr16 57037438 0 0 0.0 0 +chr16 57046853 0 0 0.0 0 +chr16 57066763 0 0 0.0 0 +chr16 57102499 0 0 0.0 0 +chr16 57140973 0 0 0.0 0 +chr16 57151070 0 0 0.0 0 +chr16 57161605 0 0 0.0 0 +chr16 57398591 0 0 0.0 0 +chr16 57460716 0 0 0.0 0 +chr16 57510378 0 0 0.0 0 +chr16 57642348 0 0 0.0 0 +chr16 57651644 0 0 0.0 0 +chr16 57652789 0 0 0.0 0 +chr16 57667098 0 0 0.0 0 +chr16 57754214 0 1 0.0179 0 +chr16 57761738 0 0 0.0 0 +chr16 57787304 0 0 0.0 0 +chr16 57797494 0 0 0.0 0 +chr16 57833705 0 0 0.0 0 +chr16 57976071 0 0 0.0 0 +chr16 57991582 0 0 0.0 0 +chr16 58036733 0 0 0.0 0 +chr16 58039217 0 0 0.0 0 +chr16 58081410 0 0 0.0 0 +chr16 58128847 1 24 0.3871 1 +chr16 58218358 0 0 0.0 0 +chr16 58221520 0 0 0.0 0 +chr16 58232774 0 0 0.0 0 +chr16 58345296 0 0 0.0 0 +chr16 58397561 0 0 0.0 0 +chr16 58473493 0 0 0.0 0 +chr16 58507165 0 0 0.0 0 +chr16 58518472 0 0 0.0 0 +chr16 58538987 0 0 0.0 0 +chr16 58740582 0 0 0.0 0 +chr16 58753913 0 0 0.0 0 +chr16 58910788 0 0 0.0 0 +chr16 59294520 0 0 0.0 0 +chr16 59347158 0 0 0.0 0 +chr16 59353430 0 0 0.0 0 +chr16 59404748 0 0 0.0 0 +chr16 60294791 0 0 0.0 0 +chr16 60314502 0 0 0.0 0 +chr16 60320680 0 0 0.0 0 +chr16 60538588 0 0 0.0 0 +chr16 60927803 0 0 0.0 0 +chr16 60936804 0 0 0.0 0 +chr16 61469226 0 0 0.0 0 +chr16 61821065 0 0 0.0 0 +chr16 61925207 0 0 0.0 0 +chr16 62093513 0 0 0.0 0 +chr16 62190164 0 0 0.0 0 +chr16 62259886 0 0 0.0 0 +chr16 62412266 0 0 0.0 0 +chr16 62545121 0 0 0.0 0 +chr16 62545308 0 0 0.0 0 +chr16 62608602 0 0 0.0 0 +chr16 62623191 0 0 0.0 0 +chr16 62743530 0 0 0.0 0 +chr16 62889283 0 0 0.0 0 +chr16 62992532 0 0 0.0 0 +chr16 63282292 0 0 0.0 0 +chr16 63898514 0 0 0.0 0 +chr16 63901290 0 0 0.0 0 +chr16 64027083 0 0 0.0 0 +chr16 64134541 0 0 0.0 0 +chr16 64352331 0 0 0.0 0 +chr16 64392815 0 0 0.0 0 +chr16 64435354 0 0 0.0 0 +chr16 64570527 0 0 0.0 0 +chr16 64663190 0 0 0.0 0 +chr16 64830405 0 0 0.0 0 +chr16 64847337 0 0 0.0 0 +chr16 64905186 0 0 0.0 0 +chr16 65069971 0 0 0.0 0 +chr16 65117788 0 0 0.0 0 +chr16 65124402 0 0 0.0 0 +chr16 65184224 0 0 0.0 0 +chr16 65211370 0 0 0.0 0 +chr16 65377079 0 0 0.0 0 +chr16 65448587 0 1 0.0208 0 +chr16 65523520 0 0 0.0 0 +chr16 65538699 0 0 0.0 0 +chr16 65599821 0 0 0.0 0 +chr16 65636837 0 0 0.0 0 +chr16 65709220 0 0 0.0 0 +chr16 65766668 0 0 0.0 0 +chr16 65833322 0 0 0.0 0 +chr16 65967971 0 0 0.0 0 +chr16 66031204 0 0 0.0 0 +chr16 66036413 0 0 0.0 0 +chr16 66143436 0 0 0.0 0 +chr16 66338082 0 0 0.0 0 +chr16 66471954 0 1 0.0175 0 +chr16 66494049 0 0 0.0 0 +chr16 66702994 0 0 0.0 0 +chr16 66750900 0 0 0.0 0 +chr16 66835379 0 0 0.0 0 +chr16 66859651 0 0 0.0 0 +chr16 66889390 0 0 0.0 0 +chr16 66895699 0 0 0.0 0 +chr16 66921873 0 0 0.0 0 +chr16 67121283 0 0 0.0 0 +chr16 67163706 0 0 0.0 0 +chr16 67184961 0 0 0.0 0 +chr16 67233521 0 0 0.0 0 +chr16 67256255 0 0 0.0 0 +chr16 67260562 0 0 0.0 0 +chr16 67445871 0 0 0.0 0 +chr16 67464372 0 0 0.0 0 +chr16 67466068 0 0 0.0 0 +chr16 67496041 0 0 0.0 0 +chr16 67500828 0 0 0.0 0 +chr16 67549990 0 0 0.0 0 +chr16 67558875 0 0 0.0 0 +chr16 67592001 0 0 0.0 0 +chr16 67602599 0 0 0.0 0 +chr16 67666312 0 0 0.0 0 +chr16 67730324 0 0 0.0 0 +chr16 67774259 0 0 0.0 0 +chr16 67807915 0 0 0.0 0 +chr16 67843574 0 0 0.0 0 +chr16 67925575 0 0 0.0 0 +chr16 67937400 0 0 0.0 0 +chr16 68104745 0 0 0.0 0 +chr16 68187451 0 0 0.0 0 +chr16 68206740 0 0 0.0 0 +chr16 68276560 0 0 0.0 0 +chr16 68310069 0 0 0.0 0 +chr16 68386694 0 0 0.0 0 +chr16 68474852 0 0 0.0 0 +chr16 68480590 0 0 0.0 0 +chr16 68552425 0 0 0.0 0 +chr16 68611380 0 0 0.0 0 +chr16 68629779 0 0 0.0 0 +chr16 68678796 0 0 0.0 0 +chr16 68691719 0 0 0.0 0 +chr16 68721495 0 0 0.0 0 +chr16 69139751 0 0 0.0 0 +chr16 69302587 0 0 0.0 0 +chr16 69411437 0 0 0.0 0 +chr16 69604711 0 0 0.0 0 +chr16 69681993 0 0 0.0 0 +chr16 69920650 0 0 0.0 0 +chr16 70062082 0 0 0.0 0 +chr16 70601984 0 0 0.0 0 +chr16 70644679 0 1 0.0286 0 +chr16 70644691 0 0 0.0 0 +chr16 70740421 0 0 0.0 0 +chr16 70786894 0 0 0.0 0 +chr16 70886461 0 0 0.0 0 +chr16 70936929 0 0 0.0 0 +chr16 71077245 0 0 0.0 0 +chr16 71121227 0 0 0.0 0 +chr16 71201571 0 0 0.0 0 +chr16 71250674 0 0 0.0 0 +chr16 71481984 0 0 0.0 0 +chr16 71510465 0 0 0.0 0 +chr16 71780227 0 0 0.0 0 +chr16 71857734 0 0 0.0 0 +chr16 71942710 0 0 0.0 0 +chr16 72245799 0 1 0.0127 0 +chr16 72372225 0 1 0.0233 0 +chr16 72779628 0 0 0.0 0 +chr16 72780362 0 0 0.0 0 +chr16 72842037 0 0 0.0 0 +chr16 72861209 0 0 0.0 0 +chr16 72926742 0 0 0.0 0 +chr16 72997960 0 0 0.0 0 +chr16 73011245 0 0 0.0 0 +chr16 73035829 0 0 0.0 0 +chr16 73133183 0 0 0.0 0 +chr16 73288076 0 0 0.0 0 +chr16 73302050 0 1 0.0152 0 +chr16 73403267 0 0 0.0 0 +chr16 73415720 0 0 0.0 0 +chr16 73465706 0 0 0.0 0 +chr16 73561888 0 0 0.0 0 +chr16 73590447 0 0 0.0 0 +chr16 73744673 0 0 0.0 0 +chr16 73870248 0 0 0.0 0 +chr16 73890311 0 0 0.0 0 +chr16 73975954 0 0 0.0 0 +chr16 73997018 0 0 0.0 0 +chr16 74020283 0 0 0.0 0 +chr16 74055264 0 0 0.0 0 +chr16 74120618 0 0 0.0 0 +chr16 74197036 0 0 0.0 0 +chr16 74271130 0 1 0.0222 0 +chr16 74457530 0 0 0.0 0 +chr16 74466166 0 0 0.0 0 +chr16 74505487 0 0 0.0 0 +chr16 74513496 0 0 0.0 0 +chr16 74525235 0 0 0.0 0 +chr16 74584634 0 0 0.0 0 +chr16 74691215 0 0 0.0 0 +chr16 74733297 0 0 0.0 0 +chr16 74824699 0 0 0.0 0 +chr16 74834513 0 0 0.0 0 +chr16 74870304 0 0 0.0 0 +chr16 75031957 0 0 0.0 0 +chr16 75110993 0 0 0.0 0 +chr16 75145438 0 0 0.0 0 +chr16 75192664 0 0 0.0 0 +chr16 75240407 0 0 0.0 0 +chr16 75345964 0 0 0.0 0 +chr16 75429007 1 34 0.4857 1 +chr16 75497265 0 0 0.0 0 +chr16 75511383 0 0 0.0 0 +chr16 75570218 0 0 0.0 0 +chr16 75744435 0 0 0.0 0 +chr16 75838416 0 0 0.0 0 +chr16 76049156 0 0 0.0 0 +chr16 76121827 0 0 0.0 0 +chr16 76170473 0 0 0.0 0 +chr16 76381985 0 0 0.0 0 +chr16 76447196 0 0 0.0 0 +chr16 76545274 0 0 0.0 0 +chr16 76605175 0 0 0.0 0 +chr16 76801051 0 0 0.0 0 +chr16 76834114 0 0 0.0 0 +chr16 76937087 0 0 0.0 0 +chr16 77214488 0 0 0.0 0 +chr16 77499562 0 0 0.0 0 +chr16 77504211 0 0 0.0 0 +chr16 77695977 0 0 0.0 0 +chr16 77737330 0 0 0.0 0 +chr16 77754810 0 0 0.0 0 +chr16 77884509 0 0 0.0 0 +chr16 77888144 0 0 0.0 0 +chr16 77959088 0 0 0.0 0 +chr16 77968401 0 0 0.0 0 +chr16 77986355 0 0 0.0 0 +chr16 78065801 0 0 0.0 0 +chr16 78121373 0 0 0.0 0 +chr16 78130610 0 0 0.0 0 +chr16 78147401 0 0 0.0 0 +chr16 78151265 0 0 0.0 0 +chr16 78324567 0 0 0.0 0 +chr16 78349341 0 0 0.0 0 +chr16 78424851 0 0 0.0 0 +chr16 78513008 0 0 0.0 0 +chr16 78565764 0 0 0.0 0 +chr16 78595258 0 0 0.0 0 +chr16 78610636 0 0 0.0 0 +chr16 78637783 0 0 0.0 0 +chr16 78843331 0 0 0.0 0 +chr16 78906265 0 0 0.0 0 +chr16 78913516 0 0 0.0 0 +chr16 78924078 0 0 0.0 0 +chr16 79025208 0 0 0.0 0 +chr16 79154283 0 0 0.0 0 +chr16 79154709 0 0 0.0 0 +chr16 79435631 0 0 0.0 0 +chr16 79479243 0 0 0.0 0 +chr16 79481891 0 0 0.0 0 +chr16 79509182 0 1 0.012 0 +chr16 79541623 0 0 0.0 0 +chr16 79581468 0 0 0.0 0 +chr16 79590060 0 0 0.0 0 +chr16 79630603 0 0 0.0 0 +chr16 79647357 0 0 0.0 0 +chr16 79872016 0 0 0.0 0 +chr16 79904491 0 0 0.0 0 +chr16 79933003 0 0 0.0 0 +chr16 80039364 0 0 0.0 0 +chr16 80071007 0 0 0.0 0 +chr16 80119588 0 0 0.0 0 +chr16 80206697 0 0 0.0 0 +chr16 80221274 0 0 0.0 0 +chr16 80264836 0 1 0.0156 0 +chr16 80387183 0 0 0.0 0 +chr16 80403166 0 0 0.0 0 +chr16 80550394 0 0 0.0 0 +chr16 80570350 0 0 0.0 0 +chr16 80736474 0 0 0.0 0 +chr16 80779790 0 0 0.0 0 +chr16 80825010 0 0 0.0 0 +chr16 81136109 0 0 0.0 0 +chr16 81166308 0 0 0.0 0 +chr16 81306769 0 0 0.0 0 +chr16 81340486 0 0 0.0 0 +chr16 81374086 0 0 0.0 0 +chr16 81384675 0 0 0.0 0 +chr16 81413590 0 0 0.0 0 +chr16 81562193 0 0 0.0 0 +chr16 81582839 0 0 0.0 0 +chr16 81701783 0 0 0.0 0 +chr16 81702948 0 0 0.0 0 +chr16 81715762 0 0 0.0 0 +chr16 81761674 0 0 0.0 0 +chr16 81799265 0 0 0.0 0 +chr16 81821652 0 0 0.0 0 +chr16 81838388 0 0 0.0 0 +chr16 81903233 0 0 0.0 0 +chr16 81939407 0 0 0.0 0 +chr16 81995705 0 0 0.0 0 +chr16 82049210 0 0 0.0 0 +chr16 82146555 0 0 0.0 0 +chr16 82189040 0 0 0.0 0 +chr16 82208713 0 0 0.0 0 +chr16 82531860 0 0 0.0 0 +chr16 82562039 0 0 0.0 0 +chr16 82594476 0 0 0.0 0 +chr16 82652020 0 0 0.0 0 +chr16 82688908 0 0 0.0 0 +chr16 82724853 0 0 0.0 0 +chr16 82803169 0 0 0.0 0 +chr16 82888121 0 0 0.0 0 +chr16 83148506 0 0 0.0 0 +chr16 83185627 0 0 0.0 0 +chr16 83212408 0 0 0.0 0 +chr16 83219648 0 0 0.0 0 +chr16 83233888 0 0 0.0 0 +chr16 83261219 0 0 0.0 0 +chr16 83267719 0 0 0.0 0 +chr16 83316569 0 0 0.0 0 +chr16 83320018 0 0 0.0 0 +chr16 83470305 0 0 0.0 0 +chr16 83515604 0 0 0.0 0 +chr16 83548637 0 0 0.0 0 +chr16 83792616 0 0 0.0 0 +chr16 83812895 0 0 0.0 0 +chr16 83848683 0 0 0.0 0 +chr16 83869828 0 0 0.0 0 +chr16 83912536 0 0 0.0 0 +chr16 83936341 0 0 0.0 0 +chr16 83954953 0 0 0.0 0 +chr16 84009054 0 0 0.0 0 +chr16 84180417 0 0 0.0 0 +chr16 84215846 0 0 0.0 0 +chr16 84222782 0 0 0.0 0 +chr16 84249743 0 1 0.0222 0 +chr16 84417547 0 0 0.0 0 +chr16 84465203 0 0 0.0 0 +chr16 84489969 0 0 0.0 0 +chr16 84546985 0 0 0.0 0 +chr16 84608474 0 0 0.0 0 +chr16 84609470 0 0 0.0 0 +chr16 84648358 0 0 0.0 0 +chr16 84752809 0 0 0.0 0 +chr16 84874752 0 1 0.0115 0 +chr16 84889076 0 0 0.0 0 +chr16 84918450 0 0 0.0 0 +chr16 84958499 0 0 0.0 0 +chr16 85019007 0 0 0.0 0 +chr16 85030187 0 0 0.0 0 +chr16 85045700 0 0 0.0 0 +chr16 85302929 0 0 0.0 0 +chr16 85448504 0 0 0.0 0 +chr16 85515728 0 0 0.0 0 +chr16 85523129 0 0 0.0 0 +chr16 85577204 0 0 0.0 0 +chr16 85695642 0 0 0.0 0 +chr16 85739407 0 0 0.0 0 +chr16 85745269 0 0 0.0 0 +chr16 85753045 0 0 0.0 0 +chr16 85779115 0 0 0.0 0 +chr16 85947017 0 0 0.0 0 +chr16 85959682 0 0 0.0 0 +chr16 86064436 0 0 0.0 0 +chr16 86129846 0 0 0.0 0 +chr16 86156469 0 0 0.0 0 +chr16 86177871 0 0 0.0 0 +chr16 86187313 0 0 0.0 0 +chr16 86378036 0 0 0.0 0 +chr16 86408675 0 0 0.0 0 +chr16 86453943 0 0 0.0 0 +chr16 86465067 0 0 0.0 0 +chr16 86467603 0 0 0.0 0 +chr16 86602181 0 0 0.0 0 +chr16 86627721 0 0 0.0 0 +chr16 86656351 0 0 0.0 0 +chr16 86672129 0 0 0.0 0 +chr16 86902684 0 0 0.0 0 +chr16 86905404 0 0 0.0 0 +chr16 86929506 0 0 0.0 0 +chr16 86963749 0 0 0.0 0 +chr16 87068903 0 0 0.0 0 +chr16 87147935 0 0 0.0 0 +chr16 87167519 0 0 0.0 0 +chr16 87174305 0 0 0.0 0 +chr16 87186175 0 0 0.0 0 +chr16 87344612 0 1 0.0152 0 +chr16 87421011 0 0 0.0 0 +chr16 87421466 0 0 0.0 0 +chr16 87447814 0 0 0.0 0 +chr16 87508731 0 0 0.0 0 +chr16 87618054 0 0 0.0 0 +chr16 87624568 0 0 0.0 0 +chr16 87668747 0 0 0.0 0 +chr16 87671637 0 0 0.0 0 +chr16 87738128 0 0 0.0 0 +chr16 87845944 0 0 0.0 0 +chr16 87972333 0 0 0.0 0 +chr16 88107574 0 0 0.0 0 +chr16 88133278 0 0 0.0 0 +chr16 88154399 0 0 0.0 0 +chr16 88451408 0 0 0.0 0 +chr16 88487534 0 0 0.0 0 +chr16 88494376 0 0 0.0 0 +chr16 88590401 0 0 0.0 0 +chr16 88635826 0 1 0.0133 0 +chr16 88653203 0 0 0.0 0 +chr16 88661520 0 0 0.0 0 +chr16 88663297 0 0 0.0 0 +chr16 88708507 0 0 0.0 0 +chr16 88751983 0 0 0.0 0 +chr16 88987132 0 0 0.0 0 +chr16 89025470 0 0 0.0 0 +chr16 89058642 0 0 0.0 0 +chr16 89100961 0 0 0.0 0 +chr16 89104319 0 0 0.0 0 +chr16 89131964 0 0 0.0 0 +chr16 89192359 0 1 0.0204 0 +chr16 89227745 0 0 0.0 0 +chr16 89373960 0 0 0.0 0 +chr16 89388733 0 0 0.0 0 +chr16 89675102 0 0 0.0 0 +chr16 89765872 0 0 0.0 0 +chr16 89817917 0 0 0.0 0 +chr16 89911748 0 0 0.0 0 +chr16 90057592 0 0 0.0 0 +chr16 90203624 0 0 0.0 0 +chr16_GL383556v1_alt 100111 0 0 0.0 0 +chr16_KI270728v1_random 100194 0 0 0.0 0 +chr16_KI270728v1_random 197961 0 0 0.0 0 +chr16_KI270728v1_random 309275 0 0 0.0 0 +chr16_KI270728v1_random 321849 0 0 0.0 0 +chr16_KI270728v1_random 324317 0 0 0.0 0 +chr16_KI270728v1_random 327427 0 0 0.0 0 +chr16_KI270728v1_random 342233 0 0 0.0 0 +chr16_KI270728v1_random 412536 0 0 0.0 0 +chr16_KI270728v1_random 552403 0 0 0.0 0 +chr16_KI270728v1_random 582434 0 0 0.0 0 +chr16_KI270728v1_random 595008 0 0 0.0 0 +chr16_KI270728v1_random 597476 0 0 0.0 0 +chr16_KI270728v1_random 600586 0 0 0.0 0 +chr16_KI270728v1_random 615392 0 0 0.0 0 +chr16_KI270728v1_random 733867 0 0 0.0 0 +chr16_KI270728v1_random 736977 0 0 0.0 0 +chr16_KI270728v1_random 739444 0 0 0.0 0 +chr16_KI270728v1_random 752018 0 0 0.0 0 +chr16_KI270728v1_random 782049 0 0 0.0 0 +chr16_KI270728v1_random 857675 0 0 0.0 0 +chr16_KI270728v1_random 959052 0 0 0.0 0 +chr16_KI270728v1_random 1198666 0 0 0.0 0 +chr16_KI270728v1_random 1203758 0 0 0.0 0 +chr16_KI270728v1_random 1538939 0 0 0.0 0 +chr16_KI270728v1_random 1734082 0 0 0.0 0 +chr16_KI270728v1_random 1767496 0 0 0.0 0 +chr16_KI270728v1_random 1826401 0 0 0.0 0 +chr16_KI270853v1_alt 581429 0 0 0.0 0 +chr16_KI270853v1_alt 614152 0 0 0.0 0 +chr16_KI270853v1_alt 690766 0 0 0.0 0 +chr16_KI270853v1_alt 818256 0 0 0.0 0 +chr16_KI270853v1_alt 901127 0 0 0.0 0 +chr16_KI270853v1_alt 1288754 0 0 0.0 0 +chr16_KI270853v1_alt 1308694 0 0 0.0 0 +chr16_KI270853v1_alt 1331207 0 0 0.0 0 +chr16_KI270853v1_alt 1392960 0 0 0.0 0 +chr16_KI270853v1_alt 1749102 0 0 0.0 0 +chr16_KI270853v1_alt 1812937 0 0 0.0 0 +chr16_KI270853v1_alt 1942436 0 0 0.0 0 +chr16_KI270853v1_alt 2352081 0 0 0.0 0 +chr16_KI270853v1_alt 2355848 0 0 0.0 0 +chr16_KI270853v1_alt 2446437 0 0 0.0 0 +chr16_KI270855v1_alt 153779 0 0 0.0 0 +chr16_KI270856v1_alt 33122 0 0 0.0 0 +chr17 172680 0 0 0.0 0 +chr17 194928 0 0 0.0 0 +chr17 235950 0 0 0.0 0 +chr17 292882 0 0 0.0 0 +chr17 293127 0 0 0.0 0 +chr17 330118 0 0 0.0 0 +chr17 374953 0 0 0.0 0 +chr17 443222 0 0 0.0 0 +chr17 501073 0 0 0.0 0 +chr17 501528 0 0 0.0 0 +chr17 660702 3 27 0.3553 1 +chr17 665702 0 0 0.0 0 +chr17 676609 0 0 0.0 0 +chr17 862815 0 0 0.0 0 +chr17 878282 0 0 0.0 0 +chr17 889454 0 0 0.0 0 +chr17 936648 0 0 0.0 0 +chr17 1007941 0 0 0.0 0 +chr17 1016852 0 0 0.0 0 +chr17 1017864 0 0 0.0 0 +chr17 1196955 0 0 0.0 0 +chr17 1304490 0 0 0.0 0 +chr17 1375094 0 0 0.0 0 +chr17 1408330 0 0 0.0 0 +chr17 1426489 0 0 0.0 0 +chr17 1470486 0 0 0.0 0 +chr17 1498729 0 0 0.0 0 +chr17 1642575 0 0 0.0 0 +chr17 1816157 0 0 0.0 0 +chr17 1870637 0 0 0.0 0 +chr17 1994267 0 0 0.0 0 +chr17 1996228 0 0 0.0 0 +chr17 2176552 0 0 0.0 0 +chr17 2309954 0 0 0.0 0 +chr17 2376786 0 0 0.0 0 +chr17 2379492 0 0 0.0 0 +chr17 2419507 0 0 0.0 0 +chr17 2459759 0 0 0.0 0 +chr17 2613567 0 0 0.0 0 +chr17 2652538 0 0 0.0 0 +chr17 2709005 0 0 0.0 0 +chr17 2710800 0 0 0.0 0 +chr17 2991681 0 0 0.0 0 +chr17 3013523 0 0 0.0 0 +chr17 3056494 0 0 0.0 0 +chr17 3247788 0 0 0.0 0 +chr17 3290408 0 0 0.0 0 +chr17 3324641 0 0 0.0 0 +chr17 3379306 0 0 0.0 0 +chr17 3476055 0 0 0.0 0 +chr17 3516231 0 0 0.0 0 +chr17 3526706 0 1 0.012 0 +chr17 3662693 0 0 0.0 0 +chr17 3727827 0 0 0.0 0 +chr17 3754958 0 0 0.0 0 +chr17 3762424 0 0 0.0 0 +chr17 3777441 0 0 0.0 0 +chr17 3798582 0 0 0.0 0 +chr17 3889062 0 0 0.0 0 +chr17 3898183 0 0 0.0 0 +chr17 3907403 0 0 0.0 0 +chr17 3923726 0 0 0.0 0 +chr17 4210325 0 0 0.0 0 +chr17 4214450 0 0 0.0 0 +chr17 4259713 0 0 0.0 0 +chr17 4264539 0 0 0.0 0 +chr17 4328022 0 0 0.0 0 +chr17 4402677 0 0 0.0 0 +chr17 4427158 0 0 0.0 0 +chr17 4467490 0 0 0.0 0 +chr17 4473762 0 0 0.0 0 +chr17 4567100 0 0 0.0 0 +chr17 4575103 0 0 0.0 0 +chr17 4801514 0 0 0.0 0 +chr17 4982817 0 0 0.0 0 +chr17 5088857 0 0 0.0 0 +chr17 5129467 0 1 0.0185 0 +chr17 5132628 0 0 0.0 0 +chr17 5180589 0 0 0.0 0 +chr17 5232516 0 0 0.0 0 +chr17 5528185 0 0 0.0 0 +chr17 5556198 0 0 0.0 0 +chr17 5933270 0 0 0.0 0 +chr17 6014281 0 0 0.0 0 +chr17 6017367 0 0 0.0 0 +chr17 6061156 0 0 0.0 0 +chr17 6145750 0 0 0.0 0 +chr17 6158274 0 0 0.0 0 +chr17 6273203 0 0 0.0 0 +chr17 6307497 0 0 0.0 0 +chr17 6417851 0 0 0.0 0 +chr17 6429277 0 0 0.0 0 +chr17 6542081 0 0 0.0 0 +chr17 6697637 0 0 0.0 0 +chr17 6727382 0 1 0.0222 0 +chr17 6740430 0 0 0.0 0 +chr17 6880964 0 0 0.0 0 +chr17 7186968 0 0 0.0 0 +chr17 7220965 0 0 0.0 0 +chr17 7244171 0 0 0.0 0 +chr17 7292742 0 0 0.0 0 +chr17 7447801 0 0 0.0 0 +chr17 7525346 0 0 0.0 0 +chr17 7577786 0 0 0.0 0 +chr17 7674183 0 0 0.0 0 +chr17 7834521 0 0 0.0 0 +chr17 7836328 0 0 0.0 0 +chr17 7850279 0 0 0.0 0 +chr17 7888094 0 0 0.0 0 +chr17 7893743 0 0 0.0 0 +chr17 7931716 0 0 0.0 0 +chr17 7937151 0 0 0.0 0 +chr17 7969668 0 0 0.0 0 +chr17 8223773 0 0 0.0 0 +chr17 8330652 0 0 0.0 0 +chr17 8331402 0 0 0.0 0 +chr17 8340476 0 0 0.0 0 +chr17 8468459 0 0 0.0 0 +chr17 8600178 0 1 0.0222 0 +chr17 8718085 0 0 0.0 0 +chr17 8796224 0 0 0.0 0 +chr17 8879846 0 0 0.0 0 +chr17 9020634 0 0 0.0 0 +chr17 9028264 0 0 0.0 0 +chr17 9057477 0 0 0.0 0 +chr17 9078852 0 0 0.0 0 +chr17 9084481 0 0 0.0 0 +chr17 9085630 0 0 0.0 0 +chr17 9139546 0 0 0.0 0 +chr17 9175769 0 0 0.0 0 +chr17 9195490 0 0 0.0 0 +chr17 9196985 0 0 0.0 0 +chr17 9576412 0 0 0.0 0 +chr17 9963797 0 0 0.0 0 +chr17 10116213 0 0 0.0 0 +chr17 10161474 0 0 0.0 0 +chr17 10223803 0 0 0.0 0 +chr17 10389231 0 0 0.0 0 +chr17 10521505 0 0 0.0 0 +chr17 10640299 0 0 0.0 0 +chr17 10704061 0 0 0.0 0 +chr17 10718784 0 0 0.0 0 +chr17 10720888 0 0 0.0 0 +chr17 10757123 0 0 0.0 0 +chr17 10772409 0 0 0.0 0 +chr17 10790610 0 0 0.0 0 +chr17 10815628 0 0 0.0 0 +chr17 10859560 0 0 0.0 0 +chr17 10888372 0 0 0.0 0 +chr17 10918665 0 0 0.0 0 +chr17 10982857 0 0 0.0 0 +chr17 11099598 0 0 0.0 0 +chr17 11575733 0 0 0.0 0 +chr17 11584887 0 0 0.0 0 +chr17 11626385 0 0 0.0 0 +chr17 11700213 0 0 0.0 0 +chr17 11721864 0 0 0.0 0 +chr17 11788779 0 0 0.0 0 +chr17 11834534 0 0 0.0 0 +chr17 11853164 0 0 0.0 0 +chr17 11928395 0 0 0.0 0 +chr17 11964629 0 0 0.0 0 +chr17 12044988 0 0 0.0 0 +chr17 12095695 0 0 0.0 0 +chr17 12273677 0 0 0.0 0 +chr17 12368681 0 0 0.0 0 +chr17 12491619 0 0 0.0 0 +chr17 12554617 0 0 0.0 0 +chr17 12641674 0 0 0.0 0 +chr17 12682734 0 0 0.0 0 +chr17 12717911 0 0 0.0 0 +chr17 12754486 0 0 0.0 0 +chr17 12827824 0 0 0.0 0 +chr17 12886099 0 0 0.0 0 +chr17 12896814 0 0 0.0 0 +chr17 12948261 0 0 0.0 0 +chr17 12971789 0 0 0.0 0 +chr17 13135805 0 0 0.0 0 +chr17 13276244 0 0 0.0 0 +chr17 13418978 0 0 0.0 0 +chr17 13492398 0 0 0.0 0 +chr17 13500483 0 0 0.0 0 +chr17 13555299 0 0 0.0 0 +chr17 13609057 0 0 0.0 0 +chr17 13653973 0 0 0.0 0 +chr17 13667952 0 0 0.0 0 +chr17 13674744 0 0 0.0 0 +chr17 13715656 0 0 0.0 0 +chr17 13789111 0 0 0.0 0 +chr17 13819645 0 0 0.0 0 +chr17 13873151 0 0 0.0 0 +chr17 13997116 0 0 0.0 0 +chr17 14056094 0 0 0.0 0 +chr17 14101074 0 0 0.0 0 +chr17 14141297 0 0 0.0 0 +chr17 14157678 0 0 0.0 0 +chr17 14244252 0 0 0.0 0 +chr17 14261867 0 0 0.0 0 +chr17 14303680 0 0 0.0 0 +chr17 14482794 0 0 0.0 0 +chr17 14598059 0 0 0.0 0 +chr17 14684707 0 0 0.0 0 +chr17 14708380 0 0 0.0 0 +chr17 14773047 0 0 0.0 0 +chr17 14952680 1 15 0.3659 1 +chr17 14972208 0 0 0.0 0 +chr17 15223972 0 0 0.0 0 +chr17 15364931 0 0 0.0 0 +chr17 15399410 0 0 0.0 0 +chr17 15455669 0 0 0.0 0 +chr17 15963231 0 0 0.0 0 +chr17 15970782 0 0 0.0 0 +chr17 15998208 0 0 0.0 0 +chr17 16454617 0 0 0.0 0 +chr17 16783746 0 0 0.0 0 +chr17 16873343 0 0 0.0 0 +chr17 17003184 0 0 0.0 0 +chr17 17017021 0 0 0.0 0 +chr17 17201295 0 0 0.0 0 +chr17 17204366 0 0 0.0 0 +chr17 17222441 0 0 0.0 0 +chr17 17259210 0 0 0.0 0 +chr17 17283220 0 0 0.0 0 +chr17 17719946 0 0 0.0 0 +chr17 17747469 0 0 0.0 0 +chr17 17840962 0 0 0.0 0 +chr17 17921538 0 0 0.0 0 +chr17 17978168 0 0 0.0 0 +chr17 17996670 0 0 0.0 0 +chr17 18125240 0 0 0.0 0 +chr17 18150260 0 0 0.0 0 +chr17 18155829 0 0 0.0 0 +chr17 18291102 0 0 0.0 0 +chr17 18327748 0 0 0.0 0 +chr17 18392578 0 0 0.0 0 +chr17 18484147 0 0 0.0 0 +chr17 18704723 0 0 0.0 0 +chr17 18774386 0 0 0.0 0 +chr17 19075807 0 0 0.0 0 +chr17 19176398 0 0 0.0 0 +chr17 19201864 0 0 0.0 0 +chr17 19263132 0 1 0.0149 0 +chr17 19332166 0 0 0.0 0 +chr17 19412258 0 0 0.0 0 +chr17 19525587 0 0 0.0 0 +chr17 19749457 0 0 0.0 0 +chr17 19978603 0 0 0.0 0 +chr17 20067404 0 0 0.0 0 +chr17 20282651 0 0 0.0 0 +chr17 20287605 0 0 0.0 0 +chr17 20460172 0 0 0.0 0 +chr17 20551866 0 0 0.0 0 +chr17 20765403 0 0 0.0 0 +chr17 20775586 0 0 0.0 0 +chr17 20804159 0 0 0.0 0 +chr17 20852576 0 0 0.0 0 +chr17 20969802 0 0 0.0 0 +chr17 21061201 0 0 0.0 0 +chr17 21106742 0 0 0.0 0 +chr17 21123045 0 0 0.0 0 +chr17 21169680 0 0 0.0 0 +chr17 21262550 0 0 0.0 0 +chr17 21318452 0 0 0.0 0 +chr17 21572976 0 0 0.0 0 +chr17 21723275 0 0 0.0 0 +chr17 21769525 0 0 0.0 0 +chr17 21877325 0 0 0.0 0 +chr17 21891748 0 0 0.0 0 +chr17 21893571 0 0 0.0 0 +chr17 21903033 0 0 0.0 0 +chr17 21910466 0 0 0.0 0 +chr17 22141235 0 0 0.0 0 +chr17 22188140 0 0 0.0 0 +chr17 22211270 0 0 0.0 0 +chr17 22328733 0 0 0.0 0 +chr17 22433170 0 0 0.0 0 +chr17 22437597 0 1 0.0192 0 +chr17 22442385 0 0 0.0 0 +chr17 22620380 0 0 0.0 0 +chr17 26640677 0 0 0.0 0 +chr17 26679170 0 0 0.0 0 +chr17 26802147 0 0 0.0 0 +chr17 26860601 0 0 0.0 0 +chr17 26879734 0 1 0.0233 0 +chr17 26879929 0 0 0.0 0 +chr17 27061663 0 0 0.0 0 +chr17 27082965 0 0 0.0 0 +chr17 27124241 0 0 0.0 0 +chr17 27238836 0 0 0.0 0 +chr17 27406356 0 0 0.0 0 +chr17 27408092 0 0 0.0 0 +chr17 27540591 0 0 0.0 0 +chr17 27577525 0 0 0.0 0 +chr17 27604127 0 0 0.0 0 +chr17 27606672 0 0 0.0 0 +chr17 27638536 0 0 0.0 0 +chr17 27645260 0 0 0.0 0 +chr17 27746405 0 0 0.0 0 +chr17 27752795 0 0 0.0 0 +chr17 27772214 0 0 0.0 0 +chr17 27922638 0 0 0.0 0 +chr17 27951281 0 0 0.0 0 +chr17 28031401 0 0 0.0 0 +chr17 28160727 0 0 0.0 0 +chr17 28162563 0 0 0.0 0 +chr17 28182070 0 0 0.0 0 +chr17 28217229 0 0 0.0 0 +chr17 28282946 0 0 0.0 0 +chr17 28327727 0 0 0.0 0 +chr17 28411528 0 0 0.0 0 +chr17 28451185 0 0 0.0 0 +chr17 28511763 0 0 0.0 0 +chr17 28704681 0 0 0.0 0 +chr17 28766611 0 0 0.0 0 +chr17 28816668 0 0 0.0 0 +chr17 28896216 0 0 0.0 0 +chr17 28955557 0 0 0.0 0 +chr17 29123232 0 0 0.0 0 +chr17 29182583 0 0 0.0 0 +chr17 29210686 0 0 0.0 0 +chr17 29270274 0 0 0.0 0 +chr17 29303707 0 0 0.0 0 +chr17 29496927 0 0 0.0 0 +chr17 29560009 0 0 0.0 0 +chr17 29623968 0 0 0.0 0 +chr17 29642826 0 0 0.0 0 +chr17 29645059 0 0 0.0 0 +chr17 29648630 0 0 0.0 0 +chr17 29716471 0 0 0.0 0 +chr17 29755489 0 0 0.0 0 +chr17 29789364 0 0 0.0 0 +chr17 29797654 0 0 0.0 0 +chr17 29812661 0 0 0.0 0 +chr17 30046704 0 0 0.0 0 +chr17 30090215 0 0 0.0 0 +chr17 30232305 0 0 0.0 0 +chr17 30436664 0 0 0.0 0 +chr17 30486274 0 0 0.0 0 +chr17 30497109 0 0 0.0 0 +chr17 30890810 0 1 0.0185 0 +chr17 30920284 0 0 0.0 0 +chr17 30937878 0 0 0.0 0 +chr17 31076152 0 0 0.0 0 +chr17 31281535 0 0 0.0 0 +chr17 31379352 1 14 0.3684 1 +chr17 31381756 0 0 0.0 0 +chr17 31390859 0 0 0.0 0 +chr17 31425786 0 0 0.0 0 +chr17 31465482 0 0 0.0 0 +chr17 31479163 0 0 0.0 0 +chr17 31513028 0 0 0.0 0 +chr17 31870287 0 0 0.0 0 +chr17 31904941 0 0 0.0 0 +chr17 32003125 0 0 0.0 0 +chr17 32018576 0 0 0.0 0 +chr17 32171900 0 0 0.0 0 +chr17 32197518 0 0 0.0 0 +chr17 32294995 0 0 0.0 0 +chr17 32434023 0 0 0.0 0 +chr17 32454831 0 0 0.0 0 +chr17 32504350 0 0 0.0 0 +chr17 32801544 0 0 0.0 0 +chr17 32971753 0 0 0.0 0 +chr17 33021891 0 0 0.0 0 +chr17 33284633 0 0 0.0 0 +chr17 33509165 0 0 0.0 0 +chr17 33572315 1 33 0.4286 1 +chr17 33575082 0 0 0.0 0 +chr17 33633373 0 0 0.0 0 +chr17 33740558 0 0 0.0 0 +chr17 33851428 0 0 0.0 0 +chr17 34011717 0 0 0.0 0 +chr17 34068133 0 0 0.0 0 +chr17 34090940 0 0 0.0 0 +chr17 34170541 0 0 0.0 0 +chr17 34171404 0 0 0.0 0 +chr17 34353088 0 0 0.0 0 +chr17 34540648 0 0 0.0 0 +chr17 34574859 0 0 0.0 0 +chr17 34601884 0 0 0.0 0 +chr17 34724145 0 0 0.0 0 +chr17 34861895 0 0 0.0 0 +chr17 34866388 0 0 0.0 0 +chr17 35133324 0 0 0.0 0 +chr17 35282681 0 0 0.0 0 +chr17 35425058 0 0 0.0 0 +chr17 35444696 0 0 0.0 0 +chr17 35516611 0 0 0.0 0 +chr17 35536933 0 0 0.0 0 +chr17 35599213 0 1 0.0286 0 +chr17 35612794 0 0 0.0 0 +chr17 35740252 0 0 0.0 0 +chr17 35748180 0 0 0.0 0 +chr17 35919943 0 0 0.0 0 +chr17 36063493 0 0 0.0 0 +chr17 36184608 0 0 0.0 0 +chr17 36249311 0 0 0.0 0 +chr17 36284903 0 0 0.0 0 +chr17 36373203 0 0 0.0 0 +chr17 36395892 0 0 0.0 0 +chr17 36424284 0 0 0.0 0 +chr17 36460392 0 1 0.0233 0 +chr17 36596932 0 0 0.0 0 +chr17 36611325 0 0 0.0 0 +chr17 36679540 0 0 0.0 0 +chr17 36727308 0 0 0.0 0 +chr17 36797979 0 0 0.0 0 +chr17 37009023 0 0 0.0 0 +chr17 37051083 0 0 0.0 0 +chr17 37070446 0 0 0.0 0 +chr17 37241169 0 2 0.0308 0 +chr17 37276090 0 0 0.0 0 +chr17 37362346 0 0 0.0 0 +chr17 37567433 0 0 0.0 0 +chr17 37609259 0 0 0.0 0 +chr17 37645788 0 0 0.0 0 +chr17 37649640 0 0 0.0 0 +chr17 37733493 0 1 0.0213 0 +chr17 37792219 0 0 0.0 0 +chr17 37795533 0 0 0.0 0 +chr17 37817976 0 0 0.0 0 +chr17 37826343 0 0 0.0 0 +chr17 37917001 0 0 0.0 0 +chr17 37973827 0 0 0.0 0 +chr17 38053365 0 0 0.0 0 +chr17 38088989 0 0 0.0 0 +chr17 38231553 0 0 0.0 0 +chr17 38324082 0 0 0.0 0 +chr17 38337827 0 0 0.0 0 +chr17 38400788 0 0 0.0 0 +chr17 38431384 0 0 0.0 0 +chr17 38454561 0 0 0.0 0 +chr17 38471860 0 0 0.0 0 +chr17 38494199 0 0 0.0 0 +chr17 38589104 0 0 0.0 0 +chr17 38677375 0 0 0.0 0 +chr17 38786210 0 0 0.0 0 +chr17 38796914 0 0 0.0 0 +chr17 38956990 0 0 0.0 0 +chr17 39104986 0 0 0.0 0 +chr17 39131041 0 0 0.0 0 +chr17 39131920 0 0 0.0 0 +chr17 39269094 0 0 0.0 0 +chr17 39399424 0 0 0.0 0 +chr17 39584086 0 0 0.0 0 +chr17 39628222 0 0 0.0 0 +chr17 39643623 0 0 0.0 0 +chr17 39651937 0 0 0.0 0 +chr17 39687427 0 0 0.0 0 +chr17 39906004 0 0 0.0 0 +chr17 39917121 0 0 0.0 0 +chr17 39990652 0 0 0.0 0 +chr17 40051239 0 0 0.0 0 +chr17 40075304 0 0 0.0 0 +chr17 40092643 0 0 0.0 0 +chr17 40327170 0 0 0.0 0 +chr17 40541519 0 0 0.0 0 +chr17 40686144 0 0 0.0 0 +chr17 40773410 0 0 0.0 0 +chr17 40938871 0 0 0.0 0 +chr17 41312560 0 0 0.0 0 +chr17 41393858 0 0 0.0 0 +chr17 41443765 0 0 0.0 0 +chr17 41480692 0 0 0.0 0 +chr17 41570146 0 0 0.0 0 +chr17 41581718 0 0 0.0 0 +chr17 41607889 0 0 0.0 0 +chr17 41611351 0 0 0.0 0 +chr17 41719450 0 0 0.0 0 +chr17 41802098 0 0 0.0 0 +chr17 41906968 0 0 0.0 0 +chr17 41922881 0 0 0.0 0 +chr17 41967478 0 0 0.0 0 +chr17 41976874 0 0 0.0 0 +chr17 42075238 0 0 0.0 0 +chr17 42087296 0 0 0.0 0 +chr17 42113966 0 0 0.0 0 +chr17 42134721 0 0 0.0 0 +chr17 42276659 0 0 0.0 0 +chr17 42322508 0 0 0.0 0 +chr17 42359583 0 0 0.0 0 +chr17 42516857 0 0 0.0 0 +chr17 42558560 0 0 0.0 0 +chr17 42622089 0 0 0.0 0 +chr17 42628583 0 0 0.0 0 +chr17 42685825 0 0 0.0 0 +chr17 42712417 0 0 0.0 0 +chr17 42720439 0 0 0.0 0 +chr17 43395389 0 0 0.0 0 +chr17 43550443 0 0 0.0 0 +chr17 43617213 0 1 0.0294 0 +chr17 43666119 0 0 0.0 0 +chr17 43748662 0 0 0.0 0 +chr17 43757651 0 0 0.0 0 +chr17 43772219 0 0 0.0 0 +chr17 43792417 0 0 0.0 0 +chr17 44001959 0 0 0.0 0 +chr17 44072007 0 0 0.0 0 +chr17 44106159 0 0 0.0 0 +chr17 44213604 0 0 0.0 0 +chr17 44261242 0 0 0.0 0 +chr17 44328467 0 0 0.0 0 +chr17 44329032 0 0 0.0 0 +chr17 44775348 0 0 0.0 0 +chr17 44804813 0 0 0.0 0 +chr17 44956204 0 0 0.0 0 +chr17 45098812 0 0 0.0 0 +chr17 45226103 0 0 0.0 0 +chr17 45238561 0 0 0.0 0 +chr17 45265195 0 0 0.0 0 +chr17 45314828 0 0 0.0 0 +chr17 45340458 0 0 0.0 0 +chr17 45361224 0 0 0.0 0 +chr17 45380724 0 0 0.0 0 +chr17 45454254 0 0 0.0 0 +chr17 45552884 0 0 0.0 0 +chr17 45653515 0 0 0.0 0 +chr17 45749571 0 0 0.0 0 +chr17 45793244 0 0 0.0 0 +chr17 45821126 0 0 0.0 0 +chr17 46011051 0 0 0.0 0 +chr17 46113178 0 0 0.0 0 +chr17 46292592 0 0 0.0 0 +chr17 46510166 0 0 0.0 0 +chr17 46773306 0 0 0.0 0 +chr17 46816904 0 0 0.0 0 +chr17 46834280 0 0 0.0 0 +chr17 46847630 0 0 0.0 0 +chr17 46849763 0 0 0.0 0 +chr17 46865347 0 0 0.0 0 +chr17 46940887 0 0 0.0 0 +chr17 47014653 0 0 0.0 0 +chr17 47344770 0 0 0.0 0 +chr17 47388249 0 1 0.0147 0 +chr17 47494281 0 0 0.0 0 +chr17 47557006 0 0 0.0 0 +chr17 47649170 0 0 0.0 0 +chr17 47713481 0 0 0.0 0 +chr17 47743985 0 0 0.0 0 +chr17 47877430 0 0 0.0 0 +chr17 47880989 0 0 0.0 0 +chr17 47904189 0 0 0.0 0 +chr17 48098822 0 1 0.0147 0 +chr17 48128475 0 0 0.0 0 +chr17 48468046 0 0 0.0 0 +chr17 48876271 1 73 0.9733 1 +chr17 48902461 0 0 0.0 0 +chr17 48975956 0 0 0.0 0 +chr17 49106801 0 0 0.0 0 +chr17 49456286 0 0 0.0 0 +chr17 49581471 0 0 0.0 0 +chr17 49706557 0 0 0.0 0 +chr17 49707037 0 0 0.0 0 +chr17 49826955 0 0 0.0 0 +chr17 49852717 0 0 0.0 0 +chr17 49979932 0 0 0.0 0 +chr17 49985285 0 1 0.0357 0 +chr17 49992990 0 0 0.0 0 +chr17 50098242 0 0 0.0 0 +chr17 50106934 0 0 0.0 0 +chr17 50361899 0 0 0.0 0 +chr17 50366267 0 0 0.0 0 +chr17 50403450 0 0 0.0 0 +chr17 50503224 0 0 0.0 0 +chr17 50573917 0 0 0.0 0 +chr17 50575911 0 0 0.0 0 +chr17 50578132 0 0 0.0 0 +chr17 50594713 0 0 0.0 0 +chr17 50609780 0 0 0.0 0 +chr17 50726847 0 0 0.0 0 +chr17 50799480 0 0 0.0 0 +chr17 50861553 0 0 0.0 0 +chr17 50866432 0 0 0.0 0 +chr17 50917273 0 0 0.0 0 +chr17 50919781 0 0 0.0 0 +chr17 51104103 0 0 0.0 0 +chr17 51136505 0 0 0.0 0 +chr17 51401843 0 0 0.0 0 +chr17 51446147 0 0 0.0 0 +chr17 51447265 0 0 0.0 0 +chr17 51586205 0 0 0.0 0 +chr17 51594146 0 0 0.0 0 +chr17 51669116 0 0 0.0 0 +chr17 51841481 0 0 0.0 0 +chr17 52019543 0 0 0.0 0 +chr17 52035870 0 0 0.0 0 +chr17 52128488 0 0 0.0 0 +chr17 52140539 0 0 0.0 0 +chr17 52233817 0 0 0.0 0 +chr17 52417971 0 0 0.0 0 +chr17 52481417 0 0 0.0 0 +chr17 52580704 0 0 0.0 0 +chr17 52621411 0 0 0.0 0 +chr17 52741408 0 0 0.0 0 +chr17 52920242 0 0 0.0 0 +chr17 52997121 0 0 0.0 0 +chr17 53033502 0 0 0.0 0 +chr17 53105143 0 0 0.0 0 +chr17 53124830 0 0 0.0 0 +chr17 53185696 0 0 0.0 0 +chr17 53632760 0 0 0.0 0 +chr17 53723555 0 0 0.0 0 +chr17 53832882 0 0 0.0 0 +chr17 54072924 0 0 0.0 0 +chr17 54144206 0 0 0.0 0 +chr17 54221794 0 0 0.0 0 +chr17 54228145 0 0 0.0 0 +chr17 54274142 0 0 0.0 0 +chr17 54554250 0 0 0.0 0 +chr17 54797132 0 0 0.0 0 +chr17 54913768 0 0 0.0 0 +chr17 55018289 0 0 0.0 0 +chr17 55108278 0 0 0.0 0 +chr17 55350790 0 0 0.0 0 +chr17 55457787 0 0 0.0 0 +chr17 55685448 0 0 0.0 0 +chr17 55898246 0 0 0.0 0 +chr17 55922436 0 0 0.0 0 +chr17 55930271 0 0 0.0 0 +chr17 56022567 0 0 0.0 0 +chr17 56109478 0 0 0.0 0 +chr17 56171419 0 0 0.0 0 +chr17 56294321 0 0 0.0 0 +chr17 56462660 0 0 0.0 0 +chr17 56475652 0 0 0.0 0 +chr17 56732037 0 0 0.0 0 +chr17 57136837 0 0 0.0 0 +chr17 57200747 0 0 0.0 0 +chr17 57235553 0 0 0.0 0 +chr17 57456914 0 0 0.0 0 +chr17 57561741 0 0 0.0 0 +chr17 57589883 0 0 0.0 0 +chr17 57631260 0 0 0.0 0 +chr17 57638528 0 0 0.0 0 +chr17 57642513 0 0 0.0 0 +chr17 57816200 0 0 0.0 0 +chr17 57835300 0 0 0.0 0 +chr17 57935790 0 0 0.0 0 +chr17 58033451 0 0 0.0 0 +chr17 58040612 0 0 0.0 0 +chr17 58054511 0 0 0.0 0 +chr17 58292580 0 0 0.0 0 +chr17 58302017 0 0 0.0 0 +chr17 58494528 0 0 0.0 0 +chr17 58602212 0 0 0.0 0 +chr17 58671801 0 0 0.0 0 +chr17 58842469 0 0 0.0 0 +chr17 58851564 0 0 0.0 0 +chr17 58873150 0 0 0.0 0 +chr17 59154742 0 0 0.0 0 +chr17 59170895 0 0 0.0 0 +chr17 59641186 0 0 0.0 0 +chr17 59740651 0 0 0.0 0 +chr17 59836918 0 0 0.0 0 +chr17 59881089 0 0 0.0 0 +chr17 60036382 0 0 0.0 0 +chr17 60663939 0 0 0.0 0 +chr17 60779806 0 0 0.0 0 +chr17 60792209 0 0 0.0 0 +chr17 60805333 0 0 0.0 0 +chr17 60824610 0 0 0.0 0 +chr17 60950418 0 0 0.0 0 +chr17 61229034 0 0 0.0 0 +chr17 61377136 0 0 0.0 0 +chr17 61495658 0 0 0.0 0 +chr17 61499885 0 0 0.0 0 +chr17 61650962 0 0 0.0 0 +chr17 61991376 0 0 0.0 0 +chr17 62260378 0 0 0.0 0 +chr17 62504449 0 0 0.0 0 +chr17 62622896 0 0 0.0 0 +chr17 62752065 0 0 0.0 0 +chr17 62765032 0 0 0.0 0 +chr17 62770483 0 0 0.0 0 +chr17 62822981 0 0 0.0 0 +chr17 63040954 0 0 0.0 0 +chr17 63189719 0 0 0.0 0 +chr17 63530035 0 0 0.0 0 +chr17 63548469 0 0 0.0 0 +chr17 63591631 0 0 0.0 0 +chr17 63613911 0 0 0.0 0 +chr17 63666191 0 0 0.0 0 +chr17 63899328 0 0 0.0 0 +chr17 63916979 0 0 0.0 0 +chr17 63949463 0 0 0.0 0 +chr17 63989048 0 1 0.0169 0 +chr17 64180954 0 0 0.0 0 +chr17 64247959 0 0 0.0 0 +chr17 64262152 0 0 0.0 0 +chr17 64399913 0 0 0.0 0 +chr17 64442487 0 0 0.0 0 +chr17 64762242 0 0 0.0 0 +chr17 64800731 0 0 0.0 0 +chr17 64858998 0 0 0.0 0 +chr17 64899795 0 0 0.0 0 +chr17 64992538 0 0 0.0 0 +chr17 65002342 0 0 0.0 0 +chr17 65038542 0 0 0.0 0 +chr17 65185867 0 0 0.0 0 +chr17 65187689 0 0 0.0 0 +chr17 65246480 1 34 0.4857 1 +chr17 65274869 0 0 0.0 0 +chr17 65290391 0 1 0.0143 0 +chr17 65314829 0 0 0.0 0 +chr17 65335677 0 0 0.0 0 +chr17 65342398 0 0 0.0 0 +chr17 65493101 0 0 0.0 0 +chr17 65514196 0 0 0.0 0 +chr17 65626696 0 0 0.0 0 +chr17 65722749 0 0 0.0 0 +chr17 65746301 0 0 0.0 0 +chr17 65994590 0 0 0.0 0 +chr17 66154272 0 0 0.0 0 +chr17 66170258 0 0 0.0 0 +chr17 66390828 0 1 0.0227 0 +chr17 66498159 0 0 0.0 0 +chr17 66583192 0 0 0.0 0 +chr17 66757261 0 0 0.0 0 +chr17 66795635 0 0 0.0 0 +chr17 66812645 0 0 0.0 0 +chr17 66883184 0 0 0.0 0 +chr17 67032550 0 0 0.0 0 +chr17 67047325 0 0 0.0 0 +chr17 67371196 0 0 0.0 0 +chr17 67510822 0 1 0.0238 0 +chr17 67546527 0 0 0.0 0 +chr17 67559028 0 0 0.0 0 +chr17 67903151 0 0 0.0 0 +chr17 68074295 0 2 0.4 0 +chr17 68092530 0 0 0.0 0 +chr17 68162570 0 0 0.0 0 +chr17 68189417 0 0 0.0 0 +chr17 68249014 0 0 0.0 0 +chr17 68338158 1 28 0.3889 1 +chr17 68512448 0 0 0.0 0 +chr17 68543266 0 0 0.0 0 +chr17 68656573 0 0 0.0 0 +chr17 68666932 0 0 0.0 0 +chr17 68761764 0 0 0.0 0 +chr17 68878464 0 0 0.0 0 +chr17 68880801 0 0 0.0 0 +chr17 68948137 0 0 0.0 0 +chr17 68993342 0 0 0.0 0 +chr17 69105146 0 0 0.0 0 +chr17 69224723 0 0 0.0 0 +chr17 69233977 0 0 0.0 0 +chr17 69543409 0 0 0.0 0 +chr17 69596774 0 0 0.0 0 +chr17 69630533 0 0 0.0 0 +chr17 69708809 0 0 0.0 0 +chr17 69716065 0 0 0.0 0 +chr17 69752653 0 0 0.0 0 +chr17 69798995 0 0 0.0 0 +chr17 69965858 0 0 0.0 0 +chr17 70087633 0 0 0.0 0 +chr17 70163500 0 0 0.0 0 +chr17 70345784 0 0 0.0 0 +chr17 70359095 0 0 0.0 0 +chr17 70471389 0 0 0.0 0 +chr17 70669085 0 0 0.0 0 +chr17 70810411 0 0 0.0 0 +chr17 70814677 0 0 0.0 0 +chr17 71033531 0 0 0.0 0 +chr17 71102035 0 0 0.0 0 +chr17 71201013 0 0 0.0 0 +chr17 71316780 0 0 0.0 0 +chr17 71336650 0 0 0.0 0 +chr17 71478394 0 0 0.0 0 +chr17 71549745 0 0 0.0 0 +chr17 71724288 0 0 0.0 0 +chr17 71771749 0 0 0.0 0 +chr17 71828506 0 0 0.0 0 +chr17 71848342 0 0 0.0 0 +chr17 71859491 0 1 0.0192 0 +chr17 72027301 0 0 0.0 0 +chr17 72097166 0 0 0.0 0 +chr17 72114867 0 0 0.0 0 +chr17 72190969 0 0 0.0 0 +chr17 72237282 0 0 0.0 0 +chr17 72363370 0 0 0.0 0 +chr17 72366014 0 0 0.0 0 +chr17 72591881 0 0 0.0 0 +chr17 72616131 0 0 0.0 0 +chr17 72642441 0 0 0.0 0 +chr17 72750081 0 0 0.0 0 +chr17 72778694 0 0 0.0 0 +chr17 72843911 0 0 0.0 0 +chr17 72914541 0 0 0.0 0 +chr17 72941463 0 0 0.0 0 +chr17 72951548 0 0 0.0 0 +chr17 72960906 0 0 0.0 0 +chr17 72999654 0 0 0.0 0 +chr17 73096220 0 0 0.0 0 +chr17 73105314 0 0 0.0 0 +chr17 73145530 0 0 0.0 0 +chr17 73301550 0 0 0.0 0 +chr17 73352485 0 0 0.0 0 +chr17 73432189 0 0 0.0 0 +chr17 73437781 0 0 0.0 0 +chr17 73535778 0 0 0.0 0 +chr17 73562515 0 0 0.0 0 +chr17 73720426 0 0 0.0 0 +chr17 73723963 0 0 0.0 0 +chr17 73729139 0 0 0.0 0 +chr17 73765676 0 0 0.0 0 +chr17 73805669 0 0 0.0 0 +chr17 73906843 0 0 0.0 0 +chr17 73964843 0 0 0.0 0 +chr17 73977969 0 0 0.0 0 +chr17 73992848 0 0 0.0 0 +chr17 74105246 0 0 0.0 0 +chr17 74126614 0 0 0.0 0 +chr17 74257006 0 0 0.0 0 +chr17 74275934 0 0 0.0 0 +chr17 74288985 0 0 0.0 0 +chr17 74396706 0 0 0.0 0 +chr17 74479530 0 0 0.0 0 +chr17 74611530 0 0 0.0 0 +chr17 74642446 0 0 0.0 0 +chr17 74720063 0 0 0.0 0 +chr17 74735686 0 0 0.0 0 +chr17 74753595 0 0 0.0 0 +chr17 74841659 0 0 0.0 0 +chr17 74959611 0 0 0.0 0 +chr17 74988081 0 0 0.0 0 +chr17 75200913 0 0 0.0 0 +chr17 75219404 0 0 0.0 0 +chr17 75223159 0 0 0.0 0 +chr17 75387242 0 0 0.0 0 +chr17 75405543 0 0 0.0 0 +chr17 75531202 0 0 0.0 0 +chr17 75564431 0 0 0.0 0 +chr17 75624338 0 0 0.0 0 +chr17 75703370 0 0 0.0 0 +chr17 75753751 0 0 0.0 0 +chr17 75861887 0 0 0.0 0 +chr17 75890855 0 0 0.0 0 +chr17 75904905 0 0 0.0 0 +chr17 75959728 0 0 0.0 0 +chr17 76094520 0 0 0.0 0 +chr17 76330602 0 0 0.0 0 +chr17 76405428 0 0 0.0 0 +chr17 76431948 0 0 0.0 0 +chr17 76512442 0 0 0.0 0 +chr17 76531809 0 0 0.0 0 +chr17 76584985 0 0 0.0 0 +chr17 76599167 0 0 0.0 0 +chr17 76662208 0 0 0.0 0 +chr17 76684899 0 0 0.0 0 +chr17 76685388 0 0 0.0 0 +chr17 76699536 0 0 0.0 0 +chr17 76731031 0 1 0.0182 0 +chr17 76768284 2 8 0.1923 1 +chr17 76919070 0 0 0.0 0 +chr17 77053402 0 0 0.0 0 +chr17 77069952 0 0 0.0 0 +chr17 77091792 1 8 0.127 1 +chr17 77270611 0 0 0.0 0 +chr17 77292413 0 0 0.0 0 +chr17 77326639 0 0 0.0 0 +chr17 77438336 0 0 0.0 0 +chr17 77471637 0 0 0.0 0 +chr17 77550125 0 0 0.0 0 +chr17 77566046 0 0 0.0 0 +chr17 77655752 0 0 0.0 0 +chr17 77726261 0 0 0.0 0 +chr17 77727758 0 0 0.0 0 +chr17 77737909 0 0 0.0 0 +chr17 77739365 0 0 0.0 0 +chr17 77752017 0 0 0.0 0 +chr17 77771602 0 0 0.0 0 +chr17 77934473 0 0 0.0 0 +chr17 77985289 0 0 0.0 0 +chr17 78141015 0 0 0.0 0 +chr17 78154943 0 0 0.0 0 +chr17 78269149 0 0 0.0 0 +chr17 78272500 0 0 0.0 0 +chr17 78302267 0 0 0.0 0 +chr17 78396433 0 0 0.0 0 +chr17 78463214 0 0 0.0 0 +chr17 78484628 0 0 0.0 0 +chr17 78564740 0 0 0.0 0 +chr17 78582474 0 0 0.0 0 +chr17 78607646 0 0 0.0 0 +chr17 78749521 0 0 0.0 0 +chr17 78796095 0 1 0.0189 0 +chr17 78840961 0 0 0.0 0 +chr17 78892604 0 0 0.0 0 +chr17 78917804 0 0 0.0 0 +chr17 78940458 0 0 0.0 0 +chr17 78970311 0 0 0.0 0 +chr17 78973345 0 0 0.0 0 +chr17 78974866 0 1 0.0135 0 +chr17 79184263 0 0 0.0 0 +chr17 79207564 0 0 0.0 0 +chr17 79244636 0 0 0.0 0 +chr17 79252826 0 1 0.0109 0 +chr17 79302341 0 0 0.0 0 +chr17 79321967 0 0 0.0 0 +chr17 79386525 0 0 0.0 0 +chr17 79459009 0 0 0.0 0 +chr17 79477951 0 0 0.0 0 +chr17 79517894 0 0 0.0 0 +chr17 79531107 0 0 0.0 0 +chr17 79559031 0 0 0.0 0 +chr17 79801632 0 0 0.0 0 +chr17 79820147 0 0 0.0 0 +chr17 79833835 0 0 0.0 0 +chr17 79851347 0 0 0.0 0 +chr17 79930258 0 0 0.0 0 +chr17 79935249 0 1 0.0189 0 +chr17 79942894 0 0 0.0 0 +chr17 80003369 0 0 0.0 0 +chr17 80102764 0 0 0.0 0 +chr17 80116074 0 0 0.0 0 +chr17 80141799 0 0 0.0 0 +chr17 80259108 0 0 0.0 0 +chr17 80410711 0 0 0.0 0 +chr17 80422464 0 0 0.0 0 +chr17 80447269 0 0 0.0 0 +chr17 80495596 0 0 0.0 0 +chr17 80522146 0 0 0.0 0 +chr17 80540042 0 0 0.0 0 +chr17 80790616 0 0 0.0 0 +chr17 80970670 0 0 0.0 0 +chr17 80989507 0 0 0.0 0 +chr17 81130285 0 0 0.0 0 +chr17 81179252 0 0 0.0 0 +chr17 81217760 0 0 0.0 0 +chr17 81236901 0 0 0.0 0 +chr17 81263322 0 0 0.0 0 +chr17 81298826 0 0 0.0 0 +chr17 81299786 0 0 0.0 0 +chr17 81308942 0 0 0.0 0 +chr17 81317914 0 0 0.0 0 +chr17 81444617 0 0 0.0 0 +chr17 81455559 0 0 0.0 0 +chr17 81551144 0 0 0.0 0 +chr17 81589018 0 0 0.0 0 +chr17 81636746 0 0 0.0 0 +chr17 81679934 0 0 0.0 0 +chr17 81741741 0 0 0.0 0 +chr17 81971701 0 0 0.0 0 +chr17 82003646 0 0 0.0 0 +chr17 82041454 0 1 0.0294 0 +chr17 82094475 0 0 0.0 0 +chr17 82096066 0 0 0.0 0 +chr17 82156604 0 0 0.0 0 +chr17 82168011 0 0 0.0 0 +chr17 82174551 0 0 0.0 0 +chr17 82175893 0 0 0.0 0 +chr17 82218947 0 0 0.0 0 +chr17 82242179 0 0 0.0 0 +chr17 82595652 0 0 0.0 0 +chr17 82704092 0 0 0.0 0 +chr17 82712106 0 0 0.0 0 +chr17 82740396 2 10 0.3704 1 +chr17 82748575 0 0 0.0 0 +chr17 82793988 0 0 0.0 0 +chr17 82822446 0 0 0.0 0 +chr17 82855815 0 0 0.0 0 +chr17 82904481 0 0 0.0 0 +chr17 83050809 2 33 0.6226 1 +chr17 83153595 0 0 0.0 0 +chr17 83212327 0 0 0.0 0 +chr17 83219759 0 0 0.0 0 +chr17 83221191 0 0 0.0 0 +chr17_GL000205v2_random 172844 0 0 0.0 0 +chr17_GL000258v2_alt 5331 0 0 0.0 0 +chr17_GL000258v2_alt 30960 0 0 0.0 0 +chr17_GL000258v2_alt 71228 0 0 0.0 0 +chr17_GL000258v2_alt 241207 0 0 0.0 0 +chr17_GL000258v2_alt 459142 0 0 0.0 0 +chr17_GL000258v2_alt 673517 0 0 0.0 0 +chr17_GL000258v2_alt 777583 0 0 0.0 0 +chr17_GL000258v2_alt 921918 0 0 0.0 0 +chr17_GL000258v2_alt 967065 0 0 0.0 0 +chr17_GL000258v2_alt 994926 0 0 0.0 0 +chr17_GL000258v2_alt 1038544 0 0 0.0 0 +chr17_GL000258v2_alt 1134443 0 0 0.0 0 +chr17_GL000258v2_alt 1496262 0 0 0.0 0 +chr17_GL383563v3_alt 186223 0 0 0.0 0 +chr17_GL383563v3_alt 186473 0 0 0.0 0 +chr17_GL383563v3_alt 186773 0 0 0.0 0 +chr17_GL383563v3_alt 187223 0 0 0.0 0 +chr17_GL383563v3_alt 187523 0 0 0.0 0 +chr17_GL383563v3_alt 301553 0 0 0.0 0 +chr17_GL383563v3_alt 348006 0 0 0.0 0 +chr17_GL383564v2_alt 39104 0 0 0.0 0 +chr17_GL383565v1_alt 39506 0 0 0.0 0 +chr17_GL383566v1_alt 61504 0 0 0.0 0 +chr17_GL383566v1_alt 83306 0 0 0.0 0 +chr17_JH159146v1_alt 88139 0 0 0.0 0 +chr17_KI270729v1_random 6291 0 0 0.0 0 +chr17_KI270729v1_random 258818 0 0 0.0 0 +chr17_KI270729v1_random 261737 0 0 0.0 0 +chr17_KI270730v1_random 59558 0 0 0.0 0 +chr17_KI270730v1_random 62477 0 0 0.0 0 +chr17_KI270730v1_random 83476 1 44 0.4037 1 +chr17_KI270730v1_random 90643 1 3 0.06 1 +chr17_KI270730v1_random 95826 0 0 0.0 0 +chr17_KI270730v1_random 106811 1 22 0.6471 1 +chr17_KI270857v1_alt 154475 0 0 0.0 0 +chr17_KI270857v1_alt 298380 0 0 0.0 0 +chr17_KI270857v1_alt 419512 0 0 0.0 0 +chr17_KI270857v1_alt 484214 0 0 0.0 0 +chr17_KI270857v1_alt 608106 0 0 0.0 0 +chr17_KI270857v1_alt 630795 0 0 0.0 0 +chr17_KI270857v1_alt 659187 0 0 0.0 0 +chr17_KI270857v1_alt 695296 0 0 0.0 0 +chr17_KI270857v1_alt 832425 0 0 0.0 0 +chr17_KI270857v1_alt 846829 0 0 0.0 0 +chr17_KI270857v1_alt 915037 0 0 0.0 0 +chr17_KI270857v1_alt 962681 0 0 0.0 0 +chr17_KI270857v1_alt 1477149 0 0 0.0 0 +chr17_KI270857v1_alt 1512048 0 0 0.0 0 +chr17_KI270857v1_alt 1598354 0 0 0.0 0 +chr17_KI270857v1_alt 1806600 0 0 0.0 0 +chr17_KI270857v1_alt 1884881 0 0 0.0 0 +chr17_KI270857v1_alt 2031255 0 0 0.0 0 +chr17_KI270857v1_alt 2034570 0 0 0.0 0 +chr17_KI270857v1_alt 2056664 0 0 0.0 0 +chr17_KI270857v1_alt 2155612 0 0 0.0 0 +chr17_KI270857v1_alt 2212447 0 0 0.0 0 +chr17_KI270857v1_alt 2359029 0 0 0.0 0 +chr17_KI270857v1_alt 2372774 0 0 0.0 0 +chr17_KI270857v1_alt 2466692 0 0 0.0 0 +chr17_KI270857v1_alt 2489870 0 0 0.0 0 +chr17_KI270857v1_alt 2529507 0 0 0.0 0 +chr17_KI270857v1_alt 2624422 0 0 0.0 0 +chr17_KI270857v1_alt 2712694 0 0 0.0 0 +chr17_KI270857v1_alt 2821528 0 0 0.0 0 +chr17_KI270857v1_alt 2832232 0 0 0.0 0 +chr17_KI270859v1_alt 10588 0 0 0.0 0 +chr17_KI270859v1_alt 87560 0 0 0.0 0 +chr17_KI270860v1_alt 52131 0 0 0.0 0 +chr17_KI270861v1_alt 72603 0 0 0.0 0 +chr17_KI270862v1_alt 56099 0 0 0.0 0 +chr17_KI270862v1_alt 246516 0 0 0.0 0 +chr17_KI270862v1_alt 350356 0 0 0.0 0 +chr17_KI270862v1_alt 368514 0 0 0.0 0 +chr17_KI270907v1_alt 27686 0 0 0.0 0 +chr17_KI270907v1_alt 72519 0 0 0.0 0 +chr17_KI270908v1_alt 5331 0 0 0.0 0 +chr17_KI270908v1_alt 30960 0 0 0.0 0 +chr17_KI270908v1_alt 71226 0 0 0.0 0 +chr17_KI270908v1_alt 255022 0 0 0.0 0 +chr17_KI270908v1_alt 355644 0 0 0.0 0 +chr17_KI270908v1_alt 451668 0 0 0.0 0 +chr17_KI270908v1_alt 495354 0 0 0.0 0 +chr17_KI270908v1_alt 523247 0 0 0.0 0 +chr17_KI270908v1_alt 713170 0 0 0.0 0 +chr17_KI270908v1_alt 815275 0 0 0.0 0 +chr17_KI270908v1_alt 1029858 0 0 0.0 0 +chr17_KI270908v1_alt 1369178 0 0 0.0 0 +chr17_KI270908v1_alt 1384763 0 0 0.0 0 +chr17_KI270909v1_alt 17589 0 0 0.0 0 +chr17_KI270909v1_alt 138718 0 0 0.0 0 +chr17_KI270909v1_alt 203491 0 0 0.0 0 +chr17_KI270909v1_alt 226780 0 0 0.0 0 +chr17_KI270909v1_alt 240307 0 0 0.0 0 +chr17_KI270909v1_alt 305053 0 0 0.0 0 +chr17_KI270910v1_alt 56099 0 0 0.0 0 +chr18 26222 0 0 0.0 0 +chr18 49138 0 0 0.0 0 +chr18 156370 0 0 0.0 0 +chr18 182884 0 0 0.0 0 +chr18 218376 0 0 0.0 0 +chr18 388808 0 0 0.0 0 +chr18 415740 0 0 0.0 0 +chr18 453081 0 0 0.0 0 +chr18 477830 0 0 0.0 0 +chr18 628400 0 0 0.0 0 +chr18 659019 0 0 0.0 0 +chr18 867608 0 0 0.0 0 +chr18 883583 0 0 0.0 0 +chr18 925081 0 0 0.0 0 +chr18 955027 0 0 0.0 0 +chr18 1035048 0 0 0.0 0 +chr18 1071945 0 0 0.0 0 +chr18 1127823 0 0 0.0 0 +chr18 1157158 0 0 0.0 0 +chr18 1198730 0 0 0.0 0 +chr18 1250913 0 0 0.0 0 +chr18 1308825 0 0 0.0 0 +chr18 1417057 0 0 0.0 0 +chr18 1482232 0 0 0.0 0 +chr18 1858602 0 0 0.0 0 +chr18 1954911 0 0 0.0 0 +chr18 2045118 0 0 0.0 0 +chr18 2111620 0 0 0.0 0 +chr18 2125915 0 0 0.0 0 +chr18 2185503 0 0 0.0 0 +chr18 2285509 0 0 0.0 0 +chr18 2468483 0 0 0.0 0 +chr18 2597918 0 0 0.0 0 +chr18 2765631 0 0 0.0 0 +chr18 2855298 0 0 0.0 0 +chr18 2876242 0 0 0.0 0 +chr18 2920090 0 0 0.0 0 +chr18 3044312 0 0 0.0 0 +chr18 3116069 0 0 0.0 0 +chr18 3148605 0 0 0.0 0 +chr18 3219535 0 1 0.0167 0 +chr18 3283016 0 0 0.0 0 +chr18 3338314 0 0 0.0 0 +chr18 3350447 0 0 0.0 0 +chr18 3393315 0 0 0.0 0 +chr18 3399221 0 0 0.0 0 +chr18 3684461 0 0 0.0 0 +chr18 3827158 0 0 0.0 0 +chr18 3870742 0 0 0.0 0 +chr18 4043786 0 0 0.0 0 +chr18 4116967 0 0 0.0 0 +chr18 4479613 0 0 0.0 0 +chr18 4652633 0 0 0.0 0 +chr18 5192788 0 0 0.0 0 +chr18 5199574 0 0 0.0 0 +chr18 5471389 0 0 0.0 0 +chr18 5615644 0 0 0.0 0 +chr18 5617000 0 0 0.0 0 +chr18 5716190 0 1 0.0141 0 +chr18 5769843 0 0 0.0 0 +chr18 5937423 0 0 0.0 0 +chr18 6080309 0 0 0.0 0 +chr18 6086277 0 0 0.0 0 +chr18 6224884 0 0 0.0 0 +chr18 6526042 0 0 0.0 0 +chr18 6573284 0 0 0.0 0 +chr18 6670303 0 0 0.0 0 +chr18 6770745 0 1 0.0263 0 +chr18 6955063 0 0 0.0 0 +chr18 6967639 0 0 0.0 0 +chr18 6973738 0 0 0.0 0 +chr18 7361005 0 0 0.0 0 +chr18 7634464 0 1 0.0143 0 +chr18 8191910 0 1 0.0192 0 +chr18 8314983 0 0 0.0 0 +chr18 8466441 0 0 0.0 0 +chr18 8469714 0 0 0.0 0 +chr18 8548699 0 0 0.0 0 +chr18 8583699 0 0 0.0 0 +chr18 8636184 0 0 0.0 0 +chr18 8644069 0 0 0.0 0 +chr18 8841504 0 0 0.0 0 +chr18 8882330 0 1 0.0185 0 +chr18 9041322 0 0 0.0 0 +chr18 9206835 0 0 0.0 0 +chr18 9285713 0 0 0.0 0 +chr18 9438424 0 0 0.0 0 +chr18 9477424 0 0 0.0 0 +chr18 9540700 0 0 0.0 0 +chr18 9677052 0 0 0.0 0 +chr18 9766329 0 0 0.0 0 +chr18 9869455 0 0 0.0 0 +chr18 9943814 0 1 0.0833 0 +chr18 10159570 0 0 0.0 0 +chr18 10196598 0 0 0.0 0 +chr18 10196954 0 0 0.0 0 +chr18 10213810 0 0 0.0 0 +chr18 10372327 0 0 0.0 0 +chr18 10468649 0 0 0.0 0 +chr18 10473025 0 0 0.0 0 +chr18 10723917 0 0 0.0 0 +chr18 10739476 0 0 0.0 0 +chr18 10758285 0 0 0.0 0 +chr18 11039479 0 0 0.0 0 +chr18 11129970 0 0 0.0 0 +chr18 11166500 0 0 0.0 0 +chr18 11286840 0 0 0.0 0 +chr18 11516835 0 0 0.0 0 +chr18 11550843 0 0 0.0 0 +chr18 11577067 0 0 0.0 0 +chr18 12012451 0 0 0.0 0 +chr18 12063181 0 0 0.0 0 +chr18 12376201 0 0 0.0 0 +chr18 12460055 0 0 0.0 0 +chr18 12758749 0 0 0.0 0 +chr18 12768263 0 0 0.0 0 +chr18 12789342 0 0 0.0 0 +chr18 12900248 0 0 0.0 0 +chr18 12938403 0 0 0.0 0 +chr18 12947069 0 0 0.0 0 +chr18 13118955 0 0 0.0 0 +chr18 13125486 0 0 0.0 0 +chr18 13134699 0 0 0.0 0 +chr18 13299476 0 0 0.0 0 +chr18 13302623 0 0 0.0 0 +chr18 13321069 0 0 0.0 0 +chr18 13390332 0 0 0.0 0 +chr18 13395968 0 0 0.0 0 +chr18 13446788 0 0 0.0 0 +chr18 13509379 0 0 0.0 0 +chr18 13550616 0 0 0.0 0 +chr18 13554919 0 0 0.0 0 +chr18 13566834 0 0 0.0 0 +chr18 13567290 0 0 0.0 0 +chr18 13589624 0 0 0.0 0 +chr18 13594447 0 0 0.0 0 +chr18 13601710 0 0 0.0 0 +chr18 13620532 0 0 0.0 0 +chr18 13721646 0 0 0.0 0 +chr18 13817568 0 0 0.0 0 +chr18 13863106 0 0 0.0 0 +chr18 13888682 0 0 0.0 0 +chr18 14025949 0 0 0.0 0 +chr18 14028678 0 0 0.0 0 +chr18 14036778 0 0 0.0 0 +chr18 14090074 0 0 0.0 0 +chr18 14126863 0 0 0.0 0 +chr18 14267850 0 0 0.0 0 +chr18 14295357 0 0 0.0 0 +chr18 14308155 0 0 0.0 0 +chr18 14329457 0 0 0.0 0 +chr18 14670773 0 0 0.0 0 +chr18 15002596 0 0 0.0 0 +chr18 15147518 0 0 0.0 0 +chr18 15311846 0 1 0.0127 0 +chr18 15364488 0 0 0.0 0 +chr18 15389338 0 0 0.0 0 +chr18 15406424 0 0 0.0 0 +chr18 15410184 0 0 0.0 0 +chr18 20976118 0 0 0.0 0 +chr18 20998098 0 0 0.0 0 +chr18 21067694 0 0 0.0 0 +chr18 21244607 0 0 0.0 0 +chr18 21291111 0 0 0.0 0 +chr18 21596907 0 0 0.0 0 +chr18 21603035 0 0 0.0 0 +chr18 21615372 0 0 0.0 0 +chr18 21652811 0 0 0.0 0 +chr18 21780168 0 0 0.0 0 +chr18 22430315 0 0 0.0 0 +chr18 22517641 0 0 0.0 0 +chr18 22559607 0 0 0.0 0 +chr18 22592751 0 0 0.0 0 +chr18 22685915 0 0 0.0 0 +chr18 22696069 0 0 0.0 0 +chr18 22871503 0 0 0.0 0 +chr18 22872618 0 0 0.0 0 +chr18 23060400 0 0 0.0 0 +chr18 23076799 0 0 0.0 0 +chr18 23077828 0 0 0.0 0 +chr18 23114793 0 0 0.0 0 +chr18 23161576 0 0 0.0 0 +chr18 23267195 0 0 0.0 0 +chr18 23295910 0 0 0.0 0 +chr18 23317319 0 0 0.0 0 +chr18 23393880 0 0 0.0 0 +chr18 23434020 0 0 0.0 0 +chr18 23479024 0 0 0.0 0 +chr18 23489720 0 0 0.0 0 +chr18 23665832 0 0 0.0 0 +chr18 23702080 0 0 0.0 0 +chr18 23790524 0 0 0.0 0 +chr18 23830519 0 0 0.0 0 +chr18 24284182 0 0 0.0 0 +chr18 24329247 0 0 0.0 0 +chr18 24400146 0 0 0.0 0 +chr18 24486603 0 0 0.0 0 +chr18 24534251 0 0 0.0 0 +chr18 24538906 0 0 0.0 0 +chr18 24564445 0 0 0.0 0 +chr18 24729823 0 0 0.0 0 +chr18 24808086 0 0 0.0 0 +chr18 25037103 0 0 0.0 0 +chr18 25037997 0 0 0.0 0 +chr18 25059702 0 0 0.0 0 +chr18 25086908 0 0 0.0 0 +chr18 25139513 0 0 0.0 0 +chr18 25337887 0 0 0.0 0 +chr18 25380378 0 0 0.0 0 +chr18 25499048 0 0 0.0 0 +chr18 25610505 0 0 0.0 0 +chr18 25619054 0 0 0.0 0 +chr18 25713109 0 0 0.0 0 +chr18 25830923 0 0 0.0 0 +chr18 26031853 0 0 0.0 0 +chr18 26206493 0 0 0.0 0 +chr18 26360661 0 0 0.0 0 +chr18 26451280 0 0 0.0 0 +chr18 26571077 0 0 0.0 0 +chr18 26683315 0 0 0.0 0 +chr18 26742738 0 0 0.0 0 +chr18 26868052 0 0 0.0 0 +chr18 26923577 0 0 0.0 0 +chr18 27324128 0 0 0.0 0 +chr18 27331392 0 0 0.0 0 +chr18 27570836 0 0 0.0 0 +chr18 27595948 0 0 0.0 0 +chr18 27618650 0 0 0.0 0 +chr18 27660130 0 0 0.0 0 +chr18 27710108 0 0 0.0 0 +chr18 27838508 0 0 0.0 0 +chr18 27953825 0 0 0.0 0 +chr18 27978917 0 0 0.0 0 +chr18 28077463 0 0 0.0 0 +chr18 28377721 0 0 0.0 0 +chr18 28576444 0 0 0.0 0 +chr18 28578540 0 0 0.0 0 +chr18 28865391 0 0 0.0 0 +chr18 28917319 0 0 0.0 0 +chr18 29053633 0 0 0.0 0 +chr18 29398918 0 0 0.0 0 +chr18 29704051 0 0 0.0 0 +chr18 29750936 0 0 0.0 0 +chr18 29790093 0 0 0.0 0 +chr18 29827623 0 0 0.0 0 +chr18 29937176 0 0 0.0 0 +chr18 30081672 0 0 0.0 0 +chr18 30180882 0 0 0.0 0 +chr18 30245283 0 0 0.0 0 +chr18 30366336 0 0 0.0 0 +chr18 30370779 0 0 0.0 0 +chr18 30389430 0 1 0.0169 0 +chr18 30428051 0 0 0.0 0 +chr18 30440778 0 0 0.0 0 +chr18 30541607 0 0 0.0 0 +chr18 30555309 0 0 0.0 0 +chr18 30673129 0 0 0.0 0 +chr18 30784726 0 0 0.0 0 +chr18 30853394 0 0 0.0 0 +chr18 30879472 0 0 0.0 0 +chr18 30880031 0 0 0.0 0 +chr18 31008088 0 0 0.0 0 +chr18 31074785 0 0 0.0 0 +chr18 31225029 0 0 0.0 0 +chr18 31227823 0 0 0.0 0 +chr18 31485046 0 1 0.0128 0 +chr18 31487971 0 0 0.0 0 +chr18 31559919 0 0 0.0 0 +chr18 31936117 0 0 0.0 0 +chr18 31950408 0 0 0.0 0 +chr18 31956418 0 0 0.0 0 +chr18 32126380 0 0 0.0 0 +chr18 32167529 0 0 0.0 0 +chr18 32244006 0 0 0.0 0 +chr18 32753454 0 0 0.0 0 +chr18 32773437 0 0 0.0 0 +chr18 32789083 0 0 0.0 0 +chr18 32905633 0 0 0.0 0 +chr18 32907763 0 0 0.0 0 +chr18 32915580 0 0 0.0 0 +chr18 33038691 0 0 0.0 0 +chr18 33317262 0 0 0.0 0 +chr18 33491048 0 0 0.0 0 +chr18 33495545 0 0 0.0 0 +chr18 33675067 0 0 0.0 0 +chr18 33838182 0 0 0.0 0 +chr18 33884043 0 0 0.0 0 +chr18 33890924 0 0 0.0 0 +chr18 33891413 0 0 0.0 0 +chr18 33952442 0 0 0.0 0 +chr18 33995223 0 0 0.0 0 +chr18 34279368 0 0 0.0 0 +chr18 34297142 0 0 0.0 0 +chr18 34359150 0 0 0.0 0 +chr18 34360387 0 0 0.0 0 +chr18 34397976 0 0 0.0 0 +chr18 34602635 0 0 0.0 0 +chr18 34767724 1 56 0.8358 1 +chr18 34890373 0 0 0.0 0 +chr18 35126980 0 0 0.0 0 +chr18 35184803 0 0 0.0 0 +chr18 35215363 0 0 0.0 0 +chr18 35241127 0 0 0.0 0 +chr18 35280166 0 0 0.0 0 +chr18 35290474 0 0 0.0 0 +chr18 35376787 0 0 0.0 0 +chr18 35385314 0 0 0.0 0 +chr18 35497972 0 0 0.0 0 +chr18 35706713 0 0 0.0 0 +chr18 35715301 0 0 0.0 0 +chr18 35973253 0 0 0.0 0 +chr18 36032496 0 0 0.0 0 +chr18 36039842 0 1 0.0175 0 +chr18 36045024 0 0 0.0 0 +chr18 36101589 0 0 0.0 0 +chr18 36176792 0 0 0.0 0 +chr18 36316036 0 0 0.0 0 +chr18 36409988 0 0 0.0 0 +chr18 36441205 0 0 0.0 0 +chr18 36441575 0 0 0.0 0 +chr18 36635844 0 0 0.0 0 +chr18 36773676 0 0 0.0 0 +chr18 36798146 0 0 0.0 0 +chr18 36895872 0 0 0.0 0 +chr18 37112721 0 0 0.0 0 +chr18 37218358 0 0 0.0 0 +chr18 37265578 0 0 0.0 0 +chr18 37304014 0 0 0.0 0 +chr18 37326656 0 0 0.0 0 +chr18 37341282 0 0 0.0 0 +chr18 37378169 0 0 0.0 0 +chr18 37395951 0 0 0.0 0 +chr18 37457944 0 0 0.0 0 +chr18 37517863 0 0 0.0 0 +chr18 37542995 0 0 0.0 0 +chr18 37569077 0 0 0.0 0 +chr18 37850305 0 0 0.0 0 +chr18 37856100 0 0 0.0 0 +chr18 37970627 0 0 0.0 0 +chr18 38049524 0 0 0.0 0 +chr18 38224959 0 0 0.0 0 +chr18 38507196 0 0 0.0 0 +chr18 39014692 0 0 0.0 0 +chr18 39273760 0 0 0.0 0 +chr18 39408171 0 0 0.0 0 +chr18 39495661 0 0 0.0 0 +chr18 39658326 0 0 0.0 0 +chr18 39681469 0 0 0.0 0 +chr18 39873751 0 0 0.0 0 +chr18 40274830 0 0 0.0 0 +chr18 40475862 0 1 0.0154 0 +chr18 40799348 0 0 0.0 0 +chr18 40856157 0 0 0.0 0 +chr18 40985602 0 0 0.0 0 +chr18 41144378 0 0 0.0 0 +chr18 41228032 0 0 0.0 0 +chr18 41228763 0 1 0.0278 0 +chr18 41370678 0 0 0.0 0 +chr18 41616951 0 0 0.0 0 +chr18 41654848 0 0 0.0 0 +chr18 41748885 0 0 0.0 0 +chr18 41879839 0 0 0.0 0 +chr18 41933822 0 0 0.0 0 +chr18 42365348 0 0 0.0 0 +chr18 42451627 0 0 0.0 0 +chr18 42509202 0 0 0.0 0 +chr18 42525063 0 0 0.0 0 +chr18 42600676 0 0 0.0 0 +chr18 42755083 0 0 0.0 0 +chr18 42881181 0 0 0.0 0 +chr18 42956248 0 0 0.0 0 +chr18 43091234 0 0 0.0 0 +chr18 43137215 0 0 0.0 0 +chr18 43220549 0 0 0.0 0 +chr18 43512549 0 0 0.0 0 +chr18 43791712 0 0 0.0 0 +chr18 43911436 0 0 0.0 0 +chr18 44046559 0 0 0.0 0 +chr18 44344369 0 0 0.0 0 +chr18 44349946 0 0 0.0 0 +chr18 44391977 0 0 0.0 0 +chr18 44779016 0 0 0.0 0 +chr18 44833426 0 0 0.0 0 +chr18 44959823 0 0 0.0 0 +chr18 44970213 0 0 0.0 0 +chr18 44981768 0 0 0.0 0 +chr18 45158877 0 0 0.0 0 +chr18 45203012 0 0 0.0 0 +chr18 45418552 0 0 0.0 0 +chr18 45453304 0 0 0.0 0 +chr18 45781597 0 0 0.0 0 +chr18 45826769 0 0 0.0 0 +chr18 45829786 0 0 0.0 0 +chr18 46118831 0 0 0.0 0 +chr18 46144708 0 0 0.0 0 +chr18 46182421 0 0 0.0 0 +chr18 46265704 0 0 0.0 0 +chr18 46340156 0 0 0.0 0 +chr18 46355299 0 0 0.0 0 +chr18 46399689 0 0 0.0 0 +chr18 46682472 0 1 0.0238 0 +chr18 47051637 0 0 0.0 0 +chr18 47201722 0 0 0.0 0 +chr18 47209881 0 0 0.0 0 +chr18 47328506 0 0 0.0 0 +chr18 47383369 0 0 0.0 0 +chr18 47391096 0 0 0.0 0 +chr18 47396890 0 0 0.0 0 +chr18 47417573 0 0 0.0 0 +chr18 47532150 0 0 0.0 0 +chr18 47651094 0 0 0.0 0 +chr18 47767936 0 0 0.0 0 +chr18 47773715 0 0 0.0 0 +chr18 47795533 0 0 0.0 0 +chr18 47953875 0 0 0.0 0 +chr18 47991708 0 0 0.0 0 +chr18 48035521 0 0 0.0 0 +chr18 48035881 0 0 0.0 0 +chr18 48131152 0 0 0.0 0 +chr18 48148600 0 0 0.0 0 +chr18 48190460 0 0 0.0 0 +chr18 48205539 0 0 0.0 0 +chr18 48245734 0 0 0.0 0 +chr18 48385934 0 0 0.0 0 +chr18 48412509 0 0 0.0 0 +chr18 48442789 0 0 0.0 0 +chr18 48581462 0 0 0.0 0 +chr18 48628328 0 0 0.0 0 +chr18 48663740 0 0 0.0 0 +chr18 48674488 0 0 0.0 0 +chr18 48730921 0 0 0.0 0 +chr18 48824299 0 0 0.0 0 +chr18 48869416 0 0 0.0 0 +chr18 48871250 0 0 0.0 0 +chr18 48978549 0 0 0.0 0 +chr18 48995481 0 0 0.0 0 +chr18 49003835 0 0 0.0 0 +chr18 49349930 0 0 0.0 0 +chr18 49446649 0 0 0.0 0 +chr18 49488167 0 0 0.0 0 +chr18 49589170 0 0 0.0 0 +chr18 49700967 0 0 0.0 0 +chr18 49708314 0 0 0.0 0 +chr18 49751483 0 0 0.0 0 +chr18 49757301 0 0 0.0 0 +chr18 49819698 0 0 0.0 0 +chr18 50006301 0 0 0.0 0 +chr18 50130755 0 0 0.0 0 +chr18 50198409 0 0 0.0 0 +chr18 50230307 0 0 0.0 0 +chr18 50295574 0 0 0.0 0 +chr18 50543030 0 0 0.0 0 +chr18 50716940 0 0 0.0 0 +chr18 50729696 0 0 0.0 0 +chr18 50750863 0 0 0.0 0 +chr18 50775095 0 0 0.0 0 +chr18 50966536 0 0 0.0 0 +chr18 51017345 0 0 0.0 0 +chr18 51194289 0 0 0.0 0 +chr18 51586348 0 0 0.0 0 +chr18 51658718 0 0 0.0 0 +chr18 51720042 0 0 0.0 0 +chr18 52049294 0 0 0.0 0 +chr18 52133566 0 0 0.0 0 +chr18 52156454 0 0 0.0 0 +chr18 52216307 0 0 0.0 0 +chr18 52380740 0 0 0.0 0 +chr18 52424264 0 0 0.0 0 +chr18 52633405 0 0 0.0 0 +chr18 52668905 0 0 0.0 0 +chr18 52707546 0 0 0.0 0 +chr18 52709112 0 1 0.02 0 +chr18 52821854 0 0 0.0 0 +chr18 52842683 0 0 0.0 0 +chr18 52958099 0 0 0.0 0 +chr18 52972286 0 0 0.0 0 +chr18 52983319 0 0 0.0 0 +chr18 53150613 0 0 0.0 0 +chr18 53400214 0 0 0.0 0 +chr18 53496303 0 0 0.0 0 +chr18 53641665 0 0 0.0 0 +chr18 53676633 1 5 0.2174 1 +chr18 53722019 0 0 0.0 0 +chr18 53821748 0 0 0.0 0 +chr18 53882283 0 0 0.0 0 +chr18 53898853 0 0 0.0 0 +chr18 53934451 0 0 0.0 0 +chr18 54029837 0 0 0.0 0 +chr18 54059418 0 0 0.0 0 +chr18 54200836 0 0 0.0 0 +chr18 54219629 0 0 0.0 0 +chr18 54346114 0 0 0.0 0 +chr18 54457675 0 0 0.0 0 +chr18 54463566 0 0 0.0 0 +chr18 54595551 0 0 0.0 0 +chr18 54597830 0 0 0.0 0 +chr18 55143674 0 0 0.0 0 +chr18 55161555 0 1 0.0238 0 +chr18 55171496 0 0 0.0 0 +chr18 55265384 0 0 0.0 0 +chr18 55521628 0 0 0.0 0 +chr18 55560961 0 0 0.0 0 +chr18 55605895 0 0 0.0 0 +chr18 55697494 0 0 0.0 0 +chr18 55973412 0 1 0.0167 0 +chr18 56010955 0 0 0.0 0 +chr18 56106075 0 0 0.0 0 +chr18 56275076 0 0 0.0 0 +chr18 56291379 0 0 0.0 0 +chr18 56292468 0 0 0.0 0 +chr18 56313077 0 0 0.0 0 +chr18 56495769 0 1 0.0233 0 +chr18 56635596 0 0 0.0 0 +chr18 56681067 0 0 0.0 0 +chr18 56696033 0 0 0.0 0 +chr18 56843567 0 0 0.0 0 +chr18 56860040 0 0 0.0 0 +chr18 56861515 0 0 0.0 0 +chr18 56909016 0 1 0.0196 0 +chr18 56932516 0 0 0.0 0 +chr18 56982266 0 0 0.0 0 +chr18 57254890 0 0 0.0 0 +chr18 57315014 0 0 0.0 0 +chr18 57480648 0 0 0.0 0 +chr18 57599628 0 0 0.0 0 +chr18 57712974 0 0 0.0 0 +chr18 57760444 0 0 0.0 0 +chr18 57942270 0 0 0.0 0 +chr18 57996734 0 0 0.0 0 +chr18 58059353 0 0 0.0 0 +chr18 58123090 0 0 0.0 0 +chr18 58140954 0 0 0.0 0 +chr18 58184649 0 0 0.0 0 +chr18 58191750 0 0 0.0 0 +chr18 58242629 0 0 0.0 0 +chr18 58273001 0 0 0.0 0 +chr18 58291283 0 0 0.0 0 +chr18 58302286 0 0 0.0 0 +chr18 58309849 0 0 0.0 0 +chr18 58324480 0 0 0.0 0 +chr18 58371436 0 0 0.0 0 +chr18 58387320 0 0 0.0 0 +chr18 58405228 0 0 0.0 0 +chr18 58406315 0 0 0.0 0 +chr18 58440853 0 0 0.0 0 +chr18 58557297 0 0 0.0 0 +chr18 58827169 0 0 0.0 0 +chr18 58955148 0 0 0.0 0 +chr18 59069665 0 0 0.0 0 +chr18 59141734 0 0 0.0 0 +chr18 59297662 0 0 0.0 0 +chr18 59418761 0 0 0.0 0 +chr18 59499542 0 0 0.0 0 +chr18 59650988 0 0 0.0 0 +chr18 59653617 0 0 0.0 0 +chr18 59660988 1 32 0.4706 1 +chr18 59792328 0 0 0.0 0 +chr18 59873588 0 0 0.0 0 +chr18 60010608 0 0 0.0 0 +chr18 60142926 0 0 0.0 0 +chr18 60594046 0 0 0.0 0 +chr18 60606909 0 0 0.0 0 +chr18 60866945 0 0 0.0 0 +chr18 61047123 0 0 0.0 0 +chr18 61389847 0 0 0.0 0 +chr18 61394767 0 0 0.0 0 +chr18 61481103 0 0 0.0 0 +chr18 61688322 0 0 0.0 0 +chr18 61696945 0 0 0.0 0 +chr18 61754845 0 0 0.0 0 +chr18 61783791 0 0 0.0 0 +chr18 61855511 0 0 0.0 0 +chr18 61950970 0 0 0.0 0 +chr18 61959928 0 2 0.0526 0 +chr18 62208065 0 0 0.0 0 +chr18 62252965 0 0 0.0 0 +chr18 62292676 0 0 0.0 0 +chr18 62383183 0 0 0.0 0 +chr18 62392143 0 0 0.0 0 +chr18 62689788 0 0 0.0 0 +chr18 62735172 0 0 0.0 0 +chr18 62803732 0 0 0.0 0 +chr18 62959424 0 0 0.0 0 +chr18 62987817 0 0 0.0 0 +chr18 62996321 0 0 0.0 0 +chr18 63030716 0 0 0.0 0 +chr18 63044903 0 0 0.0 0 +chr18 63062514 0 0 0.0 0 +chr18 63080390 0 0 0.0 0 +chr18 63100621 0 0 0.0 0 +chr18 63154279 0 0 0.0 0 +chr18 63255968 0 1 0.0286 0 +chr18 63297137 0 0 0.0 0 +chr18 63661298 0 0 0.0 0 +chr18 63846083 0 0 0.0 0 +chr18 64043343 0 0 0.0 0 +chr18 64069446 0 1 0.0182 0 +chr18 64418460 0 1 0.0182 0 +chr18 64589336 0 0 0.0 0 +chr18 64593283 0 0 0.0 0 +chr18 64629832 0 0 0.0 0 +chr18 64635635 0 0 0.0 0 +chr18 64840926 0 0 0.0 0 +chr18 64931502 0 0 0.0 0 +chr18 65084747 0 0 0.0 0 +chr18 65102223 0 0 0.0 0 +chr18 65127268 0 0 0.0 0 +chr18 65136387 0 0 0.0 0 +chr18 65146490 0 0 0.0 0 +chr18 65272689 0 0 0.0 0 +chr18 65441578 0 0 0.0 0 +chr18 65642950 0 0 0.0 0 +chr18 65679772 0 0 0.0 0 +chr18 65850748 0 0 0.0 0 +chr18 65903556 0 0 0.0 0 +chr18 65931227 0 0 0.0 0 +chr18 65934161 0 0 0.0 0 +chr18 66218516 0 0 0.0 0 +chr18 66252946 0 0 0.0 0 +chr18 66279213 0 0 0.0 0 +chr18 66529905 0 0 0.0 0 +chr18 68289008 0 0 0.0 0 +chr18 68329556 0 0 0.0 0 +chr18 68490284 0 0 0.0 0 +chr18 68522988 0 0 0.0 0 +chr18 68707271 0 0 0.0 0 +chr18 68944125 0 0 0.0 0 +chr18 68966927 0 0 0.0 0 +chr18 69517323 0 0 0.0 0 +chr18 69586818 0 0 0.0 0 +chr18 69704254 0 0 0.0 0 +chr18 69836733 0 0 0.0 0 +chr18 69895965 0 0 0.0 0 +chr18 70104779 0 0 0.0 0 +chr18 70110855 0 0 0.0 0 +chr18 70144613 0 0 0.0 0 +chr18 70180212 0 0 0.0 0 +chr18 70292915 0 0 0.0 0 +chr18 70492429 0 0 0.0 0 +chr18 70829194 0 0 0.0 0 +chr18 70936120 0 0 0.0 0 +chr18 71041597 0 0 0.0 0 +chr18 71110492 0 0 0.0 0 +chr18 71195075 0 0 0.0 0 +chr18 71355014 0 0 0.0 0 +chr18 71405479 0 0 0.0 0 +chr18 71440455 0 0 0.0 0 +chr18 71481115 0 0 0.0 0 +chr18 71482245 0 0 0.0 0 +chr18 71482879 0 0 0.0 0 +chr18 71642646 0 0 0.0 0 +chr18 71772831 0 0 0.0 0 +chr18 71797651 0 0 0.0 0 +chr18 71849407 0 0 0.0 0 +chr18 71858810 0 0 0.0 0 +chr18 72055368 0 0 0.0 0 +chr18 72142602 0 0 0.0 0 +chr18 72201757 0 0 0.0 0 +chr18 72316896 0 0 0.0 0 +chr18 72328379 0 0 0.0 0 +chr18 72379144 0 0 0.0 0 +chr18 72428247 0 0 0.0 0 +chr18 72535603 0 0 0.0 0 +chr18 72863624 0 1 0.02 0 +chr18 72923010 0 0 0.0 0 +chr18 73174814 0 0 0.0 0 +chr18 73255521 0 0 0.0 0 +chr18 73409493 0 0 0.0 0 +chr18 73695287 0 0 0.0 0 +chr18 73949766 0 0 0.0 0 +chr18 73961239 0 0 0.0 0 +chr18 74228386 0 0 0.0 0 +chr18 74391968 0 0 0.0 0 +chr18 74415361 0 0 0.0 0 +chr18 74428903 0 0 0.0 0 +chr18 74435338 0 0 0.0 0 +chr18 74545033 0 0 0.0 0 +chr18 74873633 0 0 0.0 0 +chr18 75027524 0 0 0.0 0 +chr18 75063999 0 0 0.0 0 +chr18 75075407 0 0 0.0 0 +chr18 75098368 0 1 0.0278 0 +chr18 75112962 0 0 0.0 0 +chr18 75201707 0 0 0.0 0 +chr18 75221012 0 0 0.0 0 +chr18 75360665 0 0 0.0 0 +chr18 75373170 0 0 0.0 0 +chr18 75383861 0 0 0.0 0 +chr18 75540639 0 0 0.0 0 +chr18 75608093 0 0 0.0 0 +chr18 75754850 0 0 0.0 0 +chr18 75771201 0 0 0.0 0 +chr18 75826425 0 0 0.0 0 +chr18 75978576 0 0 0.0 0 +chr18 76134139 0 0 0.0 0 +chr18 76144023 0 0 0.0 0 +chr18 76169793 0 0 0.0 0 +chr18 76203599 0 0 0.0 0 +chr18 76307326 0 0 0.0 0 +chr18 76312812 0 0 0.0 0 +chr18 76399996 0 0 0.0 0 +chr18 76432741 0 0 0.0 0 +chr18 76434319 0 0 0.0 0 +chr18 76455481 0 0 0.0 0 +chr18 76557584 0 0 0.0 0 +chr18 76585162 0 0 0.0 0 +chr18 76601528 0 0 0.0 0 +chr18 76616748 0 0 0.0 0 +chr18 76637976 0 0 0.0 0 +chr18 76644467 0 0 0.0 0 +chr18 76691320 1 36 1.0 1 +chr18 76772346 0 0 0.0 0 +chr18 76795233 0 0 0.0 0 +chr18 76977522 0 0 0.0 0 +chr18 77077473 0 0 0.0 0 +chr18 77090853 0 0 0.0 0 +chr18 77093253 0 0 0.0 0 +chr18 77134503 0 0 0.0 0 +chr18 77144109 0 0 0.0 0 +chr18 77831382 0 0 0.0 0 +chr18 77837254 0 0 0.0 0 +chr18 77857935 0 0 0.0 0 +chr18 77892890 0 0 0.0 0 +chr18 78168906 0 0 0.0 0 +chr18 78176859 0 0 0.0 0 +chr18 78232136 0 0 0.0 0 +chr18 78464386 0 0 0.0 0 +chr18 78474425 0 1 0.0139 0 +chr18 78475771 0 0 0.0 0 +chr18 78479206 0 0 0.0 0 +chr18 78601067 0 0 0.0 0 +chr18 78601220 0 0 0.0 0 +chr18 78658355 0 1 0.0119 0 +chr18 78660281 0 0 0.0 0 +chr18 78705986 0 0 0.0 0 +chr18 78719967 0 0 0.0 0 +chr18 78896142 0 0 0.0 0 +chr18 78935850 0 0 0.0 0 +chr18 79057312 0 0 0.0 0 +chr18 79132141 0 0 0.0 0 +chr18 79162766 0 0 0.0 0 +chr18 79393461 0 0 0.0 0 +chr18 79435895 0 0 0.0 0 +chr18 79442705 0 0 0.0 0 +chr18 79526975 0 0 0.0 0 +chr18 79527779 0 0 0.0 0 +chr18 79549878 0 0 0.0 0 +chr18 79584173 0 0 0.0 0 +chr18 79657424 0 0 0.0 0 +chr18 79657593 0 0 0.0 0 +chr18 79690488 0 0 0.0 0 +chr18 79715569 0 0 0.0 0 +chr18 79727789 0 0 0.0 0 +chr18 79756078 0 0 0.0 0 +chr18 79814149 0 0 0.0 0 +chr18 79817246 0 0 0.0 0 +chr18 79905591 0 0 0.0 0 +chr18 79939775 0 0 0.0 0 +chr18 80094022 0 0 0.0 0 +chr18 80107476 0 0 0.0 0 +chr18 80150347 0 0 0.0 0 +chr18_GL383567v1_alt 3381 0 0 0.0 0 +chr18_GL383567v1_alt 258069 0 0 0.0 0 +chr18_GL383569v1_alt 107600 0 0 0.0 0 +chr18_GL383570v1_alt 101601 0 0 0.0 0 +chr18_GL383572v1_alt 964 0 0 0.0 0 +chr18_KI270863v1_alt 100056 0 0 0.0 0 +chr18_KI270911v1_alt 964 0 0 0.0 0 +chr18_KI270912v1_alt 107600 0 0 0.0 0 +chr18_KI270912v1_alt 168017 0 0 0.0 0 +chr19 257261 0 0 0.0 0 +chr19 281159 0 0 0.0 0 +chr19 293715 0 0 0.0 0 +chr19 318378 0 0 0.0 0 +chr19 459652 0 2 0.0107 0 +chr19 601602 0 0 0.0 0 +chr19 610397 0 0 0.0 0 +chr19 676383 0 0 0.0 0 +chr19 723431 0 0 0.0 0 +chr19 898726 0 0 0.0 0 +chr19 909847 0 0 0.0 0 +chr19 912695 0 0 0.0 0 +chr19 949022 0 0 0.0 0 +chr19 957173 0 0 0.0 0 +chr19 1007374 0 0 0.0 0 +chr19 1013470 0 0 0.0 0 +chr19 1106090 0 0 0.0 0 +chr19 1182190 0 1 0.0156 0 +chr19 1190368 0 1 0.0167 0 +chr19 1288732 0 0 0.0 0 +chr19 1567572 0 0 0.0 0 +chr19 1599358 0 0 0.0 0 +chr19 1645416 0 0 0.0 0 +chr19 1650755 0 1 0.0125 0 +chr19 1653823 0 0 0.0 0 +chr19 1751350 0 0 0.0 0 +chr19 1828453 0 0 0.0 0 +chr19 1832248 0 0 0.0 0 +chr19 1839461 0 0 0.0 0 +chr19 1847436 0 0 0.0 0 +chr19 1923886 0 0 0.0 0 +chr19 2005539 0 0 0.0 0 +chr19 2072807 0 0 0.0 0 +chr19 2124112 0 0 0.0 0 +chr19 2188408 0 0 0.0 0 +chr19 2247650 0 0 0.0 0 +chr19 2248389 0 0 0.0 0 +chr19 2287827 0 0 0.0 0 +chr19 2309603 0 0 0.0 0 +chr19 2340330 0 0 0.0 0 +chr19 2357011 0 0 0.0 0 +chr19 2357748 0 0 0.0 0 +chr19 2468637 0 0 0.0 0 +chr19 2549550 0 0 0.0 0 +chr19 2586208 0 0 0.0 0 +chr19 2658467 0 0 0.0 0 +chr19 2673183 0 0 0.0 0 +chr19 2713165 0 0 0.0 0 +chr19 2777224 0 0 0.0 0 +chr19 3084815 0 0 0.0 0 +chr19 3153344 0 0 0.0 0 +chr19 3203674 0 0 0.0 0 +chr19 3357151 0 0 0.0 0 +chr19 3484782 1 4 0.0571 1 +chr19 3520578 0 0 0.0 0 +chr19 3522126 0 0 0.0 0 +chr19 3600336 0 0 0.0 0 +chr19 3613779 0 0 0.0 0 +chr19 3670338 0 0 0.0 0 +chr19 3752521 0 0 0.0 0 +chr19 3754054 0 0 0.0 0 +chr19 3805758 0 0 0.0 0 +chr19 3821870 0 0 0.0 0 +chr19 3840057 0 0 0.0 0 +chr19 3928576 0 0 0.0 0 +chr19 3931463 0 0 0.0 0 +chr19 3964879 0 0 0.0 0 +chr19 4025112 0 0 0.0 0 +chr19 4062550 0 0 0.0 0 +chr19 4069538 0 0 0.0 0 +chr19 4135898 0 0 0.0 0 +chr19 4437442 0 0 0.0 0 +chr19 4479208 0 0 0.0 0 +chr19 4521734 0 0 0.0 0 +chr19 4547231 0 0 0.0 0 +chr19 4673936 0 0 0.0 0 +chr19 4675737 0 0 0.0 0 +chr19 4676997 0 0 0.0 0 +chr19 4717925 0 0 0.0 0 +chr19 4721537 0 0 0.0 0 +chr19 4806241 0 0 0.0 0 +chr19 4807293 0 0 0.0 0 +chr19 4811076 0 0 0.0 0 +chr19 4937960 0 0 0.0 0 +chr19 4943440 0 0 0.0 0 +chr19 5064753 0 0 0.0 0 +chr19 5209367 0 0 0.0 0 +chr19 5257351 0 0 0.0 0 +chr19 5435868 0 0 0.0 0 +chr19 5443458 0 0 0.0 0 +chr19 5477506 0 0 0.0 0 +chr19 5537911 0 0 0.0 0 +chr19 5584747 0 0 0.0 0 +chr19 5619128 0 0 0.0 0 +chr19 5658450 0 0 0.0 0 +chr19 5724324 0 0 0.0 0 +chr19 5780787 0 0 0.0 0 +chr19 5806689 0 0 0.0 0 +chr19 5842143 0 0 0.0 0 +chr19 5877295 0 0 0.0 0 +chr19 5974171 0 0 0.0 0 +chr19 6013900 0 0 0.0 0 +chr19 6021818 0 0 0.0 0 +chr19 6105353 0 0 0.0 0 +chr19 6213122 0 1 0.0133 0 +chr19 6213662 0 0 0.0 0 +chr19 6250465 0 0 0.0 0 +chr19 6326219 0 0 0.0 0 +chr19 6326753 0 0 0.0 0 +chr19 6376064 0 0 0.0 0 +chr19 6416917 0 0 0.0 0 +chr19 6713453 0 0 0.0 0 +chr19 6833232 0 0 0.0 0 +chr19 6957781 0 0 0.0 0 +chr19 6959211 0 0 0.0 0 +chr19 7110444 0 0 0.0 0 +chr19 7211745 0 0 0.0 0 +chr19 7319243 0 0 0.0 0 +chr19 7334425 0 0 0.0 0 +chr19 7418154 0 0 0.0 0 +chr19 7482736 0 0 0.0 0 +chr19 7514577 0 0 0.0 0 +chr19 7530132 0 1 0.0556 0 +chr19 7562830 0 0 0.0 0 +chr19 7748535 0 0 0.0 0 +chr19 7777298 0 0 0.0 0 +chr19 7811180 0 0 0.0 0 +chr19 7890325 0 0 0.0 0 +chr19 7900117 0 0 0.0 0 +chr19 8008828 0 0 0.0 0 +chr19 8127740 0 0 0.0 0 +chr19 8167626 0 0 0.0 0 +chr19 8207599 0 0 0.0 0 +chr19 8334575 0 0 0.0 0 +chr19 8374023 0 0 0.0 0 +chr19 8375433 0 0 0.0 0 +chr19 8396993 0 0 0.0 0 +chr19 8409507 0 0 0.0 0 +chr19 8604989 0 0 0.0 0 +chr19 8612259 0 0 0.0 0 +chr19 8615118 0 0 0.0 0 +chr19 8820604 1 41 0.8039 1 +chr19 8892912 0 0 0.0 0 +chr19 8900020 0 0 0.0 0 +chr19 8903217 0 0 0.0 0 +chr19 8906029 0 0 0.0 0 +chr19 8908647 0 0 0.0 0 +chr19 8913506 0 0 0.0 0 +chr19 8916588 0 0 0.0 0 +chr19 8998536 0 0 0.0 0 +chr19 9176035 0 0 0.0 0 +chr19 9225132 0 0 0.0 0 +chr19 9319189 0 0 0.0 0 +chr19 9425567 0 0 0.0 0 +chr19 9442700 0 0 0.0 0 +chr19 9454449 0 0 0.0 0 +chr19 9630601 0 0 0.0 0 +chr19 9717398 0 0 0.0 0 +chr19 9726864 0 0 0.0 0 +chr19 9742990 0 0 0.0 0 +chr19 9891926 0 0 0.0 0 +chr19 9949089 0 0 0.0 0 +chr19 9970300 0 1 0.0625 0 +chr19 10043714 0 0 0.0 0 +chr19 10125172 0 0 0.0 0 +chr19 10243772 0 0 0.0 0 +chr19 10337842 0 0 0.0 0 +chr19 10346569 0 0 0.0 0 +chr19 10386895 0 0 0.0 0 +chr19 10464668 0 0 0.0 0 +chr19 10579892 0 0 0.0 0 +chr19 10649537 0 0 0.0 0 +chr19 10681118 0 0 0.0 0 +chr19 10730693 0 0 0.0 0 +chr19 10815382 0 0 0.0 0 +chr19 10835305 0 0 0.0 0 +chr19 10947612 0 0 0.0 0 +chr19 11484087 0 0 0.0 0 +chr19 11530180 1 35 0.4861 1 +chr19 11552860 0 0 0.0 0 +chr19 11559616 0 0 0.0 0 +chr19 11647686 0 0 0.0 0 +chr19 11781695 0 0 0.0 0 +chr19 11906555 0 0 0.0 0 +chr19 12103720 0 0 0.0 0 +chr19 12264565 0 0 0.0 0 +chr19 12392569 0 0 0.0 0 +chr19 12397130 0 0 0.0 0 +chr19 12432343 0 0 0.0 0 +chr19 12593895 0 0 0.0 0 +chr19 12731768 0 0 0.0 0 +chr19 12836675 0 0 0.0 0 +chr19 12978027 0 0 0.0 0 +chr19 12985342 0 0 0.0 0 +chr19 13212359 0 0 0.0 0 +chr19 13459710 0 0 0.0 0 +chr19 13681052 0 0 0.0 0 +chr19 13719820 0 0 0.0 0 +chr19 13957455 0 0 0.0 0 +chr19 14017976 0 0 0.0 0 +chr19 14136744 0 0 0.0 0 +chr19 14337848 0 0 0.0 0 +chr19 14408296 0 0 0.0 0 +chr19 14430948 0 0 0.0 0 +chr19 14469488 0 0 0.0 0 +chr19 14495071 0 0 0.0 0 +chr19 14505560 0 0 0.0 0 +chr19 14532146 0 0 0.0 0 +chr19 14656588 0 0 0.0 0 +chr19 14701140 0 0 0.0 0 +chr19 14826751 0 0 0.0 0 +chr19 14827585 0 0 0.0 0 +chr19 14845601 0 0 0.0 0 +chr19 14880699 0 0 0.0 0 +chr19 14925181 0 0 0.0 0 +chr19 14927769 0 0 0.0 0 +chr19 15101581 0 0 0.0 0 +chr19 15108572 0 0 0.0 0 +chr19 15113574 0 0 0.0 0 +chr19 15117894 0 0 0.0 0 +chr19 15231178 0 0 0.0 0 +chr19 15285626 0 0 0.0 0 +chr19 15287666 0 0 0.0 0 +chr19 15392430 0 0 0.0 0 +chr19 15425400 0 0 0.0 0 +chr19 15476015 0 0 0.0 0 +chr19 15532923 0 0 0.0 0 +chr19 15538294 0 0 0.0 0 +chr19 15716006 0 0 0.0 0 +chr19 15719181 0 0 0.0 0 +chr19 15738029 0 0 0.0 0 +chr19 15782708 0 0 0.0 0 +chr19 16062328 0 0 0.0 0 +chr19 16139604 0 0 0.0 0 +chr19 16178727 1 76 0.987 1 +chr19 16280928 0 0 0.0 0 +chr19 16384713 0 0 0.0 0 +chr19 16405707 0 0 0.0 0 +chr19 16415581 0 0 0.0 0 +chr19 16430996 0 0 0.0 0 +chr19 16602820 0 0 0.0 0 +chr19 16615504 0 0 0.0 0 +chr19 16634994 0 0 0.0 0 +chr19 16722108 1 27 0.3699 1 +chr19 16779429 0 0 0.0 0 +chr19 17151788 0 0 0.0 0 +chr19 17231916 0 0 0.0 0 +chr19 17276599 0 0 0.0 0 +chr19 17311873 0 0 0.0 0 +chr19 17339204 0 0 0.0 0 +chr19 17387152 0 0 0.0 0 +chr19 17415323 0 0 0.0 0 +chr19 17798098 0 0 0.0 0 +chr19 17957781 0 0 0.0 0 +chr19 18073848 0 0 0.0 0 +chr19 18183633 0 0 0.0 0 +chr19 18213786 0 0 0.0 0 +chr19 18227516 0 0 0.0 0 +chr19 18275255 0 0 0.0 0 +chr19 18310565 0 0 0.0 0 +chr19 18379130 0 0 0.0 0 +chr19 18391931 0 0 0.0 0 +chr19 18396790 0 0 0.0 0 +chr19 18432594 0 0 0.0 0 +chr19 18489209 0 0 0.0 0 +chr19 18530035 0 0 0.0 0 +chr19 18599606 0 0 0.0 0 +chr19 18684455 0 0 0.0 0 +chr19 18711993 0 0 0.0 0 +chr19 18719084 0 1 0.0143 0 +chr19 18741552 0 0 0.0 0 +chr19 18773326 0 0 0.0 0 +chr19 18931364 0 0 0.0 0 +chr19 18955843 0 0 0.0 0 +chr19 18989453 0 0 0.0 0 +chr19 19181825 0 0 0.0 0 +chr19 19257577 0 0 0.0 0 +chr19 19423135 0 0 0.0 0 +chr19 19477914 0 0 0.0 0 +chr19 19542624 0 0 0.0 0 +chr19 19762682 0 0 0.0 0 +chr19 19963723 0 0 0.0 0 +chr19 20058586 0 0 0.0 0 +chr19 20151621 0 0 0.0 0 +chr19 20206779 0 0 0.0 0 +chr19 20211186 0 0 0.0 0 +chr19 20378323 0 0 0.0 0 +chr19 20392101 0 0 0.0 0 +chr19 20472933 0 0 0.0 0 +chr19 20483297 0 0 0.0 0 +chr19 20504222 0 0 0.0 0 +chr19 20633068 0 0 0.0 0 +chr19 20651587 0 0 0.0 0 +chr19 20753677 0 0 0.0 0 +chr19 20808577 0 0 0.0 0 +chr19 20900719 0 0 0.0 0 +chr19 20970295 0 0 0.0 0 +chr19 20982297 0 0 0.0 0 +chr19 20988483 0 0 0.0 0 +chr19 21009486 0 0 0.0 0 +chr19 21360330 0 0 0.0 0 +chr19 21392779 0 0 0.0 0 +chr19 21430627 0 0 0.0 0 +chr19 21513463 0 0 0.0 0 +chr19 21672835 0 0 0.0 0 +chr19 21800385 0 0 0.0 0 +chr19 21927110 0 0 0.0 0 +chr19 22069001 0 0 0.0 0 +chr19 22109852 0 0 0.0 0 +chr19 22133220 0 0 0.0 0 +chr19 22343764 0 0 0.0 0 +chr19 22554920 0 0 0.0 0 +chr19 22605597 0 0 0.0 0 +chr19 22607890 0 0 0.0 0 +chr19 22726446 0 0 0.0 0 +chr19 22992147 0 0 0.0 0 +chr19 23011750 0 0 0.0 0 +chr19 23474977 0 0 0.0 0 +chr19 23567507 0 0 0.0 0 +chr19 23621196 0 0 0.0 0 +chr19 23650145 0 0 0.0 0 +chr19 23677000 0 1 0.0204 0 +chr19 23866650 0 0 0.0 0 +chr19 23972697 0 0 0.0 0 +chr19 24298083 0 0 0.0 0 +chr19 24346170 0 0 0.0 0 +chr19 24375754 0 0 0.0 0 +chr19 27372838 0 0 0.0 0 +chr19 27562290 0 0 0.0 0 +chr19 27751849 0 0 0.0 0 +chr19 27759520 0 0 0.0 0 +chr19 27843179 0 0 0.0 0 +chr19 27844055 0 0 0.0 0 +chr19 27925231 0 0 0.0 0 +chr19 27934543 0 0 0.0 0 +chr19 28047695 0 0 0.0 0 +chr19 28058740 0 0 0.0 0 +chr19 28151261 0 0 0.0 0 +chr19 28224963 0 0 0.0 0 +chr19 28244730 0 0 0.0 0 +chr19 28295527 0 0 0.0 0 +chr19 28327972 0 0 0.0 0 +chr19 28436968 0 0 0.0 0 +chr19 28637339 0 0 0.0 0 +chr19 28704087 0 0 0.0 0 +chr19 28770381 0 0 0.0 0 +chr19 28931103 0 0 0.0 0 +chr19 29293178 0 0 0.0 0 +chr19 29402071 0 0 0.0 0 +chr19 29523293 0 0 0.0 0 +chr19 29529707 0 0 0.0 0 +chr19 29643048 1 27 0.375 1 +chr19 29867765 0 0 0.0 0 +chr19 29882829 0 0 0.0 0 +chr19 29903840 0 0 0.0 0 +chr19 30065372 0 0 0.0 0 +chr19 30066946 0 0 0.0 0 +chr19 30151427 0 0 0.0 0 +chr19 30161804 0 0 0.0 0 +chr19 30163556 0 0 0.0 0 +chr19 30256774 0 0 0.0 0 +chr19 30264632 0 0 0.0 0 +chr19 30352993 0 0 0.0 0 +chr19 30367739 0 0 0.0 0 +chr19 30368523 0 0 0.0 0 +chr19 30372838 1 17 0.3617 1 +chr19 30379083 0 0 0.0 0 +chr19 30455458 0 0 0.0 0 +chr19 30571928 0 0 0.0 0 +chr19 30626135 0 0 0.0 0 +chr19 30630390 2 29 0.6098 1 +chr19 30709108 0 0 0.0 0 +chr19 30742239 0 0 0.0 0 +chr19 30742324 0 0 0.0 0 +chr19 30757826 0 0 0.0 0 +chr19 30771208 0 0 0.0 0 +chr19 30895827 0 0 0.0 0 +chr19 31070535 0 0 0.0 0 +chr19 31128419 0 0 0.0 0 +chr19 31128462 0 0 0.0 0 +chr19 31385116 0 0 0.0 0 +chr19 31468445 0 0 0.0 0 +chr19 31499036 0 0 0.0 0 +chr19 31504697 0 0 0.0 0 +chr19 31551183 0 1 0.0154 0 +chr19 31646614 0 0 0.0 0 +chr19 31696200 0 1 0.013 0 +chr19 31757005 0 0 0.0 0 +chr19 31772310 0 0 0.0 0 +chr19 31915505 0 0 0.0 0 +chr19 32032081 0 0 0.0 0 +chr19 32068797 0 0 0.0 0 +chr19 32161400 0 0 0.0 0 +chr19 32211610 0 0 0.0 0 +chr19 32327137 0 0 0.0 0 +chr19 32383403 0 0 0.0 0 +chr19 32510699 0 0 0.0 0 +chr19 32620037 0 0 0.0 0 +chr19 32673636 0 0 0.0 0 +chr19 32809064 0 0 0.0 0 +chr19 32868545 0 0 0.0 0 +chr19 32972067 0 0 0.0 0 +chr19 33022209 0 0 0.0 0 +chr19 33087400 0 0 0.0 0 +chr19 33121580 0 0 0.0 0 +chr19 33164706 0 0 0.0 0 +chr19 33394676 0 0 0.0 0 +chr19 33397647 0 0 0.0 0 +chr19 33438981 0 0 0.0 0 +chr19 33472342 0 0 0.0 0 +chr19 33514936 0 0 0.0 0 +chr19 33905662 0 0 0.0 0 +chr19 33916741 0 0 0.0 0 +chr19 34051407 0 0 0.0 0 +chr19 34061410 0 0 0.0 0 +chr19 34119661 0 0 0.0 0 +chr19 34249703 0 1 0.0122 0 +chr19 34261643 0 0 0.0 0 +chr19 34277179 0 0 0.0 0 +chr19 34349150 0 0 0.0 0 +chr19 34505620 0 1 0.0182 0 +chr19 34553172 0 0 0.0 0 +chr19 34561281 0 0 0.0 0 +chr19 34597418 0 0 0.0 0 +chr19 34620756 0 0 0.0 0 +chr19 34648151 0 0 0.0 0 +chr19 34694582 0 0 0.0 0 +chr19 34884130 0 0 0.0 0 +chr19 34887806 0 0 0.0 0 +chr19 34979402 0 0 0.0 0 +chr19 35010032 0 0 0.0 0 +chr19 35026287 0 0 0.0 0 +chr19 35038828 0 0 0.0 0 +chr19 35101525 0 0 0.0 0 +chr19 35138424 0 0 0.0 0 +chr19 35194794 0 0 0.0 0 +chr19 35247284 0 0 0.0 0 +chr19 35278578 0 0 0.0 0 +chr19 35322203 0 0 0.0 0 +chr19 35383408 0 0 0.0 0 +chr19 35428236 0 0 0.0 0 +chr19 35459273 0 0 0.0 0 +chr19 35515642 0 0 0.0 0 +chr19 35541537 0 0 0.0 0 +chr19 35571146 0 0 0.0 0 +chr19 35587474 0 0 0.0 0 +chr19 35613034 0 0 0.0 0 +chr19 35643617 0 0 0.0 0 +chr19 35788040 0 0 0.0 0 +chr19 35874832 0 0 0.0 0 +chr19 35881600 0 0 0.0 0 +chr19 35983050 0 0 0.0 0 +chr19 36492218 0 0 0.0 0 +chr19 36984747 0 0 0.0 0 +chr19 37075500 0 0 0.0 0 +chr19 37356326 0 0 0.0 0 +chr19 37454061 0 0 0.0 0 +chr19 38008490 0 0 0.0 0 +chr19 38076534 0 0 0.0 0 +chr19 38165495 0 0 0.0 0 +chr19 38286288 0 0 0.0 0 +chr19 38436251 0 0 0.0 0 +chr19 38481254 0 0 0.0 0 +chr19 38494520 0 0 0.0 0 +chr19 38543950 0 0 0.0 0 +chr19 38650269 0 0 0.0 0 +chr19 38746868 0 0 0.0 0 +chr19 38812751 0 0 0.0 0 +chr19 38815121 0 0 0.0 0 +chr19 38821865 0 0 0.0 0 +chr19 38924645 0 0 0.0 0 +chr19 39086399 0 0 0.0 0 +chr19 39177203 0 0 0.0 0 +chr19 39222432 0 0 0.0 0 +chr19 39296603 0 0 0.0 0 +chr19 39318167 0 0 0.0 0 +chr19 39323287 0 0 0.0 0 +chr19 39383036 0 0 0.0 0 +chr19 39503826 0 0 0.0 0 +chr19 39532173 0 0 0.0 0 +chr19 39584379 0 0 0.0 0 +chr19 39640157 0 0 0.0 0 +chr19 39649589 0 0 0.0 0 +chr19 39675673 1 41 0.4881 1 +chr19 39681701 0 0 0.0 0 +chr19 39681999 0 0 0.0 0 +chr19 39746983 0 0 0.0 0 +chr19 40209142 0 0 0.0 0 +chr19 40239356 0 0 0.0 0 +chr19 40582465 0 0 0.0 0 +chr19 40617158 0 0 0.0 0 +chr19 40701098 0 0 0.0 0 +chr19 40772049 0 0 0.0 0 +chr19 40780635 0 0 0.0 0 +chr19 40788170 0 0 0.0 0 +chr19 40794836 0 0 0.0 0 +chr19 40800409 0 0 0.0 0 +chr19 40949144 0 0 0.0 0 +chr19 41229348 0 0 0.0 0 +chr19 41242157 0 0 0.0 0 +chr19 41429378 0 0 0.0 0 +chr19 41467450 0 0 0.0 0 +chr19 41590427 0 0 0.0 0 +chr19 41603415 0 0 0.0 0 +chr19 41652881 0 0 0.0 0 +chr19 41790986 0 0 0.0 0 +chr19 42001149 0 0 0.0 0 +chr19 42021167 0 0 0.0 0 +chr19 42042965 0 0 0.0 0 +chr19 42045983 0 0 0.0 0 +chr19 42146972 0 0 0.0 0 +chr19 42169519 0 0 0.0 0 +chr19 42198918 0 0 0.0 0 +chr19 42226094 0 1 0.0123 0 +chr19 42289678 0 0 0.0 0 +chr19 42356139 0 0 0.0 0 +chr19 42506139 0 0 0.0 0 +chr19 42523464 0 0 0.0 0 +chr19 42539830 0 0 0.0 0 +chr19 42560086 0 0 0.0 0 +chr19 42579315 0 0 0.0 0 +chr19 42583212 0 0 0.0 0 +chr19 42632585 0 0 0.0 0 +chr19 42758114 0 0 0.0 0 +chr19 42762895 0 0 0.0 0 +chr19 42784086 0 0 0.0 0 +chr19 42800669 0 0 0.0 0 +chr19 42851239 0 0 0.0 0 +chr19 42871566 0 0 0.0 0 +chr19 42910378 0 0 0.0 0 +chr19 42939471 0 0 0.0 0 +chr19 42956210 0 0 0.0 0 +chr19 43027045 0 0 0.0 0 +chr19 43140369 0 0 0.0 0 +chr19 43419654 0 0 0.0 0 +chr19 43501705 0 0 0.0 0 +chr19 43639044 0 0 0.0 0 +chr19 43659655 0 0 0.0 0 +chr19 43692345 0 0 0.0 0 +chr19 43916478 0 0 0.0 0 +chr19 43944368 0 0 0.0 0 +chr19 44028244 0 0 0.0 0 +chr19 44061133 0 0 0.0 0 +chr19 44197344 0 0 0.0 0 +chr19 44241335 0 0 0.0 0 +chr19 44264493 0 0 0.0 0 +chr19 44343847 0 0 0.0 0 +chr19 44497753 0 0 0.0 0 +chr19 44537992 0 0 0.0 0 +chr19 44670180 0 0 0.0 0 +chr19 44881577 0 0 0.0 0 +chr19 44914241 0 0 0.0 0 +chr19 44939823 0 0 0.0 0 +chr19 44955509 0 0 0.0 0 +chr19 45058163 0 0 0.0 0 +chr19 45105432 0 0 0.0 0 +chr19 45118432 0 0 0.0 0 +chr19 45145960 0 0 0.0 0 +chr19 45182425 0 0 0.0 0 +chr19 45210717 0 0 0.0 0 +chr19 45273646 0 0 0.0 0 +chr19 45287069 0 0 0.0 0 +chr19 45392201 0 0 0.0 0 +chr19 45462867 0 0 0.0 0 +chr19 45551516 0 0 0.0 0 +chr19 45705687 0 0 0.0 0 +chr19 45733716 0 0 0.0 0 +chr19 45767709 0 0 0.0 0 +chr19 45774924 0 0 0.0 0 +chr19 45794917 0 0 0.0 0 +chr19 45804335 0 0 0.0 0 +chr19 45808706 0 0 0.0 0 +chr19 45816257 0 0 0.0 0 +chr19 45851988 0 0 0.0 0 +chr19 45976896 0 0 0.0 0 +chr19 46022978 0 0 0.0 0 +chr19 46053532 0 0 0.0 0 +chr19 46199428 0 0 0.0 0 +chr19 46426827 0 0 0.0 0 +chr19 46550679 0 1 0.0118 0 +chr19 46638536 0 1 0.0227 0 +chr19 46780224 0 0 0.0 0 +chr19 46819270 0 0 0.0 0 +chr19 46843784 0 0 0.0 0 +chr19 46854628 0 0 0.0 0 +chr19 46855071 2 5 0.1667 1 +chr19 46976592 0 0 0.0 0 +chr19 46993179 0 0 0.0 0 +chr19 47032851 0 0 0.0 0 +chr19 47272595 0 0 0.0 0 +chr19 47416585 0 0 0.0 0 +chr19 47421851 0 0 0.0 0 +chr19 47424243 0 0 0.0 0 +chr19 47477235 0 0 0.0 0 +chr19 47487274 0 0 0.0 0 +chr19 47640289 0 0 0.0 0 +chr19 47663145 0 0 0.0 0 +chr19 47679738 0 0 0.0 0 +chr19 47721635 0 0 0.0 0 +chr19 47780748 0 0 0.0 0 +chr19 47781379 0 0 0.0 0 +chr19 47802542 0 0 0.0 0 +chr19 47903042 0 0 0.0 0 +chr19 48005096 0 0 0.0 0 +chr19 48039511 0 0 0.0 0 +chr19 48112063 0 0 0.0 0 +chr19 48165394 0 0 0.0 0 +chr19 48200984 0 0 0.0 0 +chr19 48297070 0 0 0.0 0 +chr19 48504678 0 0 0.0 0 +chr19 48510125 0 0 0.0 0 +chr19 48606599 0 0 0.0 0 +chr19 48680509 0 0 0.0 0 +chr19 48703454 0 1 0.0145 0 +chr19 48703727 0 0 0.0 0 +chr19 48782007 0 0 0.0 0 +chr19 48845608 0 0 0.0 0 +chr19 48864952 0 0 0.0 0 +chr19 48895404 0 0 0.0 0 +chr19 48979254 0 0 0.0 0 +chr19 48999968 0 0 0.0 0 +chr19 49001552 0 0 0.0 0 +chr19 49158392 0 0 0.0 0 +chr19 49225709 0 0 0.0 0 +chr19 49256797 0 0 0.0 0 +chr19 49285578 0 0 0.0 0 +chr19 49355160 0 0 0.0 0 +chr19 49355378 0 0 0.0 0 +chr19 49365792 0 0 0.0 0 +chr19 49486590 0 0 0.0 0 +chr19 49527243 0 0 0.0 0 +chr19 49571648 0 0 0.0 0 +chr19 49683839 0 0 0.0 0 +chr19 49735761 0 0 0.0 0 +chr19 49768244 0 0 0.0 0 +chr19 49812565 0 0 0.0 0 +chr19 49915397 0 0 0.0 0 +chr19 49940038 0 0 0.0 0 +chr19 49968930 0 0 0.0 0 +chr19 49973610 0 0 0.0 0 +chr19 49979475 0 0 0.0 0 +chr19 50194293 0 0 0.0 0 +chr19 50209342 0 0 0.0 0 +chr19 50235897 0 0 0.0 0 +chr19 50325872 0 0 0.0 0 +chr19 50354301 0 0 0.0 0 +chr19 50360374 0 0 0.0 0 +chr19 50397852 0 0 0.0 0 +chr19 50407287 0 0 0.0 0 +chr19 50455828 0 0 0.0 0 +chr19 50627437 0 0 0.0 0 +chr19 50792766 0 0 0.0 0 +chr19 50851247 0 0 0.0 0 +chr19 50860215 0 0 0.0 0 +chr19 50912188 0 0 0.0 0 +chr19 50996241 0 0 0.0 0 +chr19 51106981 0 0 0.0 0 +chr19 51168195 0 0 0.0 0 +chr19 51179085 0 0 0.0 0 +chr19 51188117 0 0 0.0 0 +chr19 51210465 0 0 0.0 0 +chr19 51211898 0 0 0.0 0 +chr19 51468622 0 0 0.0 0 +chr19 51530853 0 0 0.0 0 +chr19 51546838 0 0 0.0 0 +chr19 51556127 0 0 0.0 0 +chr19 51669469 0 0 0.0 0 +chr19 51677087 0 0 0.0 0 +chr19 51727104 0 0 0.0 0 +chr19 51736998 0 0 0.0 0 +chr19 51739553 0 0 0.0 0 +chr19 51761973 0 0 0.0 0 +chr19 51789099 0 0 0.0 0 +chr19 51796332 0 0 0.0 0 +chr19 51818786 0 0 0.0 0 +chr19 51942450 0 0 0.0 0 +chr19 51956549 0 0 0.0 0 +chr19 52001824 0 0 0.0 0 +chr19 52118560 0 0 0.0 0 +chr19 52128276 0 0 0.0 0 +chr19 52209978 0 0 0.0 0 +chr19 52223810 0 0 0.0 0 +chr19 52254596 0 0 0.0 0 +chr19 52400653 0 0 0.0 0 +chr19 52539972 0 0 0.0 0 +chr19 52549238 0 0 0.0 0 +chr19 52556683 0 0 0.0 0 +chr19 52579007 0 0 0.0 0 +chr19 52640611 0 0 0.0 0 +chr19 52763330 0 0 0.0 0 +chr19 52935293 0 0 0.0 0 +chr19 52977212 0 0 0.0 0 +chr19 53075487 0 0 0.0 0 +chr19 53228672 0 0 0.0 0 +chr19 53252833 0 0 0.0 0 +chr19 53274146 0 0 0.0 0 +chr19 53339592 0 0 0.0 0 +chr19 53343803 0 0 0.0 0 +chr19 53392754 0 0 0.0 0 +chr19 53570624 0 0 0.0 0 +chr19 53666894 0 0 0.0 0 +chr19 53669378 0 0 0.0 0 +chr19 53769376 1 5 0.0714 1 +chr19 53885727 0 0 0.0 0 +chr19 53934158 0 0 0.0 0 +chr19 53956797 0 0 0.0 0 +chr19 53993092 0 0 0.0 0 +chr19 54157146 0 0 0.0 0 +chr19 54158109 0 0 0.0 0 +chr19 54294459 0 0 0.0 0 +chr19 54312430 0 0 0.0 0 +chr19 54377185 0 0 0.0 0 +chr19 54434135 0 0 0.0 0 +chr19 54459352 0 0 0.0 0 +chr19 54505155 0 0 0.0 0 +chr19 54537134 0 0 0.0 0 +chr19 54571685 0 0 0.0 0 +chr19 54600418 0 0 0.0 0 +chr19 54613507 0 0 0.0 0 +chr19 54836705 0 0 0.0 0 +chr19 54947252 0 0 0.0 0 +chr19 55149389 0 0 0.0 0 +chr19 55214018 0 0 0.0 0 +chr19 55281378 0 0 0.0 0 +chr19 55312110 0 0 0.0 0 +chr19 55343965 0 0 0.0 0 +chr19 55351213 0 0 0.0 0 +chr19 55359085 0 0 0.0 0 +chr19 55395366 0 0 0.0 0 +chr19 55631230 0 0 0.0 0 +chr19 55820267 0 0 0.0 0 +chr19 56027640 0 0 0.0 0 +chr19 56115175 0 0 0.0 0 +chr19 56118902 0 0 0.0 0 +chr19 56132768 0 0 0.0 0 +chr19 56347526 0 0 0.0 0 +chr19 56351359 0 1 0.0189 0 +chr19 56354213 0 0 0.0 0 +chr19 56395123 0 0 0.0 0 +chr19 56574742 0 0 0.0 0 +chr19 56645612 0 0 0.0 0 +chr19 56734944 0 0 0.0 0 +chr19 56982014 0 0 0.0 0 +chr19 57068734 0 0 0.0 0 +chr19 57204990 0 0 0.0 0 +chr19 57278118 0 0 0.0 0 +chr19 57444096 0 0 0.0 0 +chr19 57444651 0 0 0.0 0 +chr19 57501193 0 0 0.0 0 +chr19 57570105 0 0 0.0 0 +chr19 57680778 0 0 0.0 0 +chr19 57691451 0 0 0.0 0 +chr19 57812519 0 0 0.0 0 +chr19 57824483 0 0 0.0 0 +chr19 58057807 0 0 0.0 0 +chr19 58091674 0 0 0.0 0 +chr19 58129871 0 0 0.0 0 +chr19 58318722 0 0 0.0 0 +chr19 58389356 0 0 0.0 0 +chr19 58432759 0 0 0.0 0 +chr19 58562767 0 0 0.0 0 +chr19 58566629 0 0 0.0 0 +chr19_GL383573v1_alt 90536 0 0 0.0 0 +chr19_GL383573v1_alt 145533 0 0 0.0 0 +chr19_GL383573v1_alt 243995 0 0 0.0 0 +chr19_GL383573v1_alt 313570 0 0 0.0 0 +chr19_GL383573v1_alt 331758 0 0 0.0 0 +chr19_GL383574v1_alt 104617 0 0 0.0 0 +chr19_GL383574v1_alt 132092 0 0 0.0 0 +chr19_GL383575v2_alt 34056 0 0 0.0 0 +chr19_GL383575v2_alt 161575 0 0 0.0 0 +chr19_GL383576v1_alt 175653 0 0 0.0 0 +chr19_GL949746v1_alt 131996 0 0 0.0 0 +chr19_GL949746v1_alt 163478 0 0 0.0 0 +chr19_GL949746v1_alt 269197 0 0 0.0 0 +chr19_GL949746v1_alt 365866 0 0 0.0 0 +chr19_GL949746v1_alt 506808 0 0 0.0 0 +chr19_GL949746v1_alt 519897 0 0 0.0 0 +chr19_GL949746v1_alt 850648 0 0 0.0 0 +chr19_GL949747v2_alt 131997 0 0 0.0 0 +chr19_GL949747v2_alt 163649 0 0 0.0 0 +chr19_GL949747v2_alt 269077 0 0 0.0 0 +chr19_GL949747v2_alt 592452 0 0 0.0 0 +chr19_GL949748v2_alt 131997 0 0 0.0 0 +chr19_GL949748v2_alt 163649 0 0 0.0 0 +chr19_GL949748v2_alt 927236 0 0 0.0 0 +chr19_GL949749v2_alt 131997 0 0 0.0 0 +chr19_GL949749v2_alt 163649 0 0 0.0 0 +chr19_GL949749v2_alt 954773 0 0 0.0 0 +chr19_GL949750v2_alt 131997 0 0 0.0 0 +chr19_GL949750v2_alt 163649 0 0 0.0 0 +chr19_GL949750v2_alt 929322 0 0 0.0 0 +chr19_GL949751v2_alt 131997 0 0 0.0 0 +chr19_GL949751v2_alt 163649 0 0 0.0 0 +chr19_GL949751v2_alt 865615 0 0 0.0 0 +chr19_GL949752v1_alt 131997 0 0 0.0 0 +chr19_GL949752v1_alt 163645 0 0 0.0 0 +chr19_GL949752v1_alt 364039 0 0 0.0 0 +chr19_GL949752v1_alt 505302 0 0 0.0 0 +chr19_GL949752v1_alt 518392 0 0 0.0 0 +chr19_GL949752v1_alt 851607 0 0 0.0 0 +chr19_GL949753v2_alt 131997 0 0 0.0 0 +chr19_GL949753v2_alt 163649 0 0 0.0 0 +chr19_GL949753v2_alt 269452 0 0 0.0 0 +chr19_GL949753v2_alt 659411 0 0 0.0 0 +chr19_KI270867v1_alt 29148 0 0 0.0 0 +chr19_KI270867v1_alt 91574 0 0 0.0 0 +chr19_KI270891v1_alt 32373 0 0 0.0 0 +chr19_KI270938v1_alt 131997 0 0 0.0 0 +chr19_KI270938v1_alt 163649 0 0 0.0 0 +chr19_KI270938v1_alt 269425 0 0 0.0 0 +chr19_KI270938v1_alt 441645 0 0 0.0 0 +chr19_KI270938v1_alt 582997 0 0 0.0 0 +chr19_KI270938v1_alt 596087 0 0 0.0 0 +chr19_KI270938v1_alt 929732 0 0 0.0 0 +chr1_GL383518v1_alt 170016 0 0 0.0 0 +chr1_GL383519v1_alt 63135 0 0 0.0 0 +chr1_GL383520v2_alt 285002 0 0 0.0 0 +chr1_KI270706v1_random 151978 0 0 0.0 0 +chr1_KI270707v1_random 26958 0 0 0.0 0 +chr1_KI270708v1_random 48811 0 0 0.0 0 +chr1_KI270712v1_random 78083 0 0 0.0 0 +chr1_KI270712v1_random 108669 0 0 0.0 0 +chr1_KI270713v1_random 1556 0 0 0.0 0 +chr1_KI270759v1_alt 160304 0 0 0.0 0 +chr1_KI270759v1_alt 177940 0 0 0.0 0 +chr1_KI270761v1_alt 141256 0 0 0.0 0 +chr1_KI270762v1_alt 3190 0 0 0.0 0 +chr1_KI270762v1_alt 25747 0 0 0.0 0 +chr1_KI270762v1_alt 93609 0 0 0.0 0 +chr1_KI270763v1_alt 34170 0 0 0.0 0 +chr1_KI270763v1_alt 335361 0 0 0.0 0 +chr1_KI270763v1_alt 340271 0 0 0.0 0 +chr1_KI270763v1_alt 532220 0 0 0.0 0 +chr1_KI270763v1_alt 740299 0 0 0.0 0 +chr1_KI270766v1_alt 16168 0 0 0.0 0 +chr1_KI270892v1_alt 137634 0 0 0.0 0 +chr2 94375 0 0 0.0 0 +chr2 245350 0 0 0.0 0 +chr2 266549 0 0 0.0 0 +chr2 311156 0 0 0.0 0 +chr2 356560 0 0 0.0 0 +chr2 396100 0 0 0.0 0 +chr2 560219 0 0 0.0 0 +chr2 646588 0 0 0.0 0 +chr2 690233 0 0 0.0 0 +chr2 758423 0 0 0.0 0 +chr2 778108 0 0 0.0 0 +chr2 867425 0 0 0.0 0 +chr2 960173 0 0 0.0 0 +chr2 996759 0 0 0.0 0 +chr2 1018824 0 0 0.0 0 +chr2 1052954 0 0 0.0 0 +chr2 1077149 0 0 0.0 0 +chr2 1123618 0 0 0.0 0 +chr2 1156690 0 0 0.0 0 +chr2 1453390 0 0 0.0 0 +chr2 1461820 0 0 0.0 0 +chr2 1618101 0 0 0.0 0 +chr2 1680963 0 0 0.0 0 +chr2 1703139 1 3 1.0 1 +chr2 1703546 0 0 0.0 0 +chr2 1703863 0 0 0.0 0 +chr2 1704138 0 0 0.0 0 +chr2 1704666 0 2 0.0488 0 +chr2 1759315 0 0 0.0 0 +chr2 1798834 0 0 0.0 0 +chr2 1950843 0 0 0.0 0 +chr2 2178864 0 0 0.0 0 +chr2 2395464 0 0 0.0 0 +chr2 2461580 0 0 0.0 0 +chr2 2512593 0 0 0.0 0 +chr2 2562745 0 0 0.0 0 +chr2 2563219 0 0 0.0 0 +chr2 2563793 0 0 0.0 0 +chr2 2656964 0 0 0.0 0 +chr2 2675686 0 0 0.0 0 +chr2 2741399 0 0 0.0 0 +chr2 2762117 0 0 0.0 0 +chr2 2765644 0 0 0.0 0 +chr2 2776745 0 0 0.0 0 +chr2 2837010 0 0 0.0 0 +chr2 2846050 0 0 0.0 0 +chr2 2873648 0 0 0.0 0 +chr2 2879026 0 0 0.0 0 +chr2 2919850 0 0 0.0 0 +chr2 3080507 0 0 0.0 0 +chr2 3132921 0 1 0.0278 0 +chr2 3140106 0 0 0.0 0 +chr2 3189459 0 0 0.0 0 +chr2 3209116 0 0 0.0 0 +chr2 3309812 0 0 0.0 0 +chr2 3339100 0 0 0.0 0 +chr2 3384880 0 0 0.0 0 +chr2 3429561 0 0 0.0 0 +chr2 3430772 0 0 0.0 0 +chr2 3827748 0 0 0.0 0 +chr2 3899182 0 0 0.0 0 +chr2 4072486 0 0 0.0 0 +chr2 4109479 0 0 0.0 0 +chr2 4140259 0 0 0.0 0 +chr2 4351822 0 0 0.0 0 +chr2 4589029 0 0 0.0 0 +chr2 4658872 0 0 0.0 0 +chr2 4678025 0 0 0.0 0 +chr2 4684410 0 0 0.0 0 +chr2 4746861 0 0 0.0 0 +chr2 4765206 0 0 0.0 0 +chr2 4844607 0 0 0.0 0 +chr2 4884591 0 0 0.0 0 +chr2 4985388 0 0 0.0 0 +chr2 5090415 0 1 0.027 0 +chr2 5460272 0 0 0.0 0 +chr2 5526840 0 0 0.0 0 +chr2 5695729 0 0 0.0 0 +chr2 5889264 0 0 0.0 0 +chr2 5903433 0 0 0.0 0 +chr2 5950004 0 0 0.0 0 +chr2 6254755 0 0 0.0 0 +chr2 6283811 0 0 0.0 0 +chr2 6497333 0 0 0.0 0 +chr2 6556680 0 0 0.0 0 +chr2 6640562 0 0 0.0 0 +chr2 6721924 0 0 0.0 0 +chr2 6761176 0 0 0.0 0 +chr2 6779394 0 0 0.0 0 +chr2 6940211 0 0 0.0 0 +chr2 6961658 0 0 0.0 0 +chr2 7010494 0 0 0.0 0 +chr2 7032797 0 0 0.0 0 +chr2 7033963 0 0 0.0 0 +chr2 7205411 0 0 0.0 0 +chr2 7440559 0 0 0.0 0 +chr2 7581697 0 0 0.0 0 +chr2 7586144 0 0 0.0 0 +chr2 7674686 0 0 0.0 0 +chr2 7683011 0 0 0.0 0 +chr2 7781892 0 0 0.0 0 +chr2 7782808 0 0 0.0 0 +chr2 7850173 0 0 0.0 0 +chr2 7948543 0 0 0.0 0 +chr2 8066000 0 0 0.0 0 +chr2 8229698 0 0 0.0 0 +chr2 8298512 0 0 0.0 0 +chr2 8315334 0 0 0.0 0 +chr2 8332580 0 0 0.0 0 +chr2 8377241 0 0 0.0 0 +chr2 8488037 0 0 0.0 0 +chr2 8534061 0 0 0.0 0 +chr2 8545963 0 0 0.0 0 +chr2 8605805 0 0 0.0 0 +chr2 8639527 0 0 0.0 0 +chr2 8644603 0 0 0.0 0 +chr2 8682250 0 0 0.0 0 +chr2 8694039 0 0 0.0 0 +chr2 8764298 0 0 0.0 0 +chr2 8765173 0 0 0.0 0 +chr2 8767481 0 0 0.0 0 +chr2 8852098 0 0 0.0 0 +chr2 8898373 0 0 0.0 0 +chr2 8899190 0 0 0.0 0 +chr2 8957439 0 0 0.0 0 +chr2 9039195 0 0 0.0 0 +chr2 9124327 0 0 0.0 0 +chr2 9146847 0 0 0.0 0 +chr2 9222955 0 0 0.0 0 +chr2 9268873 0 0 0.0 0 +chr2 9462848 0 0 0.0 0 +chr2 9529207 0 0 0.0 0 +chr2 9531325 0 0 0.0 0 +chr2 9574062 0 0 0.0 0 +chr2 9593578 0 0 0.0 0 +chr2 9605915 0 0 0.0 0 +chr2 9653506 0 0 0.0 0 +chr2 9776261 0 0 0.0 0 +chr2 9944278 0 0 0.0 0 +chr2 9980063 0 0 0.0 0 +chr2 9994122 0 0 0.0 0 +chr2 10044610 0 0 0.0 0 +chr2 10139939 0 0 0.0 0 +chr2 10191038 0 0 0.0 0 +chr2 10240680 0 0 0.0 0 +chr2 10307144 0 0 0.0 0 +chr2 10369792 0 0 0.0 0 +chr2 10391550 0 0 0.0 0 +chr2 10402783 0 0 0.0 0 +chr2 10407512 0 0 0.0 0 +chr2 10463080 0 0 0.0 0 +chr2 10775920 0 0 0.0 0 +chr2 10811085 0 0 0.0 0 +chr2 10874338 0 0 0.0 0 +chr2 10934102 0 0 0.0 0 +chr2 10992184 1 11 0.1429 1 +chr2 11138552 0 0 0.0 0 +chr2 11147482 0 0 0.0 0 +chr2 11395484 0 0 0.0 0 +chr2 11474223 0 0 0.0 0 +chr2 11492758 0 0 0.0 0 +chr2 11506706 0 0 0.0 0 +chr2 11635120 0 0 0.0 0 +chr2 11788258 0 0 0.0 0 +chr2 11842372 0 0 0.0 0 +chr2 11855022 0 0 0.0 0 +chr2 11928469 0 0 0.0 0 +chr2 12033977 0 0 0.0 0 +chr2 12410866 0 0 0.0 0 +chr2 12567381 0 0 0.0 0 +chr2 12636306 0 0 0.0 0 +chr2 12729125 0 0 0.0 0 +chr2 12729686 0 0 0.0 0 +chr2 12775331 0 0 0.0 0 +chr2 12803111 0 0 0.0 0 +chr2 12875478 0 0 0.0 0 +chr2 12901563 0 0 0.0 0 +chr2 12948413 0 0 0.0 0 +chr2 13177111 0 0 0.0 0 +chr2 13307550 0 0 0.0 0 +chr2 13338971 0 0 0.0 0 +chr2 13456624 0 0 0.0 0 +chr2 13712812 0 0 0.0 0 +chr2 13803487 0 0 0.0 0 +chr2 13899450 0 0 0.0 0 +chr2 13930493 0 0 0.0 0 +chr2 14082411 0 0 0.0 0 +chr2 14092712 1 9 0.3462 1 +chr2 14344009 0 0 0.0 0 +chr2 14422226 0 0 0.0 0 +chr2 14577010 1 71 0.8765 1 +chr2 14614036 0 0 0.0 0 +chr2 14676600 0 0 0.0 0 +chr2 14808544 0 0 0.0 0 +chr2 14814526 0 0 0.0 0 +chr2 14872683 0 0 0.0 0 +chr2 14873478 0 0 0.0 0 +chr2 15036438 0 0 0.0 0 +chr2 15125686 0 0 0.0 0 +chr2 15246836 0 0 0.0 0 +chr2 15280027 0 0 0.0 0 +chr2 15340222 0 0 0.0 0 +chr2 15498451 0 0 0.0 0 +chr2 15604711 0 0 0.0 0 +chr2 15802092 0 0 0.0 0 +chr2 15838575 0 0 0.0 0 +chr2 15840335 0 0 0.0 0 +chr2 15850085 0 0 0.0 0 +chr2 15921880 0 0 0.0 0 +chr2 15952851 0 0 0.0 0 +chr2 15966651 0 0 0.0 0 +chr2 16071940 0 0 0.0 0 +chr2 16171532 0 0 0.0 0 +chr2 16207329 0 0 0.0 0 +chr2 16316631 0 0 0.0 0 +chr2 16860573 0 0 0.0 0 +chr2 16882190 0 0 0.0 0 +chr2 16957794 0 0 0.0 0 +chr2 16961334 0 0 0.0 0 +chr2 17122922 0 0 0.0 0 +chr2 17286046 0 0 0.0 0 +chr2 17512770 0 0 0.0 0 +chr2 17786886 0 0 0.0 0 +chr2 17817783 0 0 0.0 0 +chr2 17943082 0 0 0.0 0 +chr2 18132901 0 0 0.0 0 +chr2 18168063 0 0 0.0 0 +chr2 18287146 0 0 0.0 0 +chr2 18317715 0 0 0.0 0 +chr2 18340695 0 0 0.0 0 +chr2 18640079 0 0 0.0 0 +chr2 19257273 0 0 0.0 0 +chr2 19343092 0 0 0.0 0 +chr2 19368604 0 0 0.0 0 +chr2 19375566 0 0 0.0 0 +chr2 19427095 0 0 0.0 0 +chr2 19449168 0 0 0.0 0 +chr2 19505117 0 0 0.0 0 +chr2 19529237 0 0 0.0 0 +chr2 19568330 0 0 0.0 0 +chr2 19695367 0 0 0.0 0 +chr2 19959521 0 0 0.0 0 +chr2 20100296 0 0 0.0 0 +chr2 20218873 0 0 0.0 0 +chr2 20242240 0 0 0.0 0 +chr2 20242852 0 0 0.0 0 +chr2 20339326 1 7 0.0886 1 +chr2 20458898 0 0 0.0 0 +chr2 20497829 0 0 0.0 0 +chr2 20593154 0 0 0.0 0 +chr2 20641960 0 0 0.0 0 +chr2 20651815 0 0 0.0 0 +chr2 20702796 0 0 0.0 0 +chr2 20798943 0 0 0.0 0 +chr2 21032412 0 0 0.0 0 +chr2 21060599 0 0 0.0 0 +chr2 21213862 0 0 0.0 0 +chr2 21315106 0 0 0.0 0 +chr2 21329059 0 0 0.0 0 +chr2 21355202 0 0 0.0 0 +chr2 21547548 0 0 0.0 0 +chr2 22604526 0 0 0.0 0 +chr2 23030226 0 0 0.0 0 +chr2 23135957 0 0 0.0 0 +chr2 23295061 0 0 0.0 0 +chr2 23346552 0 0 0.0 0 +chr2 23376498 0 0 0.0 0 +chr2 23384008 0 0 0.0 0 +chr2 23562591 0 0 0.0 0 +chr2 23583483 0 0 0.0 0 +chr2 23718940 0 0 0.0 0 +chr2 23728400 0 0 0.0 0 +chr2 23925375 0 0 0.0 0 +chr2 24019444 0 0 0.0 0 +chr2 24357247 0 0 0.0 0 +chr2 24359387 0 0 0.0 0 +chr2 24551823 0 1 0.0256 0 +chr2 24554640 0 0 0.0 0 +chr2 24566912 0 0 0.0 0 +chr2 24643377 0 0 0.0 0 +chr2 24906567 0 0 0.0 0 +chr2 24917983 0 0 0.0 0 +chr2 24998150 0 0 0.0 0 +chr2 25133469 0 0 0.0 0 +chr2 25304917 0 0 0.0 0 +chr2 25459864 0 0 0.0 0 +chr2 25460971 0 0 0.0 0 +chr2 25624782 0 0 0.0 0 +chr2 25793871 0 0 0.0 0 +chr2 25966691 0 0 0.0 0 +chr2 26162225 0 0 0.0 0 +chr2 26197873 0 0 0.0 0 +chr2 26222045 0 0 0.0 0 +chr2 26243214 0 0 0.0 0 +chr2 26312695 0 0 0.0 0 +chr2 26449965 0 0 0.0 0 +chr2 26456991 0 0 0.0 0 +chr2 26471244 0 0 0.0 0 +chr2 26624135 0 0 0.0 0 +chr2 26698654 0 0 0.0 0 +chr2 26720918 0 0 0.0 0 +chr2 26733146 0 0 0.0 0 +chr2 26777575 0 0 0.0 0 +chr2 26777928 0 0 0.0 0 +chr2 26807513 0 0 0.0 0 +chr2 27099513 0 0 0.0 0 +chr2 27119509 0 0 0.0 0 +chr2 27120987 0 0 0.0 0 +chr2 27174184 0 0 0.0 0 +chr2 27245159 0 0 0.0 0 +chr2 27325015 0 0 0.0 0 +chr2 27416340 0 0 0.0 0 +chr2 27833656 0 0 0.0 0 +chr2 27895300 0 0 0.0 0 +chr2 28083026 0 0 0.0 0 +chr2 28233267 0 0 0.0 0 +chr2 28271329 0 0 0.0 0 +chr2 28405653 0 0 0.0 0 +chr2 28438740 0 0 0.0 0 +chr2 28449354 0 0 0.0 0 +chr2 28478489 0 0 0.0 0 +chr2 28540840 0 0 0.0 0 +chr2 28551077 0 0 0.0 0 +chr2 28588249 0 0 0.0 0 +chr2 28641225 0 0 0.0 0 +chr2 28800282 0 0 0.0 0 +chr2 28913046 0 0 0.0 0 +chr2 28959257 0 0 0.0 0 +chr2 29113906 0 0 0.0 0 +chr2 29309353 0 0 0.0 0 +chr2 29419104 0 0 0.0 0 +chr2 29446693 0 0 0.0 0 +chr2 29523738 0 0 0.0 0 +chr2 29526056 0 0 0.0 0 +chr2 29814009 0 0 0.0 0 +chr2 29849185 0 0 0.0 0 +chr2 29853550 0 0 0.0 0 +chr2 29952205 0 0 0.0 0 +chr2 29982778 0 0 0.0 0 +chr2 30339456 0 0 0.0 0 +chr2 30352887 0 0 0.0 0 +chr2 30366180 0 0 0.0 0 +chr2 30518794 0 0 0.0 0 +chr2 30661277 0 0 0.0 0 +chr2 30664500 0 0 0.0 0 +chr2 30732343 0 0 0.0 0 +chr2 30740354 0 0 0.0 0 +chr2 30810645 0 0 0.0 0 +chr2 30889360 0 0 0.0 0 +chr2 30914517 0 0 0.0 0 +chr2 30978110 0 0 0.0 0 +chr2 30980731 0 0 0.0 0 +chr2 31220480 0 0 0.0 0 +chr2 31226941 0 0 0.0 0 +chr2 31258646 0 0 0.0 0 +chr2 31261039 0 0 0.0 0 +chr2 31385056 0 0 0.0 0 +chr2 31457022 0 0 0.0 0 +chr2 31513362 0 0 0.0 0 +chr2 31522186 0 0 0.0 0 +chr2 31582798 0 0 0.0 0 +chr2 31636651 0 0 0.0 0 +chr2 31651836 0 0 0.0 0 +chr2 31854814 0 0 0.0 0 +chr2 31934730 0 0 0.0 0 +chr2 32244748 0 0 0.0 0 +chr2 32253551 0 0 0.0 0 +chr2 32287002 0 0 0.0 0 +chr2 32333974 0 0 0.0 0 +chr2 32417223 0 0 0.0 0 +chr2 32419249 0 0 0.0 0 +chr2 32579579 0 0 0.0 0 +chr2 32746794 0 0 0.0 0 +chr2 32798326 0 0 0.0 0 +chr2 32877537 0 0 0.0 0 +chr2 32914193 0 0 0.0 0 +chr2 32942856 0 0 0.0 0 +chr2 32954634 0 1 0.0154 0 +chr2 33009359 0 0 0.0 0 +chr2 33053709 0 0 0.0 0 +chr2 33117245 0 0 0.0 0 +chr2 33160595 0 0 0.0 0 +chr2 33305548 0 0 0.0 0 +chr2 33359954 0 0 0.0 0 +chr2 33467579 0 0 0.0 0 +chr2 33529075 0 0 0.0 0 +chr2 33700336 0 0 0.0 0 +chr2 33783743 0 0 0.0 0 +chr2 33822684 0 0 0.0 0 +chr2 33960483 0 0 0.0 0 +chr2 34127485 1 25 0.3333 1 +chr2 34226590 0 0 0.0 0 +chr2 34328349 0 0 0.0 0 +chr2 34398903 0 0 0.0 0 +chr2 34467360 0 0 0.0 0 +chr2 34865782 0 0 0.0 0 +chr2 34982972 0 0 0.0 0 +chr2 35140984 0 0 0.0 0 +chr2 35292950 0 0 0.0 0 +chr2 35299925 0 0 0.0 0 +chr2 35311922 0 0 0.0 0 +chr2 35540698 0 0 0.0 0 +chr2 35596023 0 0 0.0 0 +chr2 35693708 0 0 0.0 0 +chr2 35720147 0 0 0.0 0 +chr2 35797665 0 0 0.0 0 +chr2 36058228 0 0 0.0 0 +chr2 36088677 0 0 0.0 0 +chr2 36138173 0 0 0.0 0 +chr2 36187527 0 0 0.0 0 +chr2 36198287 0 0 0.0 0 +chr2 36288474 0 0 0.0 0 +chr2 36308438 0 0 0.0 0 +chr2 36580755 0 0 0.0 0 +chr2 36774543 0 0 0.0 0 +chr2 36818598 0 0 0.0 0 +chr2 36919723 0 0 0.0 0 +chr2 37005673 0 0 0.0 0 +chr2 37184099 0 0 0.0 0 +chr2 37416023 0 0 0.0 0 +chr2 37487227 0 0 0.0 0 +chr2 37767747 0 0 0.0 0 +chr2 37772154 0 0 0.0 0 +chr2 37949615 0 0 0.0 0 +chr2 38041522 0 0 0.0 0 +chr2 38154636 0 0 0.0 0 +chr2 38261660 0 0 0.0 0 +chr2 38417546 0 0 0.0 0 +chr2 38456175 0 0 0.0 0 +chr2 38576011 0 0 0.0 0 +chr2 38650053 0 0 0.0 0 +chr2 38654792 0 0 0.0 0 +chr2 38677440 0 0 0.0 0 +chr2 38876137 0 0 0.0 0 +chr2 39132489 0 0 0.0 0 +chr2 39153544 0 0 0.0 0 +chr2 39380766 0 0 0.0 0 +chr2 39456442 0 0 0.0 0 +chr2 39511536 0 0 0.0 0 +chr2 39830848 0 0 0.0 0 +chr2 39888034 0 0 0.0 0 +chr2 39970618 0 0 0.0 0 +chr2 40014773 0 0 0.0 0 +chr2 40023200 0 0 0.0 0 +chr2 40303763 0 0 0.0 0 +chr2 40326873 0 0 0.0 0 +chr2 40530900 0 0 0.0 0 +chr2 40707886 0 0 0.0 0 +chr2 41077147 0 0 0.0 0 +chr2 41798231 3 21 1.0 1 +chr2 41802482 0 0 0.0 0 +chr2 41893928 0 0 0.0 0 +chr2 41915461 0 0 0.0 0 +chr2 41919475 0 0 0.0 0 +chr2 41929051 0 0 0.0 0 +chr2 41992439 0 0 0.0 0 +chr2 42106074 0 0 0.0 0 +chr2 42210187 0 0 0.0 0 +chr2 42382657 0 1 0.0222 0 +chr2 42524394 0 0 0.0 0 +chr2 42532412 0 0 0.0 0 +chr2 42552598 1 4 0.1212 1 +chr2 42647082 0 0 0.0 0 +chr2 42760886 0 0 0.0 0 +chr2 42786902 0 0 0.0 0 +chr2 42854908 0 0 0.0 0 +chr2 42916065 0 0 0.0 0 +chr2 43016090 0 0 0.0 0 +chr2 43017879 0 0 0.0 0 +chr2 43101945 0 0 0.0 0 +chr2 43159176 0 0 0.0 0 +chr2 43370192 0 0 0.0 0 +chr2 43494387 0 0 0.0 0 +chr2 43508263 0 0 0.0 0 +chr2 43587348 0 0 0.0 0 +chr2 43716699 0 0 0.0 0 +chr2 43849957 0 0 0.0 0 +chr2 44022269 0 0 0.0 0 +chr2 44430832 0 0 0.0 0 +chr2 44478498 0 0 0.0 0 +chr2 44595254 0 0 0.0 0 +chr2 44885158 0 0 0.0 0 +chr2 44893969 0 0 0.0 0 +chr2 44903767 0 0 0.0 0 +chr2 45057789 0 0 0.0 0 +chr2 45072643 0 0 0.0 0 +chr2 45194166 0 0 0.0 0 +chr2 45333984 0 0 0.0 0 +chr2 45373500 0 0 0.0 0 +chr2 45383140 0 0 0.0 0 +chr2 45405014 0 0 0.0 0 +chr2 45411640 0 0 0.0 0 +chr2 45567755 0 0 0.0 0 +chr2 45574996 0 0 0.0 0 +chr2 45672695 0 0 0.0 0 +chr2 45732349 0 0 0.0 0 +chr2 45773327 0 0 0.0 0 +chr2 45794631 0 0 0.0 0 +chr2 45826178 0 0 0.0 0 +chr2 45905219 0 0 0.0 0 +chr2 45908838 0 0 0.0 0 +chr2 46129306 0 0 0.0 0 +chr2 46316937 0 0 0.0 0 +chr2 46354912 0 0 0.0 0 +chr2 46616675 0 0 0.0 0 +chr2 46784682 0 0 0.0 0 +chr2 46802895 0 0 0.0 0 +chr2 46813116 0 0 0.0 0 +chr2 46815388 0 0 0.0 0 +chr2 46870771 0 0 0.0 0 +chr2 46939640 0 0 0.0 0 +chr2 47090726 0 0 0.0 0 +chr2 47207616 0 0 0.0 0 +chr2 47275583 0 0 0.0 0 +chr2 47402662 0 0 0.0 0 +chr2 47434281 0 0 0.0 0 +chr2 47466983 0 0 0.0 0 +chr2 47514160 0 0 0.0 0 +chr2 47518970 0 0 0.0 0 +chr2 47536560 0 0 0.0 0 +chr2 47634387 0 0 0.0 0 +chr2 47682837 0 0 0.0 0 +chr2 47828209 0 0 0.0 0 +chr2 47973278 0 0 0.0 0 +chr2 47974371 0 0 0.0 0 +chr2 48023918 0 0 0.0 0 +chr2 48040618 0 0 0.0 0 +chr2 48113225 0 0 0.0 0 +chr2 48148256 0 0 0.0 0 +chr2 48181919 0 0 0.0 0 +chr2 48461013 0 0 0.0 0 +chr2 48501431 0 0 0.0 0 +chr2 48509880 0 0 0.0 0 +chr2 48566020 0 0 0.0 0 +chr2 48588804 0 0 0.0 0 +chr2 48906255 0 0 0.0 0 +chr2 48991364 0 0 0.0 0 +chr2 49156937 0 0 0.0 0 +chr2 49253623 0 0 0.0 0 +chr2 49276735 0 0 0.0 0 +chr2 49626686 0 0 0.0 0 +chr2 50215440 0 0 0.0 0 +chr2 50242209 0 0 0.0 0 +chr2 50294534 0 0 0.0 0 +chr2 50310279 0 0 0.0 0 +chr2 50331675 0 0 0.0 0 +chr2 50364549 0 0 0.0 0 +chr2 50513991 0 0 0.0 0 +chr2 50666060 0 0 0.0 0 +chr2 50768835 0 0 0.0 0 +chr2 50908569 0 0 0.0 0 +chr2 51026826 0 0 0.0 0 +chr2 51157760 0 0 0.0 0 +chr2 51168995 0 0 0.0 0 +chr2 51458547 0 0 0.0 0 +chr2 51496768 0 0 0.0 0 +chr2 51558648 0 0 0.0 0 +chr2 51566727 0 0 0.0 0 +chr2 51801611 0 0 0.0 0 +chr2 52277291 0 0 0.0 0 +chr2 52359460 0 0 0.0 0 +chr2 52380655 0 0 0.0 0 +chr2 52516545 0 0 0.0 0 +chr2 52540596 0 0 0.0 0 +chr2 52732824 0 0 0.0 0 +chr2 52876579 0 0 0.0 0 +chr2 52886383 0 0 0.0 0 +chr2 52903737 0 0 0.0 0 +chr2 52995276 0 0 0.0 0 +chr2 52998263 0 0 0.0 0 +chr2 53111239 0 0 0.0 0 +chr2 53361334 0 1 0.0137 0 +chr2 53391878 0 0 0.0 0 +chr2 53522523 0 0 0.0 0 +chr2 53686155 0 0 0.0 0 +chr2 53800246 0 0 0.0 0 +chr2 54000014 0 0 0.0 0 +chr2 54001813 0 0 0.0 0 +chr2 54277274 0 0 0.0 0 +chr2 54420824 0 0 0.0 0 +chr2 54455437 0 0 0.0 0 +chr2 54490720 0 0 0.0 0 +chr2 54593513 0 0 0.0 0 +chr2 54786614 0 0 0.0 0 +chr2 54838466 0 0 0.0 0 +chr2 54934673 0 0 0.0 0 +chr2 54939465 0 1 0.0189 0 +chr2 55079205 0 0 0.0 0 +chr2 55153196 0 1 0.0204 0 +chr2 55163589 0 0 0.0 0 +chr2 55251922 0 0 0.0 0 +chr2 55261729 0 0 0.0 0 +chr2 55358145 0 0 0.0 0 +chr2 55377242 0 0 0.0 0 +chr2 55433532 0 0 0.0 0 +chr2 55477854 0 0 0.0 0 +chr2 55490342 0 0 0.0 0 +chr2 55804163 0 0 0.0 0 +chr2 55882861 0 0 0.0 0 +chr2 55909600 0 0 0.0 0 +chr2 55970882 0 0 0.0 0 +chr2 55977533 0 0 0.0 0 +chr2 56051798 0 0 0.0 0 +chr2 56065418 0 1 0.0114 0 +chr2 56292689 0 0 0.0 0 +chr2 56446098 0 0 0.0 0 +chr2 56485293 0 0 0.0 0 +chr2 56491219 0 0 0.0 0 +chr2 56510912 0 0 0.0 0 +chr2 56571098 0 1 0.0115 0 +chr2 56575081 0 0 0.0 0 +chr2 56615275 0 0 0.0 0 +chr2 56736093 0 0 0.0 0 +chr2 56964515 0 0 0.0 0 +chr2 57083923 0 0 0.0 0 +chr2 57165805 0 0 0.0 0 +chr2 57204494 0 0 0.0 0 +chr2 57209647 0 0 0.0 0 +chr2 57532601 0 0 0.0 0 +chr2 57627031 0 0 0.0 0 +chr2 57684860 0 0 0.0 0 +chr2 57729709 0 0 0.0 0 +chr2 57783823 0 0 0.0 0 +chr2 58066831 0 0 0.0 0 +chr2 58143718 0 0 0.0 0 +chr2 58192690 0 0 0.0 0 +chr2 58511004 0 0 0.0 0 +chr2 58778103 0 0 0.0 0 +chr2 58854509 0 0 0.0 0 +chr2 59140117 0 0 0.0 0 +chr2 59231274 0 0 0.0 0 +chr2 59253207 0 0 0.0 0 +chr2 59402769 0 0 0.0 0 +chr2 59411669 0 0 0.0 0 +chr2 59772949 0 0 0.0 0 +chr2 59916142 0 0 0.0 0 +chr2 60055630 0 0 0.0 0 +chr2 60135725 0 0 0.0 0 +chr2 60218150 0 0 0.0 0 +chr2 60234074 0 0 0.0 0 +chr2 60307098 0 0 0.0 0 +chr2 60334698 0 0 0.0 0 +chr2 60361675 0 0 0.0 0 +chr2 60497578 0 0 0.0 0 +chr2 60638886 0 0 0.0 0 +chr2 60768399 0 0 0.0 0 +chr2 60820999 0 0 0.0 0 +chr2 60924202 0 0 0.0 0 +chr2 61022757 0 0 0.0 0 +chr2 61095955 0 0 0.0 0 +chr2 61148955 0 0 0.0 0 +chr2 61184121 0 0 0.0 0 +chr2 61270697 0 0 0.0 0 +chr2 61392235 0 0 0.0 0 +chr2 61417332 0 0 0.0 0 +chr2 61467076 0 0 0.0 0 +chr2 61615601 0 0 0.0 0 +chr2 61695682 0 0 0.0 0 +chr2 61853752 0 0 0.0 0 +chr2 62041450 0 0 0.0 0 +chr2 62135784 0 0 0.0 0 +chr2 62154482 0 0 0.0 0 +chr2 62162530 0 0 0.0 0 +chr2 62177106 0 0 0.0 0 +chr2 62406984 0 0 0.0 0 +chr2 62422293 0 0 0.0 0 +chr2 62465172 0 0 0.0 0 +chr2 62503494 0 0 0.0 0 +chr2 62575134 0 0 0.0 0 +chr2 62633578 0 0 0.0 0 +chr2 62784528 0 0 0.0 0 +chr2 63429255 0 0 0.0 0 +chr2 63470145 0 0 0.0 0 +chr2 63601535 0 0 0.0 0 +chr2 63725660 0 0 0.0 0 +chr2 63965906 0 0 0.0 0 +chr2 64119757 0 0 0.0 0 +chr2 64282662 0 0 0.0 0 +chr2 64426096 0 0 0.0 0 +chr2 64516450 0 0 0.0 0 +chr2 64543237 0 0 0.0 0 +chr2 64575507 0 0 0.0 0 +chr2 64903357 0 0 0.0 0 +chr2 64984148 0 0 0.0 0 +chr2 65160854 0 1 0.0312 0 +chr2 65442086 0 0 0.0 0 +chr2 65494145 0 0 0.0 0 +chr2 65550682 0 0 0.0 0 +chr2 65664324 0 0 0.0 0 +chr2 65750464 0 0 0.0 0 +chr2 65756563 0 0 0.0 0 +chr2 65890245 0 0 0.0 0 +chr2 65985412 0 0 0.0 0 +chr2 66127845 0 0 0.0 0 +chr2 66146681 0 0 0.0 0 +chr2 66240466 0 0 0.0 0 +chr2 66455581 0 0 0.0 0 +chr2 66862291 0 0 0.0 0 +chr2 67005774 0 0 0.0 0 +chr2 67043934 0 0 0.0 0 +chr2 67386464 0 0 0.0 0 +chr2 67393171 0 0 0.0 0 +chr2 67491994 0 0 0.0 0 +chr2 67568472 0 0 0.0 0 +chr2 67670057 0 0 0.0 0 +chr2 67750526 0 0 0.0 0 +chr2 67752752 0 0 0.0 0 +chr2 68122939 0 1 0.025 0 +chr2 68405489 0 0 0.0 0 +chr2 68425519 0 0 0.0 0 +chr2 68428295 0 0 0.0 0 +chr2 68432233 0 0 0.0 0 +chr2 68433545 0 0 0.0 0 +chr2 68447229 0 0 0.0 0 +chr2 68586158 0 0 0.0 0 +chr2 68701985 0 0 0.0 0 +chr2 68739201 0 0 0.0 0 +chr2 68745824 0 0 0.0 0 +chr2 68785710 0 0 0.0 0 +chr2 68799328 0 0 0.0 0 +chr2 68925011 0 0 0.0 0 +chr2 68998518 0 0 0.0 0 +chr2 69080183 0 0 0.0 0 +chr2 69423117 0 0 0.0 0 +chr2 69447199 0 0 0.0 0 +chr2 69500905 0 0 0.0 0 +chr2 69588416 0 0 0.0 0 +chr2 69622409 0 0 0.0 0 +chr2 69715532 0 0 0.0 0 +chr2 69720649 0 0 0.0 0 +chr2 69789704 0 0 0.0 0 +chr2 69870006 0 0 0.0 0 +chr2 69949057 0 0 0.0 0 +chr2 69980113 0 0 0.0 0 +chr2 69993355 0 0 0.0 0 +chr2 70027041 0 0 0.0 0 +chr2 70130142 0 1 0.0147 0 +chr2 70362810 0 0 0.0 0 +chr2 70392937 0 0 0.0 0 +chr2 70464459 0 0 0.0 0 +chr2 70486856 0 0 0.0 0 +chr2 70657620 0 0 0.0 0 +chr2 70682369 0 0 0.0 0 +chr2 70710338 0 0 0.0 0 +chr2 70851568 0 0 0.0 0 +chr2 70920598 0 0 0.0 0 +chr2 70965815 0 0 0.0 0 +chr2 71020753 0 0 0.0 0 +chr2 71176243 0 0 0.0 0 +chr2 71201102 0 0 0.0 0 +chr2 71211873 0 0 0.0 0 +chr2 71435447 0 0 0.0 0 +chr2 71504467 0 0 0.0 0 +chr2 71522949 0 0 0.0 0 +chr2 71545534 0 0 0.0 0 +chr2 71604790 0 0 0.0 0 +chr2 71606310 0 0 0.0 0 +chr2 71636086 0 0 0.0 0 +chr2 71734579 0 0 0.0 0 +chr2 71873731 0 0 0.0 0 +chr2 72013907 0 0 0.0 0 +chr2 72037419 0 0 0.0 0 +chr2 72107355 0 0 0.0 0 +chr2 72137264 0 1 0.0238 0 +chr2 72217715 0 0 0.0 0 +chr2 72326591 0 0 0.0 0 +chr2 72668338 0 0 0.0 0 +chr2 72753684 0 0 0.0 0 +chr2 72781188 0 0 0.0 0 +chr2 72942715 0 0 0.0 0 +chr2 72954175 0 0 0.0 0 +chr2 73051561 0 0 0.0 0 +chr2 73079200 0 0 0.0 0 +chr2 73096629 0 0 0.0 0 +chr2 73111803 0 0 0.0 0 +chr2 73322642 0 0 0.0 0 +chr2 73388839 0 0 0.0 0 +chr2 73552187 0 0 0.0 0 +chr2 73595779 0 0 0.0 0 +chr2 73634583 0 0 0.0 0 +chr2 73654823 0 0 0.0 0 +chr2 73694543 0 0 0.0 0 +chr2 73782933 0 0 0.0 0 +chr2 73846560 0 0 0.0 0 +chr2 73889202 0 0 0.0 0 +chr2 73920198 0 0 0.0 0 +chr2 74074780 0 0 0.0 0 +chr2 74144378 0 1 0.0189 0 +chr2 74154381 0 0 0.0 0 +chr2 74191555 0 0 0.0 0 +chr2 74271820 0 0 0.0 0 +chr2 74344629 0 0 0.0 0 +chr2 74388742 0 0 0.0 0 +chr2 74415786 0 0 0.0 0 +chr2 74417688 0 0 0.0 0 +chr2 74424589 0 0 0.0 0 +chr2 74479235 0 0 0.0 0 +chr2 74480729 0 0 0.0 0 +chr2 74631869 0 0 0.0 0 +chr2 74677288 0 0 0.0 0 +chr2 74778936 0 0 0.0 0 +chr2 74813731 0 0 0.0 0 +chr2 75019978 0 0 0.0 0 +chr2 75050555 0 0 0.0 0 +chr2 75125549 0 0 0.0 0 +chr2 75154909 0 0 0.0 0 +chr2 75180429 0 0 0.0 0 +chr2 75198834 0 0 0.0 0 +chr2 75374200 0 0 0.0 0 +chr2 75488193 0 0 0.0 0 +chr2 75682062 0 0 0.0 0 +chr2 75805403 0 0 0.0 0 +chr2 75948467 0 0 0.0 0 +chr2 76077729 0 0 0.0 0 +chr2 76139582 0 0 0.0 0 +chr2 76149865 0 1 0.0208 0 +chr2 76544832 0 0 0.0 0 +chr2 76663287 0 0 0.0 0 +chr2 77328596 0 0 0.0 0 +chr2 77543351 0 0 0.0 0 +chr2 77559489 0 0 0.0 0 +chr2 77626427 0 0 0.0 0 +chr2 78041912 0 0 0.0 0 +chr2 78122923 0 0 0.0 0 +chr2 78125319 0 0 0.0 0 +chr2 78669730 0 0 0.0 0 +chr2 78677411 0 0 0.0 0 +chr2 78681181 0 0 0.0 0 +chr2 78768765 0 0 0.0 0 +chr2 78889385 0 0 0.0 0 +chr2 79053572 0 0 0.0 0 +chr2 79304031 0 0 0.0 0 +chr2 79368754 0 0 0.0 0 +chr2 79481930 0 0 0.0 0 +chr2 79482862 0 0 0.0 0 +chr2 79499146 0 0 0.0 0 +chr2 79546237 0 0 0.0 0 +chr2 79629474 0 0 0.0 0 +chr2 79653549 0 0 0.0 0 +chr2 79696648 0 0 0.0 0 +chr2 79869293 0 0 0.0 0 +chr2 80102773 0 0 0.0 0 +chr2 80178019 0 1 0.0208 0 +chr2 80403486 0 0 0.0 0 +chr2 80526934 0 1 0.013 0 +chr2 80575694 0 0 0.0 0 +chr2 80815993 0 0 0.0 0 +chr2 80968749 0 0 0.0 0 +chr2 81206385 0 0 0.0 0 +chr2 81242731 0 0 0.0 0 +chr2 81300107 0 0 0.0 0 +chr2 81302707 0 0 0.0 0 +chr2 81658430 0 0 0.0 0 +chr2 81858255 0 0 0.0 0 +chr2 81926499 0 0 0.0 0 +chr2 82188942 0 0 0.0 0 +chr2 82387664 1 31 0.4429 1 +chr2 82470844 0 0 0.0 0 +chr2 82624704 0 0 0.0 0 +chr2 82657317 0 0 0.0 0 +chr2 82673896 0 0 0.0 0 +chr2 82689861 0 0 0.0 0 +chr2 82692877 0 0 0.0 0 +chr2 82845709 0 0 0.0 0 +chr2 83084394 0 0 0.0 0 +chr2 83088301 0 0 0.0 0 +chr2 83264390 0 0 0.0 0 +chr2 83293488 0 0 0.0 0 +chr2 83346024 0 0 0.0 0 +chr2 83447736 0 0 0.0 0 +chr2 83595019 0 0 0.0 0 +chr2 83868576 0 0 0.0 0 +chr2 83913400 0 0 0.0 0 +chr2 83977031 0 0 0.0 0 +chr2 84131094 0 0 0.0 0 +chr2 84131646 0 0 0.0 0 +chr2 84325173 0 0 0.0 0 +chr2 84345301 0 0 0.0 0 +chr2 84348914 0 0 0.0 0 +chr2 84415429 0 0 0.0 0 +chr2 84452405 0 0 0.0 0 +chr2 84495256 0 0 0.0 0 +chr2 84523897 0 0 0.0 0 +chr2 84576756 0 0 0.0 0 +chr2 84726629 0 0 0.0 0 +chr2 84790165 0 0 0.0 0 +chr2 84932607 0 0 0.0 0 +chr2 84977687 0 0 0.0 0 +chr2 84982044 0 0 0.0 0 +chr2 85058446 0 0 0.0 0 +chr2 85109904 0 0 0.0 0 +chr2 85143872 0 0 0.0 0 +chr2 85184808 0 0 0.0 0 +chr2 85217071 0 0 0.0 0 +chr2 85235296 0 0 0.0 0 +chr2 85282883 0 0 0.0 0 +chr2 85374010 0 0 0.0 0 +chr2 85398217 0 0 0.0 0 +chr2 85551149 0 0 0.0 0 +chr2 85558430 0 0 0.0 0 +chr2 85604099 0 0 0.0 0 +chr2 85678704 0 0 0.0 0 +chr2 85682518 0 1 0.025 0 +chr2 85835359 0 0 0.0 0 +chr2 85888593 0 0 0.0 0 +chr2 86134085 0 0 0.0 0 +chr2 86148901 0 0 0.0 0 +chr2 86326950 0 0 0.0 0 +chr2 86361226 1 18 0.4091 1 +chr2 86403546 0 0 0.0 0 +chr2 86436047 0 0 0.0 0 +chr2 86645200 0 0 0.0 0 +chr2 87112523 0 0 0.0 0 +chr2 87255425 0 0 0.0 0 +chr2 87262693 0 0 0.0 0 +chr2 87345932 0 0 0.0 0 +chr2 87377961 0 0 0.0 0 +chr2 87574985 0 0 0.0 0 +chr2 87634821 0 0 0.0 0 +chr2 87920605 0 0 0.0 0 +chr2 88026217 0 0 0.0 0 +chr2 88041978 0 0 0.0 0 +chr2 88103193 0 0 0.0 0 +chr2 88202300 0 0 0.0 0 +chr2 88353075 0 0 0.0 0 +chr2 88480726 0 0 0.0 0 +chr2 88640651 0 0 0.0 0 +chr2 88733177 0 0 0.0 0 +chr2 88764241 0 0 0.0 0 +chr2 88868642 0 0 0.0 0 +chr2 88880815 0 0 0.0 0 +chr2 88891182 0 0 0.0 0 +chr2 88917391 0 0 0.0 0 +chr2 88970555 0 0 0.0 0 +chr2 88992676 0 0 0.0 0 +chr2 89302898 0 0 0.0 0 +chr2 89304980 0 0 0.0 0 +chr2 89568538 0 0 0.0 0 +chr2 89821022 0 0 0.0 0 +chr2 89877486 0 0 0.0 0 +chr2 90075972 0 0 0.0 0 +chr2 90242276 0 0 0.0 0 +chr2 90269988 0 0 0.0 0 +chr2 91546793 0 0 0.0 0 +chr2 91642890 0 0 0.0 0 +chr2 91675321 0 0 0.0 0 +chr2 91873599 0 0 0.0 0 +chr2 91902181 0 0 0.0 0 +chr2 92008272 0 0 0.0 0 +chr2 94191870 0 0 0.0 0 +chr2 94239036 0 0 0.0 0 +chr2 94535009 0 0 0.0 0 +chr2 94535689 0 0 0.0 0 +chr2 94582425 0 0 0.0 0 +chr2 94608733 0 0 0.0 0 +chr2 94613205 0 0 0.0 0 +chr2 94669694 0 0 0.0 0 +chr2 94698439 0 0 0.0 0 +chr2 94732287 0 0 0.0 0 +chr2 94769064 0 1 0.0119 0 +chr2 94786664 0 0 0.0 0 +chr2 95015564 0 0 0.0 0 +chr2 95016888 0 0 0.0 0 +chr2 95206761 0 1 0.0122 0 +chr2 95228003 0 0 0.0 0 +chr2 95240934 0 0 0.0 0 +chr2 95342874 0 0 0.0 0 +chr2 95678658 0 0 0.0 0 +chr2 95698327 0 0 0.0 0 +chr2 95755301 0 0 0.0 0 +chr2 95829700 0 0 0.0 0 +chr2 95835105 0 0 0.0 0 +chr2 95861781 0 0 0.0 0 +chr2 96070956 0 0 0.0 0 +chr2 96152302 0 0 0.0 0 +chr2 96307533 0 0 0.0 0 +chr2 96497745 0 0 0.0 0 +chr2 96527226 0 0 0.0 0 +chr2 96572376 0 0 0.0 0 +chr2 96575171 0 0 0.0 0 +chr2 96593034 0 0 0.0 0 +chr2 96608951 0 0 0.0 0 +chr2 96646295 0 0 0.0 0 +chr2 96762321 0 0 0.0 0 +chr2 96817422 0 0 0.0 0 +chr2 96930382 0 0 0.0 0 +chr2 96958580 0 0 0.0 0 +chr2 97239537 0 0 0.0 0 +chr2 97266646 0 0 0.0 0 +chr2 97306119 0 0 0.0 0 +chr2 97402383 0 0 0.0 0 +chr2 97490547 1 14 0.4 1 +chr2 97517660 0 0 0.0 0 +chr2 97626779 0 0 0.0 0 +chr2 97656316 0 0 0.0 0 +chr2 97714271 0 0 0.0 0 +chr2 97789080 0 1 0.0139 0 +chr2 97809196 0 0 0.0 0 +chr2 98029449 0 0 0.0 0 +chr2 98042357 0 0 0.0 0 +chr2 98058522 0 0 0.0 0 +chr2 98187364 0 0 0.0 0 +chr2 98217869 0 0 0.0 0 +chr2 98359417 0 0 0.0 0 +chr2 98400830 0 0 0.0 0 +chr2 98550598 0 0 0.0 0 +chr2 98572331 0 0 0.0 0 +chr2 98576348 0 0 0.0 0 +chr2 98809739 0 0 0.0 0 +chr2 98903281 0 0 0.0 0 +chr2 99250707 0 0 0.0 0 +chr2 99278036 0 0 0.0 0 +chr2 99377674 0 0 0.0 0 +chr2 99430729 0 0 0.0 0 +chr2 99484089 0 0 0.0 0 +chr2 99952902 0 0 0.0 0 +chr2 100092262 0 0 0.0 0 +chr2 100201404 0 0 0.0 0 +chr2 100218696 0 0 0.0 0 +chr2 100257712 0 0 0.0 0 +chr2 100270706 0 0 0.0 0 +chr2 100399197 0 1 0.0139 0 +chr2 100455179 0 0 0.0 0 +chr2 100584342 0 0 0.0 0 +chr2 100685726 0 0 0.0 0 +chr2 100757165 0 0 0.0 0 +chr2 100805995 0 0 0.0 0 +chr2 100886330 0 0 0.0 0 +chr2 100940894 0 0 0.0 0 +chr2 101019145 0 0 0.0 0 +chr2 101022533 0 0 0.0 0 +chr2 101142525 0 0 0.0 0 +chr2 101243001 0 0 0.0 0 +chr2 101324159 0 1 0.0159 0 +chr2 101339378 0 0 0.0 0 +chr2 101421508 0 0 0.0 0 +chr2 101482924 0 0 0.0 0 +chr2 101518634 0 0 0.0 0 +chr2 101804597 0 0 0.0 0 +chr2 101812371 0 0 0.0 0 +chr2 101852473 0 0 0.0 0 +chr2 101935961 0 0 0.0 0 +chr2 101982080 0 0 0.0 0 +chr2 102092084 0 0 0.0 0 +chr2 102104465 0 0 0.0 0 +chr2 102114885 0 0 0.0 0 +chr2 102127325 0 0 0.0 0 +chr2 102186605 0 0 0.0 0 +chr2 102277144 0 0 0.0 0 +chr2 102389898 0 0 0.0 0 +chr2 102437226 0 0 0.0 0 +chr2 102497289 0 0 0.0 0 +chr2 102528608 0 0 0.0 0 +chr2 102531363 0 1 0.0204 0 +chr2 102536684 0 0 0.0 0 +chr2 102541495 0 0 0.0 0 +chr2 102553183 0 0 0.0 0 +chr2 102596792 0 0 0.0 0 +chr2 102673880 0 0 0.0 0 +chr2 102682490 0 0 0.0 0 +chr2 102759843 0 0 0.0 0 +chr2 102842465 0 0 0.0 0 +chr2 102865079 0 0 0.0 0 +chr2 102912489 0 0 0.0 0 +chr2 102996153 0 0 0.0 0 +chr2 103116153 0 0 0.0 0 +chr2 103201418 0 0 0.0 0 +chr2 103285017 0 0 0.0 0 +chr2 103631040 0 0 0.0 0 +chr2 103814655 0 0 0.0 0 +chr2 104182935 0 0 0.0 0 +chr2 104219140 0 0 0.0 0 +chr2 104247997 0 0 0.0 0 +chr2 104287177 0 0 0.0 0 +chr2 104392475 0 0 0.0 0 +chr2 104433935 0 0 0.0 0 +chr2 104480766 0 0 0.0 0 +chr2 104517769 0 0 0.0 0 +chr2 104652665 0 0 0.0 0 +chr2 104762272 0 0 0.0 0 +chr2 104864893 0 0 0.0 0 +chr2 105075258 0 0 0.0 0 +chr2 105218905 0 0 0.0 0 +chr2 105339579 0 0 0.0 0 +chr2 105572304 0 0 0.0 0 +chr2 105688677 0 0 0.0 0 +chr2 105993171 0 0 0.0 0 +chr2 106053274 0 0 0.0 0 +chr2 106100816 0 0 0.0 0 +chr2 106140329 0 0 0.0 0 +chr2 106192137 0 0 0.0 0 +chr2 106210884 0 0 0.0 0 +chr2 106584785 0 0 0.0 0 +chr2 106661680 0 1 0.0132 0 +chr2 106909296 0 0 0.0 0 +chr2 106950029 0 0 0.0 0 +chr2 106991675 0 0 0.0 0 +chr2 107000048 0 0 0.0 0 +chr2 107089979 0 0 0.0 0 +chr2 107096678 0 0 0.0 0 +chr2 107256254 0 0 0.0 0 +chr2 107277341 0 0 0.0 0 +chr2 107336142 0 0 0.0 0 +chr2 107500024 0 0 0.0 0 +chr2 107800846 0 0 0.0 0 +chr2 108043431 0 1 0.0179 0 +chr2 108084011 0 0 0.0 0 +chr2 108604362 0 0 0.0 0 +chr2 108611636 0 1 0.0161 0 +chr2 108777241 0 0 0.0 0 +chr2 108906785 0 0 0.0 0 +chr2 108929446 0 0 0.0 0 +chr2 109024273 0 0 0.0 0 +chr2 109098131 0 0 0.0 0 +chr2 109118963 0 0 0.0 0 +chr2 109155042 0 0 0.0 0 +chr2 109165403 0 0 0.0 0 +chr2 109220474 0 0 0.0 0 +chr2 109258760 0 0 0.0 0 +chr2 109336518 0 0 0.0 0 +chr2 109340748 0 0 0.0 0 +chr2 109381053 0 0 0.0 0 +chr2 109655693 0 0 0.0 0 +chr2 109725186 0 0 0.0 0 +chr2 109755453 0 0 0.0 0 +chr2 109772922 0 0 0.0 0 +chr2 109781967 0 0 0.0 0 +chr2 109786310 0 0 0.0 0 +chr2 109790146 0 0 0.0 0 +chr2 109889398 0 0 0.0 0 +chr2 109951507 0 0 0.0 0 +chr2 110050828 0 0 0.0 0 +chr2 110094854 0 0 0.0 0 +chr2 110249466 0 0 0.0 0 +chr2 110276535 0 0 0.0 0 +chr2 110320638 0 0 0.0 0 +chr2 110419988 0 0 0.0 0 +chr2 110482109 0 0 0.0 0 +chr2 110581345 0 0 0.0 0 +chr2 110585181 0 0 0.0 0 +chr2 110589524 0 0 0.0 0 +chr2 110598564 0 0 0.0 0 +chr2 110616043 0 0 0.0 0 +chr2 110771429 0 0 0.0 0 +chr2 110806864 0 0 0.0 0 +chr2 110828389 0 0 0.0 0 +chr2 111044406 0 0 0.0 0 +chr2 111097564 0 0 0.0 0 +chr2 111316025 0 0 0.0 0 +chr2 111375832 1 13 0.2 1 +chr2 111606165 0 0 0.0 0 +chr2 111675158 0 0 0.0 0 +chr2 111716519 0 0 0.0 0 +chr2 112044816 0 0 0.0 0 +chr2 112166532 0 0 0.0 0 +chr2 112190279 0 0 0.0 0 +chr2 112209808 0 0 0.0 0 +chr2 112253469 0 0 0.0 0 +chr2 112343651 0 0 0.0 0 +chr2 112791186 0 0 0.0 0 +chr2 112836002 0 0 0.0 0 +chr2 112868429 0 0 0.0 0 +chr2 112895917 0 0 0.0 0 +chr2 113069248 0 0 0.0 0 +chr2 113073077 0 0 0.0 0 +chr2 113320888 0 0 0.0 0 +chr2 113471645 0 0 0.0 0 +chr2 113547611 0 0 0.0 0 +chr2 113828850 0 0 0.0 0 +chr2 113852638 0 0 0.0 0 +chr2 113886926 0 0 0.0 0 +chr2 114201235 0 0 0.0 0 +chr2 114313702 0 0 0.0 0 +chr2 114354979 0 0 0.0 0 +chr2 114473006 0 0 0.0 0 +chr2 114495914 0 0 0.0 0 +chr2 114548006 0 0 0.0 0 +chr2 114562820 0 0 0.0 0 +chr2 114845607 0 0 0.0 0 +chr2 114962854 0 0 0.0 0 +chr2 115225880 0 0 0.0 0 +chr2 115266597 0 0 0.0 0 +chr2 115440937 0 0 0.0 0 +chr2 115550522 0 0 0.0 0 +chr2 115551104 0 0 0.0 0 +chr2 115626679 0 0 0.0 0 +chr2 115677213 0 0 0.0 0 +chr2 115686984 0 0 0.0 0 +chr2 115812928 0 0 0.0 0 +chr2 116065634 0 0 0.0 0 +chr2 116252533 0 0 0.0 0 +chr2 116260020 0 1 0.0238 0 +chr2 116296105 0 0 0.0 0 +chr2 116299205 0 0 0.0 0 +chr2 116385183 0 0 0.0 0 +chr2 116390721 0 0 0.0 0 +chr2 116413719 0 0 0.0 0 +chr2 116428803 0 0 0.0 0 +chr2 116545067 0 0 0.0 0 +chr2 116576090 0 0 0.0 0 +chr2 116662335 0 0 0.0 0 +chr2 116727991 0 0 0.0 0 +chr2 117030143 0 0 0.0 0 +chr2 117039366 0 0 0.0 0 +chr2 117300035 0 0 0.0 0 +chr2 117472802 0 0 0.0 0 +chr2 117544649 0 0 0.0 0 +chr2 117571818 0 0 0.0 0 +chr2 117572187 0 0 0.0 0 +chr2 117721312 0 0 0.0 0 +chr2 117800186 0 0 0.0 0 +chr2 117802158 0 0 0.0 0 +chr2 117828977 0 0 0.0 0 +chr2 117854232 0 0 0.0 0 +chr2 117972563 0 0 0.0 0 +chr2 118089791 0 0 0.0 0 +chr2 118090620 0 0 0.0 0 +chr2 118109127 0 0 0.0 0 +chr2 118121398 0 0 0.0 0 +chr2 118236818 0 0 0.0 0 +chr2 118279542 0 0 0.0 0 +chr2 118386192 0 0 0.0 0 +chr2 118426860 0 0 0.0 0 +chr2 118495864 0 0 0.0 0 +chr2 118656082 0 0 0.0 0 +chr2 118785619 0 0 0.0 0 +chr2 118882350 0 0 0.0 0 +chr2 118979546 0 0 0.0 0 +chr2 118992963 0 0 0.0 0 +chr2 119247947 0 0 0.0 0 +chr2 119379853 0 0 0.0 0 +chr2 119387956 0 0 0.0 0 +chr2 119447952 0 0 0.0 0 +chr2 119488213 0 0 0.0 0 +chr2 119517823 0 0 0.0 0 +chr2 119543624 0 0 0.0 0 +chr2 119660086 0 0 0.0 0 +chr2 119740675 0 0 0.0 0 +chr2 119914323 0 0 0.0 0 +chr2 119971221 0 0 0.0 0 +chr2 120059588 0 0 0.0 0 +chr2 120188973 0 0 0.0 0 +chr2 120232416 0 0 0.0 0 +chr2 120237708 0 0 0.0 0 +chr2 120480374 0 0 0.0 0 +chr2 120512063 0 0 0.0 0 +chr2 120517931 0 0 0.0 0 +chr2 120522388 0 0 0.0 0 +chr2 120558238 0 0 0.0 0 +chr2 120604084 0 0 0.0 0 +chr2 120632409 0 0 0.0 0 +chr2 120657236 0 0 0.0 0 +chr2 120771492 0 0 0.0 0 +chr2 120777629 0 0 0.0 0 +chr2 120781222 0 0 0.0 0 +chr2 120784577 0 0 0.0 0 +chr2 120813263 0 0 0.0 0 +chr2 120847826 0 0 0.0 0 +chr2 120873641 0 0 0.0 0 +chr2 120942710 0 0 0.0 0 +chr2 121150645 0 1 0.0115 0 +chr2 121178455 0 0 0.0 0 +chr2 121232502 0 0 0.0 0 +chr2 121296578 0 0 0.0 0 +chr2 121355812 0 0 0.0 0 +chr2 121455333 0 0 0.0 0 +chr2 121641569 0 0 0.0 0 +chr2 121705699 0 0 0.0 0 +chr2 121711233 0 0 0.0 0 +chr2 121760728 0 0 0.0 0 +chr2 121808913 0 0 0.0 0 +chr2 121820137 0 0 0.0 0 +chr2 121870987 0 0 0.0 0 +chr2 121877411 0 0 0.0 0 +chr2 121884193 0 0 0.0 0 +chr2 121895068 0 0 0.0 0 +chr2 121922287 0 1 0.0141 0 +chr2 122102859 0 0 0.0 0 +chr2 122195581 0 0 0.0 0 +chr2 122290834 0 0 0.0 0 +chr2 122373078 0 0 0.0 0 +chr2 122562594 0 0 0.0 0 +chr2 122772369 0 0 0.0 0 +chr2 123052912 0 0 0.0 0 +chr2 123206295 0 1 0.0217 0 +chr2 123404440 0 0 0.0 0 +chr2 123434052 0 1 0.0152 0 +chr2 123548750 0 0 0.0 0 +chr2 123580891 0 0 0.0 0 +chr2 123742404 0 0 0.0 0 +chr2 123803862 0 0 0.0 0 +chr2 123893539 0 0 0.0 0 +chr2 123908059 0 0 0.0 0 +chr2 123982904 0 0 0.0 0 +chr2 124123754 0 0 0.0 0 +chr2 124132819 0 0 0.0 0 +chr2 124287320 0 0 0.0 0 +chr2 124468854 0 0 0.0 0 +chr2 124565038 0 0 0.0 0 +chr2 124626849 0 0 0.0 0 +chr2 124633465 0 0 0.0 0 +chr2 124741276 0 0 0.0 0 +chr2 124763782 0 0 0.0 0 +chr2 124896022 0 0 0.0 0 +chr2 124914227 0 0 0.0 0 +chr2 125002783 0 0 0.0 0 +chr2 125393469 0 0 0.0 0 +chr2 125444578 0 0 0.0 0 +chr2 125680761 0 0 0.0 0 +chr2 125770563 0 0 0.0 0 +chr2 126085721 0 0 0.0 0 +chr2 126095598 0 0 0.0 0 +chr2 126237747 0 0 0.0 0 +chr2 126326884 0 0 0.0 0 +chr2 126373479 0 0 0.0 0 +chr2 126786201 0 0 0.0 0 +chr2 126803838 0 0 0.0 0 +chr2 126819513 0 0 0.0 0 +chr2 127059840 0 0 0.0 0 +chr2 127070125 0 0 0.0 0 +chr2 127098015 0 0 0.0 0 +chr2 127143655 0 0 0.0 0 +chr2 127162458 0 0 0.0 0 +chr2 127390244 0 0 0.0 0 +chr2 127405835 0 0 0.0 0 +chr2 127469412 0 0 0.0 0 +chr2 127512099 0 0 0.0 0 +chr2 127646605 0 0 0.0 0 +chr2 127818652 0 0 0.0 0 +chr2 128169538 0 0 0.0 0 +chr2 128340477 0 0 0.0 0 +chr2 128447918 0 0 0.0 0 +chr2 128457092 0 0 0.0 0 +chr2 128508980 0 0 0.0 0 +chr2 128559660 0 1 0.0185 0 +chr2 128627295 0 0 0.0 0 +chr2 128659936 0 0 0.0 0 +chr2 128734878 0 0 0.0 0 +chr2 128735206 0 0 0.0 0 +chr2 128755294 0 1 0.0217 0 +chr2 128833385 0 0 0.0 0 +chr2 129004522 0 0 0.0 0 +chr2 129070962 0 0 0.0 0 +chr2 129074886 0 0 0.0 0 +chr2 129145801 0 0 0.0 0 +chr2 129187090 0 0 0.0 0 +chr2 129230147 0 0 0.0 0 +chr2 129322125 0 0 0.0 0 +chr2 129369079 0 0 0.0 0 +chr2 129577480 0 0 0.0 0 +chr2 129773679 0 0 0.0 0 +chr2 129823395 0 0 0.0 0 +chr2 129825878 0 0 0.0 0 +chr2 129901617 0 0 0.0 0 +chr2 130098877 0 0 0.0 0 +chr2 130164537 0 0 0.0 0 +chr2 130174650 0 0 0.0 0 +chr2 130178420 0 0 0.0 0 +chr2 130356666 0 0 0.0 0 +chr2 130487440 0 0 0.0 0 +chr2 130633249 0 0 0.0 0 +chr2 130798112 0 0 0.0 0 +chr2 130916498 0 0 0.0 0 +chr2 130925540 0 0 0.0 0 +chr2 130999247 0 1 0.0179 0 +chr2 131073414 0 1 0.0152 0 +chr2 131197727 0 0 0.0 0 +chr2 131240037 0 0 0.0 0 +chr2 131499219 0 0 0.0 0 +chr2 131508446 0 0 0.0 0 +chr2 131782720 0 0 0.0 0 +chr2 131832768 0 0 0.0 0 +chr2 131992143 0 0 0.0 0 +chr2 132143302 0 0 0.0 0 +chr2 132224279 0 0 0.0 0 +chr2 132229766 0 0 0.0 0 +chr2 132354162 0 0 0.0 0 +chr2 132393170 0 0 0.0 0 +chr2 132429427 0 0 0.0 0 +chr2 132513756 0 0 0.0 0 +chr2 132650397 0 0 0.0 0 +chr2 132678335 0 0 0.0 0 +chr2 132696517 0 0 0.0 0 +chr2 132868487 0 0 0.0 0 +chr2 132915182 0 0 0.0 0 +chr2 132948735 0 0 0.0 0 +chr2 132959363 0 0 0.0 0 +chr2 133014565 0 0 0.0 0 +chr2 133054800 0 0 0.0 0 +chr2 133070980 0 0 0.0 0 +chr2 133110371 0 0 0.0 0 +chr2 133119119 0 0 0.0 0 +chr2 133264820 0 0 0.0 0 +chr2 133425905 0 0 0.0 0 +chr2 133573401 0 0 0.0 0 +chr2 133599449 0 0 0.0 0 +chr2 133601319 0 0 0.0 0 +chr2 133604733 0 0 0.0 0 +chr2 133693924 0 0 0.0 0 +chr2 133785681 0 0 0.0 0 +chr2 134043952 0 0 0.0 0 +chr2 134073142 0 0 0.0 0 +chr2 134078162 0 0 0.0 0 +chr2 134150747 0 0 0.0 0 +chr2 134485933 0 0 0.0 0 +chr2 134579556 0 1 0.013 0 +chr2 134704385 0 0 0.0 0 +chr2 134751799 0 0 0.0 0 +chr2 134762231 0 0 0.0 0 +chr2 134818686 0 0 0.0 0 +chr2 134819767 0 0 0.0 0 +chr2 134907065 0 0 0.0 0 +chr2 134908144 0 0 0.0 0 +chr2 134909983 0 0 0.0 0 +chr2 135158604 0 0 0.0 0 +chr2 135333491 0 0 0.0 0 +chr2 135538875 0 0 0.0 0 +chr2 135553167 0 0 0.0 0 +chr2 135816672 0 0 0.0 0 +chr2 135876606 0 0 0.0 0 +chr2 136614508 0 0 0.0 0 +chr2 136622815 0 0 0.0 0 +chr2 136751133 0 0 0.0 0 +chr2 136782210 0 0 0.0 0 +chr2 136803805 0 0 0.0 0 +chr2 136823873 0 0 0.0 0 +chr2 136875179 0 0 0.0 0 +chr2 137075869 0 0 0.0 0 +chr2 137099518 0 0 0.0 0 +chr2 137099900 0 0 0.0 0 +chr2 137111125 0 0 0.0 0 +chr2 137185109 0 0 0.0 0 +chr2 137408780 0 0 0.0 0 +chr2 137707764 0 0 0.0 0 +chr2 137978034 0 0 0.0 0 +chr2 138017127 0 0 0.0 0 +chr2 138091437 0 0 0.0 0 +chr2 138170223 0 0 0.0 0 +chr2 138234607 0 0 0.0 0 +chr2 138331187 0 0 0.0 0 +chr2 138351584 0 0 0.0 0 +chr2 138652115 0 0 0.0 0 +chr2 138663891 0 0 0.0 0 +chr2 138711776 0 0 0.0 0 +chr2 138732792 0 0 0.0 0 +chr2 138796791 0 0 0.0 0 +chr2 138834091 0 0 0.0 0 +chr2 139013629 0 0 0.0 0 +chr2 139166626 0 0 0.0 0 +chr2 139406587 0 0 0.0 0 +chr2 139781724 0 0 0.0 0 +chr2 140011715 0 0 0.0 0 +chr2 140298648 0 0 0.0 0 +chr2 140390968 0 0 0.0 0 +chr2 140498629 0 0 0.0 0 +chr2 140690685 0 0 0.0 0 +chr2 140700394 0 0 0.0 0 +chr2 140804044 0 1 0.0233 0 +chr2 141038395 0 0 0.0 0 +chr2 141128393 0 0 0.0 0 +chr2 141453427 0 0 0.0 0 +chr2 141457154 0 0 0.0 0 +chr2 141463748 0 0 0.0 0 +chr2 141579463 0 0 0.0 0 +chr2 141662043 0 0 0.0 0 +chr2 141764605 0 0 0.0 0 +chr2 141781170 0 0 0.0 0 +chr2 141903233 0 0 0.0 0 +chr2 142246751 0 0 0.0 0 +chr2 142296057 0 0 0.0 0 +chr2 142469386 0 0 0.0 0 +chr2 142655148 0 0 0.0 0 +chr2 142728729 0 0 0.0 0 +chr2 142813555 0 0 0.0 0 +chr2 143021680 0 0 0.0 0 +chr2 143060557 0 1 0.0182 0 +chr2 143062451 0 0 0.0 0 +chr2 143173554 0 0 0.0 0 +chr2 143208006 0 0 0.0 0 +chr2 143247923 0 0 0.0 0 +chr2 143649342 0 0 0.0 0 +chr2 143783559 0 0 0.0 0 +chr2 143843691 0 0 0.0 0 +chr2 143868794 0 0 0.0 0 +chr2 144099156 0 0 0.0 0 +chr2 144147613 0 0 0.0 0 +chr2 144288277 0 0 0.0 0 +chr2 144306520 0 0 0.0 0 +chr2 144399463 0 0 0.0 0 +chr2 144429934 0 0 0.0 0 +chr2 144436537 0 0 0.0 0 +chr2 144690810 0 0 0.0 0 +chr2 144703446 0 0 0.0 0 +chr2 144785570 0 0 0.0 0 +chr2 145051101 0 0 0.0 0 +chr2 145054267 0 1 0.0156 0 +chr2 145129112 0 0 0.0 0 +chr2 145163936 0 0 0.0 0 +chr2 145292185 0 0 0.0 0 +chr2 145399731 0 0 0.0 0 +chr2 145416885 0 0 0.0 0 +chr2 145449915 0 0 0.0 0 +chr2 145482322 0 0 0.0 0 +chr2 145560448 1 5 0.0725 1 +chr2 145570969 0 0 0.0 0 +chr2 145642600 0 0 0.0 0 +chr2 145856363 0 0 0.0 0 +chr2 145960587 0 0 0.0 0 +chr2 146013798 0 0 0.0 0 +chr2 146137829 0 0 0.0 0 +chr2 146222576 0 0 0.0 0 +chr2 146380222 0 0 0.0 0 +chr2 146399695 0 0 0.0 0 +chr2 146720091 0 0 0.0 0 +chr2 147129457 0 0 0.0 0 +chr2 147225476 0 0 0.0 0 +chr2 147257394 0 0 0.0 0 +chr2 147280209 0 0 0.0 0 +chr2 147382474 0 0 0.0 0 +chr2 147410151 0 0 0.0 0 +chr2 147586329 0 0 0.0 0 +chr2 147620238 0 0 0.0 0 +chr2 147707994 0 0 0.0 0 +chr2 147825178 0 0 0.0 0 +chr2 147889161 0 0 0.0 0 +chr2 147963720 0 0 0.0 0 +chr2 148087168 0 0 0.0 0 +chr2 148184274 0 0 0.0 0 +chr2 148268717 0 0 0.0 0 +chr2 148343388 0 0 0.0 0 +chr2 148375928 0 0 0.0 0 +chr2 148422284 0 0 0.0 0 +chr2 148470716 0 0 0.0 0 +chr2 148511221 0 0 0.0 0 +chr2 148525548 0 0 0.0 0 +chr2 148710910 0 0 0.0 0 +chr2 149164439 0 0 0.0 0 +chr2 149442717 0 0 0.0 0 +chr2 149493693 0 0 0.0 0 +chr2 149501065 0 0 0.0 0 +chr2 149763595 0 0 0.0 0 +chr2 149848092 0 0 0.0 0 +chr2 149956209 0 0 0.0 0 +chr2 150124693 0 0 0.0 0 +chr2 150147630 0 0 0.0 0 +chr2 150193025 0 0 0.0 0 +chr2 150265478 0 1 0.0455 0 +chr2 150311586 0 0 0.0 0 +chr2 150319444 0 0 0.0 0 +chr2 150332366 0 0 0.0 0 +chr2 150350186 0 0 0.0 0 +chr2 150362825 0 0 0.0 0 +chr2 150675958 0 0 0.0 0 +chr2 150688070 0 0 0.0 0 +chr2 150719926 0 0 0.0 0 +chr2 150980788 0 0 0.0 0 +chr2 150982269 0 0 0.0 0 +chr2 151001840 0 0 0.0 0 +chr2 151163081 0 0 0.0 0 +chr2 151261392 0 0 0.0 0 +chr2 151574067 0 0 0.0 0 +chr2 151575591 0 0 0.0 0 +chr2 151629337 0 0 0.0 0 +chr2 151754688 0 0 0.0 0 +chr2 152079039 0 0 0.0 0 +chr2 152257732 0 0 0.0 0 +chr2 152279194 0 0 0.0 0 +chr2 152339262 1 13 0.2549 1 +chr2 152896169 0 0 0.0 0 +chr2 152922264 0 0 0.0 0 +chr2 152956951 0 0 0.0 0 +chr2 152996589 0 0 0.0 0 +chr2 153207566 0 0 0.0 0 +chr2 153245489 0 0 0.0 0 +chr2 153328676 0 0 0.0 0 +chr2 153572110 0 0 0.0 0 +chr2 153593913 0 0 0.0 0 +chr2 154018342 0 0 0.0 0 +chr2 154078840 0 0 0.0 0 +chr2 154109829 0 0 0.0 0 +chr2 154345484 0 0 0.0 0 +chr2 154375505 0 0 0.0 0 +chr2 154541099 0 0 0.0 0 +chr2 154712585 0 0 0.0 0 +chr2 154785905 0 0 0.0 0 +chr2 154892689 0 0 0.0 0 +chr2 154909253 0 0 0.0 0 +chr2 155240025 0 0 0.0 0 +chr2 155416761 0 0 0.0 0 +chr2 155417397 0 0 0.0 0 +chr2 155592290 0 0 0.0 0 +chr2 155622025 0 0 0.0 0 +chr2 155644597 0 0 0.0 0 +chr2 155716897 0 0 0.0 0 +chr2 155748771 0 1 0.0208 0 +chr2 155989587 0 0 0.0 0 +chr2 156038787 0 0 0.0 0 +chr2 156114392 0 0 0.0 0 +chr2 156665965 0 0 0.0 0 +chr2 156728072 0 0 0.0 0 +chr2 156852908 0 0 0.0 0 +chr2 157126261 0 0 0.0 0 +chr2 157164935 0 0 0.0 0 +chr2 157185138 0 0 0.0 0 +chr2 157258590 0 0 0.0 0 +chr2 157262528 0 1 0.0233 0 +chr2 157358811 0 1 0.0147 0 +chr2 157410356 0 0 0.0 0 +chr2 157590991 0 0 0.0 0 +chr2 157601660 0 0 0.0 0 +chr2 157705314 0 0 0.0 0 +chr2 157771933 0 0 0.0 0 +chr2 157782186 0 0 0.0 0 +chr2 157949584 0 0 0.0 0 +chr2 158158012 0 0 0.0 0 +chr2 158460473 0 0 0.0 0 +chr2 158464762 0 0 0.0 0 +chr2 158574760 0 0 0.0 0 +chr2 158616539 0 0 0.0 0 +chr2 158767297 0 0 0.0 0 +chr2 158776597 0 0 0.0 0 +chr2 158882541 0 0 0.0 0 +chr2 159091241 0 0 0.0 0 +chr2 159289064 0 0 0.0 0 +chr2 159372453 0 0 0.0 0 +chr2 159624544 0 0 0.0 0 +chr2 159642817 0 0 0.0 0 +chr2 159666350 0 0 0.0 0 +chr2 159710073 0 0 0.0 0 +chr2 159736772 0 0 0.0 0 +chr2 159785853 0 0 0.0 0 +chr2 159798346 0 0 0.0 0 +chr2 159822331 0 0 0.0 0 +chr2 159926566 0 0 0.0 0 +chr2 159984569 0 0 0.0 0 +chr2 160064219 0 0 0.0 0 +chr2 160075700 0 0 0.0 0 +chr2 160234517 0 0 0.0 0 +chr2 160249431 0 0 0.0 0 +chr2 160286996 0 0 0.0 0 +chr2 160287683 0 0 0.0 0 +chr2 160428551 0 0 0.0 0 +chr2 160488057 0 0 0.0 0 +chr2 160578175 0 0 0.0 0 +chr2 160637619 0 0 0.0 0 +chr2 160668510 0 0 0.0 0 +chr2 160685713 0 0 0.0 0 +chr2 160812206 0 0 0.0 0 +chr2 160826260 0 0 0.0 0 +chr2 160983872 0 0 0.0 0 +chr2 161078542 0 0 0.0 0 +chr2 161092822 0 0 0.0 0 +chr2 161133817 0 0 0.0 0 +chr2 161170651 0 0 0.0 0 +chr2 161370165 0 0 0.0 0 +chr2 161421819 0 0 0.0 0 +chr2 161479711 0 0 0.0 0 +chr2 161482085 0 0 0.0 0 +chr2 161571939 0 0 0.0 0 +chr2 161876669 0 0 0.0 0 +chr2 161880369 0 0 0.0 0 +chr2 161915097 0 0 0.0 0 +chr2 161944832 0 0 0.0 0 +chr2 162109508 0 0 0.0 0 +chr2 162310547 0 0 0.0 0 +chr2 162507506 0 0 0.0 0 +chr2 162560595 0 0 0.0 0 +chr2 162735302 0 0 0.0 0 +chr2 162994449 0 0 0.0 0 +chr2 163061667 0 0 0.0 0 +chr2 163239144 0 0 0.0 0 +chr2 163413884 0 0 0.0 0 +chr2 163430441 0 0 0.0 0 +chr2 163614002 0 0 0.0 0 +chr2 164151467 0 0 0.0 0 +chr2 164211263 0 0 0.0 0 +chr2 164220603 0 0 0.0 0 +chr2 164336635 0 0 0.0 0 +chr2 164387747 0 0 0.0 0 +chr2 164437230 0 0 0.0 0 +chr2 164611759 0 0 0.0 0 +chr2 164653773 0 0 0.0 0 +chr2 164739607 0 0 0.0 0 +chr2 164841024 0 0 0.0 0 +chr2 165021299 0 0 0.0 0 +chr2 165105260 0 0 0.0 0 +chr2 165186349 0 0 0.0 0 +chr2 165326821 0 0 0.0 0 +chr2 165469562 0 0 0.0 0 +chr2 165864533 0 0 0.0 0 +chr2 166011260 0 0 0.0 0 +chr2 166069022 0 0 0.0 0 +chr2 166076858 3 48 0.8889 1 +chr2 166511449 0 0 0.0 0 +chr2 166526781 0 1 0.0152 0 +chr2 166582072 0 0 0.0 0 +chr2 166771657 0 0 0.0 0 +chr2 167088419 0 0 0.0 0 +chr2 167089720 0 0 0.0 0 +chr2 167099376 0 0 0.0 0 +chr2 167122368 0 0 0.0 0 +chr2 167159900 0 0 0.0 0 +chr2 167236388 0 0 0.0 0 +chr2 167272284 1 26 0.3824 1 +chr2 167436579 0 0 0.0 0 +chr2 167470874 0 0 0.0 0 +chr2 167500928 0 0 0.0 0 +chr2 167559191 0 0 0.0 0 +chr2 167597615 0 0 0.0 0 +chr2 167609661 0 0 0.0 0 +chr2 167726499 0 0 0.0 0 +chr2 167843435 0 0 0.0 0 +chr2 168170163 0 0 0.0 0 +chr2 168229427 0 0 0.0 0 +chr2 168328112 0 0 0.0 0 +chr2 168468697 0 0 0.0 0 +chr2 168817305 0 0 0.0 0 +chr2 169083530 0 0 0.0 0 +chr2 169105731 0 0 0.0 0 +chr2 169606520 0 0 0.0 0 +chr2 169673682 0 0 0.0 0 +chr2 169693013 0 0 0.0 0 +chr2 169704039 0 0 0.0 0 +chr2 169708853 0 1 0.0118 0 +chr2 169719399 0 0 0.0 0 +chr2 169813765 0 0 0.0 0 +chr2 169984423 0 0 0.0 0 +chr2 170004270 0 0 0.0 0 +chr2 170227969 0 0 0.0 0 +chr2 170268210 0 0 0.0 0 +chr2 170316640 0 0 0.0 0 +chr2 170388431 0 0 0.0 0 +chr2 170389903 0 0 0.0 0 +chr2 170419523 0 0 0.0 0 +chr2 170459643 0 1 0.0154 0 +chr2 170500541 0 0 0.0 0 +chr2 170520975 0 0 0.0 0 +chr2 170563444 0 0 0.0 0 +chr2 170708193 0 0 0.0 0 +chr2 170826628 0 0 0.0 0 +chr2 170863916 0 0 0.0 0 +chr2 170920057 0 0 0.0 0 +chr2 171032765 0 0 0.0 0 +chr2 171069778 0 0 0.0 0 +chr2 171091937 0 0 0.0 0 +chr2 171149488 0 0 0.0 0 +chr2 171229558 0 0 0.0 0 +chr2 171384265 0 0 0.0 0 +chr2 171449540 0 0 0.0 0 +chr2 171562465 0 0 0.0 0 +chr2 171563295 0 0 0.0 0 +chr2 171570864 0 0 0.0 0 +chr2 171610653 0 0 0.0 0 +chr2 171812622 0 0 0.0 0 +chr2 171910282 0 0 0.0 0 +chr2 171912110 0 0 0.0 0 +chr2 171973157 0 0 0.0 0 +chr2 172005051 0 0 0.0 0 +chr2 172143921 0 0 0.0 0 +chr2 172192550 0 0 0.0 0 +chr2 172343600 0 0 0.0 0 +chr2 172908900 0 0 0.0 0 +chr2 172922302 0 0 0.0 0 +chr2 173003273 0 0 0.0 0 +chr2 173109039 0 0 0.0 0 +chr2 173333971 0 0 0.0 0 +chr2 173339990 0 0 0.0 0 +chr2 173377648 0 0 0.0 0 +chr2 173581368 0 0 0.0 0 +chr2 173721527 0 0 0.0 0 +chr2 173837862 0 0 0.0 0 +chr2 173860311 0 0 0.0 0 +chr2 173874241 0 0 0.0 0 +chr2 173908973 0 0 0.0 0 +chr2 174070064 0 0 0.0 0 +chr2 174296716 0 0 0.0 0 +chr2 174320568 0 0 0.0 0 +chr2 174446507 0 0 0.0 0 +chr2 174517454 0 0 0.0 0 +chr2 174601662 0 0 0.0 0 +chr2 174661898 0 0 0.0 0 +chr2 174709583 0 0 0.0 0 +chr2 174718759 0 0 0.0 0 +chr2 174778432 0 0 0.0 0 +chr2 174807529 0 0 0.0 0 +chr2 174837310 0 0 0.0 0 +chr2 174949714 0 0 0.0 0 +chr2 175023182 0 0 0.0 0 +chr2 175039584 0 0 0.0 0 +chr2 175270724 0 0 0.0 0 +chr2 175342751 0 0 0.0 0 +chr2 175379340 0 0 0.0 0 +chr2 175453402 0 0 0.0 0 +chr2 175552567 0 0 0.0 0 +chr2 175731214 0 0 0.0 0 +chr2 175811056 0 0 0.0 0 +chr2 176016109 0 0 0.0 0 +chr2 176056593 0 0 0.0 0 +chr2 176217524 0 0 0.0 0 +chr2 176292461 0 0 0.0 0 +chr2 176345946 0 0 0.0 0 +chr2 176473329 0 0 0.0 0 +chr2 176505091 0 0 0.0 0 +chr2 176878029 0 0 0.0 0 +chr2 176963313 0 0 0.0 0 +chr2 177008856 0 0 0.0 0 +chr2 177160785 0 0 0.0 0 +chr2 177220239 0 0 0.0 0 +chr2 177336137 0 0 0.0 0 +chr2 177338189 0 0 0.0 0 +chr2 177518935 0 0 0.0 0 +chr2 177548432 0 0 0.0 0 +chr2 177673820 0 0 0.0 0 +chr2 177708919 0 0 0.0 0 +chr2 177792712 0 0 0.0 0 +chr2 177836750 0 0 0.0 0 +chr2 177916853 0 0 0.0 0 +chr2 178155996 0 0 0.0 0 +chr2 178246438 0 1 0.0182 0 +chr2 178364246 0 0 0.0 0 +chr2 178449080 0 0 0.0 0 +chr2 178498417 0 0 0.0 0 +chr2 178559779 0 0 0.0 0 +chr2 178620495 0 0 0.0 0 +chr2 178786837 0 0 0.0 0 +chr2 178997478 0 0 0.0 0 +chr2 179123235 0 0 0.0 0 +chr2 179324307 0 0 0.0 0 +chr2 179343171 0 0 0.0 0 +chr2 179359872 0 0 0.0 0 +chr2 179452182 0 0 0.0 0 +chr2 179545157 0 0 0.0 0 +chr2 179800720 0 0 0.0 0 +chr2 179881582 0 0 0.0 0 +chr2 180084088 0 0 0.0 0 +chr2 180129692 0 0 0.0 0 +chr2 180232998 0 0 0.0 0 +chr2 180307468 0 0 0.0 0 +chr2 180508681 0 0 0.0 0 +chr2 180676754 0 0 0.0 0 +chr2 180706515 0 0 0.0 0 +chr2 180882858 0 0 0.0 0 +chr2 181029881 0 0 0.0 0 +chr2 181102528 0 0 0.0 0 +chr2 181146031 0 0 0.0 0 +chr2 181362066 0 0 0.0 0 +chr2 181364107 0 0 0.0 0 +chr2 181367062 0 0 0.0 0 +chr2 181376324 0 0 0.0 0 +chr2 181399037 0 0 0.0 0 +chr2 181496966 0 0 0.0 0 +chr2 181760060 0 0 0.0 0 +chr2 181956066 0 0 0.0 0 +chr2 182064117 0 0 0.0 0 +chr2 182411539 0 0 0.0 0 +chr2 182605911 0 0 0.0 0 +chr2 182717228 0 0 0.0 0 +chr2 182830811 0 0 0.0 0 +chr2 183069549 0 0 0.0 0 +chr2 183155512 0 0 0.0 0 +chr2 183354623 0 0 0.0 0 +chr2 183416896 0 0 0.0 0 +chr2 183559310 0 0 0.0 0 +chr2 183730820 0 0 0.0 0 +chr2 184048630 0 1 0.0196 0 +chr2 184279325 0 0 0.0 0 +chr2 184433163 0 0 0.0 0 +chr2 184814751 0 0 0.0 0 +chr2 185092052 0 0 0.0 0 +chr2 185242719 0 0 0.0 0 +chr2 185275522 0 0 0.0 0 +chr2 185376892 0 0 0.0 0 +chr2 185629756 0 0 0.0 0 +chr2 185629912 0 0 0.0 0 +chr2 185737658 0 2 0.029 0 +chr2 185786637 0 0 0.0 0 +chr2 185944023 0 0 0.0 0 +chr2 186032030 0 0 0.0 0 +chr2 186090118 0 0 0.0 0 +chr2 186119989 0 0 0.0 0 +chr2 186231197 0 0 0.0 0 +chr2 186337168 0 0 0.0 0 +chr2 186533109 0 0 0.0 0 +chr2 186595189 0 0 0.0 0 +chr2 186657350 0 0 0.0 0 +chr2 186737481 0 0 0.0 0 +chr2 186812380 0 0 0.0 0 +chr2 186820029 0 0 0.0 0 +chr2 186832418 0 0 0.0 0 +chr2 186863986 0 0 0.0 0 +chr2 186870600 0 0 0.0 0 +chr2 187115556 0 0 0.0 0 +chr2 187133872 0 0 0.0 0 +chr2 187538357 0 0 0.0 0 +chr2 187541419 0 0 0.0 0 +chr2 187651958 0 0 0.0 0 +chr2 187800297 0 0 0.0 0 +chr2 187993717 0 0 0.0 0 +chr2 188229200 0 1 0.0263 0 +chr2 188346730 0 0 0.0 0 +chr2 188429802 0 0 0.0 0 +chr2 188516294 0 0 0.0 0 +chr2 189030315 0 0 0.0 0 +chr2 189184671 0 0 0.0 0 +chr2 189575607 0 0 0.0 0 +chr2 189603356 0 0 0.0 0 +chr2 189752547 0 0 0.0 0 +chr2 189893104 0 0 0.0 0 +chr2 189919129 0 0 0.0 0 +chr2 190191054 0 0 0.0 0 +chr2 190409031 0 0 0.0 0 +chr2 190448229 0 0 0.0 0 +chr2 190534295 0 0 0.0 0 +chr2 190546994 0 0 0.0 0 +chr2 191051682 0 0 0.0 0 +chr2 191142693 0 0 0.0 0 +chr2 191200990 0 0 0.0 0 +chr2 191475356 0 0 0.0 0 +chr2 191632540 0 0 0.0 0 +chr2 191638675 0 0 0.0 0 +chr2 191703891 0 0 0.0 0 +chr2 191785698 0 0 0.0 0 +chr2 191823581 0 0 0.0 0 +chr2 192041159 0 0 0.0 0 +chr2 192158446 0 0 0.0 0 +chr2 192265018 0 0 0.0 0 +chr2 192399761 0 0 0.0 0 +chr2 192482889 0 0 0.0 0 +chr2 192508343 0 0 0.0 0 +chr2 192655558 0 0 0.0 0 +chr2 193114072 0 0 0.0 0 +chr2 193295175 0 0 0.0 0 +chr2 193494759 0 0 0.0 0 +chr2 193769740 0 0 0.0 0 +chr2 193836152 0 0 0.0 0 +chr2 193970206 0 0 0.0 0 +chr2 194018497 0 0 0.0 0 +chr2 194603697 0 0 0.0 0 +chr2 194882033 0 0 0.0 0 +chr2 195262780 0 0 0.0 0 +chr2 195523331 0 0 0.0 0 +chr2 195559371 0 0 0.0 0 +chr2 195602899 0 0 0.0 0 +chr2 195610011 0 0 0.0 0 +chr2 195873057 0 0 0.0 0 +chr2 195904063 0 0 0.0 0 +chr2 196007979 0 0 0.0 0 +chr2 196053754 0 0 0.0 0 +chr2 196424466 0 0 0.0 0 +chr2 196451192 0 0 0.0 0 +chr2 196502712 0 0 0.0 0 +chr2 196619819 0 0 0.0 0 +chr2 196868597 0 0 0.0 0 +chr2 196874670 0 0 0.0 0 +chr2 196903285 0 0 0.0 0 +chr2 196992581 0 0 0.0 0 +chr2 197377796 0 0 0.0 0 +chr2 197381055 0 0 0.0 0 +chr2 197607329 0 0 0.0 0 +chr2 197628072 0 0 0.0 0 +chr2 198018523 0 0 0.0 0 +chr2 198086001 0 0 0.0 0 +chr2 198113743 0 0 0.0 0 +chr2 198202926 0 0 0.0 0 +chr2 198281309 0 0 0.0 0 +chr2 198332025 0 0 0.0 0 +chr2 198587319 0 0 0.0 0 +chr2 198883694 0 0 0.0 0 +chr2 199127491 0 0 0.0 0 +chr2 199214832 0 0 0.0 0 +chr2 199245962 0 0 0.0 0 +chr2 199365344 0 0 0.0 0 +chr2 199552159 0 0 0.0 0 +chr2 199683893 0 0 0.0 0 +chr2 199758976 0 0 0.0 0 +chr2 200048760 0 0 0.0 0 +chr2 200137474 0 0 0.0 0 +chr2 200232151 0 0 0.0 0 +chr2 200286429 0 0 0.0 0 +chr2 200290186 0 0 0.0 0 +chr2 200327530 0 0 0.0 0 +chr2 200453649 0 0 0.0 0 +chr2 200612396 0 0 0.0 0 +chr2 200936269 0 0 0.0 0 +chr2 201068812 0 0 0.0 0 +chr2 201129773 0 0 0.0 0 +chr2 201152638 0 0 0.0 0 +chr2 201330326 0 0 0.0 0 +chr2 201471567 0 0 0.0 0 +chr2 201650978 0 0 0.0 0 +chr2 201671360 0 0 0.0 0 +chr2 201803241 0 0 0.0 0 +chr2 201877526 0 0 0.0 0 +chr2 201945646 0 0 0.0 0 +chr2 201969823 0 0 0.0 0 +chr2 201985527 0 0 0.0 0 +chr2 202076789 0 0 0.0 0 +chr2 202121655 0 0 0.0 0 +chr2 202130589 0 0 0.0 0 +chr2 202139434 0 0 0.0 0 +chr2 202162161 0 0 0.0 0 +chr2 202493090 0 0 0.0 0 +chr2 202573872 0 0 0.0 0 +chr2 202734351 0 0 0.0 0 +chr2 202743142 0 0 0.0 0 +chr2 203176061 0 0 0.0 0 +chr2 203546373 0 0 0.0 0 +chr2 203651913 0 0 0.0 0 +chr2 203737006 0 0 0.0 0 +chr2 203800472 0 0 0.0 0 +chr2 203852059 0 0 0.0 0 +chr2 203870888 0 0 0.0 0 +chr2 204109646 0 0 0.0 0 +chr2 204196482 0 0 0.0 0 +chr2 204235018 0 0 0.0 0 +chr2 204542482 0 0 0.0 0 +chr2 205020041 0 0 0.0 0 +chr2 205080434 0 0 0.0 0 +chr2 205305418 0 0 0.0 0 +chr2 205321501 0 2 0.0357 0 +chr2 205615001 0 0 0.0 0 +chr2 205622316 0 0 0.0 0 +chr2 205852110 0 0 0.0 0 +chr2 205879742 0 0 0.0 0 +chr2 205882212 0 0 0.0 0 +chr2 206444889 0 0 0.0 0 +chr2 206672017 0 0 0.0 0 +chr2 206723696 0 0 0.0 0 +chr2 206762217 0 0 0.0 0 +chr2 206767894 0 0 0.0 0 +chr2 207055318 0 0 0.0 0 +chr2 207087702 0 0 0.0 0 +chr2 207291651 0 1 0.0145 0 +chr2 207322757 0 0 0.0 0 +chr2 207352708 0 0 0.0 0 +chr2 207380500 0 0 0.0 0 +chr2 207401222 0 0 0.0 0 +chr2 207468012 0 1 0.0286 0 +chr2 207665009 0 0 0.0 0 +chr2 208014953 0 0 0.0 0 +chr2 208127702 0 0 0.0 0 +chr2 208406551 0 0 0.0 0 +chr2 208413271 0 0 0.0 0 +chr2 208458151 0 0 0.0 0 +chr2 208560581 0 0 0.0 0 +chr2 208587113 0 0 0.0 0 +chr2 208752827 0 0 0.0 0 +chr2 209051117 0 0 0.0 0 +chr2 209066454 0 0 0.0 0 +chr2 209087607 0 0 0.0 0 +chr2 209124752 0 0 0.0 0 +chr2 209179730 0 0 0.0 0 +chr2 209191696 0 0 0.0 0 +chr2 209242280 0 0 0.0 0 +chr2 209414659 0 0 0.0 0 +chr2 209498279 0 0 0.0 0 +chr2 209568789 0 0 0.0 0 +chr2 209585052 0 0 0.0 0 +chr2 209704612 0 0 0.0 0 +chr2 209728386 0 0 0.0 0 +chr2 209730307 0 0 0.0 0 +chr2 209734775 0 0 0.0 0 +chr2 209755585 0 0 0.0 0 +chr2 209957735 0 1 0.0233 0 +chr2 209986829 0 0 0.0 0 +chr2 210133425 0 0 0.0 0 +chr2 210225036 0 0 0.0 0 +chr2 210357566 0 0 0.0 0 +chr2 210444130 0 0 0.0 0 +chr2 210704795 0 0 0.0 0 +chr2 211123727 0 0 0.0 0 +chr2 211186688 0 0 0.0 0 +chr2 211269616 0 0 0.0 0 +chr2 211321118 0 0 0.0 0 +chr2 211340853 0 0 0.0 0 +chr2 211377792 0 0 0.0 0 +chr2 211456355 0 0 0.0 0 +chr2 211534479 0 0 0.0 0 +chr2 212076721 0 0 0.0 0 +chr2 212160638 0 0 0.0 0 +chr2 212264110 0 0 0.0 0 +chr2 212396474 0 0 0.0 0 +chr2 212494809 0 0 0.0 0 +chr2 212651937 0 0 0.0 0 +chr2 212821667 0 0 0.0 0 +chr2 212988440 0 0 0.0 0 +chr2 213022049 0 0 0.0 0 +chr2 213147790 0 0 0.0 0 +chr2 213416578 0 0 0.0 0 +chr2 213608126 0 1 0.0147 0 +chr2 213609149 0 0 0.0 0 +chr2 213685196 0 0 0.0 0 +chr2 213790083 0 0 0.0 0 +chr2 213973490 0 0 0.0 0 +chr2 214034950 0 0 0.0 0 +chr2 214118763 0 0 0.0 0 +chr2 214371458 0 0 0.0 0 +chr2 214398304 0 0 0.0 0 +chr2 214537173 0 1 0.0132 0 +chr2 214642550 0 0 0.0 0 +chr2 214995935 0 0 0.0 0 +chr2 215005694 0 0 0.0 0 +chr2 215106990 0 0 0.0 0 +chr2 215121689 0 0 0.0 0 +chr2 215266021 0 0 0.0 0 +chr2 215302904 0 0 0.0 0 +chr2 215369605 0 0 0.0 0 +chr2 215378069 0 0 0.0 0 +chr2 215390121 0 0 0.0 0 +chr2 215609578 0 0 0.0 0 +chr2 215614780 0 0 0.0 0 +chr2 215620738 0 0 0.0 0 +chr2 215660065 0 0 0.0 0 +chr2 215667048 0 0 0.0 0 +chr2 215793814 0 0 0.0 0 +chr2 215847637 0 0 0.0 0 +chr2 215962634 0 0 0.0 0 +chr2 215988685 0 0 0.0 0 +chr2 216169269 0 0 0.0 0 +chr2 216175403 0 0 0.0 0 +chr2 216338987 0 0 0.0 0 +chr2 216362455 0 0 0.0 0 +chr2 216553471 0 0 0.0 0 +chr2 216676778 0 0 0.0 0 +chr2 216744545 0 0 0.0 0 +chr2 216752390 0 0 0.0 0 +chr2 216787049 0 0 0.0 0 +chr2 216826590 0 0 0.0 0 +chr2 216982015 0 0 0.0 0 +chr2 217029565 0 0 0.0 0 +chr2 217187847 0 0 0.0 0 +chr2 217226002 0 0 0.0 0 +chr2 217257658 0 0 0.0 0 +chr2 217627288 0 0 0.0 0 +chr2 217628622 0 0 0.0 0 +chr2 217628787 0 0 0.0 0 +chr2 217629428 0 0 0.0 0 +chr2 217683320 0 0 0.0 0 +chr2 217792780 0 0 0.0 0 +chr2 217822667 0 0 0.0 0 +chr2 217860150 0 0 0.0 0 +chr2 217863351 0 0 0.0 0 +chr2 217880168 0 0 0.0 0 +chr2 217903815 0 0 0.0 0 +chr2 218004007 0 0 0.0 0 +chr2 218235465 0 0 0.0 0 +chr2 218286338 0 0 0.0 0 +chr2 218287874 0 0 0.0 0 +chr2 218387658 0 0 0.0 0 +chr2 218403340 0 0 0.0 0 +chr2 218632613 0 0 0.0 0 +chr2 218713310 0 0 0.0 0 +chr2 218719242 0 0 0.0 0 +chr2 218786240 0 0 0.0 0 +chr2 218821009 0 0 0.0 0 +chr2 218827044 0 0 0.0 0 +chr2 218894882 0 0 0.0 0 +chr2 218957447 0 0 0.0 0 +chr2 218981598 0 0 0.0 0 +chr2 219038356 0 0 0.0 0 +chr2 219046887 0 0 0.0 0 +chr2 219160825 0 0 0.0 0 +chr2 219298255 0 0 0.0 0 +chr2 219364643 0 0 0.0 0 +chr2 219425281 0 0 0.0 0 +chr2 219519972 0 0 0.0 0 +chr2 219531479 0 0 0.0 0 +chr2 219606306 0 0 0.0 0 +chr2 219631163 0 0 0.0 0 +chr2 219640645 0 0 0.0 0 +chr2 219678899 0 0 0.0 0 +chr2 219746717 0 0 0.0 0 +chr2 219837492 0 0 0.0 0 +chr2 219949674 0 0 0.0 0 +chr2 219953084 0 0 0.0 0 +chr2 219980450 0 0 0.0 0 +chr2 220162500 0 0 0.0 0 +chr2 220174753 0 0 0.0 0 +chr2 220175553 0 0 0.0 0 +chr2 220258435 0 0 0.0 0 +chr2 220335368 0 0 0.0 0 +chr2 220344863 0 0 0.0 0 +chr2 220701222 0 0 0.0 0 +chr2 220714316 0 0 0.0 0 +chr2 220920096 0 0 0.0 0 +chr2 220992306 0 0 0.0 0 +chr2 220992479 0 0 0.0 0 +chr2 221339691 0 0 0.0 0 +chr2 221361580 0 0 0.0 0 +chr2 221437629 0 0 0.0 0 +chr2 221593570 0 0 0.0 0 +chr2 221655861 0 0 0.0 0 +chr2 222019836 2 24 0.5333 1 +chr2 222054345 0 0 0.0 0 +chr2 222082895 0 0 0.0 0 +chr2 222189968 0 0 0.0 0 +chr2 222301033 0 0 0.0 0 +chr2 222333600 0 0 0.0 0 +chr2 222620496 0 1 0.0145 0 +chr2 222780336 0 0 0.0 0 +chr2 222801950 0 0 0.0 0 +chr2 222843038 0 0 0.0 0 +chr2 222914865 0 0 0.0 0 +chr2 222993732 0 0 0.0 0 +chr2 223076371 0 0 0.0 0 +chr2 223093714 0 0 0.0 0 +chr2 223293493 0 0 0.0 0 +chr2 223537233 0 0 0.0 0 +chr2 223676335 0 0 0.0 0 +chr2 223878467 0 0 0.0 0 +chr2 223938945 0 0 0.0 0 +chr2 223995401 0 0 0.0 0 +chr2 224237545 0 0 0.0 0 +chr2 224405721 0 0 0.0 0 +chr2 224430448 0 0 0.0 0 +chr2 224672705 0 0 0.0 0 +chr2 224787917 0 0 0.0 0 +chr2 224975072 0 0 0.0 0 +chr2 225195952 0 0 0.0 0 +chr2 225366862 0 0 0.0 0 +chr2 225465642 0 0 0.0 0 +chr2 225572998 0 0 0.0 0 +chr2 225656501 0 0 0.0 0 +chr2 225805741 0 0 0.0 0 +chr2 225966859 0 0 0.0 0 +chr2 225969350 0 0 0.0 0 +chr2 226007746 0 0 0.0 0 +chr2 226027820 0 0 0.0 0 +chr2 226108118 0 0 0.0 0 +chr2 226327543 0 0 0.0 0 +chr2 226607624 0 0 0.0 0 +chr2 226688132 0 0 0.0 0 +chr2 226842994 0 0 0.0 0 +chr2 226964772 0 0 0.0 0 +chr2 227013946 0 0 0.0 0 +chr2 227026423 0 0 0.0 0 +chr2 227050739 0 0 0.0 0 +chr2 227388808 0 0 0.0 0 +chr2 227435442 0 0 0.0 0 +chr2 227593223 0 0 0.0 0 +chr2 227673316 0 1 0.0143 0 +chr2 227788364 0 0 0.0 0 +chr2 228103348 0 1 0.0217 0 +chr2 228219381 0 0 0.0 0 +chr2 228438245 0 0 0.0 0 +chr2 228658199 0 0 0.0 0 +chr2 228763097 0 0 0.0 0 +chr2 228825887 0 0 0.0 0 +chr2 228897338 0 0 0.0 0 +chr2 228898141 0 0 0.0 0 +chr2 228922093 0 0 0.0 0 +chr2 229074688 0 0 0.0 0 +chr2 229141866 1 31 0.4429 1 +chr2 229175314 0 0 0.0 0 +chr2 229233999 0 0 0.0 0 +chr2 229335627 0 0 0.0 0 +chr2 229373935 0 0 0.0 0 +chr2 229381569 0 0 0.0 0 +chr2 229522175 0 0 0.0 0 +chr2 230117417 0 0 0.0 0 +chr2 230157083 0 0 0.0 0 +chr2 230342504 0 0 0.0 0 +chr2 230351054 0 0 0.0 0 +chr2 230377422 0 0 0.0 0 +chr2 230411246 0 0 0.0 0 +chr2 230635099 0 0 0.0 0 +chr2 230652290 0 0 0.0 0 +chr2 230690788 0 0 0.0 0 +chr2 230809218 0 0 0.0 0 +chr2 230853215 0 0 0.0 0 +chr2 230935696 0 0 0.0 0 +chr2 231183309 0 0 0.0 0 +chr2 231289058 0 0 0.0 0 +chr2 231581905 0 0 0.0 0 +chr2 231607116 0 0 0.0 0 +chr2 231638662 0 0 0.0 0 +chr2 231689536 0 0 0.0 0 +chr2 231701962 0 0 0.0 0 +chr2 231715277 0 0 0.0 0 +chr2 231890925 0 2 0.0238 0 +chr2 231930036 0 0 0.0 0 +chr2 231939036 0 0 0.0 0 +chr2 232045342 0 0 0.0 0 +chr2 232050755 0 0 0.0 0 +chr2 232061647 0 0 0.0 0 +chr2 232125016 0 0 0.0 0 +chr2 232439194 0 0 0.0 0 +chr2 232461734 0 0 0.0 0 +chr2 232542307 0 0 0.0 0 +chr2 232545562 0 1 0.0208 0 +chr2 232640791 0 0 0.0 0 +chr2 232674838 0 1 0.0222 0 +chr2 232677129 0 0 0.0 0 +chr2 232930239 0 0 0.0 0 +chr2 233126495 0 0 0.0 0 +chr2 233204396 0 0 0.0 0 +chr2 233248898 0 0 0.0 0 +chr2 233263320 0 0 0.0 0 +chr2 233327224 0 0 0.0 0 +chr2 233394505 0 0 0.0 0 +chr2 233417294 0 0 0.0 0 +chr2 233675131 0 0 0.0 0 +chr2 233864807 0 0 0.0 0 +chr2 233908492 0 0 0.0 0 +chr2 233932665 0 0 0.0 0 +chr2 233991408 0 0 0.0 0 +chr2 234047532 0 0 0.0 0 +chr2 234049470 0 0 0.0 0 +chr2 234059212 0 0 0.0 0 +chr2 234110902 0 0 0.0 0 +chr2 234132074 0 0 0.0 0 +chr2 234296311 0 0 0.0 0 +chr2 234333023 0 0 0.0 0 +chr2 234470177 0 0 0.0 0 +chr2 234484097 0 0 0.0 0 +chr2 234484364 0 0 0.0 0 +chr2 234536050 0 0 0.0 0 +chr2 234570618 0 0 0.0 0 +chr2 234677612 0 0 0.0 0 +chr2 234762135 0 0 0.0 0 +chr2 234811227 0 0 0.0 0 +chr2 234852355 0 0 0.0 0 +chr2 234875519 0 0 0.0 0 +chr2 234896288 0 0 0.0 0 +chr2 234941739 0 0 0.0 0 +chr2 235135309 0 0 0.0 0 +chr2 235170019 0 0 0.0 0 +chr2 235189971 0 0 0.0 0 +chr2 235264345 0 0 0.0 0 +chr2 235349400 0 0 0.0 0 +chr2 235369940 0 0 0.0 0 +chr2 235485095 0 0 0.0 0 +chr2 235636813 0 0 0.0 0 +chr2 235749980 0 0 0.0 0 +chr2 235791303 0 0 0.0 0 +chr2 235979650 0 1 0.0233 0 +chr2 236006226 0 0 0.0 0 +chr2 236015110 0 0 0.0 0 +chr2 236031670 0 0 0.0 0 +chr2 236079744 0 0 0.0 0 +chr2 236157582 0 0 0.0 0 +chr2 236295770 0 0 0.0 0 +chr2 236400441 0 0 0.0 0 +chr2 236513828 0 0 0.0 0 +chr2 236525566 0 0 0.0 0 +chr2 236571195 0 0 0.0 0 +chr2 236574255 0 0 0.0 0 +chr2 236606060 0 0 0.0 0 +chr2 236779607 0 0 0.0 0 +chr2 236851967 0 0 0.0 0 +chr2 236863206 0 0 0.0 0 +chr2 236890673 0 0 0.0 0 +chr2 236913721 0 0 0.0 0 +chr2 237063662 0 0 0.0 0 +chr2 237148842 0 0 0.0 0 +chr2 237183662 0 0 0.0 0 +chr2 237286205 0 0 0.0 0 +chr2 237298773 0 0 0.0 0 +chr2 237330414 0 0 0.0 0 +chr2 237340500 0 0 0.0 0 +chr2 237480304 0 0 0.0 0 +chr2 237515467 0 0 0.0 0 +chr2 237520332 0 0 0.0 0 +chr2 237534244 0 0 0.0 0 +chr2 237546857 0 0 0.0 0 +chr2 237550314 0 0 0.0 0 +chr2 237641871 0 0 0.0 0 +chr2 237909780 0 0 0.0 0 +chr2 237925632 0 0 0.0 0 +chr2 237961816 0 0 0.0 0 +chr2 237978435 0 0 0.0 0 +chr2 237992774 0 0 0.0 0 +chr2 238101287 1 32 0.4571 1 +chr2 238130136 0 0 0.0 0 +chr2 238137179 0 1 0.0152 0 +chr2 238141152 0 0 0.0 0 +chr2 238206145 0 0 0.0 0 +chr2 238306936 0 0 0.0 0 +chr2 238314949 0 0 0.0 0 +chr2 238563484 0 0 0.0 0 +chr2 238624236 0 0 0.0 0 +chr2 238638306 0 0 0.0 0 +chr2 238652577 0 0 0.0 0 +chr2 238668163 0 0 0.0 0 +chr2 238784605 0 0 0.0 0 +chr2 238972743 0 0 0.0 0 +chr2 238974519 0 0 0.0 0 +chr2 239112076 0 0 0.0 0 +chr2 239121338 0 0 0.0 0 +chr2 239261776 0 0 0.0 0 +chr2 239376994 0 0 0.0 0 +chr2 239466867 0 0 0.0 0 +chr2 239475533 0 0 0.0 0 +chr2 239542748 0 0 0.0 0 +chr2 239720004 0 0 0.0 0 +chr2 239722332 0 0 0.0 0 +chr2 239745813 0 0 0.0 0 +chr2 239763828 0 0 0.0 0 +chr2 239798883 0 0 0.0 0 +chr2 239828614 0 0 0.0 0 +chr2 239858502 0 0 0.0 0 +chr2 240043606 0 0 0.0 0 +chr2 240060099 0 0 0.0 0 +chr2 240067104 0 0 0.0 0 +chr2 240117591 0 0 0.0 0 +chr2 240130252 0 0 0.0 0 +chr2 240155644 0 0 0.0 0 +chr2 240176240 0 0 0.0 0 +chr2 240231601 0 0 0.0 0 +chr2 240248964 0 0 0.0 0 +chr2 240273042 0 0 0.0 0 +chr2 240296092 0 0 0.0 0 +chr2 240326076 0 0 0.0 0 +chr2 240375039 0 0 0.0 0 +chr2 240391242 0 0 0.0 0 +chr2 240413582 0 0 0.0 0 +chr2 240451055 0 0 0.0 0 +chr2 240456524 0 0 0.0 0 +chr2 240622752 0 0 0.0 0 +chr2 240673087 0 0 0.0 0 +chr2 240701253 0 0 0.0 0 +chr2 240727137 0 0 0.0 0 +chr2 240729927 0 0 0.0 0 +chr2 240737945 0 0 0.0 0 +chr2 240769903 0 0 0.0 0 +chr2 240804863 0 0 0.0 0 +chr2 240818873 0 0 0.0 0 +chr2 240855143 0 0 0.0 0 +chr2 240963125 0 0 0.0 0 +chr2 240989896 0 0 0.0 0 +chr2 241025624 0 0 0.0 0 +chr2 241123138 0 0 0.0 0 +chr2 241143977 0 0 0.0 0 +chr2 241229765 0 0 0.0 0 +chr2 241233639 0 0 0.0 0 +chr2 241270093 0 0 0.0 0 +chr2 241307239 0 0 0.0 0 +chr2 241316630 0 0 0.0 0 +chr2 241362981 0 0 0.0 0 +chr2 241393281 0 0 0.0 0 +chr2 241407858 0 1 0.0122 0 +chr2 241676625 0 0 0.0 0 +chr2 241741158 0 0 0.0 0 +chr2 241786747 0 0 0.0 0 +chr2 241826297 0 0 0.0 0 +chr2 241852776 0 0 0.0 0 +chr2 241988311 0 0 0.0 0 +chr2 242001633 1 35 0.7143 1 +chr2 242148287 0 0 0.0 0 +chr20 62185 1 4 0.0741 1 +chr20 64371 0 0 0.0 0 +chr20 65193 0 1 0.0135 0 +chr20 115454 0 0 0.0 0 +chr20 295515 0 0 0.0 0 +chr20 426579 0 0 0.0 0 +chr20 437254 0 0 0.0 0 +chr20 441495 0 0 0.0 0 +chr20 658515 0 0 0.0 0 +chr20 674975 0 0 0.0 0 +chr20 711216 0 0 0.0 0 +chr20 742594 0 0 0.0 0 +chr20 843797 0 0 0.0 0 +chr20 884897 0 0 0.0 0 +chr20 908407 0 0 0.0 0 +chr20 938449 0 0 0.0 0 +chr20 947857 0 0 0.0 0 +chr20 1080994 0 0 0.0 0 +chr20 1169200 0 0 0.0 0 +chr20 1444303 0 0 0.0 0 +chr20 1556525 0 0 0.0 0 +chr20 1790642 0 0 0.0 0 +chr20 1794807 0 0 0.0 0 +chr20 1898806 0 0 0.0 0 +chr20 1947795 0 0 0.0 0 +chr20 2003042 0 0 0.0 0 +chr20 2116552 0 0 0.0 0 +chr20 2230286 0 0 0.0 0 +chr20 2464973 0 0 0.0 0 +chr20 2642817 0 0 0.0 0 +chr20 2656427 0 0 0.0 0 +chr20 2706982 0 0 0.0 0 +chr20 2974377 0 0 0.0 0 +chr20 3113770 0 0 0.0 0 +chr20 3155457 0 0 0.0 0 +chr20 3180269 0 0 0.0 0 +chr20 3353518 0 0 0.0 0 +chr20 3354248 0 0 0.0 0 +chr20 3386382 0 0 0.0 0 +chr20 3692615 0 0 0.0 0 +chr20 3727243 0 0 0.0 0 +chr20 3758746 0 0 0.0 0 +chr20 3768309 0 0 0.0 0 +chr20 3857831 0 0 0.0 0 +chr20 3881246 0 0 0.0 0 +chr20 3905760 0 0 0.0 0 +chr20 3933335 0 0 0.0 0 +chr20 3954978 0 0 0.0 0 +chr20 4009371 0 0 0.0 0 +chr20 4023991 0 0 0.0 0 +chr20 4063869 0 0 0.0 0 +chr20 4079472 0 0 0.0 0 +chr20 4227381 0 0 0.0 0 +chr20 4229074 0 0 0.0 0 +chr20 4233831 0 0 0.0 0 +chr20 4303581 0 0 0.0 0 +chr20 4361284 0 0 0.0 0 +chr20 4377076 0 0 0.0 0 +chr20 4381328 0 0 0.0 0 +chr20 4584717 0 0 0.0 0 +chr20 4592478 0 0 0.0 0 +chr20 4662614 0 0 0.0 0 +chr20 4893485 0 0 0.0 0 +chr20 4973144 0 1 0.0263 0 +chr20 5118876 0 0 0.0 0 +chr20 5133100 0 0 0.0 0 +chr20 5172972 0 0 0.0 0 +chr20 5294928 0 0 0.0 0 +chr20 5300424 0 0 0.0 0 +chr20 5318646 0 0 0.0 0 +chr20 5322513 0 0 0.0 0 +chr20 5722641 0 0 0.0 0 +chr20 5732002 0 0 0.0 0 +chr20 5749977 0 0 0.0 0 +chr20 5904685 0 0 0.0 0 +chr20 6247439 0 0 0.0 0 +chr20 6525477 0 0 0.0 0 +chr20 6575925 0 0 0.0 0 +chr20 6646436 0 0 0.0 0 +chr20 6680143 0 0 0.0 0 +chr20 6779362 0 0 0.0 0 +chr20 6881927 0 0 0.0 0 +chr20 6949202 0 0 0.0 0 +chr20 7045637 0 0 0.0 0 +chr20 7180829 0 0 0.0 0 +chr20 7192644 0 0 0.0 0 +chr20 7281709 0 0 0.0 0 +chr20 7346721 0 0 0.0 0 +chr20 7498398 0 0 0.0 0 +chr20 7754647 0 0 0.0 0 +chr20 7790917 0 0 0.0 0 +chr20 7802199 0 0 0.0 0 +chr20 7804644 0 0 0.0 0 +chr20 7995767 0 0 0.0 0 +chr20 8065058 0 0 0.0 0 +chr20 8104355 0 0 0.0 0 +chr20 8189913 0 0 0.0 0 +chr20 8260571 0 0 0.0 0 +chr20 8283251 0 0 0.0 0 +chr20 8553391 0 0 0.0 0 +chr20 8567426 0 0 0.0 0 +chr20 8682842 0 0 0.0 0 +chr20 8684776 0 0 0.0 0 +chr20 8925394 0 0 0.0 0 +chr20 8957967 0 0 0.0 0 +chr20 9056075 0 0 0.0 0 +chr20 9100848 0 0 0.0 0 +chr20 9389613 0 0 0.0 0 +chr20 9423841 0 0 0.0 0 +chr20 9469314 0 0 0.0 0 +chr20 9483001 0 0 0.0 0 +chr20 9528980 0 0 0.0 0 +chr20 9596199 0 0 0.0 0 +chr20 9791776 0 0 0.0 0 +chr20 9905440 0 0 0.0 0 +chr20 9905881 1 67 0.9437 1 +chr20 10088598 0 0 0.0 0 +chr20 10173879 0 0 0.0 0 +chr20 10180066 0 0 0.0 0 +chr20 10181169 0 0 0.0 0 +chr20 10214656 0 0 0.0 0 +chr20 10284962 0 0 0.0 0 +chr20 10300151 0 0 0.0 0 +chr20 10309702 0 0 0.0 0 +chr20 10406240 0 0 0.0 0 +chr20 10458561 0 0 0.0 0 +chr20 10469343 0 0 0.0 0 +chr20 10762121 0 0 0.0 0 +chr20 10797052 0 0 0.0 0 +chr20 10864251 0 0 0.0 0 +chr20 10883705 0 0 0.0 0 +chr20 11038109 0 0 0.0 0 +chr20 11047888 0 0 0.0 0 +chr20 11079936 0 0 0.0 0 +chr20 11152631 0 0 0.0 0 +chr20 11199610 0 0 0.0 0 +chr20 11232109 0 0 0.0 0 +chr20 11343918 0 0 0.0 0 +chr20 11408834 0 0 0.0 0 +chr20 11604692 0 0 0.0 0 +chr20 11772092 0 0 0.0 0 +chr20 11797617 0 0 0.0 0 +chr20 11854916 0 0 0.0 0 +chr20 11953420 0 0 0.0 0 +chr20 12052215 0 0 0.0 0 +chr20 12058661 0 0 0.0 0 +chr20 12060557 0 0 0.0 0 +chr20 12082899 0 0 0.0 0 +chr20 12151353 0 0 0.0 0 +chr20 12192527 3 18 0.5455 1 +chr20 12200415 0 0 0.0 0 +chr20 12212463 0 0 0.0 0 +chr20 12261103 0 0 0.0 0 +chr20 12285180 0 0 0.0 0 +chr20 12305980 0 1 0.0137 0 +chr20 12340754 0 0 0.0 0 +chr20 12343824 0 0 0.0 0 +chr20 12359727 0 0 0.0 0 +chr20 12408090 0 0 0.0 0 +chr20 12611331 0 0 0.0 0 +chr20 12759125 0 0 0.0 0 +chr20 12765161 0 0 0.0 0 +chr20 13027328 0 0 0.0 0 +chr20 13246526 0 0 0.0 0 +chr20 13371580 0 0 0.0 0 +chr20 13380947 0 0 0.0 0 +chr20 13753622 0 0 0.0 0 +chr20 13844466 0 0 0.0 0 +chr20 13942470 0 0 0.0 0 +chr20 14028292 0 0 0.0 0 +chr20 14085969 0 0 0.0 0 +chr20 14193576 0 0 0.0 0 +chr20 14341208 0 0 0.0 0 +chr20 14408605 0 0 0.0 0 +chr20 14431780 0 0 0.0 0 +chr20 14475882 0 0 0.0 0 +chr20 14491990 0 0 0.0 0 +chr20 14500247 0 0 0.0 0 +chr20 14568424 0 0 0.0 0 +chr20 14722511 0 0 0.0 0 +chr20 14823487 0 0 0.0 0 +chr20 15297627 0 0 0.0 0 +chr20 15309327 0 1 0.025 0 +chr20 15381794 0 0 0.0 0 +chr20 15420485 0 0 0.0 0 +chr20 15632508 0 0 0.0 0 +chr20 15747366 0 0 0.0 0 +chr20 15786631 0 0 0.0 0 +chr20 15851630 0 0 0.0 0 +chr20 15866838 0 0 0.0 0 +chr20 15921194 0 0 0.0 0 +chr20 16020358 0 0 0.0 0 +chr20 16046943 0 0 0.0 0 +chr20 16167684 0 0 0.0 0 +chr20 16171550 0 0 0.0 0 +chr20 16217151 0 0 0.0 0 +chr20 16269364 0 0 0.0 0 +chr20 16369944 0 0 0.0 0 +chr20 16628245 0 0 0.0 0 +chr20 16716269 0 0 0.0 0 +chr20 16785726 0 0 0.0 0 +chr20 16862872 0 0 0.0 0 +chr20 16955236 0 0 0.0 0 +chr20 17223988 0 0 0.0 0 +chr20 17230921 0 0 0.0 0 +chr20 17470848 0 0 0.0 0 +chr20 17487272 0 2 0.0645 0 +chr20 17526279 0 0 0.0 0 +chr20 17544363 0 0 0.0 0 +chr20 17570766 0 0 0.0 0 +chr20 17596490 0 0 0.0 0 +chr20 17605409 0 0 0.0 0 +chr20 17618284 0 0 0.0 0 +chr20 17769930 0 0 0.0 0 +chr20 17823534 0 0 0.0 0 +chr20 17833493 1 3 0.0361 1 +chr20 17845381 0 0 0.0 0 +chr20 17875128 0 0 0.0 0 +chr20 18024676 0 0 0.0 0 +chr20 18091916 0 0 0.0 0 +chr20 18102456 0 0 0.0 0 +chr20 18151118 0 0 0.0 0 +chr20 18168963 0 0 0.0 0 +chr20 18440929 0 0 0.0 0 +chr20 18451899 0 0 0.0 0 +chr20 18577725 0 0 0.0 0 +chr20 18819604 0 0 0.0 0 +chr20 18840072 0 0 0.0 0 +chr20 18910636 0 0 0.0 0 +chr20 18964354 0 0 0.0 0 +chr20 18973786 0 0 0.0 0 +chr20 19073111 0 0 0.0 0 +chr20 19339830 0 0 0.0 0 +chr20 19477598 0 0 0.0 0 +chr20 19509432 0 0 0.0 0 +chr20 19586632 0 1 0.0196 0 +chr20 19587353 0 0 0.0 0 +chr20 19772157 0 0 0.0 0 +chr20 19784854 0 0 0.0 0 +chr20 19851257 0 0 0.0 0 +chr20 20035446 0 0 0.0 0 +chr20 20081758 0 0 0.0 0 +chr20 20134448 0 0 0.0 0 +chr20 20209088 0 0 0.0 0 +chr20 20284028 0 0 0.0 0 +chr20 20318777 0 1 0.0143 0 +chr20 20431912 0 0 0.0 0 +chr20 20460325 0 0 0.0 0 +chr20 20490973 0 0 0.0 0 +chr20 20512727 0 0 0.0 0 +chr20 20709464 0 0 0.0 0 +chr20 20718241 0 0 0.0 0 +chr20 20779730 0 0 0.0 0 +chr20 20794488 0 0 0.0 0 +chr20 20908678 0 0 0.0 0 +chr20 20935952 0 0 0.0 0 +chr20 21430183 0 0 0.0 0 +chr20 21438363 0 0 0.0 0 +chr20 21565434 0 0 0.0 0 +chr20 21615990 0 0 0.0 0 +chr20 21690724 0 0 0.0 0 +chr20 21810028 0 0 0.0 0 +chr20 21868202 0 0 0.0 0 +chr20 21947910 0 0 0.0 0 +chr20 21973471 0 0 0.0 0 +chr20 21996182 0 0 0.0 0 +chr20 22045741 0 0 0.0 0 +chr20 22226392 0 0 0.0 0 +chr20 22321750 0 0 0.0 0 +chr20 22331943 0 0 0.0 0 +chr20 22332561 0 0 0.0 0 +chr20 22367867 0 0 0.0 0 +chr20 22540225 0 0 0.0 0 +chr20 22560261 0 0 0.0 0 +chr20 22657720 0 0 0.0 0 +chr20 22668159 0 0 0.0 0 +chr20 22772180 0 0 0.0 0 +chr20 22939380 0 0 0.0 0 +chr20 22957721 0 0 0.0 0 +chr20 23008204 0 0 0.0 0 +chr20 23010384 0 0 0.0 0 +chr20 23054284 0 0 0.0 0 +chr20 23110726 0 0 0.0 0 +chr20 23124039 0 0 0.0 0 +chr20 23139629 0 0 0.0 0 +chr20 23299037 0 0 0.0 0 +chr20 23323866 0 0 0.0 0 +chr20 23361475 0 0 0.0 0 +chr20 23479008 0 0 0.0 0 +chr20 24025501 0 0 0.0 0 +chr20 24041400 0 0 0.0 0 +chr20 24053228 0 0 0.0 0 +chr20 24102288 0 0 0.0 0 +chr20 24104066 0 0 0.0 0 +chr20 24324664 0 0 0.0 0 +chr20 24513007 0 0 0.0 0 +chr20 24521970 0 0 0.0 0 +chr20 24539591 0 0 0.0 0 +chr20 24563961 0 0 0.0 0 +chr20 24577486 0 0 0.0 0 +chr20 24598568 0 0 0.0 0 +chr20 24604862 0 0 0.0 0 +chr20 24619359 0 0 0.0 0 +chr20 24660984 0 0 0.0 0 +chr20 24662261 0 0 0.0 0 +chr20 24684465 0 0 0.0 0 +chr20 24716475 0 0 0.0 0 +chr20 24722646 0 0 0.0 0 +chr20 24736895 0 0 0.0 0 +chr20 24771722 0 0 0.0 0 +chr20 24792828 0 0 0.0 0 +chr20 24865859 0 0 0.0 0 +chr20 24898121 0 0 0.0 0 +chr20 24921190 0 0 0.0 0 +chr20 25277715 0 0 0.0 0 +chr20 25559549 0 0 0.0 0 +chr20 25608884 1 3 0.0411 1 +chr20 25668434 0 0 0.0 0 +chr20 28745876 0 0 0.0 0 +chr20 28809965 0 0 0.0 0 +chr20 28812181 0 0 0.0 0 +chr20 28833023 0 0 0.0 0 +chr20 28866389 0 0 0.0 0 +chr20 28898570 0 0 0.0 0 +chr20 29080370 0 0 0.0 0 +chr20 29254262 0 0 0.0 0 +chr20 29309847 0 0 0.0 0 +chr20 29561314 0 0 0.0 0 +chr20 29700987 0 0 0.0 0 +chr20 29722258 0 0 0.0 0 +chr20 29739625 0 0 0.0 0 +chr20 30145909 0 0 0.0 0 +chr20 30500962 0 0 0.0 0 +chr20 30586938 0 0 0.0 0 +chr20 30601560 0 0 0.0 0 +chr20 30639337 0 0 0.0 0 +chr20 30909581 0 0 0.0 0 +chr20 30911773 0 0 0.0 0 +chr20 30979596 0 0 0.0 0 +chr20 30981115 0 0 0.0 0 +chr20 30982650 0 0 0.0 0 +chr20 30984188 0 0 0.0 0 +chr20 31104117 0 0 0.0 0 +chr20 31164219 0 0 0.0 0 +chr20 31179367 0 0 0.0 0 +chr20 31222272 0 0 0.0 0 +chr20 31583263 0 0 0.0 0 +chr20 31608810 0 0 0.0 0 +chr20 31703304 0 0 0.0 0 +chr20 31786665 0 0 0.0 0 +chr20 31834069 0 0 0.0 0 +chr20 31834585 0 0 0.0 0 +chr20 31844167 0 0 0.0 0 +chr20 31935207 0 0 0.0 0 +chr20 32002755 0 0 0.0 0 +chr20 32035159 0 0 0.0 0 +chr20 32069021 0 0 0.0 0 +chr20 32179956 0 0 0.0 0 +chr20 32190716 0 0 0.0 0 +chr20 32230906 0 0 0.0 0 +chr20 32262458 0 0 0.0 0 +chr20 32450688 0 0 0.0 0 +chr20 32589907 0 0 0.0 0 +chr20 32641985 0 0 0.0 0 +chr20 32786327 0 0 0.0 0 +chr20 32906543 0 0 0.0 0 +chr20 32907163 0 0 0.0 0 +chr20 32981462 0 0 0.0 0 +chr20 33063246 0 0 0.0 0 +chr20 33097760 0 0 0.0 0 +chr20 33132530 0 0 0.0 0 +chr20 33413576 0 0 0.0 0 +chr20 33437317 0 0 0.0 0 +chr20 33614583 0 0 0.0 0 +chr20 33651445 0 0 0.0 0 +chr20 33875660 0 0 0.0 0 +chr20 33885027 0 0 0.0 0 +chr20 33931589 0 0 0.0 0 +chr20 33943832 0 1 0.0182 0 +chr20 33954989 0 1 0.0137 0 +chr20 34146277 0 0 0.0 0 +chr20 34642131 0 0 0.0 0 +chr20 34646791 0 0 0.0 0 +chr20 34790947 0 0 0.0 0 +chr20 34828503 0 0 0.0 0 +chr20 34879351 0 0 0.0 0 +chr20 35124149 0 0 0.0 0 +chr20 35287075 0 0 0.0 0 +chr20 35326373 0 0 0.0 0 +chr20 35333528 0 0 0.0 0 +chr20 35480397 0 0 0.0 0 +chr20 35488802 0 0 0.0 0 +chr20 35565112 0 0 0.0 0 +chr20 35957598 0 0 0.0 0 +chr20 36154127 0 0 0.0 0 +chr20 36194012 0 0 0.0 0 +chr20 36208308 0 0 0.0 0 +chr20 36232274 0 0 0.0 0 +chr20 36386309 0 0 0.0 0 +chr20 36443969 0 0 0.0 0 +chr20 36580540 0 0 0.0 0 +chr20 36588456 0 0 0.0 0 +chr20 36591123 0 0 0.0 0 +chr20 36837270 0 0 0.0 0 +chr20 36956192 0 0 0.0 0 +chr20 37098421 0 0 0.0 0 +chr20 37188455 0 0 0.0 0 +chr20 37233293 0 0 0.0 0 +chr20 37269871 0 0 0.0 0 +chr20 37309683 0 0 0.0 0 +chr20 37335474 0 0 0.0 0 +chr20 37336370 0 0 0.0 0 +chr20 37528356 0 0 0.0 0 +chr20 37541557 0 0 0.0 0 +chr20 37568806 0 0 0.0 0 +chr20 37580263 0 0 0.0 0 +chr20 37737387 0 0 0.0 0 +chr20 37763656 0 0 0.0 0 +chr20 37828003 0 0 0.0 0 +chr20 37839478 0 0 0.0 0 +chr20 37890128 0 0 0.0 0 +chr20 37973692 0 0 0.0 0 +chr20 38155828 0 0 0.0 0 +chr20 38228160 0 0 0.0 0 +chr20 38230214 0 0 0.0 0 +chr20 38243363 0 0 0.0 0 +chr20 38291746 0 0 0.0 0 +chr20 38388145 0 0 0.0 0 +chr20 38436093 0 0 0.0 0 +chr20 38489620 0 0 0.0 0 +chr20 38630901 0 0 0.0 0 +chr20 38658828 0 0 0.0 0 +chr20 38733207 0 0 0.0 0 +chr20 38750445 0 0 0.0 0 +chr20 38769068 0 0 0.0 0 +chr20 38794798 0 0 0.0 0 +chr20 38807054 0 0 0.0 0 +chr20 38875729 0 0 0.0 0 +chr20 38882207 0 0 0.0 0 +chr20 39059193 0 0 0.0 0 +chr20 39116855 0 0 0.0 0 +chr20 39140387 0 0 0.0 0 +chr20 39547824 0 0 0.0 0 +chr20 39809747 0 0 0.0 0 +chr20 39915346 0 1 0.0244 0 +chr20 40227294 0 0 0.0 0 +chr20 40304330 0 0 0.0 0 +chr20 40326638 0 0 0.0 0 +chr20 40427268 0 0 0.0 0 +chr20 40602069 0 0 0.0 0 +chr20 40647200 0 0 0.0 0 +chr20 40702017 0 0 0.0 0 +chr20 41101615 0 1 0.0152 0 +chr20 41135569 0 0 0.0 0 +chr20 41157931 0 0 0.0 0 +chr20 41218617 0 0 0.0 0 +chr20 41225938 0 0 0.0 0 +chr20 41233911 0 0 0.0 0 +chr20 41378563 0 0 0.0 0 +chr20 41498209 0 0 0.0 0 +chr20 41514844 0 0 0.0 0 +chr20 41619464 0 0 0.0 0 +chr20 41744094 0 0 0.0 0 +chr20 41789223 0 0 0.0 0 +chr20 41855970 0 0 0.0 0 +chr20 41867131 0 0 0.0 0 +chr20 41889119 0 0 0.0 0 +chr20 41954507 0 0 0.0 0 +chr20 41959733 0 0 0.0 0 +chr20 42074638 0 0 0.0 0 +chr20 42203175 0 0 0.0 0 +chr20 42262925 0 0 0.0 0 +chr20 42340722 0 0 0.0 0 +chr20 42356107 0 0 0.0 0 +chr20 42357666 0 0 0.0 0 +chr20 42368069 0 0 0.0 0 +chr20 42416928 0 0 0.0 0 +chr20 42545260 0 0 0.0 0 +chr20 42593287 0 1 0.0189 0 +chr20 42596185 0 0 0.0 0 +chr20 42601641 0 0 0.0 0 +chr20 42794840 0 1 0.0244 0 +chr20 42898231 0 0 0.0 0 +chr20 43025961 0 0 0.0 0 +chr20 43112426 0 0 0.0 0 +chr20 43136006 0 0 0.0 0 +chr20 43152495 0 0 0.0 0 +chr20 43252999 0 0 0.0 0 +chr20 43268037 0 0 0.0 0 +chr20 43347764 0 0 0.0 0 +chr20 43449154 0 0 0.0 0 +chr20 43787054 0 0 0.0 0 +chr20 43876420 0 0 0.0 0 +chr20 43901769 0 0 0.0 0 +chr20 43971399 0 0 0.0 0 +chr20 44152724 0 0 0.0 0 +chr20 44177715 0 0 0.0 0 +chr20 44439645 0 0 0.0 0 +chr20 44439841 0 0 0.0 0 +chr20 44518062 0 0 0.0 0 +chr20 44522002 0 0 0.0 0 +chr20 44580033 0 0 0.0 0 +chr20 44716055 0 0 0.0 0 +chr20 44803442 0 0 0.0 0 +chr20 45013027 0 0 0.0 0 +chr20 45164721 0 0 0.0 0 +chr20 45257748 0 0 0.0 0 +chr20 45319453 0 0 0.0 0 +chr20 45353218 0 0 0.0 0 +chr20 45436035 0 0 0.0 0 +chr20 45461571 0 0 0.0 0 +chr20 45714467 0 0 0.0 0 +chr20 45736259 0 0 0.0 0 +chr20 45881333 0 0 0.0 0 +chr20 45882878 0 0 0.0 0 +chr20 45973651 0 0 0.0 0 +chr20 46106300 0 0 0.0 0 +chr20 46149504 0 0 0.0 0 +chr20 46254183 0 0 0.0 0 +chr20 46572197 0 0 0.0 0 +chr20 46575810 0 0 0.0 0 +chr20 46614233 0 0 0.0 0 +chr20 46670069 0 0 0.0 0 +chr20 46680602 0 0 0.0 0 +chr20 46752423 0 0 0.0 0 +chr20 46759436 0 0 0.0 0 +chr20 46851941 0 0 0.0 0 +chr20 46928867 0 0 0.0 0 +chr20 46939157 0 0 0.0 0 +chr20 47015644 0 0 0.0 0 +chr20 47303865 0 0 0.0 0 +chr20 47691353 0 0 0.0 0 +chr20 47803292 0 0 0.0 0 +chr20 47879004 0 0 0.0 0 +chr20 47937348 0 0 0.0 0 +chr20 47941069 0 0 0.0 0 +chr20 48092670 0 0 0.0 0 +chr20 48151285 0 0 0.0 0 +chr20 48156419 0 0 0.0 0 +chr20 48185503 0 0 0.0 0 +chr20 48199049 0 0 0.0 0 +chr20 48246642 0 0 0.0 0 +chr20 48352711 0 0 0.0 0 +chr20 48405540 0 0 0.0 0 +chr20 48506513 0 0 0.0 0 +chr20 48704921 0 0 0.0 0 +chr20 48789274 0 0 0.0 0 +chr20 48945473 0 0 0.0 0 +chr20 48987540 0 0 0.0 0 +chr20 49072027 0 0 0.0 0 +chr20 49151545 0 0 0.0 0 +chr20 49452264 0 0 0.0 0 +chr20 49519658 0 1 0.0169 0 +chr20 49550195 0 0 0.0 0 +chr20 49585626 0 0 0.0 0 +chr20 49703982 0 0 0.0 0 +chr20 49720617 0 0 0.0 0 +chr20 49750319 0 0 0.0 0 +chr20 49897971 0 0 0.0 0 +chr20 49967131 0 0 0.0 0 +chr20 50083500 0 0 0.0 0 +chr20 50133905 0 0 0.0 0 +chr20 50215836 0 0 0.0 0 +chr20 50287742 0 0 0.0 0 +chr20 50306051 0 0 0.0 0 +chr20 50325757 0 0 0.0 0 +chr20 50568221 0 0 0.0 0 +chr20 50575681 0 0 0.0 0 +chr20 50624758 0 0 0.0 0 +chr20 50639026 0 0 0.0 0 +chr20 50674043 0 0 0.0 0 +chr20 51112811 0 0 0.0 0 +chr20 51162763 0 0 0.0 0 +chr20 51273125 0 0 0.0 0 +chr20 51449274 0 0 0.0 0 +chr20 51527377 0 0 0.0 0 +chr20 51681965 0 0 0.0 0 +chr20 51683758 0 0 0.0 0 +chr20 52000089 0 0 0.0 0 +chr20 52021236 0 0 0.0 0 +chr20 52082075 0 0 0.0 0 +chr20 52087046 0 0 0.0 0 +chr20 52118795 0 0 0.0 0 +chr20 52211254 0 0 0.0 0 +chr20 52219093 0 0 0.0 0 +chr20 52347186 0 0 0.0 0 +chr20 52568110 0 0 0.0 0 +chr20 52726425 0 0 0.0 0 +chr20 52736210 0 0 0.0 0 +chr20 52844550 0 0 0.0 0 +chr20 52870808 0 0 0.0 0 +chr20 52876335 0 0 0.0 0 +chr20 52881661 0 0 0.0 0 +chr20 52937759 0 0 0.0 0 +chr20 52943399 0 0 0.0 0 +chr20 53033534 0 0 0.0 0 +chr20 53306209 0 0 0.0 0 +chr20 53495966 0 1 0.0227 0 +chr20 53692899 0 0 0.0 0 +chr20 53779979 0 0 0.0 0 +chr20 53809508 0 0 0.0 0 +chr20 53924968 0 0 0.0 0 +chr20 54000670 0 1 0.0263 0 +chr20 54063692 0 1 0.0145 0 +chr20 54065776 0 0 0.0 0 +chr20 54130363 0 0 0.0 0 +chr20 54231460 0 0 0.0 0 +chr20 54265045 0 0 0.0 0 +chr20 54467975 0 0 0.0 0 +chr20 54479776 0 0 0.0 0 +chr20 54480709 0 0 0.0 0 +chr20 54484135 0 0 0.0 0 +chr20 54547516 0 0 0.0 0 +chr20 54636954 0 0 0.0 0 +chr20 55187441 0 0 0.0 0 +chr20 55440747 0 0 0.0 0 +chr20 55500424 0 0 0.0 0 +chr20 55510531 0 0 0.0 0 +chr20 55511677 0 0 0.0 0 +chr20 55681543 0 0 0.0 0 +chr20 55982357 0 0 0.0 0 +chr20 56155097 0 0 0.0 0 +chr20 56270406 0 0 0.0 0 +chr20 56402063 0 0 0.0 0 +chr20 56443105 0 0 0.0 0 +chr20 56451446 0 0 0.0 0 +chr20 56571018 0 0 0.0 0 +chr20 56661475 0 0 0.0 0 +chr20 56689348 0 0 0.0 0 +chr20 56741817 0 0 0.0 0 +chr20 56747830 0 0 0.0 0 +chr20 56843201 0 0 0.0 0 +chr20 56856195 0 0 0.0 0 +chr20 56877552 0 0 0.0 0 +chr20 56885013 0 0 0.0 0 +chr20 56934354 0 0 0.0 0 +chr20 56938303 0 0 0.0 0 +chr20 56965992 0 0 0.0 0 +chr20 57069755 0 0 0.0 0 +chr20 57300873 0 0 0.0 0 +chr20 57384729 0 0 0.0 0 +chr20 57394298 0 0 0.0 0 +chr20 57436734 0 0 0.0 0 +chr20 57459025 0 0 0.0 0 +chr20 57567448 0 0 0.0 0 +chr20 57664880 0 0 0.0 0 +chr20 57678626 0 0 0.0 0 +chr20 57690579 0 0 0.0 0 +chr20 57703137 0 0 0.0 0 +chr20 57793054 0 0 0.0 0 +chr20 57799314 0 0 0.0 0 +chr20 57838751 0 0 0.0 0 +chr20 57850961 0 0 0.0 0 +chr20 57886895 0 0 0.0 0 +chr20 57896462 0 0 0.0 0 +chr20 57917622 0 0 0.0 0 +chr20 57982650 0 0 0.0 0 +chr20 58015816 0 0 0.0 0 +chr20 58021594 0 0 0.0 0 +chr20 58049465 0 0 0.0 0 +chr20 58059346 0 0 0.0 0 +chr20 58091418 0 0 0.0 0 +chr20 58113040 0 0 0.0 0 +chr20 58149668 0 0 0.0 0 +chr20 58287026 0 0 0.0 0 +chr20 58518877 0 0 0.0 0 +chr20 58566705 0 0 0.0 0 +chr20 58595206 0 0 0.0 0 +chr20 58823415 0 0 0.0 0 +chr20 58833927 0 0 0.0 0 +chr20 58932075 0 0 0.0 0 +chr20 59045644 0 0 0.0 0 +chr20 59067764 0 0 0.0 0 +chr20 59213617 0 0 0.0 0 +chr20 59264197 0 0 0.0 0 +chr20 59289921 0 0 0.0 0 +chr20 59529085 0 0 0.0 0 +chr20 59561739 0 0 0.0 0 +chr20 59587260 0 0 0.0 0 +chr20 59641326 0 0 0.0 0 +chr20 59667825 0 0 0.0 0 +chr20 59668046 0 0 0.0 0 +chr20 59803637 0 0 0.0 0 +chr20 59819286 0 0 0.0 0 +chr20 60076613 0 0 0.0 0 +chr20 60127182 0 0 0.0 0 +chr20 60135581 0 0 0.0 0 +chr20 60292577 0 1 0.0204 0 +chr20 60346398 0 0 0.0 0 +chr20 60362877 0 0 0.0 0 +chr20 60412843 0 0 0.0 0 +chr20 60420026 0 0 0.0 0 +chr20 60495036 0 0 0.0 0 +chr20 60499859 0 0 0.0 0 +chr20 60637743 0 1 0.0323 0 +chr20 60664400 0 0 0.0 0 +chr20 60772742 0 0 0.0 0 +chr20 60804707 0 0 0.0 0 +chr20 60907070 0 0 0.0 0 +chr20 60919304 0 0 0.0 0 +chr20 60940050 0 0 0.0 0 +chr20 60952006 0 0 0.0 0 +chr20 60991255 1 20 0.3846 1 +chr20 61023661 0 0 0.0 0 +chr20 61073625 0 0 0.0 0 +chr20 61102154 0 0 0.0 0 +chr20 61124112 0 0 0.0 0 +chr20 61223724 0 0 0.0 0 +chr20 61299596 0 0 0.0 0 +chr20 61345052 0 0 0.0 0 +chr20 61426145 0 0 0.0 0 +chr20 61464826 0 0 0.0 0 +chr20 61531982 0 0 0.0 0 +chr20 61580856 0 0 0.0 0 +chr20 61724335 0 0 0.0 0 +chr20 61731834 0 0 0.0 0 +chr20 61810914 0 0 0.0 0 +chr20 61977293 0 0 0.0 0 +chr20 62151334 0 0 0.0 0 +chr20 62163528 0 0 0.0 0 +chr20 62168855 0 0 0.0 0 +chr20 62178678 0 0 0.0 0 +chr20 62279006 0 0 0.0 0 +chr20 62313237 0 0 0.0 0 +chr20 62382333 0 0 0.0 0 +chr20 62432567 0 0 0.0 0 +chr20 62440316 0 0 0.0 0 +chr20 62440380 0 0 0.0 0 +chr20 62519397 0 1 0.0137 0 +chr20 62563112 0 0 0.0 0 +chr20 62576669 0 0 0.0 0 +chr20 62615358 0 0 0.0 0 +chr20 62639258 0 0 0.0 0 +chr20 62674723 0 0 0.0 0 +chr20 62710622 0 0 0.0 0 +chr20 62745883 0 0 0.0 0 +chr20 62797798 0 0 0.0 0 +chr20 62800175 0 0 0.0 0 +chr20 62839585 1 40 0.5263 1 +chr20 62853612 0 0 0.0 0 +chr20 62875875 0 0 0.0 0 +chr20 62891344 0 0 0.0 0 +chr20 62924459 0 0 0.0 0 +chr20 62974819 0 0 0.0 0 +chr20 63056859 1 38 0.4691 1 +chr20 63059112 0 0 0.0 0 +chr20 63095439 0 0 0.0 0 +chr20 63096161 0 0 0.0 0 +chr20 63117985 0 0 0.0 0 +chr20 63183314 0 0 0.0 0 +chr20 63232363 0 0 0.0 0 +chr20 63232998 0 0 0.0 0 +chr20 63253731 0 0 0.0 0 +chr20 63278293 0 0 0.0 0 +chr20 63337405 0 0 0.0 0 +chr20 63347018 0 0 0.0 0 +chr20 63363150 0 0 0.0 0 +chr20 63425946 0 0 0.0 0 +chr20 63508585 0 0 0.0 0 +chr20 63524291 0 0 0.0 0 +chr20 63559376 0 0 0.0 0 +chr20 63674763 0 0 0.0 0 +chr20 63745561 0 0 0.0 0 +chr20 63800901 0 0 0.0 0 +chr20 63808901 0 1 0.0213 0 +chr20 63866554 0 0 0.0 0 +chr20 63885317 0 0 0.0 0 +chr20 63967620 0 0 0.0 0 +chr20 63968592 0 0 0.0 0 +chr20 63974583 0 0 0.0 0 +chr20 63984545 0 0 0.0 0 +chr20 64053207 0 0 0.0 0 +chr20 64083657 0 0 0.0 0 +chr20 64188550 0 0 0.0 0 +chr20 64192449 0 0 0.0 0 +chr20 64271541 0 0 0.0 0 +chr20_GL383577v2_alt 74279 0 0 0.0 0 +chr20_KI270870v1_alt 101039 0 0 0.0 0 +chr20_KI270870v1_alt 118266 0 0 0.0 0 +chr20_KI270870v1_alt 180131 0 0 0.0 0 +chr20_KI270871v1_alt 11225 0 0 0.0 0 +chr21 5141518 0 0 0.0 0 +chr21 5143491 0 0 0.0 0 +chr21 5273388 0 0 0.0 0 +chr21 5327303 0 0 0.0 0 +chr21 5329404 0 0 0.0 0 +chr21 5534486 0 0 0.0 0 +chr21 5708114 0 0 0.0 0 +chr21 5728777 0 0 0.0 0 +chr21 5849361 0 0 0.0 0 +chr21 5983320 0 0 0.0 0 +chr21 6286487 0 0 0.0 0 +chr21 6447476 0 0 0.0 0 +chr21 6448170 0 0 0.0 0 +chr21 6702639 0 0 0.0 0 +chr21 7029708 0 0 0.0 0 +chr21 7140266 0 0 0.0 0 +chr21 7210165 0 0 0.0 0 +chr21 7257324 0 0 0.0 0 +chr21 7259279 0 0 0.0 0 +chr21 7411487 0 0 0.0 0 +chr21 7595702 0 0 0.0 0 +chr21 7616365 0 0 0.0 0 +chr21 7919663 0 0 0.0 0 +chr21 7924489 0 0 0.0 0 +chr21 7927228 0 0 0.0 0 +chr21 7942622 0 0 0.0 0 +chr21 7942862 0 0 0.0 0 +chr21 7943531 0 0 0.0 0 +chr21 7945488 0 0 0.0 0 +chr21 7945688 0 0 0.0 0 +chr21 7956422 0 0 0.0 0 +chr21 7968128 0 0 0.0 0 +chr21 8106183 0 0 0.0 0 +chr21 8126846 0 0 0.0 0 +chr21 8650578 0 0 0.0 0 +chr21 8682045 0 0 0.0 0 +chr21 9030286 0 0 0.0 0 +chr21 9033782 0 0 0.0 0 +chr21 9038962 0 0 0.0 0 +chr21 9246293 0 0 0.0 0 +chr21 9741644 0 0 0.0 0 +chr21 9911820 0 0 0.0 0 +chr21 9949421 0 0 0.0 0 +chr21 9980447 0 0 0.0 0 +chr21 10133366 0 0 0.0 0 +chr21 10345406 0 0 0.0 0 +chr21 10552677 0 0 0.0 0 +chr21 10603824 0 0 0.0 0 +chr21 10649581 0 0 0.0 0 +chr21 10657470 0 0 0.0 0 +chr21 10679092 0 0 0.0 0 +chr21 10687313 0 0 0.0 0 +chr21 10689930 0 0 0.0 0 +chr21 10693343 0 0 0.0 0 +chr21 10695504 0 0 0.0 0 +chr21 10700921 0 0 0.0 0 +chr21 10701995 0 0 0.0 0 +chr21 10703450 0 0 0.0 0 +chr21 10706333 0 0 0.0 0 +chr21 10706923 0 0 0.0 0 +chr21 10707273 0 0 0.0 0 +chr21 10708238 0 0 0.0 0 +chr21 10708458 0 0 0.0 0 +chr21 10709577 0 0 0.0 0 +chr21 10710646 0 0 0.0 0 +chr21 10719457 0 0 0.0 0 +chr21 10720652 0 0 0.0 0 +chr21 10721325 0 0 0.0 0 +chr21 10722238 0 0 0.0 0 +chr21 10722523 0 0 0.0 0 +chr21 10722917 0 0 0.0 0 +chr21 10723197 0 0 0.0 0 +chr21 10724546 0 0 0.0 0 +chr21 10726762 0 0 0.0 0 +chr21 10729050 0 0 0.0 0 +chr21 10736030 0 0 0.0 0 +chr21 10736799 0 0 0.0 0 +chr21 10917983 0 0 0.0 0 +chr21 10975613 0 0 0.0 0 +chr21 10979041 0 0 0.0 0 +chr21 10982470 0 0 0.0 0 +chr21 10989319 0 0 0.0 0 +chr21 10992745 0 0 0.0 0 +chr21 10996174 0 0 0.0 0 +chr21 10999600 0 0 0.0 0 +chr21 11006449 0 0 0.0 0 +chr21 11009877 0 0 0.0 0 +chr21 11013304 0 0 0.0 0 +chr21 11016730 0 0 0.0 0 +chr21 11020155 0 0 0.0 0 +chr21 11027007 0 0 0.0 0 +chr21 11031560 0 0 0.0 0 +chr21 11038411 0 0 0.0 0 +chr21 11045260 0 0 0.0 0 +chr21 11048685 0 0 0.0 0 +chr21 11055535 0 0 0.0 0 +chr21 11062386 0 0 0.0 0 +chr21 11065811 0 0 0.0 0 +chr21 11069236 0 0 0.0 0 +chr21 11072662 0 0 0.0 0 +chr21 11079512 0 0 0.0 0 +chr21 11082936 0 0 0.0 0 +chr21 11086360 0 0 0.0 0 +chr21 11089785 0 0 0.0 0 +chr21 12976303 0 0 0.0 0 +chr21 12976533 0 0 0.0 0 +chr21 12978521 0 0 0.0 0 +chr21 13003746 0 0 0.0 0 +chr21 13056721 0 0 0.0 0 +chr21 13130783 0 0 0.0 0 +chr21 13170790 0 0 0.0 0 +chr21 13901824 0 0 0.0 0 +chr21 14033047 0 0 0.0 0 +chr21 14082897 0 0 0.0 0 +chr21 14104628 0 0 0.0 0 +chr21 14107300 0 0 0.0 0 +chr21 14391310 0 0 0.0 0 +chr21 14484476 0 0 0.0 0 +chr21 14604409 0 0 0.0 0 +chr21 14675404 0 0 0.0 0 +chr21 14752800 0 0 0.0 0 +chr21 14775345 0 0 0.0 0 +chr21 14850678 0 2 0.0282 0 +chr21 14898112 0 0 0.0 0 +chr21 14951908 0 0 0.0 0 +chr21 15192131 0 0 0.0 0 +chr21 15283921 0 0 0.0 0 +chr21 15287324 0 0 0.0 0 +chr21 15289322 0 0 0.0 0 +chr21 15327059 0 1 0.0159 0 +chr21 15377040 0 0 0.0 0 +chr21 15444575 0 0 0.0 0 +chr21 15886813 0 1 0.0357 0 +chr21 15904224 0 0 0.0 0 +chr21 17105112 0 0 0.0 0 +chr21 17116080 0 0 0.0 0 +chr21 17363977 0 0 0.0 0 +chr21 17525396 0 0 0.0 0 +chr21 17526662 0 0 0.0 0 +chr21 17659169 0 0 0.0 0 +chr21 17691018 0 0 0.0 0 +chr21 17839650 0 0 0.0 0 +chr21 18034750 0 0 0.0 0 +chr21 18085512 0 0 0.0 0 +chr21 18086902 0 0 0.0 0 +chr21 18247548 0 0 0.0 0 +chr21 18638285 0 0 0.0 0 +chr21 18832669 0 0 0.0 0 +chr21 18841911 0 0 0.0 0 +chr21 18906687 0 0 0.0 0 +chr21 18923738 0 0 0.0 0 +chr21 19018145 0 0 0.0 0 +chr21 19078027 0 0 0.0 0 +chr21 19235811 0 0 0.0 0 +chr21 19239762 0 0 0.0 0 +chr21 19273932 0 0 0.0 0 +chr21 19305441 0 0 0.0 0 +chr21 19310169 0 0 0.0 0 +chr21 19314814 0 0 0.0 0 +chr21 19586888 1 36 0.75 1 +chr21 19657672 0 0 0.0 0 +chr21 19715455 0 0 0.0 0 +chr21 19820743 0 0 0.0 0 +chr21 19834035 0 0 0.0 0 +chr21 19885231 0 0 0.0 0 +chr21 19899528 0 0 0.0 0 +chr21 20056489 0 0 0.0 0 +chr21 20410021 0 0 0.0 0 +chr21 20412997 0 0 0.0 0 +chr21 20608545 0 1 0.0172 0 +chr21 20733432 0 0 0.0 0 +chr21 20902722 0 0 0.0 0 +chr21 21029451 0 0 0.0 0 +chr21 21456915 0 0 0.0 0 +chr21 21479510 0 0 0.0 0 +chr21 21574189 0 0 0.0 0 +chr21 21714721 0 0 0.0 0 +chr21 21726531 0 0 0.0 0 +chr21 21732300 0 0 0.0 0 +chr21 21937609 0 0 0.0 0 +chr21 22005976 0 0 0.0 0 +chr21 22201231 1 3 0.0508 1 +chr21 22223758 0 0 0.0 0 +chr21 22287671 0 0 0.0 0 +chr21 22551393 0 0 0.0 0 +chr21 22598163 0 0 0.0 0 +chr21 22706074 0 0 0.0 0 +chr21 23057501 0 0 0.0 0 +chr21 23095307 0 0 0.0 0 +chr21 23172470 0 0 0.0 0 +chr21 23242933 0 0 0.0 0 +chr21 23256219 0 0 0.0 0 +chr21 23327549 0 0 0.0 0 +chr21 23416365 0 0 0.0 0 +chr21 23591717 0 0 0.0 0 +chr21 23684592 0 1 0.0227 0 +chr21 23747495 0 0 0.0 0 +chr21 23885720 0 0 0.0 0 +chr21 24439042 0 0 0.0 0 +chr21 24474160 0 0 0.0 0 +chr21 24638494 0 0 0.0 0 +chr21 24841612 0 0 0.0 0 +chr21 24881709 0 0 0.0 0 +chr21 25104515 0 0 0.0 0 +chr21 25372730 0 0 0.0 0 +chr21 25373848 0 0 0.0 0 +chr21 25549523 0 0 0.0 0 +chr21 25906182 0 0 0.0 0 +chr21 26022545 0 0 0.0 0 +chr21 26478067 0 0 0.0 0 +chr21 26538765 0 0 0.0 0 +chr21 26613397 0 0 0.0 0 +chr21 26758283 0 0 0.0 0 +chr21 26798659 0 0 0.0 0 +chr21 26846163 0 0 0.0 0 +chr21 26872132 0 0 0.0 0 +chr21 26882085 0 0 0.0 0 +chr21 27039162 0 0 0.0 0 +chr21 27076727 1 39 0.5 1 +chr21 27295951 0 0 0.0 0 +chr21 27421604 0 0 0.0 0 +chr21 27517436 0 0 0.0 0 +chr21 27530828 0 0 0.0 0 +chr21 27614885 0 0 0.0 0 +chr21 27736539 0 1 0.0238 0 +chr21 27812962 0 0 0.0 0 +chr21 27859814 0 0 0.0 0 +chr21 28119753 0 0 0.0 0 +chr21 28507372 0 0 0.0 0 +chr21 28609252 0 0 0.0 0 +chr21 28685738 0 0 0.0 0 +chr21 29103349 0 0 0.0 0 +chr21 29221740 0 0 0.0 0 +chr21 29362639 0 0 0.0 0 +chr21 29374924 0 0 0.0 0 +chr21 29423680 0 1 0.0208 0 +chr21 29616268 0 0 0.0 0 +chr21 29655165 0 0 0.0 0 +chr21 30149965 0 0 0.0 0 +chr21 30164486 0 0 0.0 0 +chr21 30168879 0 0 0.0 0 +chr21 30306772 0 0 0.0 0 +chr21 30438299 0 0 0.0 0 +chr21 30577037 0 0 0.0 0 +chr21 30780328 0 0 0.0 0 +chr21 30879535 0 0 0.0 0 +chr21 31048830 0 0 0.0 0 +chr21 31054756 1 25 0.3472 1 +chr21 31285644 0 0 0.0 0 +chr21 31316064 0 0 0.0 0 +chr21 31336974 0 0 0.0 0 +chr21 31366502 0 0 0.0 0 +chr21 31536730 0 1 0.0164 0 +chr21 32037777 0 0 0.0 0 +chr21 32169052 0 0 0.0 0 +chr21 32184044 0 0 0.0 0 +chr21 32238813 0 0 0.0 0 +chr21 32281719 0 0 0.0 0 +chr21 32296286 0 0 0.0 0 +chr21 32342648 0 0 0.0 0 +chr21 32445830 0 0 0.0 0 +chr21 32474574 0 0 0.0 0 +chr21 32606094 0 0 0.0 0 +chr21 32967038 0 0 0.0 0 +chr21 33026684 0 0 0.0 0 +chr21 33064353 0 0 0.0 0 +chr21 33735156 0 0 0.0 0 +chr21 33932320 0 0 0.0 0 +chr21 33986830 0 0 0.0 0 +chr21 34040048 0 0 0.0 0 +chr21 34100295 0 0 0.0 0 +chr21 34125421 0 0 0.0 0 +chr21 34224705 1 21 0.5676 1 +chr21 34270661 0 0 0.0 0 +chr21 34287271 0 0 0.0 0 +chr21 34344593 0 0 0.0 0 +chr21 34352688 1 53 0.9636 1 +chr21 34527010 0 0 0.0 0 +chr21 34632239 0 0 0.0 0 +chr21 34672039 0 0 0.0 0 +chr21 34688412 0 0 0.0 0 +chr21 34697809 0 0 0.0 0 +chr21 34727251 0 0 0.0 0 +chr21 34924566 0 0 0.0 0 +chr21 34932839 0 0 0.0 0 +chr21 35068044 0 0 0.0 0 +chr21 35180388 0 0 0.0 0 +chr21 35201407 0 0 0.0 0 +chr21 35341720 0 0 0.0 0 +chr21 35347180 0 0 0.0 0 +chr21 35355645 0 0 0.0 0 +chr21 35385237 0 0 0.0 0 +chr21 35424512 0 0 0.0 0 +chr21 35431763 0 0 0.0 0 +chr21 35526316 0 0 0.0 0 +chr21 35559767 0 0 0.0 0 +chr21 35632469 0 0 0.0 0 +chr21 35637788 0 0 0.0 0 +chr21 35714705 0 1 0.013 0 +chr21 35966123 0 0 0.0 0 +chr21 36059860 0 0 0.0 0 +chr21 36100830 0 0 0.0 0 +chr21 36324136 0 0 0.0 0 +chr21 36326617 0 0 0.0 0 +chr21 36456346 0 0 0.0 0 +chr21 36549439 0 0 0.0 0 +chr21 36570379 0 0 0.0 0 +chr21 36685194 0 0 0.0 0 +chr21 36719603 0 0 0.0 0 +chr21 36841909 0 0 0.0 0 +chr21 36939702 0 0 0.0 0 +chr21 36975406 0 0 0.0 0 +chr21 36977686 0 0 0.0 0 +chr21 36994937 0 0 0.0 0 +chr21 37117805 0 0 0.0 0 +chr21 37167014 0 0 0.0 0 +chr21 37172476 0 0 0.0 0 +chr21 37201668 0 0 0.0 0 +chr21 37380796 0 0 0.0 0 +chr21 37407206 0 0 0.0 0 +chr21 37442953 0 0 0.0 0 +chr21 37453449 0 0 0.0 0 +chr21 37488847 0 0 0.0 0 +chr21 37576238 0 0 0.0 0 +chr21 37587931 0 0 0.0 0 +chr21 37618428 0 0 0.0 0 +chr21 37691271 0 0 0.0 0 +chr21 37728290 0 0 0.0 0 +chr21 37737168 0 0 0.0 0 +chr21 37801669 0 0 0.0 0 +chr21 37845391 0 0 0.0 0 +chr21 37861934 0 0 0.0 0 +chr21 37938203 0 0 0.0 0 +chr21 37956946 0 0 0.0 0 +chr21 38070435 0 0 0.0 0 +chr21 38152251 0 0 0.0 0 +chr21 38501328 0 0 0.0 0 +chr21 38560353 0 0 0.0 0 +chr21 38671695 0 0 0.0 0 +chr21 38702041 0 0 0.0 0 +chr21 38763197 0 0 0.0 0 +chr21 38828176 0 0 0.0 0 +chr21 38863194 0 0 0.0 0 +chr21 38934936 0 0 0.0 0 +chr21 38947951 0 1 0.0103 0 +chr21 38974928 0 0 0.0 0 +chr21 39061997 0 0 0.0 0 +chr21 39244157 0 0 0.0 0 +chr21 39387597 0 0 0.0 0 +chr21 39456412 0 0 0.0 0 +chr21 39631539 0 0 0.0 0 +chr21 39656367 0 0 0.0 0 +chr21 39712629 0 0 0.0 0 +chr21 39775597 0 0 0.0 0 +chr21 39788000 0 0 0.0 0 +chr21 39805992 0 0 0.0 0 +chr21 39834203 0 0 0.0 0 +chr21 39870594 0 0 0.0 0 +chr21 39935573 0 0 0.0 0 +chr21 39963319 0 0 0.0 0 +chr21 39997149 0 0 0.0 0 +chr21 40078008 0 0 0.0 0 +chr21 40217647 0 0 0.0 0 +chr21 40420597 0 0 0.0 0 +chr21 40451650 0 0 0.0 0 +chr21 40473494 0 1 0.0175 0 +chr21 40486893 0 0 0.0 0 +chr21 40829576 0 0 0.0 0 +chr21 40908354 0 0 0.0 0 +chr21 41025825 0 0 0.0 0 +chr21 41062284 1 21 0.4667 1 +chr21 41220504 0 0 0.0 0 +chr21 41230631 0 0 0.0 0 +chr21 41600814 0 0 0.0 0 +chr21 41655654 0 0 0.0 0 +chr21 41781775 0 0 0.0 0 +chr21 41988834 0 0 0.0 0 +chr21 42010298 0 0 0.0 0 +chr21 42011146 0 0 0.0 0 +chr21 42082710 0 0 0.0 0 +chr21 42085933 0 0 0.0 0 +chr21 42148642 0 0 0.0 0 +chr21 42245472 0 0 0.0 0 +chr21 42269268 0 0 0.0 0 +chr21 42319915 0 0 0.0 0 +chr21 42426125 0 0 0.0 0 +chr21 42437342 0 0 0.0 0 +chr21 42474749 0 0 0.0 0 +chr21 42486457 0 0 0.0 0 +chr21 42621800 0 0 0.0 0 +chr21 42634514 0 0 0.0 0 +chr21 42754784 0 1 0.0256 0 +chr21 42820444 0 0 0.0 0 +chr21 42863387 0 0 0.0 0 +chr21 42866737 0 0 0.0 0 +chr21 43019177 0 0 0.0 0 +chr21 43021369 0 0 0.0 0 +chr21 43034553 0 0 0.0 0 +chr21 43055798 0 0 0.0 0 +chr21 43056492 0 0 0.0 0 +chr21 43325977 0 0 0.0 0 +chr21 43328787 0 0 0.0 0 +chr21 43555253 0 0 0.0 0 +chr21 43669938 0 0 0.0 0 +chr21 43744048 0 1 0.0208 0 +chr21 43781412 0 0 0.0 0 +chr21 43811289 0 0 0.0 0 +chr21 43835367 0 0 0.0 0 +chr21 43974496 0 0 0.0 0 +chr21 44016405 0 0 0.0 0 +chr21 44017028 0 0 0.0 0 +chr21 44040267 0 0 0.0 0 +chr21 44049564 0 0 0.0 0 +chr21 44118564 0 0 0.0 0 +chr21 44120537 0 0 0.0 0 +chr21 44266890 0 0 0.0 0 +chr21 44288393 0 0 0.0 0 +chr21 44315001 0 1 0.0102 0 +chr21 44328647 0 0 0.0 0 +chr21 44461295 0 0 0.0 0 +chr21 44467616 0 0 0.0 0 +chr21 44510843 0 0 0.0 0 +chr21 44514423 0 0 0.0 0 +chr21 44520160 0 0 0.0 0 +chr21 44539952 0 0 0.0 0 +chr21 44561863 0 0 0.0 0 +chr21 44582652 0 0 0.0 0 +chr21 44586089 0 0 0.0 0 +chr21 44766275 0 0 0.0 0 +chr21 44802003 0 0 0.0 0 +chr21 44807897 0 0 0.0 0 +chr21 44828247 0 0 0.0 0 +chr21 44851259 0 0 0.0 0 +chr21 44870586 0 0 0.0 0 +chr21 44888364 0 0 0.0 0 +chr21 44891789 0 0 0.0 0 +chr21 45049606 0 0 0.0 0 +chr21 45088777 0 0 0.0 0 +chr21 45104607 0 0 0.0 0 +chr21 45220578 0 0 0.0 0 +chr21 45278498 0 0 0.0 0 +chr21 45347773 0 0 0.0 0 +chr21 45349496 0 0 0.0 0 +chr21 45381788 0 0 0.0 0 +chr21 45386469 0 0 0.0 0 +chr21 45436329 0 0 0.0 0 +chr21 45466842 0 0 0.0 0 +chr21 45490193 0 0 0.0 0 +chr21 45529345 0 0 0.0 0 +chr21 45570583 0 0 0.0 0 +chr21 45582227 0 0 0.0 0 +chr21 45639577 0 0 0.0 0 +chr21 45652704 0 0 0.0 0 +chr21 45811320 0 0 0.0 0 +chr21 45828957 0 0 0.0 0 +chr21 45877769 1 6 0.0769 1 +chr21 45898258 0 0 0.0 0 +chr21 45931532 0 0 0.0 0 +chr21 46056925 0 0 0.0 0 +chr21 46223477 0 0 0.0 0 +chr21 46365192 0 0 0.0 0 +chr21 46388285 0 0 0.0 0 +chr21 46443859 0 0 0.0 0 +chr21 46498500 0 0 0.0 0 +chr21 46537702 0 0 0.0 0 +chr21 46547064 0 0 0.0 0 +chr21 46554898 0 1 0.0154 0 +chr21 46557771 0 0 0.0 0 +chr21_KI270873v1_alt 55475 0 0 0.0 0 +chr22 10627611 0 0 0.0 0 +chr22 10659194 0 0 0.0 0 +chr22 11054961 0 0 0.0 0 +chr22 11432331 0 0 0.0 0 +chr22 11570377 0 0 0.0 0 +chr22 11615490 0 0 0.0 0 +chr22 11617921 0 0 0.0 0 +chr22 11621459 0 0 0.0 0 +chr22 11830512 0 0 0.0 0 +chr22 12027912 0 0 0.0 0 +chr22 12111094 0 0 0.0 0 +chr22 12161841 0 0 0.0 0 +chr22 12169331 0 0 0.0 0 +chr22 12802202 0 0 0.0 0 +chr22 13001426 0 0 0.0 0 +chr22 13052208 0 0 0.0 0 +chr22 13109838 0 0 0.0 0 +chr22 13113266 0 0 0.0 0 +chr22 13116695 0 0 0.0 0 +chr22 13123544 0 0 0.0 0 +chr22 13126970 0 0 0.0 0 +chr22 13130399 0 0 0.0 0 +chr22 13133825 0 0 0.0 0 +chr22 13140674 0 0 0.0 0 +chr22 13144102 0 0 0.0 0 +chr22 13147529 0 0 0.0 0 +chr22 13150955 0 0 0.0 0 +chr22 13154380 0 0 0.0 0 +chr22 13161232 0 0 0.0 0 +chr22 13165785 0 0 0.0 0 +chr22 13172636 0 0 0.0 0 +chr22 13179485 0 0 0.0 0 +chr22 13182910 0 0 0.0 0 +chr22 13189760 0 0 0.0 0 +chr22 13196611 0 0 0.0 0 +chr22 13200036 0 0 0.0 0 +chr22 13203461 0 0 0.0 0 +chr22 13206887 0 0 0.0 0 +chr22 13213737 0 0 0.0 0 +chr22 13217161 0 0 0.0 0 +chr22 13220585 0 0 0.0 0 +chr22 13224010 0 0 0.0 0 +chr22 15170589 0 0 0.0 0 +chr22 15174680 0 0 0.0 0 +chr22 15177921 0 0 0.0 0 +chr22 15230193 0 0 0.0 0 +chr22 15516083 0 0 0.0 0 +chr22 15778110 0 0 0.0 0 +chr22 15834890 0 0 0.0 0 +chr22 15999836 0 0 0.0 0 +chr22 16001372 0 0 0.0 0 +chr22 16051636 0 0 0.0 0 +chr22 16061182 0 0 0.0 0 +chr22 16098552 0 0 0.0 0 +chr22 16131269 0 0 0.0 0 +chr22 16161383 0 0 0.0 0 +chr22 16268495 0 0 0.0 0 +chr22 16270033 0 0 0.0 0 +chr22 16278944 0 0 0.0 0 +chr22 16353687 0 0 0.0 0 +chr22 16546502 0 0 0.0 0 +chr22 16700419 0 0 0.0 0 +chr22 16753406 0 0 0.0 0 +chr22 16808381 0 0 0.0 0 +chr22 16878034 0 0 0.0 0 +chr22 17034569 0 1 0.0196 0 +chr22 17048448 0 0 0.0 0 +chr22 17092642 0 0 0.0 0 +chr22 17114375 0 0 0.0 0 +chr22 17247779 0 0 0.0 0 +chr22 17298924 0 0 0.0 0 +chr22 17590731 0 0 0.0 0 +chr22 17675876 0 0 0.0 0 +chr22 17785460 0 0 0.0 0 +chr22 17813467 0 0 0.0 0 +chr22 18155855 0 0 0.0 0 +chr22 18157048 0 0 0.0 0 +chr22 18538868 0 0 0.0 0 +chr22 18784518 0 0 0.0 0 +chr22 18951368 0 0 0.0 0 +chr22 18957419 0 0 0.0 0 +chr22 19044007 0 0 0.0 0 +chr22 19047230 0 0 0.0 0 +chr22 19104376 1 19 0.7917 1 +chr22 19110370 0 0 0.0 0 +chr22 19235478 0 0 0.0 0 +chr22 19288219 0 0 0.0 0 +chr22 19507119 0 0 0.0 0 +chr22 19712171 0 0 0.0 0 +chr22 19784743 0 0 0.0 0 +chr22 19801028 0 0 0.0 0 +chr22 19913256 0 0 0.0 0 +chr22 19918757 0 0 0.0 0 +chr22 19950716 0 0 0.0 0 +chr22 19979425 0 0 0.0 0 +chr22 19980427 0 0 0.0 0 +chr22 19986444 0 0 0.0 0 +chr22 20007636 0 0 0.0 0 +chr22 20028376 0 0 0.0 0 +chr22 20118928 0 0 0.0 0 +chr22 20138746 0 0 0.0 0 +chr22 20212819 0 0 0.0 0 +chr22 20396976 0 0 0.0 0 +chr22 20408976 0 0 0.0 0 +chr22 20409055 0 0 0.0 0 +chr22 20431113 0 0 0.0 0 +chr22 20553386 0 0 0.0 0 +chr22 20615949 0 0 0.0 0 +chr22 20621944 0 0 0.0 0 +chr22 20712921 0 0 0.0 0 +chr22 20750665 0 0 0.0 0 +chr22 20752637 0 0 0.0 0 +chr22 20999089 0 0 0.0 0 +chr22 21023507 0 0 0.0 0 +chr22 21074658 0 0 0.0 0 +chr22 21077588 0 0 0.0 0 +chr22 21103121 0 0 0.0 0 +chr22 21218855 0 0 0.0 0 +chr22 21453431 0 0 0.0 0 +chr22 21478225 0 0 0.0 0 +chr22 21594030 0 0 0.0 0 +chr22 21689657 0 0 0.0 0 +chr22 21712219 0 0 0.0 0 +chr22 21822717 2 8 0.25 1 +chr22 21984122 0 0 0.0 0 +chr22 22007514 0 0 0.0 0 +chr22 22039884 2 41 0.9318 1 +chr22 22083721 0 0 0.0 0 +chr22 22243563 0 0 0.0 0 +chr22 22314581 0 0 0.0 0 +chr22 22317593 0 0 0.0 0 +chr22 22324422 0 0 0.0 0 +chr22 22406160 0 0 0.0 0 +chr22 22446681 0 0 0.0 0 +chr22 22579843 0 0 0.0 0 +chr22 22588213 0 0 0.0 0 +chr22 22664474 0 0 0.0 0 +chr22 22665045 0 0 0.0 0 +chr22 22679387 0 0 0.0 0 +chr22 22697952 0 0 0.0 0 +chr22 22701031 0 0 0.0 0 +chr22 22787474 0 0 0.0 0 +chr22 22792534 0 0 0.0 0 +chr22 22812364 0 0 0.0 0 +chr22 22822821 0 0 0.0 0 +chr22 22856590 0 0 0.0 0 +chr22 22927815 0 0 0.0 0 +chr22 22932093 0 0 0.0 0 +chr22 22934178 0 0 0.0 0 +chr22 22956558 0 0 0.0 0 +chr22 23033964 0 0 0.0 0 +chr22 23072653 0 0 0.0 0 +chr22 23102800 0 0 0.0 0 +chr22 23107180 0 0 0.0 0 +chr22 23153254 0 0 0.0 0 +chr22 23203533 0 0 0.0 0 +chr22 23223200 0 0 0.0 0 +chr22 23229125 0 0 0.0 0 +chr22 23234259 0 0 0.0 0 +chr22 23330893 0 0 0.0 0 +chr22 23363132 0 0 0.0 0 +chr22 23576720 0 0 0.0 0 +chr22 23634619 0 0 0.0 0 +chr22 23650938 0 0 0.0 0 +chr22 23686345 0 0 0.0 0 +chr22 23889291 0 0 0.0 0 +chr22 23911402 0 0 0.0 0 +chr22 24061465 0 0 0.0 0 +chr22 24063823 0 0 0.0 0 +chr22 24099859 0 0 0.0 0 +chr22 24166685 0 0 0.0 0 +chr22 24191672 0 0 0.0 0 +chr22 24434580 0 0 0.0 0 +chr22 24452094 0 0 0.0 0 +chr22 24503280 0 0 0.0 0 +chr22 24838525 0 0 0.0 0 +chr22 25051126 0 0 0.0 0 +chr22 25093239 0 0 0.0 0 +chr22 25165683 0 0 0.0 0 +chr22 25334243 0 0 0.0 0 +chr22 25352217 0 0 0.0 0 +chr22 25364624 0 0 0.0 0 +chr22 25489262 0 0 0.0 0 +chr22 25515174 0 0 0.0 0 +chr22 25618683 0 0 0.0 0 +chr22 25726607 0 0 0.0 0 +chr22 25727018 0 0 0.0 0 +chr22 25754457 0 0 0.0 0 +chr22 25770959 0 0 0.0 0 +chr22 25808638 0 0 0.0 0 +chr22 25835427 0 0 0.0 0 +chr22 25903175 0 0 0.0 0 +chr22 26008393 0 0 0.0 0 +chr22 26027446 0 0 0.0 0 +chr22 26040953 0 0 0.0 0 +chr22 26056933 0 0 0.0 0 +chr22 26073226 0 0 0.0 0 +chr22 26100274 0 0 0.0 0 +chr22 26138451 0 0 0.0 0 +chr22 26241378 0 0 0.0 0 +chr22 26260531 0 0 0.0 0 +chr22 26267385 0 0 0.0 0 +chr22 26373924 0 0 0.0 0 +chr22 26432744 0 0 0.0 0 +chr22 26567954 0 0 0.0 0 +chr22 26598218 0 0 0.0 0 +chr22 26660363 0 0 0.0 0 +chr22 26717179 0 0 0.0 0 +chr22 26718215 0 0 0.0 0 +chr22 26762001 0 0 0.0 0 +chr22 26767110 0 0 0.0 0 +chr22 26795639 0 0 0.0 0 +chr22 26820527 0 0 0.0 0 +chr22 26969021 0 0 0.0 0 +chr22 27128020 0 1 0.0244 0 +chr22 27202861 0 0 0.0 0 +chr22 27219144 0 0 0.0 0 +chr22 27250929 0 0 0.0 0 +chr22 27420962 0 0 0.0 0 +chr22 27432708 0 0 0.0 0 +chr22 27442151 0 0 0.0 0 +chr22 27454901 0 0 0.0 0 +chr22 27537048 0 0 0.0 0 +chr22 27540799 0 0 0.0 0 +chr22 27610842 0 1 0.0556 0 +chr22 27621629 0 0 0.0 0 +chr22 27623545 0 0 0.0 0 +chr22 27671282 0 0 0.0 0 +chr22 27810145 0 0 0.0 0 +chr22 27827058 0 0 0.0 0 +chr22 27934973 0 0 0.0 0 +chr22 28048119 0 0 0.0 0 +chr22 28092296 0 0 0.0 0 +chr22 28171851 0 0 0.0 0 +chr22 28237269 0 0 0.0 0 +chr22 28285090 0 0 0.0 0 +chr22 28370663 0 0 0.0 0 +chr22 28429963 0 0 0.0 0 +chr22 28468208 0 0 0.0 0 +chr22 28559109 0 0 0.0 0 +chr22 28704738 0 0 0.0 0 +chr22 28721548 0 0 0.0 0 +chr22 28797988 0 0 0.0 0 +chr22 28804141 0 0 0.0 0 +chr22 28897814 0 0 0.0 0 +chr22 28963801 0 0 0.0 0 +chr22 29010170 0 0 0.0 0 +chr22 29083490 0 0 0.0 0 +chr22 29146825 0 0 0.0 0 +chr22 29252529 0 0 0.0 0 +chr22 29267857 0 0 0.0 0 +chr22 29287469 0 0 0.0 0 +chr22 29292377 0 0 0.0 0 +chr22 29296471 0 0 0.0 0 +chr22 29468866 0 0 0.0 0 +chr22 29531544 0 0 0.0 0 +chr22 29557077 0 0 0.0 0 +chr22 29635980 0 0 0.0 0 +chr22 29677481 1 7 0.1373 1 +chr22 29699724 0 0 0.0 0 +chr22 29731198 0 0 0.0 0 +chr22 29819061 0 0 0.0 0 +chr22 29884612 0 0 0.0 0 +chr22 30018006 0 0 0.0 0 +chr22 30076469 0 0 0.0 0 +chr22 30177808 0 0 0.0 0 +chr22 30201739 0 0 0.0 0 +chr22 30252789 0 0 0.0 0 +chr22 30287491 0 0 0.0 0 +chr22 30375348 0 0 0.0 0 +chr22 30410819 0 0 0.0 0 +chr22 30481773 0 0 0.0 0 +chr22 30490803 0 0 0.0 0 +chr22 30557694 0 0 0.0 0 +chr22 30597233 0 0 0.0 0 +chr22 30600088 0 0 0.0 0 +chr22 30608844 0 0 0.0 0 +chr22 30810291 0 0 0.0 0 +chr22 30814775 0 0 0.0 0 +chr22 30909211 0 0 0.0 0 +chr22 30965713 0 0 0.0 0 +chr22 31071823 0 0 0.0 0 +chr22 31095473 0 0 0.0 0 +chr22 31215248 0 0 0.0 0 +chr22 31264350 0 1 0.0164 0 +chr22 31574173 0 0 0.0 0 +chr22 31676441 0 0 0.0 0 +chr22 31836921 0 0 0.0 0 +chr22 31998893 0 0 0.0 0 +chr22 32043563 0 1 0.0145 0 +chr22 32177686 0 0 0.0 0 +chr22 32545237 0 0 0.0 0 +chr22 32595008 0 0 0.0 0 +chr22 32779772 0 0 0.0 0 +chr22 32821846 0 0 0.0 0 +chr22 32826866 0 0 0.0 0 +chr22 32831186 0 0 0.0 0 +chr22 32841748 0 0 0.0 0 +chr22 32842684 0 0 0.0 0 +chr22 32893292 0 0 0.0 0 +chr22 32917989 0 0 0.0 0 +chr22 33069736 0 0 0.0 0 +chr22 33150185 0 0 0.0 0 +chr22 33378264 0 0 0.0 0 +chr22 33535517 0 1 0.0169 0 +chr22 33664203 0 0 0.0 0 +chr22 33666092 0 0 0.0 0 +chr22 33707584 0 0 0.0 0 +chr22 33741982 0 0 0.0 0 +chr22 33762813 0 0 0.0 0 +chr22 33865158 0 0 0.0 0 +chr22 33868054 0 0 0.0 0 +chr22 34101563 0 0 0.0 0 +chr22 34211111 0 0 0.0 0 +chr22 34272818 0 0 0.0 0 +chr22 34283357 0 0 0.0 0 +chr22 34388407 0 0 0.0 0 +chr22 34431567 0 0 0.0 0 +chr22 34507966 0 0 0.0 0 +chr22 34532155 0 0 0.0 0 +chr22 34642141 0 0 0.0 0 +chr22 34759042 0 0 0.0 0 +chr22 34890152 0 0 0.0 0 +chr22 34989615 0 0 0.0 0 +chr22 35011697 0 0 0.0 0 +chr22 35083571 0 0 0.0 0 +chr22 35113748 0 0 0.0 0 +chr22 35144646 0 0 0.0 0 +chr22 35154781 0 0 0.0 0 +chr22 35166535 0 0 0.0 0 +chr22 35599934 0 0 0.0 0 +chr22 35689298 0 0 0.0 0 +chr22 35873976 0 0 0.0 0 +chr22 35893262 0 0 0.0 0 +chr22 36086270 0 0 0.0 0 +chr22 36244988 0 0 0.0 0 +chr22 36251695 0 0 0.0 0 +chr22 36252060 0 0 0.0 0 +chr22 36408603 0 0 0.0 0 +chr22 36426482 1 81 0.9529 1 +chr22 36454153 0 0 0.0 0 +chr22 36549237 0 0 0.0 0 +chr22 36623406 0 0 0.0 0 +chr22 36628227 0 0 0.0 0 +chr22 36786138 0 0 0.0 0 +chr22 36801849 0 0 0.0 0 +chr22 36879324 0 0 0.0 0 +chr22 37058346 0 0 0.0 0 +chr22 37085241 0 0 0.0 0 +chr22 37292691 0 0 0.0 0 +chr22 37335108 0 0 0.0 0 +chr22 37337811 0 0 0.0 0 +chr22 37344806 0 0 0.0 0 +chr22 37355684 0 0 0.0 0 +chr22 37384309 0 0 0.0 0 +chr22 37658325 0 0 0.0 0 +chr22 37779944 0 0 0.0 0 +chr22 37781988 0 0 0.0 0 +chr22 37813624 0 0 0.0 0 +chr22 37905539 0 0 0.0 0 +chr22 37942418 0 0 0.0 0 +chr22 38192666 0 0 0.0 0 +chr22 38218286 0 0 0.0 0 +chr22 38222902 0 0 0.0 0 +chr22 38247876 0 0 0.0 0 +chr22 38276194 0 0 0.0 0 +chr22 38279165 0 0 0.0 0 +chr22 38315663 1 44 0.8 1 +chr22 38326881 0 0 0.0 0 +chr22 38670503 0 0 0.0 0 +chr22 38712354 0 0 0.0 0 +chr22 38766089 0 0 0.0 0 +chr22 38786230 0 0 0.0 0 +chr22 39405948 0 0 0.0 0 +chr22 39497783 0 0 0.0 0 +chr22 39525512 0 0 0.0 0 +chr22 39556891 0 0 0.0 0 +chr22 39561744 0 0 0.0 0 +chr22 39600385 0 0 0.0 0 +chr22 39640889 0 0 0.0 0 +chr22 39654810 0 0 0.0 0 +chr22 39671450 0 0 0.0 0 +chr22 39709818 0 0 0.0 0 +chr22 39829425 0 0 0.0 0 +chr22 39842518 0 0 0.0 0 +chr22 39907196 0 0 0.0 0 +chr22 39976208 0 0 0.0 0 +chr22 40021929 0 0 0.0 0 +chr22 40207351 0 0 0.0 0 +chr22 40235993 0 0 0.0 0 +chr22 40308220 0 0 0.0 0 +chr22 40365758 0 0 0.0 0 +chr22 40404332 0 0 0.0 0 +chr22 40421652 0 0 0.0 0 +chr22 40657874 0 0 0.0 0 +chr22 40805472 0 0 0.0 0 +chr22 40962393 0 0 0.0 0 +chr22 40967348 0 0 0.0 0 +chr22 40994575 0 1 0.025 0 +chr22 41138523 0 0 0.0 0 +chr22 41317903 0 0 0.0 0 +chr22 41427204 0 0 0.0 0 +chr22 41448667 0 0 0.0 0 +chr22 41572129 0 0 0.0 0 +chr22 41714228 0 0 0.0 0 +chr22 41824854 0 0 0.0 0 +chr22 41838973 0 0 0.0 0 +chr22 41841019 0 0 0.0 0 +chr22 41996896 0 0 0.0 0 +chr22 42058580 0 0 0.0 0 +chr22 42213380 0 0 0.0 0 +chr22 42215005 0 0 0.0 0 +chr22 42259720 0 0 0.0 0 +chr22 42351529 0 0 0.0 0 +chr22 42415907 0 0 0.0 0 +chr22 42501201 0 0 0.0 0 +chr22 42521044 0 0 0.0 0 +chr22 42536866 0 0 0.0 0 +chr22 42554516 0 0 0.0 0 +chr22 42568152 0 0 0.0 0 +chr22 42720250 0 0 0.0 0 +chr22 42751972 0 0 0.0 0 +chr22 42900239 0 0 0.0 0 +chr22 43036730 0 0 0.0 0 +chr22 43098425 0 0 0.0 0 +chr22 43179271 0 0 0.0 0 +chr22 43202870 0 0 0.0 0 +chr22 43254064 0 0 0.0 0 +chr22 43268715 0 0 0.0 0 +chr22 43347532 0 0 0.0 0 +chr22 43347944 0 0 0.0 0 +chr22 43349110 0 0 0.0 0 +chr22 43389506 0 0 0.0 0 +chr22 43407789 0 0 0.0 0 +chr22 43421699 0 0 0.0 0 +chr22 43447674 0 0 0.0 0 +chr22 43494650 0 0 0.0 0 +chr22 43543493 0 0 0.0 0 +chr22 43602155 0 0 0.0 0 +chr22 43629258 0 0 0.0 0 +chr22 43632747 0 0 0.0 0 +chr22 43659979 0 0 0.0 0 +chr22 43682286 0 0 0.0 0 +chr22 43782826 0 0 0.0 0 +chr22 43791500 0 0 0.0 0 +chr22 43812170 0 0 0.0 0 +chr22 43844272 0 0 0.0 0 +chr22 43855799 1 24 0.4211 1 +chr22 43860402 0 0 0.0 0 +chr22 43883566 0 0 0.0 0 +chr22 43940160 0 0 0.0 0 +chr22 44213897 0 0 0.0 0 +chr22 44243945 0 0 0.0 0 +chr22 44265198 0 0 0.0 0 +chr22 44301902 0 0 0.0 0 +chr22 44406204 0 0 0.0 0 +chr22 44431440 0 0 0.0 0 +chr22 44460779 0 0 0.0 0 +chr22 44461487 0 0 0.0 0 +chr22 44678755 0 0 0.0 0 +chr22 44774348 0 0 0.0 0 +chr22 44798572 0 0 0.0 0 +chr22 44803193 0 0 0.0 0 +chr22 44821920 0 0 0.0 0 +chr22 45164110 0 0 0.0 0 +chr22 45195178 0 0 0.0 0 +chr22 45261588 0 0 0.0 0 +chr22 45429551 0 0 0.0 0 +chr22 45522891 0 0 0.0 0 +chr22 45810281 0 0 0.0 0 +chr22 45948649 0 0 0.0 0 +chr22 46013118 0 0 0.0 0 +chr22 46250783 0 0 0.0 0 +chr22 46270913 0 0 0.0 0 +chr22 46320072 0 1 0.0278 0 +chr22 46321647 0 0 0.0 0 +chr22 46401335 0 0 0.0 0 +chr22 46431874 0 0 0.0 0 +chr22 46468833 0 0 0.0 0 +chr22 46701291 0 0 0.0 0 +chr22 46731468 0 0 0.0 0 +chr22 46814026 0 0 0.0 0 +chr22 46898269 0 0 0.0 0 +chr22 46902796 0 0 0.0 0 +chr22 46910290 0 0 0.0 0 +chr22 46923666 0 0 0.0 0 +chr22 47044952 0 0 0.0 0 +chr22 47209485 0 0 0.0 0 +chr22 47273749 0 0 0.0 0 +chr22 47277990 0 0 0.0 0 +chr22 47344148 0 0 0.0 0 +chr22 47354001 0 0 0.0 0 +chr22 47391358 0 1 0.0139 0 +chr22 47553231 0 0 0.0 0 +chr22 47674954 0 0 0.0 0 +chr22 47820978 0 0 0.0 0 +chr22 48049292 0 0 0.0 0 +chr22 48070023 0 0 0.0 0 +chr22 48102931 0 0 0.0 0 +chr22 48203384 0 0 0.0 0 +chr22 48217542 0 0 0.0 0 +chr22 48250951 0 0 0.0 0 +chr22 48276002 0 0 0.0 0 +chr22 48279326 0 0 0.0 0 +chr22 48289409 0 0 0.0 0 +chr22 48296087 0 0 0.0 0 +chr22 48312058 0 0 0.0 0 +chr22 48330720 0 0 0.0 0 +chr22 48392493 0 0 0.0 0 +chr22 48452937 0 0 0.0 0 +chr22 48527076 0 0 0.0 0 +chr22 48559158 0 0 0.0 0 +chr22 48564850 0 0 0.0 0 +chr22 48673193 0 0 0.0 0 +chr22 48700657 0 0 0.0 0 +chr22 48790788 0 0 0.0 0 +chr22 48840121 0 1 0.0192 0 +chr22 48855957 0 0 0.0 0 +chr22 48889928 0 0 0.0 0 +chr22 48964750 0 0 0.0 0 +chr22 49002523 0 0 0.0 0 +chr22 49087018 0 0 0.0 0 +chr22 49136831 0 0 0.0 0 +chr22 49146458 0 0 0.0 0 +chr22 49163694 0 0 0.0 0 +chr22 49211692 0 0 0.0 0 +chr22 49233670 0 0 0.0 0 +chr22 49306666 0 0 0.0 0 +chr22 49393093 0 0 0.0 0 +chr22 49418921 0 0 0.0 0 +chr22 49437792 0 0 0.0 0 +chr22 49503111 0 0 0.0 0 +chr22 49647305 0 0 0.0 0 +chr22 49694873 0 0 0.0 0 +chr22 49734697 0 0 0.0 0 +chr22 49736133 0 0 0.0 0 +chr22 49890302 0 0 0.0 0 +chr22 50016430 0 0 0.0 0 +chr22 50110506 0 0 0.0 0 +chr22 50178746 0 0 0.0 0 +chr22 50192443 0 0 0.0 0 +chr22 50218239 0 0 0.0 0 +chr22 50219090 0 0 0.0 0 +chr22 50220081 0 0 0.0 0 +chr22 50249959 0 0 0.0 0 +chr22 50291782 0 0 0.0 0 +chr22 50415891 0 0 0.0 0 +chr22 50452858 0 0 0.0 0 +chr22 50470385 0 0 0.0 0 +chr22 50526747 0 0 0.0 0 +chr22 50579005 0 0 0.0 0 +chr22 50582172 0 0 0.0 0 +chr22 50664588 0 0 0.0 0 +chr22 50706050 0 0 0.0 0 +chr22_GL383582v2_alt 123576 0 0 0.0 0 +chr22_KI270731v1_random 76598 0 0 0.0 0 +chr22_KI270733v1_random 22595 0 0 0.0 0 +chr22_KI270733v1_random 43201 0 0 0.0 0 +chr22_KI270734v1_random 10208 0 0 0.0 0 +chr22_KI270735v1_random 42555 0 0 0.0 0 +chr22_KI270736v1_random 39247 0 0 0.0 0 +chr22_KI270736v1_random 48834 0 0 0.0 0 +chr22_KI270736v1_random 49074 0 0 0.0 0 +chr22_KI270736v1_random 52000 0 0 0.0 0 +chr22_KI270736v1_random 54424 0 0 0.0 0 +chr22_KI270736v1_random 58640 0 0 0.0 0 +chr22_KI270736v1_random 63136 0 0 0.0 0 +chr22_KI270736v1_random 65721 0 0 0.0 0 +chr22_KI270736v1_random 74454 0 0 0.0 0 +chr22_KI270736v1_random 75698 0 0 0.0 0 +chr22_KI270736v1_random 77889 0 0 0.0 0 +chr22_KI270736v1_random 85210 0 0 0.0 0 +chr22_KI270736v1_random 91920 0 0 0.0 0 +chr22_KI270736v1_random 94507 0 0 0.0 0 +chr22_KI270736v1_random 97895 0 0 0.0 0 +chr22_KI270736v1_random 100580 0 0 0.0 0 +chr22_KI270736v1_random 103969 0 0 0.0 0 +chr22_KI270736v1_random 105822 0 0 0.0 0 +chr22_KI270736v1_random 107576 0 0 0.0 0 +chr22_KI270736v1_random 108066 0 0 0.0 0 +chr22_KI270736v1_random 109120 0 0 0.0 0 +chr22_KI270736v1_random 113155 0 0 0.0 0 +chr22_KI270736v1_random 113605 0 0 0.0 0 +chr22_KI270736v1_random 116325 0 0 0.0 0 +chr22_KI270736v1_random 119624 0 0 0.0 0 +chr22_KI270736v1_random 122461 0 0 0.0 0 +chr22_KI270736v1_random 126126 0 0 0.0 0 +chr22_KI270736v1_random 130690 0 0 0.0 0 +chr22_KI270736v1_random 135804 0 0 0.0 0 +chr22_KI270736v1_random 149270 0 0 0.0 0 +chr22_KI270736v1_random 149765 0 0 0.0 0 +chr22_KI270736v1_random 151017 0 0 0.0 0 +chr22_KI270736v1_random 157460 0 0 0.0 0 +chr22_KI270736v1_random 158637 0 0 0.0 0 +chr22_KI270736v1_random 162509 0 0 0.0 0 +chr22_KI270736v1_random 166152 0 0 0.0 0 +chr22_KI270736v1_random 166811 0 0 0.0 0 +chr22_KI270736v1_random 172531 0 0 0.0 0 +chr22_KI270736v1_random 179409 0 0 0.0 0 +chr22_KI270737v1_random 32118 0 0 0.0 0 +chr22_KI270739v1_random 20697 0 0 0.0 0 +chr22_KI270739v1_random 22233 0 0 0.0 0 +chr22_KI270875v1_alt 41808 0 0 0.0 0 +chr22_KI270875v1_alt 215499 0 0 0.0 0 +chr22_KI270875v1_alt 223869 0 0 0.0 0 +chr22_KI270876v1_alt 194974 0 0 0.0 0 +chr22_KI270877v1_alt 22635 0 0 0.0 0 +chr22_KI270878v1_alt 171830 0 0 0.0 0 +chr22_KI270879v1_alt 147764 0 0 0.0 0 +chr22_KI270928v1_alt 135725 0 0 0.0 0 +chr2_KI270769v1_alt 39624 0 0 0.0 0 +chr2_KI270769v1_alt 40836 0 0 0.0 0 +chr2_KI270770v1_alt 34363 0 0 0.0 0 +chr2_KI270772v1_alt 132535 0 0 0.0 0 +chr2_KI270774v1_alt 135897 0 0 0.0 0 +chr2_KI270776v1_alt 38395 0 0 0.0 0 +chr2_KI270776v1_alt 64872 0 0 0.0 0 +chr2_KI270894v1_alt 48636 0 0 0.0 0 +chr2_KI270894v1_alt 76325 0 0 0.0 0 +chr3 26730 0 0 0.0 0 +chr3 55881 0 0 0.0 0 +chr3 126264 0 1 0.025 0 +chr3 147641 0 0 0.0 0 +chr3 281359 0 0 0.0 0 +chr3 305141 0 0 0.0 0 +chr3 337284 0 0 0.0 0 +chr3 444299 0 0 0.0 0 +chr3 471352 0 0 0.0 0 +chr3 472805 0 0 0.0 0 +chr3 571129 0 0 0.0 0 +chr3 602118 0 0 0.0 0 +chr3 632776 0 0 0.0 0 +chr3 687628 0 0 0.0 0 +chr3 721865 0 0 0.0 0 +chr3 745699 0 0 0.0 0 +chr3 999798 1 32 0.8205 1 +chr3 1030148 0 0 0.0 0 +chr3 1243359 0 0 0.0 0 +chr3 1257644 0 0 0.0 0 +chr3 1453778 0 0 0.0 0 +chr3 1478348 0 0 0.0 0 +chr3 1598575 0 0 0.0 0 +chr3 1689845 0 0 0.0 0 +chr3 1797869 0 0 0.0 0 +chr3 1959365 0 0 0.0 0 +chr3 2127235 0 0 0.0 0 +chr3 2183085 0 0 0.0 0 +chr3 2185490 0 0 0.0 0 +chr3 2195814 0 0 0.0 0 +chr3 2243618 0 0 0.0 0 +chr3 2266874 0 0 0.0 0 +chr3 2352753 0 0 0.0 0 +chr3 2382790 0 0 0.0 0 +chr3 2414072 0 0 0.0 0 +chr3 2564010 0 0 0.0 0 +chr3 2651566 0 0 0.0 0 +chr3 2762790 0 0 0.0 0 +chr3 2880334 0 0 0.0 0 +chr3 3115290 0 0 0.0 0 +chr3 3219533 0 1 0.0169 0 +chr3 3417663 0 0 0.0 0 +chr3 3419818 0 0 0.0 0 +chr3 3433120 0 0 0.0 0 +chr3 3563405 0 0 0.0 0 +chr3 3577396 0 0 0.0 0 +chr3 3577902 0 0 0.0 0 +chr3 3685997 0 0 0.0 0 +chr3 3739177 0 0 0.0 0 +chr3 3810066 0 0 0.0 0 +chr3 3836747 0 0 0.0 0 +chr3 3843577 1 32 0.7805 1 +chr3 3849316 0 0 0.0 0 +chr3 3891492 0 0 0.0 0 +chr3 4004269 0 0 0.0 0 +chr3 4143609 0 0 0.0 0 +chr3 4246002 0 0 0.0 0 +chr3 4466043 0 0 0.0 0 +chr3 4682939 0 0 0.0 0 +chr3 4693842 0 0 0.0 0 +chr3 4771260 0 0 0.0 0 +chr3 5021596 0 0 0.0 0 +chr3 5044845 0 0 0.0 0 +chr3 5110413 0 0 0.0 0 +chr3 5143132 0 0 0.0 0 +chr3 5196850 0 0 0.0 0 +chr3 5212723 0 0 0.0 0 +chr3 5277143 0 0 0.0 0 +chr3 5295893 0 0 0.0 0 +chr3 5394396 0 0 0.0 0 +chr3 5454444 0 0 0.0 0 +chr3 5482507 0 0 0.0 0 +chr3 5578425 0 0 0.0 0 +chr3 5584097 0 0 0.0 0 +chr3 5596074 0 0 0.0 0 +chr3 5715102 0 0 0.0 0 +chr3 5927687 0 0 0.0 0 +chr3 5944315 0 0 0.0 0 +chr3 6008558 0 0 0.0 0 +chr3 6066379 0 0 0.0 0 +chr3 6076593 0 0 0.0 0 +chr3 6329516 0 0 0.0 0 +chr3 6631621 0 0 0.0 0 +chr3 6675700 0 0 0.0 0 +chr3 6825159 0 1 0.0154 0 +chr3 6982338 0 0 0.0 0 +chr3 6992142 0 0 0.0 0 +chr3 6996860 0 0 0.0 0 +chr3 7041784 0 0 0.0 0 +chr3 7070905 0 0 0.0 0 +chr3 7145218 0 0 0.0 0 +chr3 7239954 0 0 0.0 0 +chr3 7324770 0 0 0.0 0 +chr3 7392194 0 0 0.0 0 +chr3 7444087 0 0 0.0 0 +chr3 7480115 0 0 0.0 0 +chr3 7525732 0 0 0.0 0 +chr3 7563704 0 0 0.0 0 +chr3 7633512 0 0 0.0 0 +chr3 7716205 0 0 0.0 0 +chr3 7773664 0 0 0.0 0 +chr3 7944755 0 0 0.0 0 +chr3 7986016 0 0 0.0 0 +chr3 8047122 0 0 0.0 0 +chr3 8051052 0 0 0.0 0 +chr3 8248105 0 0 0.0 0 +chr3 8292815 0 0 0.0 0 +chr3 8331362 0 1 0.0132 0 +chr3 8418175 0 0 0.0 0 +chr3 8478514 0 0 0.0 0 +chr3 8530610 0 0 0.0 0 +chr3 8654538 0 0 0.0 0 +chr3 8664362 0 0 0.0 0 +chr3 8673721 0 0 0.0 0 +chr3 8727494 0 0 0.0 0 +chr3 8757608 0 0 0.0 0 +chr3 8851759 0 0 0.0 0 +chr3 8853138 0 0 0.0 0 +chr3 8889523 0 0 0.0 0 +chr3 8922797 0 0 0.0 0 +chr3 9015737 0 0 0.0 0 +chr3 9410096 0 0 0.0 0 +chr3 9428153 0 0 0.0 0 +chr3 9447287 0 0 0.0 0 +chr3 9546554 0 0 0.0 0 +chr3 9592571 0 0 0.0 0 +chr3 9835769 0 0 0.0 0 +chr3 9923307 1 74 0.9737 1 +chr3 10150987 0 0 0.0 0 +chr3 10334146 0 0 0.0 0 +chr3 10351913 0 0 0.0 0 +chr3 10352990 0 0 0.0 0 +chr3 10479704 0 0 0.0 0 +chr3 10492870 0 0 0.0 0 +chr3 10571402 0 0 0.0 0 +chr3 10640535 0 0 0.0 0 +chr3 10754231 0 1 0.0208 0 +chr3 10770157 0 0 0.0 0 +chr3 10864708 0 1 0.0115 0 +chr3 10938119 0 0 0.0 0 +chr3 11020130 0 0 0.0 0 +chr3 11083314 0 0 0.0 0 +chr3 11171612 0 0 0.0 0 +chr3 11221021 0 0 0.0 0 +chr3 11333148 0 0 0.0 0 +chr3 11432459 1 60 0.9375 1 +chr3 11445140 0 0 0.0 0 +chr3 11495447 1 36 0.5217 1 +chr3 11522363 0 0 0.0 0 +chr3 11547070 0 0 0.0 0 +chr3 11622738 0 0 0.0 0 +chr3 11624259 0 0 0.0 0 +chr3 11986512 0 0 0.0 0 +chr3 12110272 0 0 0.0 0 +chr3 12168986 0 0 0.0 0 +chr3 12189453 0 0 0.0 0 +chr3 12266243 0 0 0.0 0 +chr3 12475560 0 0 0.0 0 +chr3 12487326 0 0 0.0 0 +chr3 12530011 0 0 0.0 0 +chr3 12655994 0 0 0.0 0 +chr3 12692784 0 0 0.0 0 +chr3 12753111 0 0 0.0 0 +chr3 12798100 1 67 0.8816 1 +chr3 12822560 0 0 0.0 0 +chr3 12865670 0 0 0.0 0 +chr3 12942875 0 0 0.0 0 +chr3 12966666 0 0 0.0 0 +chr3 12980995 0 0 0.0 0 +chr3 13044528 0 0 0.0 0 +chr3 13074368 2 70 0.9138 1 +chr3 13207942 0 0 0.0 0 +chr3 13314887 0 0 0.0 0 +chr3 13324581 0 0 0.0 0 +chr3 13327796 0 0 0.0 0 +chr3 13376707 0 0 0.0 0 +chr3 13498986 0 0 0.0 0 +chr3 13520387 0 0 0.0 0 +chr3 13537917 0 0 0.0 0 +chr3 13557230 0 0 0.0 0 +chr3 13674716 0 0 0.0 0 +chr3 13706816 0 0 0.0 0 +chr3 13872502 0 1 0.0222 0 +chr3 13887143 0 0 0.0 0 +chr3 14037574 0 0 0.0 0 +chr3 14138911 0 0 0.0 0 +chr3 14232343 0 1 0.0149 0 +chr3 14258734 0 0 0.0 0 +chr3 14267355 0 0 0.0 0 +chr3 14272196 0 0 0.0 0 +chr3 14303849 0 0 0.0 0 +chr3 14353613 0 0 0.0 0 +chr3 14368683 0 0 0.0 0 +chr3 14377712 0 0 0.0 0 +chr3 14503860 0 0 0.0 0 +chr3 14580095 0 0 0.0 0 +chr3 14806793 0 0 0.0 0 +chr3 14837397 0 0 0.0 0 +chr3 14852658 0 0 0.0 0 +chr3 14955676 0 0 0.0 0 +chr3 15116946 0 0 0.0 0 +chr3 15294922 0 0 0.0 0 +chr3 15303478 0 0 0.0 0 +chr3 15396769 0 0 0.0 0 +chr3 15566259 0 0 0.0 0 +chr3 15654447 0 0 0.0 0 +chr3 15874332 1 40 0.9756 1 +chr3 15900198 0 0 0.0 0 +chr3 15947396 0 0 0.0 0 +chr3 15981566 0 0 0.0 0 +chr3 16012662 0 0 0.0 0 +chr3 16045216 0 0 0.0 0 +chr3 16046411 0 0 0.0 0 +chr3 16064469 0 0 0.0 0 +chr3 16091672 0 0 0.0 0 +chr3 16164164 0 0 0.0 0 +chr3 16175947 0 0 0.0 0 +chr3 16206229 0 0 0.0 0 +chr3 16254829 0 0 0.0 0 +chr3 16302081 0 0 0.0 0 +chr3 16312223 0 0 0.0 0 +chr3 16382634 0 0 0.0 0 +chr3 16621538 0 0 0.0 0 +chr3 16650376 0 0 0.0 0 +chr3 16665114 0 0 0.0 0 +chr3 16804980 0 0 0.0 0 +chr3 17020456 0 0 0.0 0 +chr3 17149782 0 0 0.0 0 +chr3 17208706 0 0 0.0 0 +chr3 17297711 0 0 0.0 0 +chr3 17400119 0 0 0.0 0 +chr3 17500866 0 0 0.0 0 +chr3 17557679 0 0 0.0 0 +chr3 17665752 0 0 0.0 0 +chr3 17798943 0 0 0.0 0 +chr3 17852768 0 0 0.0 0 +chr3 17973681 0 0 0.0 0 +chr3 18073743 0 0 0.0 0 +chr3 18076009 0 0 0.0 0 +chr3 18178312 0 0 0.0 0 +chr3 18179906 0 0 0.0 0 +chr3 18277869 0 0 0.0 0 +chr3 18379772 0 0 0.0 0 +chr3 18531023 0 0 0.0 0 +chr3 18568058 0 0 0.0 0 +chr3 18668769 0 0 0.0 0 +chr3 19211452 0 0 0.0 0 +chr3 19286254 0 0 0.0 0 +chr3 19350947 0 0 0.0 0 +chr3 19888992 0 0 0.0 0 +chr3 19927330 0 0 0.0 0 +chr3 20025391 0 0 0.0 0 +chr3 20057409 0 0 0.0 0 +chr3 20272813 2 41 0.5395 1 +chr3 20295536 0 0 0.0 0 +chr3 20404419 0 0 0.0 0 +chr3 20575001 0 0 0.0 0 +chr3 20578118 0 0 0.0 0 +chr3 20653740 0 0 0.0 0 +chr3 20751972 0 0 0.0 0 +chr3 20793149 0 0 0.0 0 +chr3 20806169 0 0 0.0 0 +chr3 20836774 0 0 0.0 0 +chr3 20914670 0 0 0.0 0 +chr3 21027895 0 0 0.0 0 +chr3 21125148 0 0 0.0 0 +chr3 21159705 0 0 0.0 0 +chr3 21348225 0 0 0.0 0 +chr3 21396257 0 0 0.0 0 +chr3 21517358 0 0 0.0 0 +chr3 21535457 0 0 0.0 0 +chr3 21666795 0 0 0.0 0 +chr3 21767557 0 0 0.0 0 +chr3 21774774 0 0 0.0 0 +chr3 21781119 0 0 0.0 0 +chr3 21837318 0 0 0.0 0 +chr3 22078373 0 0 0.0 0 +chr3 22244202 0 0 0.0 0 +chr3 22323980 0 0 0.0 0 +chr3 22417319 0 0 0.0 0 +chr3 22424991 0 0 0.0 0 +chr3 22494563 0 0 0.0 0 +chr3 22569964 0 0 0.0 0 +chr3 22643474 0 0 0.0 0 +chr3 22785556 0 0 0.0 0 +chr3 22867832 0 0 0.0 0 +chr3 22918666 0 0 0.0 0 +chr3 23092591 0 0 0.0 0 +chr3 23138671 0 0 0.0 0 +chr3 23170587 0 0 0.0 0 +chr3 23305360 0 0 0.0 0 +chr3 23396975 0 0 0.0 0 +chr3 23416136 0 0 0.0 0 +chr3 23426249 0 0 0.0 0 +chr3 23526341 0 1 0.0227 0 +chr3 23549721 1 72 0.8889 1 +chr3 23748811 0 0 0.0 0 +chr3 24047699 0 0 0.0 0 +chr3 24198835 0 0 0.0 0 +chr3 24316046 0 0 0.0 0 +chr3 24334540 0 0 0.0 0 +chr3 24435141 0 1 0.0238 0 +chr3 24516194 0 0 0.0 0 +chr3 24648062 0 0 0.0 0 +chr3 24671583 0 0 0.0 0 +chr3 24699339 0 0 0.0 0 +chr3 24755135 0 0 0.0 0 +chr3 24938742 0 0 0.0 0 +chr3 25018384 0 0 0.0 0 +chr3 25086153 0 0 0.0 0 +chr3 25208184 0 0 0.0 0 +chr3 25241707 0 0 0.0 0 +chr3 25281820 0 0 0.0 0 +chr3 25286182 2 31 0.6078 1 +chr3 25362359 0 0 0.0 0 +chr3 25502343 0 0 0.0 0 +chr3 25522448 0 0 0.0 0 +chr3 25644888 0 0 0.0 0 +chr3 25669518 0 0 0.0 0 +chr3 25708525 0 0 0.0 0 +chr3 25904351 0 0 0.0 0 +chr3 25917066 0 0 0.0 0 +chr3 25974268 0 0 0.0 0 +chr3 26163916 0 0 0.0 0 +chr3 26169412 0 0 0.0 0 +chr3 26244346 0 0 0.0 0 +chr3 26440252 0 0 0.0 0 +chr3 26475767 0 0 0.0 0 +chr3 26504507 0 0 0.0 0 +chr3 26533872 0 0 0.0 0 +chr3 26558074 0 0 0.0 0 +chr3 26827062 0 0 0.0 0 +chr3 26906320 0 0 0.0 0 +chr3 26927947 0 0 0.0 0 +chr3 26942902 0 0 0.0 0 +chr3 26983948 0 0 0.0 0 +chr3 27003378 0 0 0.0 0 +chr3 27097029 0 0 0.0 0 +chr3 27504354 0 0 0.0 0 +chr3 27523715 0 0 0.0 0 +chr3 27546459 0 0 0.0 0 +chr3 27634335 0 0 0.0 0 +chr3 27648783 0 0 0.0 0 +chr3 27669765 0 0 0.0 0 +chr3 27778720 0 0 0.0 0 +chr3 28341415 0 0 0.0 0 +chr3 28892525 0 0 0.0 0 +chr3 28929432 0 1 0.0233 0 +chr3 28973328 0 0 0.0 0 +chr3 29015970 0 0 0.0 0 +chr3 29080344 0 0 0.0 0 +chr3 29217321 0 0 0.0 0 +chr3 29319225 0 0 0.0 0 +chr3 29339384 0 0 0.0 0 +chr3 29476342 0 0 0.0 0 +chr3 29643409 0 0 0.0 0 +chr3 29954812 0 1 0.02 0 +chr3 30028941 0 0 0.0 0 +chr3 30034202 0 0 0.0 0 +chr3 30058202 0 0 0.0 0 +chr3 30143311 0 0 0.0 0 +chr3 30373628 0 0 0.0 0 +chr3 30523239 0 0 0.0 0 +chr3 30678597 0 0 0.0 0 +chr3 30798197 0 0 0.0 0 +chr3 30829993 0 0 0.0 0 +chr3 30904124 0 0 0.0 0 +chr3 30946627 0 0 0.0 0 +chr3 31082160 0 0 0.0 0 +chr3 31213278 0 0 0.0 0 +chr3 31356722 0 0 0.0 0 +chr3 31370223 0 0 0.0 0 +chr3 31429874 0 0 0.0 0 +chr3 31430187 0 0 0.0 0 +chr3 31552762 0 0 0.0 0 +chr3 31830130 0 0 0.0 0 +chr3 31906920 0 0 0.0 0 +chr3 32023762 0 0 0.0 0 +chr3 32126585 0 0 0.0 0 +chr3 32276179 0 0 0.0 0 +chr3 32421122 0 0 0.0 0 +chr3 32451367 0 0 0.0 0 +chr3 32484990 0 0 0.0 0 +chr3 32519936 0 0 0.0 0 +chr3 32586483 0 0 0.0 0 +chr3 32673610 0 0 0.0 0 +chr3 32685281 0 0 0.0 0 +chr3 32689543 0 0 0.0 0 +chr3 32868258 0 0 0.0 0 +chr3 32870385 0 0 0.0 0 +chr3 33026175 0 0 0.0 0 +chr3 33062547 0 0 0.0 0 +chr3 33101806 0 0 0.0 0 +chr3 33184201 0 0 0.0 0 +chr3 33285989 0 0 0.0 0 +chr3 33350669 0 0 0.0 0 +chr3 33415582 0 0 0.0 0 +chr3 33809382 0 0 0.0 0 +chr3 33946598 0 0 0.0 0 +chr3 33947342 0 0 0.0 0 +chr3 33974174 0 0 0.0 0 +chr3 33983782 0 0 0.0 0 +chr3 34091091 0 0 0.0 0 +chr3 34203267 0 0 0.0 0 +chr3 34240407 0 0 0.0 0 +chr3 34341705 0 0 0.0 0 +chr3 34541433 0 0 0.0 0 +chr3 34821677 0 0 0.0 0 +chr3 34970777 0 0 0.0 0 +chr3 35313907 0 0 0.0 0 +chr3 35399056 0 0 0.0 0 +chr3 35630343 0 0 0.0 0 +chr3 35675640 0 0 0.0 0 +chr3 35803645 0 0 0.0 0 +chr3 35825923 0 0 0.0 0 +chr3 36093901 0 0 0.0 0 +chr3 36173459 0 0 0.0 0 +chr3 36187064 0 0 0.0 0 +chr3 36262183 0 0 0.0 0 +chr3 36628647 0 0 0.0 0 +chr3 36645120 0 0 0.0 0 +chr3 36857105 0 0 0.0 0 +chr3 36893532 0 0 0.0 0 +chr3 37118324 0 0 0.0 0 +chr3 37456009 0 0 0.0 0 +chr3 37470926 0 0 0.0 0 +chr3 37563517 0 0 0.0 0 +chr3 37685620 0 0 0.0 0 +chr3 37722140 3 59 1.0 1 +chr3 37764549 0 0 0.0 0 +chr3 37944466 0 0 0.0 0 +chr3 37945259 0 0 0.0 0 +chr3 38002806 0 1 0.0222 0 +chr3 38031452 0 0 0.0 0 +chr3 38115607 0 0 0.0 0 +chr3 38273350 0 0 0.0 0 +chr3 38360520 0 0 0.0 0 +chr3 38469907 0 0 0.0 0 +chr3 38650771 0 1 0.0204 0 +chr3 38757213 0 0 0.0 0 +chr3 39021660 0 0 0.0 0 +chr3 39048914 0 0 0.0 0 +chr3 39058142 0 0 0.0 0 +chr3 39132288 0 0 0.0 0 +chr3 39163765 0 0 0.0 0 +chr3 39252985 0 0 0.0 0 +chr3 39269790 0 0 0.0 0 +chr3 39361832 0 0 0.0 0 +chr3 39371895 0 0 0.0 0 +chr3 39389706 0 0 0.0 0 +chr3 39414434 0 0 0.0 0 +chr3 39622739 0 0 0.0 0 +chr3 39638729 0 0 0.0 0 +chr3 39664485 0 0 0.0 0 +chr3 39723725 0 0 0.0 0 +chr3 39810498 0 0 0.0 0 +chr3 39823467 0 0 0.0 0 +chr3 39842330 0 0 0.0 0 +chr3 39842522 0 0 0.0 0 +chr3 39847254 0 0 0.0 0 +chr3 39954396 0 0 0.0 0 +chr3 40023634 0 0 0.0 0 +chr3 40088958 0 0 0.0 0 +chr3 40317932 0 0 0.0 0 +chr3 40345512 0 0 0.0 0 +chr3 40365931 0 0 0.0 0 +chr3 40719660 0 0 0.0 0 +chr3 40862415 0 0 0.0 0 +chr3 40969304 0 0 0.0 0 +chr3 41033731 0 0 0.0 0 +chr3 41126723 0 0 0.0 0 +chr3 41147113 0 0 0.0 0 +chr3 41203910 0 0 0.0 0 +chr3 41303988 0 0 0.0 0 +chr3 41486067 0 0 0.0 0 +chr3 41616927 0 0 0.0 0 +chr3 41925695 0 0 0.0 0 +chr3 42028514 0 1 0.0114 0 +chr3 42050702 0 0 0.0 0 +chr3 42051876 0 0 0.0 0 +chr3 42127100 0 0 0.0 0 +chr3 42165700 0 0 0.0 0 +chr3 42170489 0 0 0.0 0 +chr3 42206701 0 0 0.0 0 +chr3 42226685 0 0 0.0 0 +chr3 42563142 0 0 0.0 0 +chr3 42852249 0 0 0.0 0 +chr3 42945976 0 0 0.0 0 +chr3 42983098 0 0 0.0 0 +chr3 43221419 0 0 0.0 0 +chr3 43259938 0 0 0.0 0 +chr3 43364032 0 0 0.0 0 +chr3 43390874 0 0 0.0 0 +chr3 43401992 0 0 0.0 0 +chr3 43459251 0 0 0.0 0 +chr3 43703440 0 0 0.0 0 +chr3 43808735 0 0 0.0 0 +chr3 43829922 0 0 0.0 0 +chr3 43937863 0 0 0.0 0 +chr3 43945930 0 0 0.0 0 +chr3 44039203 0 0 0.0 0 +chr3 44058622 0 0 0.0 0 +chr3 44186334 0 0 0.0 0 +chr3 44309377 0 0 0.0 0 +chr3 44358685 0 0 0.0 0 +chr3 44438638 0 0 0.0 0 +chr3 44646680 0 0 0.0 0 +chr3 44675956 0 0 0.0 0 +chr3 44708233 1 24 0.3636 1 +chr3 44762262 0 0 0.0 0 +chr3 44828107 0 0 0.0 0 +chr3 44846293 0 0 0.0 0 +chr3 45086779 0 0 0.0 0 +chr3 45103985 0 0 0.0 0 +chr3 45144119 0 0 0.0 0 +chr3 45172327 0 0 0.0 0 +chr3 45177668 0 0 0.0 0 +chr3 45243635 0 0 0.0 0 +chr3 45258360 1 7 0.0946 1 +chr3 45395941 0 0 0.0 0 +chr3 45498190 0 0 0.0 0 +chr3 45616410 0 0 0.0 0 +chr3 45624789 0 0 0.0 0 +chr3 45644169 0 0 0.0 0 +chr3 45747760 0 0 0.0 0 +chr3 45821973 0 0 0.0 0 +chr3 45872763 0 0 0.0 0 +chr3 45873113 0 0 0.0 0 +chr3 45931050 0 0 0.0 0 +chr3 46079494 0 0 0.0 0 +chr3 46163270 0 0 0.0 0 +chr3 46322469 0 0 0.0 0 +chr3 46322630 0 0 0.0 0 +chr3 46358615 0 0 0.0 0 +chr3 46419835 0 0 0.0 0 +chr3 46514818 0 0 0.0 0 +chr3 46558526 0 0 0.0 0 +chr3 46862665 0 0 0.0 0 +chr3 46998246 0 0 0.0 0 +chr3 47125048 0 0 0.0 0 +chr3 47179119 0 0 0.0 0 +chr3 47259025 0 0 0.0 0 +chr3 47433302 0 0 0.0 0 +chr3 47461005 0 0 0.0 0 +chr3 47504884 0 0 0.0 0 +chr3 47609726 0 0 0.0 0 +chr3 47711318 0 0 0.0 0 +chr3 47841034 0 0 0.0 0 +chr3 47885439 0 0 0.0 0 +chr3 48151159 0 0 0.0 0 +chr3 48227603 0 0 0.0 0 +chr3 48334396 0 0 0.0 0 +chr3 48422375 0 0 0.0 0 +chr3 48431709 0 0 0.0 0 +chr3 48560508 0 0 0.0 0 +chr3 48593393 0 0 0.0 0 +chr3 48628543 0 0 0.0 0 +chr3 48632827 0 0 0.0 0 +chr3 48673767 0 0 0.0 0 +chr3 48979361 0 0 0.0 0 +chr3 49039437 0 0 0.0 0 +chr3 49054183 0 0 0.0 0 +chr3 49200584 0 0 0.0 0 +chr3 49219706 0 0 0.0 0 +chr3 49489550 0 0 0.0 0 +chr3 49525651 0 0 0.0 0 +chr3 49554256 0 0 0.0 0 +chr3 49607987 0 0 0.0 0 +chr3 49655413 0 0 0.0 0 +chr3 49698191 0 0 0.0 0 +chr3 49727667 0 0 0.0 0 +chr3 49748413 0 0 0.0 0 +chr3 49841978 0 0 0.0 0 +chr3 49876165 0 0 0.0 0 +chr3 50051230 0 0 0.0 0 +chr3 50078753 0 0 0.0 0 +chr3 50124134 0 0 0.0 0 +chr3 50190988 0 0 0.0 0 +chr3 50276336 0 0 0.0 0 +chr3 50407583 0 0 0.0 0 +chr3 50420661 0 0 0.0 0 +chr3 50502333 0 0 0.0 0 +chr3 50560055 0 0 0.0 0 +chr3 50649511 0 0 0.0 0 +chr3 50657821 0 0 0.0 0 +chr3 50682695 0 0 0.0 0 +chr3 50721265 0 0 0.0 0 +chr3 50744370 0 0 0.0 0 +chr3 50838650 0 0 0.0 0 +chr3 50857235 0 0 0.0 0 +chr3 50878002 0 0 0.0 0 +chr3 51276646 0 0 0.0 0 +chr3 51389252 0 0 0.0 0 +chr3 51471444 0 0 0.0 0 +chr3 51645117 0 0 0.0 0 +chr3 51646284 0 0 0.0 0 +chr3 51705399 0 0 0.0 0 +chr3 51718887 0 0 0.0 0 +chr3 51738515 0 0 0.0 0 +chr3 51750859 0 0 0.0 0 +chr3 51946227 0 0 0.0 0 +chr3 52060727 0 0 0.0 0 +chr3 52441161 0 0 0.0 0 +chr3 52502631 0 0 0.0 0 +chr3 52551891 0 0 0.0 0 +chr3 52601803 0 0 0.0 0 +chr3 52761911 0 0 0.0 0 +chr3 52768484 0 0 0.0 0 +chr3 52774560 0 0 0.0 0 +chr3 52829129 0 0 0.0 0 +chr3 52868205 0 0 0.0 0 +chr3 52969858 0 0 0.0 0 +chr3 53151847 0 0 0.0 0 +chr3 53160729 0 0 0.0 0 +chr3 53172342 0 0 0.0 0 +chr3 53179139 0 0 0.0 0 +chr3 53189088 0 0 0.0 0 +chr3 53220038 0 0 0.0 0 +chr3 53228411 0 0 0.0 0 +chr3 53277327 0 0 0.0 0 +chr3 53340015 0 0 0.0 0 +chr3 53365180 0 0 0.0 0 +chr3 53407410 0 0 0.0 0 +chr3 53446032 0 0 0.0 0 +chr3 53490820 0 0 0.0 0 +chr3 53546863 0 0 0.0 0 +chr3 53563125 0 0 0.0 0 +chr3 53574202 0 0 0.0 0 +chr3 53575598 0 0 0.0 0 +chr3 53693307 0 0 0.0 0 +chr3 53716830 0 0 0.0 0 +chr3 53771845 0 0 0.0 0 +chr3 53793379 0 0 0.0 0 +chr3 53873302 0 0 0.0 0 +chr3 53943851 0 0 0.0 0 +chr3 54194311 0 0 0.0 0 +chr3 54372083 0 0 0.0 0 +chr3 54451081 0 0 0.0 0 +chr3 54467774 0 0 0.0 0 +chr3 54534431 0 0 0.0 0 +chr3 54582435 0 0 0.0 0 +chr3 54628418 0 0 0.0 0 +chr3 54665279 0 0 0.0 0 +chr3 54686241 0 0 0.0 0 +chr3 54802903 0 0 0.0 0 +chr3 55120224 0 0 0.0 0 +chr3 55333016 0 0 0.0 0 +chr3 55548690 0 0 0.0 0 +chr3 55554445 0 0 0.0 0 +chr3 55626153 0 0 0.0 0 +chr3 55640017 0 0 0.0 0 +chr3 55648132 0 0 0.0 0 +chr3 55731782 0 0 0.0 0 +chr3 55795982 0 0 0.0 0 +chr3 56052379 0 0 0.0 0 +chr3 56056821 0 0 0.0 0 +chr3 56420426 0 0 0.0 0 +chr3 56484821 0 0 0.0 0 +chr3 56489505 0 0 0.0 0 +chr3 56522461 0 0 0.0 0 +chr3 56536349 0 0 0.0 0 +chr3 56594223 0 0 0.0 0 +chr3 56668386 0 0 0.0 0 +chr3 56673665 0 0 0.0 0 +chr3 56812146 0 0 0.0 0 +chr3 56898738 0 0 0.0 0 +chr3 56928525 0 0 0.0 0 +chr3 56930113 0 0 0.0 0 +chr3 57030993 0 0 0.0 0 +chr3 57177129 0 0 0.0 0 +chr3 57303070 0 0 0.0 0 +chr3 57665882 0 0 0.0 0 +chr3 57855633 0 0 0.0 0 +chr3 57904014 0 0 0.0 0 +chr3 57983331 0 0 0.0 0 +chr3 58080230 0 0 0.0 0 +chr3 58111721 0 0 0.0 0 +chr3 58128786 0 0 0.0 0 +chr3 58155023 0 0 0.0 0 +chr3 58203139 0 0 0.0 0 +chr3 58255040 0 0 0.0 0 +chr3 58397609 0 0 0.0 0 +chr3 58423048 0 0 0.0 0 +chr3 58560129 0 0 0.0 0 +chr3 58750571 0 0 0.0 0 +chr3 58836255 0 0 0.0 0 +chr3 58971750 0 0 0.0 0 +chr3 59134197 0 0 0.0 0 +chr3 59138952 0 0 0.0 0 +chr3 59150916 0 0 0.0 0 +chr3 59226145 0 0 0.0 0 +chr3 59384507 0 0 0.0 0 +chr3 59637148 0 0 0.0 0 +chr3 59764172 0 0 0.0 0 +chr3 59958408 0 0 0.0 0 +chr3 60130478 0 0 0.0 0 +chr3 60190604 0 0 0.0 0 +chr3 60233040 0 0 0.0 0 +chr3 60235855 0 0 0.0 0 +chr3 60560353 0 0 0.0 0 +chr3 60562768 0 0 0.0 0 +chr3 60668913 0 0 0.0 0 +chr3 60812393 0 0 0.0 0 +chr3 60849535 0 0 0.0 0 +chr3 60856204 0 1 0.0135 0 +chr3 61180253 0 0 0.0 0 +chr3 61193142 0 0 0.0 0 +chr3 61277789 0 0 0.0 0 +chr3 61305043 0 0 0.0 0 +chr3 61505432 0 0 0.0 0 +chr3 61725470 0 0 0.0 0 +chr3 61727631 0 0 0.0 0 +chr3 61851325 0 0 0.0 0 +chr3 62066521 1 35 0.4605 1 +chr3 62100561 0 0 0.0 0 +chr3 62124526 0 0 0.0 0 +chr3 62158898 0 1 0.0152 0 +chr3 62336552 0 0 0.0 0 +chr3 62562005 0 0 0.0 0 +chr3 62658109 0 0 0.0 0 +chr3 62778127 0 0 0.0 0 +chr3 62826881 0 0 0.0 0 +chr3 63188066 0 0 0.0 0 +chr3 63202232 0 0 0.0 0 +chr3 63232507 0 0 0.0 0 +chr3 63369032 0 0 0.0 0 +chr3 63646041 0 0 0.0 0 +chr3 63954164 0 0 0.0 0 +chr3 63999863 0 1 0.0145 0 +chr3 64018272 0 0 0.0 0 +chr3 64060521 0 0 0.0 0 +chr3 64153863 0 0 0.0 0 +chr3 64319079 0 0 0.0 0 +chr3 64456157 0 0 0.0 0 +chr3 64575561 0 0 0.0 0 +chr3 64620716 0 0 0.0 0 +chr3 64755252 0 0 0.0 0 +chr3 65049773 0 0 0.0 0 +chr3 65231623 0 0 0.0 0 +chr3 65233689 0 0 0.0 0 +chr3 65290717 0 0 0.0 0 +chr3 65320879 0 0 0.0 0 +chr3 65364696 0 0 0.0 0 +chr3 65479422 0 0 0.0 0 +chr3 65550961 0 0 0.0 0 +chr3 65565507 0 0 0.0 0 +chr3 65589207 0 0 0.0 0 +chr3 65777991 0 0 0.0 0 +chr3 66006870 0 0 0.0 0 +chr3 66115436 0 0 0.0 0 +chr3 66242035 0 0 0.0 0 +chr3 66275249 0 0 0.0 0 +chr3 66279421 0 0 0.0 0 +chr3 66310687 0 0 0.0 0 +chr3 66342190 0 0 0.0 0 +chr3 66372996 0 0 0.0 0 +chr3 66396828 0 0 0.0 0 +chr3 66547271 0 0 0.0 0 +chr3 66656539 0 0 0.0 0 +chr3 66728525 0 0 0.0 0 +chr3 66886085 0 0 0.0 0 +chr3 67031770 0 0 0.0 0 +chr3 67237729 0 0 0.0 0 +chr3 67336263 0 0 0.0 0 +chr3 67531441 0 0 0.0 0 +chr3 67888897 0 0 0.0 0 +chr3 67914128 0 0 0.0 0 +chr3 68013880 0 0 0.0 0 +chr3 68123825 0 0 0.0 0 +chr3 68271899 0 0 0.0 0 +chr3 68368703 0 0 0.0 0 +chr3 68461627 0 0 0.0 0 +chr3 68479686 0 0 0.0 0 +chr3 68516418 0 0 0.0 0 +chr3 68756606 0 0 0.0 0 +chr3 68832494 0 0 0.0 0 +chr3 68832948 0 0 0.0 0 +chr3 68847388 0 0 0.0 0 +chr3 68904786 0 0 0.0 0 +chr3 69097292 0 0 0.0 0 +chr3 69212465 0 0 0.0 0 +chr3 69471405 0 0 0.0 0 +chr3 69496956 0 0 0.0 0 +chr3 69535790 0 0 0.0 0 +chr3 69682028 3 6 0.1463 1 +chr3 69856765 0 0 0.0 0 +chr3 69874609 0 0 0.0 0 +chr3 70001016 0 0 0.0 0 +chr3 70002197 0 0 0.0 0 +chr3 70050845 0 0 0.0 0 +chr3 70232659 0 0 0.0 0 +chr3 70347827 0 0 0.0 0 +chr3 70354954 0 0 0.0 0 +chr3 70449592 0 0 0.0 0 +chr3 70511488 0 0 0.0 0 +chr3 70627508 0 0 0.0 0 +chr3 70884631 0 0 0.0 0 +chr3 70886876 0 0 0.0 0 +chr3 71596745 0 1 0.0132 0 +chr3 71631364 0 0 0.0 0 +chr3 71690920 0 0 0.0 0 +chr3 71853684 0 0 0.0 0 +chr3 71881138 0 0 0.0 0 +chr3 71977638 0 0 0.0 0 +chr3 71985855 1 8 0.1702 1 +chr3 72134547 0 0 0.0 0 +chr3 72182167 0 0 0.0 0 +chr3 72218507 0 0 0.0 0 +chr3 72228238 0 0 0.0 0 +chr3 72233302 0 0 0.0 0 +chr3 72327889 0 0 0.0 0 +chr3 72373598 0 0 0.0 0 +chr3 72398946 0 0 0.0 0 +chr3 72488265 0 0 0.0 0 +chr3 72504929 0 0 0.0 0 +chr3 72718417 0 0 0.0 0 +chr3 72803271 0 0 0.0 0 +chr3 72850859 0 0 0.0 0 +chr3 72939523 0 0 0.0 0 +chr3 72993621 0 0 0.0 0 +chr3 73073522 0 0 0.0 0 +chr3 73087454 0 0 0.0 0 +chr3 73285833 0 0 0.0 0 +chr3 73330619 0 0 0.0 0 +chr3 73422097 0 0 0.0 0 +chr3 73442158 0 0 0.0 0 +chr3 73520772 0 0 0.0 0 +chr3 73647097 0 0 0.0 0 +chr3 73716886 0 0 0.0 0 +chr3 73729407 0 0 0.0 0 +chr3 73737262 0 0 0.0 0 +chr3 73797768 0 1 0.0213 0 +chr3 73804700 0 0 0.0 0 +chr3 74054930 0 0 0.0 0 +chr3 74139813 0 0 0.0 0 +chr3 74213289 0 0 0.0 0 +chr3 74516983 0 0 0.0 0 +chr3 74642477 0 0 0.0 0 +chr3 74746955 0 0 0.0 0 +chr3 74767581 0 0 0.0 0 +chr3 74857259 0 0 0.0 0 +chr3 74936338 0 0 0.0 0 +chr3 75133654 0 0 0.0 0 +chr3 75171060 0 0 0.0 0 +chr3 75271959 0 0 0.0 0 +chr3 75365577 0 0 0.0 0 +chr3 75540219 1 4 0.087 1 +chr3 75672396 0 0 0.0 0 +chr3 75710305 0 0 0.0 0 +chr3 75809577 0 0 0.0 0 +chr3 75850279 0 0 0.0 0 +chr3 75871045 0 0 0.0 0 +chr3 75994549 0 0 0.0 0 +chr3 76073386 0 1 0.0233 0 +chr3 76270197 0 0 0.0 0 +chr3 76451585 0 0 0.0 0 +chr3 76477886 0 0 0.0 0 +chr3 76487727 0 0 0.0 0 +chr3 76578214 0 0 0.0 0 +chr3 77033426 0 0 0.0 0 +chr3 77040545 0 0 0.0 0 +chr3 77193325 0 0 0.0 0 +chr3 77207893 0 0 0.0 0 +chr3 77317550 0 0 0.0 0 +chr3 77441131 0 0 0.0 0 +chr3 77539987 0 0 0.0 0 +chr3 77688879 0 0 0.0 0 +chr3 77704992 0 0 0.0 0 +chr3 78242150 0 0 0.0 0 +chr3 78269480 0 0 0.0 0 +chr3 78401415 0 0 0.0 0 +chr3 78502845 0 0 0.0 0 +chr3 78581720 0 0 0.0 0 +chr3 78592521 0 0 0.0 0 +chr3 78687612 0 0 0.0 0 +chr3 78783877 0 0 0.0 0 +chr3 78957475 0 0 0.0 0 +chr3 79238445 0 0 0.0 0 +chr3 79437431 0 0 0.0 0 +chr3 79542162 0 0 0.0 0 +chr3 79669939 0 0 0.0 0 +chr3 79929764 0 0 0.0 0 +chr3 79947652 0 0 0.0 0 +chr3 79955805 0 0 0.0 0 +chr3 79964730 0 0 0.0 0 +chr3 79978746 0 0 0.0 0 +chr3 80036161 0 0 0.0 0 +chr3 80052146 0 0 0.0 0 +chr3 80755031 0 0 0.0 0 +chr3 80782987 0 0 0.0 0 +chr3 80793451 0 0 0.0 0 +chr3 80837006 0 0 0.0 0 +chr3 80872613 0 0 0.0 0 +chr3 80978026 0 0 0.0 0 +chr3 81007236 0 0 0.0 0 +chr3 81296028 0 0 0.0 0 +chr3 81313875 0 0 0.0 0 +chr3 81364431 0 0 0.0 0 +chr3 81501670 1 15 0.4688 1 +chr3 81511733 0 0 0.0 0 +chr3 81614494 0 0 0.0 0 +chr3 81897418 0 0 0.0 0 +chr3 82122080 0 0 0.0 0 +chr3 82349266 0 0 0.0 0 +chr3 82393042 0 0 0.0 0 +chr3 82490274 0 0 0.0 0 +chr3 82533214 0 0 0.0 0 +chr3 82726439 0 0 0.0 0 +chr3 82738072 0 0 0.0 0 +chr3 82925307 0 0 0.0 0 +chr3 82990126 0 0 0.0 0 +chr3 83017161 0 0 0.0 0 +chr3 83168434 0 0 0.0 0 +chr3 83282804 0 0 0.0 0 +chr3 83368518 0 0 0.0 0 +chr3 83375458 0 0 0.0 0 +chr3 83491666 0 0 0.0 0 +chr3 83896081 0 0 0.0 0 +chr3 84065430 0 0 0.0 0 +chr3 84286025 0 0 0.0 0 +chr3 84487164 0 0 0.0 0 +chr3 84566442 0 0 0.0 0 +chr3 84603266 0 0 0.0 0 +chr3 84823907 0 0 0.0 0 +chr3 84907729 0 0 0.0 0 +chr3 84942975 0 0 0.0 0 +chr3 85364272 0 0 0.0 0 +chr3 86072061 0 0 0.0 0 +chr3 86116009 0 0 0.0 0 +chr3 86243839 0 0 0.0 0 +chr3 86315356 0 0 0.0 0 +chr3 86471004 0 0 0.0 0 +chr3 86520747 0 0 0.0 0 +chr3 86534250 0 0 0.0 0 +chr3 86573636 0 0 0.0 0 +chr3 87061578 0 0 0.0 0 +chr3 87088803 0 0 0.0 0 +chr3 87498200 0 0 0.0 0 +chr3 87614270 0 0 0.0 0 +chr3 87653743 0 0 0.0 0 +chr3 88182796 0 0 0.0 0 +chr3 88274031 0 0 0.0 0 +chr3 88543709 0 0 0.0 0 +chr3 88556110 0 0 0.0 0 +chr3 88761582 0 0 0.0 0 +chr3 88859186 0 0 0.0 0 +chr3 88911624 0 0 0.0 0 +chr3 89166760 0 0 0.0 0 +chr3 89303157 0 0 0.0 0 +chr3 89343093 0 0 0.0 0 +chr3 89443783 0 0 0.0 0 +chr3 89923386 0 0 0.0 0 +chr3 89948686 0 0 0.0 0 +chr3 90007237 0 0 0.0 0 +chr3 90120061 0 0 0.0 0 +chr3 90186798 0 0 0.0 0 +chr3 90428284 0 0 0.0 0 +chr3 90675379 0 0 0.0 0 +chr3 93777412 0 0 0.0 0 +chr3 93782681 0 0 0.0 0 +chr3 93845918 0 0 0.0 0 +chr3 93859516 0 0 0.0 0 +chr3 94274866 0 0 0.0 0 +chr3 94309635 0 0 0.0 0 +chr3 94337942 0 0 0.0 0 +chr3 94371466 0 0 0.0 0 +chr3 94416090 0 0 0.0 0 +chr3 94465860 0 0 0.0 0 +chr3 94631470 0 0 0.0 0 +chr3 94714900 0 0 0.0 0 +chr3 94905578 0 0 0.0 0 +chr3 94937346 0 0 0.0 0 +chr3 95139440 0 0 0.0 0 +chr3 95241294 0 0 0.0 0 +chr3 95411514 0 0 0.0 0 +chr3 95458227 0 0 0.0 0 +chr3 95574447 0 0 0.0 0 +chr3 95588551 0 1 0.0182 0 +chr3 95626778 0 0 0.0 0 +chr3 95724755 0 0 0.0 0 +chr3 95897944 0 0 0.0 0 +chr3 95910935 0 0 0.0 0 +chr3 96060655 0 0 0.0 0 +chr3 96091482 0 0 0.0 0 +chr3 96139960 0 0 0.0 0 +chr3 96217474 0 0 0.0 0 +chr3 96364093 0 0 0.0 0 +chr3 96852250 0 0 0.0 0 +chr3 96931256 0 0 0.0 0 +chr3 97180539 0 0 0.0 0 +chr3 97474839 0 0 0.0 0 +chr3 97482325 0 0 0.0 0 +chr3 97841797 0 0 0.0 0 +chr3 97919194 0 0 0.0 0 +chr3 98031633 0 0 0.0 0 +chr3 98123604 0 0 0.0 0 +chr3 98129937 0 0 0.0 0 +chr3 98180589 0 1 0.0256 0 +chr3 98328223 0 0 0.0 0 +chr3 98401973 0 0 0.0 0 +chr3 98500391 0 0 0.0 0 +chr3 98548372 0 0 0.0 0 +chr3 98556881 0 0 0.0 0 +chr3 98626769 0 0 0.0 0 +chr3 98729772 0 0 0.0 0 +chr3 98885513 0 0 0.0 0 +chr3 98928767 0 0 0.0 0 +chr3 99051892 0 0 0.0 0 +chr3 99064323 0 0 0.0 0 +chr3 99076626 0 0 0.0 0 +chr3 99130512 0 0 0.0 0 +chr3 99159136 0 0 0.0 0 +chr3 99192733 0 0 0.0 0 +chr3 99317180 0 0 0.0 0 +chr3 99364409 0 0 0.0 0 +chr3 99393206 0 0 0.0 0 +chr3 99406208 0 0 0.0 0 +chr3 99435669 0 1 0.0118 0 +chr3 99450906 0 0 0.0 0 +chr3 99507830 0 0 0.0 0 +chr3 99541323 0 0 0.0 0 +chr3 99618114 0 0 0.0 0 +chr3 99711493 0 0 0.0 0 +chr3 99720109 0 0 0.0 0 +chr3 99884078 0 0 0.0 0 +chr3 100027590 0 0 0.0 0 +chr3 100408483 0 0 0.0 0 +chr3 100479862 0 0 0.0 0 +chr3 100721651 0 0 0.0 0 +chr3 100760675 0 1 0.0137 0 +chr3 100790333 0 0 0.0 0 +chr3 100880597 0 0 0.0 0 +chr3 101043176 0 0 0.0 0 +chr3 101091549 0 0 0.0 0 +chr3 101243708 0 0 0.0 0 +chr3 101252190 0 0 0.0 0 +chr3 101526612 0 0 0.0 0 +chr3 101885221 0 0 0.0 0 +chr3 102028129 0 0 0.0 0 +chr3 102048535 0 2 0.0426 0 +chr3 102222961 0 0 0.0 0 +chr3 102233464 0 0 0.0 0 +chr3 102507073 0 0 0.0 0 +chr3 102738671 0 0 0.0 0 +chr3 102810950 0 0 0.0 0 +chr3 103186532 0 0 0.0 0 +chr3 103209502 0 0 0.0 0 +chr3 103326888 0 0 0.0 0 +chr3 103794163 0 0 0.0 0 +chr3 103831733 0 0 0.0 0 +chr3 103863258 0 0 0.0 0 +chr3 103977253 0 0 0.0 0 +chr3 104133731 0 0 0.0 0 +chr3 104286904 0 0 0.0 0 +chr3 104469584 0 0 0.0 0 +chr3 105034138 0 0 0.0 0 +chr3 105069691 0 0 0.0 0 +chr3 105193738 0 0 0.0 0 +chr3 105272802 0 0 0.0 0 +chr3 105304714 0 0 0.0 0 +chr3 105518606 0 0 0.0 0 +chr3 105551514 0 0 0.0 0 +chr3 105603723 0 0 0.0 0 +chr3 105616412 0 0 0.0 0 +chr3 106104590 0 0 0.0 0 +chr3 106149008 0 0 0.0 0 +chr3 106367176 0 0 0.0 0 +chr3 106377332 0 0 0.0 0 +chr3 106515370 0 0 0.0 0 +chr3 106522715 0 0 0.0 0 +chr3 106642176 0 0 0.0 0 +chr3 106791570 0 0 0.0 0 +chr3 106930388 0 0 0.0 0 +chr3 107135648 0 0 0.0 0 +chr3 107292888 0 0 0.0 0 +chr3 107334619 0 0 0.0 0 +chr3 107408289 0 0 0.0 0 +chr3 107747513 0 0 0.0 0 +chr3 107882517 0 0 0.0 0 +chr3 107928021 0 0 0.0 0 +chr3 108083883 1 8 0.1333 1 +chr3 108133682 0 0 0.0 0 +chr3 108290810 0 0 0.0 0 +chr3 108305659 0 0 0.0 0 +chr3 108325351 0 0 0.0 0 +chr3 108510455 0 0 0.0 0 +chr3 108576816 0 0 0.0 0 +chr3 108736369 0 0 0.0 0 +chr3 108769789 0 0 0.0 0 +chr3 108950509 0 0 0.0 0 +chr3 109105044 0 0 0.0 0 +chr3 109146659 0 0 0.0 0 +chr3 109396271 0 0 0.0 0 +chr3 109605408 0 0 0.0 0 +chr3 109614713 0 0 0.0 0 +chr3 109692420 0 0 0.0 0 +chr3 109778395 0 0 0.0 0 +chr3 110036325 0 0 0.0 0 +chr3 110294793 0 0 0.0 0 +chr3 110530800 0 0 0.0 0 +chr3 110671859 0 0 0.0 0 +chr3 110774361 0 0 0.0 0 +chr3 110957633 0 0 0.0 0 +chr3 110966680 0 0 0.0 0 +chr3 110998914 0 0 0.0 0 +chr3 111056950 0 0 0.0 0 +chr3 111095402 0 0 0.0 0 +chr3 111446976 0 0 0.0 0 +chr3 111454509 0 0 0.0 0 +chr3 111550658 0 1 0.0192 0 +chr3 111627162 0 0 0.0 0 +chr3 111627437 0 0 0.0 0 +chr3 111792463 0 0 0.0 0 +chr3 111860289 0 0 0.0 0 +chr3 111867338 0 0 0.0 0 +chr3 112048089 0 0 0.0 0 +chr3 112078337 0 0 0.0 0 +chr3 112238409 0 0 0.0 0 +chr3 112332517 0 1 0.027 0 +chr3 112740123 0 0 0.0 0 +chr3 112750714 0 0 0.0 0 +chr3 112812131 0 0 0.0 0 +chr3 112827820 0 0 0.0 0 +chr3 112849956 0 0 0.0 0 +chr3 113084956 0 0 0.0 0 +chr3 113123540 0 0 0.0 0 +chr3 113385131 0 0 0.0 0 +chr3 113450477 0 0 0.0 0 +chr3 113626148 0 0 0.0 0 +chr3 113628172 0 0 0.0 0 +chr3 113767912 0 0 0.0 0 +chr3 113837051 0 0 0.0 0 +chr3 113837536 0 0 0.0 0 +chr3 114119574 0 0 0.0 0 +chr3 114423914 0 1 0.0208 0 +chr3 114532279 0 0 0.0 0 +chr3 114585658 0 0 0.0 0 +chr3 114697931 0 0 0.0 0 +chr3 114859929 0 0 0.0 0 +chr3 115111848 0 0 0.0 0 +chr3 115118325 0 0 0.0 0 +chr3 115136412 0 0 0.0 0 +chr3 115146803 0 0 0.0 0 +chr3 115208586 0 0 0.0 0 +chr3 115254481 0 0 0.0 0 +chr3 115532457 0 0 0.0 0 +chr3 115532985 0 0 0.0 0 +chr3 115533776 0 0 0.0 0 +chr3 115547437 0 0 0.0 0 +chr3 115666541 0 0 0.0 0 +chr3 115698613 0 0 0.0 0 +chr3 115942187 0 0 0.0 0 +chr3 116054279 0 0 0.0 0 +chr3 116097051 0 0 0.0 0 +chr3 116166432 0 1 0.0263 0 +chr3 116210118 0 0 0.0 0 +chr3 116246677 0 0 0.0 0 +chr3 116428172 0 0 0.0 0 +chr3 116474602 0 0 0.0 0 +chr3 116488147 0 0 0.0 0 +chr3 117013271 0 0 0.0 0 +chr3 117284707 0 0 0.0 0 +chr3 117370657 0 0 0.0 0 +chr3 117655610 0 0 0.0 0 +chr3 117656065 0 0 0.0 0 +chr3 117745909 0 0 0.0 0 +chr3 117797959 0 0 0.0 0 +chr3 117803146 0 0 0.0 0 +chr3 117841248 0 0 0.0 0 +chr3 117851487 0 0 0.0 0 +chr3 117856790 0 0 0.0 0 +chr3 117998270 0 0 0.0 0 +chr3 118094881 0 0 0.0 0 +chr3 118144632 0 0 0.0 0 +chr3 118466668 0 0 0.0 0 +chr3 118662746 0 0 0.0 0 +chr3 118772271 0 0 0.0 0 +chr3 118833976 0 0 0.0 0 +chr3 119017458 0 0 0.0 0 +chr3 119183771 0 0 0.0 0 +chr3 119267466 0 0 0.0 0 +chr3 119280156 0 0 0.0 0 +chr3 119289697 0 0 0.0 0 +chr3 119481246 0 0 0.0 0 +chr3 119572635 0 0 0.0 0 +chr3 119587542 0 0 0.0 0 +chr3 119595537 0 0 0.0 0 +chr3 119620015 0 0 0.0 0 +chr3 119627255 0 0 0.0 0 +chr3 119645488 0 0 0.0 0 +chr3 119667266 0 0 0.0 0 +chr3 119752183 0 0 0.0 0 +chr3 119782658 0 0 0.0 0 +chr3 120031486 0 1 0.0233 0 +chr3 120095929 0 0 0.0 0 +chr3 120280205 0 0 0.0 0 +chr3 120352085 0 0 0.0 0 +chr3 120497670 0 0 0.0 0 +chr3 120505976 0 0 0.0 0 +chr3 120646678 1 8 0.1333 1 +chr3 121045907 0 0 0.0 0 +chr3 121183914 0 0 0.0 0 +chr3 121218522 0 0 0.0 0 +chr3 121241523 0 0 0.0 0 +chr3 121399312 0 0 0.0 0 +chr3 121520671 0 0 0.0 0 +chr3 121982228 0 0 0.0 0 +chr3 122090960 0 0 0.0 0 +chr3 122098534 0 0 0.0 0 +chr3 122280534 0 0 0.0 0 +chr3 122386014 0 0 0.0 0 +chr3 122458826 0 0 0.0 0 +chr3 122506439 0 0 0.0 0 +chr3 122797632 0 0 0.0 0 +chr3 122893638 0 0 0.0 0 +chr3 122912184 0 0 0.0 0 +chr3 122975185 0 0 0.0 0 +chr3 122978688 0 0 0.0 0 +chr3 123053167 0 0 0.0 0 +chr3 123088544 0 0 0.0 0 +chr3 123147374 0 0 0.0 0 +chr3 123242274 0 0 0.0 0 +chr3 123310014 0 0 0.0 0 +chr3 123404686 0 0 0.0 0 +chr3 123437853 0 0 0.0 0 +chr3 123446361 0 0 0.0 0 +chr3 123575889 0 0 0.0 0 +chr3 123759254 0 0 0.0 0 +chr3 123761616 0 0 0.0 0 +chr3 123774310 0 0 0.0 0 +chr3 124010527 0 0 0.0 0 +chr3 124045411 0 0 0.0 0 +chr3 124117641 0 0 0.0 0 +chr3 124144932 0 0 0.0 0 +chr3 124238708 0 0 0.0 0 +chr3 124323716 0 0 0.0 0 +chr3 124335282 0 0 0.0 0 +chr3 124339430 0 0 0.0 0 +chr3 124402095 0 0 0.0 0 +chr3 124633348 0 0 0.0 0 +chr3 124663382 0 0 0.0 0 +chr3 124758441 0 0 0.0 0 +chr3 124796648 0 0 0.0 0 +chr3 124858704 0 0 0.0 0 +chr3 124932665 0 0 0.0 0 +chr3 125015769 0 0 0.0 0 +chr3 125287918 0 0 0.0 0 +chr3 125598172 0 0 0.0 0 +chr3 125831484 0 0 0.0 0 +chr3 125850676 0 0 0.0 0 +chr3 125920679 0 0 0.0 0 +chr3 125933769 0 0 0.0 0 +chr3 126016619 0 0 0.0 0 +chr3 126113335 0 0 0.0 0 +chr3 126396601 0 0 0.0 0 +chr3 126414181 0 0 0.0 0 +chr3 126473979 0 0 0.0 0 +chr3 126495981 0 0 0.0 0 +chr3 126499065 0 0 0.0 0 +chr3 126573146 0 0 0.0 0 +chr3 126611686 0 0 0.0 0 +chr3 126842392 0 0 0.0 0 +chr3 126891521 0 1 0.0139 0 +chr3 127074991 0 0 0.0 0 +chr3 127127001 0 0 0.0 0 +chr3 127208887 0 0 0.0 0 +chr3 127289778 0 0 0.0 0 +chr3 127347565 0 0 0.0 0 +chr3 127387747 0 0 0.0 0 +chr3 127397165 0 0 0.0 0 +chr3 127418042 0 0 0.0 0 +chr3 127432064 0 0 0.0 0 +chr3 127606163 0 0 0.0 0 +chr3 127676350 0 0 0.0 0 +chr3 127687050 0 0 0.0 0 +chr3 127771846 0 0 0.0 0 +chr3 127776147 0 0 0.0 0 +chr3 127847970 0 0 0.0 0 +chr3 127861144 0 0 0.0 0 +chr3 128004546 0 0 0.0 0 +chr3 128198573 0 0 0.0 0 +chr3 128260798 0 0 0.0 0 +chr3 128261971 0 0 0.0 0 +chr3 128272911 0 0 0.0 0 +chr3 128290281 0 0 0.0 0 +chr3 128365383 0 0 0.0 0 +chr3 128381059 0 0 0.0 0 +chr3 128381739 0 0 0.0 0 +chr3 128414600 0 0 0.0 0 +chr3 128565713 0 0 0.0 0 +chr3 128584083 0 0 0.0 0 +chr3 128675980 0 0 0.0 0 +chr3 128687362 0 0 0.0 0 +chr3 128858241 0 0 0.0 0 +chr3 129237554 0 0 0.0 0 +chr3 129271615 0 0 0.0 0 +chr3 129296999 0 0 0.0 0 +chr3 129315126 0 0 0.0 0 +chr3 129379812 0 0 0.0 0 +chr3 129632178 0 0 0.0 0 +chr3 129674264 0 0 0.0 0 +chr3 129822163 0 0 0.0 0 +chr3 129854149 0 0 0.0 0 +chr3 129893330 0 0 0.0 0 +chr3 129901804 0 0 0.0 0 +chr3 130168236 0 0 0.0 0 +chr3 130298009 0 0 0.0 0 +chr3 130393130 0 0 0.0 0 +chr3 130547078 0 0 0.0 0 +chr3 130670669 0 0 0.0 0 +chr3 130942473 0 0 0.0 0 +chr3 130986313 0 0 0.0 0 +chr3 131011156 0 1 0.0417 0 +chr3 131091206 0 0 0.0 0 +chr3 131167690 0 0 0.0 0 +chr3 131364050 0 0 0.0 0 +chr3 131405662 0 0 0.0 0 +chr3 131469205 0 0 0.0 0 +chr3 131662237 0 0 0.0 0 +chr3 131872046 0 0 0.0 0 +chr3 132059658 0 0 0.0 0 +chr3 132190060 0 0 0.0 0 +chr3 132379064 0 0 0.0 0 +chr3 132395127 1 5 0.0781 1 +chr3 132474952 0 0 0.0 0 +chr3 132490693 0 0 0.0 0 +chr3 132541921 0 0 0.0 0 +chr3 132844006 0 0 0.0 0 +chr3 132855739 0 0 0.0 0 +chr3 132873466 0 0 0.0 0 +chr3 132916407 0 0 0.0 0 +chr3 133150102 0 0 0.0 0 +chr3 133165376 0 0 0.0 0 +chr3 133386509 0 0 0.0 0 +chr3 133394895 0 0 0.0 0 +chr3 133443719 0 1 0.027 0 +chr3 133446205 0 0 0.0 0 +chr3 133513697 0 0 0.0 0 +chr3 133550391 0 0 0.0 0 +chr3 133682081 0 0 0.0 0 +chr3 133693279 0 0 0.0 0 +chr3 133713399 0 0 0.0 0 +chr3 133748610 0 0 0.0 0 +chr3 133749822 0 0 0.0 0 +chr3 133895967 0 0 0.0 0 +chr3 133912482 0 0 0.0 0 +chr3 133974695 0 0 0.0 0 +chr3 133980508 0 0 0.0 0 +chr3 134056646 0 0 0.0 0 +chr3 134170767 0 0 0.0 0 +chr3 134257087 0 0 0.0 0 +chr3 134284182 0 0 0.0 0 +chr3 134406414 0 0 0.0 0 +chr3 134528428 0 0 0.0 0 +chr3 134596956 0 0 0.0 0 +chr3 134913535 0 0 0.0 0 +chr3 134992423 0 0 0.0 0 +chr3 134999057 0 0 0.0 0 +chr3 135036027 0 0 0.0 0 +chr3 135044954 0 0 0.0 0 +chr3 135086532 0 0 0.0 0 +chr3 135126846 0 0 0.0 0 +chr3 135150211 0 0 0.0 0 +chr3 135220721 0 0 0.0 0 +chr3 135231066 0 0 0.0 0 +chr3 135348746 0 0 0.0 0 +chr3 135374180 0 0 0.0 0 +chr3 135625889 0 0 0.0 0 +chr3 135961558 0 0 0.0 0 +chr3 136062384 0 0 0.0 0 +chr3 136211582 0 0 0.0 0 +chr3 136293136 0 0 0.0 0 +chr3 136420662 0 0 0.0 0 +chr3 136502897 0 0 0.0 0 +chr3 136640717 0 0 0.0 0 +chr3 136656492 0 0 0.0 0 +chr3 136854832 0 0 0.0 0 +chr3 137021505 0 1 0.0182 0 +chr3 137048918 0 0 0.0 0 +chr3 137154508 0 0 0.0 0 +chr3 137257994 0 0 0.0 0 +chr3 137409776 0 0 0.0 0 +chr3 137425562 0 0 0.0 0 +chr3 137615936 0 0 0.0 0 +chr3 137813230 0 0 0.0 0 +chr3 137831258 0 0 0.0 0 +chr3 138010464 0 0 0.0 0 +chr3 138259903 0 0 0.0 0 +chr3 138299855 0 0 0.0 0 +chr3 138343235 0 0 0.0 0 +chr3 138369593 0 0 0.0 0 +chr3 138435745 0 0 0.0 0 +chr3 138443418 0 0 0.0 0 +chr3 138542807 0 0 0.0 0 +chr3 138742602 0 0 0.0 0 +chr3 138851689 0 0 0.0 0 +chr3 138867297 0 1 0.0132 0 +chr3 138965813 0 0 0.0 0 +chr3 139111294 0 1 0.0167 0 +chr3 139225934 0 0 0.0 0 +chr3 139272249 0 0 0.0 0 +chr3 139314712 0 0 0.0 0 +chr3 139426075 0 0 0.0 0 +chr3 139455856 0 0 0.0 0 +chr3 139633811 0 0 0.0 0 +chr3 139650730 0 0 0.0 0 +chr3 139753735 0 0 0.0 0 +chr3 139818522 0 0 0.0 0 +chr3 139873421 0 0 0.0 0 +chr3 139910876 0 0 0.0 0 +chr3 140031362 0 0 0.0 0 +chr3 140067705 0 0 0.0 0 +chr3 140080117 0 0 0.0 0 +chr3 140100726 0 0 0.0 0 +chr3 140109967 0 0 0.0 0 +chr3 140119895 0 0 0.0 0 +chr3 140131676 0 0 0.0 0 +chr3 140442014 0 0 0.0 0 +chr3 140591690 0 0 0.0 0 +chr3 140637051 0 0 0.0 0 +chr3 140702002 0 0 0.0 0 +chr3 140754976 0 0 0.0 0 +chr3 140773077 0 0 0.0 0 +chr3 140789278 0 0 0.0 0 +chr3 140845524 0 0 0.0 0 +chr3 140900322 0 0 0.0 0 +chr3 141122228 0 0 0.0 0 +chr3 141151495 0 0 0.0 0 +chr3 141178590 0 0 0.0 0 +chr3 141253735 0 0 0.0 0 +chr3 141320218 0 0 0.0 0 +chr3 141377090 0 0 0.0 0 +chr3 141379243 0 0 0.0 0 +chr3 141381673 0 0 0.0 0 +chr3 141549361 0 0 0.0 0 +chr3 141551595 0 0 0.0 0 +chr3 141650919 0 0 0.0 0 +chr3 141763559 0 0 0.0 0 +chr3 141838533 0 0 0.0 0 +chr3 141915206 0 0 0.0 0 +chr3 142073325 0 0 0.0 0 +chr3 142086994 0 0 0.0 0 +chr3 142267446 0 0 0.0 0 +chr3 142322163 0 0 0.0 0 +chr3 142574221 0 0 0.0 0 +chr3 142901650 0 0 0.0 0 +chr3 143323832 0 0 0.0 0 +chr3 143376106 0 1 0.0182 0 +chr3 143558276 0 0 0.0 0 +chr3 143612196 0 0 0.0 0 +chr3 143688212 0 0 0.0 0 +chr3 143696863 0 0 0.0 0 +chr3 143712657 0 0 0.0 0 +chr3 143751079 0 0 0.0 0 +chr3 143928429 0 0 0.0 0 +chr3 144046531 0 0 0.0 0 +chr3 144090961 0 0 0.0 0 +chr3 144099685 0 0 0.0 0 +chr3 144159044 0 0 0.0 0 +chr3 144220523 0 0 0.0 0 +chr3 144435425 0 0 0.0 0 +chr3 144511364 0 0 0.0 0 +chr3 144806875 0 0 0.0 0 +chr3 145333180 0 0 0.0 0 +chr3 145403300 0 0 0.0 0 +chr3 145405237 0 0 0.0 0 +chr3 145515970 0 0 0.0 0 +chr3 145574372 0 0 0.0 0 +chr3 145578870 0 0 0.0 0 +chr3 145760376 0 0 0.0 0 +chr3 145789196 0 0 0.0 0 +chr3 145966493 0 0 0.0 0 +chr3 145999799 0 0 0.0 0 +chr3 146004902 0 0 0.0 0 +chr3 146005132 0 0 0.0 0 +chr3 146013548 0 0 0.0 0 +chr3 146300709 0 0 0.0 0 +chr3 146403987 0 0 0.0 0 +chr3 146540132 0 0 0.0 0 +chr3 146582594 0 0 0.0 0 +chr3 146755847 0 0 0.0 0 +chr3 146759889 0 0 0.0 0 +chr3 147215361 0 0 0.0 0 +chr3 147369092 0 0 0.0 0 +chr3 147390085 0 0 0.0 0 +chr3 147467038 0 0 0.0 0 +chr3 147678210 0 0 0.0 0 +chr3 147872753 0 0 0.0 0 +chr3 147987886 0 0 0.0 0 +chr3 148242761 0 1 0.027 0 +chr3 148557310 0 0 0.0 0 +chr3 148642823 0 0 0.0 0 +chr3 148708053 0 0 0.0 0 +chr3 148785923 0 0 0.0 0 +chr3 148790558 0 0 0.0 0 +chr3 148842985 0 0 0.0 0 +chr3 148854222 0 0 0.0 0 +chr3 149023876 1 16 0.3902 1 +chr3 149052642 0 1 0.0204 0 +chr3 149108626 0 0 0.0 0 +chr3 149508074 0 0 0.0 0 +chr3 149853965 0 0 0.0 0 +chr3 150128777 0 0 0.0 0 +chr3 150193124 1 11 0.5 1 +chr3 150209234 0 0 0.0 0 +chr3 150300286 0 0 0.0 0 +chr3 150325933 0 0 0.0 0 +chr3 150372520 0 0 0.0 0 +chr3 150375259 0 0 0.0 0 +chr3 150455170 0 0 0.0 0 +chr3 150536979 0 0 0.0 0 +chr3 150746453 0 0 0.0 0 +chr3 150779582 0 0 0.0 0 +chr3 150842510 0 0 0.0 0 +chr3 150886694 0 1 0.0233 0 +chr3 150917030 0 0 0.0 0 +chr3 150970742 0 0 0.0 0 +chr3 151020114 0 0 0.0 0 +chr3 151089900 0 0 0.0 0 +chr3 151223240 1 22 0.88 1 +chr3 151633833 0 0 0.0 0 +chr3 151638983 0 0 0.0 0 +chr3 151677839 0 0 0.0 0 +chr3 151701843 0 0 0.0 0 +chr3 152004468 0 0 0.0 0 +chr3 152177673 0 0 0.0 0 +chr3 152537472 0 0 0.0 0 +chr3 152752430 0 0 0.0 0 +chr3 152855863 1 27 0.5 1 +chr3 152930119 0 0 0.0 0 +chr3 153015891 0 0 0.0 0 +chr3 153019358 0 0 0.0 0 +chr3 153025465 0 0 0.0 0 +chr3 153278438 0 0 0.0 0 +chr3 153376433 0 0 0.0 0 +chr3 153419804 0 0 0.0 0 +chr3 153431315 0 0 0.0 0 +chr3 153795734 0 0 0.0 0 +chr3 153941270 0 0 0.0 0 +chr3 154011498 0 0 0.0 0 +chr3 154042525 0 0 0.0 0 +chr3 154089887 0 0 0.0 0 +chr3 154137069 0 0 0.0 0 +chr3 154137698 0 0 0.0 0 +chr3 154167750 0 0 0.0 0 +chr3 154374581 0 0 0.0 0 +chr3 154616693 0 0 0.0 0 +chr3 155165654 0 0 0.0 0 +chr3 155194162 0 0 0.0 0 +chr3 155201346 0 0 0.0 0 +chr3 155410721 0 0 0.0 0 +chr3 155477366 0 0 0.0 0 +chr3 155483390 0 0 0.0 0 +chr3 155710037 0 0 0.0 0 +chr3 155798681 0 0 0.0 0 +chr3 155968338 0 0 0.0 0 +chr3 155976764 0 0 0.0 0 +chr3 156003398 0 0 0.0 0 +chr3 156046032 0 0 0.0 0 +chr3 156052345 0 0 0.0 0 +chr3 156058278 0 0 0.0 0 +chr3 156183527 0 0 0.0 0 +chr3 156200681 0 0 0.0 0 +chr3 156413128 0 0 0.0 0 +chr3 156428351 0 0 0.0 0 +chr3 156517702 0 0 0.0 0 +chr3 156534992 1 6 0.1818 1 +chr3 156672076 0 0 0.0 0 +chr3 156829611 0 0 0.0 0 +chr3 157067652 0 0 0.0 0 +chr3 157073117 0 0 0.0 0 +chr3 157082059 0 0 0.0 0 +chr3 157282836 0 0 0.0 0 +chr3 157468981 0 0 0.0 0 +chr3 157678073 0 0 0.0 0 +chr3 157783041 0 0 0.0 0 +chr3 158016766 0 0 0.0 0 +chr3 158138259 0 0 0.0 0 +chr3 158217827 0 0 0.0 0 +chr3 158582345 0 0 0.0 0 +chr3 158670443 0 0 0.0 0 +chr3 158706451 0 0 0.0 0 +chr3 158740841 0 0 0.0 0 +chr3 158847319 0 0 0.0 0 +chr3 158998538 0 0 0.0 0 +chr3 159062717 0 0 0.0 0 +chr3 159166786 0 0 0.0 0 +chr3 159187052 0 0 0.0 0 +chr3 159268903 0 0 0.0 0 +chr3 159715094 0 0 0.0 0 +chr3 159749694 0 0 0.0 0 +chr3 159915199 0 0 0.0 0 +chr3 160438373 0 0 0.0 0 +chr3 160492965 0 0 0.0 0 +chr3 160666094 0 0 0.0 0 +chr3 160756692 0 0 0.0 0 +chr3 160966123 0 0 0.0 0 +chr3 161218628 0 0 0.0 0 +chr3 161331210 0 1 0.0149 0 +chr3 161419656 0 0 0.0 0 +chr3 161543791 0 0 0.0 0 +chr3 161576045 0 0 0.0 0 +chr3 161623428 0 0 0.0 0 +chr3 161753336 0 0 0.0 0 +chr3 161846815 0 1 0.0133 0 +chr3 162190954 0 0 0.0 0 +chr3 162244113 0 0 0.0 0 +chr3 162309994 0 0 0.0 0 +chr3 162579436 0 0 0.0 0 +chr3 162688544 0 1 0.0112 0 +chr3 162803567 0 0 0.0 0 +chr3 162842097 0 0 0.0 0 +chr3 163018767 0 0 0.0 0 +chr3 163052480 0 0 0.0 0 +chr3 163150803 0 0 0.0 0 +chr3 163453570 0 0 0.0 0 +chr3 163619483 0 0 0.0 0 +chr3 164008264 0 0 0.0 0 +chr3 164109708 0 0 0.0 0 +chr3 164702184 0 0 0.0 0 +chr3 164748987 0 0 0.0 0 +chr3 164927812 0 0 0.0 0 +chr3 165023611 0 0 0.0 0 +chr3 165254436 0 0 0.0 0 +chr3 165311628 0 0 0.0 0 +chr3 165546818 0 0 0.0 0 +chr3 165924350 0 1 0.0227 0 +chr3 165994836 0 0 0.0 0 +chr3 166089761 0 0 0.0 0 +chr3 166102241 0 1 0.0161 0 +chr3 166197267 0 0 0.0 0 +chr3 166329627 0 0 0.0 0 +chr3 166350958 0 0 0.0 0 +chr3 166364416 0 0 0.0 0 +chr3 166446303 0 0 0.0 0 +chr3 166489624 0 0 0.0 0 +chr3 166495340 0 0 0.0 0 +chr3 166614074 0 0 0.0 0 +chr3 166814400 0 0 0.0 0 +chr3 167085215 0 0 0.0 0 +chr3 167183366 0 0 0.0 0 +chr3 167267596 0 0 0.0 0 +chr3 167617284 0 0 0.0 0 +chr3 167697705 0 0 0.0 0 +chr3 167727701 0 0 0.0 0 +chr3 167728509 0 0 0.0 0 +chr3 167758489 0 0 0.0 0 +chr3 167912715 1 15 0.4545 1 +chr3 168042879 0 0 0.0 0 +chr3 168093768 0 0 0.0 0 +chr3 168163352 0 0 0.0 0 +chr3 168182166 0 0 0.0 0 +chr3 168240153 0 0 0.0 0 +chr3 168259385 0 0 0.0 0 +chr3 168448009 0 0 0.0 0 +chr3 168515683 0 0 0.0 0 +chr3 168697937 0 0 0.0 0 +chr3 168716210 0 0 0.0 0 +chr3 168724340 0 0 0.0 0 +chr3 168923994 0 0 0.0 0 +chr3 169158908 0 0 0.0 0 +chr3 169200822 0 0 0.0 0 +chr3 169277587 0 0 0.0 0 +chr3 169552713 0 0 0.0 0 +chr3 169555759 0 0 0.0 0 +chr3 169879533 0 0 0.0 0 +chr3 170254022 0 0 0.0 0 +chr3 170324707 0 0 0.0 0 +chr3 170431988 0 0 0.0 0 +chr3 170489158 0 0 0.0 0 +chr3 170632136 0 0 0.0 0 +chr3 170695814 0 0 0.0 0 +chr3 170801873 0 0 0.0 0 +chr3 170925101 0 0 0.0 0 +chr3 171105544 0 0 0.0 0 +chr3 171326072 0 0 0.0 0 +chr3 171333932 0 0 0.0 0 +chr3 171361390 0 0 0.0 0 +chr3 171460897 0 0 0.0 0 +chr3 171559905 0 0 0.0 0 +chr3 171772558 0 0 0.0 0 +chr3 171819656 0 0 0.0 0 +chr3 171843007 0 0 0.0 0 +chr3 171871394 0 0 0.0 0 +chr3 172536185 0 0 0.0 0 +chr3 172548348 0 0 0.0 0 +chr3 172551191 0 0 0.0 0 +chr3 172658609 0 0 0.0 0 +chr3 172721109 0 0 0.0 0 +chr3 172900147 0 0 0.0 0 +chr3 172943364 0 0 0.0 0 +chr3 173026885 0 1 0.013 0 +chr3 173031065 0 0 0.0 0 +chr3 173223839 0 0 0.0 0 +chr3 173275577 0 0 0.0 0 +chr3 173359963 0 0 0.0 0 +chr3 173375583 0 0 0.0 0 +chr3 173397199 0 0 0.0 0 +chr3 173541295 0 0 0.0 0 +chr3 173676908 0 0 0.0 0 +chr3 173693850 0 0 0.0 0 +chr3 173875271 0 0 0.0 0 +chr3 174002773 0 1 0.0159 0 +chr3 174234714 0 0 0.0 0 +chr3 174244940 0 0 0.0 0 +chr3 174281939 0 0 0.0 0 +chr3 174300114 0 0 0.0 0 +chr3 174360298 0 0 0.0 0 +chr3 174369842 0 0 0.0 0 +chr3 174569561 0 0 0.0 0 +chr3 174736337 0 0 0.0 0 +chr3 174788660 0 0 0.0 0 +chr3 175142067 0 0 0.0 0 +chr3 175343521 0 0 0.0 0 +chr3 175345446 0 0 0.0 0 +chr3 175530140 0 0 0.0 0 +chr3 176168248 0 0 0.0 0 +chr3 176433927 0 0 0.0 0 +chr3 176507959 0 0 0.0 0 +chr3 176557824 0 0 0.0 0 +chr3 176571710 0 0 0.0 0 +chr3 176594074 0 0 0.0 0 +chr3 176923010 0 0 0.0 0 +chr3 177169431 0 0 0.0 0 +chr3 177170933 0 0 0.0 0 +chr3 177175984 0 0 0.0 0 +chr3 177203888 0 0 0.0 0 +chr3 177227519 0 0 0.0 0 +chr3 177309979 0 0 0.0 0 +chr3 177430381 0 0 0.0 0 +chr3 177480186 0 0 0.0 0 +chr3 177530823 0 0 0.0 0 +chr3 177534727 0 0 0.0 0 +chr3 177604998 0 0 0.0 0 +chr3 177866000 0 0 0.0 0 +chr3 177908763 0 0 0.0 0 +chr3 177994137 0 0 0.0 0 +chr3 178022232 0 0 0.0 0 +chr3 178343015 0 0 0.0 0 +chr3 178411979 0 0 0.0 0 +chr3 178509574 0 0 0.0 0 +chr3 178823690 0 0 0.0 0 +chr3 179263442 0 0 0.0 0 +chr3 179508360 0 0 0.0 0 +chr3 179604917 0 0 0.0 0 +chr3 179692451 0 0 0.0 0 +chr3 179779421 0 0 0.0 0 +chr3 179975748 0 0 0.0 0 +chr3 180102528 0 0 0.0 0 +chr3 180214789 0 0 0.0 0 +chr3 180365566 0 0 0.0 0 +chr3 180626302 0 0 0.0 0 +chr3 180947986 0 0 0.0 0 +chr3 181154654 0 0 0.0 0 +chr3 181162915 0 0 0.0 0 +chr3 181388098 0 0 0.0 0 +chr3 181593021 0 0 0.0 0 +chr3 181640728 0 0 0.0 0 +chr3 181714019 0 0 0.0 0 +chr3 181802229 0 0 0.0 0 +chr3 181942794 0 0 0.0 0 +chr3 181951835 0 0 0.0 0 +chr3 182134306 0 0 0.0 0 +chr3 182198361 0 0 0.0 0 +chr3 182385212 0 0 0.0 0 +chr3 182403364 0 0 0.0 0 +chr3 182785207 0 0 0.0 0 +chr3 182842594 0 0 0.0 0 +chr3 183000802 0 0 0.0 0 +chr3 183167676 0 0 0.0 0 +chr3 183225766 0 0 0.0 0 +chr3 183282223 0 0 0.0 0 +chr3 183306688 0 0 0.0 0 +chr3 183386365 0 0 0.0 0 +chr3 183403864 0 0 0.0 0 +chr3 183497048 0 0 0.0 0 +chr3 183567666 0 0 0.0 0 +chr3 183577999 0 0 0.0 0 +chr3 183699743 0 0 0.0 0 +chr3 183771600 0 0 0.0 0 +chr3 183806744 0 0 0.0 0 +chr3 183959621 0 0 0.0 0 +chr3 184291115 0 0 0.0 0 +chr3 184299883 0 0 0.0 0 +chr3 184357711 0 0 0.0 0 +chr3 184455763 0 0 0.0 0 +chr3 184499204 0 0 0.0 0 +chr3 184500985 0 0 0.0 0 +chr3 184638713 0 0 0.0 0 +chr3 184694128 0 0 0.0 0 +chr3 184765017 0 0 0.0 0 +chr3 184783614 0 0 0.0 0 +chr3 185068906 0 0 0.0 0 +chr3 185072729 0 0 0.0 0 +chr3 185520085 0 0 0.0 0 +chr3 186073530 0 0 0.0 0 +chr3 186243625 0 1 0.0143 0 +chr3 186392461 1 31 0.4429 1 +chr3 186405555 0 0 0.0 0 +chr3 186722491 0 0 0.0 0 +chr3 186851992 0 0 0.0 0 +chr3 186897254 0 0 0.0 0 +chr3 186909407 0 0 0.0 0 +chr3 186936365 0 0 0.0 0 +chr3 187023045 0 0 0.0 0 +chr3 187193564 0 0 0.0 0 +chr3 187228214 0 0 0.0 0 +chr3 187516217 0 0 0.0 0 +chr3 187534907 0 0 0.0 0 +chr3 187678172 0 0 0.0 0 +chr3 187924386 0 0 0.0 0 +chr3 187978626 0 0 0.0 0 +chr3 188127064 0 0 0.0 0 +chr3 188148915 0 0 0.0 0 +chr3 188289799 0 0 0.0 0 +chr3 188427782 0 0 0.0 0 +chr3 188429894 0 0 0.0 0 +chr3 188539965 0 0 0.0 0 +chr3 188551773 0 0 0.0 0 +chr3 188600728 0 0 0.0 0 +chr3 188623830 0 0 0.0 0 +chr3 188758422 0 0 0.0 0 +chr3 189083456 0 0 0.0 0 +chr3 189286513 0 0 0.0 0 +chr3 189293296 0 0 0.0 0 +chr3 189309745 0 0 0.0 0 +chr3 189330498 0 0 0.0 0 +chr3 189337791 0 0 0.0 0 +chr3 189765694 0 0 0.0 0 +chr3 189768955 0 2 0.0526 0 +chr3 189823451 0 0 0.0 0 +chr3 189874160 0 0 0.0 0 +chr3 189887650 0 0 0.0 0 +chr3 189979941 0 0 0.0 0 +chr3 190009824 0 0 0.0 0 +chr3 190192465 0 0 0.0 0 +chr3 190223683 0 0 0.0 0 +chr3 190572739 0 0 0.0 0 +chr3 190628209 0 0 0.0 0 +chr3 190733349 0 0 0.0 0 +chr3 190778352 0 0 0.0 0 +chr3 190934330 0 0 0.0 0 +chr3 190971826 0 0 0.0 0 +chr3 191151655 0 0 0.0 0 +chr3 191220777 0 0 0.0 0 +chr3 191272788 0 0 0.0 0 +chr3 191355879 0 0 0.0 0 +chr3 191424740 0 0 0.0 0 +chr3 191599308 0 0 0.0 0 +chr3 191737836 0 0 0.0 0 +chr3 191919147 0 0 0.0 0 +chr3 191929403 0 0 0.0 0 +chr3 191988013 0 0 0.0 0 +chr3 192123062 0 0 0.0 0 +chr3 192407995 0 0 0.0 0 +chr3 192420125 0 0 0.0 0 +chr3 192493491 0 0 0.0 0 +chr3 192501900 0 0 0.0 0 +chr3 192572649 0 0 0.0 0 +chr3 192699156 0 0 0.0 0 +chr3 192788552 1 77 0.8953 1 +chr3 192821871 0 0 0.0 0 +chr3 192916319 0 0 0.0 0 +chr3 193167882 0 0 0.0 0 +chr3 193266671 0 0 0.0 0 +chr3 193368760 0 0 0.0 0 +chr3 193451435 0 0 0.0 0 +chr3 193483558 0 0 0.0 0 +chr3 193518320 0 0 0.0 0 +chr3 193610319 0 0 0.0 0 +chr3 193836589 0 0 0.0 0 +chr3 193854100 0 0 0.0 0 +chr3 194068566 0 0 0.0 0 +chr3 194076068 0 0 0.0 0 +chr3 194079764 0 0 0.0 0 +chr3 194115175 0 0 0.0 0 +chr3 194190675 0 0 0.0 0 +chr3 194269101 0 0 0.0 0 +chr3 194330225 0 0 0.0 0 +chr3 194384229 0 0 0.0 0 +chr3 194547452 0 0 0.0 0 +chr3 194594012 0 0 0.0 0 +chr3 194609892 0 0 0.0 0 +chr3 194660323 0 0 0.0 0 +chr3 194797253 0 0 0.0 0 +chr3 194863201 0 0 0.0 0 +chr3 195005869 0 0 0.0 0 +chr3 195077617 0 0 0.0 0 +chr3 195139812 0 0 0.0 0 +chr3 195209938 0 0 0.0 0 +chr3 195265776 0 0 0.0 0 +chr3 195402768 0 0 0.0 0 +chr3 195534038 0 0 0.0 0 +chr3 195556578 0 0 0.0 0 +chr3 195685060 0 0 0.0 0 +chr3 195705699 0 1 0.0095 0 +chr3 195802282 0 0 0.0 0 +chr3 195880185 0 0 0.0 0 +chr3 195917171 0 1 0.0323 0 +chr3 195964180 0 0 0.0 0 +chr3 196104261 0 0 0.0 0 +chr3 196171784 0 0 0.0 0 +chr3 196201809 0 0 0.0 0 +chr3 196221979 0 1 0.0135 0 +chr3 196344520 0 0 0.0 0 +chr3 196344665 0 0 0.0 0 +chr3 196362398 0 0 0.0 0 +chr3 196584794 0 0 0.0 0 +chr3 196627262 0 0 0.0 0 +chr3 196649117 0 0 0.0 0 +chr3 196742844 0 0 0.0 0 +chr3 196879133 0 0 0.0 0 +chr3 196895086 0 0 0.0 0 +chr3 196959284 0 0 0.0 0 +chr3 197095886 0 0 0.0 0 +chr3 197117747 0 0 0.0 0 +chr3 197446835 0 0 0.0 0 +chr3 197464545 0 0 0.0 0 +chr3 197725118 0 0 0.0 0 +chr3 197739623 0 0 0.0 0 +chr3 197804873 1 5 0.0694 1 +chr3 197810779 0 0 0.0 0 +chr3 197878614 0 0 0.0 0 +chr3 197879570 0 0 0.0 0 +chr3 198135341 0 0 0.0 0 +chr3_GL383526v1_alt 44468 0 0 0.0 0 +chr3_GL383526v1_alt 49618 0 0 0.0 0 +chr3_GL383526v1_alt 123015 0 0 0.0 0 +chr3_KI270777v1_alt 117465 0 0 0.0 0 +chr3_KI270777v1_alt 148151 0 0 0.0 0 +chr3_KI270778v1_alt 50163 0 0 0.0 0 +chr3_KI270778v1_alt 68497 0 0 0.0 0 +chr3_KI270778v1_alt 150382 0 0 0.0 0 +chr3_KI270779v1_alt 55557 0 0 0.0 0 +chr3_KI270780v1_alt 190982 0 0 0.0 0 +chr3_KI270781v1_alt 34135 0 0 0.0 0 +chr3_KI270781v1_alt 77577 0 0 0.0 0 +chr3_KI270782v1_alt 94329 0 0 0.0 0 +chr3_KI270783v1_alt 17567 0 0 0.0 0 +chr3_KI270784v1_alt 100219 0 0 0.0 0 +chr3_KI270895v1_alt 107340 0 0 0.0 0 +chr3_KI270924v1_alt 110984 0 0 0.0 0 +chr3_KI270934v1_alt 107902 0 0 0.0 0 +chr3_KI270935v1_alt 55557 0 0 0.0 0 +chr3_KI270936v1_alt 108614 0 0 0.0 0 +chr3_KI270937v1_alt 110051 0 0 0.0 0 +chr4 139662 0 0 0.0 0 +chr4 271661 0 0 0.0 0 +chr4 336585 0 0 0.0 0 +chr4 538323 0 0 0.0 0 +chr4 580060 0 0 0.0 0 +chr4 593062 0 0 0.0 0 +chr4 626858 0 0 0.0 0 +chr4 703522 0 0 0.0 0 +chr4 755272 0 0 0.0 0 +chr4 837903 0 0 0.0 0 +chr4 845050 0 0 0.0 0 +chr4 895567 0 0 0.0 0 +chr4 951840 0 0 0.0 0 +chr4 1179589 0 0 0.0 0 +chr4 1200902 0 0 0.0 0 +chr4 1206089 0 0 0.0 0 +chr4 1309562 0 0 0.0 0 +chr4 1375077 0 0 0.0 0 +chr4 1396267 0 0 0.0 0 +chr4 1450530 0 0 0.0 0 +chr4 1460247 0 0 0.0 0 +chr4 1531655 0 0 0.0 0 +chr4 1556821 0 0 0.0 0 +chr4 1569051 0 0 0.0 0 +chr4 1595822 0 0 0.0 0 +chr4 1610067 0 0 0.0 0 +chr4 1764083 0 0 0.0 0 +chr4 1909450 0 0 0.0 0 +chr4 1929994 0 0 0.0 0 +chr4 2005255 0 0 0.0 0 +chr4 2035454 0 0 0.0 0 +chr4 2069624 0 0 0.0 0 +chr4 2097308 0 0 0.0 0 +chr4 2144961 0 0 0.0 0 +chr4 2374503 0 0 0.0 0 +chr4 2592443 0 0 0.0 0 +chr4 2599601 0 0 0.0 0 +chr4 2740453 0 0 0.0 0 +chr4 2754854 0 0 0.0 0 +chr4 2923008 0 0 0.0 0 +chr4 2929454 0 0 0.0 0 +chr4 2953710 0 0 0.0 0 +chr4 3056934 0 0 0.0 0 +chr4 3111062 0 0 0.0 0 +chr4 3174572 0 0 0.0 0 +chr4 3232561 0 0 0.0 0 +chr4 3254535 0 0 0.0 0 +chr4 3282714 0 0 0.0 0 +chr4 3284096 0 0 0.0 0 +chr4 3424439 0 0 0.0 0 +chr4 3438060 0 0 0.0 0 +chr4 3445290 0 0 0.0 0 +chr4 3456836 0 0 0.0 0 +chr4 3541064 0 0 0.0 0 +chr4 3574038 0 0 0.0 0 +chr4 3664167 0 2 0.04 0 +chr4 3723150 0 0 0.0 0 +chr4 3785410 0 0 0.0 0 +chr4 3866521 0 0 0.0 0 +chr4 3936227 0 0 0.0 0 +chr4 4031196 0 0 0.0 0 +chr4 4045037 0 0 0.0 0 +chr4 4083739 0 0 0.0 0 +chr4 4183998 0 0 0.0 0 +chr4 4190144 0 0 0.0 0 +chr4 4240099 0 0 0.0 0 +chr4 4281670 0 0 0.0 0 +chr4 4400989 0 0 0.0 0 +chr4 4486780 0 0 0.0 0 +chr4 4493307 0 0 0.0 0 +chr4 4569855 0 0 0.0 0 +chr4 4710556 0 0 0.0 0 +chr4 4743407 0 1 0.0116 0 +chr4 4748013 0 0 0.0 0 +chr4 4797087 0 0 0.0 0 +chr4 4805313 0 0 0.0 0 +chr4 4819441 0 0 0.0 0 +chr4 4827717 0 0 0.0 0 +chr4 4850587 0 0 0.0 0 +chr4 4911529 0 0 0.0 0 +chr4 4992853 0 0 0.0 0 +chr4 5016736 0 0 0.0 0 +chr4 5083357 0 0 0.0 0 +chr4 5099139 0 0 0.0 0 +chr4 5124096 0 0 0.0 0 +chr4 5151655 0 0 0.0 0 +chr4 5345642 0 0 0.0 0 +chr4 5485539 0 0 0.0 0 +chr4 5490736 0 0 0.0 0 +chr4 5508216 0 0 0.0 0 +chr4 5547073 0 0 0.0 0 +chr4 5690217 0 0 0.0 0 +chr4 5701992 0 1 0.0208 0 +chr4 5799399 0 0 0.0 0 +chr4 5803721 0 0 0.0 0 +chr4 5826357 0 0 0.0 0 +chr4 5855416 0 0 0.0 0 +chr4 5870213 0 0 0.0 0 +chr4 5873015 0 0 0.0 0 +chr4 5894772 0 0 0.0 0 +chr4 5994190 0 0 0.0 0 +chr4 6023929 0 0 0.0 0 +chr4 6025680 0 0 0.0 0 +chr4 6155848 0 0 0.0 0 +chr4 6179756 0 0 0.0 0 +chr4 6231052 0 0 0.0 0 +chr4 6287122 0 0 0.0 0 +chr4 6293982 0 0 0.0 0 +chr4 6302534 0 0 0.0 0 +chr4 6329223 0 0 0.0 0 +chr4 6335186 0 0 0.0 0 +chr4 6360079 0 0 0.0 0 +chr4 6381337 0 0 0.0 0 +chr4 6437221 0 0 0.0 0 +chr4 6451259 0 0 0.0 0 +chr4 6498612 0 0 0.0 0 +chr4 6544172 0 0 0.0 0 +chr4 6759273 0 0 0.0 0 +chr4 6929659 0 0 0.0 0 +chr4 6954051 0 0 0.0 0 +chr4 6975776 0 0 0.0 0 +chr4 7061571 0 0 0.0 0 +chr4 7071178 0 0 0.0 0 +chr4 7082172 0 0 0.0 0 +chr4 7102024 0 0 0.0 0 +chr4 7215504 0 0 0.0 0 +chr4 7234584 0 0 0.0 0 +chr4 7246952 0 0 0.0 0 +chr4 7277052 0 0 0.0 0 +chr4 7307403 0 0 0.0 0 +chr4 7425804 0 0 0.0 0 +chr4 7440659 0 0 0.0 0 +chr4 7486269 0 0 0.0 0 +chr4 7636028 0 0 0.0 0 +chr4 7681324 0 0 0.0 0 +chr4 7699021 0 0 0.0 0 +chr4 7763985 0 0 0.0 0 +chr4 7931954 0 0 0.0 0 +chr4 7963145 0 0 0.0 0 +chr4 7965522 0 0 0.0 0 +chr4 8024295 0 0 0.0 0 +chr4 8067024 0 0 0.0 0 +chr4 8101014 0 0 0.0 0 +chr4 8169074 0 0 0.0 0 +chr4 8193691 0 0 0.0 0 +chr4 8225807 0 0 0.0 0 +chr4 8264333 0 1 0.02 0 +chr4 8290277 0 0 0.0 0 +chr4 8369597 0 0 0.0 0 +chr4 8373531 0 0 0.0 0 +chr4 8416189 0 0 0.0 0 +chr4 8428033 0 0 0.0 0 +chr4 8514086 0 0 0.0 0 +chr4 8514538 0 0 0.0 0 +chr4 8548261 0 0 0.0 0 +chr4 8579395 0 0 0.0 0 +chr4 8644782 0 0 0.0 0 +chr4 8708986 0 0 0.0 0 +chr4 8793530 0 0 0.0 0 +chr4 8833580 0 0 0.0 0 +chr4 8850646 0 0 0.0 0 +chr4 8862201 0 0 0.0 0 +chr4 8893490 0 0 0.0 0 +chr4 8973375 0 0 0.0 0 +chr4 8979762 0 0 0.0 0 +chr4 9015543 0 0 0.0 0 +chr4 9024073 0 0 0.0 0 +chr4 9099375 0 0 0.0 0 +chr4 9100621 0 0 0.0 0 +chr4 9556905 0 0 0.0 0 +chr4 9606302 0 0 0.0 0 +chr4 9694901 0 0 0.0 0 +chr4 9698508 0 0 0.0 0 +chr4 9710031 0 0 0.0 0 +chr4 9777435 0 0 0.0 0 +chr4 9792397 0 0 0.0 0 +chr4 9800519 0 0 0.0 0 +chr4 9864237 0 0 0.0 0 +chr4 9897672 0 0 0.0 0 +chr4 9922286 0 0 0.0 0 +chr4 10001204 0 0 0.0 0 +chr4 10027582 0 0 0.0 0 +chr4 10041010 0 0 0.0 0 +chr4 10071285 0 0 0.0 0 +chr4 10116237 0 0 0.0 0 +chr4 10125222 0 1 0.0192 0 +chr4 10231108 0 0 0.0 0 +chr4 10254667 0 0 0.0 0 +chr4 10294455 0 0 0.0 0 +chr4 10335981 0 0 0.0 0 +chr4 10345858 0 0 0.0 0 +chr4 10541783 0 0 0.0 0 +chr4 10551471 0 0 0.0 0 +chr4 10667493 0 0 0.0 0 +chr4 10727150 0 0 0.0 0 +chr4 10767875 0 0 0.0 0 +chr4 10830317 0 0 0.0 0 +chr4 10854101 0 0 0.0 0 +chr4 11013619 0 0 0.0 0 +chr4 11132377 0 0 0.0 0 +chr4 11212694 0 0 0.0 0 +chr4 11345316 0 0 0.0 0 +chr4 11376969 0 0 0.0 0 +chr4 11392480 0 0 0.0 0 +chr4 11392742 0 0 0.0 0 +chr4 11421200 0 0 0.0 0 +chr4 11437632 0 0 0.0 0 +chr4 11582654 0 0 0.0 0 +chr4 11604649 0 0 0.0 0 +chr4 11620905 0 0 0.0 0 +chr4 11663693 0 0 0.0 0 +chr4 11709351 0 0 0.0 0 +chr4 11857552 0 0 0.0 0 +chr4 11860793 0 0 0.0 0 +chr4 11922099 0 0 0.0 0 +chr4 12119889 0 0 0.0 0 +chr4 12241563 0 0 0.0 0 +chr4 12272217 0 0 0.0 0 +chr4 12495964 0 0 0.0 0 +chr4 12623620 0 0 0.0 0 +chr4 12744159 0 0 0.0 0 +chr4 12854942 0 0 0.0 0 +chr4 12894313 0 0 0.0 0 +chr4 13050824 0 0 0.0 0 +chr4 13094490 0 0 0.0 0 +chr4 13284395 0 0 0.0 0 +chr4 13584197 0 0 0.0 0 +chr4 13733116 0 0 0.0 0 +chr4 13752441 0 0 0.0 0 +chr4 13782496 0 0 0.0 0 +chr4 14389838 0 0 0.0 0 +chr4 14396836 0 0 0.0 0 +chr4 14618075 0 0 0.0 0 +chr4 14619775 0 0 0.0 0 +chr4 14647252 0 0 0.0 0 +chr4 14845794 0 0 0.0 0 +chr4 14900715 0 0 0.0 0 +chr4 15367197 0 1 0.0152 0 +chr4 15398875 0 0 0.0 0 +chr4 15418029 0 0 0.0 0 +chr4 15445016 0 0 0.0 0 +chr4 15449584 0 0 0.0 0 +chr4 15620565 0 0 0.0 0 +chr4 15726611 0 0 0.0 0 +chr4 15818146 0 0 0.0 0 +chr4 16023832 0 0 0.0 0 +chr4 16399525 0 0 0.0 0 +chr4 16437766 0 0 0.0 0 +chr4 16501616 0 0 0.0 0 +chr4 16538154 0 0 0.0 0 +chr4 16579042 0 0 0.0 0 +chr4 16638810 0 0 0.0 0 +chr4 16677001 0 0 0.0 0 +chr4 16818620 0 0 0.0 0 +chr4 16926107 0 0 0.0 0 +chr4 16997703 0 0 0.0 0 +chr4 17369378 0 0 0.0 0 +chr4 17446603 0 0 0.0 0 +chr4 17454664 0 0 0.0 0 +chr4 17467576 0 0 0.0 0 +chr4 17481615 0 0 0.0 0 +chr4 17507133 0 0 0.0 0 +chr4 17572343 0 0 0.0 0 +chr4 17625204 0 0 0.0 0 +chr4 17631954 0 0 0.0 0 +chr4 17649341 0 0 0.0 0 +chr4 17687151 0 0 0.0 0 +chr4 17725066 0 0 0.0 0 +chr4 17911056 0 0 0.0 0 +chr4 17929980 0 0 0.0 0 +chr4 17960268 0 0 0.0 0 +chr4 17982396 0 0 0.0 0 +chr4 18059167 0 0 0.0 0 +chr4 18225085 0 0 0.0 0 +chr4 18253326 0 0 0.0 0 +chr4 18283487 0 0 0.0 0 +chr4 18285100 0 0 0.0 0 +chr4 18436194 0 0 0.0 0 +chr4 18539513 0 0 0.0 0 +chr4 18687936 0 0 0.0 0 +chr4 18769050 0 0 0.0 0 +chr4 18905027 0 0 0.0 0 +chr4 18980766 0 0 0.0 0 +chr4 19117501 0 0 0.0 0 +chr4 19144527 0 0 0.0 0 +chr4 19334323 0 0 0.0 0 +chr4 19802365 0 0 0.0 0 +chr4 19921001 0 0 0.0 0 +chr4 19945701 0 0 0.0 0 +chr4 20045365 0 0 0.0 0 +chr4 20087367 0 0 0.0 0 +chr4 20094641 0 0 0.0 0 +chr4 20224208 0 0 0.0 0 +chr4 20594917 0 0 0.0 0 +chr4 21149355 0 0 0.0 0 +chr4 21245309 0 0 0.0 0 +chr4 21259472 0 0 0.0 0 +chr4 21404351 0 0 0.0 0 +chr4 21448222 0 1 0.0182 0 +chr4 21489164 0 0 0.0 0 +chr4 21745574 0 0 0.0 0 +chr4 21981595 0 0 0.0 0 +chr4 21999370 0 0 0.0 0 +chr4 22304008 0 0 0.0 0 +chr4 22557005 0 0 0.0 0 +chr4 23356772 0 0 0.0 0 +chr4 23385071 0 0 0.0 0 +chr4 23418783 0 0 0.0 0 +chr4 23480481 0 0 0.0 0 +chr4 23625917 0 0 0.0 0 +chr4 23708279 0 0 0.0 0 +chr4 23827813 0 0 0.0 0 +chr4 23927920 0 0 0.0 0 +chr4 24020954 0 0 0.0 0 +chr4 24030231 0 0 0.0 0 +chr4 24084064 0 0 0.0 0 +chr4 24115762 0 0 0.0 0 +chr4 24183315 0 0 0.0 0 +chr4 24210624 0 0 0.0 0 +chr4 24217032 0 0 0.0 0 +chr4 24241117 0 0 0.0 0 +chr4 24262531 0 0 0.0 0 +chr4 24370693 0 0 0.0 0 +chr4 24380445 0 0 0.0 0 +chr4 24486862 0 0 0.0 0 +chr4 24488900 0 0 0.0 0 +chr4 24557430 0 0 0.0 0 +chr4 24577985 0 0 0.0 0 +chr4 24800516 0 0 0.0 0 +chr4 24992393 0 0 0.0 0 +chr4 25022130 0 1 0.0128 0 +chr4 25057918 0 0 0.0 0 +chr4 25246637 0 0 0.0 0 +chr4 25267675 0 0 0.0 0 +chr4 25367214 0 0 0.0 0 +chr4 25580801 0 0 0.0 0 +chr4 25636520 0 0 0.0 0 +chr4 25806616 0 0 0.0 0 +chr4 25901071 0 0 0.0 0 +chr4 25905534 0 0 0.0 0 +chr4 26174758 0 0 0.0 0 +chr4 26184355 0 0 0.0 0 +chr4 26226798 0 0 0.0 0 +chr4 26228002 0 0 0.0 0 +chr4 26406256 0 0 0.0 0 +chr4 26561343 0 1 0.0233 0 +chr4 26873838 0 0 0.0 0 +chr4 26921221 0 0 0.0 0 +chr4 26959661 0 0 0.0 0 +chr4 26975546 0 0 0.0 0 +chr4 26996449 0 0 0.0 0 +chr4 27094290 0 0 0.0 0 +chr4 27104847 0 0 0.0 0 +chr4 27111354 0 0 0.0 0 +chr4 27314426 0 0 0.0 0 +chr4 27426202 0 0 0.0 0 +chr4 27509420 0 0 0.0 0 +chr4 27812453 0 0 0.0 0 +chr4 27909980 0 0 0.0 0 +chr4 27978342 0 0 0.0 0 +chr4 28182985 0 0 0.0 0 +chr4 28187565 0 0 0.0 0 +chr4 28651230 0 0 0.0 0 +chr4 28704308 0 0 0.0 0 +chr4 28772351 0 0 0.0 0 +chr4 28856795 0 0 0.0 0 +chr4 29002883 0 0 0.0 0 +chr4 29070206 0 0 0.0 0 +chr4 29082289 0 0 0.0 0 +chr4 29546027 0 0 0.0 0 +chr4 29929921 0 0 0.0 0 +chr4 30070834 0 0 0.0 0 +chr4 30225550 0 0 0.0 0 +chr4 30637559 0 0 0.0 0 +chr4 30781482 0 0 0.0 0 +chr4 30850425 0 0 0.0 0 +chr4 30875396 0 0 0.0 0 +chr4 31234834 0 0 0.0 0 +chr4 31310567 0 0 0.0 0 +chr4 31481530 0 0 0.0 0 +chr4 31543267 0 0 0.0 0 +chr4 31663046 0 0 0.0 0 +chr4 31691815 0 0 0.0 0 +chr4 31862560 0 0 0.0 0 +chr4 31888705 0 0 0.0 0 +chr4 32043824 0 0 0.0 0 +chr4 32177345 0 0 0.0 0 +chr4 32177400 0 0 0.0 0 +chr4 32196878 0 0 0.0 0 +chr4 32274718 0 0 0.0 0 +chr4 32325466 0 0 0.0 0 +chr4 32371144 0 0 0.0 0 +chr4 32371557 0 0 0.0 0 +chr4 32461927 0 0 0.0 0 +chr4 32519491 0 0 0.0 0 +chr4 32718780 0 0 0.0 0 +chr4 32772556 0 0 0.0 0 +chr4 32942008 0 0 0.0 0 +chr4 33149591 0 0 0.0 0 +chr4 33149950 0 0 0.0 0 +chr4 33188322 0 0 0.0 0 +chr4 33188722 0 0 0.0 0 +chr4 33207975 0 0 0.0 0 +chr4 33316150 0 0 0.0 0 +chr4 33382984 0 0 0.0 0 +chr4 33530743 0 0 0.0 0 +chr4 33577712 0 0 0.0 0 +chr4 33647689 0 0 0.0 0 +chr4 34127861 0 0 0.0 0 +chr4 34188028 0 0 0.0 0 +chr4 34251667 0 0 0.0 0 +chr4 34786361 0 0 0.0 0 +chr4 35006524 0 0 0.0 0 +chr4 35312542 0 0 0.0 0 +chr4 35312713 0 0 0.0 0 +chr4 35316780 0 0 0.0 0 +chr4 35420545 0 0 0.0 0 +chr4 35505909 0 0 0.0 0 +chr4 35566781 0 0 0.0 0 +chr4 35770914 0 0 0.0 0 +chr4 36263953 0 0 0.0 0 +chr4 36458567 0 0 0.0 0 +chr4 36510810 0 0 0.0 0 +chr4 36574616 0 0 0.0 0 +chr4 36935912 0 0 0.0 0 +chr4 36957975 0 0 0.0 0 +chr4 36972533 0 1 0.013 0 +chr4 36995695 0 0 0.0 0 +chr4 37048749 0 0 0.0 0 +chr4 37123105 0 0 0.0 0 +chr4 37143325 0 0 0.0 0 +chr4 37398556 0 0 0.0 0 +chr4 37408325 0 0 0.0 0 +chr4 37421388 0 0 0.0 0 +chr4 37424246 0 0 0.0 0 +chr4 37475135 0 0 0.0 0 +chr4 37522664 0 0 0.0 0 +chr4 37562833 0 0 0.0 0 +chr4 37591129 0 0 0.0 0 +chr4 37646434 0 0 0.0 0 +chr4 37807343 0 0 0.0 0 +chr4 37958953 0 0 0.0 0 +chr4 37968937 0 0 0.0 0 +chr4 38105140 0 0 0.0 0 +chr4 38106901 0 0 0.0 0 +chr4 38108509 0 0 0.0 0 +chr4 38123641 0 0 0.0 0 +chr4 38141019 0 0 0.0 0 +chr4 38160670 0 0 0.0 0 +chr4 38197104 0 0 0.0 0 +chr4 38235807 0 0 0.0 0 +chr4 38366582 0 0 0.0 0 +chr4 38393610 0 0 0.0 0 +chr4 38871353 0 1 0.0141 0 +chr4 39128844 0 0 0.0 0 +chr4 39313509 0 0 0.0 0 +chr4 39384306 0 0 0.0 0 +chr4 39415028 0 0 0.0 0 +chr4 39566326 0 0 0.0 0 +chr4 39682494 0 0 0.0 0 +chr4 39744195 0 0 0.0 0 +chr4 40182938 0 0 0.0 0 +chr4 40281676 0 0 0.0 0 +chr4 40285049 0 0 0.0 0 +chr4 40668026 0 0 0.0 0 +chr4 40680974 0 0 0.0 0 +chr4 40799348 0 0 0.0 0 +chr4 40840907 0 0 0.0 0 +chr4 40933409 0 0 0.0 0 +chr4 41079027 0 0 0.0 0 +chr4 41321170 0 0 0.0 0 +chr4 41442745 0 0 0.0 0 +chr4 41546948 0 0 0.0 0 +chr4 41582503 0 0 0.0 0 +chr4 41601903 0 0 0.0 0 +chr4 41705593 0 0 0.0 0 +chr4 41713175 0 0 0.0 0 +chr4 41718244 0 0 0.0 0 +chr4 41882221 0 0 0.0 0 +chr4 41925060 0 1 0.0244 0 +chr4 41990430 0 0 0.0 0 +chr4 42237184 0 0 0.0 0 +chr4 42278660 0 0 0.0 0 +chr4 42287919 0 0 0.0 0 +chr4 42385323 0 0 0.0 0 +chr4 42477151 0 0 0.0 0 +chr4 42482059 0 0 0.0 0 +chr4 42728154 0 0 0.0 0 +chr4 42811770 0 0 0.0 0 +chr4 42890555 0 0 0.0 0 +chr4 42975245 0 0 0.0 0 +chr4 43337567 0 0 0.0 0 +chr4 43513105 0 0 0.0 0 +chr4 43525330 0 0 0.0 0 +chr4 43543980 0 0 0.0 0 +chr4 43641011 0 0 0.0 0 +chr4 43841002 0 0 0.0 0 +chr4 44137304 0 0 0.0 0 +chr4 44142072 0 0 0.0 0 +chr4 44225221 0 1 0.0139 0 +chr4 44275844 0 0 0.0 0 +chr4 44414561 0 0 0.0 0 +chr4 44454740 0 0 0.0 0 +chr4 44814628 0 0 0.0 0 +chr4 44926736 0 0 0.0 0 +chr4 45207135 0 0 0.0 0 +chr4 45276442 0 0 0.0 0 +chr4 45283313 0 0 0.0 0 +chr4 45424940 0 0 0.0 0 +chr4 45562024 0 0 0.0 0 +chr4 45762695 0 0 0.0 0 +chr4 45841040 0 0 0.0 0 +chr4 46196568 0 0 0.0 0 +chr4 46315103 0 0 0.0 0 +chr4 46355672 0 0 0.0 0 +chr4 46926116 0 0 0.0 0 +chr4 47129686 0 0 0.0 0 +chr4 47216292 0 0 0.0 0 +chr4 47222759 0 0 0.0 0 +chr4 47257003 0 0 0.0 0 +chr4 47323624 0 0 0.0 0 +chr4 47343651 0 0 0.0 0 +chr4 47723711 0 0 0.0 0 +chr4 47880298 0 0 0.0 0 +chr4 48092983 0 0 0.0 0 +chr4 48347790 0 0 0.0 0 +chr4 48600452 0 0 0.0 0 +chr4 48704570 0 0 0.0 0 +chr4 48729145 0 0 0.0 0 +chr4 48895124 0 0 0.0 0 +chr4 48972568 0 0 0.0 0 +chr4 49117567 0 0 0.0 0 +chr4 49127148 0 0 0.0 0 +chr4 49134975 0 0 0.0 0 +chr4 49152574 1 4 0.05 1 +chr4 49175087 0 0 0.0 0 +chr4 49270141 0 0 0.0 0 +chr4 49635003 0 1 0.0172 0 +chr4 51812754 0 0 0.0 0 +chr4 51833774 0 0 0.0 0 +chr4 51879364 0 0 0.0 0 +chr4 51971711 0 0 0.0 0 +chr4 52160831 0 0 0.0 0 +chr4 52173644 0 0 0.0 0 +chr4 52631456 0 0 0.0 0 +chr4 52793507 0 0 0.0 0 +chr4 52866645 0 0 0.0 0 +chr4 53061755 0 0 0.0 0 +chr4 53228354 0 0 0.0 0 +chr4 53271796 0 0 0.0 0 +chr4 53286523 0 1 0.0238 0 +chr4 53597500 0 0 0.0 0 +chr4 53675072 0 0 0.0 0 +chr4 53833035 0 0 0.0 0 +chr4 53867272 0 0 0.0 0 +chr4 54189558 0 0 0.0 0 +chr4 54385077 0 0 0.0 0 +chr4 54459618 0 0 0.0 0 +chr4 54739123 0 0 0.0 0 +chr4 54825552 0 0 0.0 0 +chr4 54930164 0 0 0.0 0 +chr4 54992998 0 0 0.0 0 +chr4 55020356 0 0 0.0 0 +chr4 55157740 0 0 0.0 0 +chr4 55169417 0 0 0.0 0 +chr4 55249160 0 0 0.0 0 +chr4 55352476 0 0 0.0 0 +chr4 55353534 0 0 0.0 0 +chr4 55529684 0 0 0.0 0 +chr4 55539735 0 0 0.0 0 +chr4 55633812 0 0 0.0 0 +chr4 55660254 0 0 0.0 0 +chr4 55728177 0 0 0.0 0 +chr4 55978247 0 0 0.0 0 +chr4 56076050 0 0 0.0 0 +chr4 56218192 0 0 0.0 0 +chr4 56291036 0 0 0.0 0 +chr4 56302764 0 0 0.0 0 +chr4 56382403 0 0 0.0 0 +chr4 56571631 0 0 0.0 0 +chr4 56598509 0 0 0.0 0 +chr4 56640216 0 0 0.0 0 +chr4 56713495 0 0 0.0 0 +chr4 56718795 0 0 0.0 0 +chr4 56833197 0 0 0.0 0 +chr4 56862418 0 0 0.0 0 +chr4 56913634 0 0 0.0 0 +chr4 56941264 0 0 0.0 0 +chr4 57052709 0 0 0.0 0 +chr4 57159125 0 0 0.0 0 +chr4 57195819 0 0 0.0 0 +chr4 57302340 0 0 0.0 0 +chr4 57541665 0 0 0.0 0 +chr4 57582437 0 0 0.0 0 +chr4 57677321 0 0 0.0 0 +chr4 57686776 0 0 0.0 0 +chr4 57868028 0 0 0.0 0 +chr4 58039295 0 0 0.0 0 +chr4 58186478 0 0 0.0 0 +chr4 58251632 0 0 0.0 0 +chr4 58294869 0 0 0.0 0 +chr4 58394339 0 0 0.0 0 +chr4 58442753 0 0 0.0 0 +chr4 58548389 0 0 0.0 0 +chr4 58602501 0 0 0.0 0 +chr4 58605635 0 0 0.0 0 +chr4 58619260 0 0 0.0 0 +chr4 58659262 0 0 0.0 0 +chr4 58829223 0 0 0.0 0 +chr4 59207326 0 0 0.0 0 +chr4 59283586 0 0 0.0 0 +chr4 59344261 0 0 0.0 0 +chr4 59490412 0 0 0.0 0 +chr4 59571998 0 0 0.0 0 +chr4 59584102 0 0 0.0 0 +chr4 59615555 0 0 0.0 0 +chr4 59634603 0 0 0.0 0 +chr4 59785403 0 0 0.0 0 +chr4 59995933 0 0 0.0 0 +chr4 60272361 0 0 0.0 0 +chr4 60296788 0 0 0.0 0 +chr4 60329354 0 0 0.0 0 +chr4 60388909 0 0 0.0 0 +chr4 60456723 0 0 0.0 0 +chr4 60489634 0 0 0.0 0 +chr4 60545699 0 0 0.0 0 +chr4 60585939 0 0 0.0 0 +chr4 60644439 0 0 0.0 0 +chr4 60736509 0 0 0.0 0 +chr4 60863394 0 0 0.0 0 +chr4 61107108 0 0 0.0 0 +chr4 61195044 0 0 0.0 0 +chr4 61592900 0 0 0.0 0 +chr4 61714604 0 0 0.0 0 +chr4 61716992 0 0 0.0 0 +chr4 61878698 0 0 0.0 0 +chr4 62100543 0 0 0.0 0 +chr4 62310125 0 0 0.0 0 +chr4 62571237 0 0 0.0 0 +chr4 62621504 0 0 0.0 0 +chr4 62677859 0 0 0.0 0 +chr4 62813934 0 0 0.0 0 +chr4 63017482 0 0 0.0 0 +chr4 63112086 0 0 0.0 0 +chr4 63378192 0 0 0.0 0 +chr4 63418631 0 0 0.0 0 +chr4 63501047 0 0 0.0 0 +chr4 63815097 0 0 0.0 0 +chr4 63829250 0 0 0.0 0 +chr4 63909386 0 0 0.0 0 +chr4 64060492 0 0 0.0 0 +chr4 64068452 0 0 0.0 0 +chr4 64145286 0 0 0.0 0 +chr4 64224608 0 0 0.0 0 +chr4 64326571 0 0 0.0 0 +chr4 64416301 0 0 0.0 0 +chr4 64425101 0 0 0.0 0 +chr4 64453332 0 0 0.0 0 +chr4 64563162 0 0 0.0 0 +chr4 64613278 0 0 0.0 0 +chr4 64732002 1 33 0.9706 1 +chr4 64796896 0 0 0.0 0 +chr4 65042113 0 0 0.0 0 +chr4 65195976 0 0 0.0 0 +chr4 65860663 0 0 0.0 0 +chr4 66011452 0 0 0.0 0 +chr4 66018063 0 0 0.0 0 +chr4 66389431 0 0 0.0 0 +chr4 66636279 0 0 0.0 0 +chr4 66636786 0 0 0.0 0 +chr4 66865134 0 0 0.0 0 +chr4 66921325 0 0 0.0 0 +chr4 67049424 0 0 0.0 0 +chr4 67118280 0 0 0.0 0 +chr4 67252185 0 0 0.0 0 +chr4 67282220 0 0 0.0 0 +chr4 67288808 0 0 0.0 0 +chr4 67306986 0 0 0.0 0 +chr4 67334646 0 0 0.0 0 +chr4 67754743 0 0 0.0 0 +chr4 68048046 0 0 0.0 0 +chr4 68148167 0 0 0.0 0 +chr4 68162704 0 1 0.0312 0 +chr4 68194929 0 0 0.0 0 +chr4 68224733 0 0 0.0 0 +chr4 68421058 0 0 0.0 0 +chr4 68577366 0 0 0.0 0 +chr4 68663436 0 0 0.0 0 +chr4 68664825 0 0 0.0 0 +chr4 69033688 0 0 0.0 0 +chr4 69156561 0 0 0.0 0 +chr4 69239951 0 0 0.0 0 +chr4 69268799 0 0 0.0 0 +chr4 69309791 0 0 0.0 0 +chr4 69322943 0 0 0.0 0 +chr4 69632387 0 1 0.0345 0 +chr4 70040340 0 0 0.0 0 +chr4 70317935 0 0 0.0 0 +chr4 70361211 0 0 0.0 0 +chr4 70368570 0 0 0.0 0 +chr4 70424598 0 0 0.0 0 +chr4 70548890 0 0 0.0 0 +chr4 70626659 0 0 0.0 0 +chr4 70675984 0 0 0.0 0 +chr4 70927847 0 0 0.0 0 +chr4 71121312 0 0 0.0 0 +chr4 71122661 0 0 0.0 0 +chr4 71176058 0 0 0.0 0 +chr4 71527517 0 0 0.0 0 +chr4 71528056 0 0 0.0 0 +chr4 71712496 0 0 0.0 0 +chr4 71892250 0 0 0.0 0 +chr4 71922810 0 0 0.0 0 +chr4 72009368 0 0 0.0 0 +chr4 72250336 0 0 0.0 0 +chr4 72663976 0 0 0.0 0 +chr4 72680098 0 0 0.0 0 +chr4 72691352 0 0 0.0 0 +chr4 72878675 0 0 0.0 0 +chr4 73197054 0 0 0.0 0 +chr4 73244240 0 0 0.0 0 +chr4 73300233 0 0 0.0 0 +chr4 73357710 0 0 0.0 0 +chr4 73379431 0 0 0.0 0 +chr4 73646231 0 0 0.0 0 +chr4 74066312 0 0 0.0 0 +chr4 74081053 0 0 0.0 0 +chr4 74317477 0 0 0.0 0 +chr4 74434540 0 0 0.0 0 +chr4 74793769 0 0 0.0 0 +chr4 74889843 0 0 0.0 0 +chr4 74925238 0 0 0.0 0 +chr4 74950989 0 0 0.0 0 +chr4 74985394 0 0 0.0 0 +chr4 75038594 0 0 0.0 0 +chr4 75079543 0 0 0.0 0 +chr4 75104252 0 0 0.0 0 +chr4 75400875 0 0 0.0 0 +chr4 75416441 0 0 0.0 0 +chr4 75458045 0 0 0.0 0 +chr4 75616223 0 0 0.0 0 +chr4 76003833 0 0 0.0 0 +chr4 76016743 0 0 0.0 0 +chr4 76099513 0 0 0.0 0 +chr4 76180113 0 0 0.0 0 +chr4 76193543 0 0 0.0 0 +chr4 76501367 0 0 0.0 0 +chr4 76537303 0 0 0.0 0 +chr4 76555436 0 0 0.0 0 +chr4 76598119 0 0 0.0 0 +chr4 76667447 0 0 0.0 0 +chr4 76684467 0 0 0.0 0 +chr4 77010917 0 0 0.0 0 +chr4 77019578 0 0 0.0 0 +chr4 77183683 0 0 0.0 0 +chr4 77193747 0 0 0.0 0 +chr4 77205926 0 0 0.0 0 +chr4 77249592 0 0 0.0 0 +chr4 77334296 0 0 0.0 0 +chr4 77376057 0 0 0.0 0 +chr4 77485396 0 0 0.0 0 +chr4 77562310 0 0 0.0 0 +chr4 77655038 0 0 0.0 0 +chr4 77720543 0 0 0.0 0 +chr4 77797794 0 0 0.0 0 +chr4 77825879 0 0 0.0 0 +chr4 77930115 0 0 0.0 0 +chr4 78000831 0 0 0.0 0 +chr4 78025896 0 0 0.0 0 +chr4 78037504 0 0 0.0 0 +chr4 78042105 0 0 0.0 0 +chr4 78044480 0 0 0.0 0 +chr4 78075618 0 0 0.0 0 +chr4 78098508 0 0 0.0 0 +chr4 78548239 0 0 0.0 0 +chr4 78940798 0 0 0.0 0 +chr4 79065725 1 19 0.2879 1 +chr4 79307393 0 0 0.0 0 +chr4 79372596 0 0 0.0 0 +chr4 79998845 0 0 0.0 0 +chr4 80072903 0 0 0.0 0 +chr4 80190171 0 0 0.0 0 +chr4 80196393 0 0 0.0 0 +chr4 80202179 0 0 0.0 0 +chr4 80286490 0 0 0.0 0 +chr4 80388637 0 0 0.0 0 +chr4 80467205 0 0 0.0 0 +chr4 80509878 1 10 0.1613 1 +chr4 80567444 0 0 0.0 0 +chr4 80829513 0 0 0.0 0 +chr4 80860691 0 0 0.0 0 +chr4 81351074 0 0 0.0 0 +chr4 81462864 0 0 0.0 0 +chr4 81590451 0 0 0.0 0 +chr4 81610153 0 0 0.0 0 +chr4 81647441 0 0 0.0 0 +chr4 81698615 0 0 0.0 0 +chr4 81710610 0 0 0.0 0 +chr4 81712423 0 0 0.0 0 +chr4 81763388 0 0 0.0 0 +chr4 82090043 0 0 0.0 0 +chr4 82130488 0 0 0.0 0 +chr4 82176269 0 0 0.0 0 +chr4 82475482 0 0 0.0 0 +chr4 82496828 0 0 0.0 0 +chr4 82593341 0 0 0.0 0 +chr4 82607554 0 0 0.0 0 +chr4 82621539 0 0 0.0 0 +chr4 82748209 0 0 0.0 0 +chr4 82963401 0 0 0.0 0 +chr4 82968782 0 0 0.0 0 +chr4 82975840 0 0 0.0 0 +chr4 83153234 0 0 0.0 0 +chr4 83164890 0 0 0.0 0 +chr4 83249773 0 0 0.0 0 +chr4 83327787 0 0 0.0 0 +chr4 83455957 0 0 0.0 0 +chr4 83524033 0 1 0.0137 0 +chr4 83698624 0 0 0.0 0 +chr4 83738871 0 0 0.0 0 +chr4 83769355 0 0 0.0 0 +chr4 83832055 0 0 0.0 0 +chr4 83901215 0 0 0.0 0 +chr4 83901518 0 0 0.0 0 +chr4 83937532 0 0 0.0 0 +chr4 83993185 0 0 0.0 0 +chr4 84051841 0 0 0.0 0 +chr4 84266208 0 0 0.0 0 +chr4 84286224 0 0 0.0 0 +chr4 84583069 0 0 0.0 0 +chr4 84659582 0 0 0.0 0 +chr4 84708935 0 0 0.0 0 +chr4 84777281 0 0 0.0 0 +chr4 84816816 0 0 0.0 0 +chr4 85129986 0 0 0.0 0 +chr4 85251631 0 0 0.0 0 +chr4 85276857 0 0 0.0 0 +chr4 85317654 0 0 0.0 0 +chr4 85344860 0 0 0.0 0 +chr4 85404293 0 0 0.0 0 +chr4 85425510 0 0 0.0 0 +chr4 85430546 0 0 0.0 0 +chr4 85459775 0 0 0.0 0 +chr4 85772362 0 0 0.0 0 +chr4 85784714 0 0 0.0 0 +chr4 85832617 0 0 0.0 0 +chr4 85852766 0 0 0.0 0 +chr4 85951191 0 0 0.0 0 +chr4 86007676 0 0 0.0 0 +chr4 86193624 0 0 0.0 0 +chr4 86221615 0 0 0.0 0 +chr4 86263443 0 0 0.0 0 +chr4 86591635 0 0 0.0 0 +chr4 86625018 0 0 0.0 0 +chr4 86654982 0 0 0.0 0 +chr4 86719171 0 0 0.0 0 +chr4 86742698 0 0 0.0 0 +chr4 86820409 0 0 0.0 0 +chr4 86910822 0 0 0.0 0 +chr4 86943003 0 0 0.0 0 +chr4 87055071 0 0 0.0 0 +chr4 87093859 0 0 0.0 0 +chr4 87101670 0 0 0.0 0 +chr4 87461879 0 0 0.0 0 +chr4 87488960 0 1 0.125 0 +chr4 87583718 0 0 0.0 0 +chr4 87634230 0 0 0.0 0 +chr4 87673896 0 0 0.0 0 +chr4 87794241 0 0 0.0 0 +chr4 87871996 0 0 0.0 0 +chr4 87920233 0 0 0.0 0 +chr4 87989869 0 0 0.0 0 +chr4 88073551 0 1 0.0145 0 +chr4 88528650 0 0 0.0 0 +chr4 88652600 0 0 0.0 0 +chr4 88720347 0 0 0.0 0 +chr4 88745976 0 0 0.0 0 +chr4 88748911 0 0 0.0 0 +chr4 88774849 0 0 0.0 0 +chr4 88777070 0 0 0.0 0 +chr4 88806934 0 0 0.0 0 +chr4 88843892 0 0 0.0 0 +chr4 88893381 0 0 0.0 0 +chr4 88904584 0 0 0.0 0 +chr4 89089897 0 0 0.0 0 +chr4 89106976 0 0 0.0 0 +chr4 89222239 0 0 0.0 0 +chr4 89713894 0 0 0.0 0 +chr4 89841177 0 0 0.0 0 +chr4 89913753 0 0 0.0 0 +chr4 89981088 0 0 0.0 0 +chr4 90001286 0 0 0.0 0 +chr4 90225872 0 0 0.0 0 +chr4 90385344 0 2 0.0308 0 +chr4 90428938 0 0 0.0 0 +chr4 90492941 0 0 0.0 0 +chr4 90511443 0 0 0.0 0 +chr4 90731102 0 0 0.0 0 +chr4 91250652 0 0 0.0 0 +chr4 91482159 0 0 0.0 0 +chr4 91550586 0 0 0.0 0 +chr4 91613712 0 0 0.0 0 +chr4 91822709 0 0 0.0 0 +chr4 91874236 0 0 0.0 0 +chr4 91951462 0 1 0.0294 0 +chr4 92240511 0 0 0.0 0 +chr4 92254176 0 1 0.0116 0 +chr4 92399255 0 0 0.0 0 +chr4 92615217 0 0 0.0 0 +chr4 92656153 0 0 0.0 0 +chr4 92712172 0 0 0.0 0 +chr4 92816551 0 0 0.0 0 +chr4 92837207 0 0 0.0 0 +chr4 92895941 0 0 0.0 0 +chr4 93033830 0 0 0.0 0 +chr4 93278129 0 1 0.0159 0 +chr4 93332005 0 0 0.0 0 +chr4 93542248 0 0 0.0 0 +chr4 93542675 0 0 0.0 0 +chr4 93823325 0 0 0.0 0 +chr4 93880156 0 0 0.0 0 +chr4 93885890 0 0 0.0 0 +chr4 93932668 0 0 0.0 0 +chr4 94031966 0 0 0.0 0 +chr4 94045307 0 0 0.0 0 +chr4 94336531 0 0 0.0 0 +chr4 94409258 0 0 0.0 0 +chr4 94540225 0 0 0.0 0 +chr4 94660826 0 0 0.0 0 +chr4 94693652 0 0 0.0 0 +chr4 94815524 0 0 0.0 0 +chr4 94843850 0 0 0.0 0 +chr4 94897011 0 0 0.0 0 +chr4 95142231 0 0 0.0 0 +chr4 95638332 0 0 0.0 0 +chr4 95647539 0 0 0.0 0 +chr4 95679119 0 0 0.0 0 +chr4 95696284 0 0 0.0 0 +chr4 95728840 0 0 0.0 0 +chr4 95764165 0 0 0.0 0 +chr4 95901032 0 0 0.0 0 +chr4 95975406 0 0 0.0 0 +chr4 96044576 0 0 0.0 0 +chr4 96399586 0 0 0.0 0 +chr4 96464678 0 0 0.0 0 +chr4 96525593 0 0 0.0 0 +chr4 96567269 0 1 0.0294 0 +chr4 96599773 0 0 0.0 0 +chr4 96631648 0 0 0.0 0 +chr4 96651171 0 0 0.0 0 +chr4 96778801 0 0 0.0 0 +chr4 97120297 0 0 0.0 0 +chr4 97381639 0 0 0.0 0 +chr4 97519467 0 0 0.0 0 +chr4 97764248 0 0 0.0 0 +chr4 97923390 0 1 0.0303 0 +chr4 98179863 0 0 0.0 0 +chr4 98266908 0 0 0.0 0 +chr4 98480550 0 0 0.0 0 +chr4 98620257 0 0 0.0 0 +chr4 98743085 0 0 0.0 0 +chr4 98779161 0 0 0.0 0 +chr4 98795391 0 0 0.0 0 +chr4 99055064 1 6 0.0938 1 +chr4 99090082 0 0 0.0 0 +chr4 99161441 0 0 0.0 0 +chr4 99190973 0 0 0.0 0 +chr4 99388078 0 0 0.0 0 +chr4 99391663 0 0 0.0 0 +chr4 99630807 0 0 0.0 0 +chr4 99783552 0 0 0.0 0 +chr4 99892941 0 0 0.0 0 +chr4 100078717 0 0 0.0 0 +chr4 100303580 0 0 0.0 0 +chr4 100355694 0 0 0.0 0 +chr4 100413910 0 0 0.0 0 +chr4 100512124 0 0 0.0 0 +chr4 100613829 0 0 0.0 0 +chr4 100705191 0 0 0.0 0 +chr4 100900738 0 0 0.0 0 +chr4 100961498 0 0 0.0 0 +chr4 101042009 0 0 0.0 0 +chr4 101110620 0 0 0.0 0 +chr4 101129040 0 0 0.0 0 +chr4 101157702 0 0 0.0 0 +chr4 101318363 0 0 0.0 0 +chr4 101603822 0 0 0.0 0 +chr4 101619324 0 0 0.0 0 +chr4 101734632 0 1 0.0238 0 +chr4 101823483 0 0 0.0 0 +chr4 102013115 0 0 0.0 0 +chr4 102125540 0 0 0.0 0 +chr4 102170823 0 0 0.0 0 +chr4 102176856 0 0 0.0 0 +chr4 102401406 0 0 0.0 0 +chr4 102442254 0 0 0.0 0 +chr4 102511304 0 0 0.0 0 +chr4 102596757 0 0 0.0 0 +chr4 102746729 0 0 0.0 0 +chr4 102915523 0 0 0.0 0 +chr4 102971230 0 0 0.0 0 +chr4 103077883 0 0 0.0 0 +chr4 103087927 0 0 0.0 0 +chr4 103101380 0 0 0.0 0 +chr4 103200441 0 0 0.0 0 +chr4 103427378 0 0 0.0 0 +chr4 103451248 0 0 0.0 0 +chr4 103493094 0 0 0.0 0 +chr4 103787435 0 0 0.0 0 +chr4 103980595 0 0 0.0 0 +chr4 104218473 0 0 0.0 0 +chr4 104369947 0 0 0.0 0 +chr4 104650975 0 0 0.0 0 +chr4 104749728 0 0 0.0 0 +chr4 105063081 0 0 0.0 0 +chr4 105124878 0 0 0.0 0 +chr4 105414381 0 0 0.0 0 +chr4 105473540 0 0 0.0 0 +chr4 105505610 0 0 0.0 0 +chr4 105648788 0 0 0.0 0 +chr4 105696112 0 0 0.0 0 +chr4 105761987 0 0 0.0 0 +chr4 106092412 0 0 0.0 0 +chr4 106173925 0 0 0.0 0 +chr4 106287661 0 0 0.0 0 +chr4 106320552 0 0 0.0 0 +chr4 106423343 0 0 0.0 0 +chr4 106603981 0 0 0.0 0 +chr4 106616181 0 0 0.0 0 +chr4 106617202 0 0 0.0 0 +chr4 106710852 0 0 0.0 0 +chr4 106862711 0 0 0.0 0 +chr4 106978050 0 0 0.0 0 +chr4 107652948 0 0 0.0 0 +chr4 107714724 0 0 0.0 0 +chr4 107779972 0 0 0.0 0 +chr4 107884894 0 0 0.0 0 +chr4 107892516 0 0 0.0 0 +chr4 107898766 0 0 0.0 0 +chr4 108295562 0 0 0.0 0 +chr4 108452537 0 0 0.0 0 +chr4 108673601 1 10 0.2632 1 +chr4 108690122 0 1 0.0256 0 +chr4 108804729 0 0 0.0 0 +chr4 108821795 0 0 0.0 0 +chr4 108863978 0 0 0.0 0 +chr4 109171754 0 0 0.0 0 +chr4 109234732 0 0 0.0 0 +chr4 109282826 0 0 0.0 0 +chr4 109306523 0 0 0.0 0 +chr4 109652232 0 0 0.0 0 +chr4 109712784 0 0 0.0 0 +chr4 109857513 0 0 0.0 0 +chr4 109870002 0 0 0.0 0 +chr4 110063359 0 0 0.0 0 +chr4 110107746 0 0 0.0 0 +chr4 110117346 0 0 0.0 0 +chr4 110142480 0 0 0.0 0 +chr4 110253666 0 0 0.0 0 +chr4 110432036 0 0 0.0 0 +chr4 110737934 0 0 0.0 0 +chr4 111049140 0 0 0.0 0 +chr4 111303698 0 0 0.0 0 +chr4 111414272 0 0 0.0 0 +chr4 111628323 0 0 0.0 0 +chr4 111721796 0 0 0.0 0 +chr4 111746143 0 0 0.0 0 +chr4 111767556 0 0 0.0 0 +chr4 111952939 0 0 0.0 0 +chr4 112616197 0 0 0.0 0 +chr4 112705176 0 1 0.0256 0 +chr4 112918874 0 0 0.0 0 +chr4 112924932 0 0 0.0 0 +chr4 113086482 0 0 0.0 0 +chr4 113104073 0 0 0.0 0 +chr4 113133085 0 0 0.0 0 +chr4 113281425 0 0 0.0 0 +chr4 113303011 0 0 0.0 0 +chr4 113505851 0 0 0.0 0 +chr4 113754845 0 0 0.0 0 +chr4 113849090 0 0 0.0 0 +chr4 114180342 0 0 0.0 0 +chr4 114190952 0 0 0.0 0 +chr4 114285644 0 0 0.0 0 +chr4 114293514 0 0 0.0 0 +chr4 114349311 0 0 0.0 0 +chr4 114481998 0 0 0.0 0 +chr4 114924549 0 0 0.0 0 +chr4 115027484 0 0 0.0 0 +chr4 115094624 0 0 0.0 0 +chr4 115387540 0 0 0.0 0 +chr4 115522362 0 0 0.0 0 +chr4 115524614 0 0 0.0 0 +chr4 115678509 0 0 0.0 0 +chr4 115835099 0 0 0.0 0 +chr4 116186024 0 0 0.0 0 +chr4 116241634 0 0 0.0 0 +chr4 116357838 0 0 0.0 0 +chr4 116539663 0 0 0.0 0 +chr4 116591268 0 0 0.0 0 +chr4 116595767 0 0 0.0 0 +chr4 116693041 0 0 0.0 0 +chr4 116761464 0 0 0.0 0 +chr4 116821020 0 0 0.0 0 +chr4 116879791 0 0 0.0 0 +chr4 117154509 0 0 0.0 0 +chr4 117172738 0 0 0.0 0 +chr4 117201409 0 0 0.0 0 +chr4 117206564 0 0 0.0 0 +chr4 117218377 0 0 0.0 0 +chr4 117368234 0 1 0.0164 0 +chr4 117560161 0 0 0.0 0 +chr4 117743875 0 0 0.0 0 +chr4 118091511 0 0 0.0 0 +chr4 118115040 0 0 0.0 0 +chr4 118313140 0 0 0.0 0 +chr4 118448884 0 0 0.0 0 +chr4 118460860 0 0 0.0 0 +chr4 118666533 0 0 0.0 0 +chr4 118901793 0 0 0.0 0 +chr4 118969047 0 0 0.0 0 +chr4 119148060 0 0 0.0 0 +chr4 119198509 0 0 0.0 0 +chr4 119255035 0 0 0.0 0 +chr4 119525914 0 0 0.0 0 +chr4 119868648 0 2 0.0444 0 +chr4 119986783 0 0 0.0 0 +chr4 120052374 0 0 0.0 0 +chr4 120070706 0 0 0.0 0 +chr4 120165243 0 0 0.0 0 +chr4 120238536 0 0 0.0 0 +chr4 120509405 0 0 0.0 0 +chr4 120900221 0 0 0.0 0 +chr4 120900311 0 0 0.0 0 +chr4 120918266 0 0 0.0 0 +chr4 121003859 0 0 0.0 0 +chr4 121048349 0 0 0.0 0 +chr4 121061493 0 0 0.0 0 +chr4 121273300 0 0 0.0 0 +chr4 121436869 0 0 0.0 0 +chr4 121631963 0 0 0.0 0 +chr4 121868474 0 0 0.0 0 +chr4 121984295 0 0 0.0 0 +chr4 122062232 1 30 0.4348 1 +chr4 122195414 1 8 0.0964 1 +chr4 122350791 0 0 0.0 0 +chr4 122435447 0 0 0.0 0 +chr4 122835457 0 0 0.0 0 +chr4 122894076 0 0 0.0 0 +chr4 122923774 0 0 0.0 0 +chr4 123198920 0 0 0.0 0 +chr4 123269308 0 0 0.0 0 +chr4 123464055 0 0 0.0 0 +chr4 123559885 0 0 0.0 0 +chr4 123819432 0 0 0.0 0 +chr4 123870001 0 0 0.0 0 +chr4 123933837 0 0 0.0 0 +chr4 124156015 0 0 0.0 0 +chr4 124183293 0 0 0.0 0 +chr4 124338773 0 0 0.0 0 +chr4 124477680 0 0 0.0 0 +chr4 124562278 0 0 0.0 0 +chr4 124716277 0 0 0.0 0 +chr4 124719170 1 5 0.2 1 +chr4 125028567 0 0 0.0 0 +chr4 125129989 0 0 0.0 0 +chr4 125297376 0 0 0.0 0 +chr4 125357169 0 0 0.0 0 +chr4 125369707 0 0 0.0 0 +chr4 125676433 0 0 0.0 0 +chr4 126011360 0 0 0.0 0 +chr4 126080907 0 0 0.0 0 +chr4 126370816 0 0 0.0 0 +chr4 126616489 0 0 0.0 0 +chr4 126775376 0 0 0.0 0 +chr4 126815984 0 0 0.0 0 +chr4 127002320 0 0 0.0 0 +chr4 127026989 0 0 0.0 0 +chr4 127076646 0 0 0.0 0 +chr4 127276921 0 0 0.0 0 +chr4 127426344 0 0 0.0 0 +chr4 127511105 0 0 0.0 0 +chr4 127544576 0 0 0.0 0 +chr4 127684121 0 0 0.0 0 +chr4 127796365 0 0 0.0 0 +chr4 127832782 0 0 0.0 0 +chr4 127959192 0 0 0.0 0 +chr4 128054741 0 0 0.0 0 +chr4 128266598 0 0 0.0 0 +chr4 128292477 0 0 0.0 0 +chr4 128336780 0 0 0.0 0 +chr4 128416064 0 0 0.0 0 +chr4 128631517 0 0 0.0 0 +chr4 128783913 0 0 0.0 0 +chr4 128930558 0 0 0.0 0 +chr4 129024430 0 0 0.0 0 +chr4 129091343 0 0 0.0 0 +chr4 129239446 0 0 0.0 0 +chr4 129283988 0 0 0.0 0 +chr4 129376084 0 0 0.0 0 +chr4 129489965 0 0 0.0 0 +chr4 129566560 0 0 0.0 0 +chr4 129623365 0 0 0.0 0 +chr4 129881197 0 0 0.0 0 +chr4 129959918 0 0 0.0 0 +chr4 130036698 0 0 0.0 0 +chr4 130292947 1 21 0.3559 1 +chr4 130397489 0 0 0.0 0 +chr4 130753925 1 19 0.6786 1 +chr4 130866572 0 0 0.0 0 +chr4 130932491 0 0 0.0 0 +chr4 130990578 0 0 0.0 0 +chr4 131039687 0 0 0.0 0 +chr4 131040506 0 0 0.0 0 +chr4 131210510 0 0 0.0 0 +chr4 131275058 0 0 0.0 0 +chr4 131293441 0 0 0.0 0 +chr4 131385908 0 0 0.0 0 +chr4 131424944 0 0 0.0 0 +chr4 131459685 0 0 0.0 0 +chr4 131526492 1 36 0.4932 1 +chr4 131721396 0 2 0.0312 0 +chr4 131771996 0 0 0.0 0 +chr4 131826494 0 0 0.0 0 +chr4 131840671 0 0 0.0 0 +chr4 132028094 0 0 0.0 0 +chr4 132142889 0 0 0.0 0 +chr4 132343960 0 0 0.0 0 +chr4 132511122 0 0 0.0 0 +chr4 132540308 0 1 0.0263 0 +chr4 132646407 0 0 0.0 0 +chr4 132813544 0 0 0.0 0 +chr4 132844990 0 0 0.0 0 +chr4 132861860 0 0 0.0 0 +chr4 132938911 0 0 0.0 0 +chr4 132965619 0 0 0.0 0 +chr4 133334212 0 0 0.0 0 +chr4 133652160 0 0 0.0 0 +chr4 133701837 0 0 0.0 0 +chr4 133878781 0 0 0.0 0 +chr4 133926571 0 0 0.0 0 +chr4 134125044 0 0 0.0 0 +chr4 134388159 0 0 0.0 0 +chr4 134442456 1 21 0.236 1 +chr4 134545621 0 0 0.0 0 +chr4 134724883 0 0 0.0 0 +chr4 134807064 0 0 0.0 0 +chr4 134892107 0 0 0.0 0 +chr4 135137466 0 0 0.0 0 +chr4 135390729 0 0 0.0 0 +chr4 135904241 0 0 0.0 0 +chr4 135960476 0 0 0.0 0 +chr4 135990890 0 0 0.0 0 +chr4 136160335 0 0 0.0 0 +chr4 136243420 0 0 0.0 0 +chr4 136770142 0 0 0.0 0 +chr4 136779148 0 0 0.0 0 +chr4 137049551 0 0 0.0 0 +chr4 137164037 0 1 0.0125 0 +chr4 137215304 0 0 0.0 0 +chr4 137454783 0 0 0.0 0 +chr4 137612391 0 0 0.0 0 +chr4 137711024 0 0 0.0 0 +chr4 137801258 0 0 0.0 0 +chr4 137826850 0 0 0.0 0 +chr4 137946681 0 0 0.0 0 +chr4 138036566 0 0 0.0 0 +chr4 138039544 0 0 0.0 0 +chr4 138101213 0 0 0.0 0 +chr4 138124119 0 0 0.0 0 +chr4 138337979 0 0 0.0 0 +chr4 138833196 0 0 0.0 0 +chr4 138911114 0 0 0.0 0 +chr4 139048962 0 0 0.0 0 +chr4 139054289 0 0 0.0 0 +chr4 139102279 0 0 0.0 0 +chr4 139129285 0 0 0.0 0 +chr4 139140449 0 0 0.0 0 +chr4 139286778 0 0 0.0 0 +chr4 139319045 0 0 0.0 0 +chr4 139395343 0 0 0.0 0 +chr4 139417726 0 0 0.0 0 +chr4 139425044 0 0 0.0 0 +chr4 139785983 0 0 0.0 0 +chr4 139793379 0 0 0.0 0 +chr4 139870335 0 0 0.0 0 +chr4 139955763 0 0 0.0 0 +chr4 140086605 0 0 0.0 0 +chr4 140152229 0 0 0.0 0 +chr4 140232181 0 1 0.0227 0 +chr4 140255989 0 0 0.0 0 +chr4 140291741 0 0 0.0 0 +chr4 140350598 0 0 0.0 0 +chr4 140506921 0 0 0.0 0 +chr4 140591279 0 0 0.0 0 +chr4 140662676 0 0 0.0 0 +chr4 140805384 0 0 0.0 0 +chr4 141163095 0 0 0.0 0 +chr4 141248942 0 0 0.0 0 +chr4 141497940 0 0 0.0 0 +chr4 141509174 0 0 0.0 0 +chr4 141775420 0 0 0.0 0 +chr4 141796320 0 0 0.0 0 +chr4 141941055 0 0 0.0 0 +chr4 142829027 0 0 0.0 0 +chr4 142850862 0 0 0.0 0 +chr4 142868564 0 0 0.0 0 +chr4 142991759 0 0 0.0 0 +chr4 143020136 0 0 0.0 0 +chr4 143086841 0 1 0.0152 0 +chr4 143135067 0 0 0.0 0 +chr4 143156456 0 0 0.0 0 +chr4 143261999 0 0 0.0 0 +chr4 143323718 0 0 0.0 0 +chr4 143414084 0 0 0.0 0 +chr4 143497950 0 0 0.0 0 +chr4 143516568 0 0 0.0 0 +chr4 143529980 0 0 0.0 0 +chr4 143560945 0 0 0.0 0 +chr4 144191350 0 0 0.0 0 +chr4 144299631 0 0 0.0 0 +chr4 144338379 0 0 0.0 0 +chr4 144348547 0 0 0.0 0 +chr4 144381546 0 0 0.0 0 +chr4 144399388 0 0 0.0 0 +chr4 144435221 0 0 0.0 0 +chr4 144564280 0 0 0.0 0 +chr4 144583759 0 0 0.0 0 +chr4 144596164 0 0 0.0 0 +chr4 144661277 0 0 0.0 0 +chr4 144725932 0 0 0.0 0 +chr4 144978218 0 0 0.0 0 +chr4 145275705 0 1 0.0278 0 +chr4 145323384 0 0 0.0 0 +chr4 145378960 0 0 0.0 0 +chr4 145545781 0 0 0.0 0 +chr4 145673516 0 0 0.0 0 +chr4 145740431 0 0 0.0 0 +chr4 145758328 0 0 0.0 0 +chr4 145891084 0 0 0.0 0 +chr4 146131978 0 0 0.0 0 +chr4 146184691 0 0 0.0 0 +chr4 146280925 0 0 0.0 0 +chr4 146420553 0 0 0.0 0 +chr4 146457372 0 0 0.0 0 +chr4 146527815 0 0 0.0 0 +chr4 146529736 0 0 0.0 0 +chr4 146596153 0 0 0.0 0 +chr4 147064221 0 0 0.0 0 +chr4 147144977 0 0 0.0 0 +chr4 147272460 0 0 0.0 0 +chr4 147561029 0 0 0.0 0 +chr4 147636972 0 0 0.0 0 +chr4 148174755 0 1 0.0154 0 +chr4 148563236 0 0 0.0 0 +chr4 148585467 0 0 0.0 0 +chr4 148653893 0 1 0.0244 0 +chr4 148949650 0 0 0.0 0 +chr4 148975410 0 0 0.0 0 +chr4 149048190 0 0 0.0 0 +chr4 149229801 0 0 0.0 0 +chr4 149290787 0 0 0.0 0 +chr4 149295202 0 0 0.0 0 +chr4 149374872 0 0 0.0 0 +chr4 149477820 0 0 0.0 0 +chr4 149600839 0 0 0.0 0 +chr4 149699814 0 0 0.0 0 +chr4 149789577 0 0 0.0 0 +chr4 149848273 0 0 0.0 0 +chr4 149903818 0 0 0.0 0 +chr4 149981765 0 0 0.0 0 +chr4 150207722 0 0 0.0 0 +chr4 150271651 0 0 0.0 0 +chr4 150272177 0 0 0.0 0 +chr4 150294438 0 0 0.0 0 +chr4 150332583 0 0 0.0 0 +chr4 150335826 0 0 0.0 0 +chr4 150641236 0 0 0.0 0 +chr4 151054127 0 0 0.0 0 +chr4 151062935 0 1 0.0189 0 +chr4 151155162 0 0 0.0 0 +chr4 151232931 0 0 0.0 0 +chr4 151259405 0 0 0.0 0 +chr4 151283611 0 0 0.0 0 +chr4 151809952 0 0 0.0 0 +chr4 151821074 0 0 0.0 0 +chr4 151860793 0 0 0.0 0 +chr4 151862432 0 0 0.0 0 +chr4 151883716 0 0 0.0 0 +chr4 151935837 0 0 0.0 0 +chr4 152185141 0 0 0.0 0 +chr4 152204901 0 0 0.0 0 +chr4 152434546 0 0 0.0 0 +chr4 152522129 0 0 0.0 0 +chr4 152539625 0 0 0.0 0 +chr4 152540068 0 0 0.0 0 +chr4 152873603 0 0 0.0 0 +chr4 153006529 0 0 0.0 0 +chr4 153402460 0 0 0.0 0 +chr4 153413162 0 0 0.0 0 +chr4 153459570 0 0 0.0 0 +chr4 153651210 0 0 0.0 0 +chr4 153660432 0 0 0.0 0 +chr4 153660941 0 0 0.0 0 +chr4 153709575 0 0 0.0 0 +chr4 153902756 0 0 0.0 0 +chr4 154031289 0 0 0.0 0 +chr4 154074946 0 0 0.0 0 +chr4 154130272 0 0 0.0 0 +chr4 154141784 0 0 0.0 0 +chr4 154165402 0 0 0.0 0 +chr4 154289209 0 0 0.0 0 +chr4 154292481 0 0 0.0 0 +chr4 154301597 0 0 0.0 0 +chr4 154413514 0 0 0.0 0 +chr4 154428044 0 0 0.0 0 +chr4 154510453 0 0 0.0 0 +chr4 154598647 0 0 0.0 0 +chr4 154601944 0 0 0.0 0 +chr4 154843739 0 0 0.0 0 +chr4 154899078 0 0 0.0 0 +chr4 154904229 0 0 0.0 0 +chr4 154911137 0 0 0.0 0 +chr4 154926376 0 0 0.0 0 +chr4 154981838 0 0 0.0 0 +chr4 155021058 0 0 0.0 0 +chr4 155034027 0 0 0.0 0 +chr4 155162929 0 0 0.0 0 +chr4 155177632 0 0 0.0 0 +chr4 155212373 0 0 0.0 0 +chr4 155242184 0 0 0.0 0 +chr4 155492368 0 0 0.0 0 +chr4 155585926 0 0 0.0 0 +chr4 155723707 0 0 0.0 0 +chr4 155801664 0 0 0.0 0 +chr4 155974173 0 0 0.0 0 +chr4 156059807 0 0 0.0 0 +chr4 156496435 0 1 0.0192 0 +chr4 156708782 0 0 0.0 0 +chr4 156913097 0 0 0.0 0 +chr4 157091441 0 0 0.0 0 +chr4 157193498 0 0 0.0 0 +chr4 157196316 0 0 0.0 0 +chr4 157208432 0 0 0.0 0 +chr4 157633510 0 0 0.0 0 +chr4 157739818 0 0 0.0 0 +chr4 157760578 0 0 0.0 0 +chr4 157781815 0 0 0.0 0 +chr4 157782281 0 0 0.0 0 +chr4 157803586 0 0 0.0 0 +chr4 158024632 0 0 0.0 0 +chr4 158124491 0 0 0.0 0 +chr4 158188630 0 0 0.0 0 +chr4 158504734 0 0 0.0 0 +chr4 158509911 0 0 0.0 0 +chr4 158515175 0 0 0.0 0 +chr4 158605578 0 0 0.0 0 +chr4 158650297 1 51 0.9623 1 +chr4 158661527 0 0 0.0 0 +chr4 158761023 0 0 0.0 0 +chr4 158820174 0 0 0.0 0 +chr4 158844192 0 0 0.0 0 +chr4 158893074 0 0 0.0 0 +chr4 158922400 0 0 0.0 0 +chr4 159061949 0 0 0.0 0 +chr4 159391691 0 0 0.0 0 +chr4 159423534 0 0 0.0 0 +chr4 159572014 0 0 0.0 0 +chr4 159709004 0 0 0.0 0 +chr4 159855028 0 0 0.0 0 +chr4 159995291 0 0 0.0 0 +chr4 160001947 0 0 0.0 0 +chr4 160212436 0 0 0.0 0 +chr4 160342345 0 0 0.0 0 +chr4 160398969 0 0 0.0 0 +chr4 160594677 0 0 0.0 0 +chr4 160601398 0 0 0.0 0 +chr4 160744843 0 0 0.0 0 +chr4 160782969 0 0 0.0 0 +chr4 160989095 0 2 0.0323 0 +chr4 161004531 0 0 0.0 0 +chr4 161112557 0 0 0.0 0 +chr4 161509448 0 0 0.0 0 +chr4 161930084 0 0 0.0 0 +chr4 162076813 0 0 0.0 0 +chr4 162181322 0 0 0.0 0 +chr4 162274565 0 0 0.0 0 +chr4 162599907 0 0 0.0 0 +chr4 162613868 0 0 0.0 0 +chr4 162700050 0 0 0.0 0 +chr4 162876320 0 0 0.0 0 +chr4 162969733 0 0 0.0 0 +chr4 163354998 0 0 0.0 0 +chr4 163460003 0 0 0.0 0 +chr4 163490580 0 0 0.0 0 +chr4 163609422 0 0 0.0 0 +chr4 163618248 0 0 0.0 0 +chr4 163799199 0 0 0.0 0 +chr4 164187079 0 0 0.0 0 +chr4 164223541 0 0 0.0 0 +chr4 164294558 0 0 0.0 0 +chr4 164484364 0 1 0.0154 0 +chr4 164515823 0 0 0.0 0 +chr4 164537175 0 0 0.0 0 +chr4 164564009 0 0 0.0 0 +chr4 164620343 0 0 0.0 0 +chr4 164699143 0 0 0.0 0 +chr4 164820088 0 0 0.0 0 +chr4 164900011 0 0 0.0 0 +chr4 164906922 1 49 1.0 1 +chr4 165061658 0 0 0.0 0 +chr4 165108904 0 0 0.0 0 +chr4 165118943 0 0 0.0 0 +chr4 165330958 0 0 0.0 0 +chr4 165366129 0 0 0.0 0 +chr4 165412786 0 0 0.0 0 +chr4 165505062 0 0 0.0 0 +chr4 165546492 0 0 0.0 0 +chr4 165707668 0 0 0.0 0 +chr4 166154266 0 0 0.0 0 +chr4 166308845 0 0 0.0 0 +chr4 166346823 0 0 0.0 0 +chr4 166399003 0 0 0.0 0 +chr4 166426118 0 0 0.0 0 +chr4 166567058 0 0 0.0 0 +chr4 166769469 0 0 0.0 0 +chr4 167460392 0 0 0.0 0 +chr4 167483983 0 0 0.0 0 +chr4 168195770 0 0 0.0 0 +chr4 168271139 0 0 0.0 0 +chr4 168331234 0 0 0.0 0 +chr4 168646071 0 0 0.0 0 +chr4 168695691 0 0 0.0 0 +chr4 168777126 0 2 0.0357 0 +chr4 168840533 0 0 0.0 0 +chr4 169059551 0 0 0.0 0 +chr4 169386370 0 0 0.0 0 +chr4 169441110 0 0 0.0 0 +chr4 169471436 0 0 0.0 0 +chr4 169471982 0 0 0.0 0 +chr4 169554207 0 0 0.0 0 +chr4 169905978 0 0 0.0 0 +chr4 169907004 0 0 0.0 0 +chr4 169974374 0 0 0.0 0 +chr4 169985821 0 2 0.0312 0 +chr4 170308448 0 1 0.0154 0 +chr4 170487687 0 1 0.027 0 +chr4 170626018 0 0 0.0 0 +chr4 170645662 0 0 0.0 0 +chr4 170662603 0 0 0.0 0 +chr4 170808233 0 0 0.0 0 +chr4 170902825 0 0 0.0 0 +chr4 171376902 0 0 0.0 0 +chr4 171572915 0 0 0.0 0 +chr4 171584395 0 0 0.0 0 +chr4 171707220 0 0 0.0 0 +chr4 171838505 0 0 0.0 0 +chr4 171840405 0 0 0.0 0 +chr4 171929333 0 0 0.0 0 +chr4 172080392 0 0 0.0 0 +chr4 172373654 0 0 0.0 0 +chr4 172446499 0 0 0.0 0 +chr4 172449629 0 0 0.0 0 +chr4 172682781 0 0 0.0 0 +chr4 172726463 0 1 0.0154 0 +chr4 172941481 0 0 0.0 0 +chr4 173156790 0 0 0.0 0 +chr4 173201297 0 0 0.0 0 +chr4 173312752 0 0 0.0 0 +chr4 173379961 0 0 0.0 0 +chr4 173407862 0 0 0.0 0 +chr4 173584748 0 0 0.0 0 +chr4 173618532 0 0 0.0 0 +chr4 173968175 0 0 0.0 0 +chr4 174124496 0 0 0.0 0 +chr4 174702843 0 0 0.0 0 +chr4 174949450 0 0 0.0 0 +chr4 174990686 0 0 0.0 0 +chr4 175050455 0 0 0.0 0 +chr4 175078517 0 0 0.0 0 +chr4 175495103 0 0 0.0 0 +chr4 175605307 0 0 0.0 0 +chr4 175648842 0 0 0.0 0 +chr4 175670024 1 37 0.5522 1 +chr4 175738199 0 0 0.0 0 +chr4 175863256 0 0 0.0 0 +chr4 175938827 0 0 0.0 0 +chr4 175991525 0 0 0.0 0 +chr4 176197695 0 0 0.0 0 +chr4 176221465 0 0 0.0 0 +chr4 176240771 0 0 0.0 0 +chr4 176286440 0 0 0.0 0 +chr4 176304866 0 0 0.0 0 +chr4 176334081 0 0 0.0 0 +chr4 176392854 0 0 0.0 0 +chr4 176470373 0 0 0.0 0 +chr4 176562996 0 0 0.0 0 +chr4 176617639 0 0 0.0 0 +chr4 176701704 0 0 0.0 0 +chr4 176786259 0 0 0.0 0 +chr4 176993399 0 0 0.0 0 +chr4 177034775 0 0 0.0 0 +chr4 177073630 0 0 0.0 0 +chr4 177162317 0 0 0.0 0 +chr4 177357115 0 0 0.0 0 +chr4 177373889 0 0 0.0 0 +chr4 177407906 0 0 0.0 0 +chr4 177497662 0 0 0.0 0 +chr4 177551207 0 0 0.0 0 +chr4 178090671 0 0 0.0 0 +chr4 178141631 0 0 0.0 0 +chr4 178424477 0 0 0.0 0 +chr4 178937293 0 0 0.0 0 +chr4 178962993 0 0 0.0 0 +chr4 178965078 0 0 0.0 0 +chr4 179132292 0 1 0.0213 0 +chr4 179168442 0 0 0.0 0 +chr4 179248069 0 0 0.0 0 +chr4 179282221 0 0 0.0 0 +chr4 179382590 0 0 0.0 0 +chr4 179494546 0 0 0.0 0 +chr4 179780753 0 0 0.0 0 +chr4 179871569 0 0 0.0 0 +chr4 179913088 0 0 0.0 0 +chr4 180067316 0 0 0.0 0 +chr4 180130199 0 0 0.0 0 +chr4 180230587 0 0 0.0 0 +chr4 180371878 0 0 0.0 0 +chr4 180458982 0 0 0.0 0 +chr4 180625921 0 0 0.0 0 +chr4 180765532 0 0 0.0 0 +chr4 180814428 0 0 0.0 0 +chr4 180902132 0 0 0.0 0 +chr4 181235354 0 0 0.0 0 +chr4 181528217 0 0 0.0 0 +chr4 181543464 0 0 0.0 0 +chr4 181675739 0 0 0.0 0 +chr4 181927315 0 0 0.0 0 +chr4 181948868 0 0 0.0 0 +chr4 182204694 0 0 0.0 0 +chr4 182288797 0 0 0.0 0 +chr4 182324112 0 0 0.0 0 +chr4 182396329 0 0 0.0 0 +chr4 182503456 0 0 0.0 0 +chr4 182619897 0 0 0.0 0 +chr4 182738360 0 0 0.0 0 +chr4 183017503 0 0 0.0 0 +chr4 183138896 0 0 0.0 0 +chr4 183314451 0 0 0.0 0 +chr4 183359488 1 71 0.8554 1 +chr4 183389884 0 0 0.0 0 +chr4 183428234 0 1 0.0133 0 +chr4 183659377 0 0 0.0 0 +chr4 183706679 0 0 0.0 0 +chr4 183724886 0 0 0.0 0 +chr4 183745713 0 0 0.0 0 +chr4 183912298 0 0 0.0 0 +chr4 183928402 0 0 0.0 0 +chr4 183945254 0 0 0.0 0 +chr4 183990828 0 0 0.0 0 +chr4 184035201 0 0 0.0 0 +chr4 184068118 0 0 0.0 0 +chr4 184072817 0 0 0.0 0 +chr4 184143323 0 0 0.0 0 +chr4 184204239 0 0 0.0 0 +chr4 184254686 0 0 0.0 0 +chr4 184261444 0 0 0.0 0 +chr4 184380904 0 0 0.0 0 +chr4 184382425 0 0 0.0 0 +chr4 184384912 0 0 0.0 0 +chr4 184394982 0 0 0.0 0 +chr4 184483026 0 0 0.0 0 +chr4 184484280 0 0 0.0 0 +chr4 184949626 0 0 0.0 0 +chr4 185001481 0 0 0.0 0 +chr4 185104031 0 0 0.0 0 +chr4 185331708 0 0 0.0 0 +chr4 185505055 0 0 0.0 0 +chr4 185537086 0 0 0.0 0 +chr4 185544575 0 0 0.0 0 +chr4 185587296 2 10 0.25 1 +chr4 185859908 0 0 0.0 0 +chr4 185872781 0 0 0.0 0 +chr4 186178108 0 0 0.0 0 +chr4 186278322 0 0 0.0 0 +chr4 186343238 0 0 0.0 0 +chr4 186485882 0 0 0.0 0 +chr4 186515700 0 0 0.0 0 +chr4 186624880 0 0 0.0 0 +chr4 186670973 0 0 0.0 0 +chr4 186778329 0 0 0.0 0 +chr4 186790684 0 0 0.0 0 +chr4 186830211 0 0 0.0 0 +chr4 187174751 0 0 0.0 0 +chr4 187314575 0 0 0.0 0 +chr4 187327069 0 0 0.0 0 +chr4 187372863 0 0 0.0 0 +chr4 187429089 0 0 0.0 0 +chr4 187629021 0 0 0.0 0 +chr4 187659873 0 0 0.0 0 +chr4 187681663 0 0 0.0 0 +chr4 187687535 0 0 0.0 0 +chr4 187871496 0 0 0.0 0 +chr4 187883598 0 0 0.0 0 +chr4 188044783 0 0 0.0 0 +chr4 188154741 0 0 0.0 0 +chr4 188179329 0 0 0.0 0 +chr4 188298992 0 0 0.0 0 +chr4 188336327 0 1 0.027 0 +chr4 188754862 0 0 0.0 0 +chr4 188988373 0 0 0.0 0 +chr4 189026381 0 0 0.0 0 +chr4 189053805 0 0 0.0 0 +chr4 189058967 0 0 0.0 0 +chr4 189115822 0 0 0.0 0 +chr4 189254315 0 0 0.0 0 +chr4 189280993 0 0 0.0 0 +chr4 189343402 0 0 0.0 0 +chr4 189401596 0 0 0.0 0 +chr4 189498260 0 0 0.0 0 +chr4 189504941 0 0 0.0 0 +chr4 189984453 0 0 0.0 0 +chr4_GL000008v2_random 4752 0 0 0.0 0 +chr4_GL000008v2_random 96551 0 0 0.0 0 +chr4_GL000257v2_alt 114744 0 0 0.0 0 +chr4_GL000257v2_alt 301410 0 0 0.0 0 +chr4_GL383528v1_alt 278689 0 0 0.0 0 +chr4_KI270787v1_alt 50085 0 0 0.0 0 +chr4_KI270788v1_alt 80484 0 0 0.0 0 +chr4_KI270896v1_alt 321984 0 0 0.0 0 +chr4_KI270925v1_alt 136468 0 0 0.0 0 +chr5 21104 0 0 0.0 0 +chr5 270456 1 27 0.4426 1 +chr5 355292 0 0 0.0 0 +chr5 416009 0 0 0.0 0 +chr5 545879 0 0 0.0 0 +chr5 877909 0 0 0.0 0 +chr5 900582 0 0 0.0 0 +chr5 917022 0 0 0.0 0 +chr5 994013 0 0 0.0 0 +chr5 1077361 0 0 0.0 0 +chr5 1120833 0 0 0.0 0 +chr5 1148921 0 0 0.0 0 +chr5 1170966 0 0 0.0 0 +chr5 1181930 0 0 0.0 0 +chr5 1242559 0 0 0.0 0 +chr5 1330340 0 0 0.0 0 +chr5 1380069 0 0 0.0 0 +chr5 1390451 0 0 0.0 0 +chr5 1394027 0 0 0.0 0 +chr5 1430768 0 0 0.0 0 +chr5 1496011 0 0 0.0 0 +chr5 1549624 0 0 0.0 0 +chr5 1566291 0 0 0.0 0 +chr5 1573060 0 0 0.0 0 +chr5 1601058 0 0 0.0 0 +chr5 1739368 0 0 0.0 0 +chr5 1781999 0 0 0.0 0 +chr5 1939276 0 2 0.0417 0 +chr5 1951454 0 0 0.0 0 +chr5 2073464 0 0 0.0 0 +chr5 2110806 0 0 0.0 0 +chr5 2117286 0 0 0.0 0 +chr5 2144489 0 0 0.0 0 +chr5 2213547 0 0 0.0 0 +chr5 2226974 0 0 0.0 0 +chr5 2278563 0 0 0.0 0 +chr5 2319592 0 0 0.0 0 +chr5 2370983 1 70 0.7527 1 +chr5 2421612 0 0 0.0 0 +chr5 2433915 0 0 0.0 0 +chr5 2449704 0 0 0.0 0 +chr5 2457875 0 0 0.0 0 +chr5 2477863 0 0 0.0 0 +chr5 2634564 0 0 0.0 0 +chr5 2642883 0 0 0.0 0 +chr5 2701144 0 0 0.0 0 +chr5 2709184 0 0 0.0 0 +chr5 2714739 0 0 0.0 0 +chr5 2895504 0 0 0.0 0 +chr5 2919071 0 0 0.0 0 +chr5 2986113 0 1 0.0222 0 +chr5 3062822 0 0 0.0 0 +chr5 3077663 0 0 0.0 0 +chr5 3097653 0 0 0.0 0 +chr5 3109408 0 0 0.0 0 +chr5 3110651 0 0 0.0 0 +chr5 3145751 0 0 0.0 0 +chr5 3249096 0 2 0.0488 0 +chr5 3286190 0 0 0.0 0 +chr5 3357885 0 0 0.0 0 +chr5 3420346 0 0 0.0 0 +chr5 3422186 0 0 0.0 0 +chr5 3474797 0 1 0.0122 0 +chr5 3602560 0 0 0.0 0 +chr5 3713182 0 0 0.0 0 +chr5 3734737 0 0 0.0 0 +chr5 3885067 0 0 0.0 0 +chr5 3964172 0 0 0.0 0 +chr5 3994812 0 0 0.0 0 +chr5 4077030 0 0 0.0 0 +chr5 4241147 0 0 0.0 0 +chr5 4312192 0 0 0.0 0 +chr5 4461586 0 0 0.0 0 +chr5 4494154 0 0 0.0 0 +chr5 4511948 0 0 0.0 0 +chr5 4579697 0 1 0.0208 0 +chr5 4836992 0 0 0.0 0 +chr5 4946755 0 0 0.0 0 +chr5 5032118 0 0 0.0 0 +chr5 5070913 0 0 0.0 0 +chr5 5105828 0 0 0.0 0 +chr5 5111544 0 0 0.0 0 +chr5 5142306 0 0 0.0 0 +chr5 5146282 0 0 0.0 0 +chr5 5159153 0 0 0.0 0 +chr5 5177305 0 0 0.0 0 +chr5 5251944 0 0 0.0 0 +chr5 5272783 0 0 0.0 0 +chr5 5283311 0 0 0.0 0 +chr5 5386584 0 0 0.0 0 +chr5 5514916 0 0 0.0 0 +chr5 5621738 0 0 0.0 0 +chr5 5634818 0 0 0.0 0 +chr5 5693907 0 0 0.0 0 +chr5 5720137 0 0 0.0 0 +chr5 5799854 0 0 0.0 0 +chr5 5864210 0 0 0.0 0 +chr5 5968665 0 0 0.0 0 +chr5 6216893 0 0 0.0 0 +chr5 6369678 0 0 0.0 0 +chr5 6376202 0 0 0.0 0 +chr5 6462745 0 0 0.0 0 +chr5 6577939 0 0 0.0 0 +chr5 6748286 0 0 0.0 0 +chr5 6908011 0 0 0.0 0 +chr5 7000902 0 0 0.0 0 +chr5 7162674 0 0 0.0 0 +chr5 7171427 0 0 0.0 0 +chr5 7237956 0 0 0.0 0 +chr5 7247121 0 0 0.0 0 +chr5 7367827 0 0 0.0 0 +chr5 7426012 0 0 0.0 0 +chr5 7502133 0 0 0.0 0 +chr5 7557947 0 0 0.0 0 +chr5 7664050 0 0 0.0 0 +chr5 7677655 0 0 0.0 0 +chr5 7681724 0 0 0.0 0 +chr5 7704296 0 0 0.0 0 +chr5 8038292 0 0 0.0 0 +chr5 8098307 0 0 0.0 0 +chr5 8115897 0 0 0.0 0 +chr5 8213443 0 0 0.0 0 +chr5 8249086 0 0 0.0 0 +chr5 8363154 0 0 0.0 0 +chr5 8545904 0 0 0.0 0 +chr5 8589407 0 0 0.0 0 +chr5 8945586 0 0 0.0 0 +chr5 8965031 0 0 0.0 0 +chr5 9014621 0 0 0.0 0 +chr5 9033513 0 0 0.0 0 +chr5 9203810 0 1 0.0167 0 +chr5 9219448 0 0 0.0 0 +chr5 9272713 0 0 0.0 0 +chr5 9297286 0 0 0.0 0 +chr5 9314929 0 0 0.0 0 +chr5 9324800 0 0 0.0 0 +chr5 9372798 0 0 0.0 0 +chr5 9449387 0 0 0.0 0 +chr5 9725703 0 0 0.0 0 +chr5 9782666 0 0 0.0 0 +chr5 9829363 0 0 0.0 0 +chr5 9893052 0 0 0.0 0 +chr5 9905052 0 0 0.0 0 +chr5 10080240 0 0 0.0 0 +chr5 10127442 0 0 0.0 0 +chr5 10128133 0 0 0.0 0 +chr5 10187992 0 0 0.0 0 +chr5 10430139 0 0 0.0 0 +chr5 10516473 0 0 0.0 0 +chr5 10618753 0 0 0.0 0 +chr5 10619707 0 0 0.0 0 +chr5 10659669 0 0 0.0 0 +chr5 10674062 0 0 0.0 0 +chr5 10729702 0 0 0.0 0 +chr5 10957732 0 0 0.0 0 +chr5 10958995 0 0 0.0 0 +chr5 11084603 0 0 0.0 0 +chr5 11143670 0 0 0.0 0 +chr5 11154252 0 0 0.0 0 +chr5 11186943 0 0 0.0 0 +chr5 11192995 0 1 0.0145 0 +chr5 11219998 0 0 0.0 0 +chr5 11224708 0 0 0.0 0 +chr5 11262881 0 0 0.0 0 +chr5 11364380 0 0 0.0 0 +chr5 11390701 0 0 0.0 0 +chr5 11415201 0 0 0.0 0 +chr5 11582247 0 0 0.0 0 +chr5 11689906 0 0 0.0 0 +chr5 11915914 0 0 0.0 0 +chr5 11959048 0 0 0.0 0 +chr5 11983865 0 0 0.0 0 +chr5 12080590 0 0 0.0 0 +chr5 12413457 0 0 0.0 0 +chr5 12624033 0 0 0.0 0 +chr5 12715553 0 0 0.0 0 +chr5 12728288 0 0 0.0 0 +chr5 12861387 0 0 0.0 0 +chr5 13017902 0 0 0.0 0 +chr5 13030874 0 0 0.0 0 +chr5 13166892 0 1 0.0147 0 +chr5 13232438 0 0 0.0 0 +chr5 13318013 0 0 0.0 0 +chr5 13323621 0 0 0.0 0 +chr5 13397875 0 0 0.0 0 +chr5 13459252 0 0 0.0 0 +chr5 13459409 0 0 0.0 0 +chr5 13635664 0 0 0.0 0 +chr5 13686210 0 0 0.0 0 +chr5 13782237 0 0 0.0 0 +chr5 13817493 0 0 0.0 0 +chr5 14034913 0 1 0.0204 0 +chr5 14172008 0 0 0.0 0 +chr5 14254588 0 0 0.0 0 +chr5 14358126 0 0 0.0 0 +chr5 14410516 0 0 0.0 0 +chr5 14488116 0 0 0.0 0 +chr5 14553557 0 0 0.0 0 +chr5 14632981 0 0 0.0 0 +chr5 14845728 0 0 0.0 0 +chr5 15077608 0 0 0.0 0 +chr5 15257840 0 0 0.0 0 +chr5 15580833 0 0 0.0 0 +chr5 15786371 0 0 0.0 0 +chr5 16041982 0 0 0.0 0 +chr5 16125120 0 0 0.0 0 +chr5 16180347 0 0 0.0 0 +chr5 16346708 0 0 0.0 0 +chr5 16422195 0 0 0.0 0 +chr5 16448450 0 0 0.0 0 +chr5 16486738 0 0 0.0 0 +chr5 16526787 0 0 0.0 0 +chr5 16565374 0 0 0.0 0 +chr5 16642004 0 1 0.0192 0 +chr5 16711227 0 0 0.0 0 +chr5 16778231 0 0 0.0 0 +chr5 16790396 0 0 0.0 0 +chr5 16802995 0 0 0.0 0 +chr5 16885402 0 0 0.0 0 +chr5 16990118 0 0 0.0 0 +chr5 17186998 0 0 0.0 0 +chr5 17232787 0 0 0.0 0 +chr5 17279334 0 0 0.0 0 +chr5 17351113 0 0 0.0 0 +chr5 17382892 0 0 0.0 0 +chr5 17477449 0 0 0.0 0 +chr5 17742104 0 0 0.0 0 +chr5 18006514 0 0 0.0 0 +chr5 18151747 0 0 0.0 0 +chr5 18491681 0 0 0.0 0 +chr5 18512487 0 0 0.0 0 +chr5 18638096 0 0 0.0 0 +chr5 18672410 0 0 0.0 0 +chr5 18688569 0 0 0.0 0 +chr5 18837985 0 0 0.0 0 +chr5 19569451 0 0 0.0 0 +chr5 19618439 0 0 0.0 0 +chr5 19669819 0 0 0.0 0 +chr5 19836355 0 0 0.0 0 +chr5 20421211 0 0 0.0 0 +chr5 21038845 0 0 0.0 0 +chr5 21177467 0 0 0.0 0 +chr5 21299818 0 0 0.0 0 +chr5 21309566 0 0 0.0 0 +chr5 21424723 0 0 0.0 0 +chr5 21500281 0 0 0.0 0 +chr5 21500997 0 0 0.0 0 +chr5 21559172 0 0 0.0 0 +chr5 21595024 0 0 0.0 0 +chr5 21689136 0 0 0.0 0 +chr5 22226329 0 0 0.0 0 +chr5 22791227 0 0 0.0 0 +chr5 22887468 0 0 0.0 0 +chr5 22950996 0 0 0.0 0 +chr5 23261096 0 0 0.0 0 +chr5 23405275 0 0 0.0 0 +chr5 23528020 0 0 0.0 0 +chr5 23761354 0 0 0.0 0 +chr5 23987228 0 0 0.0 0 +chr5 24247166 0 0 0.0 0 +chr5 24259946 0 0 0.0 0 +chr5 24470343 0 0 0.0 0 +chr5 24495147 0 0 0.0 0 +chr5 24500431 0 0 0.0 0 +chr5 24611848 0 0 0.0 0 +chr5 25363158 0 0 0.0 0 +chr5 25422699 0 0 0.0 0 +chr5 25488774 0 0 0.0 0 +chr5 25708221 0 0 0.0 0 +chr5 25811742 0 0 0.0 0 +chr5 25813869 0 0 0.0 0 +chr5 25889678 0 0 0.0 0 +chr5 25906101 0 0 0.0 0 +chr5 25921077 0 0 0.0 0 +chr5 26214586 0 0 0.0 0 +chr5 26341477 0 0 0.0 0 +chr5 26344241 0 0 0.0 0 +chr5 26395641 0 0 0.0 0 +chr5 26428523 0 0 0.0 0 +chr5 26585917 0 0 0.0 0 +chr5 26657709 0 0 0.0 0 +chr5 26704156 0 0 0.0 0 +chr5 26744476 0 0 0.0 0 +chr5 27010258 0 0 0.0 0 +chr5 27095998 0 0 0.0 0 +chr5 27175212 0 0 0.0 0 +chr5 27213178 0 0 0.0 0 +chr5 27277775 0 0 0.0 0 +chr5 27452377 0 0 0.0 0 +chr5 27504432 0 0 0.0 0 +chr5 27738757 0 0 0.0 0 +chr5 27742983 0 0 0.0 0 +chr5 27785095 0 0 0.0 0 +chr5 28066248 0 0 0.0 0 +chr5 28099550 0 0 0.0 0 +chr5 28107840 0 0 0.0 0 +chr5 28519717 0 0 0.0 0 +chr5 28560810 0 0 0.0 0 +chr5 28570214 0 0 0.0 0 +chr5 28677198 0 0 0.0 0 +chr5 28743647 0 0 0.0 0 +chr5 28835109 0 0 0.0 0 +chr5 28852811 0 0 0.0 0 +chr5 28942115 0 0 0.0 0 +chr5 29064358 0 0 0.0 0 +chr5 29103830 0 0 0.0 0 +chr5 29225982 0 0 0.0 0 +chr5 29371078 0 0 0.0 0 +chr5 29660964 0 0 0.0 0 +chr5 29815675 0 1 0.0147 0 +chr5 29863230 1 36 0.5217 1 +chr5 30023664 0 0 0.0 0 +chr5 30037047 0 1 0.0196 0 +chr5 30045516 0 0 0.0 0 +chr5 30121368 0 0 0.0 0 +chr5 30428636 0 0 0.0 0 +chr5 30469773 0 0 0.0 0 +chr5 30603089 0 0 0.0 0 +chr5 30731456 0 0 0.0 0 +chr5 30915482 0 0 0.0 0 +chr5 31008934 0 0 0.0 0 +chr5 31121092 0 0 0.0 0 +chr5 31157595 0 0 0.0 0 +chr5 31292593 0 0 0.0 0 +chr5 31295344 0 0 0.0 0 +chr5 31332712 0 0 0.0 0 +chr5 31342904 0 0 0.0 0 +chr5 31371455 0 0 0.0 0 +chr5 31397523 0 0 0.0 0 +chr5 31713838 0 0 0.0 0 +chr5 31772419 0 0 0.0 0 +chr5 31869488 0 0 0.0 0 +chr5 31887878 0 0 0.0 0 +chr5 31964342 0 0 0.0 0 +chr5 31990537 0 0 0.0 0 +chr5 32001848 0 0 0.0 0 +chr5 32017330 0 0 0.0 0 +chr5 32372590 0 0 0.0 0 +chr5 32556338 0 0 0.0 0 +chr5 32568651 0 0 0.0 0 +chr5 32738333 0 0 0.0 0 +chr5 32984373 0 0 0.0 0 +chr5 33050839 0 0 0.0 0 +chr5 33518550 0 0 0.0 0 +chr5 33519094 0 0 0.0 0 +chr5 33523866 0 0 0.0 0 +chr5 33546659 0 0 0.0 0 +chr5 33626169 0 0 0.0 0 +chr5 33968315 0 0 0.0 0 +chr5 33971566 0 0 0.0 0 +chr5 33981137 0 0 0.0 0 +chr5 33987331 0 0 0.0 0 +chr5 34100167 0 0 0.0 0 +chr5 34176640 0 0 0.0 0 +chr5 34177357 0 0 0.0 0 +chr5 34463035 0 0 0.0 0 +chr5 34564630 0 0 0.0 0 +chr5 34656271 0 0 0.0 0 +chr5 34731842 0 0 0.0 0 +chr5 34786689 0 0 0.0 0 +chr5 34788510 0 0 0.0 0 +chr5 34921281 0 1 0.0263 0 +chr5 34967078 0 0 0.0 0 +chr5 35051159 0 0 0.0 0 +chr5 35062143 0 0 0.0 0 +chr5 35115595 0 0 0.0 0 +chr5 35141266 0 0 0.0 0 +chr5 35160983 0 0 0.0 0 +chr5 35221904 0 0 0.0 0 +chr5 35234240 0 0 0.0 0 +chr5 35284316 0 0 0.0 0 +chr5 35301617 0 0 0.0 0 +chr5 35424706 0 0 0.0 0 +chr5 35432540 0 0 0.0 0 +chr5 35473299 0 0 0.0 0 +chr5 35708019 0 0 0.0 0 +chr5 35837091 0 0 0.0 0 +chr5 35871940 0 0 0.0 0 +chr5 36160782 0 0 0.0 0 +chr5 36383853 0 0 0.0 0 +chr5 36391048 0 0 0.0 0 +chr5 36450376 0 0 0.0 0 +chr5 36455986 0 0 0.0 0 +chr5 36460909 0 0 0.0 0 +chr5 36465527 0 0 0.0 0 +chr5 36562855 0 0 0.0 0 +chr5 36674365 0 0 0.0 0 +chr5 36677056 0 0 0.0 0 +chr5 36718104 0 0 0.0 0 +chr5 36746725 0 1 0.0152 0 +chr5 36836471 0 0 0.0 0 +chr5 37026883 0 0 0.0 0 +chr5 37183217 0 0 0.0 0 +chr5 37392605 0 0 0.0 0 +chr5 37656817 0 0 0.0 0 +chr5 37847630 0 0 0.0 0 +chr5 37927385 0 0 0.0 0 +chr5 37990426 0 0 0.0 0 +chr5 38243063 0 0 0.0 0 +chr5 38263171 0 0 0.0 0 +chr5 38287195 0 0 0.0 0 +chr5 38326164 0 0 0.0 0 +chr5 38370244 0 0 0.0 0 +chr5 38422030 0 0 0.0 0 +chr5 38446448 0 0 0.0 0 +chr5 38597790 0 0 0.0 0 +chr5 38699925 0 0 0.0 0 +chr5 38814965 1 29 0.7838 1 +chr5 38923037 0 0 0.0 0 +chr5 38972245 0 0 0.0 0 +chr5 39579908 0 0 0.0 0 +chr5 39584085 0 0 0.0 0 +chr5 39744549 0 0 0.0 0 +chr5 40035111 0 0 0.0 0 +chr5 40060916 0 0 0.0 0 +chr5 40154833 0 0 0.0 0 +chr5 40381873 0 0 0.0 0 +chr5 40402008 0 0 0.0 0 +chr5 40422502 0 0 0.0 0 +chr5 40620775 0 1 0.0222 0 +chr5 40696545 0 0 0.0 0 +chr5 40904401 0 0 0.0 0 +chr5 41019112 0 0 0.0 0 +chr5 41362310 0 0 0.0 0 +chr5 41399755 0 0 0.0 0 +chr5 41645737 0 0 0.0 0 +chr5 41652531 0 0 0.0 0 +chr5 41686657 0 0 0.0 0 +chr5 41867271 0 0 0.0 0 +chr5 41937043 0 0 0.0 0 +chr5 41954473 0 0 0.0 0 +chr5 42114406 0 0 0.0 0 +chr5 42127834 0 0 0.0 0 +chr5 42399662 0 0 0.0 0 +chr5 42828915 0 0 0.0 0 +chr5 43233047 0 0 0.0 0 +chr5 43315504 0 1 0.0161 0 +chr5 43354124 0 0 0.0 0 +chr5 43483975 0 0 0.0 0 +chr5 43566370 0 0 0.0 0 +chr5 43748476 0 0 0.0 0 +chr5 43764243 0 0 0.0 0 +chr5 43930069 0 0 0.0 0 +chr5 44050465 0 0 0.0 0 +chr5 44391942 0 0 0.0 0 +chr5 44467143 0 0 0.0 0 +chr5 44553181 0 0 0.0 0 +chr5 44722964 0 0 0.0 0 +chr5 44747303 0 0 0.0 0 +chr5 44980875 0 0 0.0 0 +chr5 45225336 0 0 0.0 0 +chr5 45347248 0 0 0.0 0 +chr5 45998703 0 0 0.0 0 +chr5 46072311 0 0 0.0 0 +chr5 46164222 0 0 0.0 0 +chr5 46183331 0 0 0.0 0 +chr5 46230679 0 0 0.0 0 +chr5 46295420 0 0 0.0 0 +chr5 46359165 0 0 0.0 0 +chr5 46362857 0 0 0.0 0 +chr5 46397189 0 0 0.0 0 +chr5 50293217 0 0 0.0 0 +chr5 50315415 0 0 0.0 0 +chr5 50336754 0 0 0.0 0 +chr5 50408047 0 0 0.0 0 +chr5 50470564 0 0 0.0 0 +chr5 50601070 0 0 0.0 0 +chr5 50900613 0 0 0.0 0 +chr5 50922840 0 0 0.0 0 +chr5 51061136 0 0 0.0 0 +chr5 51272770 0 0 0.0 0 +chr5 51341944 0 0 0.0 0 +chr5 51349538 0 0 0.0 0 +chr5 51358523 0 0 0.0 0 +chr5 51994068 1 68 0.8947 1 +chr5 52040940 0 0 0.0 0 +chr5 52062208 0 0 0.0 0 +chr5 52141159 0 0 0.0 0 +chr5 52875313 0 0 0.0 0 +chr5 52875686 0 0 0.0 0 +chr5 52989185 0 0 0.0 0 +chr5 53006503 0 0 0.0 0 +chr5 53043001 0 1 0.0227 0 +chr5 53167932 0 0 0.0 0 +chr5 53169541 0 0 0.0 0 +chr5 53191205 0 0 0.0 0 +chr5 53207669 0 0 0.0 0 +chr5 53405459 0 0 0.0 0 +chr5 53470560 0 0 0.0 0 +chr5 53631746 0 0 0.0 0 +chr5 53640347 0 0 0.0 0 +chr5 53822758 0 0 0.0 0 +chr5 53940298 0 0 0.0 0 +chr5 54022089 0 0 0.0 0 +chr5 54089861 0 0 0.0 0 +chr5 54142911 0 0 0.0 0 +chr5 54369572 0 0 0.0 0 +chr5 54395376 0 0 0.0 0 +chr5 54398890 0 1 0.0152 0 +chr5 54504860 0 0 0.0 0 +chr5 54640175 0 0 0.0 0 +chr5 54934666 0 0 0.0 0 +chr5 55200276 1 6 0.0857 1 +chr5 55558759 0 0 0.0 0 +chr5 55632674 0 0 0.0 0 +chr5 55663215 0 0 0.0 0 +chr5 55676639 0 0 0.0 0 +chr5 55868441 0 0 0.0 0 +chr5 55879322 0 0 0.0 0 +chr5 55909069 0 0 0.0 0 +chr5 56100287 0 0 0.0 0 +chr5 56201095 0 0 0.0 0 +chr5 56213127 0 0 0.0 0 +chr5 56235213 0 0 0.0 0 +chr5 56289103 0 0 0.0 0 +chr5 56468091 0 0 0.0 0 +chr5 56476483 0 0 0.0 0 +chr5 56537569 0 0 0.0 0 +chr5 56715456 0 0 0.0 0 +chr5 56749305 0 0 0.0 0 +chr5 56756631 0 0 0.0 0 +chr5 56887256 0 0 0.0 0 +chr5 57268509 0 0 0.0 0 +chr5 57327596 0 0 0.0 0 +chr5 57328947 0 0 0.0 0 +chr5 57746295 0 0 0.0 0 +chr5 57761030 0 0 0.0 0 +chr5 57762456 0 0 0.0 0 +chr5 57924053 0 0 0.0 0 +chr5 57971892 0 0 0.0 0 +chr5 58126302 0 0 0.0 0 +chr5 58524487 0 0 0.0 0 +chr5 58606765 0 0 0.0 0 +chr5 58647845 0 0 0.0 0 +chr5 58649269 0 0 0.0 0 +chr5 58667055 0 0 0.0 0 +chr5 58775853 0 0 0.0 0 +chr5 58786564 0 0 0.0 0 +chr5 58898038 0 0 0.0 0 +chr5 58903862 0 0 0.0 0 +chr5 58916243 0 0 0.0 0 +chr5 58948354 0 0 0.0 0 +chr5 59062020 0 0 0.0 0 +chr5 59236322 0 0 0.0 0 +chr5 59330336 0 0 0.0 0 +chr5 60001159 0 0 0.0 0 +chr5 60222230 0 0 0.0 0 +chr5 60336592 0 0 0.0 0 +chr5 60351269 0 0 0.0 0 +chr5 60729243 0 0 0.0 0 +chr5 60838377 0 0 0.0 0 +chr5 60965983 0 0 0.0 0 +chr5 61013375 0 0 0.0 0 +chr5 61156623 0 0 0.0 0 +chr5 61214564 0 0 0.0 0 +chr5 61262174 0 0 0.0 0 +chr5 61275463 0 0 0.0 0 +chr5 61280974 0 0 0.0 0 +chr5 61307935 0 0 0.0 0 +chr5 61390735 0 0 0.0 0 +chr5 61485711 0 0 0.0 0 +chr5 61590679 0 0 0.0 0 +chr5 61645065 0 0 0.0 0 +chr5 61685604 0 0 0.0 0 +chr5 61727003 0 0 0.0 0 +chr5 61756682 0 0 0.0 0 +chr5 61764958 0 0 0.0 0 +chr5 61798689 0 0 0.0 0 +chr5 61813365 0 0 0.0 0 +chr5 61847395 0 0 0.0 0 +chr5 62008946 0 0 0.0 0 +chr5 62051486 0 0 0.0 0 +chr5 62124734 0 0 0.0 0 +chr5 62195794 0 0 0.0 0 +chr5 62342318 0 0 0.0 0 +chr5 62418956 0 0 0.0 0 +chr5 62523605 0 0 0.0 0 +chr5 62628414 0 0 0.0 0 +chr5 62774485 0 0 0.0 0 +chr5 62941471 0 0 0.0 0 +chr5 63112171 0 0 0.0 0 +chr5 63304783 0 0 0.0 0 +chr5 63358514 0 0 0.0 0 +chr5 63373432 0 0 0.0 0 +chr5 63444249 0 0 0.0 0 +chr5 63954110 0 0 0.0 0 +chr5 64227919 0 0 0.0 0 +chr5 64243377 0 0 0.0 0 +chr5 64258701 0 0 0.0 0 +chr5 64407286 0 0 0.0 0 +chr5 64544432 0 0 0.0 0 +chr5 64765893 0 0 0.0 0 +chr5 65100931 0 1 0.0204 0 +chr5 65487994 0 0 0.0 0 +chr5 65720585 0 0 0.0 0 +chr5 65852676 0 0 0.0 0 +chr5 66008853 0 0 0.0 0 +chr5 66038476 0 0 0.0 0 +chr5 66100985 0 0 0.0 0 +chr5 66123203 0 0 0.0 0 +chr5 66302645 0 0 0.0 0 +chr5 66524364 0 0 0.0 0 +chr5 66604301 0 0 0.0 0 +chr5 66728310 0 0 0.0 0 +chr5 66882820 0 0 0.0 0 +chr5 66945890 0 0 0.0 0 +chr5 66973662 0 0 0.0 0 +chr5 67030465 0 0 0.0 0 +chr5 67064707 0 0 0.0 0 +chr5 67439325 0 0 0.0 0 +chr5 67481244 0 0 0.0 0 +chr5 67501382 0 0 0.0 0 +chr5 67603606 0 0 0.0 0 +chr5 67844819 0 0 0.0 0 +chr5 67859336 0 0 0.0 0 +chr5 67953846 0 0 0.0 0 +chr5 67981580 0 0 0.0 0 +chr5 68004919 0 0 0.0 0 +chr5 68033318 0 0 0.0 0 +chr5 68074254 0 0 0.0 0 +chr5 68349772 0 0 0.0 0 +chr5 68469563 0 0 0.0 0 +chr5 68489196 0 0 0.0 0 +chr5 68518554 0 0 0.0 0 +chr5 68523926 0 0 0.0 0 +chr5 68549838 0 0 0.0 0 +chr5 68584858 0 0 0.0 0 +chr5 68680732 0 0 0.0 0 +chr5 68713037 0 0 0.0 0 +chr5 68713758 0 0 0.0 0 +chr5 68714174 0 0 0.0 0 +chr5 68827258 0 0 0.0 0 +chr5 68913501 0 0 0.0 0 +chr5 69278179 1 56 0.6914 1 +chr5 69313496 0 0 0.0 0 +chr5 69459941 0 0 0.0 0 +chr5 69468872 0 0 0.0 0 +chr5 69527892 0 0 0.0 0 +chr5 69546253 0 0 0.0 0 +chr5 69749750 0 0 0.0 0 +chr5 69805514 0 0 0.0 0 +chr5 69919342 0 0 0.0 0 +chr5 69920038 0 0 0.0 0 +chr5 70198085 0 0 0.0 0 +chr5 70198781 0 0 0.0 0 +chr5 70329693 0 0 0.0 0 +chr5 70625062 0 0 0.0 0 +chr5 70680409 0 0 0.0 0 +chr5 70794390 0 0 0.0 0 +chr5 70795086 0 0 0.0 0 +chr5 71081644 0 0 0.0 0 +chr5 71127399 0 0 0.0 0 +chr5 71198476 0 0 0.0 0 +chr5 71199172 0 0 0.0 0 +chr5 71319212 0 0 0.0 0 +chr5 71329009 0 0 0.0 0 +chr5 71786469 0 0 0.0 0 +chr5 71808240 0 0 0.0 0 +chr5 71843230 0 0 0.0 0 +chr5 71906906 0 0 0.0 0 +chr5 71916221 0 0 0.0 0 +chr5 71967031 0 0 0.0 0 +chr5 72039960 0 0 0.0 0 +chr5 72229692 0 0 0.0 0 +chr5 72251131 0 0 0.0 0 +chr5 72320073 0 0 0.0 0 +chr5 72356269 0 0 0.0 0 +chr5 72620311 0 0 0.0 0 +chr5 72739262 0 0 0.0 0 +chr5 72754696 0 0 0.0 0 +chr5 72791666 0 0 0.0 0 +chr5 72795673 0 0 0.0 0 +chr5 72808900 0 0 0.0 0 +chr5 73034346 0 0 0.0 0 +chr5 73125927 0 0 0.0 0 +chr5 73128607 0 0 0.0 0 +chr5 73193867 0 0 0.0 0 +chr5 73239495 0 0 0.0 0 +chr5 73259355 0 0 0.0 0 +chr5 73278500 0 0 0.0 0 +chr5 73404865 0 0 0.0 0 +chr5 73583974 0 0 0.0 0 +chr5 73666157 0 1 0.0156 0 +chr5 73925627 0 0 0.0 0 +chr5 73928080 0 0 0.0 0 +chr5 74038362 0 0 0.0 0 +chr5 74276010 0 0 0.0 0 +chr5 74323867 0 0 0.0 0 +chr5 74337730 0 0 0.0 0 +chr5 74480166 0 1 0.012 0 +chr5 74513688 0 0 0.0 0 +chr5 74587662 0 0 0.0 0 +chr5 74726238 0 0 0.0 0 +chr5 74861947 0 0 0.0 0 +chr5 74916532 0 0 0.0 0 +chr5 75293114 0 0 0.0 0 +chr5 75306139 0 0 0.0 0 +chr5 75314488 0 0 0.0 0 +chr5 75479905 0 0 0.0 0 +chr5 75566236 0 0 0.0 0 +chr5 75582322 0 0 0.0 0 +chr5 75617117 0 0 0.0 0 +chr5 75774833 0 0 0.0 0 +chr5 75831831 0 0 0.0 0 +chr5 75917164 0 0 0.0 0 +chr5 75963068 0 0 0.0 0 +chr5 75968053 0 0 0.0 0 +chr5 76074035 0 0 0.0 0 +chr5 76074306 0 0 0.0 0 +chr5 76082295 0 0 0.0 0 +chr5 76155120 0 0 0.0 0 +chr5 76188832 0 0 0.0 0 +chr5 76349041 0 0 0.0 0 +chr5 76612468 0 0 0.0 0 +chr5 76711588 0 0 0.0 0 +chr5 76940728 0 0 0.0 0 +chr5 77134811 0 0 0.0 0 +chr5 77279861 0 0 0.0 0 +chr5 77338064 0 0 0.0 0 +chr5 77518309 0 0 0.0 0 +chr5 77537944 0 0 0.0 0 +chr5 77629274 0 0 0.0 0 +chr5 77708091 0 0 0.0 0 +chr5 77790178 0 0 0.0 0 +chr5 77803397 0 0 0.0 0 +chr5 77913916 0 1 0.0222 0 +chr5 77927667 0 0 0.0 0 +chr5 77970853 0 0 0.0 0 +chr5 77972569 0 0 0.0 0 +chr5 77988138 0 0 0.0 0 +chr5 78165215 0 1 0.0172 0 +chr5 78174499 0 0 0.0 0 +chr5 78242346 0 0 0.0 0 +chr5 78261556 0 0 0.0 0 +chr5 78354384 0 0 0.0 0 +chr5 78418235 0 0 0.0 0 +chr5 78495496 0 0 0.0 0 +chr5 78509806 0 0 0.0 0 +chr5 78517301 0 0 0.0 0 +chr5 78778991 0 0 0.0 0 +chr5 78847250 0 0 0.0 0 +chr5 79005241 0 0 0.0 0 +chr5 79021500 0 0 0.0 0 +chr5 79186881 0 0 0.0 0 +chr5 79215625 0 0 0.0 0 +chr5 79261980 0 0 0.0 0 +chr5 79286966 0 0 0.0 0 +chr5 79289209 1 18 0.375 1 +chr5 79294539 0 0 0.0 0 +chr5 79806943 0 0 0.0 0 +chr5 79812628 0 0 0.0 0 +chr5 79853854 0 0 0.0 0 +chr5 79888636 0 0 0.0 0 +chr5 79927476 0 0 0.0 0 +chr5 79952311 0 0 0.0 0 +chr5 79990137 0 0 0.0 0 +chr5 80070449 0 0 0.0 0 +chr5 80083391 0 0 0.0 0 +chr5 80178788 1 69 0.7841 1 +chr5 80181026 0 0 0.0 0 +chr5 80184441 0 0 0.0 0 +chr5 80351976 0 0 0.0 0 +chr5 80435430 0 0 0.0 0 +chr5 80456019 0 0 0.0 0 +chr5 80615611 0 0 0.0 0 +chr5 80648769 0 0 0.0 0 +chr5 80655453 0 0 0.0 0 +chr5 80711217 0 1 0.0256 0 +chr5 80752485 0 0 0.0 0 +chr5 80894527 0 0 0.0 0 +chr5 81027893 0 0 0.0 0 +chr5 81087266 0 0 0.0 0 +chr5 81128644 0 0 0.0 0 +chr5 81132634 0 0 0.0 0 +chr5 81243130 0 0 0.0 0 +chr5 81680125 0 0 0.0 0 +chr5 81950797 0 0 0.0 0 +chr5 81961593 0 0 0.0 0 +chr5 81987609 0 0 0.0 0 +chr5 82039212 0 0 0.0 0 +chr5 82083704 0 0 0.0 0 +chr5 82114241 0 0 0.0 0 +chr5 82493236 0 0 0.0 0 +chr5 82554155 0 0 0.0 0 +chr5 82878246 0 0 0.0 0 +chr5 82991749 0 0 0.0 0 +chr5 83115354 0 0 0.0 0 +chr5 83342680 0 0 0.0 0 +chr5 83343965 0 0 0.0 0 +chr5 83480757 0 0 0.0 0 +chr5 83619586 0 0 0.0 0 +chr5 83644637 0 0 0.0 0 +chr5 83833221 0 0 0.0 0 +chr5 84031205 0 0 0.0 0 +chr5 84218734 0 0 0.0 0 +chr5 84722751 0 1 0.0192 0 +chr5 84918784 0 0 0.0 0 +chr5 85352051 0 0 0.0 0 +chr5 85548562 0 0 0.0 0 +chr5 85857843 0 0 0.0 0 +chr5 86161846 0 0 0.0 0 +chr5 86291662 0 0 0.0 0 +chr5 86367028 0 0 0.0 0 +chr5 86492270 0 0 0.0 0 +chr5 86505723 0 0 0.0 0 +chr5 86592752 0 0 0.0 0 +chr5 86777635 0 0 0.0 0 +chr5 86796153 0 0 0.0 0 +chr5 86883488 0 0 0.0 0 +chr5 86980107 0 0 0.0 0 +chr5 87085287 0 0 0.0 0 +chr5 87182580 0 0 0.0 0 +chr5 87277159 0 0 0.0 0 +chr5 87295106 0 0 0.0 0 +chr5 87510900 0 0 0.0 0 +chr5 87524629 0 0 0.0 0 +chr5 87567397 0 0 0.0 0 +chr5 87800727 0 0 0.0 0 +chr5 87860494 0 0 0.0 0 +chr5 87924277 0 0 0.0 0 +chr5 87933091 0 0 0.0 0 +chr5 88014982 0 0 0.0 0 +chr5 88046332 0 0 0.0 0 +chr5 88271285 0 0 0.0 0 +chr5 88494444 0 0 0.0 0 +chr5 88628395 0 0 0.0 0 +chr5 88792988 0 0 0.0 0 +chr5 89011027 0 0 0.0 0 +chr5 89012678 0 0 0.0 0 +chr5 89125975 0 0 0.0 0 +chr5 89341791 0 0 0.0 0 +chr5 89698365 0 0 0.0 0 +chr5 89865167 0 0 0.0 0 +chr5 89885475 0 0 0.0 0 +chr5 90330162 0 0 0.0 0 +chr5 90358057 0 0 0.0 0 +chr5 90481917 0 0 0.0 0 +chr5 90618184 0 0 0.0 0 +chr5 90795294 0 0 0.0 0 +chr5 90803749 0 2 0.0357 0 +chr5 90899512 0 0 0.0 0 +chr5 91009205 0 0 0.0 0 +chr5 91060559 0 0 0.0 0 +chr5 91143392 0 0 0.0 0 +chr5 91216266 0 0 0.0 0 +chr5 91233503 0 0 0.0 0 +chr5 91246184 0 0 0.0 0 +chr5 91288806 0 0 0.0 0 +chr5 91301745 0 0 0.0 0 +chr5 91396902 0 0 0.0 0 +chr5 91437596 0 0 0.0 0 +chr5 91882616 0 0 0.0 0 +chr5 92055603 0 1 0.0333 0 +chr5 92370225 0 0 0.0 0 +chr5 92420388 0 0 0.0 0 +chr5 92469760 0 0 0.0 0 +chr5 92488410 0 0 0.0 0 +chr5 92591702 0 0 0.0 0 +chr5 92643595 0 0 0.0 0 +chr5 92971792 0 0 0.0 0 +chr5 93037766 0 0 0.0 0 +chr5 93205811 0 0 0.0 0 +chr5 93249461 0 0 0.0 0 +chr5 93350940 0 0 0.0 0 +chr5 93395675 0 0 0.0 0 +chr5 93422066 0 0 0.0 0 +chr5 93458167 0 0 0.0 0 +chr5 93478123 0 0 0.0 0 +chr5 93523141 0 0 0.0 0 +chr5 93690346 0 0 0.0 0 +chr5 94036505 0 0 0.0 0 +chr5 94106065 0 0 0.0 0 +chr5 94107842 0 0 0.0 0 +chr5 94120581 0 0 0.0 0 +chr5 94406545 0 0 0.0 0 +chr5 94406630 0 0 0.0 0 +chr5 94486382 0 0 0.0 0 +chr5 94529838 0 0 0.0 0 +chr5 94899681 0 0 0.0 0 +chr5 95087340 0 0 0.0 0 +chr5 95190282 0 0 0.0 0 +chr5 95303294 0 0 0.0 0 +chr5 95345558 0 0 0.0 0 +chr5 95651529 0 0 0.0 0 +chr5 95744961 0 0 0.0 0 +chr5 95807110 0 0 0.0 0 +chr5 95808455 0 1 0.0182 0 +chr5 95882090 0 0 0.0 0 +chr5 95941639 0 0 0.0 0 +chr5 96032906 0 0 0.0 0 +chr5 96384654 0 0 0.0 0 +chr5 96445322 0 0 0.0 0 +chr5 96499546 0 0 0.0 0 +chr5 96549816 0 0 0.0 0 +chr5 96718902 0 0 0.0 0 +chr5 96754405 0 0 0.0 0 +chr5 96757735 0 0 0.0 0 +chr5 96877715 1 47 0.8393 1 +chr5 96885379 0 0 0.0 0 +chr5 97102464 0 0 0.0 0 +chr5 97263765 0 0 0.0 0 +chr5 97319060 0 0 0.0 0 +chr5 97460811 0 0 0.0 0 +chr5 97601050 0 0 0.0 0 +chr5 97651079 0 0 0.0 0 +chr5 97689369 0 0 0.0 0 +chr5 97728230 0 0 0.0 0 +chr5 97849860 0 0 0.0 0 +chr5 97860572 0 0 0.0 0 +chr5 97921362 0 0 0.0 0 +chr5 98079870 0 0 0.0 0 +chr5 98601072 0 0 0.0 0 +chr5 98640951 0 0 0.0 0 +chr5 98681029 0 0 0.0 0 +chr5 99028112 0 0 0.0 0 +chr5 99273659 0 0 0.0 0 +chr5 99474279 0 0 0.0 0 +chr5 99718871 0 0 0.0 0 +chr5 99783619 0 0 0.0 0 +chr5 99821636 0 0 0.0 0 +chr5 99928591 0 0 0.0 0 +chr5 100100916 0 0 0.0 0 +chr5 100112156 0 0 0.0 0 +chr5 100216750 0 0 0.0 0 +chr5 100801677 0 0 0.0 0 +chr5 101128075 0 0 0.0 0 +chr5 101271703 0 0 0.0 0 +chr5 101387561 0 0 0.0 0 +chr5 101535193 0 0 0.0 0 +chr5 101635336 0 1 0.02 0 +chr5 101667665 0 0 0.0 0 +chr5 101715208 0 0 0.0 0 +chr5 101798609 0 0 0.0 0 +chr5 101874629 0 0 0.0 0 +chr5 101903708 0 0 0.0 0 +chr5 101914574 0 0 0.0 0 +chr5 102013579 0 0 0.0 0 +chr5 102138278 0 0 0.0 0 +chr5 102410157 0 0 0.0 0 +chr5 102452928 0 0 0.0 0 +chr5 102569588 0 0 0.0 0 +chr5 102579278 0 0 0.0 0 +chr5 102660180 0 0 0.0 0 +chr5 102682703 0 0 0.0 0 +chr5 102812023 0 0 0.0 0 +chr5 102903304 0 0 0.0 0 +chr5 102963175 0 0 0.0 0 +chr5 102966619 0 0 0.0 0 +chr5 102997915 0 0 0.0 0 +chr5 103026868 0 0 0.0 0 +chr5 103313588 0 0 0.0 0 +chr5 103388518 0 0 0.0 0 +chr5 103476374 0 0 0.0 0 +chr5 103713622 0 0 0.0 0 +chr5 103837978 0 0 0.0 0 +chr5 103858538 0 0 0.0 0 +chr5 103884420 0 0 0.0 0 +chr5 103924327 0 0 0.0 0 +chr5 104019583 0 0 0.0 0 +chr5 104093013 0 0 0.0 0 +chr5 104104401 0 0 0.0 0 +chr5 104235529 0 0 0.0 0 +chr5 104681138 0 1 0.0133 0 +chr5 104771659 0 0 0.0 0 +chr5 104964160 0 1 0.0227 0 +chr5 105016640 0 0 0.0 0 +chr5 105650073 0 0 0.0 0 +chr5 105795330 0 0 0.0 0 +chr5 106004742 0 0 0.0 0 +chr5 106206102 0 0 0.0 0 +chr5 106278876 0 0 0.0 0 +chr5 106380364 0 0 0.0 0 +chr5 106381029 0 0 0.0 0 +chr5 106436298 0 0 0.0 0 +chr5 106488718 0 0 0.0 0 +chr5 106490384 0 0 0.0 0 +chr5 106726353 0 0 0.0 0 +chr5 106904808 0 0 0.0 0 +chr5 106926753 0 0 0.0 0 +chr5 107224016 0 0 0.0 0 +chr5 107290020 0 0 0.0 0 +chr5 107290287 0 0 0.0 0 +chr5 107417279 0 0 0.0 0 +chr5 107487595 0 0 0.0 0 +chr5 107781911 0 0 0.0 0 +chr5 107858607 0 0 0.0 0 +chr5 107863904 0 0 0.0 0 +chr5 107869162 0 0 0.0 0 +chr5 107950757 0 0 0.0 0 +chr5 108399630 0 0 0.0 0 +chr5 108510794 0 0 0.0 0 +chr5 108579950 0 0 0.0 0 +chr5 108749435 0 0 0.0 0 +chr5 108912695 0 0 0.0 0 +chr5 109088782 0 0 0.0 0 +chr5 109138830 0 0 0.0 0 +chr5 109165280 0 0 0.0 0 +chr5 109185138 0 0 0.0 0 +chr5 109289883 0 0 0.0 0 +chr5 109337994 0 0 0.0 0 +chr5 109405639 0 0 0.0 0 +chr5 109527960 0 0 0.0 0 +chr5 109737731 0 0 0.0 0 +chr5 109781247 0 0 0.0 0 +chr5 109831150 0 0 0.0 0 +chr5 109986200 0 0 0.0 0 +chr5 110199549 0 0 0.0 0 +chr5 110310170 0 0 0.0 0 +chr5 110363223 0 0 0.0 0 +chr5 110399283 0 0 0.0 0 +chr5 110412103 0 0 0.0 0 +chr5 110598860 0 0 0.0 0 +chr5 110672426 0 1 0.0196 0 +chr5 110693185 0 0 0.0 0 +chr5 110788075 0 0 0.0 0 +chr5 110843967 0 0 0.0 0 +chr5 110882542 0 0 0.0 0 +chr5 110909401 0 0 0.0 0 +chr5 111078987 0 1 0.02 0 +chr5 111801921 0 0 0.0 0 +chr5 111926853 0 0 0.0 0 +chr5 112144852 0 0 0.0 0 +chr5 112181377 0 1 0.0222 0 +chr5 112273854 0 0 0.0 0 +chr5 112279398 0 0 0.0 0 +chr5 112285992 0 0 0.0 0 +chr5 112479113 0 0 0.0 0 +chr5 112482541 0 0 0.0 0 +chr5 112513220 0 1 0.0169 0 +chr5 112539246 0 0 0.0 0 +chr5 112546419 0 0 0.0 0 +chr5 112616919 0 0 0.0 0 +chr5 112626801 0 0 0.0 0 +chr5 112772480 0 0 0.0 0 +chr5 112931700 0 0 0.0 0 +chr5 112963339 0 0 0.0 0 +chr5 113170881 0 0 0.0 0 +chr5 113288068 0 0 0.0 0 +chr5 113293385 0 0 0.0 0 +chr5 113433351 0 0 0.0 0 +chr5 113437009 0 0 0.0 0 +chr5 113519588 0 0 0.0 0 +chr5 113693669 0 0 0.0 0 +chr5 113736329 0 0 0.0 0 +chr5 113745795 0 0 0.0 0 +chr5 113785492 0 0 0.0 0 +chr5 113872602 0 0 0.0 0 +chr5 113938043 0 0 0.0 0 +chr5 113940830 0 0 0.0 0 +chr5 113981106 0 0 0.0 0 +chr5 113998989 0 0 0.0 0 +chr5 114090965 0 0 0.0 0 +chr5 114145051 0 0 0.0 0 +chr5 114219050 0 0 0.0 0 +chr5 114321092 0 1 0.0256 0 +chr5 114354566 0 0 0.0 0 +chr5 114374764 0 0 0.0 0 +chr5 114440617 0 0 0.0 0 +chr5 114490262 0 0 0.0 0 +chr5 114534073 0 0 0.0 0 +chr5 114598868 0 0 0.0 0 +chr5 114609420 0 0 0.0 0 +chr5 114834359 0 0 0.0 0 +chr5 114894669 0 0 0.0 0 +chr5 114993931 0 0 0.0 0 +chr5 115000110 0 0 0.0 0 +chr5 115118457 0 0 0.0 0 +chr5 115202422 0 0 0.0 0 +chr5 115299650 0 0 0.0 0 +chr5 115393508 0 0 0.0 0 +chr5 115409362 0 0 0.0 0 +chr5 115551772 0 0 0.0 0 +chr5 115624103 0 0 0.0 0 +chr5 115709222 0 0 0.0 0 +chr5 115978813 0 0 0.0 0 +chr5 115981376 0 0 0.0 0 +chr5 116033849 0 0 0.0 0 +chr5 116034527 0 0 0.0 0 +chr5 116180910 0 0 0.0 0 +chr5 116322722 0 0 0.0 0 +chr5 116423363 0 0 0.0 0 +chr5 116591337 0 0 0.0 0 +chr5 116854782 0 0 0.0 0 +chr5 116884905 0 0 0.0 0 +chr5 116978811 0 0 0.0 0 +chr5 116992184 0 0 0.0 0 +chr5 117044599 0 0 0.0 0 +chr5 117065236 0 0 0.0 0 +chr5 117270765 0 0 0.0 0 +chr5 117438134 0 0 0.0 0 +chr5 117639518 0 0 0.0 0 +chr5 117658635 0 0 0.0 0 +chr5 117666253 0 0 0.0 0 +chr5 117939896 0 0 0.0 0 +chr5 118463841 0 0 0.0 0 +chr5 118480930 0 0 0.0 0 +chr5 118520264 1 19 0.3393 1 +chr5 118701395 0 0 0.0 0 +chr5 118786098 0 0 0.0 0 +chr5 118858867 0 0 0.0 0 +chr5 118889620 0 0 0.0 0 +chr5 118987104 0 0 0.0 0 +chr5 119085878 0 0 0.0 0 +chr5 119231566 0 0 0.0 0 +chr5 119266885 0 0 0.0 0 +chr5 119330036 0 0 0.0 0 +chr5 119344269 0 1 0.0175 0 +chr5 119377449 0 0 0.0 0 +chr5 119393122 0 0 0.0 0 +chr5 119497299 0 0 0.0 0 +chr5 119679563 0 0 0.0 0 +chr5 119952192 0 0 0.0 0 +chr5 120023346 0 0 0.0 0 +chr5 120040831 0 0 0.0 0 +chr5 120275507 0 0 0.0 0 +chr5 120326057 0 0 0.0 0 +chr5 120351052 0 0 0.0 0 +chr5 120576801 0 0 0.0 0 +chr5 120857122 0 0 0.0 0 +chr5 120885761 0 0 0.0 0 +chr5 121047252 0 0 0.0 0 +chr5 121263423 0 0 0.0 0 +chr5 121603001 0 0 0.0 0 +chr5 121681312 0 0 0.0 0 +chr5 121756020 0 0 0.0 0 +chr5 121860393 0 0 0.0 0 +chr5 122093152 0 0 0.0 0 +chr5 122190352 0 0 0.0 0 +chr5 122616809 0 0 0.0 0 +chr5 123299357 0 0 0.0 0 +chr5 123383755 0 0 0.0 0 +chr5 123402942 0 0 0.0 0 +chr5 123488625 0 0 0.0 0 +chr5 123674487 0 0 0.0 0 +chr5 123725382 0 0 0.0 0 +chr5 123854730 0 0 0.0 0 +chr5 123920517 0 0 0.0 0 +chr5 124027396 0 0 0.0 0 +chr5 124151813 0 0 0.0 0 +chr5 124173590 0 0 0.0 0 +chr5 124257055 0 0 0.0 0 +chr5 124441118 0 0 0.0 0 +chr5 124642528 0 0 0.0 0 +chr5 124699806 0 0 0.0 0 +chr5 124932826 0 0 0.0 0 +chr5 125003861 1 13 0.1884 1 +chr5 125091540 0 0 0.0 0 +chr5 125106794 0 0 0.0 0 +chr5 125201282 0 0 0.0 0 +chr5 125288983 0 0 0.0 0 +chr5 125441269 0 0 0.0 0 +chr5 125463593 0 0 0.0 0 +chr5 125543303 0 0 0.0 0 +chr5 125880530 0 0 0.0 0 +chr5 126044559 0 0 0.0 0 +chr5 126223716 0 0 0.0 0 +chr5 126336761 0 0 0.0 0 +chr5 126648345 0 0 0.0 0 +chr5 126728646 0 0 0.0 0 +chr5 126800209 0 0 0.0 0 +chr5 126820939 0 0 0.0 0 +chr5 126973187 0 0 0.0 0 +chr5 127136147 0 0 0.0 0 +chr5 127302568 0 0 0.0 0 +chr5 127611243 0 0 0.0 0 +chr5 127658157 0 0 0.0 0 +chr5 127679202 0 0 0.0 0 +chr5 127865748 0 0 0.0 0 +chr5 127873798 0 0 0.0 0 +chr5 127968159 0 0 0.0 0 +chr5 127992471 0 0 0.0 0 +chr5 128096862 0 0 0.0 0 +chr5 128181561 0 0 0.0 0 +chr5 128195151 0 0 0.0 0 +chr5 128731727 0 0 0.0 0 +chr5 128798184 0 0 0.0 0 +chr5 129008720 0 0 0.0 0 +chr5 129203515 0 0 0.0 0 +chr5 129244428 0 0 0.0 0 +chr5 129250233 0 0 0.0 0 +chr5 129331954 0 0 0.0 0 +chr5 129458242 0 0 0.0 0 +chr5 129584768 0 0 0.0 0 +chr5 129751441 0 0 0.0 0 +chr5 129771321 0 0 0.0 0 +chr5 129803583 0 0 0.0 0 +chr5 129816530 0 0 0.0 0 +chr5 129826557 0 0 0.0 0 +chr5 129930510 2 6 0.3 1 +chr5 129964974 0 0 0.0 0 +chr5 130006600 0 0 0.0 0 +chr5 130017001 0 0 0.0 0 +chr5 130074332 0 0 0.0 0 +chr5 130293123 0 0 0.0 0 +chr5 130686998 0 0 0.0 0 +chr5 130841630 0 0 0.0 0 +chr5 130894097 0 0 0.0 0 +chr5 130925010 0 0 0.0 0 +chr5 131149013 0 0 0.0 0 +chr5 131222762 0 0 0.0 0 +chr5 131352820 0 0 0.0 0 +chr5 131364915 0 0 0.0 0 +chr5 131451237 0 0 0.0 0 +chr5 131688774 0 0 0.0 0 +chr5 131712847 0 0 0.0 0 +chr5 131765802 0 0 0.0 0 +chr5 131776255 0 0 0.0 0 +chr5 132003025 0 0 0.0 0 +chr5 132003724 0 0 0.0 0 +chr5 132066664 0 0 0.0 0 +chr5 132077969 0 0 0.0 0 +chr5 132156737 0 0 0.0 0 +chr5 132165845 0 0 0.0 0 +chr5 132272130 0 0 0.0 0 +chr5 132281693 0 0 0.0 0 +chr5 132452479 0 0 0.0 0 +chr5 132666622 0 0 0.0 0 +chr5 132754773 0 0 0.0 0 +chr5 132785613 0 0 0.0 0 +chr5 133115230 0 0 0.0 0 +chr5 133248951 0 0 0.0 0 +chr5 133309493 0 0 0.0 0 +chr5 133366614 0 0 0.0 0 +chr5 133381925 0 0 0.0 0 +chr5 133447075 0 0 0.0 0 +chr5 133489554 0 0 0.0 0 +chr5 133499098 0 0 0.0 0 +chr5 133581429 0 0 0.0 0 +chr5 133590523 0 0 0.0 0 +chr5 133667245 1 70 0.8642 1 +chr5 133727046 0 0 0.0 0 +chr5 133813099 0 0 0.0 0 +chr5 133815195 0 0 0.0 0 +chr5 133847100 0 0 0.0 0 +chr5 133893564 0 0 0.0 0 +chr5 133908124 0 0 0.0 0 +chr5 133992955 0 0 0.0 0 +chr5 134039889 0 0 0.0 0 +chr5 134053650 0 0 0.0 0 +chr5 134090806 0 1 0.0172 0 +chr5 134097518 0 0 0.0 0 +chr5 134179037 0 0 0.0 0 +chr5 134320468 0 0 0.0 0 +chr5 134438001 0 0 0.0 0 +chr5 134462453 0 0 0.0 0 +chr5 134559268 0 0 0.0 0 +chr5 134572175 0 0 0.0 0 +chr5 135103411 0 0 0.0 0 +chr5 135169705 0 0 0.0 0 +chr5 135215912 0 0 0.0 0 +chr5 135295071 0 0 0.0 0 +chr5 135373808 0 0 0.0 0 +chr5 135401316 0 0 0.0 0 +chr5 135414492 0 0 0.0 0 +chr5 135487763 0 0 0.0 0 +chr5 135551822 0 0 0.0 0 +chr5 135575109 0 0 0.0 0 +chr5 135679254 0 0 0.0 0 +chr5 135691566 0 1 0.0169 0 +chr5 135867843 0 0 0.0 0 +chr5 135887634 0 0 0.0 0 +chr5 136073321 0 0 0.0 0 +chr5 136133520 0 0 0.0 0 +chr5 136270099 0 1 0.0217 0 +chr5 136311949 0 0 0.0 0 +chr5 136635092 0 0 0.0 0 +chr5 136725543 0 0 0.0 0 +chr5 136767391 0 0 0.0 0 +chr5 137028926 0 0 0.0 0 +chr5 137409100 0 0 0.0 0 +chr5 137410584 0 0 0.0 0 +chr5 137433423 0 0 0.0 0 +chr5 137637432 0 0 0.0 0 +chr5 137642751 0 0 0.0 0 +chr5 137746852 0 0 0.0 0 +chr5 137801107 0 0 0.0 0 +chr5 138127207 0 0 0.0 0 +chr5 138289610 0 0 0.0 0 +chr5 138440305 0 1 0.0159 0 +chr5 138451033 0 0 0.0 0 +chr5 138614976 0 0 0.0 0 +chr5 138636783 0 0 0.0 0 +chr5 138702538 0 0 0.0 0 +chr5 138757498 0 0 0.0 0 +chr5 138870127 0 0 0.0 0 +chr5 138894725 0 0 0.0 0 +chr5 138932371 0 0 0.0 0 +chr5 139163596 0 0 0.0 0 +chr5 139175521 0 0 0.0 0 +chr5 139200099 0 0 0.0 0 +chr5 139258068 0 0 0.0 0 +chr5 139307483 0 0 0.0 0 +chr5 139364164 0 0 0.0 0 +chr5 139374627 0 0 0.0 0 +chr5 139461486 0 0 0.0 0 +chr5 139486324 0 0 0.0 0 +chr5 139558381 0 0 0.0 0 +chr5 139788653 0 0 0.0 0 +chr5 139908827 0 0 0.0 0 +chr5 139909524 0 0 0.0 0 +chr5 140011635 0 0 0.0 0 +chr5 140131103 0 0 0.0 0 +chr5 140157464 0 0 0.0 0 +chr5 140190726 0 0 0.0 0 +chr5 140313159 0 0 0.0 0 +chr5 140506135 0 0 0.0 0 +chr5 140629981 0 0 0.0 0 +chr5 140705781 0 1 0.0169 0 +chr5 140721540 0 0 0.0 0 +chr5 140728614 0 0 0.0 0 +chr5 140729587 0 0 0.0 0 +chr5 140742273 0 0 0.0 0 +chr5 140881248 0 0 0.0 0 +chr5 140958162 0 0 0.0 0 +chr5 141176365 0 0 0.0 0 +chr5 141213733 0 1 0.025 0 +chr5 141396211 0 0 0.0 0 +chr5 141399083 0 0 0.0 0 +chr5 141563877 0 0 0.0 0 +chr5 141567234 0 0 0.0 0 +chr5 141632720 0 0 0.0 0 +chr5 141735889 0 0 0.0 0 +chr5 141815121 0 0 0.0 0 +chr5 141929569 0 0 0.0 0 +chr5 141971909 0 0 0.0 0 +chr5 141991586 0 0 0.0 0 +chr5 142079070 0 0 0.0 0 +chr5 142187291 0 0 0.0 0 +chr5 142263442 0 0 0.0 0 +chr5 142320064 0 0 0.0 0 +chr5 142426415 0 0 0.0 0 +chr5 142530488 0 0 0.0 0 +chr5 142996693 0 0 0.0 0 +chr5 142998452 0 0 0.0 0 +chr5 143040248 0 0 0.0 0 +chr5 143044392 0 0 0.0 0 +chr5 143045696 0 0 0.0 0 +chr5 143274076 0 1 0.0118 0 +chr5 143310917 0 0 0.0 0 +chr5 143338860 0 0 0.0 0 +chr5 143426947 0 0 0.0 0 +chr5 143437679 0 0 0.0 0 +chr5 143490529 0 0 0.0 0 +chr5 143664825 0 0 0.0 0 +chr5 143677636 0 0 0.0 0 +chr5 143732542 0 0 0.0 0 +chr5 143842038 0 0 0.0 0 +chr5 143967804 0 1 0.0204 0 +chr5 144065963 0 0 0.0 0 +chr5 144092738 0 0 0.0 0 +chr5 144122433 0 0 0.0 0 +chr5 144229890 0 0 0.0 0 +chr5 144457916 0 0 0.0 0 +chr5 144487203 0 0 0.0 0 +chr5 144487518 0 0 0.0 0 +chr5 144549196 0 0 0.0 0 +chr5 144566551 0 0 0.0 0 +chr5 144750551 0 0 0.0 0 +chr5 145237060 0 0 0.0 0 +chr5 145333081 0 0 0.0 0 +chr5 145380177 0 0 0.0 0 +chr5 145484889 0 0 0.0 0 +chr5 145679582 0 0 0.0 0 +chr5 145743521 0 0 0.0 0 +chr5 145816284 0 0 0.0 0 +chr5 146046235 0 0 0.0 0 +chr5 146060638 0 0 0.0 0 +chr5 146095984 0 0 0.0 0 +chr5 146204776 0 0 0.0 0 +chr5 146232868 0 0 0.0 0 +chr5 146234121 0 0 0.0 0 +chr5 146376986 0 0 0.0 0 +chr5 146413637 0 0 0.0 0 +chr5 146477826 0 0 0.0 0 +chr5 146536144 0 0 0.0 0 +chr5 146922537 0 0 0.0 0 +chr5 147131010 0 0 0.0 0 +chr5 147142422 0 0 0.0 0 +chr5 147204604 0 0 0.0 0 +chr5 147211364 0 0 0.0 0 +chr5 147397707 0 0 0.0 0 +chr5 147592917 0 0 0.0 0 +chr5 148043464 0 0 0.0 0 +chr5 148051076 0 0 0.0 0 +chr5 148281154 0 0 0.0 0 +chr5 148502378 0 0 0.0 0 +chr5 148718055 0 0 0.0 0 +chr5 148828395 0 0 0.0 0 +chr5 148904815 0 0 0.0 0 +chr5 148924940 0 0 0.0 0 +chr5 149006144 0 0 0.0 0 +chr5 149033613 0 0 0.0 0 +chr5 149059562 0 0 0.0 0 +chr5 149093829 0 0 0.0 0 +chr5 149198450 0 0 0.0 0 +chr5 149204805 0 0 0.0 0 +chr5 149314196 0 0 0.0 0 +chr5 149678257 0 0 0.0 0 +chr5 149771874 0 0 0.0 0 +chr5 149772142 0 0 0.0 0 +chr5 149779053 0 0 0.0 0 +chr5 149818501 0 0 0.0 0 +chr5 149897403 0 0 0.0 0 +chr5 150016229 0 0 0.0 0 +chr5 150066041 0 0 0.0 0 +chr5 150166002 0 0 0.0 0 +chr5 150204693 0 0 0.0 0 +chr5 150217124 0 0 0.0 0 +chr5 150249284 0 0 0.0 0 +chr5 150256687 0 0 0.0 0 +chr5 150269027 0 0 0.0 0 +chr5 150269615 0 0 0.0 0 +chr5 150347577 0 0 0.0 0 +chr5 150410437 0 0 0.0 0 +chr5 150507170 0 0 0.0 0 +chr5 150580008 0 0 0.0 0 +chr5 150608426 0 0 0.0 0 +chr5 150636600 0 0 0.0 0 +chr5 150681992 0 0 0.0 0 +chr5 150779744 0 0 0.0 0 +chr5 150789217 0 0 0.0 0 +chr5 150836738 0 0 0.0 0 +chr5 150838707 0 0 0.0 0 +chr5 150870583 0 0 0.0 0 +chr5 150930961 0 0 0.0 0 +chr5 150974530 0 0 0.0 0 +chr5 151023363 0 0 0.0 0 +chr5 151087115 0 0 0.0 0 +chr5 151090815 0 0 0.0 0 +chr5 151173703 0 0 0.0 0 +chr5 151295010 0 0 0.0 0 +chr5 151349395 0 0 0.0 0 +chr5 151356692 0 0 0.0 0 +chr5 151414637 0 0 0.0 0 +chr5 151540321 0 0 0.0 0 +chr5 151592753 0 0 0.0 0 +chr5 151607587 0 0 0.0 0 +chr5 151688383 0 0 0.0 0 +chr5 151740290 1 63 0.9403 1 +chr5 152144413 0 0 0.0 0 +chr5 152166170 0 0 0.0 0 +chr5 152228256 0 0 0.0 0 +chr5 152405303 0 0 0.0 0 +chr5 152510250 0 1 0.0149 0 +chr5 152520456 0 0 0.0 0 +chr5 152885674 0 0 0.0 0 +chr5 152939146 0 0 0.0 0 +chr5 153095641 0 0 0.0 0 +chr5 153438502 0 0 0.0 0 +chr5 153453262 0 1 0.0208 0 +chr5 153517822 0 0 0.0 0 +chr5 153672913 0 0 0.0 0 +chr5 153704941 0 0 0.0 0 +chr5 153846940 0 0 0.0 0 +chr5 153880875 0 1 0.0161 0 +chr5 153917114 0 0 0.0 0 +chr5 154100339 0 0 0.0 0 +chr5 154196918 0 0 0.0 0 +chr5 154208867 0 0 0.0 0 +chr5 154270516 0 0 0.0 0 +chr5 154378802 0 0 0.0 0 +chr5 154506826 0 0 0.0 0 +chr5 154602455 0 0 0.0 0 +chr5 154627213 0 0 0.0 0 +chr5 154706052 0 0 0.0 0 +chr5 154733133 0 0 0.0 0 +chr5 154742053 0 0 0.0 0 +chr5 154818686 0 0 0.0 0 +chr5 154881176 0 0 0.0 0 +chr5 155004986 0 0 0.0 0 +chr5 155310471 0 0 0.0 0 +chr5 155694227 0 0 0.0 0 +chr5 156325222 0 0 0.0 0 +chr5 156370805 0 0 0.0 0 +chr5 156406353 0 0 0.0 0 +chr5 156423752 0 0 0.0 0 +chr5 156511678 0 0 0.0 0 +chr5 156613293 0 0 0.0 0 +chr5 156733309 0 0 0.0 0 +chr5 156806707 0 0 0.0 0 +chr5 156816091 0 0 0.0 0 +chr5 156821144 0 0 0.0 0 +chr5 156905941 0 0 0.0 0 +chr5 157063232 0 0 0.0 0 +chr5 157084371 0 0 0.0 0 +chr5 157089283 0 0 0.0 0 +chr5 157458352 0 0 0.0 0 +chr5 157486132 0 0 0.0 0 +chr5 157502590 0 0 0.0 0 +chr5 157539645 0 0 0.0 0 +chr5 157709367 0 0 0.0 0 +chr5 157756857 0 0 0.0 0 +chr5 157897107 0 0 0.0 0 +chr5 157918604 0 0 0.0 0 +chr5 157992794 0 0 0.0 0 +chr5 158016434 0 0 0.0 0 +chr5 158073354 0 0 0.0 0 +chr5 158209866 0 0 0.0 0 +chr5 158227248 0 0 0.0 0 +chr5 158276887 0 0 0.0 0 +chr5 158278369 0 0 0.0 0 +chr5 158291079 0 0 0.0 0 +chr5 158301152 0 0 0.0 0 +chr5 158422801 0 0 0.0 0 +chr5 158450127 0 0 0.0 0 +chr5 158595390 0 0 0.0 0 +chr5 158615158 0 0 0.0 0 +chr5 158670364 0 0 0.0 0 +chr5 158729899 0 0 0.0 0 +chr5 158842387 0 0 0.0 0 +chr5 158893563 0 1 0.0159 0 +chr5 158912365 0 0 0.0 0 +chr5 159062425 0 0 0.0 0 +chr5 159078486 0 0 0.0 0 +chr5 159103455 0 0 0.0 0 +chr5 159263655 0 0 0.0 0 +chr5 159377025 0 0 0.0 0 +chr5 159450162 0 0 0.0 0 +chr5 159456498 0 0 0.0 0 +chr5 159519280 0 0 0.0 0 +chr5 159525935 0 0 0.0 0 +chr5 159653522 0 0 0.0 0 +chr5 160127764 0 0 0.0 0 +chr5 160212415 0 0 0.0 0 +chr5 160213394 0 0 0.0 0 +chr5 160234864 0 0 0.0 0 +chr5 160262754 0 0 0.0 0 +chr5 160415577 0 0 0.0 0 +chr5 160505334 0 0 0.0 0 +chr5 160522869 0 0 0.0 0 +chr5 160583881 0 0 0.0 0 +chr5 160601129 0 0 0.0 0 +chr5 160630198 0 0 0.0 0 +chr5 160807139 0 0 0.0 0 +chr5 161008264 0 0 0.0 0 +chr5 161055365 0 0 0.0 0 +chr5 161093562 0 0 0.0 0 +chr5 161095470 0 0 0.0 0 +chr5 161107933 0 0 0.0 0 +chr5 161310011 0 0 0.0 0 +chr5 161892761 0 0 0.0 0 +chr5 161897711 0 0 0.0 0 +chr5 161926065 0 0 0.0 0 +chr5 161934661 0 0 0.0 0 +chr5 161992970 0 0 0.0 0 +chr5 162165461 0 0 0.0 0 +chr5 162364733 0 0 0.0 0 +chr5 162458404 0 0 0.0 0 +chr5 162686705 0 0 0.0 0 +chr5 162782892 0 0 0.0 0 +chr5 162915265 0 0 0.0 0 +chr5 163105135 0 0 0.0 0 +chr5 163283897 0 0 0.0 0 +chr5 163536127 0 0 0.0 0 +chr5 163554313 0 0 0.0 0 +chr5 163887461 0 0 0.0 0 +chr5 164204319 0 0 0.0 0 +chr5 164765669 0 0 0.0 0 +chr5 164808046 0 0 0.0 0 +chr5 164832201 0 0 0.0 0 +chr5 164969667 0 0 0.0 0 +chr5 165045728 0 0 0.0 0 +chr5 165089585 0 0 0.0 0 +chr5 165165215 0 0 0.0 0 +chr5 165176028 0 0 0.0 0 +chr5 165874006 0 0 0.0 0 +chr5 165932410 0 0 0.0 0 +chr5 165980812 0 0 0.0 0 +chr5 165998197 0 0 0.0 0 +chr5 166102695 0 0 0.0 0 +chr5 166194264 0 0 0.0 0 +chr5 166206743 0 0 0.0 0 +chr5 166352239 0 0 0.0 0 +chr5 166449839 0 0 0.0 0 +chr5 166489922 0 0 0.0 0 +chr5 166501316 0 0 0.0 0 +chr5 166575978 0 0 0.0 0 +chr5 166590428 0 0 0.0 0 +chr5 166620701 0 0 0.0 0 +chr5 166650091 0 0 0.0 0 +chr5 166706504 0 0 0.0 0 +chr5 166770243 0 0 0.0 0 +chr5 166772057 0 0 0.0 0 +chr5 166795240 0 0 0.0 0 +chr5 166829320 0 0 0.0 0 +chr5 166832713 0 0 0.0 0 +chr5 166863059 0 0 0.0 0 +chr5 166879027 0 0 0.0 0 +chr5 166884645 0 0 0.0 0 +chr5 167020860 0 0 0.0 0 +chr5 167381989 0 0 0.0 0 +chr5 167524754 0 0 0.0 0 +chr5 167748522 0 0 0.0 0 +chr5 167925925 0 0 0.0 0 +chr5 167933356 0 0 0.0 0 +chr5 167960568 0 0 0.0 0 +chr5 168009864 0 0 0.0 0 +chr5 168090296 0 0 0.0 0 +chr5 168098424 0 0 0.0 0 +chr5 168207614 0 0 0.0 0 +chr5 168311184 0 0 0.0 0 +chr5 168350494 0 0 0.0 0 +chr5 168592383 0 0 0.0 0 +chr5 168789682 0 0 0.0 0 +chr5 168805847 0 0 0.0 0 +chr5 168844407 0 0 0.0 0 +chr5 168897135 1 65 0.9848 1 +chr5 168934223 0 0 0.0 0 +chr5 169065441 0 0 0.0 0 +chr5 169120440 0 0 0.0 0 +chr5 169127015 0 0 0.0 0 +chr5 169153357 0 0 0.0 0 +chr5 169206134 0 0 0.0 0 +chr5 169213906 0 0 0.0 0 +chr5 169224495 0 0 0.0 0 +chr5 169276807 0 0 0.0 0 +chr5 169296516 0 0 0.0 0 +chr5 169322113 0 0 0.0 0 +chr5 169424175 0 0 0.0 0 +chr5 169801143 1 5 0.3846 1 +chr5 169911913 0 0 0.0 0 +chr5 170132547 0 0 0.0 0 +chr5 170148608 0 0 0.0 0 +chr5 170246425 0 0 0.0 0 +chr5 170317515 0 0 0.0 0 +chr5 170388470 0 0 0.0 0 +chr5 170395986 0 0 0.0 0 +chr5 170416120 0 1 0.0169 0 +chr5 170496043 0 0 0.0 0 +chr5 170534420 0 0 0.0 0 +chr5 170604818 0 0 0.0 0 +chr5 170606643 0 0 0.0 0 +chr5 170662462 0 0 0.0 0 +chr5 170665945 0 0 0.0 0 +chr5 170678935 0 0 0.0 0 +chr5 170817581 0 0 0.0 0 +chr5 171314859 0 0 0.0 0 +chr5 171351045 0 0 0.0 0 +chr5 171586088 0 0 0.0 0 +chr5 171597610 0 0 0.0 0 +chr5 171623396 0 0 0.0 0 +chr5 171705674 0 0 0.0 0 +chr5 171777405 1 3 0.0462 1 +chr5 171840214 0 0 0.0 0 +chr5 171881140 0 0 0.0 0 +chr5 171932412 0 0 0.0 0 +chr5 172001226 0 0 0.0 0 +chr5 172027190 0 0 0.0 0 +chr5 172061272 0 0 0.0 0 +chr5 172088648 0 0 0.0 0 +chr5 172103712 0 0 0.0 0 +chr5 172174262 0 0 0.0 0 +chr5 172224623 0 0 0.0 0 +chr5 172426002 0 0 0.0 0 +chr5 172485647 0 0 0.0 0 +chr5 172548766 0 0 0.0 0 +chr5 172678724 0 0 0.0 0 +chr5 172689772 0 0 0.0 0 +chr5 172860028 0 0 0.0 0 +chr5 172961256 0 0 0.0 0 +chr5 172973616 0 0 0.0 0 +chr5 173015365 0 0 0.0 0 +chr5 173086504 0 0 0.0 0 +chr5 173090442 0 0 0.0 0 +chr5 173213800 0 0 0.0 0 +chr5 173342481 0 0 0.0 0 +chr5 173391799 0 0 0.0 0 +chr5 173394864 0 0 0.0 0 +chr5 173478142 0 0 0.0 0 +chr5 173487006 0 0 0.0 0 +chr5 173504050 0 0 0.0 0 +chr5 173542863 0 0 0.0 0 +chr5 173547850 0 0 0.0 0 +chr5 173653953 0 0 0.0 0 +chr5 173741029 0 0 0.0 0 +chr5 173798999 0 0 0.0 0 +chr5 173822661 0 0 0.0 0 +chr5 173930915 0 0 0.0 0 +chr5 174129347 0 0 0.0 0 +chr5 174130711 0 0 0.0 0 +chr5 174206537 0 0 0.0 0 +chr5 174213583 0 0 0.0 0 +chr5 174363790 0 0 0.0 0 +chr5 174400340 0 0 0.0 0 +chr5 174539081 0 1 0.0222 0 +chr5 174584777 0 0 0.0 0 +chr5 174848434 0 0 0.0 0 +chr5 174901607 0 0 0.0 0 +chr5 175078556 0 0 0.0 0 +chr5 175218781 0 0 0.0 0 +chr5 175285965 0 0 0.0 0 +chr5 175394687 0 0 0.0 0 +chr5 175588344 0 0 0.0 0 +chr5 175666885 0 0 0.0 0 +chr5 175693945 0 0 0.0 0 +chr5 175707519 0 0 0.0 0 +chr5 175826108 0 0 0.0 0 +chr5 175940801 0 0 0.0 0 +chr5 176076849 0 0 0.0 0 +chr5 176100390 0 0 0.0 0 +chr5 176172456 0 0 0.0 0 +chr5 176587987 0 0 0.0 0 +chr5 176691366 0 0 0.0 0 +chr5 176766546 0 0 0.0 0 +chr5 176838638 0 0 0.0 0 +chr5 176845763 0 0 0.0 0 +chr5 177087482 0 0 0.0 0 +chr5 177096564 0 1 0.0159 0 +chr5 177162926 0 0 0.0 0 +chr5 177387649 0 0 0.0 0 +chr5 177638824 0 0 0.0 0 +chr5 177761299 0 0 0.0 0 +chr5 177904348 0 0 0.0 0 +chr5 177984218 0 0 0.0 0 +chr5 178022471 0 0 0.0 0 +chr5 178057946 0 0 0.0 0 +chr5 178149242 0 0 0.0 0 +chr5 178203933 0 0 0.0 0 +chr5 178210077 0 0 0.0 0 +chr5 178233289 0 0 0.0 0 +chr5 178285273 0 0 0.0 0 +chr5 178371983 0 0 0.0 0 +chr5 178428999 0 0 0.0 0 +chr5 178643655 0 1 0.0139 0 +chr5 178655065 0 0 0.0 0 +chr5 178678931 0 0 0.0 0 +chr5 178731562 0 0 0.0 0 +chr5 178752835 0 0 0.0 0 +chr5 178774389 0 0 0.0 0 +chr5 178844951 0 0 0.0 0 +chr5 179001711 0 0 0.0 0 +chr5 179054631 0 0 0.0 0 +chr5 179064101 0 0 0.0 0 +chr5 179113350 0 0 0.0 0 +chr5 179165964 0 0 0.0 0 +chr5 179307037 0 0 0.0 0 +chr5 179709014 0 0 0.0 0 +chr5 179774666 0 0 0.0 0 +chr5 179795587 0 0 0.0 0 +chr5 179990455 0 0 0.0 0 +chr5 180341858 0 0 0.0 0 +chr5 180355352 0 0 0.0 0 +chr5 180384354 0 0 0.0 0 +chr5 180391993 1 5 0.125 1 +chr5 180489945 0 0 0.0 0 +chr5 180591607 0 0 0.0 0 +chr5 180605089 0 0 0.0 0 +chr5 180788230 0 0 0.0 0 +chr5 180846953 0 0 0.0 0 +chr5 180889992 0 0 0.0 0 +chr5 181110862 0 0 0.0 0 +chr5 181119087 0 1 0.0167 0 +chr5 181150306 0 0 0.0 0 +chr5 181196835 0 0 0.0 0 +chr5 181242316 0 0 0.0 0 +chr5 181405109 0 0 0.0 0 +chr5 181445526 0 0 0.0 0 +chr5 181453574 0 0 0.0 0 +chr5 181455006 0 0 0.0 0 +chr5_GL339449v2_alt 242879 0 0 0.0 0 +chr5_GL339449v2_alt 251759 0 0 0.0 0 +chr5_GL339449v2_alt 329196 0 0 0.0 0 +chr5_GL339449v2_alt 615734 0 0 0.0 0 +chr5_GL339449v2_alt 616431 0 0 0.0 0 +chr5_GL339449v2_alt 752477 0 0 0.0 0 +chr5_GL339449v2_alt 807749 0 0 0.0 0 +chr5_GL339449v2_alt 1011891 0 0 0.0 0 +chr5_GL339449v2_alt 1128706 0 0 0.0 0 +chr5_GL339449v2_alt 1129403 0 0 0.0 0 +chr5_GL339449v2_alt 1327512 0 0 0.0 0 +chr5_GL383532v1_alt 28459 0 0 0.0 0 +chr5_GL949742v1_alt 35073 0 0 0.0 0 +chr5_GL949742v1_alt 76212 0 0 0.0 0 +chr5_KI270791v1_alt 13762 0 0 0.0 0 +chr5_KI270791v1_alt 79005 0 0 0.0 0 +chr5_KI270791v1_alt 119982 0 0 0.0 0 +chr5_KI270791v1_alt 183669 0 0 0.0 0 +chr5_KI270792v1_alt 12520 0 0 0.0 0 +chr5_KI270792v1_alt 95189 0 0 0.0 0 +chr5_KI270792v1_alt 138515 0 0 0.0 0 +chr5_KI270792v1_alt 166602 0 0 0.0 0 +chr5_KI270795v1_alt 38884 0 0 0.0 0 +chr5_KI270795v1_alt 122797 0 0 0.0 0 +chr5_KI270897v1_alt 10178 0 0 0.0 0 +chr5_KI270897v1_alt 144344 0 0 0.0 0 +chr5_KI270897v1_alt 145041 0 0 0.0 0 +chr5_KI270897v1_alt 724117 0 0 0.0 0 +chr5_KI270897v1_alt 724814 0 0 0.0 0 +chr5_KI270897v1_alt 858991 0 0 0.0 0 +chr5_KI270898v1_alt 38884 0 0 0.0 0 +chr5_KI270898v1_alt 119032 0 0 0.0 0 +chr6 96702 0 0 0.0 0 +chr6 156617 0 0 0.0 0 +chr6 157013 0 0 0.0 0 +chr6 438335 0 0 0.0 0 +chr6 714418 0 0 0.0 0 +chr6 804430 0 0 0.0 0 +chr6 807556 0 0 0.0 0 +chr6 838490 0 0 0.0 0 +chr6 912983 0 0 0.0 0 +chr6 1031822 0 0 0.0 0 +chr6 1069960 0 0 0.0 0 +chr6 1147351 0 0 0.0 0 +chr6 1185017 0 0 0.0 0 +chr6 1199129 0 0 0.0 0 +chr6 1211653 0 0 0.0 0 +chr6 1264609 0 0 0.0 0 +chr6 1290771 0 0 0.0 0 +chr6 1307514 0 0 0.0 0 +chr6 1478697 0 0 0.0 0 +chr6 1491657 0 0 0.0 0 +chr6 1491685 0 1 0.0172 0 +chr6 1529255 0 0 0.0 0 +chr6 1632410 0 0 0.0 0 +chr6 1688068 0 0 0.0 0 +chr6 1717110 0 0 0.0 0 +chr6 1750865 0 0 0.0 0 +chr6 1773519 0 1 0.0159 0 +chr6 1775560 0 0 0.0 0 +chr6 1786528 0 0 0.0 0 +chr6 1995172 0 0 0.0 0 +chr6 2005762 0 0 0.0 0 +chr6 2615703 0 0 0.0 0 +chr6 2673839 0 0 0.0 0 +chr6 2828666 0 0 0.0 0 +chr6 2840559 0 0 0.0 0 +chr6 2848185 0 0 0.0 0 +chr6 2877854 0 0 0.0 0 +chr6 2947391 0 0 0.0 0 +chr6 3004610 0 0 0.0 0 +chr6 3006190 0 0 0.0 0 +chr6 3051137 0 0 0.0 0 +chr6 3160257 0 1 0.0182 0 +chr6 3264401 0 0 0.0 0 +chr6 3269754 0 0 0.0 0 +chr6 3273089 0 0 0.0 0 +chr6 3362696 0 0 0.0 0 +chr6 3491232 0 0 0.0 0 +chr6 3501393 0 0 0.0 0 +chr6 3529081 0 0 0.0 0 +chr6 3534762 0 0 0.0 0 +chr6 3627370 0 0 0.0 0 +chr6 3650886 0 0 0.0 0 +chr6 3705452 0 0 0.0 0 +chr6 3761194 0 0 0.0 0 +chr6 3850677 0 0 0.0 0 +chr6 3889127 0 0 0.0 0 +chr6 3920438 0 0 0.0 0 +chr6 3940648 0 1 0.0154 0 +chr6 3975271 0 0 0.0 0 +chr6 4153269 0 0 0.0 0 +chr6 4158654 0 0 0.0 0 +chr6 4205817 0 0 0.0 0 +chr6 4375779 0 0 0.0 0 +chr6 4441262 0 0 0.0 0 +chr6 4584672 0 0 0.0 0 +chr6 4680772 0 0 0.0 0 +chr6 4712130 0 0 0.0 0 +chr6 4745948 0 0 0.0 0 +chr6 4768750 0 0 0.0 0 +chr6 4820981 0 0 0.0 0 +chr6 4852892 0 0 0.0 0 +chr6 4984419 0 0 0.0 0 +chr6 5044222 0 0 0.0 0 +chr6 5109844 0 0 0.0 0 +chr6 5217838 0 0 0.0 0 +chr6 5239716 0 0 0.0 0 +chr6 5293806 0 0 0.0 0 +chr6 5308406 0 0 0.0 0 +chr6 5403767 0 0 0.0 0 +chr6 5500461 0 0 0.0 0 +chr6 5503794 0 0 0.0 0 +chr6 5642012 0 0 0.0 0 +chr6 5659028 0 0 0.0 0 +chr6 5776963 0 0 0.0 0 +chr6 5936864 0 0 0.0 0 +chr6 5958083 0 0 0.0 0 +chr6 6031334 0 0 0.0 0 +chr6 6061700 0 0 0.0 0 +chr6 6201515 0 0 0.0 0 +chr6 6285298 0 1 0.0213 0 +chr6 6328465 0 0 0.0 0 +chr6 6349953 0 0 0.0 0 +chr6 6465923 0 0 0.0 0 +chr6 6528310 0 0 0.0 0 +chr6 6572623 0 0 0.0 0 +chr6 6585716 0 0 0.0 0 +chr6 6595930 0 0 0.0 0 +chr6 6689535 0 0 0.0 0 +chr6 6692996 0 0 0.0 0 +chr6 6715351 0 0 0.0 0 +chr6 6717927 0 0 0.0 0 +chr6 6765839 0 0 0.0 0 +chr6 6785465 0 0 0.0 0 +chr6 6892001 0 0 0.0 0 +chr6 6941104 0 0 0.0 0 +chr6 6979027 0 0 0.0 0 +chr6 7008379 0 0 0.0 0 +chr6 7021245 0 0 0.0 0 +chr6 7027692 0 0 0.0 0 +chr6 7114395 0 0 0.0 0 +chr6 7157189 0 0 0.0 0 +chr6 7167133 0 0 0.0 0 +chr6 7340931 0 0 0.0 0 +chr6 7444066 0 0 0.0 0 +chr6 7494391 0 0 0.0 0 +chr6 7570163 0 1 0.0189 0 +chr6 7583493 0 0 0.0 0 +chr6 7663305 0 0 0.0 0 +chr6 7859225 0 0 0.0 0 +chr6 7879266 0 0 0.0 0 +chr6 7938450 0 0 0.0 0 +chr6 7965766 0 0 0.0 0 +chr6 8009913 0 0 0.0 0 +chr6 8048329 0 0 0.0 0 +chr6 8269768 0 0 0.0 0 +chr6 8298451 0 0 0.0 0 +chr6 8623381 0 0 0.0 0 +chr6 8646076 0 0 0.0 0 +chr6 8730846 0 0 0.0 0 +chr6 8804018 0 0 0.0 0 +chr6 8812581 0 0 0.0 0 +chr6 8943474 0 0 0.0 0 +chr6 9646557 0 0 0.0 0 +chr6 9671241 0 0 0.0 0 +chr6 9692707 0 0 0.0 0 +chr6 9984793 0 0 0.0 0 +chr6 10021250 0 0 0.0 0 +chr6 10120161 0 0 0.0 0 +chr6 10151513 0 0 0.0 0 +chr6 10259779 0 0 0.0 0 +chr6 10270112 0 0 0.0 0 +chr6 10385606 0 0 0.0 0 +chr6 10470982 0 0 0.0 0 +chr6 10482740 0 0 0.0 0 +chr6 10487269 0 0 0.0 0 +chr6 10497190 0 0 0.0 0 +chr6 10505467 0 0 0.0 0 +chr6 10648403 0 0 0.0 0 +chr6 10692217 0 0 0.0 0 +chr6 10850697 0 0 0.0 0 +chr6 10894029 0 0 0.0 0 +chr6 10988016 0 0 0.0 0 +chr6 11088333 0 0 0.0 0 +chr6 11104521 0 0 0.0 0 +chr6 11110677 0 0 0.0 0 +chr6 11345717 0 0 0.0 0 +chr6 11607579 0 0 0.0 0 +chr6 11639310 0 0 0.0 0 +chr6 11689118 0 0 0.0 0 +chr6 11694963 0 0 0.0 0 +chr6 11779644 0 0 0.0 0 +chr6 11795498 0 0 0.0 0 +chr6 11827475 0 0 0.0 0 +chr6 11837480 0 0 0.0 0 +chr6 11862128 0 0 0.0 0 +chr6 11959275 0 0 0.0 0 +chr6 12026265 0 0 0.0 0 +chr6 12500594 0 0 0.0 0 +chr6 12519176 0 0 0.0 0 +chr6 12605769 0 0 0.0 0 +chr6 12650520 0 0 0.0 0 +chr6 12680687 0 0 0.0 0 +chr6 12735624 0 0 0.0 0 +chr6 12775363 0 0 0.0 0 +chr6 12876571 0 0 0.0 0 +chr6 12898358 0 0 0.0 0 +chr6 12961371 0 0 0.0 0 +chr6 13197287 0 0 0.0 0 +chr6 13225430 0 0 0.0 0 +chr6 13253744 0 0 0.0 0 +chr6 13282740 1 18 0.3158 1 +chr6 13299074 0 0 0.0 0 +chr6 13418796 0 0 0.0 0 +chr6 13422853 0 0 0.0 0 +chr6 13616232 0 0 0.0 0 +chr6 13661179 0 0 0.0 0 +chr6 13880000 0 0 0.0 0 +chr6 13927417 0 0 0.0 0 +chr6 13944075 0 0 0.0 0 +chr6 14001740 0 0 0.0 0 +chr6 14125825 0 0 0.0 0 +chr6 14148715 0 0 0.0 0 +chr6 14223090 0 0 0.0 0 +chr6 14233315 0 0 0.0 0 +chr6 14244365 0 0 0.0 0 +chr6 14248945 0 0 0.0 0 +chr6 14257299 0 0 0.0 0 +chr6 14264109 0 0 0.0 0 +chr6 14338219 0 0 0.0 0 +chr6 14416249 0 0 0.0 0 +chr6 14979136 0 0 0.0 0 +chr6 15088756 0 0 0.0 0 +chr6 15117810 0 0 0.0 0 +chr6 15139548 0 0 0.0 0 +chr6 15176721 0 0 0.0 0 +chr6 15228616 0 0 0.0 0 +chr6 15276233 0 0 0.0 0 +chr6 15300026 0 0 0.0 0 +chr6 15390247 0 0 0.0 0 +chr6 15391712 0 0 0.0 0 +chr6 15394054 0 0 0.0 0 +chr6 15463301 0 0 0.0 0 +chr6 15525451 0 0 0.0 0 +chr6 15543497 0 0 0.0 0 +chr6 15741164 0 0 0.0 0 +chr6 15753909 0 0 0.0 0 +chr6 15952602 0 0 0.0 0 +chr6 16040402 0 0 0.0 0 +chr6 16049116 0 0 0.0 0 +chr6 16115477 0 0 0.0 0 +chr6 16347214 0 0 0.0 0 +chr6 16623430 0 0 0.0 0 +chr6 16646194 0 0 0.0 0 +chr6 16689152 0 0 0.0 0 +chr6 16712694 1 50 0.6849 1 +chr6 16720275 0 0 0.0 0 +chr6 16738227 0 0 0.0 0 +chr6 16752665 0 0 0.0 0 +chr6 16797536 0 0 0.0 0 +chr6 16833815 0 0 0.0 0 +chr6 16858021 0 0 0.0 0 +chr6 16870500 0 0 0.0 0 +chr6 16921718 0 0 0.0 0 +chr6 16940334 0 0 0.0 0 +chr6 17074285 0 0 0.0 0 +chr6 17104955 0 1 0.0141 0 +chr6 17210615 0 0 0.0 0 +chr6 17222392 0 0 0.0 0 +chr6 17238992 0 0 0.0 0 +chr6 17487732 0 0 0.0 0 +chr6 17542118 0 0 0.0 0 +chr6 17696830 0 0 0.0 0 +chr6 17810171 0 0 0.0 0 +chr6 17930590 0 0 0.0 0 +chr6 17994803 0 0 0.0 0 +chr6 18128569 0 0 0.0 0 +chr6 18131555 0 0 0.0 0 +chr6 18308677 0 0 0.0 0 +chr6 18420590 0 0 0.0 0 +chr6 18688149 0 1 0.0263 0 +chr6 18732136 0 0 0.0 0 +chr6 18753861 0 0 0.0 0 +chr6 18811227 0 0 0.0 0 +chr6 18836726 0 0 0.0 0 +chr6 18868278 0 0 0.0 0 +chr6 19041479 0 0 0.0 0 +chr6 19142824 0 0 0.0 0 +chr6 19155529 0 0 0.0 0 +chr6 19275583 0 0 0.0 0 +chr6 19404436 0 0 0.0 0 +chr6 19427628 0 0 0.0 0 +chr6 19438184 0 0 0.0 0 +chr6 19534787 0 0 0.0 0 +chr6 19541085 0 0 0.0 0 +chr6 19598895 0 0 0.0 0 +chr6 19742136 0 0 0.0 0 +chr6 19746328 0 0 0.0 0 +chr6 19796509 0 0 0.0 0 +chr6 19894309 0 0 0.0 0 +chr6 19911639 0 0 0.0 0 +chr6 19978644 0 0 0.0 0 +chr6 20036712 0 0 0.0 0 +chr6 20136257 0 0 0.0 0 +chr6 20186684 0 0 0.0 0 +chr6 20317639 0 1 0.0139 0 +chr6 20367006 0 0 0.0 0 +chr6 20513401 0 0 0.0 0 +chr6 20596533 0 0 0.0 0 +chr6 20733540 0 0 0.0 0 +chr6 20809753 0 0 0.0 0 +chr6 21035184 0 0 0.0 0 +chr6 21048059 0 0 0.0 0 +chr6 21158588 0 0 0.0 0 +chr6 21215957 0 0 0.0 0 +chr6 21256347 0 0 0.0 0 +chr6 21266003 0 0 0.0 0 +chr6 21384063 0 0 0.0 0 +chr6 21407309 0 0 0.0 0 +chr6 21556531 0 0 0.0 0 +chr6 21853880 0 0 0.0 0 +chr6 21860271 0 0 0.0 0 +chr6 21882266 0 0 0.0 0 +chr6 22083001 0 0 0.0 0 +chr6 22182141 0 0 0.0 0 +chr6 22322109 0 0 0.0 0 +chr6 22430176 0 0 0.0 0 +chr6 22478603 0 0 0.0 0 +chr6 22542832 0 0 0.0 0 +chr6 22687650 0 0 0.0 0 +chr6 22766137 0 0 0.0 0 +chr6 23702955 0 0 0.0 0 +chr6 24055316 0 0 0.0 0 +chr6 24104541 0 0 0.0 0 +chr6 24227364 0 0 0.0 0 +chr6 24278556 0 0 0.0 0 +chr6 24394185 0 0 0.0 0 +chr6 24496882 0 0 0.0 0 +chr6 24539300 0 0 0.0 0 +chr6 24566666 0 0 0.0 0 +chr6 24574947 0 0 0.0 0 +chr6 24580600 0 0 0.0 0 +chr6 24779602 0 0 0.0 0 +chr6 24841205 0 0 0.0 0 +chr6 24947266 0 0 0.0 0 +chr6 25006674 0 0 0.0 0 +chr6 25036880 0 0 0.0 0 +chr6 25142685 0 0 0.0 0 +chr6 25185904 0 0 0.0 0 +chr6 25214760 0 0 0.0 0 +chr6 25240649 0 0 0.0 0 +chr6 25363658 0 0 0.0 0 +chr6 25431813 0 0 0.0 0 +chr6 25486257 0 0 0.0 0 +chr6 25524980 0 0 0.0 0 +chr6 25673890 0 0 0.0 0 +chr6 25732122 0 0 0.0 0 +chr6 25853509 0 0 0.0 0 +chr6 25862408 0 0 0.0 0 +chr6 25891983 0 0 0.0 0 +chr6 25994295 0 0 0.0 0 +chr6 26045448 0 0 0.0 0 +chr6 26315081 0 0 0.0 0 +chr6 26337424 0 0 0.0 0 +chr6 26347104 0 0 0.0 0 +chr6 26378748 0 0 0.0 0 +chr6 26431726 0 0 0.0 0 +chr6 26454166 0 0 0.0 0 +chr6 26538384 0 0 0.0 0 +chr6 26879523 0 0 0.0 0 +chr6 26880239 0 0 0.0 0 +chr6 26945499 0 0 0.0 0 +chr6 26990388 0 0 0.0 0 +chr6 27000142 0 0 0.0 0 +chr6 27039600 0 0 0.0 0 +chr6 27040819 0 0 0.0 0 +chr6 27158300 0 0 0.0 0 +chr6 27175265 0 0 0.0 0 +chr6 27178176 0 0 0.0 0 +chr6 27233142 0 0 0.0 0 +chr6 27271431 0 0 0.0 0 +chr6 27410921 0 0 0.0 0 +chr6 27543466 0 0 0.0 0 +chr6 27644644 0 0 0.0 0 +chr6 27705513 0 0 0.0 0 +chr6 27726623 0 0 0.0 0 +chr6 27740351 0 0 0.0 0 +chr6 27770896 0 0 0.0 0 +chr6 27872278 0 0 0.0 0 +chr6 27890755 0 0 0.0 0 +chr6 27916977 0 0 0.0 0 +chr6 27949793 0 0 0.0 0 +chr6 27998142 0 0 0.0 0 +chr6 28078254 0 0 0.0 0 +chr6 28417698 0 0 0.0 0 +chr6 28513335 0 0 0.0 0 +chr6 28674241 0 0 0.0 0 +chr6 28731846 0 0 0.0 0 +chr6 28748548 0 0 0.0 0 +chr6 28952314 0 0 0.0 0 +chr6 28989197 0 0 0.0 0 +chr6 29055386 0 0 0.0 0 +chr6 29330224 0 0 0.0 0 +chr6 29400135 0 0 0.0 0 +chr6 29480274 0 0 0.0 0 +chr6 29563274 0 0 0.0 0 +chr6 29587751 0 0 0.0 0 +chr6 29714690 0 0 0.0 0 +chr6 29778514 0 0 0.0 0 +chr6 29881261 0 0 0.0 0 +chr6 29891945 0 0 0.0 0 +chr6 29907255 0 0 0.0 0 +chr6 30003113 1 56 0.7887 1 +chr6 30075991 0 0 0.0 0 +chr6 30282220 0 0 0.0 0 +chr6 30339899 0 0 0.0 0 +chr6 30347517 0 0 0.0 0 +chr6 30510416 0 0 0.0 0 +chr6 30553093 0 0 0.0 0 +chr6 30578240 0 0 0.0 0 +chr6 30604619 0 0 0.0 0 +chr6 30766666 0 0 0.0 0 +chr6 30774602 0 0 0.0 0 +chr6 30821770 0 0 0.0 0 +chr6 30872008 0 0 0.0 0 +chr6 30903019 0 0 0.0 0 +chr6 30933761 0 0 0.0 0 +chr6 30946097 0 0 0.0 0 +chr6 31147460 0 0 0.0 0 +chr6 31168779 0 0 0.0 0 +chr6 31357990 0 0 0.0 0 +chr6 31416907 0 0 0.0 0 +chr6 31463669 0 0 0.0 0 +chr6 31530706 0 0 0.0 0 +chr6 31536210 0 0 0.0 0 +chr6 31550781 0 0 0.0 0 +chr6 31683418 0 0 0.0 0 +chr6 31766388 0 0 0.0 0 +chr6 31779440 0 0 0.0 0 +chr6 31816821 0 0 0.0 0 +chr6 31829015 0 0 0.0 0 +chr6 31963511 0 0 0.0 0 +chr6 31983847 0 0 0.0 0 +chr6 32013189 0 0 0.0 0 +chr6 32016585 0 0 0.0 0 +chr6 32078896 0 0 0.0 0 +chr6 32086097 0 0 0.0 0 +chr6 32204293 0 0 0.0 0 +chr6 32311536 0 0 0.0 0 +chr6 32368522 0 0 0.0 0 +chr6 32401350 0 0 0.0 0 +chr6 32586123 0 0 0.0 0 +chr6 32638064 0 0 0.0 0 +chr6 32641905 0 0 0.0 0 +chr6 32679832 0 0 0.0 0 +chr6 32742054 0 0 0.0 0 +chr6 32807607 0 0 0.0 0 +chr6 32808119 0 0 0.0 0 +chr6 33036811 0 0 0.0 0 +chr6 33117716 0 0 0.0 0 +chr6 33173088 0 0 0.0 0 +chr6 33197859 0 0 0.0 0 +chr6 33198325 0 0 0.0 0 +chr6 33380734 0 0 0.0 0 +chr6 33398413 0 0 0.0 0 +chr6 33418473 0 0 0.0 0 +chr6 33499043 0 0 0.0 0 +chr6 33611826 0 0 0.0 0 +chr6 33664910 0 0 0.0 0 +chr6 33689361 0 0 0.0 0 +chr6 33780265 0 0 0.0 0 +chr6 33848913 0 0 0.0 0 +chr6 33982899 0 0 0.0 0 +chr6 34067968 0 0 0.0 0 +chr6 34238191 0 0 0.0 0 +chr6 34288456 0 0 0.0 0 +chr6 34460178 0 0 0.0 0 +chr6 34518648 0 1 0.0208 0 +chr6 34580973 0 0 0.0 0 +chr6 34646959 0 1 0.025 0 +chr6 34852020 0 0 0.0 0 +chr6 34923391 0 0 0.0 0 +chr6 35016978 1 5 0.2174 1 +chr6 35024821 0 0 0.0 0 +chr6 35132754 0 0 0.0 0 +chr6 35168336 0 0 0.0 0 +chr6 35192606 0 0 0.0 0 +chr6 35240392 0 0 0.0 0 +chr6 35346442 0 0 0.0 0 +chr6 35644233 0 0 0.0 0 +chr6 35779321 0 0 0.0 0 +chr6 36089759 0 0 0.0 0 +chr6 36121515 0 0 0.0 0 +chr6 36132648 0 0 0.0 0 +chr6 36135921 0 0 0.0 0 +chr6 36508696 0 0 0.0 0 +chr6 36637564 0 0 0.0 0 +chr6 36676328 0 0 0.0 0 +chr6 36680440 0 1 0.0256 0 +chr6 36733438 0 0 0.0 0 +chr6 36756981 0 0 0.0 0 +chr6 36781108 0 0 0.0 0 +chr6 36781372 0 0 0.0 0 +chr6 36976687 0 0 0.0 0 +chr6 37046658 0 0 0.0 0 +chr6 37305974 0 0 0.0 0 +chr6 37327838 0 0 0.0 0 +chr6 37357192 0 0 0.0 0 +chr6 37475224 0 0 0.0 0 +chr6 37503816 0 0 0.0 0 +chr6 37769684 0 0 0.0 0 +chr6 37832065 0 0 0.0 0 +chr6 37924851 0 0 0.0 0 +chr6 37941476 0 0 0.0 0 +chr6 38063989 0 0 0.0 0 +chr6 38124341 0 0 0.0 0 +chr6 38160778 0 0 0.0 0 +chr6 38592338 0 0 0.0 0 +chr6 38709366 0 0 0.0 0 +chr6 38806946 0 0 0.0 0 +chr6 38825917 0 0 0.0 0 +chr6 38831042 0 0 0.0 0 +chr6 38899905 0 0 0.0 0 +chr6 38933237 0 0 0.0 0 +chr6 39029164 0 0 0.0 0 +chr6 39037605 0 0 0.0 0 +chr6 39120867 0 0 0.0 0 +chr6 39178378 0 0 0.0 0 +chr6 39198391 0 0 0.0 0 +chr6 39282639 0 0 0.0 0 +chr6 39284668 0 0 0.0 0 +chr6 39316909 0 0 0.0 0 +chr6 39343287 0 0 0.0 0 +chr6 39433131 0 0 0.0 0 +chr6 39444663 1 55 0.8462 1 +chr6 39476589 0 0 0.0 0 +chr6 39526377 1 58 0.8788 1 +chr6 39663377 0 0 0.0 0 +chr6 39775455 0 0 0.0 0 +chr6 39802470 0 0 0.0 0 +chr6 39884869 0 0 0.0 0 +chr6 39901942 0 0 0.0 0 +chr6 40052502 0 0 0.0 0 +chr6 40059504 0 0 0.0 0 +chr6 40087174 0 0 0.0 0 +chr6 40104749 0 1 0.0204 0 +chr6 40167805 0 0 0.0 0 +chr6 40191774 0 0 0.0 0 +chr6 40220913 0 0 0.0 0 +chr6 40352942 0 0 0.0 0 +chr6 40384535 0 0 0.0 0 +chr6 40494589 0 0 0.0 0 +chr6 40622806 0 0 0.0 0 +chr6 40647319 0 0 0.0 0 +chr6 40665268 0 1 0.0149 0 +chr6 40759079 0 0 0.0 0 +chr6 40853414 0 0 0.0 0 +chr6 40888126 0 0 0.0 0 +chr6 40960443 0 0 0.0 0 +chr6 40996996 0 0 0.0 0 +chr6 41023670 0 0 0.0 0 +chr6 41146731 0 0 0.0 0 +chr6 41170187 0 0 0.0 0 +chr6 41173837 0 1 0.0133 0 +chr6 41181803 0 0 0.0 0 +chr6 41194701 0 0 0.0 0 +chr6 41249481 0 2 0.0435 0 +chr6 41317441 0 0 0.0 0 +chr6 41368655 0 0 0.0 0 +chr6 41380437 0 0 0.0 0 +chr6 41392981 0 0 0.0 0 +chr6 41495584 0 0 0.0 0 +chr6 41550209 0 0 0.0 0 +chr6 41656054 0 0 0.0 0 +chr6 41875630 0 0 0.0 0 +chr6 41915201 0 0 0.0 0 +chr6 41933195 0 0 0.0 0 +chr6 42005983 0 1 0.0312 0 +chr6 42014413 1 9 0.2727 1 +chr6 42407642 0 0 0.0 0 +chr6 42443270 0 0 0.0 0 +chr6 42530737 0 0 0.0 0 +chr6 42573992 0 0 0.0 0 +chr6 42665046 0 0 0.0 0 +chr6 42689668 0 1 0.0286 0 +chr6 42745649 0 0 0.0 0 +chr6 42937790 0 0 0.0 0 +chr6 43154226 0 0 0.0 0 +chr6 43244644 0 0 0.0 0 +chr6 43319945 0 0 0.0 0 +chr6 43495332 0 0 0.0 0 +chr6 43795565 0 0 0.0 0 +chr6 43861388 0 0 0.0 0 +chr6 43939679 0 0 0.0 0 +chr6 43998432 0 0 0.0 0 +chr6 44002111 0 0 0.0 0 +chr6 44011040 0 0 0.0 0 +chr6 44033932 0 0 0.0 0 +chr6 44227217 0 0 0.0 0 +chr6 44272392 0 0 0.0 0 +chr6 44283311 0 0 0.0 0 +chr6 44396280 0 0 0.0 0 +chr6 44415577 0 0 0.0 0 +chr6 44543304 0 0 0.0 0 +chr6 44650266 0 0 0.0 0 +chr6 44692551 0 0 0.0 0 +chr6 44717151 0 0 0.0 0 +chr6 44834368 0 0 0.0 0 +chr6 45527047 0 0 0.0 0 +chr6 45668794 0 0 0.0 0 +chr6 45813872 0 0 0.0 0 +chr6 45897951 0 2 0.05 0 +chr6 45927318 0 0 0.0 0 +chr6 45929873 0 0 0.0 0 +chr6 45955746 0 0 0.0 0 +chr6 45978654 0 0 0.0 0 +chr6 46022397 0 0 0.0 0 +chr6 46045442 0 0 0.0 0 +chr6 46087751 0 0 0.0 0 +chr6 46095013 0 0 0.0 0 +chr6 46210476 0 0 0.0 0 +chr6 46247986 0 0 0.0 0 +chr6 46320674 0 0 0.0 0 +chr6 46324102 0 0 0.0 0 +chr6 46607721 0 0 0.0 0 +chr6 46781939 0 0 0.0 0 +chr6 46921093 0 0 0.0 0 +chr6 46924715 0 0 0.0 0 +chr6 46926256 0 0 0.0 0 +chr6 47031973 0 0 0.0 0 +chr6 47102764 0 0 0.0 0 +chr6 47180151 0 1 0.0222 0 +chr6 47206206 0 0 0.0 0 +chr6 47209677 0 0 0.0 0 +chr6 47290268 0 0 0.0 0 +chr6 47500070 0 0 0.0 0 +chr6 47705798 0 0 0.0 0 +chr6 47805555 0 0 0.0 0 +chr6 48224519 0 0 0.0 0 +chr6 48435276 0 0 0.0 0 +chr6 48561018 0 0 0.0 0 +chr6 48605135 0 0 0.0 0 +chr6 48962309 0 0 0.0 0 +chr6 48974028 1 29 0.5918 1 +chr6 49118647 0 0 0.0 0 +chr6 49239786 0 0 0.0 0 +chr6 49341541 0 0 0.0 0 +chr6 49424261 0 0 0.0 0 +chr6 49459331 0 0 0.0 0 +chr6 49503362 0 0 0.0 0 +chr6 49755062 0 0 0.0 0 +chr6 49977105 0 0 0.0 0 +chr6 49989698 0 0 0.0 0 +chr6 50022090 0 0 0.0 0 +chr6 50167418 0 0 0.0 0 +chr6 50314178 0 0 0.0 0 +chr6 50475399 0 0 0.0 0 +chr6 50547841 0 0 0.0 0 +chr6 50712096 0 0 0.0 0 +chr6 50722278 0 0 0.0 0 +chr6 50824960 0 0 0.0 0 +chr6 50841583 0 1 0.0233 0 +chr6 51084850 0 0 0.0 0 +chr6 51136310 0 0 0.0 0 +chr6 51220771 0 0 0.0 0 +chr6 51323382 0 0 0.0 0 +chr6 51445362 0 0 0.0 0 +chr6 51453566 0 0 0.0 0 +chr6 51463782 0 0 0.0 0 +chr6 51498104 0 0 0.0 0 +chr6 51609991 0 0 0.0 0 +chr6 51779575 0 0 0.0 0 +chr6 51820783 0 0 0.0 0 +chr6 51889354 0 0 0.0 0 +chr6 51947868 0 0 0.0 0 +chr6 51969126 0 0 0.0 0 +chr6 52156590 0 0 0.0 0 +chr6 52189284 0 0 0.0 0 +chr6 52212934 0 0 0.0 0 +chr6 52484867 0 0 0.0 0 +chr6 52488631 0 0 0.0 0 +chr6 52506620 0 0 0.0 0 +chr6 52522031 0 0 0.0 0 +chr6 52642750 0 0 0.0 0 +chr6 52649773 0 0 0.0 0 +chr6 52792900 0 0 0.0 0 +chr6 52829196 0 0 0.0 0 +chr6 52920071 0 0 0.0 0 +chr6 52995370 0 0 0.0 0 +chr6 53089336 0 0 0.0 0 +chr6 53133984 0 0 0.0 0 +chr6 53161816 0 0 0.0 0 +chr6 53247342 0 0 0.0 0 +chr6 53395504 0 0 0.0 0 +chr6 53419270 0 0 0.0 0 +chr6 53658491 0 0 0.0 0 +chr6 53726199 0 0 0.0 0 +chr6 53826062 0 0 0.0 0 +chr6 54327747 0 0 0.0 0 +chr6 54559623 0 0 0.0 0 +chr6 54600278 0 0 0.0 0 +chr6 54888509 0 0 0.0 0 +chr6 54978749 0 0 0.0 0 +chr6 55011424 0 0 0.0 0 +chr6 55102725 0 0 0.0 0 +chr6 55273159 0 0 0.0 0 +chr6 55493676 0 0 0.0 0 +chr6 55516096 0 0 0.0 0 +chr6 55790632 0 0 0.0 0 +chr6 55950683 0 0 0.0 0 +chr6 56406817 0 0 0.0 0 +chr6 56412537 0 0 0.0 0 +chr6 56437600 0 0 0.0 0 +chr6 56717984 0 0 0.0 0 +chr6 56945244 0 0 0.0 0 +chr6 57116309 0 0 0.0 0 +chr6 57303259 0 0 0.0 0 +chr6 57432712 0 0 0.0 0 +chr6 57860124 0 0 0.0 0 +chr6 57920608 0 0 0.0 0 +chr6 57921325 0 0 0.0 0 +chr6 58217092 0 0 0.0 0 +chr6 58235536 0 0 0.0 0 +chr6 58394663 0 0 0.0 0 +chr6 60329084 0 0 0.0 0 +chr6 60356800 0 0 0.0 0 +chr6 60563436 0 0 0.0 0 +chr6 61052686 0 0 0.0 0 +chr6 61483292 0 0 0.0 0 +chr6 61651153 0 0 0.0 0 +chr6 61868543 0 0 0.0 0 +chr6 62054664 0 0 0.0 0 +chr6 62170204 0 0 0.0 0 +chr6 62175877 0 0 0.0 0 +chr6 62542010 0 0 0.0 0 +chr6 62860997 0 0 0.0 0 +chr6 63173497 0 0 0.0 0 +chr6 63362847 0 0 0.0 0 +chr6 63382191 0 0 0.0 0 +chr6 63507537 0 0 0.0 0 +chr6 63556319 1 6 0.0845 1 +chr6 63688111 0 0 0.0 0 +chr6 63689142 0 0 0.0 0 +chr6 63778204 0 0 0.0 0 +chr6 63829912 0 0 0.0 0 +chr6 63887937 0 0 0.0 0 +chr6 63972158 0 0 0.0 0 +chr6 64077366 0 0 0.0 0 +chr6 64209382 0 0 0.0 0 +chr6 64333573 0 0 0.0 0 +chr6 64385926 0 0 0.0 0 +chr6 64605043 0 0 0.0 0 +chr6 64613854 0 0 0.0 0 +chr6 64790479 0 0 0.0 0 +chr6 65299452 0 0 0.0 0 +chr6 65510488 0 0 0.0 0 +chr6 65966694 0 0 0.0 0 +chr6 66173125 1 22 0.55 1 +chr6 66181523 0 0 0.0 0 +chr6 66331221 0 0 0.0 0 +chr6 66407378 0 0 0.0 0 +chr6 66469593 0 0 0.0 0 +chr6 66631701 0 0 0.0 0 +chr6 66755934 0 0 0.0 0 +chr6 67153746 0 0 0.0 0 +chr6 67314060 0 1 0.0217 0 +chr6 67541135 0 0 0.0 0 +chr6 67550998 0 0 0.0 0 +chr6 67883223 0 0 0.0 0 +chr6 67888994 0 0 0.0 0 +chr6 67899512 0 0 0.0 0 +chr6 68218825 0 0 0.0 0 +chr6 68456179 0 0 0.0 0 +chr6 68544148 0 0 0.0 0 +chr6 68636527 0 0 0.0 0 +chr6 69006769 0 0 0.0 0 +chr6 69398208 0 0 0.0 0 +chr6 69618705 0 0 0.0 0 +chr6 69637800 0 0 0.0 0 +chr6 69726392 0 0 0.0 0 +chr6 70352822 0 0 0.0 0 +chr6 70419957 0 0 0.0 0 +chr6 70448495 0 0 0.0 0 +chr6 70516629 0 0 0.0 0 +chr6 70820961 0 0 0.0 0 +chr6 70967300 0 0 0.0 0 +chr6 71070932 0 0 0.0 0 +chr6 71091202 0 0 0.0 0 +chr6 71280051 0 0 0.0 0 +chr6 71332529 0 0 0.0 0 +chr6 71351744 0 0 0.0 0 +chr6 71432791 0 0 0.0 0 +chr6 71480834 0 0 0.0 0 +chr6 71536823 0 0 0.0 0 +chr6 71752100 0 0 0.0 0 +chr6 71847780 0 0 0.0 0 +chr6 72074888 0 0 0.0 0 +chr6 72125294 0 0 0.0 0 +chr6 72148857 0 0 0.0 0 +chr6 72154748 0 0 0.0 0 +chr6 72183740 0 0 0.0 0 +chr6 72470305 0 0 0.0 0 +chr6 72512360 0 0 0.0 0 +chr6 72546657 0 0 0.0 0 +chr6 72653528 0 0 0.0 0 +chr6 72720030 0 0 0.0 0 +chr6 72911672 0 0 0.0 0 +chr6 72935511 0 0 0.0 0 +chr6 72952496 0 0 0.0 0 +chr6 73077199 0 0 0.0 0 +chr6 73124917 0 0 0.0 0 +chr6 73153065 0 0 0.0 0 +chr6 73165513 0 0 0.0 0 +chr6 73204382 0 0 0.0 0 +chr6 73224387 0 0 0.0 0 +chr6 73322684 0 1 0.0196 0 +chr6 73391504 0 0 0.0 0 +chr6 73419168 0 0 0.0 0 +chr6 73636982 0 0 0.0 0 +chr6 73710834 0 0 0.0 0 +chr6 73938874 0 0 0.0 0 +chr6 73972396 0 0 0.0 0 +chr6 74074573 0 0 0.0 0 +chr6 74084324 0 0 0.0 0 +chr6 74135987 0 0 0.0 0 +chr6 74288116 0 0 0.0 0 +chr6 74378314 0 0 0.0 0 +chr6 74646982 0 0 0.0 0 +chr6 74819139 0 0 0.0 0 +chr6 74854830 0 0 0.0 0 +chr6 74994129 0 0 0.0 0 +chr6 75048876 0 0 0.0 0 +chr6 75163623 0 0 0.0 0 +chr6 75301803 0 0 0.0 0 +chr6 75351834 0 0 0.0 0 +chr6 75514653 0 0 0.0 0 +chr6 75552827 0 0 0.0 0 +chr6 75821024 0 0 0.0 0 +chr6 75914990 0 0 0.0 0 +chr6 76030140 0 0 0.0 0 +chr6 76143007 0 0 0.0 0 +chr6 76184014 0 0 0.0 0 +chr6 76307882 0 0 0.0 0 +chr6 76327104 0 1 0.0294 0 +chr6 76783366 0 0 0.0 0 +chr6 76849592 0 0 0.0 0 +chr6 77363489 0 0 0.0 0 +chr6 77776468 0 0 0.0 0 +chr6 77876575 0 0 0.0 0 +chr6 77880858 0 0 0.0 0 +chr6 78145381 0 0 0.0 0 +chr6 78194642 0 0 0.0 0 +chr6 78211431 0 0 0.0 0 +chr6 78259435 0 0 0.0 0 +chr6 78266852 0 0 0.0 0 +chr6 78454179 0 0 0.0 0 +chr6 78655697 0 0 0.0 0 +chr6 78693313 0 0 0.0 0 +chr6 78733715 0 0 0.0 0 +chr6 78745695 0 0 0.0 0 +chr6 78942532 0 0 0.0 0 +chr6 79021703 0 0 0.0 0 +chr6 79256593 0 0 0.0 0 +chr6 79527469 0 0 0.0 0 +chr6 79551847 0 0 0.0 0 +chr6 79767646 0 0 0.0 0 +chr6 79848467 0 0 0.0 0 +chr6 79943326 0 0 0.0 0 +chr6 79994523 0 0 0.0 0 +chr6 80330861 0 0 0.0 0 +chr6 80474981 0 0 0.0 0 +chr6 80766180 0 0 0.0 0 +chr6 80799673 0 0 0.0 0 +chr6 80813288 0 0 0.0 0 +chr6 80863365 0 0 0.0 0 +chr6 81083128 0 0 0.0 0 +chr6 81235869 0 0 0.0 0 +chr6 81263376 0 0 0.0 0 +chr6 81493375 0 0 0.0 0 +chr6 81538730 0 0 0.0 0 +chr6 81869886 0 0 0.0 0 +chr6 82014743 0 0 0.0 0 +chr6 82038841 0 0 0.0 0 +chr6 82103676 0 0 0.0 0 +chr6 82190340 0 0 0.0 0 +chr6 82348051 0 0 0.0 0 +chr6 82364051 0 0 0.0 0 +chr6 82428250 0 0 0.0 0 +chr6 82512571 0 0 0.0 0 +chr6 82575601 0 0 0.0 0 +chr6 82590590 0 0 0.0 0 +chr6 82625543 0 0 0.0 0 +chr6 82667633 0 0 0.0 0 +chr6 82944442 0 0 0.0 0 +chr6 82991391 0 0 0.0 0 +chr6 83099919 0 0 0.0 0 +chr6 83197745 0 0 0.0 0 +chr6 83220094 0 0 0.0 0 +chr6 83258772 0 0 0.0 0 +chr6 83539468 0 0 0.0 0 +chr6 83547321 0 0 0.0 0 +chr6 83562512 0 0 0.0 0 +chr6 83586194 0 0 0.0 0 +chr6 83593627 0 0 0.0 0 +chr6 83838200 0 0 0.0 0 +chr6 84054947 0 0 0.0 0 +chr6 84064108 0 0 0.0 0 +chr6 84089270 0 0 0.0 0 +chr6 84133144 0 0 0.0 0 +chr6 84287829 0 0 0.0 0 +chr6 84357640 0 0 0.0 0 +chr6 84625033 0 0 0.0 0 +chr6 84773058 0 0 0.0 0 +chr6 84978286 0 0 0.0 0 +chr6 84996222 0 1 0.0147 0 +chr6 85012577 0 0 0.0 0 +chr6 85318572 0 0 0.0 0 +chr6 85345128 0 0 0.0 0 +chr6 85370898 0 0 0.0 0 +chr6 85500627 0 0 0.0 0 +chr6 85628041 0 2 0.0417 0 +chr6 85700045 0 0 0.0 0 +chr6 85710062 0 0 0.0 0 +chr6 85878778 0 0 0.0 0 +chr6 85879850 0 0 0.0 0 +chr6 85926147 0 0 0.0 0 +chr6 85936989 0 0 0.0 0 +chr6 86057096 0 0 0.0 0 +chr6 86065657 0 0 0.0 0 +chr6 86228236 0 0 0.0 0 +chr6 86276263 0 0 0.0 0 +chr6 86291776 0 0 0.0 0 +chr6 86427603 0 0 0.0 0 +chr6 86491907 0 0 0.0 0 +chr6 86590946 0 0 0.0 0 +chr6 86745932 0 0 0.0 0 +chr6 86879378 0 0 0.0 0 +chr6 87302239 0 0 0.0 0 +chr6 87441368 0 0 0.0 0 +chr6 87706811 0 0 0.0 0 +chr6 87727836 0 0 0.0 0 +chr6 87844610 0 0 0.0 0 +chr6 87991063 0 0 0.0 0 +chr6 88007498 0 0 0.0 0 +chr6 88300722 0 0 0.0 0 +chr6 88312843 0 0 0.0 0 +chr6 88489291 0 0 0.0 0 +chr6 88845425 0 0 0.0 0 +chr6 88944563 0 0 0.0 0 +chr6 89018799 0 0 0.0 0 +chr6 89079686 0 0 0.0 0 +chr6 89167832 0 1 0.0114 0 +chr6 89194294 0 0 0.0 0 +chr6 89244406 0 0 0.0 0 +chr6 89352877 0 0 0.0 0 +chr6 89501142 0 0 0.0 0 +chr6 89716080 0 0 0.0 0 +chr6 89804962 0 0 0.0 0 +chr6 89917683 0 0 0.0 0 +chr6 89998806 0 0 0.0 0 +chr6 90080602 0 0 0.0 0 +chr6 90116055 0 0 0.0 0 +chr6 90236599 0 0 0.0 0 +chr6 90266056 0 0 0.0 0 +chr6 90363762 0 0 0.0 0 +chr6 90390329 0 0 0.0 0 +chr6 90500503 0 0 0.0 0 +chr6 90563286 0 0 0.0 0 +chr6 90623957 0 0 0.0 0 +chr6 90654153 0 0 0.0 0 +chr6 90681157 0 0 0.0 0 +chr6 90812824 0 0 0.0 0 +chr6 90816674 0 0 0.0 0 +chr6 90831021 0 0 0.0 0 +chr6 90868530 0 0 0.0 0 +chr6 90872790 0 0 0.0 0 +chr6 90873309 0 0 0.0 0 +chr6 90932206 0 0 0.0 0 +chr6 90941876 0 0 0.0 0 +chr6 90981731 0 0 0.0 0 +chr6 91127347 0 0 0.0 0 +chr6 91381355 0 0 0.0 0 +chr6 91868574 0 0 0.0 0 +chr6 92189004 0 0 0.0 0 +chr6 92200872 0 0 0.0 0 +chr6 92443303 0 0 0.0 0 +chr6 92508325 0 0 0.0 0 +chr6 92593199 0 0 0.0 0 +chr6 92693676 0 0 0.0 0 +chr6 92699141 0 0 0.0 0 +chr6 92870069 0 0 0.0 0 +chr6 93199739 0 0 0.0 0 +chr6 93464425 0 0 0.0 0 +chr6 93474759 0 0 0.0 0 +chr6 93626480 0 0 0.0 0 +chr6 93668637 0 0 0.0 0 +chr6 93681064 0 0 0.0 0 +chr6 93718890 0 0 0.0 0 +chr6 93758780 0 0 0.0 0 +chr6 93764887 0 0 0.0 0 +chr6 93767717 0 0 0.0 0 +chr6 93772012 0 0 0.0 0 +chr6 93857331 0 0 0.0 0 +chr6 93944497 0 0 0.0 0 +chr6 94145993 0 0 0.0 0 +chr6 94218322 0 0 0.0 0 +chr6 94340118 0 0 0.0 0 +chr6 94474929 0 0 0.0 0 +chr6 94672677 0 0 0.0 0 +chr6 94680255 0 0 0.0 0 +chr6 94792582 0 0 0.0 0 +chr6 94797780 0 0 0.0 0 +chr6 94819243 0 0 0.0 0 +chr6 95075757 0 0 0.0 0 +chr6 95143882 0 0 0.0 0 +chr6 95175061 0 0 0.0 0 +chr6 95196360 0 0 0.0 0 +chr6 95349654 0 0 0.0 0 +chr6 95357917 0 0 0.0 0 +chr6 95374186 0 0 0.0 0 +chr6 95636842 0 0 0.0 0 +chr6 95654879 0 0 0.0 0 +chr6 95660394 0 0 0.0 0 +chr6 95857330 0 0 0.0 0 +chr6 95916553 0 0 0.0 0 +chr6 96216124 0 0 0.0 0 +chr6 96418193 0 0 0.0 0 +chr6 96616064 0 0 0.0 0 +chr6 96627454 0 0 0.0 0 +chr6 96644365 0 0 0.0 0 +chr6 96838423 0 1 0.0143 0 +chr6 96992347 0 0 0.0 0 +chr6 97007904 0 0 0.0 0 +chr6 97119485 0 0 0.0 0 +chr6 97144719 0 0 0.0 0 +chr6 97884004 0 0 0.0 0 +chr6 98004860 0 0 0.0 0 +chr6 98073344 0 0 0.0 0 +chr6 98269624 0 0 0.0 0 +chr6 98304194 0 0 0.0 0 +chr6 98363373 0 0 0.0 0 +chr6 98518503 0 0 0.0 0 +chr6 98527681 0 0 0.0 0 +chr6 98564767 0 0 0.0 0 +chr6 98642674 0 0 0.0 0 +chr6 98732780 0 0 0.0 0 +chr6 98752882 0 1 0.0244 0 +chr6 98876907 0 0 0.0 0 +chr6 98946616 0 0 0.0 0 +chr6 99068875 0 0 0.0 0 +chr6 99271213 0 0 0.0 0 +chr6 99296870 0 0 0.0 0 +chr6 99367131 0 0 0.0 0 +chr6 99560190 0 0 0.0 0 +chr6 99620139 0 0 0.0 0 +chr6 99681530 0 0 0.0 0 +chr6 99836926 0 0 0.0 0 +chr6 100060786 0 0 0.0 0 +chr6 100077816 0 0 0.0 0 +chr6 100110950 0 1 0.0156 0 +chr6 100345865 0 0 0.0 0 +chr6 100349118 0 0 0.0 0 +chr6 100427146 0 0 0.0 0 +chr6 100537705 0 0 0.0 0 +chr6 100627486 0 0 0.0 0 +chr6 100967094 0 0 0.0 0 +chr6 101340568 0 0 0.0 0 +chr6 101606993 0 0 0.0 0 +chr6 101620914 0 0 0.0 0 +chr6 101650586 0 0 0.0 0 +chr6 101673038 0 0 0.0 0 +chr6 101798561 0 0 0.0 0 +chr6 101986784 0 0 0.0 0 +chr6 102216537 0 0 0.0 0 +chr6 102290076 0 0 0.0 0 +chr6 102524883 0 0 0.0 0 +chr6 102792988 0 0 0.0 0 +chr6 102884243 0 0 0.0 0 +chr6 102890180 0 0 0.0 0 +chr6 103357667 0 0 0.0 0 +chr6 103593170 0 0 0.0 0 +chr6 103609267 0 0 0.0 0 +chr6 103764274 0 0 0.0 0 +chr6 103784077 0 1 0.0145 0 +chr6 103872873 0 0 0.0 0 +chr6 103882408 0 0 0.0 0 +chr6 103934356 0 0 0.0 0 +chr6 104027635 0 0 0.0 0 +chr6 104034510 0 0 0.0 0 +chr6 104085644 0 0 0.0 0 +chr6 104184483 0 0 0.0 0 +chr6 104375474 0 0 0.0 0 +chr6 104460616 0 0 0.0 0 +chr6 104515844 0 1 0.0238 0 +chr6 104554173 0 0 0.0 0 +chr6 104586302 0 0 0.0 0 +chr6 104596603 0 0 0.0 0 +chr6 104800571 0 0 0.0 0 +chr6 104882733 0 1 0.0145 0 +chr6 104910888 0 0 0.0 0 +chr6 104983248 0 0 0.0 0 +chr6 105145198 0 0 0.0 0 +chr6 105360908 0 0 0.0 0 +chr6 105536205 0 0 0.0 0 +chr6 105560666 0 0 0.0 0 +chr6 105731908 0 0 0.0 0 +chr6 105908042 0 0 0.0 0 +chr6 106064780 0 0 0.0 0 +chr6 106066106 0 0 0.0 0 +chr6 106146369 0 0 0.0 0 +chr6 106363551 0 0 0.0 0 +chr6 106487988 0 0 0.0 0 +chr6 106575494 0 0 0.0 0 +chr6 106853578 0 0 0.0 0 +chr6 107031022 0 0 0.0 0 +chr6 107243067 0 0 0.0 0 +chr6 107277157 0 0 0.0 0 +chr6 107421861 0 0 0.0 0 +chr6 107678268 0 0 0.0 0 +chr6 107705085 0 0 0.0 0 +chr6 108095992 0 0 0.0 0 +chr6 108375671 0 0 0.0 0 +chr6 108915943 0 0 0.0 0 +chr6 108929607 0 0 0.0 0 +chr6 109442342 0 0 0.0 0 +chr6 109450072 0 0 0.0 0 +chr6 109502465 0 0 0.0 0 +chr6 109535431 0 0 0.0 0 +chr6 109687984 0 0 0.0 0 +chr6 109849755 0 0 0.0 0 +chr6 109852764 0 0 0.0 0 +chr6 110020212 0 1 0.0294 0 +chr6 110044549 0 0 0.0 0 +chr6 110203537 0 0 0.0 0 +chr6 110204106 0 0 0.0 0 +chr6 110303456 0 0 0.0 0 +chr6 110307383 0 0 0.0 0 +chr6 110320179 0 0 0.0 0 +chr6 110336294 0 0 0.0 0 +chr6 110377482 0 0 0.0 0 +chr6 110534690 0 0 0.0 0 +chr6 110769906 0 0 0.0 0 +chr6 110987603 0 0 0.0 0 +chr6 111502712 0 0 0.0 0 +chr6 111576608 0 0 0.0 0 +chr6 111598123 0 0 0.0 0 +chr6 111605427 0 1 0.0139 0 +chr6 111623650 0 0 0.0 0 +chr6 111747627 0 0 0.0 0 +chr6 111783635 0 0 0.0 0 +chr6 111845749 0 0 0.0 0 +chr6 112027144 0 0 0.0 0 +chr6 112100723 0 0 0.0 0 +chr6 112106706 0 0 0.0 0 +chr6 112181217 0 0 0.0 0 +chr6 112219298 0 0 0.0 0 +chr6 112268709 0 0 0.0 0 +chr6 112270298 0 0 0.0 0 +chr6 112367369 0 0 0.0 0 +chr6 112408754 0 0 0.0 0 +chr6 112541624 0 0 0.0 0 +chr6 112632464 0 0 0.0 0 +chr6 112685621 0 0 0.0 0 +chr6 112787443 0 0 0.0 0 +chr6 112979870 0 0 0.0 0 +chr6 113188630 0 0 0.0 0 +chr6 113191951 0 0 0.0 0 +chr6 113224762 0 0 0.0 0 +chr6 113399094 0 0 0.0 0 +chr6 113402395 0 0 0.0 0 +chr6 113420093 0 0 0.0 0 +chr6 113438154 0 0 0.0 0 +chr6 113448643 0 0 0.0 0 +chr6 113586534 0 0 0.0 0 +chr6 113815859 0 0 0.0 0 +chr6 113844236 0 0 0.0 0 +chr6 113888443 0 0 0.0 0 +chr6 114015865 0 0 0.0 0 +chr6 114020600 0 0 0.0 0 +chr6 114031673 0 0 0.0 0 +chr6 114102371 0 0 0.0 0 +chr6 114188704 0 0 0.0 0 +chr6 114192696 0 0 0.0 0 +chr6 114230879 0 0 0.0 0 +chr6 114425875 0 0 0.0 0 +chr6 114928497 0 0 0.0 0 +chr6 115051114 0 0 0.0 0 +chr6 115126831 0 0 0.0 0 +chr6 115212128 0 0 0.0 0 +chr6 115220367 0 0 0.0 0 +chr6 115274324 0 0 0.0 0 +chr6 115276897 0 0 0.0 0 +chr6 115289140 0 0 0.0 0 +chr6 115336200 0 0 0.0 0 +chr6 115394457 0 0 0.0 0 +chr6 115555338 0 0 0.0 0 +chr6 115643178 0 0 0.0 0 +chr6 115646001 0 0 0.0 0 +chr6 115815827 0 1 0.0196 0 +chr6 115839757 0 0 0.0 0 +chr6 115972912 0 0 0.0 0 +chr6 115998032 0 0 0.0 0 +chr6 116069906 0 0 0.0 0 +chr6 116097694 0 0 0.0 0 +chr6 116558860 0 0 0.0 0 +chr6 116681810 0 0 0.0 0 +chr6 116892834 0 0 0.0 0 +chr6 117126444 0 0 0.0 0 +chr6 117173876 0 0 0.0 0 +chr6 117645913 0 0 0.0 0 +chr6 117646431 0 0 0.0 0 +chr6 117655703 0 0 0.0 0 +chr6 117685181 0 0 0.0 0 +chr6 117932281 0 0 0.0 0 +chr6 118046330 0 0 0.0 0 +chr6 118097120 0 0 0.0 0 +chr6 118100326 0 0 0.0 0 +chr6 118120525 0 0 0.0 0 +chr6 118142146 0 0 0.0 0 +chr6 118274093 0 0 0.0 0 +chr6 118309820 0 0 0.0 0 +chr6 118322164 0 1 0.0526 0 +chr6 118342414 0 0 0.0 0 +chr6 118384053 0 0 0.0 0 +chr6 118432792 0 0 0.0 0 +chr6 118471174 0 0 0.0 0 +chr6 118598316 0 0 0.0 0 +chr6 118670928 0 0 0.0 0 +chr6 118693074 0 0 0.0 0 +chr6 118775755 0 0 0.0 0 +chr6 118954806 0 0 0.0 0 +chr6 119138287 0 0 0.0 0 +chr6 119286574 0 0 0.0 0 +chr6 119563746 0 0 0.0 0 +chr6 119587899 0 0 0.0 0 +chr6 119614000 0 0 0.0 0 +chr6 119643846 0 0 0.0 0 +chr6 119759248 0 0 0.0 0 +chr6 119768576 0 0 0.0 0 +chr6 119966907 0 0 0.0 0 +chr6 120262688 0 0 0.0 0 +chr6 120267129 0 0 0.0 0 +chr6 120271077 0 0 0.0 0 +chr6 120405376 0 0 0.0 0 +chr6 120461899 0 0 0.0 0 +chr6 120469837 0 0 0.0 0 +chr6 120587166 0 0 0.0 0 +chr6 120786568 0 0 0.0 0 +chr6 120794051 0 0 0.0 0 +chr6 120815499 0 0 0.0 0 +chr6 120842836 0 0 0.0 0 +chr6 120938129 1 3 0.0462 1 +chr6 121017068 0 0 0.0 0 +chr6 121145133 0 0 0.0 0 +chr6 121194263 0 0 0.0 0 +chr6 121268324 0 0 0.0 0 +chr6 121313756 0 0 0.0 0 +chr6 121412378 0 0 0.0 0 +chr6 121620923 0 0 0.0 0 +chr6 121725091 0 0 0.0 0 +chr6 121738336 0 0 0.0 0 +chr6 121805649 0 0 0.0 0 +chr6 121855828 0 0 0.0 0 +chr6 121906960 0 0 0.0 0 +chr6 121937002 0 0 0.0 0 +chr6 121952897 0 0 0.0 0 +chr6 122108582 0 0 0.0 0 +chr6 122265026 0 0 0.0 0 +chr6 122424177 0 0 0.0 0 +chr6 122554130 0 0 0.0 0 +chr6 122566175 0 0 0.0 0 +chr6 122668687 0 0 0.0 0 +chr6 122810661 0 0 0.0 0 +chr6 122820208 0 0 0.0 0 +chr6 122972786 0 0 0.0 0 +chr6 123012616 0 0 0.0 0 +chr6 123016986 0 0 0.0 0 +chr6 123075517 0 0 0.0 0 +chr6 123150338 0 0 0.0 0 +chr6 123309572 0 0 0.0 0 +chr6 123419021 0 0 0.0 0 +chr6 123709913 0 0 0.0 0 +chr6 123816840 0 0 0.0 0 +chr6 123828119 0 0 0.0 0 +chr6 123854997 0 0 0.0 0 +chr6 123860892 0 0 0.0 0 +chr6 123897262 0 0 0.0 0 +chr6 124019553 0 0 0.0 0 +chr6 124468245 0 0 0.0 0 +chr6 124470177 0 0 0.0 0 +chr6 124623172 0 0 0.0 0 +chr6 124682614 0 0 0.0 0 +chr6 124863622 0 0 0.0 0 +chr6 124992582 0 2 0.0345 0 +chr6 125259329 0 0 0.0 0 +chr6 125448506 0 0 0.0 0 +chr6 125627613 0 0 0.0 0 +chr6 125705414 0 0 0.0 0 +chr6 125710404 0 0 0.0 0 +chr6 125722631 0 0 0.0 0 +chr6 125766623 0 0 0.0 0 +chr6 125823601 0 0 0.0 0 +chr6 126035670 0 0 0.0 0 +chr6 126042336 0 0 0.0 0 +chr6 126526263 0 0 0.0 0 +chr6 126727127 0 0 0.0 0 +chr6 126755968 0 0 0.0 0 +chr6 126765528 0 0 0.0 0 +chr6 126790756 0 0 0.0 0 +chr6 126881185 0 0 0.0 0 +chr6 126888844 0 0 0.0 0 +chr6 127229340 0 0 0.0 0 +chr6 127283190 0 0 0.0 0 +chr6 127333624 0 0 0.0 0 +chr6 127416234 0 0 0.0 0 +chr6 127475005 0 0 0.0 0 +chr6 127589929 0 0 0.0 0 +chr6 127819015 0 0 0.0 0 +chr6 127901172 0 0 0.0 0 +chr6 128329072 0 0 0.0 0 +chr6 128420016 0 0 0.0 0 +chr6 128561101 0 0 0.0 0 +chr6 128732576 0 0 0.0 0 +chr6 128968798 1 26 0.3421 1 +chr6 129315989 0 0 0.0 0 +chr6 129350488 0 0 0.0 0 +chr6 129358213 0 0 0.0 0 +chr6 129405539 0 0 0.0 0 +chr6 129411295 0 0 0.0 0 +chr6 129464374 0 0 0.0 0 +chr6 129569271 0 0 0.0 0 +chr6 129569816 0 0 0.0 0 +chr6 129713396 0 0 0.0 0 +chr6 129728293 0 0 0.0 0 +chr6 129756645 0 0 0.0 0 +chr6 129784345 0 0 0.0 0 +chr6 129889046 0 0 0.0 0 +chr6 130023933 0 0 0.0 0 +chr6 130174047 0 0 0.0 0 +chr6 130206320 0 0 0.0 0 +chr6 130294481 0 0 0.0 0 +chr6 130308304 0 0 0.0 0 +chr6 130371238 0 0 0.0 0 +chr6 130473066 0 0 0.0 0 +chr6 130580819 0 0 0.0 0 +chr6 130640814 0 0 0.0 0 +chr6 130652514 0 0 0.0 0 +chr6 130661806 0 0 0.0 0 +chr6 130672893 0 0 0.0 0 +chr6 131031171 0 0 0.0 0 +chr6 131061246 0 0 0.0 0 +chr6 131109205 0 0 0.0 0 +chr6 131352828 0 0 0.0 0 +chr6 131593759 0 0 0.0 0 +chr6 131679939 0 1 0.0164 0 +chr6 131687130 0 0 0.0 0 +chr6 131791713 0 0 0.0 0 +chr6 131918517 0 0 0.0 0 +chr6 132135318 0 0 0.0 0 +chr6 132656151 0 0 0.0 0 +chr6 133131800 0 0 0.0 0 +chr6 133154377 0 0 0.0 0 +chr6 133202787 0 0 0.0 0 +chr6 133396490 0 0 0.0 0 +chr6 133590498 0 0 0.0 0 +chr6 133593331 0 0 0.0 0 +chr6 133620106 0 0 0.0 0 +chr6 133621043 0 0 0.0 0 +chr6 133690437 0 0 0.0 0 +chr6 133722968 0 0 0.0 0 +chr6 133744833 0 0 0.0 0 +chr6 133806327 0 0 0.0 0 +chr6 133812975 0 0 0.0 0 +chr6 133889219 0 0 0.0 0 +chr6 133904707 0 0 0.0 0 +chr6 134114874 0 0 0.0 0 +chr6 134175713 0 0 0.0 0 +chr6 134353896 0 0 0.0 0 +chr6 134460175 1 68 0.7816 1 +chr6 134534733 0 0 0.0 0 +chr6 134578797 0 0 0.0 0 +chr6 134589834 0 0 0.0 0 +chr6 134811071 0 0 0.0 0 +chr6 135155656 0 0 0.0 0 +chr6 135203830 0 0 0.0 0 +chr6 135223358 0 0 0.0 0 +chr6 135232879 0 0 0.0 0 +chr6 135243652 0 0 0.0 0 +chr6 135334161 0 0 0.0 0 +chr6 135518066 0 0 0.0 0 +chr6 135620098 0 0 0.0 0 +chr6 135924402 0 0 0.0 0 +chr6 135929840 0 0 0.0 0 +chr6 135947736 0 0 0.0 0 +chr6 135992083 0 0 0.0 0 +chr6 136160811 0 0 0.0 0 +chr6 136322639 0 0 0.0 0 +chr6 136352092 0 0 0.0 0 +chr6 136379685 0 0 0.0 0 +chr6 136519000 0 0 0.0 0 +chr6 136566265 0 0 0.0 0 +chr6 136636529 0 0 0.0 0 +chr6 136701574 0 0 0.0 0 +chr6 136748101 0 0 0.0 0 +chr6 136896492 0 0 0.0 0 +chr6 136937276 0 0 0.0 0 +chr6 137152075 0 0 0.0 0 +chr6 137320170 0 0 0.0 0 +chr6 137563881 1 16 0.3636 1 +chr6 137603876 0 0 0.0 0 +chr6 137766669 0 0 0.0 0 +chr6 137943197 0 0 0.0 0 +chr6 137989457 0 0 0.0 0 +chr6 138372925 0 0 0.0 0 +chr6 138447030 0 0 0.0 0 +chr6 138593734 0 0 0.0 0 +chr6 138739723 0 0 0.0 0 +chr6 138786290 0 0 0.0 0 +chr6 138919202 0 0 0.0 0 +chr6 139154002 0 0 0.0 0 +chr6 139251928 0 0 0.0 0 +chr6 139298681 0 0 0.0 0 +chr6 139312030 0 0 0.0 0 +chr6 139382322 0 0 0.0 0 +chr6 139447558 0 0 0.0 0 +chr6 139540937 0 0 0.0 0 +chr6 139551400 0 0 0.0 0 +chr6 139797125 0 0 0.0 0 +chr6 139864511 0 0 0.0 0 +chr6 140417441 0 0 0.0 0 +chr6 140507675 0 0 0.0 0 +chr6 140644697 0 0 0.0 0 +chr6 140655431 0 0 0.0 0 +chr6 140656906 0 0 0.0 0 +chr6 140693663 0 0 0.0 0 +chr6 140696846 0 0 0.0 0 +chr6 140766011 0 0 0.0 0 +chr6 141375452 0 0 0.0 0 +chr6 141644979 0 0 0.0 0 +chr6 141902403 0 0 0.0 0 +chr6 142043663 0 0 0.0 0 +chr6 142190810 0 0 0.0 0 +chr6 142493379 0 0 0.0 0 +chr6 142658688 0 0 0.0 0 +chr6 142693349 0 0 0.0 0 +chr6 142768649 0 0 0.0 0 +chr6 142820210 0 0 0.0 0 +chr6 142957113 0 0 0.0 0 +chr6 143035243 0 0 0.0 0 +chr6 143086073 0 0 0.0 0 +chr6 143165562 1 47 0.7344 1 +chr6 143173324 0 0 0.0 0 +chr6 143407031 0 0 0.0 0 +chr6 143417051 0 0 0.0 0 +chr6 143541618 0 0 0.0 0 +chr6 143603999 0 0 0.0 0 +chr6 143621222 0 0 0.0 0 +chr6 143684467 0 0 0.0 0 +chr6 143842412 0 0 0.0 0 +chr6 143901100 0 0 0.0 0 +chr6 144019205 0 0 0.0 0 +chr6 144112264 0 0 0.0 0 +chr6 144125645 0 0 0.0 0 +chr6 144215721 0 0 0.0 0 +chr6 144329572 0 1 0.0135 0 +chr6 144341986 0 0 0.0 0 +chr6 144356306 0 0 0.0 0 +chr6 144626579 0 0 0.0 0 +chr6 144659284 0 0 0.0 0 +chr6 144744598 1 17 0.5152 1 +chr6 144749117 0 0 0.0 0 +chr6 144764921 0 1 0.0233 0 +chr6 144780710 0 0 0.0 0 +chr6 144852122 0 0 0.0 0 +chr6 145002860 1 59 0.831 1 +chr6 145021090 0 0 0.0 0 +chr6 145074208 0 0 0.0 0 +chr6 145472244 0 0 0.0 0 +chr6 145573737 0 0 0.0 0 +chr6 145637454 2 7 0.175 1 +chr6 146063129 0 0 0.0 0 +chr6 146164769 0 0 0.0 0 +chr6 146280746 0 0 0.0 0 +chr6 146322210 0 0 0.0 0 +chr6 146324263 0 0 0.0 0 +chr6 146336320 0 0 0.0 0 +chr6 146445773 0 0 0.0 0 +chr6 146514974 0 0 0.0 0 +chr6 146658411 0 0 0.0 0 +chr6 146738369 0 0 0.0 0 +chr6 146828649 0 0 0.0 0 +chr6 146920561 0 0 0.0 0 +chr6 146937383 0 0 0.0 0 +chr6 147241394 0 0 0.0 0 +chr6 147408272 0 0 0.0 0 +chr6 147495273 0 0 0.0 0 +chr6 147511737 0 0 0.0 0 +chr6 147537681 0 1 0.0625 0 +chr6 147560347 0 0 0.0 0 +chr6 147609528 0 0 0.0 0 +chr6 147674653 0 0 0.0 0 +chr6 147804058 0 0 0.0 0 +chr6 147837342 0 0 0.0 0 +chr6 147841080 0 0 0.0 0 +chr6 148192583 0 0 0.0 0 +chr6 148267639 0 0 0.0 0 +chr6 148329106 0 0 0.0 0 +chr6 148413595 0 0 0.0 0 +chr6 148562488 0 0 0.0 0 +chr6 148587644 0 0 0.0 0 +chr6 148631033 0 0 0.0 0 +chr6 148670913 0 0 0.0 0 +chr6 149216120 0 0 0.0 0 +chr6 149435828 0 0 0.0 0 +chr6 149546414 0 0 0.0 0 +chr6 149652839 0 0 0.0 0 +chr6 149859846 0 0 0.0 0 +chr6 149922408 0 0 0.0 0 +chr6 149939233 0 0 0.0 0 +chr6 149942676 0 0 0.0 0 +chr6 149989587 0 0 0.0 0 +chr6 150024870 0 0 0.0 0 +chr6 150037407 0 0 0.0 0 +chr6 150112194 0 0 0.0 0 +chr6 150133232 0 0 0.0 0 +chr6 150202491 0 0 0.0 0 +chr6 150419355 0 0 0.0 0 +chr6 150517356 0 0 0.0 0 +chr6 150538917 0 0 0.0 0 +chr6 150615701 0 0 0.0 0 +chr6 150624238 0 0 0.0 0 +chr6 150669374 0 0 0.0 0 +chr6 150680215 0 0 0.0 0 +chr6 150856331 0 0 0.0 0 +chr6 150949716 0 0 0.0 0 +chr6 151098453 0 0 0.0 0 +chr6 151342397 0 0 0.0 0 +chr6 151616555 0 0 0.0 0 +chr6 151656697 0 0 0.0 0 +chr6 151662393 0 0 0.0 0 +chr6 151666785 0 0 0.0 0 +chr6 151743235 0 0 0.0 0 +chr6 151817213 0 0 0.0 0 +chr6 151824961 0 0 0.0 0 +chr6 151921089 0 0 0.0 0 +chr6 152194601 0 0 0.0 0 +chr6 152209507 0 0 0.0 0 +chr6 152430910 0 0 0.0 0 +chr6 152643582 0 1 0.0164 0 +chr6 152646582 0 0 0.0 0 +chr6 152661643 0 0 0.0 0 +chr6 152702212 0 0 0.0 0 +chr6 152757982 0 0 0.0 0 +chr6 152982869 0 0 0.0 0 +chr6 153208529 0 0 0.0 0 +chr6 153390198 0 0 0.0 0 +chr6 153406943 0 0 0.0 0 +chr6 153540003 0 0 0.0 0 +chr6 153547603 0 0 0.0 0 +chr6 153701943 0 0 0.0 0 +chr6 153743894 0 0 0.0 0 +chr6 153785649 0 0 0.0 0 +chr6 153884994 0 0 0.0 0 +chr6 153899665 0 0 0.0 0 +chr6 154140777 0 0 0.0 0 +chr6 154308700 0 0 0.0 0 +chr6 154354336 0 0 0.0 0 +chr6 154355118 0 0 0.0 0 +chr6 154395082 0 0 0.0 0 +chr6 154458907 0 0 0.0 0 +chr6 154514990 0 0 0.0 0 +chr6 154530094 0 0 0.0 0 +chr6 154636374 0 0 0.0 0 +chr6 154679023 0 0 0.0 0 +chr6 154712903 0 0 0.0 0 +chr6 154820334 0 0 0.0 0 +chr6 154882037 0 0 0.0 0 +chr6 154930907 0 0 0.0 0 +chr6 155003613 0 0 0.0 0 +chr6 155023661 0 0 0.0 0 +chr6 155040468 0 0 0.0 0 +chr6 155074930 0 0 0.0 0 +chr6 155345060 0 0 0.0 0 +chr6 155346168 0 0 0.0 0 +chr6 155422096 0 0 0.0 0 +chr6 155697945 0 0 0.0 0 +chr6 155748884 0 0 0.0 0 +chr6 155836642 0 0 0.0 0 +chr6 155959926 0 0 0.0 0 +chr6 156158380 0 0 0.0 0 +chr6 156213129 0 0 0.0 0 +chr6 156374613 0 0 0.0 0 +chr6 156392792 0 0 0.0 0 +chr6 156466456 0 0 0.0 0 +chr6 156487944 0 0 0.0 0 +chr6 156525832 0 0 0.0 0 +chr6 156637897 0 0 0.0 0 +chr6 156664354 0 0 0.0 0 +chr6 156814445 0 0 0.0 0 +chr6 156822523 0 0 0.0 0 +chr6 156824267 0 0 0.0 0 +chr6 156852053 0 0 0.0 0 +chr6 156908449 0 0 0.0 0 +chr6 156946499 0 0 0.0 0 +chr6 156949389 0 0 0.0 0 +chr6 157012371 0 0 0.0 0 +chr6 157190463 0 0 0.0 0 +chr6 157456717 0 0 0.0 0 +chr6 157647811 0 0 0.0 0 +chr6 157676511 0 0 0.0 0 +chr6 157718890 0 0 0.0 0 +chr6 157722097 0 0 0.0 0 +chr6 157933730 0 0 0.0 0 +chr6 157983411 0 0 0.0 0 +chr6 158158464 0 0 0.0 0 +chr6 158173782 0 0 0.0 0 +chr6 158177015 0 0 0.0 0 +chr6 158417015 0 0 0.0 0 +chr6 158625727 0 0 0.0 0 +chr6 158642719 0 0 0.0 0 +chr6 158690308 0 0 0.0 0 +chr6 158713228 0 0 0.0 0 +chr6 158767430 0 0 0.0 0 +chr6 158941373 0 0 0.0 0 +chr6 159015109 0 0 0.0 0 +chr6 159133310 0 0 0.0 0 +chr6 159176232 0 0 0.0 0 +chr6 159278263 0 0 0.0 0 +chr6 159481121 0 0 0.0 0 +chr6 159492921 0 0 0.0 0 +chr6 159747409 0 0 0.0 0 +chr6 159762444 0 0 0.0 0 +chr6 159845749 0 0 0.0 0 +chr6 159850418 0 0 0.0 0 +chr6 159967090 0 0 0.0 0 +chr6 160034225 0 0 0.0 0 +chr6 160042351 0 0 0.0 0 +chr6 160121969 0 0 0.0 0 +chr6 160302256 0 0 0.0 0 +chr6 160331570 0 0 0.0 0 +chr6 160373878 0 0 0.0 0 +chr6 160485431 0 0 0.0 0 +chr6 160571745 0 0 0.0 0 +chr6 160595372 0 0 0.0 0 +chr6 160674768 0 0 0.0 0 +chr6 160830365 0 0 0.0 0 +chr6 161116607 0 0 0.0 0 +chr6 161140813 0 0 0.0 0 +chr6 161159336 0 0 0.0 0 +chr6 161165020 0 0 0.0 0 +chr6 161380216 0 0 0.0 0 +chr6 161445310 0 0 0.0 0 +chr6 161460379 0 0 0.0 0 +chr6 161484768 0 0 0.0 0 +chr6 161529669 0 0 0.0 0 +chr6 161613210 0 0 0.0 0 +chr6 161676398 0 0 0.0 0 +chr6 162723493 0 0 0.0 0 +chr6 162783909 0 0 0.0 0 +chr6 162955836 0 0 0.0 0 +chr6 162997441 0 0 0.0 0 +chr6 163116825 0 0 0.0 0 +chr6 163157204 0 0 0.0 0 +chr6 163282936 0 0 0.0 0 +chr6 163314369 0 0 0.0 0 +chr6 163612425 0 0 0.0 0 +chr6 163768445 0 0 0.0 0 +chr6 163841622 0 0 0.0 0 +chr6 163856125 0 0 0.0 0 +chr6 163904211 0 0 0.0 0 +chr6 163963916 0 0 0.0 0 +chr6 164078964 0 0 0.0 0 +chr6 164101855 0 1 0.0182 0 +chr6 164122675 0 0 0.0 0 +chr6 164132266 0 0 0.0 0 +chr6 164308318 0 0 0.0 0 +chr6 164342282 0 0 0.0 0 +chr6 164617020 0 0 0.0 0 +chr6 164687506 0 0 0.0 0 +chr6 164760353 0 0 0.0 0 +chr6 164793733 0 0 0.0 0 +chr6 165212485 0 0 0.0 0 +chr6 165405152 0 0 0.0 0 +chr6 165438045 0 0 0.0 0 +chr6 165525540 0 0 0.0 0 +chr6 165644749 0 1 0.0172 0 +chr6 165662493 0 0 0.0 0 +chr6 165708146 0 0 0.0 0 +chr6 165767978 0 0 0.0 0 +chr6 165848487 0 0 0.0 0 +chr6 165852975 0 0 0.0 0 +chr6 165856581 0 0 0.0 0 +chr6 165998629 0 0 0.0 0 +chr6 166314028 0 0 0.0 0 +chr6 166379096 0 0 0.0 0 +chr6 166404616 0 0 0.0 0 +chr6 166457620 0 0 0.0 0 +chr6 166506908 0 0 0.0 0 +chr6 166652453 0 0 0.0 0 +chr6 166982035 0 0 0.0 0 +chr6 167037688 0 0 0.0 0 +chr6 167042458 0 0 0.0 0 +chr6 167125369 0 0 0.0 0 +chr6 167140758 0 0 0.0 0 +chr6 167176680 0 0 0.0 0 +chr6 167186101 0 0 0.0 0 +chr6 167286735 0 0 0.0 0 +chr6 167293461 0 0 0.0 0 +chr6 167339781 0 0 0.0 0 +chr6 167368986 0 0 0.0 0 +chr6 167378410 0 0 0.0 0 +chr6 167570916 0 0 0.0 0 +chr6 167647518 0 0 0.0 0 +chr6 167765372 0 0 0.0 0 +chr6 167769622 0 0 0.0 0 +chr6 167782984 0 0 0.0 0 +chr6 167805187 0 0 0.0 0 +chr6 167871203 0 0 0.0 0 +chr6 167888995 0 0 0.0 0 +chr6 167919127 0 0 0.0 0 +chr6 167975799 0 0 0.0 0 +chr6 168064180 0 0 0.0 0 +chr6 168103546 0 0 0.0 0 +chr6 168166495 0 0 0.0 0 +chr6 168242599 0 0 0.0 0 +chr6 168326806 0 0 0.0 0 +chr6 168336659 0 0 0.0 0 +chr6 168339997 0 0 0.0 0 +chr6 168452726 0 0 0.0 0 +chr6 168463360 0 0 0.0 0 +chr6 168633603 0 0 0.0 0 +chr6 168660787 0 0 0.0 0 +chr6 168766458 0 0 0.0 0 +chr6 168897251 0 0 0.0 0 +chr6 168915686 0 0 0.0 0 +chr6 168916318 0 0 0.0 0 +chr6 168941837 0 0 0.0 0 +chr6 168996308 0 0 0.0 0 +chr6 169160591 0 0 0.0 0 +chr6 169173945 0 0 0.0 0 +chr6 169232025 0 0 0.0 0 +chr6 169233373 0 0 0.0 0 +chr6 169234403 0 0 0.0 0 +chr6 169288278 0 0 0.0 0 +chr6 169399630 0 0 0.0 0 +chr6 169417768 0 0 0.0 0 +chr6 169448804 0 0 0.0 0 +chr6 169502724 0 1 0.0196 0 +chr6 169584545 0 0 0.0 0 +chr6 169625146 0 0 0.0 0 +chr6 169774413 0 0 0.0 0 +chr6 169843523 0 0 0.0 0 +chr6 169939059 0 0 0.0 0 +chr6 170049311 0 0 0.0 0 +chr6 170177060 0 0 0.0 0 +chr6 170260017 0 0 0.0 0 +chr6 170324698 0 0 0.0 0 +chr6 170680665 0 0 0.0 0 +chr6 170714630 0 0 0.0 0 +chr6 170721265 0 0 0.0 0 +chr6 170726803 0 0 0.0 0 +chr6 170728235 0 0 0.0 0 +chr6_GL000250v2_alt 321009 0 0 0.0 0 +chr6_GL000250v2_alt 745935 0 0 0.0 0 +chr6_GL000250v2_alt 778346 0 0 0.0 0 +chr6_GL000250v2_alt 1044346 0 0 0.0 0 +chr6_GL000250v2_alt 1260824 0 0 0.0 0 +chr6_GL000250v2_alt 1334083 0 0 0.0 0 +chr6_GL000250v2_alt 1669395 0 0 0.0 0 +chr6_GL000250v2_alt 1839928 0 0 0.0 0 +chr6_GL000250v2_alt 1882598 0 0 0.0 0 +chr6_GL000250v2_alt 3112050 0 0 0.0 0 +chr6_GL000250v2_alt 3149443 0 0 0.0 0 +chr6_GL000250v2_alt 3411497 0 0 0.0 0 +chr6_GL000250v2_alt 3700774 0 0 0.0 0 +chr6_GL000250v2_alt 3733579 0 0 0.0 0 +chr6_GL000250v2_alt 3833547 0 0 0.0 0 +chr6_GL000250v2_alt 4048191 0 0 0.0 0 +chr6_GL000250v2_alt 4113687 0 0 0.0 0 +chr6_GL000250v2_alt 4114198 0 0 0.0 0 +chr6_GL000251v2_alt 164077 0 0 0.0 0 +chr6_GL000251v2_alt 438720 0 0 0.0 0 +chr6_GL000251v2_alt 541861 0 0 0.0 0 +chr6_GL000251v2_alt 816814 0 0 0.0 0 +chr6_GL000251v2_alt 886596 0 0 0.0 0 +chr6_GL000251v2_alt 966726 0 0 0.0 0 +chr6_GL000251v2_alt 999137 0 0 0.0 0 +chr6_GL000251v2_alt 1201202 0 0 0.0 0 +chr6_GL000251v2_alt 1262296 0 0 0.0 0 +chr6_GL000251v2_alt 1482500 0 0 0.0 0 +chr6_GL000251v2_alt 1555762 0 0 0.0 0 +chr6_GL000251v2_alt 1819580 0 0 0.0 0 +chr6_GL000251v2_alt 1990145 0 0 0.0 0 +chr6_GL000251v2_alt 2032813 0 0 0.0 0 +chr6_GL000251v2_alt 2057963 0 0 0.0 0 +chr6_GL000251v2_alt 2254314 0 0 0.0 0 +chr6_GL000251v2_alt 2301500 0 0 0.0 0 +chr6_GL000251v2_alt 2382789 0 0 0.0 0 +chr6_GL000251v2_alt 2413343 0 0 0.0 0 +chr6_GL000251v2_alt 2425671 0 0 0.0 0 +chr6_GL000251v2_alt 2629877 0 0 0.0 0 +chr6_GL000251v2_alt 2806700 0 0 0.0 0 +chr6_GL000251v2_alt 2897277 0 0 0.0 0 +chr6_GL000251v2_alt 2940994 0 0 0.0 0 +chr6_GL000251v2_alt 3008039 0 0 0.0 0 +chr6_GL000251v2_alt 3028105 0 0 0.0 0 +chr6_GL000251v2_alt 3160708 0 0 0.0 0 +chr6_GL000251v2_alt 3256681 0 0 0.0 0 +chr6_GL000251v2_alt 3294072 0 0 0.0 0 +chr6_GL000251v2_alt 3306268 0 0 0.0 0 +chr6_GL000251v2_alt 3440937 0 0 0.0 0 +chr6_GL000251v2_alt 3461274 0 0 0.0 0 +chr6_GL000251v2_alt 3517234 0 0 0.0 0 +chr6_GL000251v2_alt 3806672 0 0 0.0 0 +chr6_GL000251v2_alt 3839427 0 0 0.0 0 +chr6_GL000251v2_alt 3943056 0 0 0.0 0 +chr6_GL000251v2_alt 4155625 0 0 0.0 0 +chr6_GL000251v2_alt 4220866 0 0 0.0 0 +chr6_GL000251v2_alt 4221378 0 0 0.0 0 +chr6_GL000251v2_alt 4584595 0 0 0.0 0 +chr6_GL000251v2_alt 4609366 0 0 0.0 0 +chr6_GL000251v2_alt 4609831 0 0 0.0 0 +chr6_GL000251v2_alt 4792233 0 0 0.0 0 +chr6_GL000252v2_alt 320989 0 0 0.0 0 +chr6_GL000252v2_alt 595867 0 0 0.0 0 +chr6_GL000252v2_alt 665644 0 0 0.0 0 +chr6_GL000252v2_alt 745797 0 0 0.0 0 +chr6_GL000252v2_alt 778208 0 0 0.0 0 +chr6_GL000252v2_alt 980375 0 0 0.0 0 +chr6_GL000252v2_alt 1041499 0 0 0.0 0 +chr6_GL000252v2_alt 1258650 0 0 0.0 0 +chr6_GL000252v2_alt 1331907 0 0 0.0 0 +chr6_GL000252v2_alt 1595745 0 0 0.0 0 +chr6_GL000252v2_alt 1766244 0 0 0.0 0 +chr6_GL000252v2_alt 1808917 0 0 0.0 0 +chr6_GL000252v2_alt 1834071 0 0 0.0 0 +chr6_GL000252v2_alt 2030573 0 0 0.0 0 +chr6_GL000252v2_alt 2078032 0 0 0.0 0 +chr6_GL000252v2_alt 2159326 0 0 0.0 0 +chr6_GL000252v2_alt 2190068 0 0 0.0 0 +chr6_GL000252v2_alt 2202403 0 0 0.0 0 +chr6_GL000252v2_alt 2406768 0 0 0.0 0 +chr6_GL000252v2_alt 2573853 0 0 0.0 0 +chr6_GL000252v2_alt 2778478 0 0 0.0 0 +chr6_GL000252v2_alt 2798545 0 0 0.0 0 +chr6_GL000252v2_alt 2931191 0 0 0.0 0 +chr6_GL000252v2_alt 3027213 0 0 0.0 0 +chr6_GL000252v2_alt 3064600 0 0 0.0 0 +chr6_GL000252v2_alt 3211285 0 0 0.0 0 +chr6_GL000252v2_alt 3231620 0 0 0.0 0 +chr6_GL000252v2_alt 3260964 0 0 0.0 0 +chr6_GL000252v2_alt 3264360 0 0 0.0 0 +chr6_GL000252v2_alt 3320303 0 0 0.0 0 +chr6_GL000252v2_alt 3609652 0 0 0.0 0 +chr6_GL000252v2_alt 3642427 0 0 0.0 0 +chr6_GL000252v2_alt 3986808 0 0 0.0 0 +chr6_GL000252v2_alt 4052377 0 0 0.0 0 +chr6_GL000252v2_alt 4052888 0 0 0.0 0 +chr6_GL000252v2_alt 4416586 0 0 0.0 0 +chr6_GL000252v2_alt 4441358 0 0 0.0 0 +chr6_GL000252v2_alt 4441823 0 0 0.0 0 +chr6_GL000253v2_alt 217875 0 0 0.0 0 +chr6_GL000253v2_alt 320944 0 0 0.0 0 +chr6_GL000253v2_alt 595826 0 0 0.0 0 +chr6_GL000253v2_alt 665280 0 0 0.0 0 +chr6_GL000253v2_alt 745399 0 0 0.0 0 +chr6_GL000253v2_alt 777810 0 0 0.0 0 +chr6_GL000253v2_alt 979942 0 0 0.0 0 +chr6_GL000253v2_alt 1041094 0 0 0.0 0 +chr6_GL000253v2_alt 1263842 0 0 0.0 0 +chr6_GL000253v2_alt 1336741 0 0 0.0 0 +chr6_GL000253v2_alt 1650130 0 0 0.0 0 +chr6_GL000253v2_alt 1820644 0 0 0.0 0 +chr6_GL000253v2_alt 1863322 0 0 0.0 0 +chr6_GL000253v2_alt 1888469 0 0 0.0 0 +chr6_GL000253v2_alt 2084843 0 0 0.0 0 +chr6_GL000253v2_alt 2132016 0 0 0.0 0 +chr6_GL000253v2_alt 2213257 0 0 0.0 0 +chr6_GL000253v2_alt 2243996 0 0 0.0 0 +chr6_GL000253v2_alt 2457966 0 0 0.0 0 +chr6_GL000253v2_alt 2634881 0 0 0.0 0 +chr6_GL000253v2_alt 2725493 0 0 0.0 0 +chr6_GL000253v2_alt 2835778 0 0 0.0 0 +chr6_GL000253v2_alt 2855828 0 0 0.0 0 +chr6_GL000253v2_alt 2988465 0 0 0.0 0 +chr6_GL000253v2_alt 3383902 0 0 0.0 0 +chr6_GL000253v2_alt 3673521 0 0 0.0 0 +chr6_GL000253v2_alt 3706366 0 0 0.0 0 +chr6_GL000253v2_alt 4098385 0 0 0.0 0 +chr6_GL000253v2_alt 4161368 0 0 0.0 0 +chr6_GL000253v2_alt 4226960 0 0 0.0 0 +chr6_GL000253v2_alt 4227471 0 0 0.0 0 +chr6_GL000253v2_alt 4592560 0 0 0.0 0 +chr6_GL000253v2_alt 4617332 0 0 0.0 0 +chr6_GL000253v2_alt 4617797 0 0 0.0 0 +chr6_GL000254v2_alt 218058 0 0 0.0 0 +chr6_GL000254v2_alt 321129 0 0 0.0 0 +chr6_GL000254v2_alt 596047 0 0 0.0 0 +chr6_GL000254v2_alt 665509 0 0 0.0 0 +chr6_GL000254v2_alt 745648 0 0 0.0 0 +chr6_GL000254v2_alt 778060 0 0 0.0 0 +chr6_GL000254v2_alt 980034 0 0 0.0 0 +chr6_GL000254v2_alt 1041165 0 0 0.0 0 +chr6_GL000254v2_alt 1347168 0 0 0.0 0 +chr6_GL000254v2_alt 1420081 0 0 0.0 0 +chr6_GL000254v2_alt 1854466 0 0 0.0 0 +chr6_GL000254v2_alt 1897139 0 0 0.0 0 +chr6_GL000254v2_alt 1922286 0 0 0.0 0 +chr6_GL000254v2_alt 2247170 0 0 0.0 0 +chr6_GL000254v2_alt 2277892 0 0 0.0 0 +chr6_GL000254v2_alt 2290230 0 0 0.0 0 +chr6_GL000254v2_alt 2491579 0 0 0.0 0 +chr6_GL000254v2_alt 2668485 0 0 0.0 0 +chr6_GL000254v2_alt 2872648 0 0 0.0 0 +chr6_GL000254v2_alt 2892714 0 0 0.0 0 +chr6_GL000254v2_alt 3025290 0 0 0.0 0 +chr6_GL000254v2_alt 3121328 0 0 0.0 0 +chr6_GL000254v2_alt 3305546 0 0 0.0 0 +chr6_GL000254v2_alt 3355225 0 0 0.0 0 +chr6_GL000254v2_alt 3358621 0 0 0.0 0 +chr6_GL000254v2_alt 3420928 0 0 0.0 0 +chr6_GL000254v2_alt 3710287 0 0 0.0 0 +chr6_GL000254v2_alt 3743104 0 0 0.0 0 +chr6_GL000254v2_alt 4041427 0 0 0.0 0 +chr6_GL000254v2_alt 4106699 0 0 0.0 0 +chr6_GL000254v2_alt 4107210 0 0 0.0 0 +chr6_GL000254v2_alt 4609044 0 0 0.0 0 +chr6_GL000254v2_alt 4633813 0 0 0.0 0 +chr6_GL000254v2_alt 4634278 0 0 0.0 0 +chr6_GL000254v2_alt 4816678 0 0 0.0 0 +chr6_GL000255v2_alt 217894 0 0 0.0 0 +chr6_GL000255v2_alt 320966 0 0 0.0 0 +chr6_GL000255v2_alt 745740 0 0 0.0 0 +chr6_GL000255v2_alt 778151 0 0 0.0 0 +chr6_GL000255v2_alt 980329 0 0 0.0 0 +chr6_GL000255v2_alt 1041498 0 0 0.0 0 +chr6_GL000255v2_alt 1258208 0 0 0.0 0 +chr6_GL000255v2_alt 1331146 0 0 0.0 0 +chr6_GL000255v2_alt 1594981 0 0 0.0 0 +chr6_GL000255v2_alt 1765507 0 0 0.0 0 +chr6_GL000255v2_alt 1808178 0 0 0.0 0 +chr6_GL000255v2_alt 1833329 0 0 0.0 0 +chr6_GL000255v2_alt 2029686 0 0 0.0 0 +chr6_GL000255v2_alt 2076876 0 0 0.0 0 +chr6_GL000255v2_alt 2158189 0 0 0.0 0 +chr6_GL000255v2_alt 2188913 0 0 0.0 0 +chr6_GL000255v2_alt 2201249 0 0 0.0 0 +chr6_GL000255v2_alt 2405475 0 0 0.0 0 +chr6_GL000255v2_alt 2672633 0 0 0.0 0 +chr6_GL000255v2_alt 2786567 0 0 0.0 0 +chr6_GL000255v2_alt 2806631 0 0 0.0 0 +chr6_GL000255v2_alt 2939238 0 0 0.0 0 +chr6_GL000255v2_alt 3072649 0 0 0.0 0 +chr6_GL000255v2_alt 3084847 0 0 0.0 0 +chr6_GL000255v2_alt 3219480 0 0 0.0 0 +chr6_GL000255v2_alt 3239818 0 0 0.0 0 +chr6_GL000255v2_alt 3302101 0 0 0.0 0 +chr6_GL000255v2_alt 3591577 0 0 0.0 0 +chr6_GL000255v2_alt 3624385 0 0 0.0 0 +chr6_GL000255v2_alt 3724394 0 0 0.0 0 +chr6_GL000255v2_alt 3936317 0 0 0.0 0 +chr6_GL000255v2_alt 4367491 0 0 0.0 0 +chr6_GL000255v2_alt 4392263 0 0 0.0 0 +chr6_GL000255v2_alt 4392728 0 0 0.0 0 +chr6_GL000255v2_alt 4575139 0 0 0.0 0 +chr6_GL000256v2_alt 261699 0 0 0.0 0 +chr6_GL000256v2_alt 364747 0 0 0.0 0 +chr6_GL000256v2_alt 639662 0 0 0.0 0 +chr6_GL000256v2_alt 709140 0 0 0.0 0 +chr6_GL000256v2_alt 789285 0 0 0.0 0 +chr6_GL000256v2_alt 821696 0 0 0.0 0 +chr6_GL000256v2_alt 1023726 0 0 0.0 0 +chr6_GL000256v2_alt 1084664 0 0 0.0 0 +chr6_GL000256v2_alt 1300918 0 0 0.0 0 +chr6_GL000256v2_alt 1374910 0 0 0.0 0 +chr6_GL000256v2_alt 1638356 0 0 0.0 0 +chr6_GL000256v2_alt 1811177 0 0 0.0 0 +chr6_GL000256v2_alt 1853850 0 0 0.0 0 +chr6_GL000256v2_alt 1879000 0 0 0.0 0 +chr6_GL000256v2_alt 2122478 0 0 0.0 0 +chr6_GL000256v2_alt 2719183 0 0 0.0 0 +chr6_GL000256v2_alt 2762918 0 0 0.0 0 +chr6_GL000256v2_alt 2850063 0 0 0.0 0 +chr6_GL000256v2_alt 2982699 0 0 0.0 0 +chr6_GL000256v2_alt 3078730 0 0 0.0 0 +chr6_GL000256v2_alt 3264699 0 0 0.0 0 +chr6_GL000256v2_alt 3285036 0 0 0.0 0 +chr6_GL000256v2_alt 3314378 0 0 0.0 0 +chr6_GL000256v2_alt 3317774 0 0 0.0 0 +chr6_GL000256v2_alt 3684457 0 0 0.0 0 +chr6_GL000256v2_alt 3717276 0 0 0.0 0 +chr6_GL000256v2_alt 3907813 0 0 0.0 0 +chr6_GL000256v2_alt 4078813 0 0 0.0 0 +chr6_GL000256v2_alt 4142200 0 0 0.0 0 +chr6_GL000256v2_alt 4208075 0 0 0.0 0 +chr6_GL000256v2_alt 4208586 0 0 0.0 0 +chr6_GL000256v2_alt 4621732 0 0 0.0 0 +chr6_GL000256v2_alt 4867198 0 0 0.0 0 +chr6_KB021644v2_alt 131427 0 0 0.0 0 +chr6_KB021644v2_alt 149863 0 0 0.0 0 +chr6_KB021644v2_alt 150494 0 0 0.0 0 +chr6_KB021644v2_alt 176013 0 0 0.0 0 +chr6_KI270758v1_alt 52605 0 0 0.0 0 +chr6_KI270797v1_alt 49615 0 0 0.0 0 +chr6_KI270797v1_alt 118724 0 0 0.0 0 +chr6_KI270798v1_alt 51936 0 0 0.0 0 +chr6_KI270801v1_alt 29625 0 0 0.0 0 +chr6_KI270801v1_alt 164212 0 0 0.0 0 +chr6_KI270801v1_alt 246370 0 0 0.0 0 +chr6_KI270801v1_alt 678406 0 0 0.0 0 +chr6_KI270801v1_alt 769350 0 0 0.0 0 +chr7 60709 0 0 0.0 0 +chr7 85812 0 0 0.0 0 +chr7 247399 0 0 0.0 0 +chr7 261904 0 0 0.0 0 +chr7 278086 0 0 0.0 0 +chr7 286292 0 0 0.0 0 +chr7 345300 0 0 0.0 0 +chr7 423246 0 0 0.0 0 +chr7 424709 0 0 0.0 0 +chr7 442249 0 0 0.0 0 +chr7 593622 0 0 0.0 0 +chr7 691211 0 0 0.0 0 +chr7 770810 0 0 0.0 0 +chr7 828896 0 0 0.0 0 +chr7 848016 0 0 0.0 0 +chr7 895900 0 0 0.0 0 +chr7 959488 0 0 0.0 0 +chr7 1079640 0 0 0.0 0 +chr7 1085450 0 0 0.0 0 +chr7 1093550 0 0 0.0 0 +chr7 1231370 0 0 0.0 0 +chr7 1286122 0 0 0.0 0 +chr7 1325035 0 0 0.0 0 +chr7 1356067 0 0 0.0 0 +chr7 1377166 0 0 0.0 0 +chr7 1427423 0 0 0.0 0 +chr7 1546832 0 0 0.0 0 +chr7 1702122 0 0 0.0 0 +chr7 1867321 2 21 0.4038 1 +chr7 1920011 1 73 0.9605 1 +chr7 1953833 0 0 0.0 0 +chr7 2033769 0 0 0.0 0 +chr7 2038162 0 0 0.0 0 +chr7 2044468 0 0 0.0 0 +chr7 2048177 0 0 0.0 0 +chr7 2066281 0 0 0.0 0 +chr7 2138030 0 0 0.0 0 +chr7 2233381 0 0 0.0 0 +chr7 2311484 0 0 0.0 0 +chr7 2355506 0 0 0.0 0 +chr7 2398564 0 0 0.0 0 +chr7 2408062 0 0 0.0 0 +chr7 2505664 0 0 0.0 0 +chr7 2531752 0 0 0.0 0 +chr7 2621822 0 0 0.0 0 +chr7 2641034 0 0 0.0 0 +chr7 2659713 0 0 0.0 0 +chr7 2714738 0 1 0.0227 0 +chr7 2736067 0 0 0.0 0 +chr7 2800635 0 0 0.0 0 +chr7 2973863 0 0 0.0 0 +chr7 3035865 0 0 0.0 0 +chr7 3044190 0 0 0.0 0 +chr7 3084933 0 0 0.0 0 +chr7 3172350 0 0 0.0 0 +chr7 3195081 0 0 0.0 0 +chr7 3272324 0 0 0.0 0 +chr7 3279857 0 0 0.0 0 +chr7 3370554 0 0 0.0 0 +chr7 3374735 0 0 0.0 0 +chr7 3494909 0 0 0.0 0 +chr7 3587026 0 0 0.0 0 +chr7 3666584 0 0 0.0 0 +chr7 3684597 0 0 0.0 0 +chr7 3948619 0 1 0.0172 0 +chr7 4017323 0 0 0.0 0 +chr7 4040552 0 0 0.0 0 +chr7 4141882 0 0 0.0 0 +chr7 4150172 0 0 0.0 0 +chr7 4191160 0 0 0.0 0 +chr7 4209453 0 0 0.0 0 +chr7 4226404 0 0 0.0 0 +chr7 4230751 0 0 0.0 0 +chr7 4234205 0 0 0.0 0 +chr7 4295058 0 0 0.0 0 +chr7 4303473 0 0 0.0 0 +chr7 4337659 0 0 0.0 0 +chr7 4358036 0 0 0.0 0 +chr7 4372839 0 0 0.0 0 +chr7 4379178 0 0 0.0 0 +chr7 4398900 0 0 0.0 0 +chr7 4443113 0 0 0.0 0 +chr7 4548404 0 0 0.0 0 +chr7 4557609 0 0 0.0 0 +chr7 4605342 0 0 0.0 0 +chr7 4613536 0 0 0.0 0 +chr7 4668724 1 7 0.0921 1 +chr7 4697120 0 0 0.0 0 +chr7 4815917 0 0 0.0 0 +chr7 4835683 0 0 0.0 0 +chr7 4881796 0 0 0.0 0 +chr7 4907547 0 0 0.0 0 +chr7 4910993 0 0 0.0 0 +chr7 4917744 0 0 0.0 0 +chr7 4925623 0 0 0.0 0 +chr7 4946846 0 0 0.0 0 +chr7 4960642 0 0 0.0 0 +chr7 5013938 0 0 0.0 0 +chr7 5265791 0 0 0.0 0 +chr7 5306622 0 0 0.0 0 +chr7 5388163 0 0 0.0 0 +chr7 5400158 0 0 0.0 0 +chr7 5478861 0 0 0.0 0 +chr7 5493056 0 0 0.0 0 +chr7 5500235 0 0 0.0 0 +chr7 5527040 0 0 0.0 0 +chr7 5706147 0 0 0.0 0 +chr7 5827670 0 0 0.0 0 +chr7 6026579 0 0 0.0 0 +chr7 6201021 0 0 0.0 0 +chr7 6373579 0 0 0.0 0 +chr7 6417204 0 0 0.0 0 +chr7 6611059 0 0 0.0 0 +chr7 6623480 0 0 0.0 0 +chr7 6682295 0 0 0.0 0 +chr7 6701266 0 0 0.0 0 +chr7 6709006 0 0 0.0 0 +chr7 6728054 0 0 0.0 0 +chr7 6924591 0 1 0.0256 0 +chr7 6936128 0 0 0.0 0 +chr7 6957286 0 0 0.0 0 +chr7 6989313 0 0 0.0 0 +chr7 7119171 0 0 0.0 0 +chr7 7128648 0 0 0.0 0 +chr7 7201288 0 0 0.0 0 +chr7 7251818 0 0 0.0 0 +chr7 7265081 0 0 0.0 0 +chr7 7274113 0 0 0.0 0 +chr7 7352573 0 0 0.0 0 +chr7 7393799 0 0 0.0 0 +chr7 7411913 0 0 0.0 0 +chr7 7434609 0 0 0.0 0 +chr7 7460475 0 0 0.0 0 +chr7 7478558 0 1 0.0233 0 +chr7 7519404 0 0 0.0 0 +chr7 7556627 0 0 0.0 0 +chr7 7687379 0 0 0.0 0 +chr7 7871080 0 0 0.0 0 +chr7 7971920 0 0 0.0 0 +chr7 8262664 0 0 0.0 0 +chr7 8316146 0 0 0.0 0 +chr7 8401475 0 1 0.0208 0 +chr7 8412854 0 0 0.0 0 +chr7 8483453 0 0 0.0 0 +chr7 8487596 0 0 0.0 0 +chr7 8513760 0 0 0.0 0 +chr7 8624669 0 0 0.0 0 +chr7 8678255 0 0 0.0 0 +chr7 8799911 0 0 0.0 0 +chr7 9130186 0 0 0.0 0 +chr7 9135161 0 0 0.0 0 +chr7 9249091 0 0 0.0 0 +chr7 9388442 0 0 0.0 0 +chr7 9616046 0 0 0.0 0 +chr7 9735846 0 0 0.0 0 +chr7 9966519 0 0 0.0 0 +chr7 10109745 0 0 0.0 0 +chr7 10110569 0 0 0.0 0 +chr7 10296785 0 0 0.0 0 +chr7 10439159 0 0 0.0 0 +chr7 10657628 0 0 0.0 0 +chr7 10742212 0 0 0.0 0 +chr7 10766569 0 0 0.0 0 +chr7 10882047 0 0 0.0 0 +chr7 10958439 0 0 0.0 0 +chr7 10974089 0 0 0.0 0 +chr7 10996666 0 0 0.0 0 +chr7 11613626 0 0 0.0 0 +chr7 11675556 0 0 0.0 0 +chr7 11792593 0 0 0.0 0 +chr7 11820120 0 0 0.0 0 +chr7 11856914 0 0 0.0 0 +chr7 11953888 0 0 0.0 0 +chr7 12111664 0 0 0.0 0 +chr7 12170728 0 0 0.0 0 +chr7 12651676 0 1 0.0227 0 +chr7 13187416 0 0 0.0 0 +chr7 13200023 0 0 0.0 0 +chr7 13425890 0 0 0.0 0 +chr7 13516465 0 0 0.0 0 +chr7 13712322 0 0 0.0 0 +chr7 13819516 0 0 0.0 0 +chr7 13990975 0 0 0.0 0 +chr7 14165933 0 0 0.0 0 +chr7 14311506 0 0 0.0 0 +chr7 14433134 0 0 0.0 0 +chr7 14544617 0 0 0.0 0 +chr7 14754959 0 0 0.0 0 +chr7 14808957 0 0 0.0 0 +chr7 14822611 0 0 0.0 0 +chr7 14894692 0 0 0.0 0 +chr7 14901477 0 0 0.0 0 +chr7 14919355 0 0 0.0 0 +chr7 15008171 0 0 0.0 0 +chr7 15087035 0 0 0.0 0 +chr7 15134402 0 0 0.0 0 +chr7 15163433 0 0 0.0 0 +chr7 15343856 0 0 0.0 0 +chr7 15497552 0 0 0.0 0 +chr7 15755719 0 0 0.0 0 +chr7 15934756 0 0 0.0 0 +chr7 16054883 0 0 0.0 0 +chr7 16215121 0 0 0.0 0 +chr7 16309535 0 0 0.0 0 +chr7 16326441 0 0 0.0 0 +chr7 16664660 0 0 0.0 0 +chr7 16771557 0 0 0.0 0 +chr7 16862631 0 0 0.0 0 +chr7 16943356 0 0 0.0 0 +chr7 17024077 0 0 0.0 0 +chr7 17033098 0 0 0.0 0 +chr7 17076133 0 0 0.0 0 +chr7 17156551 0 0 0.0 0 +chr7 17167855 0 0 0.0 0 +chr7 17259976 0 0 0.0 0 +chr7 17288495 0 0 0.0 0 +chr7 17493300 0 0 0.0 0 +chr7 17509764 0 0 0.0 0 +chr7 17531563 0 0 0.0 0 +chr7 17665052 0 0 0.0 0 +chr7 17965573 0 1 0.0192 0 +chr7 18260231 0 0 0.0 0 +chr7 18487505 0 0 0.0 0 +chr7 18601777 0 0 0.0 0 +chr7 18602438 0 0 0.0 0 +chr7 18814963 0 0 0.0 0 +chr7 19128622 0 0 0.0 0 +chr7 19154090 0 0 0.0 0 +chr7 19248994 0 1 0.0238 0 +chr7 19480756 0 0 0.0 0 +chr7 19519462 0 0 0.0 0 +chr7 19558710 0 0 0.0 0 +chr7 19805864 0 0 0.0 0 +chr7 20100100 0 0 0.0 0 +chr7 20266164 0 0 0.0 0 +chr7 20291924 0 0 0.0 0 +chr7 20559865 0 0 0.0 0 +chr7 20662898 0 0 0.0 0 +chr7 20709687 0 0 0.0 0 +chr7 21105286 0 0 0.0 0 +chr7 21107346 0 0 0.0 0 +chr7 21142291 0 0 0.0 0 +chr7 21221435 0 0 0.0 0 +chr7 21247235 0 0 0.0 0 +chr7 21339061 0 0 0.0 0 +chr7 21405372 0 0 0.0 0 +chr7 21599482 0 0 0.0 0 +chr7 21641119 0 1 0.0233 0 +chr7 21776015 0 0 0.0 0 +chr7 21779834 0 0 0.0 0 +chr7 21897368 0 0 0.0 0 +chr7 21917141 0 0 0.0 0 +chr7 22108280 0 0 0.0 0 +chr7 22119005 0 0 0.0 0 +chr7 22157620 0 0 0.0 0 +chr7 22266141 0 0 0.0 0 +chr7 22543361 0 0 0.0 0 +chr7 22555087 0 0 0.0 0 +chr7 22562444 0 0 0.0 0 +chr7 22682401 0 0 0.0 0 +chr7 22694365 0 0 0.0 0 +chr7 22719361 0 0 0.0 0 +chr7 22734158 0 0 0.0 0 +chr7 22748032 0 0 0.0 0 +chr7 22865053 0 0 0.0 0 +chr7 22974644 0 0 0.0 0 +chr7 23048794 0 0 0.0 0 +chr7 23228327 0 0 0.0 0 +chr7 23235493 0 0 0.0 0 +chr7 23268944 0 0 0.0 0 +chr7 23379138 0 0 0.0 0 +chr7 23596743 0 0 0.0 0 +chr7 23623522 0 0 0.0 0 +chr7 23701028 0 0 0.0 0 +chr7 23724299 0 0 0.0 0 +chr7 23745164 0 0 0.0 0 +chr7 23836084 0 0 0.0 0 +chr7 23956969 0 0 0.0 0 +chr7 24048489 0 0 0.0 0 +chr7 24364082 0 0 0.0 0 +chr7 24731124 0 0 0.0 0 +chr7 24761620 0 0 0.0 0 +chr7 24878140 0 0 0.0 0 +chr7 24988453 0 0 0.0 0 +chr7 25175926 0 0 0.0 0 +chr7 25430654 0 0 0.0 0 +chr7 25482663 0 0 0.0 0 +chr7 25662144 0 0 0.0 0 +chr7 25783852 0 0 0.0 0 +chr7 25867404 0 0 0.0 0 +chr7 26167326 0 0 0.0 0 +chr7 26530722 0 0 0.0 0 +chr7 26614412 0 0 0.0 0 +chr7 26645478 0 0 0.0 0 +chr7 26770325 0 0 0.0 0 +chr7 26901303 0 0 0.0 0 +chr7 27012632 0 0 0.0 0 +chr7 27087771 0 0 0.0 0 +chr7 27100855 0 0 0.0 0 +chr7 27264815 0 0 0.0 0 +chr7 27399553 0 0 0.0 0 +chr7 27414559 0 0 0.0 0 +chr7 27448854 1 21 0.2838 1 +chr7 27516773 0 0 0.0 0 +chr7 27979121 0 0 0.0 0 +chr7 28000197 0 0 0.0 0 +chr7 28053120 0 0 0.0 0 +chr7 28144539 0 0 0.0 0 +chr7 28313046 0 0 0.0 0 +chr7 28373887 1 42 0.6667 1 +chr7 28496705 0 0 0.0 0 +chr7 28567375 0 0 0.0 0 +chr7 28791433 0 0 0.0 0 +chr7 28853084 0 0 0.0 0 +chr7 29001183 0 0 0.0 0 +chr7 29035773 0 0 0.0 0 +chr7 29153066 0 0 0.0 0 +chr7 29282020 0 0 0.0 0 +chr7 29454770 0 0 0.0 0 +chr7 29479220 0 0 0.0 0 +chr7 29586722 0 0 0.0 0 +chr7 29648127 0 0 0.0 0 +chr7 29701241 0 0 0.0 0 +chr7 29759914 0 0 0.0 0 +chr7 29817672 0 0 0.0 0 +chr7 30084468 0 0 0.0 0 +chr7 30095594 0 0 0.0 0 +chr7 30123151 0 0 0.0 0 +chr7 30138376 0 0 0.0 0 +chr7 30277397 0 0 0.0 0 +chr7 30452009 0 0 0.0 0 +chr7 30785968 0 0 0.0 0 +chr7 30794084 0 0 0.0 0 +chr7 30905540 0 0 0.0 0 +chr7 30963567 0 0 0.0 0 +chr7 30966121 0 0 0.0 0 +chr7 30989459 0 0 0.0 0 +chr7 31003058 0 0 0.0 0 +chr7 31065901 0 0 0.0 0 +chr7 31179809 0 0 0.0 0 +chr7 31185786 0 0 0.0 0 +chr7 31186815 0 0 0.0 0 +chr7 31249771 0 0 0.0 0 +chr7 31307147 0 0 0.0 0 +chr7 31402431 0 0 0.0 0 +chr7 31531655 0 0 0.0 0 +chr7 31758822 0 0 0.0 0 +chr7 31761600 0 0 0.0 0 +chr7 31816358 0 0 0.0 0 +chr7 32021051 0 0 0.0 0 +chr7 32029704 0 0 0.0 0 +chr7 32070711 0 0 0.0 0 +chr7 32263993 0 0 0.0 0 +chr7 32330534 0 0 0.0 0 +chr7 32421577 0 0 0.0 0 +chr7 32573365 0 0 0.0 0 +chr7 32586100 0 0 0.0 0 +chr7 32660177 1 32 0.4923 1 +chr7 32672856 0 0 0.0 0 +chr7 32784349 0 0 0.0 0 +chr7 32860510 0 0 0.0 0 +chr7 32877274 0 0 0.0 0 +chr7 33314673 0 0 0.0 0 +chr7 33461442 0 0 0.0 0 +chr7 33840838 0 0 0.0 0 +chr7 33856677 0 0 0.0 0 +chr7 33998984 0 0 0.0 0 +chr7 34012617 0 0 0.0 0 +chr7 34340570 0 0 0.0 0 +chr7 34415063 0 0 0.0 0 +chr7 34576665 0 0 0.0 0 +chr7 34601982 0 0 0.0 0 +chr7 34706944 0 0 0.0 0 +chr7 34829713 0 0 0.0 0 +chr7 34874474 0 0 0.0 0 +chr7 34889836 0 0 0.0 0 +chr7 34912957 0 0 0.0 0 +chr7 35007380 0 0 0.0 0 +chr7 35021436 0 0 0.0 0 +chr7 35327882 0 0 0.0 0 +chr7 35489968 0 0 0.0 0 +chr7 35605051 0 0 0.0 0 +chr7 35717016 0 0 0.0 0 +chr7 35844719 0 1 0.0263 0 +chr7 36000679 0 0 0.0 0 +chr7 36002913 0 0 0.0 0 +chr7 36021600 0 0 0.0 0 +chr7 36058295 0 0 0.0 0 +chr7 36141597 0 0 0.0 0 +chr7 36186217 0 0 0.0 0 +chr7 36202167 0 0 0.0 0 +chr7 36287503 0 0 0.0 0 +chr7 36309662 0 0 0.0 0 +chr7 36311139 0 0 0.0 0 +chr7 36511792 0 0 0.0 0 +chr7 36524800 0 0 0.0 0 +chr7 36537836 0 0 0.0 0 +chr7 36639050 0 0 0.0 0 +chr7 36794091 0 0 0.0 0 +chr7 36830186 0 0 0.0 0 +chr7 36859497 0 0 0.0 0 +chr7 36874023 0 0 0.0 0 +chr7 36893749 0 0 0.0 0 +chr7 37320890 0 0 0.0 0 +chr7 37434859 0 0 0.0 0 +chr7 37443067 0 0 0.0 0 +chr7 37497448 0 0 0.0 0 +chr7 37542394 0 0 0.0 0 +chr7 37943349 0 0 0.0 0 +chr7 37963116 0 0 0.0 0 +chr7 37978285 0 1 0.0137 0 +chr7 38009794 0 0 0.0 0 +chr7 38063258 0 0 0.0 0 +chr7 38067946 0 0 0.0 0 +chr7 38186450 0 0 0.0 0 +chr7 38268702 0 0 0.0 0 +chr7 38284058 0 0 0.0 0 +chr7 38611949 0 0 0.0 0 +chr7 38631578 0 0 0.0 0 +chr7 38635715 0 0 0.0 0 +chr7 38644122 1 40 0.8696 1 +chr7 38682900 0 0 0.0 0 +chr7 38728937 0 1 0.0294 0 +chr7 38767009 0 0 0.0 0 +chr7 38792230 0 0 0.0 0 +chr7 38945146 0 0 0.0 0 +chr7 39006093 0 0 0.0 0 +chr7 39086829 0 0 0.0 0 +chr7 39238823 0 0 0.0 0 +chr7 39292322 0 0 0.0 0 +chr7 39331389 0 0 0.0 0 +chr7 39424063 0 0 0.0 0 +chr7 39473865 1 39 0.4815 1 +chr7 39475578 0 0 0.0 0 +chr7 39481617 0 0 0.0 0 +chr7 39552228 0 1 0.0139 0 +chr7 39553843 0 0 0.0 0 +chr7 39683573 0 0 0.0 0 +chr7 39864745 0 0 0.0 0 +chr7 40261970 0 0 0.0 0 +chr7 40422186 0 0 0.0 0 +chr7 40520080 0 0 0.0 0 +chr7 40600807 0 0 0.0 0 +chr7 40663763 0 0 0.0 0 +chr7 40788145 0 0 0.0 0 +chr7 40924635 0 0 0.0 0 +chr7 40978466 0 0 0.0 0 +chr7 40988013 0 0 0.0 0 +chr7 41056851 0 0 0.0 0 +chr7 41079652 0 0 0.0 0 +chr7 41151085 0 0 0.0 0 +chr7 41252701 0 1 0.012 0 +chr7 41270419 0 0 0.0 0 +chr7 41301008 0 0 0.0 0 +chr7 41311787 0 0 0.0 0 +chr7 41315799 0 0 0.0 0 +chr7 41452348 0 0 0.0 0 +chr7 41463960 0 0 0.0 0 +chr7 41501463 0 0 0.0 0 +chr7 41574359 0 0 0.0 0 +chr7 41683164 0 0 0.0 0 +chr7 41701271 0 0 0.0 0 +chr7 41737440 0 0 0.0 0 +chr7 41742438 0 0 0.0 0 +chr7 42049489 0 0 0.0 0 +chr7 42078155 0 0 0.0 0 +chr7 42211058 0 0 0.0 0 +chr7 42237499 0 0 0.0 0 +chr7 42356542 0 0 0.0 0 +chr7 42357741 0 0 0.0 0 +chr7 42453322 0 0 0.0 0 +chr7 42473001 0 0 0.0 0 +chr7 42591138 0 0 0.0 0 +chr7 42658437 0 0 0.0 0 +chr7 42759989 0 0 0.0 0 +chr7 42874160 0 0 0.0 0 +chr7 42878664 0 0 0.0 0 +chr7 43192447 0 0 0.0 0 +chr7 43459866 0 0 0.0 0 +chr7 43532372 0 0 0.0 0 +chr7 43772553 0 0 0.0 0 +chr7 43794967 0 0 0.0 0 +chr7 43874000 0 0 0.0 0 +chr7 43928583 0 0 0.0 0 +chr7 44134518 0 0 0.0 0 +chr7 44220847 0 0 0.0 0 +chr7 44240655 0 0 0.0 0 +chr7 44404304 0 0 0.0 0 +chr7 44466023 0 0 0.0 0 +chr7 44476943 0 0 0.0 0 +chr7 44503136 0 0 0.0 0 +chr7 44538571 0 0 0.0 0 +chr7 44644166 0 0 0.0 0 +chr7 44645544 0 0 0.0 0 +chr7 44710476 0 0 0.0 0 +chr7 44838936 0 0 0.0 0 +chr7 44920620 0 0 0.0 0 +chr7 44921987 0 0 0.0 0 +chr7 44949587 0 0 0.0 0 +chr7 44966760 0 0 0.0 0 +chr7 44973999 0 0 0.0 0 +chr7 45076484 0 0 0.0 0 +chr7 45101944 0 0 0.0 0 +chr7 45130662 0 0 0.0 0 +chr7 45195546 0 0 0.0 0 +chr7 45206931 0 0 0.0 0 +chr7 45207648 0 0 0.0 0 +chr7 45259435 0 0 0.0 0 +chr7 45483520 0 0 0.0 0 +chr7 45655556 0 0 0.0 0 +chr7 45845761 0 0 0.0 0 +chr7 45873119 0 0 0.0 0 +chr7 45965280 0 0 0.0 0 +chr7 46080837 0 0 0.0 0 +chr7 46513801 0 0 0.0 0 +chr7 46568986 0 0 0.0 0 +chr7 46631470 0 0 0.0 0 +chr7 46797892 0 0 0.0 0 +chr7 46951155 0 0 0.0 0 +chr7 46955422 0 0 0.0 0 +chr7 46974508 0 0 0.0 0 +chr7 47156494 0 0 0.0 0 +chr7 47200415 0 0 0.0 0 +chr7 47208086 0 1 0.0182 0 +chr7 47211758 0 0 0.0 0 +chr7 47245128 0 0 0.0 0 +chr7 47344376 1 31 0.4189 1 +chr7 47428185 0 0 0.0 0 +chr7 47458115 0 0 0.0 0 +chr7 47517631 0 0 0.0 0 +chr7 47573438 0 0 0.0 0 +chr7 47625899 0 0 0.0 0 +chr7 47718773 0 0 0.0 0 +chr7 47798234 0 0 0.0 0 +chr7 47840629 0 0 0.0 0 +chr7 47887732 0 0 0.0 0 +chr7 47891080 0 0 0.0 0 +chr7 47990527 0 0 0.0 0 +chr7 48029356 0 0 0.0 0 +chr7 48109654 0 0 0.0 0 +chr7 48201479 0 0 0.0 0 +chr7 48315766 0 0 0.0 0 +chr7 48460048 0 0 0.0 0 +chr7 48769235 0 0 0.0 0 +chr7 48831809 0 0 0.0 0 +chr7 48836503 0 0 0.0 0 +chr7 48950238 0 0 0.0 0 +chr7 48959389 0 0 0.0 0 +chr7 49304330 0 0 0.0 0 +chr7 49550492 0 0 0.0 0 +chr7 50131976 0 0 0.0 0 +chr7 50156647 0 0 0.0 0 +chr7 50177942 0 0 0.0 0 +chr7 50294823 0 0 0.0 0 +chr7 50306713 0 1 0.0118 0 +chr7 50380634 0 0 0.0 0 +chr7 50383734 0 0 0.0 0 +chr7 50504200 0 0 0.0 0 +chr7 50589292 0 0 0.0 0 +chr7 50607632 0 0 0.0 0 +chr7 50611975 0 0 0.0 0 +chr7 50623680 0 0 0.0 0 +chr7 50771587 0 0 0.0 0 +chr7 50808495 0 0 0.0 0 +chr7 50914195 0 0 0.0 0 +chr7 50937158 0 0 0.0 0 +chr7 50980070 0 0 0.0 0 +chr7 51093489 0 0 0.0 0 +chr7 51118087 0 0 0.0 0 +chr7 51490430 0 0 0.0 0 +chr7 51564057 0 0 0.0 0 +chr7 51624421 0 1 0.05 0 +chr7 51769760 0 0 0.0 0 +chr7 51927958 0 0 0.0 0 +chr7 51955795 0 0 0.0 0 +chr7 51971594 0 0 0.0 0 +chr7 52056615 0 0 0.0 0 +chr7 52112991 0 0 0.0 0 +chr7 52175625 0 0 0.0 0 +chr7 52302155 0 0 0.0 0 +chr7 52335315 0 0 0.0 0 +chr7 52361494 0 0 0.0 0 +chr7 52833159 0 0 0.0 0 +chr7 52959909 0 0 0.0 0 +chr7 52999445 0 0 0.0 0 +chr7 53024937 0 0 0.0 0 +chr7 53297604 0 0 0.0 0 +chr7 53309733 0 0 0.0 0 +chr7 53377126 0 1 0.0143 0 +chr7 53399675 0 0 0.0 0 +chr7 53537836 0 0 0.0 0 +chr7 53595415 0 0 0.0 0 +chr7 53709643 0 0 0.0 0 +chr7 53823191 0 1 0.0119 0 +chr7 53829374 0 0 0.0 0 +chr7 53931328 0 0 0.0 0 +chr7 53941784 0 0 0.0 0 +chr7 54048030 0 0 0.0 0 +chr7 54185608 0 0 0.0 0 +chr7 54185912 0 0 0.0 0 +chr7 54275239 0 0 0.0 0 +chr7 54401247 0 0 0.0 0 +chr7 54449413 0 0 0.0 0 +chr7 54566447 0 0 0.0 0 +chr7 54948529 0 0 0.0 0 +chr7 55033014 0 0 0.0 0 +chr7 55145548 0 0 0.0 0 +chr7 55248720 0 0 0.0 0 +chr7 55254831 0 0 0.0 0 +chr7 55272510 0 0 0.0 0 +chr7 55294784 0 0 0.0 0 +chr7 55371634 0 0 0.0 0 +chr7 55434689 0 0 0.0 0 +chr7 55477407 0 0 0.0 0 +chr7 55484499 0 0 0.0 0 +chr7 55498498 0 0 0.0 0 +chr7 55523052 0 0 0.0 0 +chr7 55864054 0 0 0.0 0 +chr7 55903782 0 0 0.0 0 +chr7 56116783 0 0 0.0 0 +chr7 56191686 0 0 0.0 0 +chr7 56317502 0 0 0.0 0 +chr7 56436717 0 0 0.0 0 +chr7 56617863 0 0 0.0 0 +chr7 56714923 0 0 0.0 0 +chr7 56809835 0 0 0.0 0 +chr7 56907745 0 0 0.0 0 +chr7 56967878 0 0 0.0 0 +chr7 57007568 0 0 0.0 0 +chr7 57128200 0 0 0.0 0 +chr7 57183441 0 0 0.0 0 +chr7 57235602 0 0 0.0 0 +chr7 57236910 0 0 0.0 0 +chr7 57359295 0 0 0.0 0 +chr7 57399733 0 0 0.0 0 +chr7 57768914 0 0 0.0 0 +chr7 57900666 0 0 0.0 0 +chr7 57920074 0 0 0.0 0 +chr7 58019094 0 0 0.0 0 +chr7 58029503 0 0 0.0 0 +chr7 61097486 0 0 0.0 0 +chr7 61114100 0 0 0.0 0 +chr7 61734552 0 0 0.0 0 +chr7 61805304 0 0 0.0 0 +chr7 61823616 0 0 0.0 0 +chr7 61826712 0 0 0.0 0 +chr7 61829170 0 0 0.0 0 +chr7 61848663 0 0 0.0 0 +chr7 61880096 0 0 0.0 0 +chr7 61893466 0 0 0.0 0 +chr7 61927115 0 0 0.0 0 +chr7 61948971 0 0 0.0 0 +chr7 62218038 0 0 0.0 0 +chr7 62237259 0 0 0.0 0 +chr7 62251342 0 0 0.0 0 +chr7 62619541 0 0 0.0 0 +chr7 62622316 0 0 0.0 0 +chr7 62633951 0 1 0.027 0 +chr7 62742058 0 0 0.0 0 +chr7 62844783 0 0 0.0 0 +chr7 62895102 0 0 0.0 0 +chr7 62908588 0 0 0.0 0 +chr7 62921442 0 0 0.0 0 +chr7 62940631 0 0 0.0 0 +chr7 62956942 0 0 0.0 0 +chr7 63072020 0 0 0.0 0 +chr7 63174868 0 0 0.0 0 +chr7 63221544 0 0 0.0 0 +chr7 63569332 0 0 0.0 0 +chr7 63609072 0 0 0.0 0 +chr7 63669198 0 0 0.0 0 +chr7 63828057 0 0 0.0 0 +chr7 64117424 0 0 0.0 0 +chr7 64185147 0 0 0.0 0 +chr7 64430351 0 0 0.0 0 +chr7 64525049 0 0 0.0 0 +chr7 64569915 0 0 0.0 0 +chr7 64704940 0 0 0.0 0 +chr7 64837294 0 0 0.0 0 +chr7 64947639 0 0 0.0 0 +chr7 65136630 0 0 0.0 0 +chr7 65200052 0 0 0.0 0 +chr7 65559358 0 0 0.0 0 +chr7 65643271 0 0 0.0 0 +chr7 65705784 0 0 0.0 0 +chr7 65937965 0 0 0.0 0 +chr7 65955686 0 0 0.0 0 +chr7 65965574 0 0 0.0 0 +chr7 65985865 0 1 0.0192 0 +chr7 66000889 0 0 0.0 0 +chr7 66026017 0 0 0.0 0 +chr7 66085055 0 0 0.0 0 +chr7 66216032 0 0 0.0 0 +chr7 66356473 0 0 0.0 0 +chr7 66552575 0 0 0.0 0 +chr7 66555988 0 0 0.0 0 +chr7 66566445 0 0 0.0 0 +chr7 66792829 0 0 0.0 0 +chr7 66847388 0 0 0.0 0 +chr7 66949058 0 0 0.0 0 +chr7 66960688 0 0 0.0 0 +chr7 67209520 0 0 0.0 0 +chr7 67346872 0 0 0.0 0 +chr7 67401554 0 0 0.0 0 +chr7 67401851 0 0 0.0 0 +chr7 67419932 0 0 0.0 0 +chr7 67483208 0 0 0.0 0 +chr7 67483746 0 0 0.0 0 +chr7 67557988 0 0 0.0 0 +chr7 67589516 0 0 0.0 0 +chr7 67812343 0 0 0.0 0 +chr7 67888829 0 0 0.0 0 +chr7 68082074 0 0 0.0 0 +chr7 68095533 0 0 0.0 0 +chr7 68105768 0 0 0.0 0 +chr7 68114415 0 0 0.0 0 +chr7 68142837 0 0 0.0 0 +chr7 68188333 0 0 0.0 0 +chr7 68402710 0 0 0.0 0 +chr7 68443599 0 0 0.0 0 +chr7 68509992 0 0 0.0 0 +chr7 68603684 0 1 0.0294 0 +chr7 68934392 0 0 0.0 0 +chr7 69094434 0 0 0.0 0 +chr7 69118119 0 0 0.0 0 +chr7 69233174 0 0 0.0 0 +chr7 69263462 0 0 0.0 0 +chr7 69358827 0 0 0.0 0 +chr7 69396074 0 0 0.0 0 +chr7 69420760 0 0 0.0 0 +chr7 69422735 0 0 0.0 0 +chr7 69434593 0 0 0.0 0 +chr7 69464256 0 0 0.0 0 +chr7 69619817 0 0 0.0 0 +chr7 69718478 0 0 0.0 0 +chr7 69842541 0 0 0.0 0 +chr7 70094669 0 0 0.0 0 +chr7 70168241 0 0 0.0 0 +chr7 70204034 0 0 0.0 0 +chr7 70269404 0 0 0.0 0 +chr7 70389403 0 0 0.0 0 +chr7 70442138 0 0 0.0 0 +chr7 70631952 0 0 0.0 0 +chr7 70647855 0 0 0.0 0 +chr7 70707668 0 0 0.0 0 +chr7 71092797 0 0 0.0 0 +chr7 71220597 0 0 0.0 0 +chr7 71280310 0 0 0.0 0 +chr7 71280822 0 0 0.0 0 +chr7 71350219 0 0 0.0 0 +chr7 71486621 0 0 0.0 0 +chr7 71737390 0 0 0.0 0 +chr7 71789622 0 0 0.0 0 +chr7 71866929 0 0 0.0 0 +chr7 72017493 0 0 0.0 0 +chr7 72109226 0 0 0.0 0 +chr7 72153152 0 0 0.0 0 +chr7 72323376 0 0 0.0 0 +chr7 72404174 0 0 0.0 0 +chr7 72465570 0 0 0.0 0 +chr7 72473199 0 0 0.0 0 +chr7 72484675 0 0 0.0 0 +chr7 72701525 0 0 0.0 0 +chr7 73422455 0 0 0.0 0 +chr7 73554901 0 0 0.0 0 +chr7 73624347 0 0 0.0 0 +chr7 73625357 0 0 0.0 0 +chr7 73626647 0 0 0.0 0 +chr7 73702058 0 0 0.0 0 +chr7 73839833 0 0 0.0 0 +chr7 73893460 0 0 0.0 0 +chr7 74019801 0 0 0.0 0 +chr7 74041375 0 0 0.0 0 +chr7 74086306 0 0 0.0 0 +chr7 74109771 0 0 0.0 0 +chr7 74113949 0 0 0.0 0 +chr7 74173651 0 0 0.0 0 +chr7 74293547 0 0 0.0 0 +chr7 74312483 0 0 0.0 0 +chr7 74589743 0 0 0.0 0 +chr7 75015398 0 0 0.0 0 +chr7 75591785 0 0 0.0 0 +chr7 75821526 0 0 0.0 0 +chr7 75928370 0 0 0.0 0 +chr7 75994846 0 0 0.0 0 +chr7 76016785 0 0 0.0 0 +chr7 76083482 0 0 0.0 0 +chr7 76120690 0 0 0.0 0 +chr7 76214312 0 0 0.0 0 +chr7 76224766 0 0 0.0 0 +chr7 76236943 0 0 0.0 0 +chr7 76385662 1 10 0.1587 1 +chr7 76467160 0 0 0.0 0 +chr7 76480989 0 0 0.0 0 +chr7 76686229 0 0 0.0 0 +chr7 76772180 0 0 0.0 0 +chr7 76869542 0 0 0.0 0 +chr7 76965269 0 0 0.0 0 +chr7 76979088 0 0 0.0 0 +chr7 77096101 0 0 0.0 0 +chr7 77147693 0 0 0.0 0 +chr7 77234736 0 1 0.0119 0 +chr7 77343025 0 0 0.0 0 +chr7 77348061 0 0 0.0 0 +chr7 77468918 0 0 0.0 0 +chr7 77497329 0 0 0.0 0 +chr7 77529422 0 0 0.0 0 +chr7 77542817 0 0 0.0 0 +chr7 77636339 0 0 0.0 0 +chr7 77662899 0 0 0.0 0 +chr7 77664529 0 0 0.0 0 +chr7 77668474 0 0 0.0 0 +chr7 77782407 0 0 0.0 0 +chr7 77900368 0 0 0.0 0 +chr7 78015713 0 0 0.0 0 +chr7 78256737 0 0 0.0 0 +chr7 78335294 0 0 0.0 0 +chr7 78429917 0 0 0.0 0 +chr7 78451907 0 0 0.0 0 +chr7 78472931 0 0 0.0 0 +chr7 78519447 0 0 0.0 0 +chr7 78566084 0 0 0.0 0 +chr7 79346852 0 0 0.0 0 +chr7 79441732 0 0 0.0 0 +chr7 79513905 0 0 0.0 0 +chr7 79698820 0 0 0.0 0 +chr7 79740538 0 0 0.0 0 +chr7 79905810 0 0 0.0 0 +chr7 79919967 0 0 0.0 0 +chr7 79934915 0 0 0.0 0 +chr7 80020975 0 0 0.0 0 +chr7 80118165 0 0 0.0 0 +chr7 80159248 0 0 0.0 0 +chr7 80767177 0 0 0.0 0 +chr7 80993731 0 0 0.0 0 +chr7 81135404 0 0 0.0 0 +chr7 81358730 0 0 0.0 0 +chr7 81459654 0 0 0.0 0 +chr7 81464128 0 0 0.0 0 +chr7 82256268 0 0 0.0 0 +chr7 82290857 0 0 0.0 0 +chr7 82492594 0 0 0.0 0 +chr7 82497393 0 0 0.0 0 +chr7 82576875 0 0 0.0 0 +chr7 82595080 0 0 0.0 0 +chr7 82626586 0 0 0.0 0 +chr7 82684692 0 0 0.0 0 +chr7 83001992 0 0 0.0 0 +chr7 83014140 0 0 0.0 0 +chr7 83341917 0 0 0.0 0 +chr7 83367651 0 0 0.0 0 +chr7 83510187 0 0 0.0 0 +chr7 83660789 0 0 0.0 0 +chr7 83716670 0 0 0.0 0 +chr7 83886440 0 0 0.0 0 +chr7 83982099 0 0 0.0 0 +chr7 84020682 0 0 0.0 0 +chr7 84111353 0 0 0.0 0 +chr7 84279968 0 0 0.0 0 +chr7 84303038 0 0 0.0 0 +chr7 84472670 0 0 0.0 0 +chr7 84824808 0 0 0.0 0 +chr7 84895586 0 0 0.0 0 +chr7 84992728 0 0 0.0 0 +chr7 85080537 0 0 0.0 0 +chr7 85103287 0 0 0.0 0 +chr7 85348844 0 0 0.0 0 +chr7 85469705 0 0 0.0 0 +chr7 85580219 0 0 0.0 0 +chr7 85581311 0 0 0.0 0 +chr7 85692569 0 2 0.027 0 +chr7 85850373 0 0 0.0 0 +chr7 85956179 0 0 0.0 0 +chr7 85961538 0 0 0.0 0 +chr7 86174794 0 0 0.0 0 +chr7 86211239 0 0 0.0 0 +chr7 86282110 0 0 0.0 0 +chr7 86333291 0 0 0.0 0 +chr7 86506515 0 0 0.0 0 +chr7 86713931 0 0 0.0 0 +chr7 86736322 0 0 0.0 0 +chr7 86805168 0 0 0.0 0 +chr7 86912990 0 0 0.0 0 +chr7 86996441 0 0 0.0 0 +chr7 87077825 0 0 0.0 0 +chr7 87107365 0 0 0.0 0 +chr7 87182335 0 0 0.0 0 +chr7 87317289 0 0 0.0 0 +chr7 87355773 0 0 0.0 0 +chr7 87567379 0 0 0.0 0 +chr7 87609388 0 0 0.0 0 +chr7 87945996 0 0 0.0 0 +chr7 88089220 0 1 0.0122 0 +chr7 88101894 0 0 0.0 0 +chr7 88316229 0 0 0.0 0 +chr7 88442855 0 0 0.0 0 +chr7 88449192 0 0 0.0 0 +chr7 88458823 0 0 0.0 0 +chr7 88465344 0 0 0.0 0 +chr7 88725076 0 0 0.0 0 +chr7 88998105 0 0 0.0 0 +chr7 89080848 0 0 0.0 0 +chr7 89088117 0 0 0.0 0 +chr7 89203591 0 0 0.0 0 +chr7 89234814 0 0 0.0 0 +chr7 89587270 0 0 0.0 0 +chr7 89700963 0 0 0.0 0 +chr7 90055320 0 0 0.0 0 +chr7 90413367 0 0 0.0 0 +chr7 90429123 0 0 0.0 0 +chr7 90541737 0 0 0.0 0 +chr7 90551059 0 0 0.0 0 +chr7 90621436 0 0 0.0 0 +chr7 90707305 0 0 0.0 0 +chr7 90735695 0 0 0.0 0 +chr7 90846663 0 0 0.0 0 +chr7 91159855 0 0 0.0 0 +chr7 91197324 0 0 0.0 0 +chr7 91198050 0 0 0.0 0 +chr7 91257746 0 0 0.0 0 +chr7 91342535 0 0 0.0 0 +chr7 91417864 0 0 0.0 0 +chr7 91457370 0 0 0.0 0 +chr7 91539904 0 0 0.0 0 +chr7 91540812 0 0 0.0 0 +chr7 91555635 0 0 0.0 0 +chr7 91635290 0 0 0.0 0 +chr7 91715851 0 0 0.0 0 +chr7 92130562 0 0 0.0 0 +chr7 92133723 0 0 0.0 0 +chr7 92147329 0 0 0.0 0 +chr7 92239970 0 0 0.0 0 +chr7 92422882 0 0 0.0 0 +chr7 92468267 0 0 0.0 0 +chr7 92486227 0 0 0.0 0 +chr7 92559181 0 0 0.0 0 +chr7 92674214 0 0 0.0 0 +chr7 92765690 0 0 0.0 0 +chr7 92783812 0 0 0.0 0 +chr7 92846725 0 0 0.0 0 +chr7 92861886 0 0 0.0 0 +chr7 92915508 0 0 0.0 0 +chr7 92943314 0 0 0.0 0 +chr7 93021185 0 0 0.0 0 +chr7 93028769 0 0 0.0 0 +chr7 93095435 0 0 0.0 0 +chr7 93104456 0 0 0.0 0 +chr7 93253796 0 0 0.0 0 +chr7 93371111 0 0 0.0 0 +chr7 93456481 0 0 0.0 0 +chr7 93604283 0 0 0.0 0 +chr7 93663334 0 0 0.0 0 +chr7 93716311 0 0 0.0 0 +chr7 93923972 0 1 0.0135 0 +chr7 94147383 0 0 0.0 0 +chr7 94318759 0 0 0.0 0 +chr7 94372822 0 0 0.0 0 +chr7 94728746 0 0 0.0 0 +chr7 94786866 0 0 0.0 0 +chr7 94970018 0 0 0.0 0 +chr7 95081779 0 0 0.0 0 +chr7 95115675 0 0 0.0 0 +chr7 95286317 0 0 0.0 0 +chr7 95340717 0 0 0.0 0 +chr7 95428310 0 0 0.0 0 +chr7 95631689 0 0 0.0 0 +chr7 95819505 0 0 0.0 0 +chr7 95822900 0 0 0.0 0 +chr7 95900127 0 0 0.0 0 +chr7 95941081 0 0 0.0 0 +chr7 96086057 0 0 0.0 0 +chr7 96115994 0 0 0.0 0 +chr7 96153418 0 0 0.0 0 +chr7 96181379 0 0 0.0 0 +chr7 96185486 0 0 0.0 0 +chr7 96236323 0 0 0.0 0 +chr7 96296423 0 0 0.0 0 +chr7 96311292 0 0 0.0 0 +chr7 96397392 0 0 0.0 0 +chr7 96415430 0 0 0.0 0 +chr7 96431482 0 0 0.0 0 +chr7 96450831 0 0 0.0 0 +chr7 96454011 0 0 0.0 0 +chr7 96548056 0 0 0.0 0 +chr7 96549271 0 1 0.0182 0 +chr7 96549899 0 0 0.0 0 +chr7 96552000 0 0 0.0 0 +chr7 96754299 0 0 0.0 0 +chr7 96801455 0 0 0.0 0 +chr7 96900282 0 0 0.0 0 +chr7 96989646 0 0 0.0 0 +chr7 97014854 0 0 0.0 0 +chr7 97051202 0 0 0.0 0 +chr7 97151592 0 0 0.0 0 +chr7 97161291 0 0 0.0 0 +chr7 97252752 0 0 0.0 0 +chr7 97268641 0 0 0.0 0 +chr7 97286023 0 0 0.0 0 +chr7 97348843 0 0 0.0 0 +chr7 97391380 0 0 0.0 0 +chr7 97549451 0 0 0.0 0 +chr7 97640804 0 0 0.0 0 +chr7 97644185 0 0 0.0 0 +chr7 97753867 0 0 0.0 0 +chr7 97798844 0 1 0.0244 0 +chr7 97823076 0 0 0.0 0 +chr7 97837523 0 0 0.0 0 +chr7 97842885 0 0 0.0 0 +chr7 97905376 0 0 0.0 0 +chr7 98040934 0 0 0.0 0 +chr7 98240676 0 0 0.0 0 +chr7 98312637 0 1 0.0139 0 +chr7 98322690 0 0 0.0 0 +chr7 98331133 0 0 0.0 0 +chr7 98360388 0 0 0.0 0 +chr7 98409523 0 0 0.0 0 +chr7 98441162 0 1 0.0238 0 +chr7 98682300 0 0 0.0 0 +chr7 98953719 0 0 0.0 0 +chr7 98955791 0 0 0.0 0 +chr7 99196549 0 0 0.0 0 +chr7 99350063 0 0 0.0 0 +chr7 99429015 0 0 0.0 0 +chr7 99553670 0 0 0.0 0 +chr7 99749315 0 0 0.0 0 +chr7 99796590 0 0 0.0 0 +chr7 99837779 0 0 0.0 0 +chr7 99879743 0 0 0.0 0 +chr7 99954090 0 0 0.0 0 +chr7 100080989 0 0 0.0 0 +chr7 100081340 0 0 0.0 0 +chr7 100172361 0 0 0.0 0 +chr7 100270796 0 0 0.0 0 +chr7 100288902 0 0 0.0 0 +chr7 100356946 0 0 0.0 0 +chr7 100467317 0 0 0.0 0 +chr7 100612244 0 1 0.0167 0 +chr7 100683502 0 0 0.0 0 +chr7 100877073 0 0 0.0 0 +chr7 100906208 0 0 0.0 0 +chr7 100970174 0 0 0.0 0 +chr7 101034301 0 0 0.0 0 +chr7 101036776 0 0 0.0 0 +chr7 101038189 0 0 0.0 0 +chr7 101121933 0 0 0.0 0 +chr7 101218402 0 0 0.0 0 +chr7 101388687 0 0 0.0 0 +chr7 101400007 0 0 0.0 0 +chr7 101453829 0 0 0.0 0 +chr7 101462879 0 0 0.0 0 +chr7 101468549 0 0 0.0 0 +chr7 101533003 0 0 0.0 0 +chr7 101538739 0 0 0.0 0 +chr7 101583644 0 0 0.0 0 +chr7 101766705 0 0 0.0 0 +chr7 101844849 0 0 0.0 0 +chr7 101855578 0 0 0.0 0 +chr7 101911520 0 0 0.0 0 +chr7 101939324 0 0 0.0 0 +chr7 101947318 0 0 0.0 0 +chr7 101970887 0 0 0.0 0 +chr7 102007325 0 0 0.0 0 +chr7 102025145 0 0 0.0 0 +chr7 102071084 0 0 0.0 0 +chr7 102136650 0 0 0.0 0 +chr7 102179880 0 0 0.0 0 +chr7 102305939 0 0 0.0 0 +chr7 102720017 0 0 0.0 0 +chr7 102723422 0 0 0.0 0 +chr7 102775274 0 0 0.0 0 +chr7 102844672 0 0 0.0 0 +chr7 102979042 0 0 0.0 0 +chr7 103017206 0 0 0.0 0 +chr7 103019065 0 0 0.0 0 +chr7 103047505 0 0 0.0 0 +chr7 103084450 0 0 0.0 0 +chr7 103133223 0 1 0.0204 0 +chr7 103405496 0 0 0.0 0 +chr7 103528246 0 0 0.0 0 +chr7 103870446 0 0 0.0 0 +chr7 104059441 0 0 0.0 0 +chr7 104152275 0 0 0.0 0 +chr7 104191334 0 0 0.0 0 +chr7 104492448 0 0 0.0 0 +chr7 104523882 0 0 0.0 0 +chr7 104534950 0 0 0.0 0 +chr7 104595353 0 0 0.0 0 +chr7 104618925 0 0 0.0 0 +chr7 104713937 0 0 0.0 0 +chr7 104802841 0 0 0.0 0 +chr7 104864956 0 1 0.0147 0 +chr7 104928037 0 0 0.0 0 +chr7 104930667 0 0 0.0 0 +chr7 105219078 0 0 0.0 0 +chr7 105798715 0 0 0.0 0 +chr7 105839350 0 0 0.0 0 +chr7 105867934 0 0 0.0 0 +chr7 105874512 0 0 0.0 0 +chr7 105995231 0 0 0.0 0 +chr7 106001271 0 0 0.0 0 +chr7 106050124 0 0 0.0 0 +chr7 106125484 0 0 0.0 0 +chr7 106169561 0 1 0.0135 0 +chr7 106200325 0 0 0.0 0 +chr7 106217255 0 0 0.0 0 +chr7 106313177 0 0 0.0 0 +chr7 106332196 0 0 0.0 0 +chr7 106338052 0 0 0.0 0 +chr7 106358282 0 0 0.0 0 +chr7 106359229 0 0 0.0 0 +chr7 106384786 0 0 0.0 0 +chr7 106489373 0 0 0.0 0 +chr7 106531953 0 0 0.0 0 +chr7 106659723 0 0 0.0 0 +chr7 106862052 0 0 0.0 0 +chr7 106885188 0 0 0.0 0 +chr7 107060872 0 0 0.0 0 +chr7 107069560 0 0 0.0 0 +chr7 107119633 0 0 0.0 0 +chr7 107182411 0 0 0.0 0 +chr7 107185872 0 0 0.0 0 +chr7 107209951 0 0 0.0 0 +chr7 107304728 0 0 0.0 0 +chr7 107442098 0 0 0.0 0 +chr7 107505422 0 0 0.0 0 +chr7 107662105 0 0 0.0 0 +chr7 107756817 0 0 0.0 0 +chr7 107791101 0 0 0.0 0 +chr7 107885796 0 0 0.0 0 +chr7 107939233 0 0 0.0 0 +chr7 107946145 0 0 0.0 0 +chr7 108103274 0 0 0.0 0 +chr7 108137132 0 0 0.0 0 +chr7 108138056 0 0 0.0 0 +chr7 108249237 0 0 0.0 0 +chr7 108250592 0 0 0.0 0 +chr7 108410755 0 0 0.0 0 +chr7 108645228 0 0 0.0 0 +chr7 108818183 0 0 0.0 0 +chr7 108837536 0 0 0.0 0 +chr7 109083121 0 0 0.0 0 +chr7 109234533 0 0 0.0 0 +chr7 109278950 0 0 0.0 0 +chr7 109292693 0 0 0.0 0 +chr7 109719988 0 0 0.0 0 +chr7 109808745 0 0 0.0 0 +chr7 110119984 0 0 0.0 0 +chr7 110267769 0 0 0.0 0 +chr7 110338082 0 0 0.0 0 +chr7 110519041 0 0 0.0 0 +chr7 110575522 0 0 0.0 0 +chr7 110641334 0 0 0.0 0 +chr7 110683710 0 0 0.0 0 +chr7 110726148 0 0 0.0 0 +chr7 110776220 0 0 0.0 0 +chr7 110852635 0 0 0.0 0 +chr7 110937622 0 0 0.0 0 +chr7 111496807 0 0 0.0 0 +chr7 111585794 0 0 0.0 0 +chr7 111646844 0 0 0.0 0 +chr7 111712816 0 0 0.0 0 +chr7 111750595 0 0 0.0 0 +chr7 111876345 0 0 0.0 0 +chr7 112100122 0 0 0.0 0 +chr7 112226510 0 0 0.0 0 +chr7 112262929 0 0 0.0 0 +chr7 112379106 0 0 0.0 0 +chr7 112672601 0 0 0.0 0 +chr7 112743989 0 0 0.0 0 +chr7 112785868 0 0 0.0 0 +chr7 113115421 0 0 0.0 0 +chr7 113124223 0 0 0.0 0 +chr7 113303931 0 0 0.0 0 +chr7 113737469 0 0 0.0 0 +chr7 113901679 0 0 0.0 0 +chr7 113944753 0 0 0.0 0 +chr7 114053483 0 0 0.0 0 +chr7 114185616 0 0 0.0 0 +chr7 114203461 0 0 0.0 0 +chr7 114263580 0 0 0.0 0 +chr7 114347674 0 0 0.0 0 +chr7 114506076 0 0 0.0 0 +chr7 114589959 0 0 0.0 0 +chr7 114698599 0 0 0.0 0 +chr7 114752901 0 0 0.0 0 +chr7 115134504 0 0 0.0 0 +chr7 115190416 0 0 0.0 0 +chr7 115504317 0 0 0.0 0 +chr7 115592065 0 0 0.0 0 +chr7 115715190 0 0 0.0 0 +chr7 115750217 0 0 0.0 0 +chr7 115776457 0 0 0.0 0 +chr7 115870904 0 0 0.0 0 +chr7 115953061 0 0 0.0 0 +chr7 116065357 0 0 0.0 0 +chr7 116181995 0 0 0.0 0 +chr7 116201934 0 0 0.0 0 +chr7 116220284 0 0 0.0 0 +chr7 116743520 0 0 0.0 0 +chr7 116743887 0 0 0.0 0 +chr7 116814665 0 0 0.0 0 +chr7 116877891 0 0 0.0 0 +chr7 116954780 0 0 0.0 0 +chr7 117045147 0 0 0.0 0 +chr7 117241083 0 0 0.0 0 +chr7 117310473 0 0 0.0 0 +chr7 117421306 0 0 0.0 0 +chr7 117518692 0 0 0.0 0 +chr7 117655888 0 0 0.0 0 +chr7 117675195 0 0 0.0 0 +chr7 117771202 0 0 0.0 0 +chr7 117889023 0 0 0.0 0 +chr7 118036910 0 0 0.0 0 +chr7 118142395 0 0 0.0 0 +chr7 118150432 0 0 0.0 0 +chr7 118294569 0 0 0.0 0 +chr7 118332396 0 0 0.0 0 +chr7 118588020 0 0 0.0 0 +chr7 118754198 0 0 0.0 0 +chr7 118775886 0 0 0.0 0 +chr7 119141881 0 0 0.0 0 +chr7 119428269 0 0 0.0 0 +chr7 119501144 0 0 0.0 0 +chr7 119807551 0 0 0.0 0 +chr7 119855677 0 0 0.0 0 +chr7 119974994 0 0 0.0 0 +chr7 120042478 0 0 0.0 0 +chr7 120690012 0 0 0.0 0 +chr7 120792028 0 0 0.0 0 +chr7 121009809 0 0 0.0 0 +chr7 121053965 0 0 0.0 0 +chr7 121057713 0 0 0.0 0 +chr7 121124789 0 0 0.0 0 +chr7 121156664 0 0 0.0 0 +chr7 121467900 0 0 0.0 0 +chr7 121533555 0 0 0.0 0 +chr7 121839151 0 0 0.0 0 +chr7 121850435 0 0 0.0 0 +chr7 121895969 0 0 0.0 0 +chr7 121898031 0 0 0.0 0 +chr7 122140411 0 0 0.0 0 +chr7 122276077 0 0 0.0 0 +chr7 122409849 0 0 0.0 0 +chr7 122422057 0 0 0.0 0 +chr7 122433636 0 0 0.0 0 +chr7 122665414 0 0 0.0 0 +chr7 122677953 0 0 0.0 0 +chr7 122914079 0 0 0.0 0 +chr7 123004231 0 0 0.0 0 +chr7 123044949 0 0 0.0 0 +chr7 123149624 0 0 0.0 0 +chr7 123397639 0 0 0.0 0 +chr7 123475559 0 0 0.0 0 +chr7 123595048 0 0 0.0 0 +chr7 123844308 0 0 0.0 0 +chr7 124142997 0 0 0.0 0 +chr7 124153553 0 0 0.0 0 +chr7 124193016 0 0 0.0 0 +chr7 124786214 0 0 0.0 0 +chr7 124796623 0 0 0.0 0 +chr7 124805148 0 0 0.0 0 +chr7 124854025 0 0 0.0 0 +chr7 125125089 0 0 0.0 0 +chr7 125477194 0 0 0.0 0 +chr7 125630999 0 0 0.0 0 +chr7 125766185 0 0 0.0 0 +chr7 126025096 0 0 0.0 0 +chr7 126147698 0 1 0.0127 0 +chr7 126208386 0 0 0.0 0 +chr7 126334924 0 0 0.0 0 +chr7 126337405 0 0 0.0 0 +chr7 126473068 0 0 0.0 0 +chr7 126513755 0 0 0.0 0 +chr7 126571466 0 0 0.0 0 +chr7 126682578 0 0 0.0 0 +chr7 126756835 0 0 0.0 0 +chr7 126878760 0 0 0.0 0 +chr7 126914319 0 0 0.0 0 +chr7 127091869 0 0 0.0 0 +chr7 127150361 0 0 0.0 0 +chr7 127236682 0 0 0.0 0 +chr7 127464635 0 0 0.0 0 +chr7 127563695 0 0 0.0 0 +chr7 127608634 0 0 0.0 0 +chr7 127613524 0 0 0.0 0 +chr7 127629557 0 0 0.0 0 +chr7 127679358 0 0 0.0 0 +chr7 128192314 0 0 0.0 0 +chr7 128233756 0 0 0.0 0 +chr7 128275812 0 0 0.0 0 +chr7 128430340 0 0 0.0 0 +chr7 128446382 0 0 0.0 0 +chr7 128486589 2 10 0.122 1 +chr7 128519408 0 0 0.0 0 +chr7 128558361 0 0 0.0 0 +chr7 128691786 0 0 0.0 0 +chr7 128698242 0 0 0.0 0 +chr7 128720727 0 0 0.0 0 +chr7 128837276 0 0 0.0 0 +chr7 128980079 0 0 0.0 0 +chr7 129153597 0 0 0.0 0 +chr7 129155298 0 0 0.0 0 +chr7 129168196 0 0 0.0 0 +chr7 129252657 0 0 0.0 0 +chr7 129400552 0 0 0.0 0 +chr7 129402370 0 0 0.0 0 +chr7 129558512 0 0 0.0 0 +chr7 129642245 0 0 0.0 0 +chr7 129702234 0 0 0.0 0 +chr7 129835493 0 0 0.0 0 +chr7 129905279 0 0 0.0 0 +chr7 129967124 0 0 0.0 0 +chr7 130135014 0 0 0.0 0 +chr7 130264667 0 0 0.0 0 +chr7 130386971 0 0 0.0 0 +chr7 130460018 0 0 0.0 0 +chr7 130468482 0 0 0.0 0 +chr7 130523645 0 0 0.0 0 +chr7 130527870 0 0 0.0 0 +chr7 130532062 0 0 0.0 0 +chr7 130532247 0 0 0.0 0 +chr7 130638598 0 0 0.0 0 +chr7 131000676 0 0 0.0 0 +chr7 131219378 0 0 0.0 0 +chr7 131255420 0 0 0.0 0 +chr7 131447457 0 0 0.0 0 +chr7 131533308 0 0 0.0 0 +chr7 131669008 0 0 0.0 0 +chr7 131840094 0 0 0.0 0 +chr7 131883359 0 1 0.0116 0 +chr7 132133337 0 0 0.0 0 +chr7 132141575 0 0 0.0 0 +chr7 132214131 0 0 0.0 0 +chr7 132234474 0 0 0.0 0 +chr7 132435517 0 0 0.0 0 +chr7 132470280 0 0 0.0 0 +chr7 132498750 0 0 0.0 0 +chr7 132549009 0 0 0.0 0 +chr7 132567604 0 0 0.0 0 +chr7 132594112 0 0 0.0 0 +chr7 132616174 0 0 0.0 0 +chr7 132634419 0 0 0.0 0 +chr7 133001276 0 0 0.0 0 +chr7 133090519 0 0 0.0 0 +chr7 133138485 0 0 0.0 0 +chr7 133188530 0 0 0.0 0 +chr7 133330292 0 0 0.0 0 +chr7 133333739 0 0 0.0 0 +chr7 133423144 0 0 0.0 0 +chr7 134162872 0 0 0.0 0 +chr7 134239930 0 0 0.0 0 +chr7 134273257 0 0 0.0 0 +chr7 134281960 0 0 0.0 0 +chr7 134316707 0 0 0.0 0 +chr7 134399436 0 0 0.0 0 +chr7 134517656 0 0 0.0 0 +chr7 134548377 0 0 0.0 0 +chr7 134587482 0 0 0.0 0 +chr7 134613361 0 0 0.0 0 +chr7 134705080 0 0 0.0 0 +chr7 134764684 0 0 0.0 0 +chr7 134926211 0 0 0.0 0 +chr7 135222410 0 0 0.0 0 +chr7 135251904 0 0 0.0 0 +chr7 135308095 0 0 0.0 0 +chr7 135353407 0 0 0.0 0 +chr7 135420791 0 0 0.0 0 +chr7 135439574 0 0 0.0 0 +chr7 135567340 0 0 0.0 0 +chr7 135748860 0 0 0.0 0 +chr7 135798428 0 0 0.0 0 +chr7 135909967 0 0 0.0 0 +chr7 135934268 0 0 0.0 0 +chr7 135973856 0 0 0.0 0 +chr7 135976972 0 0 0.0 0 +chr7 136000677 0 0 0.0 0 +chr7 136006042 0 0 0.0 0 +chr7 136068827 0 0 0.0 0 +chr7 136116997 0 0 0.0 0 +chr7 136199500 0 0 0.0 0 +chr7 136222775 0 0 0.0 0 +chr7 136228461 0 0 0.0 0 +chr7 136252533 0 0 0.0 0 +chr7 136266558 0 0 0.0 0 +chr7 136280747 0 0 0.0 0 +chr7 136534211 0 0 0.0 0 +chr7 136709041 0 0 0.0 0 +chr7 136845304 0 0 0.0 0 +chr7 137103681 0 0 0.0 0 +chr7 137165821 0 0 0.0 0 +chr7 137168627 0 0 0.0 0 +chr7 137319756 0 0 0.0 0 +chr7 137520095 0 0 0.0 0 +chr7 137667777 0 0 0.0 0 +chr7 137769212 0 0 0.0 0 +chr7 137819091 0 0 0.0 0 +chr7 137963081 0 0 0.0 0 +chr7 137967992 0 0 0.0 0 +chr7 138229434 0 0 0.0 0 +chr7 138442535 0 0 0.0 0 +chr7 138472149 0 0 0.0 0 +chr7 138508293 0 0 0.0 0 +chr7 138738864 0 0 0.0 0 +chr7 138841068 0 0 0.0 0 +chr7 138924052 0 0 0.0 0 +chr7 138925164 0 0 0.0 0 +chr7 138948147 0 0 0.0 0 +chr7 138988165 0 0 0.0 0 +chr7 139001995 0 0 0.0 0 +chr7 139035554 0 1 0.0213 0 +chr7 139106973 1 20 0.4 1 +chr7 139125186 0 0 0.0 0 +chr7 139157961 0 0 0.0 0 +chr7 139222474 0 0 0.0 0 +chr7 139305519 0 0 0.0 0 +chr7 139510685 0 0 0.0 0 +chr7 139514671 0 0 0.0 0 +chr7 139731262 0 0 0.0 0 +chr7 139823990 0 0 0.0 0 +chr7 139873279 0 0 0.0 0 +chr7 139991253 0 0 0.0 0 +chr7 140012184 0 0 0.0 0 +chr7 140111141 0 0 0.0 0 +chr7 140126680 0 0 0.0 0 +chr7 140204535 0 0 0.0 0 +chr7 140220407 0 0 0.0 0 +chr7 140456036 0 0 0.0 0 +chr7 140494041 0 0 0.0 0 +chr7 140532403 0 0 0.0 0 +chr7 140549152 0 0 0.0 0 +chr7 140704859 0 0 0.0 0 +chr7 140705704 0 0 0.0 0 +chr7 140791528 0 0 0.0 0 +chr7 140801463 0 0 0.0 0 +chr7 140933092 0 0 0.0 0 +chr7 141238440 0 0 0.0 0 +chr7 141334395 0 0 0.0 0 +chr7 141503429 0 0 0.0 0 +chr7 141576323 0 0 0.0 0 +chr7 141636344 0 0 0.0 0 +chr7 141715842 0 0 0.0 0 +chr7 141760542 0 0 0.0 0 +chr7 141909199 0 0 0.0 0 +chr7 141926908 0 0 0.0 0 +chr7 142036692 0 0 0.0 0 +chr7 142074321 0 0 0.0 0 +chr7 142097198 0 0 0.0 0 +chr7 142099359 0 0 0.0 0 +chr7 142211040 0 0 0.0 0 +chr7 142518996 0 0 0.0 0 +chr7 142612216 0 0 0.0 0 +chr7 142626030 0 0 0.0 0 +chr7 142782913 0 0 0.0 0 +chr7 142786478 0 0 0.0 0 +chr7 142792024 0 0 0.0 0 +chr7 142797472 0 1 0.0182 0 +chr7 142801371 0 0 0.0 0 +chr7 142865357 0 0 0.0 0 +chr7 143204882 0 0 0.0 0 +chr7 143264533 0 0 0.0 0 +chr7 143351229 0 0 0.0 0 +chr7 143621478 0 0 0.0 0 +chr7 143836182 0 0 0.0 0 +chr7 144250865 0 0 0.0 0 +chr7 144300112 0 0 0.0 0 +chr7 144426435 0 0 0.0 0 +chr7 144500864 0 0 0.0 0 +chr7 144622639 0 0 0.0 0 +chr7 144784399 0 0 0.0 0 +chr7 145125310 0 0 0.0 0 +chr7 145350619 0 0 0.0 0 +chr7 145374925 0 0 0.0 0 +chr7 145441009 0 0 0.0 0 +chr7 145494736 0 1 0.013 0 +chr7 145514379 0 0 0.0 0 +chr7 145587270 0 0 0.0 0 +chr7 145644752 0 0 0.0 0 +chr7 145774340 0 0 0.0 0 +chr7 145922328 0 1 0.0244 0 +chr7 145975578 0 0 0.0 0 +chr7 145978445 0 0 0.0 0 +chr7 146243639 0 0 0.0 0 +chr7 146253813 0 0 0.0 0 +chr7 146372528 0 0 0.0 0 +chr7 146424074 0 0 0.0 0 +chr7 146708919 0 0 0.0 0 +chr7 146763019 0 0 0.0 0 +chr7 146787002 0 0 0.0 0 +chr7 147047005 1 22 0.5 1 +chr7 147069415 0 0 0.0 0 +chr7 147106793 0 0 0.0 0 +chr7 147129103 0 0 0.0 0 +chr7 147569871 0 0 0.0 0 +chr7 147721970 0 0 0.0 0 +chr7 147822524 0 0 0.0 0 +chr7 147918041 0 0 0.0 0 +chr7 147922314 0 0 0.0 0 +chr7 148153111 0 0 0.0 0 +chr7 148329462 0 0 0.0 0 +chr7 148791583 0 0 0.0 0 +chr7 148802333 0 0 0.0 0 +chr7 148841458 0 0 0.0 0 +chr7 148847919 0 0 0.0 0 +chr7 148854360 0 0 0.0 0 +chr7 148901735 0 0 0.0 0 +chr7 148926051 0 0 0.0 0 +chr7 149071126 0 0 0.0 0 +chr7 149102517 0 0 0.0 0 +chr7 149105065 0 0 0.0 0 +chr7 149199575 0 0 0.0 0 +chr7 149213324 0 0 0.0 0 +chr7 149224732 0 0 0.0 0 +chr7 149318304 0 0 0.0 0 +chr7 149419682 0 0 0.0 0 +chr7 149602826 0 0 0.0 0 +chr7 149607066 0 0 0.0 0 +chr7 149631511 0 0 0.0 0 +chr7 149651425 0 0 0.0 0 +chr7 149673353 0 0 0.0 0 +chr7 149675507 0 0 0.0 0 +chr7 149700596 0 0 0.0 0 +chr7 149754259 0 0 0.0 0 +chr7 149789653 0 0 0.0 0 +chr7 149819293 0 0 0.0 0 +chr7 149836693 0 0 0.0 0 +chr7 149962612 0 0 0.0 0 +chr7 150052079 0 0 0.0 0 +chr7 150092904 0 0 0.0 0 +chr7 150383628 0 0 0.0 0 +chr7 150412610 0 0 0.0 0 +chr7 150439393 0 0 0.0 0 +chr7 150566949 0 0 0.0 0 +chr7 150860508 0 0 0.0 0 +chr7 150946450 0 0 0.0 0 +chr7 151038116 0 0 0.0 0 +chr7 151050475 0 1 0.0256 0 +chr7 151064930 0 0 0.0 0 +chr7 151141596 0 0 0.0 0 +chr7 151211537 0 1 0.0139 0 +chr7 151242669 0 0 0.0 0 +chr7 151251196 0 0 0.0 0 +chr7 151279350 0 0 0.0 0 +chr7 151298392 0 0 0.0 0 +chr7 151352321 0 0 0.0 0 +chr7 151364345 0 0 0.0 0 +chr7 151400165 0 0 0.0 0 +chr7 151564912 0 0 0.0 0 +chr7 151583283 0 0 0.0 0 +chr7 151617016 0 0 0.0 0 +chr7 151624130 1 15 0.2239 1 +chr7 151672598 0 0 0.0 0 +chr7 151687344 0 0 0.0 0 +chr7 151739063 0 0 0.0 0 +chr7 151842742 0 0 0.0 0 +chr7 151988454 0 0 0.0 0 +chr7 152043989 0 0 0.0 0 +chr7 152087512 0 0 0.0 0 +chr7 152106483 0 0 0.0 0 +chr7 152130883 0 0 0.0 0 +chr7 152150760 0 0 0.0 0 +chr7 152546655 0 0 0.0 0 +chr7 152622889 0 0 0.0 0 +chr7 152684965 0 1 0.0357 0 +chr7 152828739 0 0 0.0 0 +chr7 152831762 0 0 0.0 0 +chr7 153053840 0 0 0.0 0 +chr7 153068374 0 0 0.0 0 +chr7 153084537 0 0 0.0 0 +chr7 153103194 0 0 0.0 0 +chr7 153185513 0 0 0.0 0 +chr7 153234862 0 0 0.0 0 +chr7 153257026 0 0 0.0 0 +chr7 153262094 0 0 0.0 0 +chr7 153542244 0 0 0.0 0 +chr7 153566443 0 0 0.0 0 +chr7 153612404 0 0 0.0 0 +chr7 153614055 0 0 0.0 0 +chr7 153658071 0 0 0.0 0 +chr7 154048626 0 0 0.0 0 +chr7 154134362 0 0 0.0 0 +chr7 154232431 0 0 0.0 0 +chr7 154371499 0 0 0.0 0 +chr7 154483293 0 0 0.0 0 +chr7 154568527 0 0 0.0 0 +chr7 154582930 0 0 0.0 0 +chr7 154624785 0 0 0.0 0 +chr7 154641970 0 0 0.0 0 +chr7 154694823 0 0 0.0 0 +chr7 154719378 1 33 0.3548 1 +chr7 154725678 0 0 0.0 0 +chr7 154794375 0 0 0.0 0 +chr7 154860882 0 0 0.0 0 +chr7 154907269 0 1 0.02 0 +chr7 155080157 0 0 0.0 0 +chr7 155153853 0 0 0.0 0 +chr7 155317374 0 0 0.0 0 +chr7 155436027 0 0 0.0 0 +chr7 155506430 0 0 0.0 0 +chr7 155572982 0 0 0.0 0 +chr7 155603386 0 0 0.0 0 +chr7 155746277 0 0 0.0 0 +chr7 155780288 0 0 0.0 0 +chr7 155889896 0 0 0.0 0 +chr7 155986240 0 0 0.0 0 +chr7 156019856 0 0 0.0 0 +chr7 156045624 0 0 0.0 0 +chr7 156121518 0 0 0.0 0 +chr7 156127672 0 0 0.0 0 +chr7 156129831 0 0 0.0 0 +chr7 156397152 0 0 0.0 0 +chr7 156471723 0 0 0.0 0 +chr7 156557435 0 0 0.0 0 +chr7 156618470 0 0 0.0 0 +chr7 156756944 0 0 0.0 0 +chr7 156850089 0 0 0.0 0 +chr7 156900645 0 0 0.0 0 +chr7 157074226 0 0 0.0 0 +chr7 157080245 0 0 0.0 0 +chr7 157383494 0 0 0.0 0 +chr7 157399930 0 0 0.0 0 +chr7 157412315 0 0 0.0 0 +chr7 157418216 0 0 0.0 0 +chr7 157441357 0 1 0.0161 0 +chr7 157505854 0 0 0.0 0 +chr7 157550342 0 0 0.0 0 +chr7 157607424 0 0 0.0 0 +chr7 157615148 0 1 0.0294 0 +chr7 157633020 0 0 0.0 0 +chr7 157789574 0 0 0.0 0 +chr7 157818286 0 0 0.0 0 +chr7 157818901 0 0 0.0 0 +chr7 157824924 0 1 0.0204 0 +chr7 157885715 0 0 0.0 0 +chr7 157938567 0 0 0.0 0 +chr7 158006348 0 0 0.0 0 +chr7 158017969 0 0 0.0 0 +chr7 158040118 0 0 0.0 0 +chr7 158206172 0 0 0.0 0 +chr7 158265057 0 0 0.0 0 +chr7 158300391 0 0 0.0 0 +chr7 158376546 0 0 0.0 0 +chr7 158376816 0 0 0.0 0 +chr7 158454935 0 0 0.0 0 +chr7 158540095 0 0 0.0 0 +chr7 158784611 0 0 0.0 0 +chr7 158937875 0 0 0.0 0 +chr7 158985464 0 0 0.0 0 +chr7 159087174 0 0 0.0 0 +chr7 159087457 0 0 0.0 0 +chr7 159087784 0 0 0.0 0 +chr7 159092601 0 0 0.0 0 +chr7 159151342 0 0 0.0 0 +chr7_GL383534v2_alt 88442 0 0 0.0 0 +chr7_KI270803v1_alt 61239 0 0 0.0 0 +chr7_KI270803v1_alt 172920 0 0 0.0 0 +chr7_KI270803v1_alt 327106 0 0 0.0 0 +chr7_KI270803v1_alt 615879 0 0 0.0 0 +chr7_KI270803v1_alt 809450 0 0 0.0 0 +chr7_KI270803v1_alt 814995 0 0 0.0 0 +chr7_KI270803v1_alt 820445 0 0 0.0 0 +chr7_KI270803v1_alt 824342 0 0 0.0 0 +chr7_KI270804v1_alt 16808 0 0 0.0 0 +chr7_KI270805v1_alt 22240 0 0 0.0 0 +chr7_KI270805v1_alt 100358 0 0 0.0 0 +chr7_KI270805v1_alt 100628 0 0 0.0 0 +chr7_KI270805v1_alt 177347 0 0 0.0 0 +chr7_KI270807v1_alt 95422 0 0 0.0 0 +chr7_KI270807v1_alt 124749 0 0 0.0 0 +chr7_KI270808v1_alt 186054 0 0 0.0 0 +chr7_KI270899v1_alt 53030 0 0 0.0 0 +chr8 79123 0 0 0.0 0 +chr8 80555 0 0 0.0 0 +chr8 86621 0 0 0.0 0 +chr8 127512 0 0 0.0 0 +chr8 294760 0 0 0.0 0 +chr8 334591 0 0 0.0 0 +chr8 362809 0 0 0.0 0 +chr8 626847 0 0 0.0 0 +chr8 716542 0 0 0.0 0 +chr8 733720 0 0 0.0 0 +chr8 875158 0 0 0.0 0 +chr8 896412 0 0 0.0 0 +chr8 1001841 0 0 0.0 0 +chr8 1037796 0 0 0.0 0 +chr8 1089585 0 0 0.0 0 +chr8 1089779 0 0 0.0 0 +chr8 1162055 0 0 0.0 0 +chr8 1204425 0 0 0.0 0 +chr8 1364398 0 0 0.0 0 +chr8 1546503 0 0 0.0 0 +chr8 1557151 0 0 0.0 0 +chr8 1595169 0 0 0.0 0 +chr8 1700144 0 0 0.0 0 +chr8 1846480 0 0 0.0 0 +chr8 1849621 0 1 0.0179 0 +chr8 1855326 0 0 0.0 0 +chr8 1858151 1 13 0.3023 1 +chr8 1864544 0 0 0.0 0 +chr8 1910266 0 0 0.0 0 +chr8 1934091 0 0 0.0 0 +chr8 2022691 0 0 0.0 0 +chr8 2204732 0 0 0.0 0 +chr8 2485466 0 0 0.0 0 +chr8 2506381 0 0 0.0 0 +chr8 2575529 0 0 0.0 0 +chr8 2814704 0 0 0.0 0 +chr8 2825052 0 0 0.0 0 +chr8 2851712 0 0 0.0 0 +chr8 2853069 0 0 0.0 0 +chr8 2990812 0 0 0.0 0 +chr8 3026548 0 0 0.0 0 +chr8 3106372 0 0 0.0 0 +chr8 3123650 0 0 0.0 0 +chr8 3153489 0 0 0.0 0 +chr8 3195307 0 0 0.0 0 +chr8 3205077 0 0 0.0 0 +chr8 3277257 0 0 0.0 0 +chr8 3468888 0 0 0.0 0 +chr8 3529093 0 0 0.0 0 +chr8 3598287 0 0 0.0 0 +chr8 3742617 0 0 0.0 0 +chr8 3762956 1 69 0.9857 1 +chr8 3857602 0 0 0.0 0 +chr8 3887010 0 0 0.0 0 +chr8 3900302 0 0 0.0 0 +chr8 3928857 0 0 0.0 0 +chr8 4045198 0 0 0.0 0 +chr8 4045806 0 0 0.0 0 +chr8 4085757 0 0 0.0 0 +chr8 4107434 0 0 0.0 0 +chr8 4168796 0 0 0.0 0 +chr8 4227542 0 0 0.0 0 +chr8 4254622 0 0 0.0 0 +chr8 4320749 0 0 0.0 0 +chr8 4381362 0 0 0.0 0 +chr8 4490974 0 0 0.0 0 +chr8 4530214 0 0 0.0 0 +chr8 4583203 0 0 0.0 0 +chr8 4624420 0 0 0.0 0 +chr8 4692877 0 0 0.0 0 +chr8 4958815 0 0 0.0 0 +chr8 4961370 0 0 0.0 0 +chr8 4988973 0 0 0.0 0 +chr8 5039374 0 0 0.0 0 +chr8 5288785 0 0 0.0 0 +chr8 5300427 0 0 0.0 0 +chr8 5473619 0 0 0.0 0 +chr8 5490519 0 0 0.0 0 +chr8 5600317 0 0 0.0 0 +chr8 5710185 0 0 0.0 0 +chr8 5714062 0 0 0.0 0 +chr8 5780669 0 0 0.0 0 +chr8 5809216 0 0 0.0 0 +chr8 5890594 0 1 0.0152 0 +chr8 5907758 0 0 0.0 0 +chr8 6009164 1 14 0.4 1 +chr8 6043412 0 0 0.0 0 +chr8 6045073 0 0 0.0 0 +chr8 6189914 0 0 0.0 0 +chr8 6210412 0 0 0.0 0 +chr8 6223714 0 0 0.0 0 +chr8 6348200 0 0 0.0 0 +chr8 6489356 0 0 0.0 0 +chr8 6504033 0 0 0.0 0 +chr8 6553203 0 0 0.0 0 +chr8 6720947 0 1 0.0217 0 +chr8 6821010 0 0 0.0 0 +chr8 6869761 0 0 0.0 0 +chr8 6873921 0 0 0.0 0 +chr8 6959250 0 0 0.0 0 +chr8 6983503 0 0 0.0 0 +chr8 7002608 0 0 0.0 0 +chr8 7021704 0 0 0.0 0 +chr8 7022521 0 0 0.0 0 +chr8 7116643 0 0 0.0 0 +chr8 7155702 0 0 0.0 0 +chr8 7473881 0 0 0.0 0 +chr8 7486176 0 0 0.0 0 +chr8 7825384 0 0 0.0 0 +chr8 7837674 0 0 0.0 0 +chr8 8131770 0 0 0.0 0 +chr8 8173719 0 0 0.0 0 +chr8 8243820 0 0 0.0 0 +chr8 8364741 0 0 0.0 0 +chr8 8374404 0 0 0.0 0 +chr8 8535213 0 0 0.0 0 +chr8 8588665 0 0 0.0 0 +chr8 8645296 0 0 0.0 0 +chr8 8664532 0 0 0.0 0 +chr8 8814469 0 0 0.0 0 +chr8 8825137 0 0 0.0 0 +chr8 8897351 0 0 0.0 0 +chr8 9025008 0 0 0.0 0 +chr8 9090133 0 0 0.0 0 +chr8 9148842 0 0 0.0 0 +chr8 9477374 0 0 0.0 0 +chr8 9527148 0 0 0.0 0 +chr8 9814807 0 0 0.0 0 +chr8 9816255 0 0 0.0 0 +chr8 9904829 0 0 0.0 0 +chr8 9999512 0 0 0.0 0 +chr8 10004843 0 0 0.0 0 +chr8 10078651 0 0 0.0 0 +chr8 10104749 0 0 0.0 0 +chr8 10198635 0 0 0.0 0 +chr8 10229155 0 0 0.0 0 +chr8 10415265 0 0 0.0 0 +chr8 10518895 0 0 0.0 0 +chr8 10620198 0 0 0.0 0 +chr8 10643672 0 0 0.0 0 +chr8 10754559 0 0 0.0 0 +chr8 10898712 0 0 0.0 0 +chr8 10925331 0 0 0.0 0 +chr8 10949801 0 0 0.0 0 +chr8 10992903 0 0 0.0 0 +chr8 11011448 0 0 0.0 0 +chr8 11039545 0 0 0.0 0 +chr8 11058654 0 0 0.0 0 +chr8 11079132 0 0 0.0 0 +chr8 11181011 0 0 0.0 0 +chr8 11200836 0 0 0.0 0 +chr8 11233037 0 0 0.0 0 +chr8 11282886 0 0 0.0 0 +chr8 11334028 0 0 0.0 0 +chr8 11593485 0 0 0.0 0 +chr8 11627842 0 0 0.0 0 +chr8 11628328 0 0 0.0 0 +chr8 11660823 0 0 0.0 0 +chr8 11687274 0 1 0.0111 0 +chr8 11739282 0 0 0.0 0 +chr8 11748808 0 1 0.0185 0 +chr8 11757536 0 0 0.0 0 +chr8 11786018 0 0 0.0 0 +chr8 11786562 0 0 0.0 0 +chr8 11797327 0 0 0.0 0 +chr8 11969228 0 0 0.0 0 +chr8 12187621 0 0 0.0 0 +chr8 12190030 0 0 0.0 0 +chr8 12231340 0 0 0.0 0 +chr8 12429899 0 0 0.0 0 +chr8 12432304 0 0 0.0 0 +chr8 12491945 0 0 0.0 0 +chr8 12533914 0 0 0.0 0 +chr8 12577409 0 0 0.0 0 +chr8 12635509 0 0 0.0 0 +chr8 12759800 0 0 0.0 0 +chr8 12924206 0 0 0.0 0 +chr8 13034022 0 0 0.0 0 +chr8 13100064 0 0 0.0 0 +chr8 13244547 0 0 0.0 0 +chr8 13425225 0 0 0.0 0 +chr8 13700318 0 0 0.0 0 +chr8 13710492 0 0 0.0 0 +chr8 13744441 0 0 0.0 0 +chr8 13753130 0 0 0.0 0 +chr8 14127964 0 0 0.0 0 +chr8 14317082 0 0 0.0 0 +chr8 14435171 0 0 0.0 0 +chr8 14444357 0 0 0.0 0 +chr8 14492712 0 0 0.0 0 +chr8 14493002 0 0 0.0 0 +chr8 14936496 0 0 0.0 0 +chr8 15032798 0 0 0.0 0 +chr8 15145328 0 0 0.0 0 +chr8 15239862 0 0 0.0 0 +chr8 15363080 0 0 0.0 0 +chr8 15372681 0 0 0.0 0 +chr8 15388801 0 0 0.0 0 +chr8 15583729 0 0 0.0 0 +chr8 15613554 0 0 0.0 0 +chr8 15756879 0 1 0.0145 0 +chr8 15767567 0 0 0.0 0 +chr8 15896210 0 0 0.0 0 +chr8 15941496 1 72 0.9114 1 +chr8 16040114 0 0 0.0 0 +chr8 16106128 0 0 0.0 0 +chr8 16234754 0 0 0.0 0 +chr8 16346345 0 0 0.0 0 +chr8 16376209 0 0 0.0 0 +chr8 16497538 0 0 0.0 0 +chr8 16507836 0 0 0.0 0 +chr8 16527128 0 0 0.0 0 +chr8 16561673 0 0 0.0 0 +chr8 16598887 0 0 0.0 0 +chr8 16702126 0 0 0.0 0 +chr8 16761511 0 0 0.0 0 +chr8 16786116 0 0 0.0 0 +chr8 16979128 0 0 0.0 0 +chr8 17090225 0 0 0.0 0 +chr8 17124916 0 0 0.0 0 +chr8 17158527 0 0 0.0 0 +chr8 17383714 0 0 0.0 0 +chr8 17388767 0 0 0.0 0 +chr8 17446962 0 0 0.0 0 +chr8 17553540 0 0 0.0 0 +chr8 17577318 0 0 0.0 0 +chr8 17606595 0 0 0.0 0 +chr8 17628821 0 0 0.0 0 +chr8 17634351 0 0 0.0 0 +chr8 17665187 0 0 0.0 0 +chr8 17672763 0 0 0.0 0 +chr8 17722253 1 10 0.3448 1 +chr8 17746351 0 0 0.0 0 +chr8 17797979 0 0 0.0 0 +chr8 17887489 0 0 0.0 0 +chr8 17929677 0 0 0.0 0 +chr8 17945448 0 0 0.0 0 +chr8 18213432 0 0 0.0 0 +chr8 18448842 0 0 0.0 0 +chr8 18459185 0 0 0.0 0 +chr8 18564806 0 0 0.0 0 +chr8 18828206 0 0 0.0 0 +chr8 18903326 0 0 0.0 0 +chr8 18963646 0 0 0.0 0 +chr8 18966908 0 0 0.0 0 +chr8 19053346 0 0 0.0 0 +chr8 19058966 0 0 0.0 0 +chr8 19167122 0 0 0.0 0 +chr8 19474217 0 0 0.0 0 +chr8 19671496 0 0 0.0 0 +chr8 19678411 0 0 0.0 0 +chr8 19810592 0 0 0.0 0 +chr8 19860049 0 0 0.0 0 +chr8 20087569 0 1 0.0222 0 +chr8 20159912 0 0 0.0 0 +chr8 20243080 0 0 0.0 0 +chr8 20272941 0 0 0.0 0 +chr8 20396903 0 0 0.0 0 +chr8 20406237 0 0 0.0 0 +chr8 20463353 0 0 0.0 0 +chr8 20503906 0 0 0.0 0 +chr8 20557382 0 0 0.0 0 +chr8 20650469 0 0 0.0 0 +chr8 20724206 0 0 0.0 0 +chr8 20829331 0 0 0.0 0 +chr8 20829728 0 0 0.0 0 +chr8 20884197 0 0 0.0 0 +chr8 21021566 0 0 0.0 0 +chr8 21049521 0 0 0.0 0 +chr8 21053918 0 0 0.0 0 +chr8 21171925 0 0 0.0 0 +chr8 21324279 0 0 0.0 0 +chr8 21343710 0 0 0.0 0 +chr8 21462621 0 0 0.0 0 +chr8 21610726 0 0 0.0 0 +chr8 21672276 0 0 0.0 0 +chr8 21702895 0 0 0.0 0 +chr8 21710531 0 0 0.0 0 +chr8 21805946 0 0 0.0 0 +chr8 22067254 0 0 0.0 0 +chr8 22121371 0 0 0.0 0 +chr8 22154422 0 0 0.0 0 +chr8 22194607 0 0 0.0 0 +chr8 22287142 0 0 0.0 0 +chr8 22380693 1 37 0.5286 1 +chr8 22487079 0 0 0.0 0 +chr8 22573981 0 1 0.0141 0 +chr8 22606147 0 0 0.0 0 +chr8 22669765 0 0 0.0 0 +chr8 22681909 0 0 0.0 0 +chr8 22719316 0 0 0.0 0 +chr8 22725471 0 0 0.0 0 +chr8 22756811 0 0 0.0 0 +chr8 22840503 0 0 0.0 0 +chr8 22946760 0 1 0.0189 0 +chr8 22999316 0 0 0.0 0 +chr8 23034322 0 0 0.0 0 +chr8 23043299 0 0 0.0 0 +chr8 23112494 0 0 0.0 0 +chr8 23135923 0 0 0.0 0 +chr8 23171714 0 0 0.0 0 +chr8 23220734 0 0 0.0 0 +chr8 23223868 0 0 0.0 0 +chr8 23356449 0 0 0.0 0 +chr8 23524410 0 0 0.0 0 +chr8 23552280 0 0 0.0 0 +chr8 23577870 0 0 0.0 0 +chr8 23798243 0 0 0.0 0 +chr8 23804732 0 0 0.0 0 +chr8 23864207 0 0 0.0 0 +chr8 23977875 0 0 0.0 0 +chr8 23989576 0 0 0.0 0 +chr8 24076978 0 0 0.0 0 +chr8 24141154 0 0 0.0 0 +chr8 24278949 0 0 0.0 0 +chr8 24346520 0 0 0.0 0 +chr8 24515468 0 0 0.0 0 +chr8 24529896 0 0 0.0 0 +chr8 24548556 0 0 0.0 0 +chr8 24769030 0 1 0.0227 0 +chr8 24896326 0 0 0.0 0 +chr8 24986416 0 0 0.0 0 +chr8 25084172 0 0 0.0 0 +chr8 25142362 0 0 0.0 0 +chr8 25260201 0 0 0.0 0 +chr8 25281106 0 0 0.0 0 +chr8 25290107 0 0 0.0 0 +chr8 25343752 0 0 0.0 0 +chr8 25438157 0 0 0.0 0 +chr8 25488013 0 0 0.0 0 +chr8 25769122 0 0 0.0 0 +chr8 25796084 0 0 0.0 0 +chr8 25813890 0 0 0.0 0 +chr8 25846852 0 0 0.0 0 +chr8 25925094 0 0 0.0 0 +chr8 25950656 0 0 0.0 0 +chr8 25952643 0 0 0.0 0 +chr8 26070064 0 0 0.0 0 +chr8 26144033 0 0 0.0 0 +chr8 26330581 0 0 0.0 0 +chr8 26437651 0 0 0.0 0 +chr8 26499785 0 0 0.0 0 +chr8 26545543 0 0 0.0 0 +chr8 26612844 0 0 0.0 0 +chr8 26888363 0 0 0.0 0 +chr8 26960740 0 0 0.0 0 +chr8 27224390 0 0 0.0 0 +chr8 27298567 0 0 0.0 0 +chr8 27428719 0 0 0.0 0 +chr8 27481626 0 0 0.0 0 +chr8 27521176 0 0 0.0 0 +chr8 27563703 0 0 0.0 0 +chr8 27581554 0 0 0.0 0 +chr8 27606540 0 0 0.0 0 +chr8 27653669 0 0 0.0 0 +chr8 27686190 0 0 0.0 0 +chr8 27904540 0 0 0.0 0 +chr8 27983720 0 0 0.0 0 +chr8 28421421 0 0 0.0 0 +chr8 28461356 0 0 0.0 0 +chr8 28549218 0 0 0.0 0 +chr8 29045903 0 0 0.0 0 +chr8 29110712 0 0 0.0 0 +chr8 29204982 0 0 0.0 0 +chr8 29396487 0 0 0.0 0 +chr8 29440741 0 0 0.0 0 +chr8 29495537 0 0 0.0 0 +chr8 29568789 0 0 0.0 0 +chr8 29662274 1 50 0.8929 1 +chr8 29725572 0 0 0.0 0 +chr8 29734445 0 0 0.0 0 +chr8 29759894 0 0 0.0 0 +chr8 29880759 0 0 0.0 0 +chr8 29887388 0 0 0.0 0 +chr8 29934796 0 0 0.0 0 +chr8 29988186 0 0 0.0 0 +chr8 30058867 0 0 0.0 0 +chr8 30086578 0 0 0.0 0 +chr8 30094522 0 0 0.0 0 +chr8 30151332 0 0 0.0 0 +chr8 30162183 0 0 0.0 0 +chr8 30269548 0 0 0.0 0 +chr8 30429010 0 0 0.0 0 +chr8 30431140 0 0 0.0 0 +chr8 30588798 0 0 0.0 0 +chr8 30730523 0 0 0.0 0 +chr8 30773509 0 0 0.0 0 +chr8 30868429 0 0 0.0 0 +chr8 30903349 0 0 0.0 0 +chr8 30964075 0 0 0.0 0 +chr8 31009210 0 0 0.0 0 +chr8 31246405 0 0 0.0 0 +chr8 31267603 0 0 0.0 0 +chr8 31373972 0 0 0.0 0 +chr8 31416724 0 0 0.0 0 +chr8 31438860 0 0 0.0 0 +chr8 31452466 0 0 0.0 0 +chr8 31478493 0 0 0.0 0 +chr8 31545402 0 0 0.0 0 +chr8 31645219 0 0 0.0 0 +chr8 32006623 0 0 0.0 0 +chr8 32147463 0 0 0.0 0 +chr8 32297588 0 0 0.0 0 +chr8 32379010 0 0 0.0 0 +chr8 32456889 0 0 0.0 0 +chr8 32463319 0 0 0.0 0 +chr8 32493338 0 0 0.0 0 +chr8 32655403 0 0 0.0 0 +chr8 32778815 0 0 0.0 0 +chr8 32856674 0 0 0.0 0 +chr8 32928119 0 0 0.0 0 +chr8 33016654 0 0 0.0 0 +chr8 33311566 0 0 0.0 0 +chr8 33338174 0 0 0.0 0 +chr8 33352796 0 0 0.0 0 +chr8 33436668 0 0 0.0 0 +chr8 33529020 0 0 0.0 0 +chr8 33594081 0 0 0.0 0 +chr8 33742477 0 0 0.0 0 +chr8 33763179 0 0 0.0 0 +chr8 33797893 0 0 0.0 0 +chr8 33967001 0 0 0.0 0 +chr8 33973939 0 0 0.0 0 +chr8 34035661 0 0 0.0 0 +chr8 34047133 0 0 0.0 0 +chr8 34271074 0 0 0.0 0 +chr8 34349951 0 0 0.0 0 +chr8 34525566 0 0 0.0 0 +chr8 34535798 0 0 0.0 0 +chr8 34542963 0 0 0.0 0 +chr8 34629582 0 0 0.0 0 +chr8 34770253 0 0 0.0 0 +chr8 34786392 0 0 0.0 0 +chr8 34809171 0 0 0.0 0 +chr8 34872572 0 0 0.0 0 +chr8 34880807 0 0 0.0 0 +chr8 34985193 0 0 0.0 0 +chr8 35099798 0 0 0.0 0 +chr8 35142224 0 0 0.0 0 +chr8 35298263 0 0 0.0 0 +chr8 35398588 0 0 0.0 0 +chr8 35566595 0 0 0.0 0 +chr8 35609817 0 0 0.0 0 +chr8 35863508 0 0 0.0 0 +chr8 36017167 0 0 0.0 0 +chr8 36181904 0 0 0.0 0 +chr8 36307724 0 0 0.0 0 +chr8 36395534 0 0 0.0 0 +chr8 36415816 0 0 0.0 0 +chr8 36440890 0 0 0.0 0 +chr8 36511007 0 0 0.0 0 +chr8 36587197 0 0 0.0 0 +chr8 36907278 0 0 0.0 0 +chr8 37347431 0 0 0.0 0 +chr8 37369155 0 0 0.0 0 +chr8 37380167 0 0 0.0 0 +chr8 37419913 0 0 0.0 0 +chr8 37445161 0 1 0.025 0 +chr8 37529809 0 0 0.0 0 +chr8 37594944 0 0 0.0 0 +chr8 37690321 0 0 0.0 0 +chr8 37789630 0 0 0.0 0 +chr8 37877120 0 0 0.0 0 +chr8 37898858 1 6 0.24 1 +chr8 37904511 0 0 0.0 0 +chr8 37961046 0 0 0.0 0 +chr8 37976926 0 0 0.0 0 +chr8 37978550 0 0 0.0 0 +chr8 37979270 0 0 0.0 0 +chr8 38889969 0 1 0.0455 0 +chr8 38938405 0 0 0.0 0 +chr8 39001474 0 0 0.0 0 +chr8 39021819 0 0 0.0 0 +chr8 39122109 0 0 0.0 0 +chr8 39357432 0 0 0.0 0 +chr8 39414879 0 0 0.0 0 +chr8 39580866 0 0 0.0 0 +chr8 39650907 0 0 0.0 0 +chr8 39870952 0 0 0.0 0 +chr8 39988950 0 0 0.0 0 +chr8 39994998 0 0 0.0 0 +chr8 40203762 0 2 0.0308 0 +chr8 40336047 0 0 0.0 0 +chr8 40347129 0 0 0.0 0 +chr8 40393554 0 0 0.0 0 +chr8 40417946 0 0 0.0 0 +chr8 40418367 0 0 0.0 0 +chr8 40430904 0 0 0.0 0 +chr8 40492088 0 0 0.0 0 +chr8 40599194 0 0 0.0 0 +chr8 40752803 0 0 0.0 0 +chr8 40782964 0 0 0.0 0 +chr8 40864692 0 0 0.0 0 +chr8 41008638 0 0 0.0 0 +chr8 41103588 0 0 0.0 0 +chr8 41202661 0 0 0.0 0 +chr8 41301576 0 0 0.0 0 +chr8 41329150 0 0 0.0 0 +chr8 41340583 0 0 0.0 0 +chr8 41341790 0 0 0.0 0 +chr8 41357220 0 0 0.0 0 +chr8 41431378 0 0 0.0 0 +chr8 41441688 0 0 0.0 0 +chr8 41463223 0 0 0.0 0 +chr8 41465768 0 1 0.0141 0 +chr8 41569714 0 0 0.0 0 +chr8 41604371 0 0 0.0 0 +chr8 41640801 0 0 0.0 0 +chr8 41665647 0 0 0.0 0 +chr8 41687023 0 0 0.0 0 +chr8 41722548 0 0 0.0 0 +chr8 41730826 0 0 0.0 0 +chr8 41762758 0 0 0.0 0 +chr8 41773867 0 0 0.0 0 +chr8 41789228 0 0 0.0 0 +chr8 41810608 0 0 0.0 0 +chr8 41916184 0 0 0.0 0 +chr8 41953852 0 0 0.0 0 +chr8 41967687 0 0 0.0 0 +chr8 42140870 0 0 0.0 0 +chr8 42152343 0 0 0.0 0 +chr8 42217937 0 0 0.0 0 +chr8 42218403 0 0 0.0 0 +chr8 42280136 0 0 0.0 0 +chr8 42326207 0 0 0.0 0 +chr8 42439307 0 0 0.0 0 +chr8 42731246 0 0 0.0 0 +chr8 42982499 0 0 0.0 0 +chr8 43178132 0 0 0.0 0 +chr8 43212996 0 0 0.0 0 +chr8 43270749 0 0 0.0 0 +chr8 43423557 0 0 0.0 0 +chr8 43454979 0 0 0.0 0 +chr8 43465443 0 0 0.0 0 +chr8 43519133 0 0 0.0 0 +chr8 43597031 0 0 0.0 0 +chr8 43624122 0 0 0.0 0 +chr8 43641863 0 0 0.0 0 +chr8 43694118 0 0 0.0 0 +chr8 43841095 0 0 0.0 0 +chr8 46012146 0 0 0.0 0 +chr8 46089669 0 0 0.0 0 +chr8 46097939 0 0 0.0 0 +chr8 46115210 0 0 0.0 0 +chr8 46116383 0 0 0.0 0 +chr8 46141452 0 0 0.0 0 +chr8 46144929 0 0 0.0 0 +chr8 46152239 0 0 0.0 0 +chr8 46187802 0 0 0.0 0 +chr8 46224173 0 0 0.0 0 +chr8 46463576 0 0 0.0 0 +chr8 46510190 0 0 0.0 0 +chr8 46559629 0 0 0.0 0 +chr8 46667544 0 1 0.0147 0 +chr8 46806892 0 1 0.013 0 +chr8 46999515 0 0 0.0 0 +chr8 47024591 0 0 0.0 0 +chr8 47207303 0 1 0.0118 0 +chr8 47553594 0 0 0.0 0 +chr8 47641072 0 0 0.0 0 +chr8 47725182 0 0 0.0 0 +chr8 47751568 0 0 0.0 0 +chr8 47752808 0 1 0.0114 0 +chr8 47860775 0 1 0.027 0 +chr8 47887083 0 0 0.0 0 +chr8 47957912 0 0 0.0 0 +chr8 48043651 0 0 0.0 0 +chr8 48143198 0 0 0.0 0 +chr8 48392087 0 0 0.0 0 +chr8 48396650 0 0 0.0 0 +chr8 48431750 0 1 0.0147 0 +chr8 48433056 0 1 0.0139 0 +chr8 48486395 0 0 0.0 0 +chr8 48589872 0 0 0.0 0 +chr8 48592849 0 0 0.0 0 +chr8 48653149 0 0 0.0 0 +chr8 48715987 0 0 0.0 0 +chr8 48914648 0 0 0.0 0 +chr8 48923896 0 0 0.0 0 +chr8 48973382 0 0 0.0 0 +chr8 49263645 0 0 0.0 0 +chr8 49336369 0 1 0.0208 0 +chr8 49429876 0 0 0.0 0 +chr8 49652670 0 0 0.0 0 +chr8 49756639 0 0 0.0 0 +chr8 49865023 0 0 0.0 0 +chr8 50010776 0 1 0.0769 0 +chr8 50260861 0 0 0.0 0 +chr8 50405676 0 0 0.0 0 +chr8 50419475 0 0 0.0 0 +chr8 50469394 0 0 0.0 0 +chr8 50630376 0 0 0.0 0 +chr8 50712700 0 0 0.0 0 +chr8 50792932 0 0 0.0 0 +chr8 50816853 0 0 0.0 0 +chr8 50874441 0 0 0.0 0 +chr8 51080465 0 0 0.0 0 +chr8 51247487 0 0 0.0 0 +chr8 51295749 0 0 0.0 0 +chr8 51377890 0 0 0.0 0 +chr8 51394946 0 1 0.0244 0 +chr8 51457312 0 0 0.0 0 +chr8 51507422 0 0 0.0 0 +chr8 51510979 0 0 0.0 0 +chr8 51698654 0 0 0.0 0 +chr8 51736878 0 0 0.0 0 +chr8 51751880 0 0 0.0 0 +chr8 52031925 0 0 0.0 0 +chr8 52214701 0 0 0.0 0 +chr8 52314942 0 1 0.0208 0 +chr8 52433781 0 0 0.0 0 +chr8 52846578 0 0 0.0 0 +chr8 52874997 0 0 0.0 0 +chr8 52958201 0 0 0.0 0 +chr8 53025747 0 0 0.0 0 +chr8 53071156 0 0 0.0 0 +chr8 53139237 0 0 0.0 0 +chr8 53193161 0 0 0.0 0 +chr8 53209363 0 0 0.0 0 +chr8 53215337 0 0 0.0 0 +chr8 53439113 0 0 0.0 0 +chr8 53565042 0 0 0.0 0 +chr8 53751331 0 0 0.0 0 +chr8 53759169 0 0 0.0 0 +chr8 53879603 0 0 0.0 0 +chr8 53942631 0 0 0.0 0 +chr8 54001094 0 0 0.0 0 +chr8 54366149 0 0 0.0 0 +chr8 54443761 0 0 0.0 0 +chr8 54458231 0 0 0.0 0 +chr8 54503500 0 0 0.0 0 +chr8 54548768 0 2 0.04 0 +chr8 54572557 0 0 0.0 0 +chr8 54579951 0 0 0.0 0 +chr8 54849297 0 0 0.0 0 +chr8 54977180 0 0 0.0 0 +chr8 55059420 0 0 0.0 0 +chr8 55096902 0 0 0.0 0 +chr8 55128225 0 0 0.0 0 +chr8 55228670 0 0 0.0 0 +chr8 55266807 0 0 0.0 0 +chr8 55277274 0 0 0.0 0 +chr8 55312886 0 0 0.0 0 +chr8 55317665 0 0 0.0 0 +chr8 55991322 0 0 0.0 0 +chr8 56007243 0 0 0.0 0 +chr8 56100821 0 0 0.0 0 +chr8 56111527 0 0 0.0 0 +chr8 56234594 0 0 0.0 0 +chr8 56338052 0 0 0.0 0 +chr8 56573116 0 0 0.0 0 +chr8 56629017 0 0 0.0 0 +chr8 56662643 0 0 0.0 0 +chr8 56959466 0 0 0.0 0 +chr8 56964528 0 0 0.0 0 +chr8 57268650 0 0 0.0 0 +chr8 57275096 0 0 0.0 0 +chr8 57275895 0 0 0.0 0 +chr8 57308833 0 0 0.0 0 +chr8 57326220 0 0 0.0 0 +chr8 57355304 0 0 0.0 0 +chr8 57361273 0 0 0.0 0 +chr8 57524835 0 0 0.0 0 +chr8 57646864 0 0 0.0 0 +chr8 57677230 0 0 0.0 0 +chr8 57696028 0 0 0.0 0 +chr8 57839529 0 0 0.0 0 +chr8 57901487 0 0 0.0 0 +chr8 57979857 0 0 0.0 0 +chr8 58121391 0 0 0.0 0 +chr8 58129495 0 0 0.0 0 +chr8 58332574 0 0 0.0 0 +chr8 58411443 0 0 0.0 0 +chr8 58411799 0 0 0.0 0 +chr8 58551973 0 0 0.0 0 +chr8 58749876 0 0 0.0 0 +chr8 58855543 0 0 0.0 0 +chr8 58890446 0 0 0.0 0 +chr8 59012294 0 0 0.0 0 +chr8 59038273 0 0 0.0 0 +chr8 59274613 0 0 0.0 0 +chr8 59328555 0 0 0.0 0 +chr8 59403747 0 0 0.0 0 +chr8 59524528 0 0 0.0 0 +chr8 59559432 0 0 0.0 0 +chr8 59588808 0 0 0.0 0 +chr8 59655310 0 0 0.0 0 +chr8 59680379 0 0 0.0 0 +chr8 59683487 0 0 0.0 0 +chr8 59683966 0 0 0.0 0 +chr8 59993361 0 0 0.0 0 +chr8 60000230 0 0 0.0 0 +chr8 60041039 0 0 0.0 0 +chr8 60082805 0 0 0.0 0 +chr8 60083973 0 0 0.0 0 +chr8 60293777 0 0 0.0 0 +chr8 60310053 0 0 0.0 0 +chr8 60583795 0 0 0.0 0 +chr8 60664195 0 0 0.0 0 +chr8 60981517 0 0 0.0 0 +chr8 61112769 0 0 0.0 0 +chr8 61227934 0 0 0.0 0 +chr8 61241652 0 0 0.0 0 +chr8 61336905 0 1 0.027 0 +chr8 61554207 0 1 0.04 0 +chr8 61581445 0 0 0.0 0 +chr8 61854320 0 0 0.0 0 +chr8 61870105 0 0 0.0 0 +chr8 62293520 0 0 0.0 0 +chr8 62397629 0 0 0.0 0 +chr8 62492876 0 0 0.0 0 +chr8 62523895 0 0 0.0 0 +chr8 62577861 0 0 0.0 0 +chr8 62861211 0 0 0.0 0 +chr8 63026778 0 0 0.0 0 +chr8 63078035 0 0 0.0 0 +chr8 63084990 0 0 0.0 0 +chr8 63174550 0 0 0.0 0 +chr8 63263983 0 0 0.0 0 +chr8 63394889 0 0 0.0 0 +chr8 63417197 1 32 0.4848 1 +chr8 63426176 0 0 0.0 0 +chr8 63441134 0 0 0.0 0 +chr8 63584353 0 0 0.0 0 +chr8 63648515 0 0 0.0 0 +chr8 63761357 0 0 0.0 0 +chr8 64056816 0 0 0.0 0 +chr8 64310808 0 0 0.0 0 +chr8 64352620 0 0 0.0 0 +chr8 64404826 0 0 0.0 0 +chr8 64581677 0 0 0.0 0 +chr8 64624543 1 4 0.0597 1 +chr8 64672443 0 0 0.0 0 +chr8 64764722 0 0 0.0 0 +chr8 64884297 0 0 0.0 0 +chr8 64916091 0 0 0.0 0 +chr8 64956430 0 0 0.0 0 +chr8 64988140 0 0 0.0 0 +chr8 65025725 0 0 0.0 0 +chr8 65042124 0 0 0.0 0 +chr8 65232571 0 0 0.0 0 +chr8 65269536 0 2 0.0278 0 +chr8 65316266 0 1 0.0196 0 +chr8 65327304 0 0 0.0 0 +chr8 65514746 0 0 0.0 0 +chr8 65779779 0 0 0.0 0 +chr8 65782785 0 0 0.0 0 +chr8 65975252 0 0 0.0 0 +chr8 65977809 0 0 0.0 0 +chr8 66128414 0 0 0.0 0 +chr8 66239216 0 0 0.0 0 +chr8 66439478 0 0 0.0 0 +chr8 66463113 0 0 0.0 0 +chr8 66523657 0 0 0.0 0 +chr8 66831901 0 0 0.0 0 +chr8 66848564 0 0 0.0 0 +chr8 66875101 0 0 0.0 0 +chr8 67059374 0 0 0.0 0 +chr8 67320592 0 0 0.0 0 +chr8 67496053 0 0 0.0 0 +chr8 67718131 0 0 0.0 0 +chr8 67759993 0 0 0.0 0 +chr8 67761413 0 0 0.0 0 +chr8 67819244 0 0 0.0 0 +chr8 67979605 0 0 0.0 0 +chr8 67999386 0 0 0.0 0 +chr8 68250116 0 0 0.0 0 +chr8 68265320 0 0 0.0 0 +chr8 68274492 0 0 0.0 0 +chr8 68393176 0 1 0.025 0 +chr8 68709438 0 0 0.0 0 +chr8 68990038 0 0 0.0 0 +chr8 69074824 0 0 0.0 0 +chr8 69131813 0 0 0.0 0 +chr8 69280491 0 0 0.0 0 +chr8 69281047 0 0 0.0 0 +chr8 69447123 0 0 0.0 0 +chr8 69478199 0 0 0.0 0 +chr8 69478609 0 0 0.0 0 +chr8 69548355 0 0 0.0 0 +chr8 69609435 0 0 0.0 0 +chr8 69623277 0 0 0.0 0 +chr8 69709765 0 0 0.0 0 +chr8 69893569 0 0 0.0 0 +chr8 70058515 0 0 0.0 0 +chr8 70090099 0 0 0.0 0 +chr8 70091755 0 0 0.0 0 +chr8 70189337 0 0 0.0 0 +chr8 70288000 0 0 0.0 0 +chr8 70396702 0 0 0.0 0 +chr8 70398982 0 0 0.0 0 +chr8 70581661 0 0 0.0 0 +chr8 70837683 0 0 0.0 0 +chr8 70918067 0 0 0.0 0 +chr8 70954596 0 0 0.0 0 +chr8 71090040 0 0 0.0 0 +chr8 71197505 0 0 0.0 0 +chr8 71223093 0 0 0.0 0 +chr8 71301144 0 0 0.0 0 +chr8 71452650 0 0 0.0 0 +chr8 71917760 0 0 0.0 0 +chr8 71938799 0 0 0.0 0 +chr8 71981633 0 0 0.0 0 +chr8 72112029 0 0 0.0 0 +chr8 72143744 0 0 0.0 0 +chr8 72205340 0 0 0.0 0 +chr8 72371081 0 0 0.0 0 +chr8 72403904 0 0 0.0 0 +chr8 72405599 0 0 0.0 0 +chr8 72460065 0 0 0.0 0 +chr8 72545239 0 0 0.0 0 +chr8 72582817 0 1 0.0185 0 +chr8 72628764 0 0 0.0 0 +chr8 72671768 0 0 0.0 0 +chr8 72807720 0 0 0.0 0 +chr8 72898171 0 0 0.0 0 +chr8 73148352 0 0 0.0 0 +chr8 73191737 0 0 0.0 0 +chr8 73203162 0 0 0.0 0 +chr8 73218738 0 0 0.0 0 +chr8 73299928 0 0 0.0 0 +chr8 73418199 0 0 0.0 0 +chr8 73484847 0 0 0.0 0 +chr8 73739626 0 0 0.0 0 +chr8 73786560 0 0 0.0 0 +chr8 73812558 0 0 0.0 0 +chr8 73908758 0 0 0.0 0 +chr8 73956899 0 0 0.0 0 +chr8 73967117 0 0 0.0 0 +chr8 73972769 0 0 0.0 0 +chr8 74039490 0 0 0.0 0 +chr8 74079928 0 0 0.0 0 +chr8 74086733 0 0 0.0 0 +chr8 74153531 0 0 0.0 0 +chr8 74303710 0 0 0.0 0 +chr8 74330179 0 0 0.0 0 +chr8 74414560 0 0 0.0 0 +chr8 74514822 0 1 0.0175 0 +chr8 74577332 0 0 0.0 0 +chr8 74776706 0 0 0.0 0 +chr8 74844956 0 0 0.0 0 +chr8 75011470 0 0 0.0 0 +chr8 75126215 0 0 0.0 0 +chr8 75198606 0 1 0.0156 0 +chr8 75219286 0 0 0.0 0 +chr8 75296977 0 0 0.0 0 +chr8 75771626 0 0 0.0 0 +chr8 75808722 0 0 0.0 0 +chr8 75843922 0 0 0.0 0 +chr8 75847099 0 0 0.0 0 +chr8 75995503 0 0 0.0 0 +chr8 76286424 0 0 0.0 0 +chr8 76292376 0 0 0.0 0 +chr8 76319756 0 0 0.0 0 +chr8 76418329 0 0 0.0 0 +chr8 76442178 0 0 0.0 0 +chr8 76550548 0 0 0.0 0 +chr8 76558046 0 0 0.0 0 +chr8 76665318 0 0 0.0 0 +chr8 76711629 0 0 0.0 0 +chr8 76740536 0 0 0.0 0 +chr8 76837033 0 0 0.0 0 +chr8 77133712 0 0 0.0 0 +chr8 77408490 0 0 0.0 0 +chr8 77411804 0 0 0.0 0 +chr8 77619740 0 0 0.0 0 +chr8 77648667 0 0 0.0 0 +chr8 77728611 0 1 0.0227 0 +chr8 77919130 0 0 0.0 0 +chr8 78411696 0 0 0.0 0 +chr8 78413995 0 0 0.0 0 +chr8 78437783 0 0 0.0 0 +chr8 78444894 0 0 0.0 0 +chr8 78668720 0 0 0.0 0 +chr8 78864242 0 0 0.0 0 +chr8 78883580 0 0 0.0 0 +chr8 78946873 0 0 0.0 0 +chr8 79377216 0 0 0.0 0 +chr8 79392852 0 0 0.0 0 +chr8 79435651 0 0 0.0 0 +chr8 79502489 0 0 0.0 0 +chr8 79559963 0 0 0.0 0 +chr8 79584549 0 0 0.0 0 +chr8 79609313 0 0 0.0 0 +chr8 79670207 0 0 0.0 0 +chr8 79765302 0 0 0.0 0 +chr8 79919385 0 0 0.0 0 +chr8 80126875 0 0 0.0 0 +chr8 80534423 0 0 0.0 0 +chr8 80667028 0 0 0.0 0 +chr8 80675356 0 0 0.0 0 +chr8 80729263 0 0 0.0 0 +chr8 80760083 0 0 0.0 0 +chr8 80838911 0 0 0.0 0 +chr8 80924343 0 0 0.0 0 +chr8 81058225 0 0 0.0 0 +chr8 81194778 0 0 0.0 0 +chr8 81213021 0 0 0.0 0 +chr8 81230176 0 0 0.0 0 +chr8 81459146 0 1 0.0312 0 +chr8 81473016 0 0 0.0 0 +chr8 81631021 0 0 0.0 0 +chr8 81631076 0 0 0.0 0 +chr8 81760073 0 0 0.0 0 +chr8 81849064 0 0 0.0 0 +chr8 81906023 0 0 0.0 0 +chr8 82035018 0 0 0.0 0 +chr8 82091845 0 0 0.0 0 +chr8 82248247 0 0 0.0 0 +chr8 82346144 0 0 0.0 0 +chr8 82655839 0 0 0.0 0 +chr8 82663711 0 0 0.0 0 +chr8 82733466 0 0 0.0 0 +chr8 83037736 0 0 0.0 0 +chr8 83066698 0 0 0.0 0 +chr8 83095542 0 0 0.0 0 +chr8 83097404 0 0 0.0 0 +chr8 83208389 0 0 0.0 0 +chr8 83372993 0 0 0.0 0 +chr8 83602559 0 0 0.0 0 +chr8 83761919 0 0 0.0 0 +chr8 83912721 0 0 0.0 0 +chr8 83943480 0 0 0.0 0 +chr8 83966196 0 0 0.0 0 +chr8 84445211 0 0 0.0 0 +chr8 84476100 0 0 0.0 0 +chr8 84978673 0 0 0.0 0 +chr8 85087135 0 0 0.0 0 +chr8 85403127 0 0 0.0 0 +chr8 85424126 0 0 0.0 0 +chr8 85438605 1 14 0.4516 1 +chr8 85470884 0 0 0.0 0 +chr8 85480705 0 0 0.0 0 +chr8 85535541 0 0 0.0 0 +chr8 85591864 0 0 0.0 0 +chr8 85655835 0 0 0.0 0 +chr8 85662672 0 0 0.0 0 +chr8 85714685 0 0 0.0 0 +chr8 85736139 0 0 0.0 0 +chr8 85745691 0 0 0.0 0 +chr8 85764058 0 0 0.0 0 +chr8 85776252 0 0 0.0 0 +chr8 85791527 0 0 0.0 0 +chr8 85803720 0 0 0.0 0 +chr8 85815911 0 0 0.0 0 +chr8 85828101 0 0 0.0 0 +chr8 86191024 0 0 0.0 0 +chr8 86209189 0 0 0.0 0 +chr8 86274615 0 0 0.0 0 +chr8 86295873 0 0 0.0 0 +chr8 86334967 0 0 0.0 0 +chr8 86451127 0 0 0.0 0 +chr8 86563171 0 0 0.0 0 +chr8 86594183 0 0 0.0 0 +chr8 86603318 0 0 0.0 0 +chr8 86619882 0 0 0.0 0 +chr8 86624052 0 0 0.0 0 +chr8 86726552 0 0 0.0 0 +chr8 86859337 0 0 0.0 0 +chr8 87089486 0 0 0.0 0 +chr8 87385998 0 0 0.0 0 +chr8 87392651 0 0 0.0 0 +chr8 87778683 0 0 0.0 0 +chr8 87860035 0 0 0.0 0 +chr8 87906354 0 0 0.0 0 +chr8 87917896 0 0 0.0 0 +chr8 88070415 0 0 0.0 0 +chr8 88081069 0 0 0.0 0 +chr8 88081341 0 0 0.0 0 +chr8 88164876 0 0 0.0 0 +chr8 88323220 0 0 0.0 0 +chr8 88399741 0 0 0.0 0 +chr8 88450351 0 0 0.0 0 +chr8 88627521 0 0 0.0 0 +chr8 88724752 0 0 0.0 0 +chr8 88859912 0 0 0.0 0 +chr8 89147163 0 0 0.0 0 +chr8 89192403 0 0 0.0 0 +chr8 89219056 0 0 0.0 0 +chr8 89304485 0 0 0.0 0 +chr8 89515914 0 0 0.0 0 +chr8 89673335 0 0 0.0 0 +chr8 89867583 0 0 0.0 0 +chr8 90008716 0 0 0.0 0 +chr8 90109063 0 0 0.0 0 +chr8 90129495 0 0 0.0 0 +chr8 90137784 0 0 0.0 0 +chr8 90189974 0 0 0.0 0 +chr8 90734079 1 20 0.3279 1 +chr8 90900830 0 0 0.0 0 +chr8 91002166 0 0 0.0 0 +chr8 91040283 0 0 0.0 0 +chr8 91041996 0 0 0.0 0 +chr8 91068387 0 0 0.0 0 +chr8 91185107 0 0 0.0 0 +chr8 91206975 0 0 0.0 0 +chr8 91326594 0 0 0.0 0 +chr8 91380192 0 0 0.0 0 +chr8 91454264 0 0 0.0 0 +chr8 91513623 0 0 0.0 0 +chr8 91544870 0 0 0.0 0 +chr8 91665108 0 0 0.0 0 +chr8 91934727 0 0 0.0 0 +chr8 92414049 0 0 0.0 0 +chr8 92516040 0 0 0.0 0 +chr8 92539918 0 0 0.0 0 +chr8 92562135 0 0 0.0 0 +chr8 92752395 0 0 0.0 0 +chr8 92780237 0 0 0.0 0 +chr8 92843838 0 0 0.0 0 +chr8 93047884 0 0 0.0 0 +chr8 93058334 0 0 0.0 0 +chr8 93075440 0 0 0.0 0 +chr8 93323245 0 0 0.0 0 +chr8 93345338 0 0 0.0 0 +chr8 93463036 0 0 0.0 0 +chr8 93467188 0 0 0.0 0 +chr8 93597369 0 0 0.0 0 +chr8 93825802 0 0 0.0 0 +chr8 93855581 0 0 0.0 0 +chr8 93901667 0 0 0.0 0 +chr8 93981737 0 0 0.0 0 +chr8 93997180 0 0 0.0 0 +chr8 94167619 0 0 0.0 0 +chr8 94229277 0 0 0.0 0 +chr8 94568947 0 0 0.0 0 +chr8 94793924 0 0 0.0 0 +chr8 94815023 0 0 0.0 0 +chr8 94953844 0 0 0.0 0 +chr8 94959269 0 0 0.0 0 +chr8 95043833 0 0 0.0 0 +chr8 95105593 0 0 0.0 0 +chr8 95205392 0 0 0.0 0 +chr8 95271494 0 0 0.0 0 +chr8 95351446 0 0 0.0 0 +chr8 95385061 0 0 0.0 0 +chr8 95417518 0 0 0.0 0 +chr8 95421493 0 0 0.0 0 +chr8 95456602 0 0 0.0 0 +chr8 95474297 0 0 0.0 0 +chr8 95493196 0 2 0.0833 0 +chr8 95508613 0 0 0.0 0 +chr8 95733569 0 0 0.0 0 +chr8 95800976 0 0 0.0 0 +chr8 95903035 0 0 0.0 0 +chr8 95970997 0 0 0.0 0 +chr8 96091600 0 1 0.0185 0 +chr8 96096005 0 0 0.0 0 +chr8 96146959 0 0 0.0 0 +chr8 96365111 0 0 0.0 0 +chr8 96380472 0 0 0.0 0 +chr8 96437963 0 0 0.0 0 +chr8 96460736 0 0 0.0 0 +chr8 96466861 0 0 0.0 0 +chr8 96498554 0 0 0.0 0 +chr8 96635650 0 0 0.0 0 +chr8 96642169 0 0 0.0 0 +chr8 96886617 0 0 0.0 0 +chr8 97053567 0 0 0.0 0 +chr8 97111066 0 0 0.0 0 +chr8 97112577 0 0 0.0 0 +chr8 97129998 0 0 0.0 0 +chr8 97155290 0 0 0.0 0 +chr8 97248380 0 0 0.0 0 +chr8 97476033 0 0 0.0 0 +chr8 97531020 0 0 0.0 0 +chr8 97557284 0 0 0.0 0 +chr8 97650049 0 0 0.0 0 +chr8 97821347 0 2 0.0253 0 +chr8 97848549 0 0 0.0 0 +chr8 97895493 0 0 0.0 0 +chr8 97948996 0 0 0.0 0 +chr8 98027432 0 0 0.0 0 +chr8 98029656 0 0 0.0 0 +chr8 98065768 0 0 0.0 0 +chr8 98182865 0 0 0.0 0 +chr8 98384782 0 0 0.0 0 +chr8 98443632 0 0 0.0 0 +chr8 98557608 0 0 0.0 0 +chr8 98562201 0 0 0.0 0 +chr8 98711724 0 0 0.0 0 +chr8 98808073 0 0 0.0 0 +chr8 98917882 0 0 0.0 0 +chr8 98924037 0 0 0.0 0 +chr8 99300174 0 0 0.0 0 +chr8 99606415 0 0 0.0 0 +chr8 99633635 0 0 0.0 0 +chr8 99642406 0 0 0.0 0 +chr8 99711943 0 0 0.0 0 +chr8 99764676 0 0 0.0 0 +chr8 100310438 0 0 0.0 0 +chr8 100326121 0 0 0.0 0 +chr8 100461535 0 0 0.0 0 +chr8 100467117 0 0 0.0 0 +chr8 100482544 0 0 0.0 0 +chr8 100519041 0 0 0.0 0 +chr8 100598071 0 0 0.0 0 +chr8 100607326 0 0 0.0 0 +chr8 100893273 0 0 0.0 0 +chr8 101110946 0 0 0.0 0 +chr8 101156006 0 0 0.0 0 +chr8 101195961 0 0 0.0 0 +chr8 101267057 0 0 0.0 0 +chr8 101272463 0 0 0.0 0 +chr8 101340249 0 0 0.0 0 +chr8 101371558 0 0 0.0 0 +chr8 101461889 0 0 0.0 0 +chr8 101478260 0 0 0.0 0 +chr8 101587154 0 1 0.0156 0 +chr8 101888665 0 0 0.0 0 +chr8 101972647 0 0 0.0 0 +chr8 102059874 0 0 0.0 0 +chr8 102173830 0 0 0.0 0 +chr8 102408815 0 0 0.0 0 +chr8 102550746 0 0 0.0 0 +chr8 102569088 0 0 0.0 0 +chr8 102574541 0 0 0.0 0 +chr8 102738900 0 0 0.0 0 +chr8 102762117 0 0 0.0 0 +chr8 102778262 0 0 0.0 0 +chr8 102817752 0 0 0.0 0 +chr8 102830476 0 0 0.0 0 +chr8 102872859 0 0 0.0 0 +chr8 102956628 0 1 0.0278 0 +chr8 103077582 0 0 0.0 0 +chr8 103140337 0 0 0.0 0 +chr8 103192975 0 0 0.0 0 +chr8 103201476 0 0 0.0 0 +chr8 103241295 0 0 0.0 0 +chr8 103274822 0 1 0.0164 0 +chr8 103667051 0 0 0.0 0 +chr8 103734819 0 0 0.0 0 +chr8 104332802 0 0 0.0 0 +chr8 104365710 0 0 0.0 0 +chr8 104677270 0 0 0.0 0 +chr8 105267388 0 0 0.0 0 +chr8 105429974 0 0 0.0 0 +chr8 105611063 0 0 0.0 0 +chr8 105717960 0 0 0.0 0 +chr8 105897824 0 0 0.0 0 +chr8 105971701 0 0 0.0 0 +chr8 106126971 0 0 0.0 0 +chr8 106180773 0 0 0.0 0 +chr8 106257374 0 0 0.0 0 +chr8 106276284 0 0 0.0 0 +chr8 106350928 0 0 0.0 0 +chr8 106650359 0 0 0.0 0 +chr8 106689458 0 0 0.0 0 +chr8 106706469 0 0 0.0 0 +chr8 106781918 0 0 0.0 0 +chr8 106845533 0 0 0.0 0 +chr8 106969864 0 0 0.0 0 +chr8 106986610 0 0 0.0 0 +chr8 107144718 0 0 0.0 0 +chr8 107317864 0 0 0.0 0 +chr8 107364936 0 0 0.0 0 +chr8 107423316 0 0 0.0 0 +chr8 107490510 0 0 0.0 0 +chr8 107527404 0 0 0.0 0 +chr8 107597041 0 0 0.0 0 +chr8 107661208 0 0 0.0 0 +chr8 107725344 0 0 0.0 0 +chr8 107736460 0 0 0.0 0 +chr8 107756864 0 0 0.0 0 +chr8 107815522 0 0 0.0 0 +chr8 107823127 0 0 0.0 0 +chr8 107877485 0 0 0.0 0 +chr8 108030074 0 0 0.0 0 +chr8 108114295 0 0 0.0 0 +chr8 108122896 0 0 0.0 0 +chr8 108142782 0 0 0.0 0 +chr8 108177712 0 0 0.0 0 +chr8 108200844 0 0 0.0 0 +chr8 108458382 0 0 0.0 0 +chr8 108674716 0 0 0.0 0 +chr8 108773541 0 0 0.0 0 +chr8 108796998 0 0 0.0 0 +chr8 108803384 0 0 0.0 0 +chr8 108931310 0 0 0.0 0 +chr8 109218323 0 0 0.0 0 +chr8 109293434 0 0 0.0 0 +chr8 109647260 0 0 0.0 0 +chr8 109691391 0 0 0.0 0 +chr8 109876724 0 0 0.0 0 +chr8 109976097 0 0 0.0 0 +chr8 110278274 0 0 0.0 0 +chr8 110411892 0 0 0.0 0 +chr8 110420800 0 0 0.0 0 +chr8 110485543 0 0 0.0 0 +chr8 110536196 0 0 0.0 0 +chr8 110691955 0 0 0.0 0 +chr8 110737940 0 0 0.0 0 +chr8 111012190 0 0 0.0 0 +chr8 111115253 0 0 0.0 0 +chr8 111235659 0 0 0.0 0 +chr8 111283414 0 0 0.0 0 +chr8 111493283 0 0 0.0 0 +chr8 111572467 0 0 0.0 0 +chr8 111640562 0 0 0.0 0 +chr8 111770640 0 0 0.0 0 +chr8 111807377 0 0 0.0 0 +chr8 111876617 0 0 0.0 0 +chr8 111904443 0 0 0.0 0 +chr8 111981906 0 0 0.0 0 +chr8 111985870 0 0 0.0 0 +chr8 112169900 0 0 0.0 0 +chr8 112389359 0 0 0.0 0 +chr8 112558133 0 0 0.0 0 +chr8 112580535 1 52 0.8387 1 +chr8 112792494 0 1 0.0286 0 +chr8 113042333 0 0 0.0 0 +chr8 113044777 0 0 0.0 0 +chr8 113479029 0 0 0.0 0 +chr8 113499038 0 0 0.0 0 +chr8 113792605 0 0 0.0 0 +chr8 114149384 0 0 0.0 0 +chr8 114354861 0 0 0.0 0 +chr8 114373291 0 0 0.0 0 +chr8 114429337 0 0 0.0 0 +chr8 114681765 0 0 0.0 0 +chr8 114719683 0 0 0.0 0 +chr8 114777055 0 0 0.0 0 +chr8 115017677 0 0 0.0 0 +chr8 115024310 0 0 0.0 0 +chr8 115274917 0 0 0.0 0 +chr8 115277435 0 0 0.0 0 +chr8 115751360 0 0 0.0 0 +chr8 115786764 0 0 0.0 0 +chr8 115901395 0 0 0.0 0 +chr8 115949371 0 0 0.0 0 +chr8 116046050 0 0 0.0 0 +chr8 116100304 0 0 0.0 0 +chr8 116205824 0 0 0.0 0 +chr8 116235581 0 0 0.0 0 +chr8 116272704 0 0 0.0 0 +chr8 116442447 0 0 0.0 0 +chr8 116495017 0 0 0.0 0 +chr8 116621951 0 0 0.0 0 +chr8 116880445 0 0 0.0 0 +chr8 116919736 0 0 0.0 0 +chr8 116968630 1 18 0.3273 1 +chr8 117003623 0 0 0.0 0 +chr8 117071592 0 0 0.0 0 +chr8 117078816 0 0 0.0 0 +chr8 117088740 0 0 0.0 0 +chr8 117127084 0 0 0.0 0 +chr8 117179460 0 0 0.0 0 +chr8 117343956 0 0 0.0 0 +chr8 117514482 0 0 0.0 0 +chr8 117549053 0 0 0.0 0 +chr8 117585883 0 0 0.0 0 +chr8 117705408 0 0 0.0 0 +chr8 117794901 0 0 0.0 0 +chr8 117901066 0 0 0.0 0 +chr8 117947759 0 0 0.0 0 +chr8 117988728 0 0 0.0 0 +chr8 118009948 0 0 0.0 0 +chr8 118039037 0 0 0.0 0 +chr8 118100245 0 0 0.0 0 +chr8 118207240 0 0 0.0 0 +chr8 118350251 0 0 0.0 0 +chr8 118447151 0 0 0.0 0 +chr8 118590399 0 0 0.0 0 +chr8 118653265 0 0 0.0 0 +chr8 118948394 0 0 0.0 0 +chr8 118993810 0 0 0.0 0 +chr8 119031763 0 0 0.0 0 +chr8 119055274 0 0 0.0 0 +chr8 119278765 0 0 0.0 0 +chr8 119619318 0 0 0.0 0 +chr8 119660737 0 0 0.0 0 +chr8 119801407 0 0 0.0 0 +chr8 119960275 0 0 0.0 0 +chr8 120010589 0 0 0.0 0 +chr8 120167032 0 0 0.0 0 +chr8 120395426 0 0 0.0 0 +chr8 120407404 0 0 0.0 0 +chr8 120458988 0 0 0.0 0 +chr8 120485898 0 0 0.0 0 +chr8 120522367 1 44 0.4632 1 +chr8 120854205 0 0 0.0 0 +chr8 120854985 0 0 0.0 0 +chr8 121014918 0 0 0.0 0 +chr8 121033186 0 0 0.0 0 +chr8 121241358 0 2 0.0345 0 +chr8 121617757 0 0 0.0 0 +chr8 121864092 0 0 0.0 0 +chr8 121948455 0 0 0.0 0 +chr8 121979085 0 1 0.0182 0 +chr8 122096250 0 0 0.0 0 +chr8 122156190 0 0 0.0 0 +chr8 122496171 0 0 0.0 0 +chr8 122603497 0 0 0.0 0 +chr8 122642292 0 1 0.0263 0 +chr8 122800327 0 0 0.0 0 +chr8 122985082 0 0 0.0 0 +chr8 123014775 0 0 0.0 0 +chr8 123140503 0 0 0.0 0 +chr8 123460492 0 0 0.0 0 +chr8 123472569 0 0 0.0 0 +chr8 123599604 0 0 0.0 0 +chr8 123873676 0 0 0.0 0 +chr8 123894155 0 0 0.0 0 +chr8 124082450 0 0 0.0 0 +chr8 124142908 0 0 0.0 0 +chr8 124151486 0 0 0.0 0 +chr8 124191228 0 0 0.0 0 +chr8 124195997 0 0 0.0 0 +chr8 124205191 0 0 0.0 0 +chr8 124281720 0 0 0.0 0 +chr8 124374155 0 0 0.0 0 +chr8 124533465 0 0 0.0 0 +chr8 124570625 0 0 0.0 0 +chr8 124573141 0 0 0.0 0 +chr8 124694435 0 0 0.0 0 +chr8 124774253 0 0 0.0 0 +chr8 124922888 0 0 0.0 0 +chr8 124953385 0 0 0.0 0 +chr8 124960014 0 0 0.0 0 +chr8 125166702 0 0 0.0 0 +chr8 125201485 0 0 0.0 0 +chr8 125238117 0 0 0.0 0 +chr8 125258870 0 1 0.0294 0 +chr8 125425393 0 0 0.0 0 +chr8 125468578 0 0 0.0 0 +chr8 125470602 0 0 0.0 0 +chr8 125472191 0 0 0.0 0 +chr8 125914927 0 1 0.0179 0 +chr8 126012269 0 0 0.0 0 +chr8 126160263 0 0 0.0 0 +chr8 126299768 0 0 0.0 0 +chr8 126367887 0 0 0.0 0 +chr8 126394078 0 0 0.0 0 +chr8 126437405 0 0 0.0 0 +chr8 126473014 0 0 0.0 0 +chr8 126481706 0 0 0.0 0 +chr8 126493298 0 0 0.0 0 +chr8 126608931 1 28 0.3457 1 +chr8 126760298 0 0 0.0 0 +chr8 126889411 0 0 0.0 0 +chr8 127061716 0 0 0.0 0 +chr8 127273519 0 0 0.0 0 +chr8 127424861 0 0 0.0 0 +chr8 127556352 0 0 0.0 0 +chr8 127587794 0 0 0.0 0 +chr8 127597143 0 0 0.0 0 +chr8 127729357 0 0 0.0 0 +chr8 127755422 0 0 0.0 0 +chr8 127805671 0 0 0.0 0 +chr8 127843536 0 0 0.0 0 +chr8 127843765 1 34 0.5075 1 +chr8 127864222 0 0 0.0 0 +chr8 127876938 0 0 0.0 0 +chr8 127968881 0 0 0.0 0 +chr8 128004020 0 0 0.0 0 +chr8 128142734 0 0 0.0 0 +chr8 128250685 0 0 0.0 0 +chr8 128290110 0 0 0.0 0 +chr8 128325231 0 0 0.0 0 +chr8 128371436 0 0 0.0 0 +chr8 128372126 0 0 0.0 0 +chr8 128428837 0 0 0.0 0 +chr8 128631342 0 0 0.0 0 +chr8 128695731 0 0 0.0 0 +chr8 128773026 0 0 0.0 0 +chr8 128900144 0 0 0.0 0 +chr8 128904333 0 0 0.0 0 +chr8 129209817 1 42 0.4828 1 +chr8 129238982 0 0 0.0 0 +chr8 129418096 0 0 0.0 0 +chr8 129431489 0 0 0.0 0 +chr8 129445347 0 0 0.0 0 +chr8 129487727 0 0 0.0 0 +chr8 129608988 0 0 0.0 0 +chr8 129868630 0 0 0.0 0 +chr8 130127642 0 0 0.0 0 +chr8 130233411 0 0 0.0 0 +chr8 130242662 0 0 0.0 0 +chr8 130256256 0 0 0.0 0 +chr8 130336569 0 0 0.0 0 +chr8 130469820 0 0 0.0 0 +chr8 130529344 0 0 0.0 0 +chr8 130545493 0 0 0.0 0 +chr8 130612421 0 0 0.0 0 +chr8 130747409 0 0 0.0 0 +chr8 130795322 0 0 0.0 0 +chr8 130838930 0 0 0.0 0 +chr8 131011829 0 0 0.0 0 +chr8 131100754 0 0 0.0 0 +chr8 131139120 0 0 0.0 0 +chr8 131483009 0 0 0.0 0 +chr8 131499484 0 0 0.0 0 +chr8 131607834 0 0 0.0 0 +chr8 131756759 0 0 0.0 0 +chr8 131782150 0 0 0.0 0 +chr8 131843926 0 0 0.0 0 +chr8 131932331 0 0 0.0 0 +chr8 131936143 0 0 0.0 0 +chr8 131977401 0 0 0.0 0 +chr8 132073800 0 0 0.0 0 +chr8 132141434 0 0 0.0 0 +chr8 132153100 0 0 0.0 0 +chr8 132172385 2 10 0.2703 1 +chr8 132350578 0 0 0.0 0 +chr8 132356957 0 0 0.0 0 +chr8 132400917 0 0 0.0 0 +chr8 132417345 0 0 0.0 0 +chr8 132419612 0 0 0.0 0 +chr8 132556455 0 0 0.0 0 +chr8 132687826 0 0 0.0 0 +chr8 132735011 0 0 0.0 0 +chr8 132777602 0 0 0.0 0 +chr8 132785866 0 0 0.0 0 +chr8 132799663 0 0 0.0 0 +chr8 132877931 0 0 0.0 0 +chr8 132912705 0 0 0.0 0 +chr8 132923329 0 0 0.0 0 +chr8 132970925 0 0 0.0 0 +chr8 132984194 0 0 0.0 0 +chr8 133016799 0 0 0.0 0 +chr8 133052436 0 0 0.0 0 +chr8 133104376 0 0 0.0 0 +chr8 133212256 0 0 0.0 0 +chr8 133252917 0 0 0.0 0 +chr8 133269427 0 0 0.0 0 +chr8 133271483 0 0 0.0 0 +chr8 133399837 0 0 0.0 0 +chr8 133422705 0 0 0.0 0 +chr8 133480565 0 0 0.0 0 +chr8 133500282 0 0 0.0 0 +chr8 133520321 0 0 0.0 0 +chr8 133520606 0 0 0.0 0 +chr8 133524864 0 0 0.0 0 +chr8 133573382 0 0 0.0 0 +chr8 133654801 0 0 0.0 0 +chr8 133737536 0 0 0.0 0 +chr8 133831965 0 0 0.0 0 +chr8 133847300 0 0 0.0 0 +chr8 133853610 0 0 0.0 0 +chr8 133967530 0 0 0.0 0 +chr8 133969884 0 2 0.0571 0 +chr8 134047901 0 0 0.0 0 +chr8 134174253 0 0 0.0 0 +chr8 134240155 0 0 0.0 0 +chr8 134434037 0 0 0.0 0 +chr8 134453671 0 0 0.0 0 +chr8 134465941 0 0 0.0 0 +chr8 134605730 0 0 0.0 0 +chr8 134620230 0 0 0.0 0 +chr8 134623955 0 0 0.0 0 +chr8 134625910 0 0 0.0 0 +chr8 134823616 0 0 0.0 0 +chr8 134851900 0 0 0.0 0 +chr8 134978912 0 0 0.0 0 +chr8 135046136 0 0 0.0 0 +chr8 135052966 0 0 0.0 0 +chr8 135126230 0 0 0.0 0 +chr8 135133687 0 0 0.0 0 +chr8 135140788 0 0 0.0 0 +chr8 135146878 0 0 0.0 0 +chr8 135227356 0 0 0.0 0 +chr8 135253613 0 0 0.0 0 +chr8 135472963 0 0 0.0 0 +chr8 135496870 0 0 0.0 0 +chr8 135748261 0 0 0.0 0 +chr8 135748807 0 0 0.0 0 +chr8 135764680 0 0 0.0 0 +chr8 135825617 0 0 0.0 0 +chr8 136012543 0 0 0.0 0 +chr8 136016063 0 1 0.0127 0 +chr8 136350229 0 0 0.0 0 +chr8 136554625 0 0 0.0 0 +chr8 136583807 0 0 0.0 0 +chr8 136598784 0 0 0.0 0 +chr8 136606473 0 0 0.0 0 +chr8 136628378 0 0 0.0 0 +chr8 136648151 0 0 0.0 0 +chr8 136954146 0 0 0.0 0 +chr8 136996191 0 0 0.0 0 +chr8 137043957 0 0 0.0 0 +chr8 137143175 0 0 0.0 0 +chr8 137186480 0 0 0.0 0 +chr8 137288226 0 0 0.0 0 +chr8 137373459 0 0 0.0 0 +chr8 137457261 0 0 0.0 0 +chr8 137565858 0 0 0.0 0 +chr8 137643637 0 0 0.0 0 +chr8 137907894 0 0 0.0 0 +chr8 137922926 0 0 0.0 0 +chr8 138248044 0 0 0.0 0 +chr8 138325310 0 0 0.0 0 +chr8 138364319 0 0 0.0 0 +chr8 138648674 0 0 0.0 0 +chr8 138663291 0 0 0.0 0 +chr8 138741048 0 0 0.0 0 +chr8 138918034 0 0 0.0 0 +chr8 138935486 0 0 0.0 0 +chr8 138948530 0 0 0.0 0 +chr8 139020967 0 0 0.0 0 +chr8 139028159 0 0 0.0 0 +chr8 139069636 0 0 0.0 0 +chr8 139117589 0 0 0.0 0 +chr8 139190915 0 0 0.0 0 +chr8 139243441 0 0 0.0 0 +chr8 139277086 0 0 0.0 0 +chr8 139353937 0 0 0.0 0 +chr8 139396012 0 0 0.0 0 +chr8 139627957 0 0 0.0 0 +chr8 139655868 0 0 0.0 0 +chr8 139735890 0 0 0.0 0 +chr8 139753460 0 0 0.0 0 +chr8 139774701 0 0 0.0 0 +chr8 139776160 0 0 0.0 0 +chr8 139846883 0 0 0.0 0 +chr8 139864948 0 0 0.0 0 +chr8 139871498 0 0 0.0 0 +chr8 139909241 0 0 0.0 0 +chr8 140021287 0 0 0.0 0 +chr8 140042751 0 0 0.0 0 +chr8 140112474 0 0 0.0 0 +chr8 140128417 0 0 0.0 0 +chr8 140197923 0 0 0.0 0 +chr8 140245594 0 0 0.0 0 +chr8 140265009 0 0 0.0 0 +chr8 140344967 0 0 0.0 0 +chr8 140522625 0 0 0.0 0 +chr8 140612957 0 0 0.0 0 +chr8 140616803 0 0 0.0 0 +chr8 140732869 0 0 0.0 0 +chr8 140786715 0 0 0.0 0 +chr8 140871804 0 0 0.0 0 +chr8 140926109 0 0 0.0 0 +chr8 141000129 0 0 0.0 0 +chr8 141026670 0 0 0.0 0 +chr8 141037550 0 0 0.0 0 +chr8 141056879 0 0 0.0 0 +chr8 141224150 0 0 0.0 0 +chr8 141255473 0 0 0.0 0 +chr8 141293540 0 0 0.0 0 +chr8 141308898 0 0 0.0 0 +chr8 141363679 0 0 0.0 0 +chr8 141472135 1 28 0.3836 1 +chr8 141567684 0 0 0.0 0 +chr8 141570659 1 66 0.8049 1 +chr8 141591433 0 0 0.0 0 +chr8 141666958 0 0 0.0 0 +chr8 141709136 0 0 0.0 0 +chr8 141752952 0 0 0.0 0 +chr8 141950556 0 0 0.0 0 +chr8 142078506 0 0 0.0 0 +chr8 142087930 0 0 0.0 0 +chr8 142099618 0 0 0.0 0 +chr8 142106358 0 0 0.0 0 +chr8 142188379 0 0 0.0 0 +chr8 142199117 0 0 0.0 0 +chr8 142206945 0 0 0.0 0 +chr8 142236822 0 0 0.0 0 +chr8 142255229 0 0 0.0 0 +chr8 142328668 0 0 0.0 0 +chr8 142339365 0 0 0.0 0 +chr8 142420310 0 0 0.0 0 +chr8 142424709 0 1 0.0164 0 +chr8 142447944 0 0 0.0 0 +chr8 142465981 0 0 0.0 0 +chr8 142613430 0 0 0.0 0 +chr8 142659036 0 0 0.0 0 +chr8 142664773 0 0 0.0 0 +chr8 142682866 0 0 0.0 0 +chr8 142737710 0 0 0.0 0 +chr8 142769282 0 0 0.0 0 +chr8 142813953 0 0 0.0 0 +chr8 142902303 0 0 0.0 0 +chr8 142918888 0 0 0.0 0 +chr8 143019258 0 0 0.0 0 +chr8 143122805 0 0 0.0 0 +chr8 143266193 0 0 0.0 0 +chr8 143296456 0 0 0.0 0 +chr8 143297719 0 0 0.0 0 +chr8 143375031 0 0 0.0 0 +chr8 143384796 0 0 0.0 0 +chr8 143440794 0 0 0.0 0 +chr8 143472437 0 0 0.0 0 +chr8 143483368 0 0 0.0 0 +chr8 143527270 0 0 0.0 0 +chr8 143615612 0 0 0.0 0 +chr8 143676638 0 0 0.0 0 +chr8 143726340 0 0 0.0 0 +chr8 143739974 0 0 0.0 0 +chr8 143792968 0 0 0.0 0 +chr8 143919926 0 0 0.0 0 +chr8 143921102 0 0 0.0 0 +chr8 144068617 0 0 0.0 0 +chr8 144097878 0 0 0.0 0 +chr8 144167859 0 0 0.0 0 +chr8 144239968 0 0 0.0 0 +chr8 144243242 0 0 0.0 0 +chr8 144259970 0 0 0.0 0 +chr8 144263368 0 0 0.0 0 +chr8 144264975 0 0 0.0 0 +chr8 144340683 0 0 0.0 0 +chr8 144408054 0 0 0.0 0 +chr8 144441866 0 0 0.0 0 +chr8 144522241 1 66 0.88 1 +chr8 144826908 0 0 0.0 0 +chr8 144857721 0 0 0.0 0 +chr8_KI270810v1_alt 76620 0 0 0.0 0 +chr8_KI270810v1_alt 141009 0 0 0.0 0 +chr8_KI270810v1_alt 221688 0 0 0.0 0 +chr8_KI270810v1_alt 348818 0 0 0.0 0 +chr8_KI270811v1_alt 262683 0 0 0.0 0 +chr8_KI270812v1_alt 34770 0 0 0.0 0 +chr8_KI270812v1_alt 143130 0 0 0.0 0 +chr8_KI270812v1_alt 179086 0 0 0.0 0 +chr8_KI270812v1_alt 230875 0 0 0.0 0 +chr8_KI270813v1_alt 156989 0 0 0.0 0 +chr8_KI270813v1_alt 169281 0 0 0.0 0 +chr8_KI270814v1_alt 113510 0 0 0.0 0 +chr8_KI270814v1_alt 114309 0 0 0.0 0 +chr8_KI270816v1_alt 17309 0 0 0.0 0 +chr8_KI270816v1_alt 105651 0 0 0.0 0 +chr8_KI270816v1_alt 153685 0 0 0.0 0 +chr8_KI270816v1_alt 203387 0 0 0.0 0 +chr8_KI270816v1_alt 270015 0 0 0.0 0 +chr8_KI270817v1_alt 9546 0 0 0.0 0 +chr8_KI270818v1_alt 15311 0 0 0.0 0 +chr8_KI270821v1_alt 41503 0 0 0.0 0 +chr8_KI270821v1_alt 93641 0 0 0.0 0 +chr8_KI270821v1_alt 387580 0 0 0.0 0 +chr8_KI270821v1_alt 674063 0 0 0.0 0 +chr8_KI270821v1_alt 743188 0 0 0.0 0 +chr8_KI270822v1_alt 263172 0 0 0.0 0 +chr8_KI270822v1_alt 401537 0 0 0.0 0 +chr8_KI270822v1_alt 621587 0 0 0.0 0 +chr8_KI270900v1_alt 168122 0 0 0.0 0 +chr8_KI270900v1_alt 204784 0 0 0.0 0 +chr8_KI270900v1_alt 309411 0 0 0.0 0 +chr8_KI270901v1_alt 62978 0 0 0.0 0 +chr8_KI270926v1_alt 8265 0 0 0.0 0 +chr8_KI270926v1_alt 112806 0 0 0.0 0 +chr9 67738 0 0 0.0 0 +chr9 303628 0 0 0.0 0 +chr9 327290 0 0 0.0 0 +chr9 348815 0 0 0.0 0 +chr9 561900 0 0 0.0 0 +chr9 624885 0 0 0.0 0 +chr9 948038 0 0 0.0 0 +chr9 972683 0 0 0.0 0 +chr9 1016795 0 0 0.0 0 +chr9 1042204 0 0 0.0 0 +chr9 1070609 0 0 0.0 0 +chr9 1208292 0 0 0.0 0 +chr9 1250700 0 0 0.0 0 +chr9 1305277 0 0 0.0 0 +chr9 1393669 0 0 0.0 0 +chr9 1396303 0 0 0.0 0 +chr9 1476335 0 0 0.0 0 +chr9 1542169 0 0 0.0 0 +chr9 1609980 0 0 0.0 0 +chr9 1675194 0 0 0.0 0 +chr9 1766554 0 0 0.0 0 +chr9 1936348 0 0 0.0 0 +chr9 1950114 0 0 0.0 0 +chr9 1980887 0 0 0.0 0 +chr9 2307973 0 1 0.0143 0 +chr9 2334429 0 0 0.0 0 +chr9 2382823 1 3 0.04 1 +chr9 2498922 0 0 0.0 0 +chr9 2527205 0 0 0.0 0 +chr9 2611162 0 0 0.0 0 +chr9 2723984 1 9 0.1875 1 +chr9 2743479 0 0 0.0 0 +chr9 2786758 0 0 0.0 0 +chr9 2875346 0 0 0.0 0 +chr9 3006470 0 0 0.0 0 +chr9 3033376 0 0 0.0 0 +chr9 3107132 0 0 0.0 0 +chr9 3113818 0 0 0.0 0 +chr9 3271005 0 0 0.0 0 +chr9 3330428 0 0 0.0 0 +chr9 3353815 0 0 0.0 0 +chr9 3526287 0 0 0.0 0 +chr9 3574495 0 0 0.0 0 +chr9 3659138 0 0 0.0 0 +chr9 3699170 0 0 0.0 0 +chr9 3750462 0 0 0.0 0 +chr9 3756110 1 38 0.475 1 +chr9 3792988 0 0 0.0 0 +chr9 3802845 0 0 0.0 0 +chr9 3904918 0 0 0.0 0 +chr9 4060465 0 0 0.0 0 +chr9 4080843 0 0 0.0 0 +chr9 4095311 0 0 0.0 0 +chr9 4160288 0 0 0.0 0 +chr9 4195101 0 0 0.0 0 +chr9 4196790 0 0 0.0 0 +chr9 4209150 0 0 0.0 0 +chr9 4235884 0 0 0.0 0 +chr9 4434150 0 0 0.0 0 +chr9 4482642 0 0 0.0 0 +chr9 4528122 0 0 0.0 0 +chr9 4598904 0 0 0.0 0 +chr9 4621240 0 0 0.0 0 +chr9 4642245 0 0 0.0 0 +chr9 4851974 0 0 0.0 0 +chr9 4901394 0 0 0.0 0 +chr9 4919881 0 0 0.0 0 +chr9 4938894 0 0 0.0 0 +chr9 5020261 0 0 0.0 0 +chr9 5083461 0 0 0.0 0 +chr9 5173674 0 0 0.0 0 +chr9 5178461 0 0 0.0 0 +chr9 5272796 0 0 0.0 0 +chr9 5439667 0 0 0.0 0 +chr9 5467892 0 0 0.0 0 +chr9 5554496 0 0 0.0 0 +chr9 5721477 0 1 0.025 0 +chr9 5878635 0 0 0.0 0 +chr9 6022180 0 0 0.0 0 +chr9 6145203 0 0 0.0 0 +chr9 6242993 0 0 0.0 0 +chr9 6346796 0 0 0.0 0 +chr9 6580058 0 0 0.0 0 +chr9 6614363 0 0 0.0 0 +chr9 6673919 0 0 0.0 0 +chr9 6726581 0 0 0.0 0 +chr9 6887034 0 0 0.0 0 +chr9 6989004 0 0 0.0 0 +chr9 6993984 0 0 0.0 0 +chr9 7028512 0 0 0.0 0 +chr9 7129681 0 0 0.0 0 +chr9 7240127 0 0 0.0 0 +chr9 7320188 0 0 0.0 0 +chr9 7350591 0 0 0.0 0 +chr9 7416493 0 0 0.0 0 +chr9 7513993 0 0 0.0 0 +chr9 7518424 0 0 0.0 0 +chr9 7525598 0 0 0.0 0 +chr9 7741486 0 0 0.0 0 +chr9 7799606 0 0 0.0 0 +chr9 7828890 0 0 0.0 0 +chr9 7898643 0 0 0.0 0 +chr9 8032953 0 0 0.0 0 +chr9 8115803 0 0 0.0 0 +chr9 8134107 0 0 0.0 0 +chr9 8290520 0 0 0.0 0 +chr9 8329326 0 0 0.0 0 +chr9 8350139 0 0 0.0 0 +chr9 8522266 0 0 0.0 0 +chr9 8528753 0 0 0.0 0 +chr9 8538599 0 0 0.0 0 +chr9 8636754 0 0 0.0 0 +chr9 8722748 0 0 0.0 0 +chr9 8738526 0 0 0.0 0 +chr9 8959445 0 0 0.0 0 +chr9 9004230 0 0 0.0 0 +chr9 9245391 0 0 0.0 0 +chr9 9356336 0 0 0.0 0 +chr9 9406463 0 0 0.0 0 +chr9 9573970 0 0 0.0 0 +chr9 9629688 0 0 0.0 0 +chr9 9640521 0 0 0.0 0 +chr9 9651103 0 0 0.0 0 +chr9 9837055 0 0 0.0 0 +chr9 9874194 0 0 0.0 0 +chr9 9888704 0 0 0.0 0 +chr9 10031374 0 0 0.0 0 +chr9 10281021 0 0 0.0 0 +chr9 10633885 0 0 0.0 0 +chr9 10949233 0 0 0.0 0 +chr9 10954628 0 0 0.0 0 +chr9 10961955 0 1 0.0233 0 +chr9 10967967 0 0 0.0 0 +chr9 11066811 0 0 0.0 0 +chr9 11166624 0 0 0.0 0 +chr9 11797642 0 0 0.0 0 +chr9 11919314 0 0 0.0 0 +chr9 11993746 0 0 0.0 0 +chr9 12396654 0 0 0.0 0 +chr9 12499664 0 0 0.0 0 +chr9 12617025 0 0 0.0 0 +chr9 12643963 0 0 0.0 0 +chr9 12681716 0 0 0.0 0 +chr9 12773846 0 0 0.0 0 +chr9 12872771 0 0 0.0 0 +chr9 12919204 0 0 0.0 0 +chr9 12920410 0 0 0.0 0 +chr9 13035438 0 0 0.0 0 +chr9 13177625 0 0 0.0 0 +chr9 13309236 0 0 0.0 0 +chr9 13321640 0 0 0.0 0 +chr9 13411870 0 0 0.0 0 +chr9 13426471 0 0 0.0 0 +chr9 13453022 0 0 0.0 0 +chr9 13476439 0 1 0.037 0 +chr9 13484029 0 0 0.0 0 +chr9 13518491 0 0 0.0 0 +chr9 13561457 0 0 0.0 0 +chr9 13598854 0 0 0.0 0 +chr9 13727531 0 0 0.0 0 +chr9 13738056 0 0 0.0 0 +chr9 13792490 0 0 0.0 0 +chr9 13811742 0 0 0.0 0 +chr9 14004361 0 0 0.0 0 +chr9 14150402 0 0 0.0 0 +chr9 14153116 0 0 0.0 0 +chr9 14204657 0 0 0.0 0 +chr9 14252299 0 0 0.0 0 +chr9 14266773 0 0 0.0 0 +chr9 14270664 0 0 0.0 0 +chr9 14313149 0 0 0.0 0 +chr9 14376342 0 0 0.0 0 +chr9 14485557 0 0 0.0 0 +chr9 14497815 0 0 0.0 0 +chr9 14522917 0 0 0.0 0 +chr9 14547140 0 0 0.0 0 +chr9 14719760 0 0 0.0 0 +chr9 14950023 0 0 0.0 0 +chr9 14993303 0 0 0.0 0 +chr9 14996475 0 0 0.0 0 +chr9 14999451 0 0 0.0 0 +chr9 15015138 0 0 0.0 0 +chr9 15055123 0 0 0.0 0 +chr9 15119680 0 0 0.0 0 +chr9 15186308 0 0 0.0 0 +chr9 15246529 0 0 0.0 0 +chr9 15423973 0 0 0.0 0 +chr9 15501769 0 0 0.0 0 +chr9 15519257 0 0 0.0 0 +chr9 15639933 0 0 0.0 0 +chr9 15689951 0 0 0.0 0 +chr9 15818075 0 0 0.0 0 +chr9 15846266 0 0 0.0 0 +chr9 15888037 0 1 0.0217 0 +chr9 15999565 0 0 0.0 0 +chr9 16025005 0 0 0.0 0 +chr9 16170856 0 0 0.0 0 +chr9 16183010 0 0 0.0 0 +chr9 16231865 0 0 0.0 0 +chr9 16321879 0 0 0.0 0 +chr9 16331098 0 0 0.0 0 +chr9 16474543 0 0 0.0 0 +chr9 16509153 0 0 0.0 0 +chr9 16523567 0 0 0.0 0 +chr9 16554637 0 0 0.0 0 +chr9 16581135 0 0 0.0 0 +chr9 16689403 0 0 0.0 0 +chr9 16940788 0 0 0.0 0 +chr9 17042977 0 0 0.0 0 +chr9 17422079 0 0 0.0 0 +chr9 17559655 0 0 0.0 0 +chr9 17974541 0 0 0.0 0 +chr9 17995989 0 0 0.0 0 +chr9 18068161 0 0 0.0 0 +chr9 18119009 0 0 0.0 0 +chr9 18302395 0 0 0.0 0 +chr9 18420351 0 0 0.0 0 +chr9 18651312 0 0 0.0 0 +chr9 18656221 0 0 0.0 0 +chr9 18861330 0 0 0.0 0 +chr9 18906429 0 0 0.0 0 +chr9 18967057 0 0 0.0 0 +chr9 18967615 0 0 0.0 0 +chr9 19005529 0 0 0.0 0 +chr9 19136314 0 0 0.0 0 +chr9 19229164 0 0 0.0 0 +chr9 19323729 0 0 0.0 0 +chr9 19489650 0 0 0.0 0 +chr9 19533358 0 0 0.0 0 +chr9 19572708 0 0 0.0 0 +chr9 19612013 0 0 0.0 0 +chr9 19627156 0 0 0.0 0 +chr9 19680410 0 0 0.0 0 +chr9 19873762 0 0 0.0 0 +chr9 19912119 0 0 0.0 0 +chr9 19941635 0 0 0.0 0 +chr9 19942437 0 0 0.0 0 +chr9 20226832 0 0 0.0 0 +chr9 20405868 0 0 0.0 0 +chr9 20800422 0 0 0.0 0 +chr9 20803772 0 0 0.0 0 +chr9 20812706 0 0 0.0 0 +chr9 20827603 0 0 0.0 0 +chr9 20922758 0 0 0.0 0 +chr9 21060304 0 0 0.0 0 +chr9 21101412 0 0 0.0 0 +chr9 21110417 0 0 0.0 0 +chr9 21147604 0 0 0.0 0 +chr9 21210246 0 0 0.0 0 +chr9 21239935 0 0 0.0 0 +chr9 21260531 0 0 0.0 0 +chr9 21290776 0 0 0.0 0 +chr9 21348552 0 0 0.0 0 +chr9 21635199 0 0 0.0 0 +chr9 21663886 0 0 0.0 0 +chr9 21926889 0 0 0.0 0 +chr9 22061236 0 0 0.0 0 +chr9 22066545 0 0 0.0 0 +chr9 22066752 0 0 0.0 0 +chr9 22138687 0 0 0.0 0 +chr9 22162481 0 0 0.0 0 +chr9 22209207 0 0 0.0 0 +chr9 22257864 0 0 0.0 0 +chr9 22438093 0 0 0.0 0 +chr9 22490685 0 0 0.0 0 +chr9 22756280 0 0 0.0 0 +chr9 22838113 0 0 0.0 0 +chr9 22867862 0 0 0.0 0 +chr9 22891787 0 0 0.0 0 +chr9 22907547 0 0 0.0 0 +chr9 23102936 0 0 0.0 0 +chr9 23105961 0 0 0.0 0 +chr9 23123533 0 0 0.0 0 +chr9 23132001 0 0 0.0 0 +chr9 23215488 0 0 0.0 0 +chr9 23483299 0 0 0.0 0 +chr9 23498538 0 0 0.0 0 +chr9 23535171 0 0 0.0 0 +chr9 23750461 0 0 0.0 0 +chr9 23922349 0 0 0.0 0 +chr9 23992546 0 0 0.0 0 +chr9 24051011 0 0 0.0 0 +chr9 24103761 0 0 0.0 0 +chr9 24153768 0 0 0.0 0 +chr9 24358150 0 0 0.0 0 +chr9 24362107 0 0 0.0 0 +chr9 24544503 0 1 0.0135 0 +chr9 24799544 1 20 0.3922 1 +chr9 24912981 0 0 0.0 0 +chr9 25004702 0 0 0.0 0 +chr9 25005745 0 0 0.0 0 +chr9 25052093 0 0 0.0 0 +chr9 25061180 0 0 0.0 0 +chr9 25305904 0 0 0.0 0 +chr9 25320642 0 0 0.0 0 +chr9 25327032 0 0 0.0 0 +chr9 25680644 0 0 0.0 0 +chr9 25717554 0 0 0.0 0 +chr9 25871206 0 0 0.0 0 +chr9 25889785 0 0 0.0 0 +chr9 25953785 0 0 0.0 0 +chr9 25974955 0 0 0.0 0 +chr9 26083814 0 0 0.0 0 +chr9 26218184 0 0 0.0 0 +chr9 26221561 0 0 0.0 0 +chr9 26292172 0 0 0.0 0 +chr9 26603955 0 0 0.0 0 +chr9 26714175 0 0 0.0 0 +chr9 26790528 0 0 0.0 0 +chr9 26846948 0 0 0.0 0 +chr9 26876625 0 0 0.0 0 +chr9 26956529 0 0 0.0 0 +chr9 27221058 0 0 0.0 0 +chr9 27286102 0 0 0.0 0 +chr9 27528390 0 0 0.0 0 +chr9 27632237 0 0 0.0 0 +chr9 27963945 0 0 0.0 0 +chr9 27989653 0 0 0.0 0 +chr9 28015529 0 0 0.0 0 +chr9 28147705 0 1 0.0149 0 +chr9 28192001 0 0 0.0 0 +chr9 28259902 0 0 0.0 0 +chr9 28339532 0 0 0.0 0 +chr9 28424071 0 0 0.0 0 +chr9 28497941 0 0 0.0 0 +chr9 28571883 0 0 0.0 0 +chr9 28982357 0 0 0.0 0 +chr9 28984972 0 0 0.0 0 +chr9 28990738 0 0 0.0 0 +chr9 29088490 0 0 0.0 0 +chr9 29108583 0 0 0.0 0 +chr9 29171127 0 0 0.0 0 +chr9 29303457 0 0 0.0 0 +chr9 29330157 0 0 0.0 0 +chr9 29472495 0 0 0.0 0 +chr9 29485240 0 0 0.0 0 +chr9 29628080 0 0 0.0 0 +chr9 29726270 0 0 0.0 0 +chr9 29970475 0 0 0.0 0 +chr9 30189370 0 1 0.0278 0 +chr9 30199835 0 0 0.0 0 +chr9 30378113 0 0 0.0 0 +chr9 30408333 0 0 0.0 0 +chr9 30415230 0 0 0.0 0 +chr9 30471434 0 0 0.0 0 +chr9 30778650 0 0 0.0 0 +chr9 30854407 0 0 0.0 0 +chr9 30976280 0 0 0.0 0 +chr9 31250840 0 1 0.0312 0 +chr9 31335510 0 0 0.0 0 +chr9 31391990 0 0 0.0 0 +chr9 31420804 0 0 0.0 0 +chr9 31445256 0 0 0.0 0 +chr9 31469550 0 0 0.0 0 +chr9 31506949 0 0 0.0 0 +chr9 31836486 0 0 0.0 0 +chr9 31922706 0 0 0.0 0 +chr9 32076040 0 0 0.0 0 +chr9 32099358 0 0 0.0 0 +chr9 32496842 0 0 0.0 0 +chr9 32523020 0 0 0.0 0 +chr9 32534302 0 0 0.0 0 +chr9 32690447 0 0 0.0 0 +chr9 32723626 0 0 0.0 0 +chr9 32875439 0 1 0.0192 0 +chr9 33064547 0 0 0.0 0 +chr9 33174104 0 0 0.0 0 +chr9 33217494 0 0 0.0 0 +chr9 33241603 0 0 0.0 0 +chr9 33363616 0 0 0.0 0 +chr9 33438871 0 0 0.0 0 +chr9 33441266 0 0 0.0 0 +chr9 33586858 0 0 0.0 0 +chr9 33692144 0 0 0.0 0 +chr9 33722083 0 0 0.0 0 +chr9 33802823 0 0 0.0 0 +chr9 33803307 0 0 0.0 0 +chr9 33919704 0 2 0.0488 0 +chr9 34046813 0 0 0.0 0 +chr9 34180274 0 0 0.0 0 +chr9 34426857 0 0 0.0 0 +chr9 34447190 0 0 0.0 0 +chr9 34503656 0 0 0.0 0 +chr9 34519003 0 0 0.0 0 +chr9 34553341 0 0 0.0 0 +chr9 34715060 0 0 0.0 0 +chr9 34971259 0 0 0.0 0 +chr9 34974917 0 0 0.0 0 +chr9 35339778 0 0 0.0 0 +chr9 35436580 0 0 0.0 0 +chr9 35539528 0 0 0.0 0 +chr9 35582526 0 0 0.0 0 +chr9 35750504 0 0 0.0 0 +chr9 35910651 0 0 0.0 0 +chr9 35981300 0 0 0.0 0 +chr9 36121156 0 0 0.0 0 +chr9 36229613 0 0 0.0 0 +chr9 36270449 0 0 0.0 0 +chr9 36368115 0 0 0.0 0 +chr9 36379864 0 0 0.0 0 +chr9 36817929 0 0 0.0 0 +chr9 37026732 0 0 0.0 0 +chr9 37046518 0 0 0.0 0 +chr9 37076714 0 0 0.0 0 +chr9 37595028 0 0 0.0 0 +chr9 37701465 0 1 0.0133 0 +chr9 37928202 0 0 0.0 0 +chr9 37937234 0 0 0.0 0 +chr9 38120250 0 0 0.0 0 +chr9 38194008 0 0 0.0 0 +chr9 38322372 0 0 0.0 0 +chr9 38428591 0 0 0.0 0 +chr9 38506874 0 0 0.0 0 +chr9 38557373 0 0 0.0 0 +chr9 38563561 0 0 0.0 0 +chr9 38566784 0 0 0.0 0 +chr9 38639983 0 0 0.0 0 +chr9 38646220 0 1 0.02 0 +chr9 39227193 0 0 0.0 0 +chr9 39710365 0 0 0.0 0 +chr9 39735025 0 0 0.0 0 +chr9 39897890 0 0 0.0 0 +chr9 39935515 0 0 0.0 0 +chr9 39966397 0 0 0.0 0 +chr9 40107654 0 0 0.0 0 +chr9 40118864 0 0 0.0 0 +chr9 40195148 0 0 0.0 0 +chr9 40385965 0 0 0.0 0 +chr9 40472905 0 0 0.0 0 +chr9 40477374 0 0 0.0 0 +chr9 40503728 0 0 0.0 0 +chr9 40750657 0 0 0.0 0 +chr9 40802207 0 0 0.0 0 +chr9 40830558 0 0 0.0 0 +chr9 40832775 0 0 0.0 0 +chr9 40839079 0 0 0.0 0 +chr9 40852018 0 0 0.0 0 +chr9 40857304 0 0 0.0 0 +chr9 40891159 0 0 0.0 0 +chr9 41037510 0 0 0.0 0 +chr9 41068924 0 0 0.0 0 +chr9 41272545 0 0 0.0 0 +chr9 41344668 0 0 0.0 0 +chr9 41357859 0 0 0.0 0 +chr9 41497158 0 0 0.0 0 +chr9 41528013 0 0 0.0 0 +chr9 41568462 0 0 0.0 0 +chr9 41757031 0 0 0.0 0 +chr9 41795666 0 0 0.0 0 +chr9 42065072 0 0 0.0 0 +chr9 42394070 0 0 0.0 0 +chr9 42468387 0 0 0.0 0 +chr9 42492967 0 0 0.0 0 +chr9 42624410 0 0 0.0 0 +chr9 42669907 0 0 0.0 0 +chr9 42824310 0 0 0.0 0 +chr9 42831499 0 0 0.0 0 +chr9 42978404 0 0 0.0 0 +chr9 43012346 0 1 0.0192 0 +chr9 43101250 0 0 0.0 0 +chr9 43105706 0 0 0.0 0 +chr9 43132014 0 0 0.0 0 +chr9 43159439 0 0 0.0 0 +chr9 43181137 0 0 0.0 0 +chr9 60760815 0 0 0.0 0 +chr9 61391874 0 0 0.0 0 +chr9 61531908 0 0 0.0 0 +chr9 61556298 0 0 0.0 0 +chr9 61557926 0 0 0.0 0 +chr9 61578959 0 0 0.0 0 +chr9 62284322 0 0 0.0 0 +chr9 62315206 0 0 0.0 0 +chr9 62352833 0 0 0.0 0 +chr9 62431856 0 0 0.0 0 +chr9 62477354 0 0 0.0 0 +chr9 62607400 0 0 0.0 0 +chr9 62632052 0 0 0.0 0 +chr9 62836897 0 0 0.0 0 +chr9 62844980 0 0 0.0 0 +chr9 63063406 0 0 0.0 0 +chr9 63121246 0 0 0.0 0 +chr9 63147589 0 0 0.0 0 +chr9 63152061 0 0 0.0 0 +chr9 63308443 0 0 0.0 0 +chr9 63312910 0 0 0.0 0 +chr9 63339194 0 0 0.0 0 +chr9 63564554 0 0 0.0 0 +chr9 63704882 0 0 0.0 0 +chr9 63716765 0 0 0.0 0 +chr9 64021920 0 0 0.0 0 +chr9 64022222 0 0 0.0 0 +chr9 64075753 0 0 0.0 0 +chr9 64077031 0 0 0.0 0 +chr9 64205348 0 0 0.0 0 +chr9 64612917 0 0 0.0 0 +chr9 64617390 0 0 0.0 0 +chr9 64643700 0 0 0.0 0 +chr9 64701548 0 0 0.0 0 +chr9 64874264 0 0 0.0 0 +chr9 64922996 0 0 0.0 0 +chr9 64946036 0 0 0.0 0 +chr9 64963806 0 0 0.0 0 +chr9 64966023 0 0 0.0 0 +chr9 64972327 0 0 0.0 0 +chr9 64987652 0 0 0.0 0 +chr9 65148900 0 0 0.0 0 +chr9 65185813 0 0 0.0 0 +chr9 65416145 0 0 0.0 0 +chr9 65484546 0 0 0.0 0 +chr9 65489034 0 0 0.0 0 +chr9 65510055 0 0 0.0 0 +chr9 65835885 0 0 0.0 0 +chr9 65872653 0 0 0.0 0 +chr9 65898947 0 0 0.0 0 +chr9 65990341 0 0 0.0 0 +chr9 66181226 0 0 0.0 0 +chr9 66257131 0 0 0.0 0 +chr9 66268972 0 0 0.0 0 +chr9 66641922 0 0 0.0 0 +chr9 66666570 0 0 0.0 0 +chr9 67122405 0 0 0.0 0 +chr9 67619513 0 0 0.0 0 +chr9 67802539 0 0 0.0 0 +chr9 68362814 0 0 0.0 0 +chr9 68394576 0 0 0.0 0 +chr9 68487539 0 0 0.0 0 +chr9 68594017 0 0 0.0 0 +chr9 68665736 0 0 0.0 0 +chr9 68870786 0 0 0.0 0 +chr9 69008316 0 0 0.0 0 +chr9 69010477 0 0 0.0 0 +chr9 69015804 0 0 0.0 0 +chr9 69030632 0 0 0.0 0 +chr9 69134508 0 0 0.0 0 +chr9 69269809 0 0 0.0 0 +chr9 69292297 0 0 0.0 0 +chr9 69492620 0 0 0.0 0 +chr9 69582565 0 0 0.0 0 +chr9 69731274 0 0 0.0 0 +chr9 69933908 0 0 0.0 0 +chr9 69953126 0 0 0.0 0 +chr9 70079033 0 0 0.0 0 +chr9 70185193 0 0 0.0 0 +chr9 70437714 0 0 0.0 0 +chr9 70443028 0 0 0.0 0 +chr9 70937974 0 0 0.0 0 +chr9 70996864 0 0 0.0 0 +chr9 71056976 0 0 0.0 0 +chr9 71058845 0 0 0.0 0 +chr9 71274274 0 0 0.0 0 +chr9 71286372 0 0 0.0 0 +chr9 71325299 0 0 0.0 0 +chr9 71378577 0 0 0.0 0 +chr9 71755933 0 2 0.1111 0 +chr9 71864664 0 0 0.0 0 +chr9 72086391 0 0 0.0 0 +chr9 72142337 0 0 0.0 0 +chr9 72148088 0 0 0.0 0 +chr9 72165557 0 0 0.0 0 +chr9 72197917 0 0 0.0 0 +chr9 72287701 0 0 0.0 0 +chr9 72585883 0 0 0.0 0 +chr9 72656298 0 0 0.0 0 +chr9 72679935 0 0 0.0 0 +chr9 72762005 0 0 0.0 0 +chr9 72901842 0 0 0.0 0 +chr9 73049289 0 0 0.0 0 +chr9 73296965 0 0 0.0 0 +chr9 73760714 0 0 0.0 0 +chr9 74025802 0 0 0.0 0 +chr9 74390927 0 0 0.0 0 +chr9 74511719 0 0 0.0 0 +chr9 74633332 0 0 0.0 0 +chr9 74661178 0 0 0.0 0 +chr9 74727969 0 0 0.0 0 +chr9 74849107 0 0 0.0 0 +chr9 74964696 0 0 0.0 0 +chr9 74968100 0 0 0.0 0 +chr9 74978111 0 0 0.0 0 +chr9 75099487 0 0 0.0 0 +chr9 75108198 0 0 0.0 0 +chr9 75177546 0 0 0.0 0 +chr9 75254270 0 0 0.0 0 +chr9 75333261 0 0 0.0 0 +chr9 75698492 0 0 0.0 0 +chr9 75799184 0 0 0.0 0 +chr9 75821614 0 0 0.0 0 +chr9 75822775 0 0 0.0 0 +chr9 75864236 0 0 0.0 0 +chr9 75985441 0 0 0.0 0 +chr9 76234313 0 0 0.0 0 +chr9 76410955 0 0 0.0 0 +chr9 76437708 0 0 0.0 0 +chr9 76584375 0 0 0.0 0 +chr9 76712192 0 0 0.0 0 +chr9 76814288 0 0 0.0 0 +chr9 76925038 0 0 0.0 0 +chr9 77023887 0 0 0.0 0 +chr9 77177590 0 0 0.0 0 +chr9 77198046 0 0 0.0 0 +chr9 77272081 0 0 0.0 0 +chr9 77579247 0 0 0.0 0 +chr9 77588451 0 0 0.0 0 +chr9 77630934 0 0 0.0 0 +chr9 77847464 0 0 0.0 0 +chr9 77925166 0 0 0.0 0 +chr9 78019583 0 0 0.0 0 +chr9 78043665 0 0 0.0 0 +chr9 78063385 0 0 0.0 0 +chr9 78075833 0 0 0.0 0 +chr9 78079385 0 0 0.0 0 +chr9 78147969 0 0 0.0 0 +chr9 78209690 0 0 0.0 0 +chr9 78335647 0 0 0.0 0 +chr9 78348960 0 0 0.0 0 +chr9 78372194 0 0 0.0 0 +chr9 78413945 0 0 0.0 0 +chr9 78539244 0 0 0.0 0 +chr9 78556234 0 0 0.0 0 +chr9 78645334 0 0 0.0 0 +chr9 78680529 0 0 0.0 0 +chr9 78769400 1 48 0.7059 1 +chr9 78846503 0 0 0.0 0 +chr9 78890498 0 0 0.0 0 +chr9 78943930 0 0 0.0 0 +chr9 78985283 0 0 0.0 0 +chr9 79006035 0 0 0.0 0 +chr9 79191853 0 0 0.0 0 +chr9 79215980 0 0 0.0 0 +chr9 79265014 0 0 0.0 0 +chr9 79369664 0 0 0.0 0 +chr9 79390158 0 1 0.0238 0 +chr9 79395450 0 0 0.0 0 +chr9 79432729 0 0 0.0 0 +chr9 79594311 0 0 0.0 0 +chr9 79694211 0 0 0.0 0 +chr9 79723489 0 0 0.0 0 +chr9 79850943 0 0 0.0 0 +chr9 79910138 0 0 0.0 0 +chr9 79947852 0 0 0.0 0 +chr9 80185294 0 0 0.0 0 +chr9 80197109 0 0 0.0 0 +chr9 80287305 0 0 0.0 0 +chr9 80338167 0 0 0.0 0 +chr9 80418319 0 0 0.0 0 +chr9 80446431 0 0 0.0 0 +chr9 80493184 0 0 0.0 0 +chr9 80527780 0 0 0.0 0 +chr9 80553105 0 0 0.0 0 +chr9 80621505 0 0 0.0 0 +chr9 80725238 0 0 0.0 0 +chr9 80736058 0 0 0.0 0 +chr9 80806483 0 0 0.0 0 +chr9 80812244 0 0 0.0 0 +chr9 81162704 0 0 0.0 0 +chr9 81227075 0 0 0.0 0 +chr9 81374986 0 0 0.0 0 +chr9 81454387 0 0 0.0 0 +chr9 81468280 0 0 0.0 0 +chr9 81652301 0 0 0.0 0 +chr9 81717530 0 0 0.0 0 +chr9 81927525 0 0 0.0 0 +chr9 81942597 0 0 0.0 0 +chr9 81995194 0 0 0.0 0 +chr9 82014224 0 0 0.0 0 +chr9 82048135 0 0 0.0 0 +chr9 82074780 0 0 0.0 0 +chr9 82142507 0 0 0.0 0 +chr9 82328114 0 0 0.0 0 +chr9 83017242 0 0 0.0 0 +chr9 83323071 0 0 0.0 0 +chr9 83416190 0 0 0.0 0 +chr9 83541576 0 0 0.0 0 +chr9 83641269 0 0 0.0 0 +chr9 83644051 0 0 0.0 0 +chr9 83678810 0 0 0.0 0 +chr9 83696340 0 0 0.0 0 +chr9 83802074 0 0 0.0 0 +chr9 83959590 0 0 0.0 0 +chr9 84112825 0 0 0.0 0 +chr9 84179538 0 0 0.0 0 +chr9 84181303 0 0 0.0 0 +chr9 84368731 0 0 0.0 0 +chr9 84535726 0 0 0.0 0 +chr9 84689364 0 1 0.0135 0 +chr9 84764522 0 0 0.0 0 +chr9 84803390 0 0 0.0 0 +chr9 84968279 0 0 0.0 0 +chr9 85011491 0 0 0.0 0 +chr9 85041022 0 0 0.0 0 +chr9 85300184 0 0 0.0 0 +chr9 85454539 0 0 0.0 0 +chr9 85929691 0 0 0.0 0 +chr9 85963774 0 0 0.0 0 +chr9 86006877 0 0 0.0 0 +chr9 86039586 0 0 0.0 0 +chr9 86165222 0 2 0.069 0 +chr9 86174654 0 0 0.0 0 +chr9 86250006 0 0 0.0 0 +chr9 86265250 0 0 0.0 0 +chr9 86342868 0 0 0.0 0 +chr9 86382754 0 0 0.0 0 +chr9 86447431 0 0 0.0 0 +chr9 86480486 0 0 0.0 0 +chr9 86497679 0 0 0.0 0 +chr9 86532515 0 0 0.0 0 +chr9 86657409 0 0 0.0 0 +chr9 86738577 0 0 0.0 0 +chr9 86743610 0 0 0.0 0 +chr9 86870504 0 0 0.0 0 +chr9 86909532 0 0 0.0 0 +chr9 87032647 0 0 0.0 0 +chr9 87082923 0 0 0.0 0 +chr9 87203858 0 0 0.0 0 +chr9 87300086 0 0 0.0 0 +chr9 87343801 0 0 0.0 0 +chr9 87657442 0 0 0.0 0 +chr9 87674003 0 0 0.0 0 +chr9 87701650 0 0 0.0 0 +chr9 87769033 0 0 0.0 0 +chr9 87814707 0 0 0.0 0 +chr9 87848871 0 0 0.0 0 +chr9 87870814 0 0 0.0 0 +chr9 87938123 0 0 0.0 0 +chr9 88027649 0 0 0.0 0 +chr9 88114838 0 0 0.0 0 +chr9 88259249 0 0 0.0 0 +chr9 88399679 0 0 0.0 0 +chr9 88412242 0 0 0.0 0 +chr9 88630603 0 0 0.0 0 +chr9 88685937 0 0 0.0 0 +chr9 88781979 0 0 0.0 0 +chr9 88813589 0 0 0.0 0 +chr9 89217934 0 0 0.0 0 +chr9 89220100 0 0 0.0 0 +chr9 89381137 0 0 0.0 0 +chr9 89467791 0 0 0.0 0 +chr9 89496272 0 0 0.0 0 +chr9 89590608 0 0 0.0 0 +chr9 89632051 0 0 0.0 0 +chr9 89842241 0 0 0.0 0 +chr9 89918959 0 0 0.0 0 +chr9 90088199 0 0 0.0 0 +chr9 90137419 0 0 0.0 0 +chr9 90175351 0 0 0.0 0 +chr9 90183188 0 0 0.0 0 +chr9 90188049 0 0 0.0 0 +chr9 90223996 0 0 0.0 0 +chr9 90396884 0 0 0.0 0 +chr9 90442890 0 0 0.0 0 +chr9 90515663 0 0 0.0 0 +chr9 90556091 0 0 0.0 0 +chr9 90704985 0 0 0.0 0 +chr9 90758915 0 0 0.0 0 +chr9 90846738 0 0 0.0 0 +chr9 90867613 0 0 0.0 0 +chr9 91103136 0 0 0.0 0 +chr9 91133330 0 0 0.0 0 +chr9 91163160 0 0 0.0 0 +chr9 91190176 0 1 0.0175 0 +chr9 91267142 0 0 0.0 0 +chr9 91492566 0 0 0.0 0 +chr9 91652469 0 0 0.0 0 +chr9 91675360 0 0 0.0 0 +chr9 91680227 0 0 0.0 0 +chr9 91692246 1 31 0.3974 1 +chr9 91816147 0 0 0.0 0 +chr9 91932716 0 0 0.0 0 +chr9 91944814 0 0 0.0 0 +chr9 91991397 0 0 0.0 0 +chr9 92145002 0 1 0.0141 0 +chr9 92310963 0 0 0.0 0 +chr9 92325116 0 0 0.0 0 +chr9 92477649 0 0 0.0 0 +chr9 92524687 0 0 0.0 0 +chr9 92639625 0 0 0.0 0 +chr9 92784192 0 0 0.0 0 +chr9 92799070 0 0 0.0 0 +chr9 92934508 0 0 0.0 0 +chr9 93006184 0 0 0.0 0 +chr9 93021208 0 0 0.0 0 +chr9 93031242 0 0 0.0 0 +chr9 93151505 0 0 0.0 0 +chr9 93195003 1 5 0.0877 1 +chr9 93292699 0 0 0.0 0 +chr9 93311084 0 0 0.0 0 +chr9 93565932 0 0 0.0 0 +chr9 93615863 0 0 0.0 0 +chr9 93713188 0 0 0.0 0 +chr9 93821149 0 0 0.0 0 +chr9 93855599 0 0 0.0 0 +chr9 93873231 0 0 0.0 0 +chr9 93880285 0 0 0.0 0 +chr9 93910464 0 0 0.0 0 +chr9 93914525 0 0 0.0 0 +chr9 93919892 0 0 0.0 0 +chr9 93960077 0 0 0.0 0 +chr9 93995715 0 0 0.0 0 +chr9 94000841 0 0 0.0 0 +chr9 94311244 0 0 0.0 0 +chr9 94325526 0 0 0.0 0 +chr9 94328031 0 0 0.0 0 +chr9 94516028 0 0 0.0 0 +chr9 94606808 0 0 0.0 0 +chr9 94721053 0 0 0.0 0 +chr9 95007148 0 0 0.0 0 +chr9 95041838 0 0 0.0 0 +chr9 95045248 0 0 0.0 0 +chr9 95095358 0 0 0.0 0 +chr9 95187172 0 0 0.0 0 +chr9 95260963 0 0 0.0 0 +chr9 95302229 0 0 0.0 0 +chr9 95307955 0 0 0.0 0 +chr9 95331947 0 0 0.0 0 +chr9 95339439 0 0 0.0 0 +chr9 95388875 0 0 0.0 0 +chr9 95414674 0 0 0.0 0 +chr9 95478661 0 0 0.0 0 +chr9 95532257 0 0 0.0 0 +chr9 95548675 0 0 0.0 0 +chr9 95643201 0 0 0.0 0 +chr9 95710169 0 0 0.0 0 +chr9 95769638 0 0 0.0 0 +chr9 95958264 0 0 0.0 0 +chr9 96050794 0 0 0.0 0 +chr9 96085628 0 0 0.0 0 +chr9 96092147 0 0 0.0 0 +chr9 96112352 0 0 0.0 0 +chr9 96161324 0 0 0.0 0 +chr9 96286399 0 0 0.0 0 +chr9 96501793 0 2 0.0526 0 +chr9 96688505 0 0 0.0 0 +chr9 96731420 1 3 0.0789 1 +chr9 96832552 0 0 0.0 0 +chr9 96874914 0 0 0.0 0 +chr9 96929614 0 0 0.0 0 +chr9 96932131 0 0 0.0 0 +chr9 96944851 0 0 0.0 0 +chr9 97096063 0 0 0.0 0 +chr9 97148057 0 0 0.0 0 +chr9 97225530 0 0 0.0 0 +chr9 97238607 0 0 0.0 0 +chr9 97313786 0 0 0.0 0 +chr9 97356530 0 0 0.0 0 +chr9 97364910 0 0 0.0 0 +chr9 97388554 0 0 0.0 0 +chr9 97463722 0 0 0.0 0 +chr9 97860815 0 0 0.0 0 +chr9 98040273 0 0 0.0 0 +chr9 98085688 0 0 0.0 0 +chr9 98155606 0 0 0.0 0 +chr9 98170968 0 0 0.0 0 +chr9 98265165 0 0 0.0 0 +chr9 98389908 0 0 0.0 0 +chr9 98415944 0 0 0.0 0 +chr9 98480724 0 0 0.0 0 +chr9 98690688 0 0 0.0 0 +chr9 98708113 0 0 0.0 0 +chr9 98710657 0 0 0.0 0 +chr9 98712911 0 0 0.0 0 +chr9 98790559 0 0 0.0 0 +chr9 98840225 0 0 0.0 0 +chr9 98906546 0 0 0.0 0 +chr9 99092484 0 0 0.0 0 +chr9 99103619 0 0 0.0 0 +chr9 99190536 0 0 0.0 0 +chr9 99320803 0 0 0.0 0 +chr9 99361624 0 0 0.0 0 +chr9 99455744 0 0 0.0 0 +chr9 100258701 0 0 0.0 0 +chr9 100367613 0 0 0.0 0 +chr9 100391046 0 0 0.0 0 +chr9 100492892 0 0 0.0 0 +chr9 100638036 0 0 0.0 0 +chr9 100829055 0 0 0.0 0 +chr9 100838600 0 0 0.0 0 +chr9 100899355 0 0 0.0 0 +chr9 100917760 0 0 0.0 0 +chr9 101315335 0 0 0.0 0 +chr9 101486397 0 0 0.0 0 +chr9 101502308 0 0 0.0 0 +chr9 101587493 0 0 0.0 0 +chr9 101589234 0 0 0.0 0 +chr9 101944673 0 0 0.0 0 +chr9 102168491 0 0 0.0 0 +chr9 102204617 0 0 0.0 0 +chr9 102328976 0 0 0.0 0 +chr9 102752799 0 0 0.0 0 +chr9 103191498 0 0 0.0 0 +chr9 103197104 0 0 0.0 0 +chr9 103501322 0 0 0.0 0 +chr9 103711323 0 0 0.0 0 +chr9 103738197 0 0 0.0 0 +chr9 103773806 0 0 0.0 0 +chr9 103803451 0 0 0.0 0 +chr9 103805254 0 0 0.0 0 +chr9 103997553 0 1 0.0161 0 +chr9 104038827 0 0 0.0 0 +chr9 104228956 0 0 0.0 0 +chr9 104330478 0 0 0.0 0 +chr9 104339471 0 0 0.0 0 +chr9 104346748 0 0 0.0 0 +chr9 104349157 0 0 0.0 0 +chr9 104442666 0 0 0.0 0 +chr9 104447176 0 0 0.0 0 +chr9 104520466 0 0 0.0 0 +chr9 104618273 0 0 0.0 0 +chr9 104674456 0 0 0.0 0 +chr9 104767324 0 0 0.0 0 +chr9 104825287 0 0 0.0 0 +chr9 104895470 0 0 0.0 0 +chr9 104922248 0 0 0.0 0 +chr9 105096556 0 0 0.0 0 +chr9 105109835 0 0 0.0 0 +chr9 105178023 0 0 0.0 0 +chr9 105185463 0 0 0.0 0 +chr9 105238791 0 0 0.0 0 +chr9 105272339 0 0 0.0 0 +chr9 105379314 0 0 0.0 0 +chr9 105416130 0 0 0.0 0 +chr9 105601028 0 0 0.0 0 +chr9 105642809 0 0 0.0 0 +chr9 105674207 0 0 0.0 0 +chr9 105790356 0 0 0.0 0 +chr9 105843391 0 0 0.0 0 +chr9 105850560 0 0 0.0 0 +chr9 105866213 0 0 0.0 0 +chr9 106051921 0 0 0.0 0 +chr9 106152194 0 0 0.0 0 +chr9 106243815 0 0 0.0 0 +chr9 106439689 3 32 0.8889 1 +chr9 106519430 0 1 0.0132 0 +chr9 106757087 0 0 0.0 0 +chr9 106757322 0 0 0.0 0 +chr9 106929111 0 0 0.0 0 +chr9 106950980 0 0 0.0 0 +chr9 107133122 0 0 0.0 0 +chr9 107158289 0 0 0.0 0 +chr9 107206288 0 0 0.0 0 +chr9 107300553 0 0 0.0 0 +chr9 107426036 0 0 0.0 0 +chr9 107493244 0 0 0.0 0 +chr9 107527359 0 0 0.0 0 +chr9 107538264 0 0 0.0 0 +chr9 107572269 0 0 0.0 0 +chr9 107586372 0 0 0.0 0 +chr9 107778578 0 0 0.0 0 +chr9 107942481 0 0 0.0 0 +chr9 108238962 0 0 0.0 0 +chr9 108309005 0 0 0.0 0 +chr9 108318317 0 0 0.0 0 +chr9 108483087 0 0 0.0 0 +chr9 108673701 0 0 0.0 0 +chr9 108675424 0 0 0.0 0 +chr9 108708503 0 0 0.0 0 +chr9 108772390 0 0 0.0 0 +chr9 108907780 0 0 0.0 0 +chr9 108953208 0 0 0.0 0 +chr9 109000814 0 0 0.0 0 +chr9 109230471 0 0 0.0 0 +chr9 109287679 0 0 0.0 0 +chr9 109301876 0 0 0.0 0 +chr9 109353235 0 0 0.0 0 +chr9 109386198 0 0 0.0 0 +chr9 109431289 0 0 0.0 0 +chr9 109495118 0 0 0.0 0 +chr9 109504414 0 0 0.0 0 +chr9 109521125 0 0 0.0 0 +chr9 109535276 0 0 0.0 0 +chr9 109632943 0 0 0.0 0 +chr9 109708919 0 0 0.0 0 +chr9 109725960 0 0 0.0 0 +chr9 109836260 0 0 0.0 0 +chr9 110054325 0 0 0.0 0 +chr9 110113867 0 0 0.0 0 +chr9 110136363 0 1 0.0196 0 +chr9 110250024 0 0 0.0 0 +chr9 110317500 0 0 0.0 0 +chr9 110432786 0 0 0.0 0 +chr9 110580696 0 0 0.0 0 +chr9 110748012 0 0 0.0 0 +chr9 110875737 0 0 0.0 0 +chr9 110891278 0 0 0.0 0 +chr9 110906237 0 0 0.0 0 +chr9 111154877 0 0 0.0 0 +chr9 111286037 0 0 0.0 0 +chr9 111305455 0 0 0.0 0 +chr9 111330865 0 0 0.0 0 +chr9 111430915 0 0 0.0 0 +chr9 111583531 0 0 0.0 0 +chr9 111723305 0 0 0.0 0 +chr9 111748184 0 0 0.0 0 +chr9 111817215 0 0 0.0 0 +chr9 111824036 0 1 0.0147 0 +chr9 112457994 0 0 0.0 0 +chr9 112470281 0 0 0.0 0 +chr9 112721080 0 0 0.0 0 +chr9 112726236 0 0 0.0 0 +chr9 112743379 0 0 0.0 0 +chr9 112764065 0 0 0.0 0 +chr9 112772056 0 0 0.0 0 +chr9 112838261 0 0 0.0 0 +chr9 112865593 0 0 0.0 0 +chr9 112963694 0 0 0.0 0 +chr9 113111355 0 0 0.0 0 +chr9 113113219 0 0 0.0 0 +chr9 113136266 0 0 0.0 0 +chr9 113141769 0 0 0.0 0 +chr9 113429253 0 1 0.0222 0 +chr9 113534980 0 0 0.0 0 +chr9 113539537 0 0 0.0 0 +chr9 113542671 0 0 0.0 0 +chr9 113583552 0 0 0.0 0 +chr9 113704892 0 0 0.0 0 +chr9 113721463 0 0 0.0 0 +chr9 114107618 0 0 0.0 0 +chr9 114170499 0 0 0.0 0 +chr9 114202467 0 0 0.0 0 +chr9 114218575 0 0 0.0 0 +chr9 114373052 0 0 0.0 0 +chr9 114510633 0 0 0.0 0 +chr9 114656415 0 0 0.0 0 +chr9 114659105 0 0 0.0 0 +chr9 114669702 0 0 0.0 0 +chr9 114697433 0 0 0.0 0 +chr9 114715435 0 0 0.0 0 +chr9 114733942 0 0 0.0 0 +chr9 114765308 0 0 0.0 0 +chr9 114799060 0 0 0.0 0 +chr9 114836089 0 0 0.0 0 +chr9 114853299 0 0 0.0 0 +chr9 114870002 0 0 0.0 0 +chr9 114897812 0 0 0.0 0 +chr9 114944342 0 0 0.0 0 +chr9 115006787 0 0 0.0 0 +chr9 115018020 0 0 0.0 0 +chr9 115030046 0 0 0.0 0 +chr9 115084644 0 0 0.0 0 +chr9 115100655 0 0 0.0 0 +chr9 115159360 0 0 0.0 0 +chr9 115164088 0 0 0.0 0 +chr9 115262757 0 0 0.0 0 +chr9 115732630 0 0 0.0 0 +chr9 115967137 0 0 0.0 0 +chr9 115996410 0 0 0.0 0 +chr9 116002377 0 0 0.0 0 +chr9 116053451 0 0 0.0 0 +chr9 116058844 0 0 0.0 0 +chr9 116104697 0 0 0.0 0 +chr9 116180090 0 0 0.0 0 +chr9 116204459 0 0 0.0 0 +chr9 116226640 0 0 0.0 0 +chr9 116284959 0 0 0.0 0 +chr9 116307464 0 0 0.0 0 +chr9 116486716 0 0 0.0 0 +chr9 116747157 0 0 0.0 0 +chr9 116877057 0 0 0.0 0 +chr9 116911250 0 0 0.0 0 +chr9 116923936 0 0 0.0 0 +chr9 116987181 0 0 0.0 0 +chr9 117135899 0 0 0.0 0 +chr9 117146094 0 0 0.0 0 +chr9 117160320 0 0 0.0 0 +chr9 117184541 0 0 0.0 0 +chr9 117255910 0 0 0.0 0 +chr9 117337841 0 0 0.0 0 +chr9 117348225 0 0 0.0 0 +chr9 117371985 0 0 0.0 0 +chr9 117422471 0 0 0.0 0 +chr9 117443055 0 0 0.0 0 +chr9 117494708 0 0 0.0 0 +chr9 117551288 0 0 0.0 0 +chr9 117603182 0 0 0.0 0 +chr9 117744926 0 0 0.0 0 +chr9 117747356 0 0 0.0 0 +chr9 117805572 0 0 0.0 0 +chr9 117890196 0 0 0.0 0 +chr9 118017744 0 0 0.0 0 +chr9 118164066 0 0 0.0 0 +chr9 118194473 0 0 0.0 0 +chr9 118201851 0 0 0.0 0 +chr9 118448830 0 0 0.0 0 +chr9 118979099 0 0 0.0 0 +chr9 119240799 0 0 0.0 0 +chr9 119245678 0 0 0.0 0 +chr9 119279171 0 0 0.0 0 +chr9 119359710 0 0 0.0 0 +chr9 119368540 0 0 0.0 0 +chr9 119375889 0 0 0.0 0 +chr9 119482468 0 0 0.0 0 +chr9 119736904 0 0 0.0 0 +chr9 119764277 0 0 0.0 0 +chr9 119768824 0 0 0.0 0 +chr9 119857983 0 0 0.0 0 +chr9 119869078 0 0 0.0 0 +chr9 119959982 0 0 0.0 0 +chr9 119989681 0 0 0.0 0 +chr9 120027136 0 0 0.0 0 +chr9 120029961 0 0 0.0 0 +chr9 120034805 0 0 0.0 0 +chr9 120118849 0 0 0.0 0 +chr9 120240433 0 0 0.0 0 +chr9 120468736 0 0 0.0 0 +chr9 120689503 0 0 0.0 0 +chr9 120901992 0 1 0.0185 0 +chr9 120932194 0 0 0.0 0 +chr9 120938616 0 0 0.0 0 +chr9 121027019 0 0 0.0 0 +chr9 121072697 0 0 0.0 0 +chr9 121095841 0 0 0.0 0 +chr9 121233027 0 0 0.0 0 +chr9 121266058 0 0 0.0 0 +chr9 121268958 0 0 0.0 0 +chr9 121475519 0 0 0.0 0 +chr9 121518201 0 0 0.0 0 +chr9 121571145 0 0 0.0 0 +chr9 121574471 0 0 0.0 0 +chr9 121733332 0 0 0.0 0 +chr9 121784314 0 0 0.0 0 +chr9 121866842 0 0 0.0 0 +chr9 121868096 0 0 0.0 0 +chr9 121955472 0 0 0.0 0 +chr9 121955971 0 1 0.25 0 +chr9 122014934 0 0 0.0 0 +chr9 122058200 0 0 0.0 0 +chr9 122169959 0 1 0.0238 0 +chr9 122195730 0 0 0.0 0 +chr9 122216755 0 0 0.0 0 +chr9 122252568 0 0 0.0 0 +chr9 122255612 0 0 0.0 0 +chr9 122284719 0 0 0.0 0 +chr9 122389631 0 0 0.0 0 +chr9 122392175 0 1 0.0154 0 +chr9 122427309 0 0 0.0 0 +chr9 122478319 0 0 0.0 0 +chr9 122611258 0 0 0.0 0 +chr9 122686515 0 0 0.0 0 +chr9 122728871 0 0 0.0 0 +chr9 122823663 0 0 0.0 0 +chr9 122897197 0 0 0.0 0 +chr9 122934022 0 0 0.0 0 +chr9 123381707 0 0 0.0 0 +chr9 123414844 0 0 0.0 0 +chr9 123417837 0 0 0.0 0 +chr9 123421453 0 0 0.0 0 +chr9 123435030 0 0 0.0 0 +chr9 123591982 0 0 0.0 0 +chr9 123682596 0 0 0.0 0 +chr9 123737053 0 0 0.0 0 +chr9 123807750 0 0 0.0 0 +chr9 123923264 0 0 0.0 0 +chr9 123948401 0 0 0.0 0 +chr9 123962518 0 0 0.0 0 +chr9 123980704 0 1 0.0196 0 +chr9 123982359 0 0 0.0 0 +chr9 124022444 0 0 0.0 0 +chr9 124044665 0 0 0.0 0 +chr9 124282608 0 0 0.0 0 +chr9 124482137 0 0 0.0 0 +chr9 124490439 0 0 0.0 0 +chr9 124571111 0 0 0.0 0 +chr9 124786192 0 0 0.0 0 +chr9 124810060 0 0 0.0 0 +chr9 124853421 0 0 0.0 0 +chr9 124886148 0 0 0.0 0 +chr9 125205749 0 0 0.0 0 +chr9 125305777 0 0 0.0 0 +chr9 125376467 0 0 0.0 0 +chr9 125490154 0 0 0.0 0 +chr9 125634638 0 0 0.0 0 +chr9 125644954 0 0 0.0 0 +chr9 125671889 0 0 0.0 0 +chr9 125872956 0 0 0.0 0 +chr9 125986391 0 0 0.0 0 +chr9 126046864 0 0 0.0 0 +chr9 126229096 0 0 0.0 0 +chr9 126276603 0 0 0.0 0 +chr9 126524915 0 0 0.0 0 +chr9 126695812 0 0 0.0 0 +chr9 126793532 0 1 0.0128 0 +chr9 126969231 0 0 0.0 0 +chr9 127133226 0 0 0.0 0 +chr9 127211739 0 0 0.0 0 +chr9 127459452 0 0 0.0 0 +chr9 127540849 0 0 0.0 0 +chr9 127554361 0 0 0.0 0 +chr9 127630264 0 0 0.0 0 +chr9 127738883 0 0 0.0 0 +chr9 127908445 0 0 0.0 0 +chr9 128074674 0 0 0.0 0 +chr9 128080819 0 0 0.0 0 +chr9 128197440 0 0 0.0 0 +chr9 128202911 0 0 0.0 0 +chr9 128206123 0 0 0.0 0 +chr9 128390176 0 0 0.0 0 +chr9 128410098 0 0 0.0 0 +chr9 128419420 0 0 0.0 0 +chr9 128555111 0 0 0.0 0 +chr9 128624942 0 0 0.0 0 +chr9 128647300 0 0 0.0 0 +chr9 128688419 0 0 0.0 0 +chr9 128809104 0 0 0.0 0 +chr9 128826625 0 0 0.0 0 +chr9 128925179 0 0 0.0 0 +chr9 128945092 0 0 0.0 0 +chr9 129009883 0 0 0.0 0 +chr9 129061142 0 0 0.0 0 +chr9 129071903 0 0 0.0 0 +chr9 129085177 0 0 0.0 0 +chr9 129216318 0 0 0.0 0 +chr9 129257565 0 0 0.0 0 +chr9 129341103 0 0 0.0 0 +chr9 129362071 0 0 0.0 0 +chr9 129371045 0 0 0.0 0 +chr9 129415285 0 0 0.0 0 +chr9 129495107 0 1 0.0182 0 +chr9 129510652 0 0 0.0 0 +chr9 129643891 0 0 0.0 0 +chr9 129823314 0 0 0.0 0 +chr9 129966091 0 0 0.0 0 +chr9 130047095 0 0 0.0 0 +chr9 130135652 0 0 0.0 0 +chr9 130234803 0 0 0.0 0 +chr9 130342363 0 0 0.0 0 +chr9 130404752 0 0 0.0 0 +chr9 130411795 0 0 0.0 0 +chr9 130425713 0 0 0.0 0 +chr9 130431276 0 0 0.0 0 +chr9 130449579 0 0 0.0 0 +chr9 130550628 0 0 0.0 0 +chr9 130630503 0 0 0.0 0 +chr9 130741158 0 0 0.0 0 +chr9 130829489 0 0 0.0 0 +chr9 130864722 0 0 0.0 0 +chr9 130891468 0 0 0.0 0 +chr9 130894737 0 0 0.0 0 +chr9 130946928 0 0 0.0 0 +chr9 131192749 0 0 0.0 0 +chr9 131234244 0 0 0.0 0 +chr9 131284502 0 0 0.0 0 +chr9 131426095 0 0 0.0 0 +chr9 131531053 0 0 0.0 0 +chr9 131643090 0 2 0.0204 0 +chr9 131667444 0 0 0.0 0 +chr9 131845840 0 0 0.0 0 +chr9 131853660 0 0 0.0 0 +chr9 131973343 0 0 0.0 0 +chr9 132024063 0 0 0.0 0 +chr9 132198367 0 0 0.0 0 +chr9 132254287 0 0 0.0 0 +chr9 132264394 0 0 0.0 0 +chr9 132295156 0 0 0.0 0 +chr9 132318144 0 0 0.0 0 +chr9 132447873 0 0 0.0 0 +chr9 132532057 0 0 0.0 0 +chr9 132636343 0 0 0.0 0 +chr9 132638714 0 0 0.0 0 +chr9 132694604 0 0 0.0 0 +chr9 132848684 0 0 0.0 0 +chr9 132884240 0 0 0.0 0 +chr9 132893597 0 0 0.0 0 +chr9 133024339 0 0 0.0 0 +chr9 133031139 0 0 0.0 0 +chr9 133066146 0 0 0.0 0 +chr9 133079964 0 0 0.0 0 +chr9 133089246 0 1 0.025 0 +chr9 133193671 0 0 0.0 0 +chr9 133204642 0 0 0.0 0 +chr9 133284281 0 0 0.0 0 +chr9 133341497 0 0 0.0 0 +chr9 133350239 0 0 0.0 0 +chr9 133413882 0 0 0.0 0 +chr9 133464343 0 0 0.0 0 +chr9 133586571 0 0 0.0 0 +chr9 133629228 0 0 0.0 0 +chr9 133633655 0 0 0.0 0 +chr9 133646230 0 0 0.0 0 +chr9 133651992 0 0 0.0 0 +chr9 133681268 0 0 0.0 0 +chr9 133708637 0 0 0.0 0 +chr9 133810175 0 0 0.0 0 +chr9 133852071 0 0 0.0 0 +chr9 133907574 0 0 0.0 0 +chr9 134229289 0 0 0.0 0 +chr9 134234945 0 0 0.0 0 +chr9 134416927 0 0 0.0 0 +chr9 134422933 0 0 0.0 0 +chr9 134463486 0 0 0.0 0 +chr9 134583933 0 0 0.0 0 +chr9 134680542 0 0 0.0 0 +chr9 134761568 0 0 0.0 0 +chr9 134773466 0 0 0.0 0 +chr9 134789417 0 0 0.0 0 +chr9 134799092 0 0 0.0 0 +chr9 134818489 0 0 0.0 0 +chr9 134941562 0 0 0.0 0 +chr9 135008960 0 0 0.0 0 +chr9 135029775 0 0 0.0 0 +chr9 135112805 0 0 0.0 0 +chr9 135187644 0 0 0.0 0 +chr9 135266836 0 0 0.0 0 +chr9 135378393 0 0 0.0 0 +chr9 135384291 0 0 0.0 0 +chr9 135442679 0 0 0.0 0 +chr9 135588556 0 0 0.0 0 +chr9 135717793 0 0 0.0 0 +chr9 135733075 0 0 0.0 0 +chr9 135781209 0 0 0.0 0 +chr9 135809837 0 0 0.0 0 +chr9 135861913 0 0 0.0 0 +chr9 135886751 0 0 0.0 0 +chr9 135979977 0 0 0.0 0 +chr9 136049726 0 0 0.0 0 +chr9 136051419 0 0 0.0 0 +chr9 136072303 0 0 0.0 0 +chr9 136147925 0 0 0.0 0 +chr9 136160158 0 1 0.0087 0 +chr9 136241180 0 0 0.0 0 +chr9 136263706 0 0 0.0 0 +chr9 136277622 0 0 0.0 0 +chr9 136290467 0 0 0.0 0 +chr9 136316130 0 0 0.0 0 +chr9 136357084 0 0 0.0 0 +chr9 136423514 0 0 0.0 0 +chr9 136456329 0 0 0.0 0 +chr9 136495999 0 0 0.0 0 +chr9 136531131 0 0 0.0 0 +chr9 136563902 0 0 0.0 0 +chr9 136606220 0 0 0.0 0 +chr9 136671758 0 0 0.0 0 +chr9 136757827 0 0 0.0 0 +chr9 136762066 0 1 0.0149 0 +chr9 136875728 0 0 0.0 0 +chr9 136878791 0 0 0.0 0 +chr9 136943454 0 0 0.0 0 +chr9 136970438 0 0 0.0 0 +chr9 137030019 0 0 0.0 0 +chr9 137041321 0 0 0.0 0 +chr9 137081808 0 0 0.0 0 +chr9 137095755 0 0 0.0 0 +chr9 137136634 0 0 0.0 0 +chr9 137153525 0 1 0.0119 0 +chr9 137230788 0 0 0.0 0 +chr9 137264875 0 0 0.0 0 +chr9 137358817 0 0 0.0 0 +chr9 137408236 0 1 0.0169 0 +chr9 137427732 0 0 0.0 0 +chr9 137463526 0 0 0.0 0 +chr9 137570369 0 0 0.0 0 +chr9 137606146 0 0 0.0 0 +chr9 137713180 0 0 0.0 0 +chr9 137725872 0 0 0.0 0 +chr9 137792311 0 1 0.012 0 +chr9 137942803 0 0 0.0 0 +chr9 137975378 0 0 0.0 0 +chr9 138000359 0 0 0.0 0 +chr9 138023308 0 0 0.0 0 +chr9 138051029 0 0 0.0 0 +chr9 138112896 0 0 0.0 0 +chr9 138114009 0 0 0.0 0 +chr9 138175462 0 0 0.0 0 +chr9 138199060 0 0 0.0 0 +chr9_GL383541v1_alt 54921 0 0 0.0 0 +chr9_GL383541v1_alt 167160 0 0 0.0 0 +chr9_KI270719v1_random 102336 0 0 0.0 0 +chr9_KI270719v1_random 171501 0 0 0.0 0 +chr9_KI270720v1_random 35195 0 0 0.0 0 +chr9_KI270823v1_alt 366537 0 0 0.0 0 +chrUn_GL000195v1 105859 0 0 0.0 0 +chrUn_GL000214v1 108144 0 0 0.0 0 +chrUn_GL000216v2 13134 0 0 0.0 0 +chrUn_GL000220v1 5668 0 0 0.0 0 +chrUn_GL000220v1 26279 0 0 0.0 0 +chrUn_KI270438v1 47971 0 0 0.0 0 +chrUn_KI270438v1 71010 1 9 0.3333 1 +chrUn_KI270438v1 73152 0 0 0.0 0 +chrUn_KI270438v1 84766 0 0 0.0 0 +chrUn_KI270442v1 18989 0 0 0.0 0 +chrUn_KI270442v1 22440 0 0 0.0 0 +chrUn_KI270442v1 23889 0 0 0.0 0 +chrUn_KI270442v1 58174 1 3 0.75 1 +chrUn_KI270442v1 71566 0 0 0.0 0 +chrUn_KI270442v1 76681 0 0 0.0 0 +chrUn_KI270442v1 83366 0 0 0.0 0 +chrUn_KI270442v1 101797 0 0 0.0 0 +chrUn_KI270442v1 108113 0 0 0.0 0 +chrUn_KI270442v1 109297 0 0 0.0 0 +chrUn_KI270442v1 110312 0 0 0.0 0 +chrUn_KI270442v1 128770 0 0 0.0 0 +chrUn_KI270442v1 234230 0 0 0.0 0 +chrUn_KI270509v1 237 0 0 0.0 0 +chrUn_KI270511v1 3221 0 0 0.0 0 +chrUn_KI270512v1 21612 0 0 0.0 0 +chrUn_KI270579v1 12851 0 0 0.0 0 +chrUn_KI270588v1 3475 0 0 0.0 0 +chrUn_KI270589v1 42477 0 2 0.2 0 +chrUn_KI270743v1 81449 0 0 0.0 0 +chrUn_KI270743v1 172907 0 0 0.0 0 +chrUn_KI270743v1 194415 0 0 0.0 0 +chrUn_KI270746v1 29569 0 0 0.0 0 +chrUn_KI270748v1 29889 0 0 0.0 0 +chrUn_KI270748v1 84066 0 0 0.0 0 +chrUn_KI270748v1 85499 0 0 0.0 0 +chrUn_KI270749v1 129302 0 0 0.0 0 +chrUn_KI270756v1 50558 0 0 0.0 0 +chrUn_KI270756v1 62898 0 0 0.0 0 +chrX 20619 0 1 0.0159 0 +chrX 282238 0 0 0.0 0 +chrX 356090 0 0 0.0 0 +chrX 370842 0 0 0.0 0 +chrX 385838 0 0 0.0 0 +chrX 423040 0 0 0.0 0 +chrX 461323 0 0 0.0 0 +chrX 504410 0 0 0.0 0 +chrX 542193 0 0 0.0 0 +chrX 651742 0 0 0.0 0 +chrX 658236 0 0 0.0 0 +chrX 700205 0 0 0.0 0 +chrX 700517 0 0 0.0 0 +chrX 788866 0 0 0.0 0 +chrX 792078 0 0 0.0 0 +chrX 831723 0 0 0.0 0 +chrX 833280 0 0 0.0 0 +chrX 884138 0 0 0.0 0 +chrX 894521 0 0 0.0 0 +chrX 936841 0 0 0.0 0 +chrX 982140 0 1 0.0128 0 +chrX 1060315 0 0 0.0 0 +chrX 1072125 0 0 0.0 0 +chrX 1092575 0 1 0.0169 0 +chrX 1114430 0 0 0.0 0 +chrX 1123555 0 0 0.0 0 +chrX 1130406 0 0 0.0 0 +chrX 1138359 0 0 0.0 0 +chrX 1179931 0 0 0.0 0 +chrX 1186908 0 0 0.0 0 +chrX 1248383 0 0 0.0 0 +chrX 1444883 0 0 0.0 0 +chrX 1451010 0 0 0.0 0 +chrX 1550070 0 0 0.0 0 +chrX 1574238 0 0 0.0 0 +chrX 1632820 0 0 0.0 0 +chrX 1774953 0 0 0.0 0 +chrX 1934146 0 0 0.0 0 +chrX 2192859 0 0 0.0 0 +chrX 2220898 0 0 0.0 0 +chrX 2232322 1 22 0.3333 1 +chrX 2244802 0 0 0.0 0 +chrX 2256254 0 0 0.0 0 +chrX 2412345 0 0 0.0 0 +chrX 2459864 0 0 0.0 0 +chrX 2679047 0 0 0.0 0 +chrX 2835351 0 0 0.0 0 +chrX 2855604 0 0 0.0 0 +chrX 3209115 0 1 0.0217 0 +chrX 3397503 0 0 0.0 0 +chrX 4360234 0 0 0.0 0 +chrX 4393307 0 0 0.0 0 +chrX 4401196 0 0 0.0 0 +chrX 4684638 0 0 0.0 0 +chrX 4782402 0 0 0.0 0 +chrX 4932669 0 0 0.0 0 +chrX 5073176 0 0 0.0 0 +chrX 5209384 0 0 0.0 0 +chrX 5454780 0 0 0.0 0 +chrX 5676513 0 0 0.0 0 +chrX 5751621 0 0 0.0 0 +chrX 5800319 0 0 0.0 0 +chrX 5968011 0 0 0.0 0 +chrX 6415404 0 0 0.0 0 +chrX 6458336 0 0 0.0 0 +chrX 6588946 0 0 0.0 0 +chrX 7020103 0 0 0.0 0 +chrX 7060081 0 0 0.0 0 +chrX 7148632 0 0 0.0 0 +chrX 7298654 0 0 0.0 0 +chrX 7383631 0 0 0.0 0 +chrX 7631794 0 0 0.0 0 +chrX 7727605 0 0 0.0 0 +chrX 7842731 0 0 0.0 0 +chrX 7902690 0 0 0.0 0 +chrX 7934782 0 0 0.0 0 +chrX 7938527 0 0 0.0 0 +chrX 7972555 0 0 0.0 0 +chrX 8105568 0 0 0.0 0 +chrX 8346053 0 0 0.0 0 +chrX 8365308 0 1 0.0213 0 +chrX 8390233 0 0 0.0 0 +chrX 8522462 0 0 0.0 0 +chrX 8702839 0 0 0.0 0 +chrX 8803827 0 0 0.0 0 +chrX 8879243 0 0 0.0 0 +chrX 8910814 0 0 0.0 0 +chrX 9144922 0 0 0.0 0 +chrX 9186331 0 0 0.0 0 +chrX 9224958 0 0 0.0 0 +chrX 9266699 0 0 0.0 0 +chrX 9342840 0 0 0.0 0 +chrX 9384826 0 0 0.0 0 +chrX 9456266 0 0 0.0 0 +chrX 9465076 0 0 0.0 0 +chrX 9772040 0 0 0.0 0 +chrX 9804153 0 0 0.0 0 +chrX 9807152 0 0 0.0 0 +chrX 9813241 0 0 0.0 0 +chrX 9822834 0 0 0.0 0 +chrX 9983771 0 0 0.0 0 +chrX 10067643 0 0 0.0 0 +chrX 10116654 0 0 0.0 0 +chrX 10257048 0 0 0.0 0 +chrX 10369421 0 0 0.0 0 +chrX 10601990 0 0 0.0 0 +chrX 10697755 0 1 0.0175 0 +chrX 10834615 0 0 0.0 0 +chrX 11024664 0 0 0.0 0 +chrX 11140891 0 0 0.0 0 +chrX 11215715 0 0 0.0 0 +chrX 11263900 0 0 0.0 0 +chrX 11601786 0 0 0.0 0 +chrX 11783517 0 0 0.0 0 +chrX 11849670 2 12 0.3871 1 +chrX 11976856 0 0 0.0 0 +chrX 11991242 0 0 0.0 0 +chrX 12007501 0 0 0.0 0 +chrX 12097237 0 0 0.0 0 +chrX 12209591 0 0 0.0 0 +chrX 12349985 0 0 0.0 0 +chrX 12439000 0 0 0.0 0 +chrX 12464297 0 0 0.0 0 +chrX 12619486 0 0 0.0 0 +chrX 12792373 0 0 0.0 0 +chrX 12829416 0 0 0.0 0 +chrX 12839228 0 0 0.0 0 +chrX 12854636 0 0 0.0 0 +chrX 12903933 0 0 0.0 0 +chrX 12974955 0 0 0.0 0 +chrX 12994383 0 0 0.0 0 +chrX 13081595 0 0 0.0 0 +chrX 13181904 0 0 0.0 0 +chrX 13599692 0 0 0.0 0 +chrX 13718234 0 1 0.0213 0 +chrX 13810418 0 0 0.0 0 +chrX 13923571 0 0 0.0 0 +chrX 13936671 0 0 0.0 0 +chrX 14619269 0 0 0.0 0 +chrX 14736105 0 0 0.0 0 +chrX 14913612 0 0 0.0 0 +chrX 15015917 0 0 0.0 0 +chrX 15052998 0 1 0.0278 0 +chrX 15146681 0 0 0.0 0 +chrX 15310094 0 0 0.0 0 +chrX 15536982 0 0 0.0 0 +chrX 15673679 0 0 0.0 0 +chrX 15687973 0 0 0.0 0 +chrX 15712362 0 0 0.0 0 +chrX 15763047 0 0 0.0 0 +chrX 15972990 0 0 0.0 0 +chrX 16002529 0 0 0.0 0 +chrX 16002948 0 0 0.0 0 +chrX 16471335 0 1 0.0233 0 +chrX 16493618 0 0 0.0 0 +chrX 16555102 0 0 0.0 0 +chrX 16652864 0 0 0.0 0 +chrX 16722945 0 0 0.0 0 +chrX 16762762 0 0 0.0 0 +chrX 16819192 0 0 0.0 0 +chrX 16938240 0 0 0.0 0 +chrX 17042864 0 0 0.0 0 +chrX 17145034 0 0 0.0 0 +chrX 17160896 0 0 0.0 0 +chrX 17283921 0 0 0.0 0 +chrX 17535173 0 0 0.0 0 +chrX 17544428 0 1 0.0263 0 +chrX 17567106 0 0 0.0 0 +chrX 17755368 0 0 0.0 0 +chrX 17779713 0 1 0.0222 0 +chrX 17818905 0 0 0.0 0 +chrX 17929631 0 0 0.0 0 +chrX 17985000 0 0 0.0 0 +chrX 18061482 0 1 0.0185 0 +chrX 18234241 0 0 0.0 0 +chrX 18595369 0 0 0.0 0 +chrX 18721091 0 0 0.0 0 +chrX 18728592 0 0 0.0 0 +chrX 18751456 0 0 0.0 0 +chrX 18876398 0 0 0.0 0 +chrX 19087437 0 0 0.0 0 +chrX 19138944 0 0 0.0 0 +chrX 19321416 0 0 0.0 0 +chrX 19823515 0 0 0.0 0 +chrX 19856350 0 0 0.0 0 +chrX 20217462 0 0 0.0 0 +chrX 20261384 0 0 0.0 0 +chrX 20408612 0 0 0.0 0 +chrX 20726280 0 0 0.0 0 +chrX 20875049 0 0 0.0 0 +chrX 21019493 0 0 0.0 0 +chrX 21077712 0 0 0.0 0 +chrX 21085812 0 0 0.0 0 +chrX 21141286 0 0 0.0 0 +chrX 21349047 0 0 0.0 0 +chrX 21376681 0 0 0.0 0 +chrX 21571916 0 0 0.0 0 +chrX 22234636 0 0 0.0 0 +chrX 22238560 0 0 0.0 0 +chrX 22243977 0 0 0.0 0 +chrX 22419316 0 0 0.0 0 +chrX 22482689 0 0 0.0 0 +chrX 22525143 0 0 0.0 0 +chrX 22680610 0 0 0.0 0 +chrX 22966070 0 0 0.0 0 +chrX 23001065 0 0 0.0 0 +chrX 23039404 0 0 0.0 0 +chrX 23066125 0 0 0.0 0 +chrX 23352620 0 0 0.0 0 +chrX 23450271 0 0 0.0 0 +chrX 23512870 0 0 0.0 0 +chrX 23703858 0 0 0.0 0 +chrX 23870410 0 0 0.0 0 +chrX 24095450 0 0 0.0 0 +chrX 24481981 0 0 0.0 0 +chrX 24621885 0 0 0.0 0 +chrX 24650073 0 0 0.0 0 +chrX 24797606 0 0 0.0 0 +chrX 25040040 0 0 0.0 0 +chrX 25047738 0 0 0.0 0 +chrX 25247372 0 0 0.0 0 +chrX 25432522 0 0 0.0 0 +chrX 25443176 0 0 0.0 0 +chrX 25704982 0 0 0.0 0 +chrX 25781433 0 0 0.0 0 +chrX 25872520 0 0 0.0 0 +chrX 25897264 0 0 0.0 0 +chrX 25968769 0 0 0.0 0 +chrX 25984034 0 0 0.0 0 +chrX 26044482 0 0 0.0 0 +chrX 26144096 0 0 0.0 0 +chrX 26163902 0 0 0.0 0 +chrX 26197124 0 0 0.0 0 +chrX 26783976 0 1 0.0278 0 +chrX 27253551 0 0 0.0 0 +chrX 27638225 0 0 0.0 0 +chrX 27734322 0 0 0.0 0 +chrX 27754666 0 0 0.0 0 +chrX 28034256 0 0 0.0 0 +chrX 28036252 0 0 0.0 0 +chrX 28045538 0 0 0.0 0 +chrX 28145318 0 0 0.0 0 +chrX 28172389 0 0 0.0 0 +chrX 28306652 0 0 0.0 0 +chrX 28675346 0 0 0.0 0 +chrX 28852751 0 0 0.0 0 +chrX 28868502 0 0 0.0 0 +chrX 29290854 0 0 0.0 0 +chrX 29348264 0 0 0.0 0 +chrX 29610600 0 0 0.0 0 +chrX 29838907 0 0 0.0 0 +chrX 30277259 0 0 0.0 0 +chrX 30285351 0 0 0.0 0 +chrX 30489746 0 0 0.0 0 +chrX 31011395 0 0 0.0 0 +chrX 31112188 0 0 0.0 0 +chrX 31249175 0 0 0.0 0 +chrX 31505319 0 0 0.0 0 +chrX 31589287 0 0 0.0 0 +chrX 31741447 0 0 0.0 0 +chrX 31873865 0 0 0.0 0 +chrX 31911161 0 0 0.0 0 +chrX 31940190 0 0 0.0 0 +chrX 32593131 0 0 0.0 0 +chrX 32624650 0 0 0.0 0 +chrX 33485347 0 0 0.0 0 +chrX 33551920 0 0 0.0 0 +chrX 33619568 0 0 0.0 0 +chrX 34019380 0 0 0.0 0 +chrX 34241963 0 0 0.0 0 +chrX 34408205 0 0 0.0 0 +chrX 34620425 0 0 0.0 0 +chrX 35321322 0 0 0.0 0 +chrX 35986017 0 0 0.0 0 +chrX 35987479 0 0 0.0 0 +chrX 36210670 0 0 0.0 0 +chrX 36478403 0 0 0.0 0 +chrX 36555519 0 0 0.0 0 +chrX 36564810 0 0 0.0 0 +chrX 36607233 0 0 0.0 0 +chrX 36928785 0 0 0.0 0 +chrX 37025543 0 0 0.0 0 +chrX 37058947 0 0 0.0 0 +chrX 37064790 0 0 0.0 0 +chrX 37319935 0 0 0.0 0 +chrX 37467924 0 0 0.0 0 +chrX 37497327 0 0 0.0 0 +chrX 37642404 0 0 0.0 0 +chrX 37868113 0 0 0.0 0 +chrX 37933249 0 0 0.0 0 +chrX 38038104 0 0 0.0 0 +chrX 38141240 0 0 0.0 0 +chrX 38392843 0 0 0.0 0 +chrX 38404879 0 0 0.0 0 +chrX 38673339 1 18 0.75 1 +chrX 38701616 0 0 0.0 0 +chrX 38861595 0 0 0.0 0 +chrX 38871646 0 0 0.0 0 +chrX 39089098 0 0 0.0 0 +chrX 39131276 0 0 0.0 0 +chrX 39380913 0 0 0.0 0 +chrX 39482788 0 0 0.0 0 +chrX 39519855 0 0 0.0 0 +chrX 39524659 0 0 0.0 0 +chrX 39603527 0 0 0.0 0 +chrX 39730181 0 0 0.0 0 +chrX 39803584 0 0 0.0 0 +chrX 39810716 0 0 0.0 0 +chrX 39866143 0 0 0.0 0 +chrX 39959088 0 0 0.0 0 +chrX 40096661 0 0 0.0 0 +chrX 40111901 0 0 0.0 0 +chrX 40142977 0 0 0.0 0 +chrX 40158700 0 0 0.0 0 +chrX 40239147 0 0 0.0 0 +chrX 40298989 0 0 0.0 0 +chrX 40299537 0 0 0.0 0 +chrX 40410765 0 0 0.0 0 +chrX 40417768 0 0 0.0 0 +chrX 40588493 0 0 0.0 0 +chrX 40645413 0 0 0.0 0 +chrX 41300104 0 0 0.0 0 +chrX 41312510 0 0 0.0 0 +chrX 41624161 0 0 0.0 0 +chrX 41657958 0 0 0.0 0 +chrX 41799568 0 0 0.0 0 +chrX 41877175 0 0 0.0 0 +chrX 42244901 0 0 0.0 0 +chrX 42330276 0 0 0.0 0 +chrX 42374724 0 0 0.0 0 +chrX 42375871 0 0 0.0 0 +chrX 42409421 0 0 0.0 0 +chrX 42681891 0 0 0.0 0 +chrX 42716992 0 0 0.0 0 +chrX 42756362 0 0 0.0 0 +chrX 43513050 0 0 0.0 0 +chrX 43839565 0 0 0.0 0 +chrX 44032513 0 0 0.0 0 +chrX 44168692 0 0 0.0 0 +chrX 44302376 0 0 0.0 0 +chrX 44366784 0 0 0.0 0 +chrX 44469822 0 0 0.0 0 +chrX 44986855 0 0 0.0 0 +chrX 45066854 0 0 0.0 0 +chrX 45099278 0 2 0.0571 0 +chrX 45411537 0 0 0.0 0 +chrX 45451716 0 0 0.0 0 +chrX 45663563 0 0 0.0 0 +chrX 46419864 0 0 0.0 0 +chrX 46611878 0 0 0.0 0 +chrX 46715639 0 0 0.0 0 +chrX 46766125 0 0 0.0 0 +chrX 47091073 0 0 0.0 0 +chrX 47270993 0 0 0.0 0 +chrX 47300290 1 7 0.3043 1 +chrX 47413708 0 0 0.0 0 +chrX 47595926 0 0 0.0 0 +chrX 47663924 0 0 0.0 0 +chrX 47674889 0 0 0.0 0 +chrX 47896846 0 0 0.0 0 +chrX 47983304 0 0 0.0 0 +chrX 48508471 0 0 0.0 0 +chrX 48576162 0 0 0.0 0 +chrX 48691027 0 0 0.0 0 +chrX 49005580 0 0 0.0 0 +chrX 49149077 0 0 0.0 0 +chrX 49165889 0 0 0.0 0 +chrX 49191380 0 1 0.0227 0 +chrX 49215558 0 0 0.0 0 +chrX 49287163 0 0 0.0 0 +chrX 49299881 0 0 0.0 0 +chrX 49633295 0 0 0.0 0 +chrX 49702987 0 0 0.0 0 +chrX 49793588 0 0 0.0 0 +chrX 49845563 0 0 0.0 0 +chrX 49880643 0 0 0.0 0 +chrX 50156349 0 0 0.0 0 +chrX 50160359 0 0 0.0 0 +chrX 50491986 0 0 0.0 0 +chrX 50528871 0 0 0.0 0 +chrX 50587966 0 0 0.0 0 +chrX 50713609 0 0 0.0 0 +chrX 50765161 0 0 0.0 0 +chrX 50973192 0 0 0.0 0 +chrX 51037118 0 0 0.0 0 +chrX 51126077 0 0 0.0 0 +chrX 51157085 0 0 0.0 0 +chrX 51368737 0 0 0.0 0 +chrX 51684541 0 0 0.0 0 +chrX 51708802 0 0 0.0 0 +chrX 52049022 0 0 0.0 0 +chrX 52051209 0 0 0.0 0 +chrX 52062595 0 0 0.0 0 +chrX 52107051 0 0 0.0 0 +chrX 52108753 0 0 0.0 0 +chrX 52121112 0 0 0.0 0 +chrX 52191501 0 0 0.0 0 +chrX 52202887 0 0 0.0 0 +chrX 52205074 0 0 0.0 0 +chrX 52335276 0 0 0.0 0 +chrX 52392238 0 0 0.0 0 +chrX 52478762 0 0 0.0 0 +chrX 52534126 0 0 0.0 0 +chrX 52555149 0 0 0.0 0 +chrX 52581697 0 0 0.0 0 +chrX 52593679 0 0 0.0 0 +chrX 52834472 0 0 0.0 0 +chrX 52851346 0 0 0.0 0 +chrX 52889886 0 0 0.0 0 +chrX 52916236 0 0 0.0 0 +chrX 52939579 0 0 0.0 0 +chrX 52965928 0 0 0.0 0 +chrX 53049448 0 0 0.0 0 +chrX 53084550 0 0 0.0 0 +chrX 53175647 0 0 0.0 0 +chrX 53374740 0 0 0.0 0 +chrX 53733448 0 0 0.0 0 +chrX 53794216 0 0 0.0 0 +chrX 53814038 0 0 0.0 0 +chrX 53962985 0 0 0.0 0 +chrX 54286568 0 0 0.0 0 +chrX 54553359 0 0 0.0 0 +chrX 54597228 0 0 0.0 0 +chrX 54645713 0 0 0.0 0 +chrX 54660866 0 0 0.0 0 +chrX 54934377 0 0 0.0 0 +chrX 55007140 0 0 0.0 0 +chrX 55170312 0 0 0.0 0 +chrX 55305588 0 0 0.0 0 +chrX 55338629 0 0 0.0 0 +chrX 55344525 0 0 0.0 0 +chrX 55564660 0 0 0.0 0 +chrX 55645813 0 0 0.0 0 +chrX 55811559 0 0 0.0 0 +chrX 55934900 0 0 0.0 0 +chrX 56029422 0 0 0.0 0 +chrX 56228666 0 0 0.0 0 +chrX 56587732 0 0 0.0 0 +chrX 56659022 0 0 0.0 0 +chrX 56844443 0 0 0.0 0 +chrX 56912681 0 0 0.0 0 +chrX 57030334 0 0 0.0 0 +chrX 57211576 0 0 0.0 0 +chrX 57348175 0 0 0.0 0 +chrX 57386400 0 0 0.0 0 +chrX 57401842 0 0 0.0 0 +chrX 57404019 0 0 0.0 0 +chrX 57864038 0 0 0.0 0 +chrX 57871797 0 0 0.0 0 +chrX 57889298 0 0 0.0 0 +chrX 57964594 0 0 0.0 0 +chrX 57988549 0 0 0.0 0 +chrX 58044612 0 0 0.0 0 +chrX 58245246 0 0 0.0 0 +chrX 58406190 0 0 0.0 0 +chrX 58412330 0 0 0.0 0 +chrX 58459233 0 0 0.0 0 +chrX 62529304 0 0 0.0 0 +chrX 62556311 0 0 0.0 0 +chrX 62812704 0 0 0.0 0 +chrX 63451643 0 0 0.0 0 +chrX 63577333 0 0 0.0 0 +chrX 63707483 0 0 0.0 0 +chrX 63741899 0 0 0.0 0 +chrX 63910217 0 0 0.0 0 +chrX 63965592 0 0 0.0 0 +chrX 63992600 0 0 0.0 0 +chrX 64191350 0 0 0.0 0 +chrX 64192374 0 0 0.0 0 +chrX 64208919 0 0 0.0 0 +chrX 64315213 0 0 0.0 0 +chrX 64327957 0 0 0.0 0 +chrX 64433503 0 0 0.0 0 +chrX 64451380 0 0 0.0 0 +chrX 64702475 0 0 0.0 0 +chrX 64729635 0 0 0.0 0 +chrX 64741301 0 0 0.0 0 +chrX 64919096 0 0 0.0 0 +chrX 64945950 0 0 0.0 0 +chrX 65084633 0 0 0.0 0 +chrX 65419174 0 0 0.0 0 +chrX 65714209 0 0 0.0 0 +chrX 65745859 0 0 0.0 0 +chrX 65819553 0 0 0.0 0 +chrX 65837589 0 0 0.0 0 +chrX 66024091 0 0 0.0 0 +chrX 66107613 0 0 0.0 0 +chrX 66127091 0 0 0.0 0 +chrX 66131165 0 0 0.0 0 +chrX 66191531 0 0 0.0 0 +chrX 66405371 0 0 0.0 0 +chrX 66832526 0 0 0.0 0 +chrX 67236819 0 0 0.0 0 +chrX 67509481 0 0 0.0 0 +chrX 67768841 0 0 0.0 0 +chrX 67864607 0 0 0.0 0 +chrX 68271756 0 0 0.0 0 +chrX 68289540 0 0 0.0 0 +chrX 68696992 0 0 0.0 0 +chrX 68716074 0 0 0.0 0 +chrX 68917408 0 0 0.0 0 +chrX 68988638 0 0 0.0 0 +chrX 69077336 0 0 0.0 0 +chrX 69351624 0 0 0.0 0 +chrX 69428412 0 0 0.0 0 +chrX 69474619 0 0 0.0 0 +chrX 69554324 0 0 0.0 0 +chrX 69648424 0 0 0.0 0 +chrX 69702639 0 0 0.0 0 +chrX 69829443 0 0 0.0 0 +chrX 70135634 0 0 0.0 0 +chrX 70206481 0 0 0.0 0 +chrX 70468047 0 0 0.0 0 +chrX 70483689 0 0 0.0 0 +chrX 70491574 0 0 0.0 0 +chrX 70508201 0 0 0.0 0 +chrX 70579421 0 0 0.0 0 +chrX 70636502 0 0 0.0 0 +chrX 70687654 0 0 0.0 0 +chrX 70920517 0 0 0.0 0 +chrX 70997558 0 0 0.0 0 +chrX 71076765 0 0 0.0 0 +chrX 71170679 0 0 0.0 0 +chrX 71185187 0 0 0.0 0 +chrX 71187119 0 0 0.0 0 +chrX 71249052 0 0 0.0 0 +chrX 71386848 0 0 0.0 0 +chrX 71486183 0 0 0.0 0 +chrX 71538032 0 0 0.0 0 +chrX 71970759 0 0 0.0 0 +chrX 72007061 0 0 0.0 0 +chrX 72309551 0 0 0.0 0 +chrX 72348018 0 0 0.0 0 +chrX 72521843 0 0 0.0 0 +chrX 72782049 0 0 0.0 0 +chrX 72786645 0 0 0.0 0 +chrX 72913218 0 0 0.0 0 +chrX 72934179 0 0 0.0 0 +chrX 72938773 0 0 0.0 0 +chrX 73026915 0 0 0.0 0 +chrX 73140674 0 0 0.0 0 +chrX 73456205 0 0 0.0 0 +chrX 73497909 0 0 0.0 0 +chrX 73598182 0 0 0.0 0 +chrX 73669316 0 0 0.0 0 +chrX 73873017 0 0 0.0 0 +chrX 74207485 0 0 0.0 0 +chrX 74324949 0 0 0.0 0 +chrX 74402600 0 0 0.0 0 +chrX 74507513 0 0 0.0 0 +chrX 74857496 0 0 0.0 0 +chrX 74915897 0 0 0.0 0 +chrX 75075699 0 0 0.0 0 +chrX 75297621 0 0 0.0 0 +chrX 75583614 0 0 0.0 0 +chrX 75764286 0 0 0.0 0 +chrX 75814490 0 0 0.0 0 +chrX 75903372 0 0 0.0 0 +chrX 76012434 0 0 0.0 0 +chrX 76025697 0 0 0.0 0 +chrX 76169199 0 0 0.0 0 +chrX 76233937 0 0 0.0 0 +chrX 76279242 0 0 0.0 0 +chrX 76671325 0 0 0.0 0 +chrX 76998849 0 0 0.0 0 +chrX 77007285 0 0 0.0 0 +chrX 77060776 0 0 0.0 0 +chrX 77411910 0 0 0.0 0 +chrX 77454011 0 0 0.0 0 +chrX 77616889 0 0 0.0 0 +chrX 77876268 0 0 0.0 0 +chrX 78086286 0 0 0.0 0 +chrX 78179870 0 0 0.0 0 +chrX 78216622 0 0 0.0 0 +chrX 78232373 0 0 0.0 0 +chrX 78692745 0 0 0.0 0 +chrX 78747118 0 0 0.0 0 +chrX 79013300 0 0 0.0 0 +chrX 79232607 0 0 0.0 0 +chrX 79632242 0 0 0.0 0 +chrX 79828105 0 0 0.0 0 +chrX 79936572 0 1 0.0233 0 +chrX 79975823 0 0 0.0 0 +chrX 80026288 0 0 0.0 0 +chrX 80043214 0 0 0.0 0 +chrX 80083930 0 0 0.0 0 +chrX 80320131 0 0 0.0 0 +chrX 80646342 0 0 0.0 0 +chrX 80776880 0 0 0.0 0 +chrX 80874585 0 0 0.0 0 +chrX 80903248 0 0 0.0 0 +chrX 81047111 0 0 0.0 0 +chrX 81173963 0 1 0.0233 0 +chrX 81264849 0 0 0.0 0 +chrX 81270990 0 0 0.0 0 +chrX 81323883 0 0 0.0 0 +chrX 81567322 0 0 0.0 0 +chrX 81931229 0 0 0.0 0 +chrX 81996302 0 0 0.0 0 +chrX 82149416 0 0 0.0 0 +chrX 82166630 0 0 0.0 0 +chrX 82445889 0 0 0.0 0 +chrX 82593468 0 0 0.0 0 +chrX 82713154 0 0 0.0 0 +chrX 82797513 0 0 0.0 0 +chrX 83113007 0 0 0.0 0 +chrX 83181887 1 3 0.0667 1 +chrX 83225289 0 0 0.0 0 +chrX 83670376 0 0 0.0 0 +chrX 84085441 0 0 0.0 0 +chrX 84226456 0 0 0.0 0 +chrX 84391914 0 0 0.0 0 +chrX 84582991 1 12 0.3529 1 +chrX 84873181 0 0 0.0 0 +chrX 85241407 0 0 0.0 0 +chrX 85370708 0 0 0.0 0 +chrX 85958863 0 0 0.0 0 +chrX 86026164 0 0 0.0 0 +chrX 86156297 0 0 0.0 0 +chrX 86188378 0 0 0.0 0 +chrX 86278834 0 0 0.0 0 +chrX 86487329 0 0 0.0 0 +chrX 86626789 0 0 0.0 0 +chrX 86785178 0 0 0.0 0 +chrX 86997847 0 0 0.0 0 +chrX 87123726 0 0 0.0 0 +chrX 87569019 0 0 0.0 0 +chrX 87735619 0 0 0.0 0 +chrX 87753679 0 0 0.0 0 +chrX 88639183 0 0 0.0 0 +chrX 88828331 0 0 0.0 0 +chrX 89636627 0 0 0.0 0 +chrX 89768014 0 1 0.1667 0 +chrX 89815977 0 0 0.0 0 +chrX 89842532 0 0 0.0 0 +chrX 90084853 0 0 0.0 0 +chrX 90124991 0 0 0.0 0 +chrX 90204260 0 0 0.0 0 +chrX 90278663 0 0 0.0 0 +chrX 90378286 0 0 0.0 0 +chrX 90404422 0 0 0.0 0 +chrX 90427894 0 0 0.0 0 +chrX 90472712 0 0 0.0 0 +chrX 90665486 0 0 0.0 0 +chrX 90914957 0 0 0.0 0 +chrX 90936321 0 0 0.0 0 +chrX 90983599 0 0 0.0 0 +chrX 91111147 0 0 0.0 0 +chrX 91167199 0 0 0.0 0 +chrX 91212865 0 0 0.0 0 +chrX 91285450 0 0 0.0 0 +chrX 91384133 0 0 0.0 0 +chrX 91602964 0 0 0.0 0 +chrX 92005785 0 0 0.0 0 +chrX 92019258 0 0 0.0 0 +chrX 92615503 0 0 0.0 0 +chrX 92701369 0 0 0.0 0 +chrX 92716400 0 0 0.0 0 +chrX 93260433 0 0 0.0 0 +chrX 93372968 0 0 0.0 0 +chrX 93431621 0 0 0.0 0 +chrX 93616354 0 0 0.0 0 +chrX 93804241 0 0 0.0 0 +chrX 93854404 0 0 0.0 0 +chrX 93931764 0 0 0.0 0 +chrX 94125332 0 0 0.0 0 +chrX 94230761 0 0 0.0 0 +chrX 94369317 0 0 0.0 0 +chrX 94669596 0 0 0.0 0 +chrX 94702370 0 0 0.0 0 +chrX 94729956 0 0 0.0 0 +chrX 94777000 0 0 0.0 0 +chrX 94823366 0 0 0.0 0 +chrX 95239749 0 0 0.0 0 +chrX 95321718 0 0 0.0 0 +chrX 95322134 0 0 0.0 0 +chrX 95403710 0 0 0.0 0 +chrX 95555187 0 0 0.0 0 +chrX 95887340 0 0 0.0 0 +chrX 96084789 0 0 0.0 0 +chrX 96196717 0 0 0.0 0 +chrX 96270253 0 0 0.0 0 +chrX 96342970 0 0 0.0 0 +chrX 96383889 0 0 0.0 0 +chrX 96475078 0 0 0.0 0 +chrX 96533557 0 0 0.0 0 +chrX 96688728 0 0 0.0 0 +chrX 96702793 0 0 0.0 0 +chrX 97906003 0 0 0.0 0 +chrX 98210566 0 0 0.0 0 +chrX 98240709 0 0 0.0 0 +chrX 98325028 0 0 0.0 0 +chrX 98390052 0 0 0.0 0 +chrX 98397467 0 0 0.0 0 +chrX 98400306 0 0 0.0 0 +chrX 98415863 0 0 0.0 0 +chrX 98679034 0 0 0.0 0 +chrX 99119323 0 0 0.0 0 +chrX 99147182 0 0 0.0 0 +chrX 99162988 0 0 0.0 0 +chrX 99187762 0 0 0.0 0 +chrX 99208918 0 0 0.0 0 +chrX 99269801 0 1 0.0227 0 +chrX 99425569 0 0 0.0 0 +chrX 99468776 0 0 0.0 0 +chrX 99618002 0 0 0.0 0 +chrX 99950367 0 0 0.0 0 +chrX 100080832 0 0 0.0 0 +chrX 100214643 0 0 0.0 0 +chrX 100236334 0 0 0.0 0 +chrX 100402591 0 0 0.0 0 +chrX 100720488 0 1 0.0167 0 +chrX 101034438 0 0 0.0 0 +chrX 101037990 0 0 0.0 0 +chrX 101196215 0 0 0.0 0 +chrX 101386794 0 0 0.0 0 +chrX 101441125 0 0 0.0 0 +chrX 101551731 0 0 0.0 0 +chrX 101698615 0 0 0.0 0 +chrX 101783840 0 0 0.0 0 +chrX 101992118 0 0 0.0 0 +chrX 102004823 0 0 0.0 0 +chrX 102044019 0 0 0.0 0 +chrX 102224779 0 0 0.0 0 +chrX 102260031 0 0 0.0 0 +chrX 102281383 0 0 0.0 0 +chrX 102405733 0 0 0.0 0 +chrX 102427091 0 0 0.0 0 +chrX 102462331 0 0 0.0 0 +chrX 102490410 0 0 0.0 0 +chrX 102698245 0 0 0.0 0 +chrX 102699525 0 0 0.0 0 +chrX 103380280 0 0 0.0 0 +chrX 103642124 0 0 0.0 0 +chrX 103727268 0 0 0.0 0 +chrX 104115475 0 0 0.0 0 +chrX 104160185 0 0 0.0 0 +chrX 104534265 0 0 0.0 0 +chrX 104562187 0 0 0.0 0 +chrX 104924285 0 0 0.0 0 +chrX 105140851 0 0 0.0 0 +chrX 105158283 0 0 0.0 0 +chrX 105259233 0 0 0.0 0 +chrX 105413376 0 0 0.0 0 +chrX 105418464 0 0 0.0 0 +chrX 105465223 0 0 0.0 0 +chrX 105466012 0 0 0.0 0 +chrX 105492138 0 0 0.0 0 +chrX 105625831 1 25 0.8929 1 +chrX 105631455 0 0 0.0 0 +chrX 105668291 0 0 0.0 0 +chrX 105685269 0 0 0.0 0 +chrX 106072401 0 0 0.0 0 +chrX 106099787 0 0 0.0 0 +chrX 106184293 0 0 0.0 0 +chrX 106330347 0 0 0.0 0 +chrX 106363935 0 0 0.0 0 +chrX 106393032 0 0 0.0 0 +chrX 106402524 0 0 0.0 0 +chrX 106525640 0 0 0.0 0 +chrX 107014209 0 0 0.0 0 +chrX 107134582 0 0 0.0 0 +chrX 107268080 0 0 0.0 0 +chrX 107272602 0 0 0.0 0 +chrX 107520397 0 0 0.0 0 +chrX 107570659 0 0 0.0 0 +chrX 108017288 0 0 0.0 0 +chrX 108168837 0 0 0.0 0 +chrX 108480755 0 0 0.0 0 +chrX 108674877 0 0 0.0 0 +chrX 108687252 0 0 0.0 0 +chrX 108766245 0 0 0.0 0 +chrX 108807625 0 0 0.0 0 +chrX 108816973 0 0 0.0 0 +chrX 108970155 0 0 0.0 0 +chrX 109286769 0 0 0.0 0 +chrX 109337716 0 0 0.0 0 +chrX 109472403 0 0 0.0 0 +chrX 109594247 0 0 0.0 0 +chrX 109624439 0 0 0.0 0 +chrX 109800553 0 0 0.0 0 +chrX 109848424 0 0 0.0 0 +chrX 109928726 0 0 0.0 0 +chrX 109976052 0 0 0.0 0 +chrX 110332806 0 0 0.0 0 +chrX 110407625 0 0 0.0 0 +chrX 110543210 0 0 0.0 0 +chrX 110627169 0 0 0.0 0 +chrX 110754543 0 0 0.0 0 +chrX 110948549 0 0 0.0 0 +chrX 110986965 0 0 0.0 0 +chrX 111056301 0 0 0.0 0 +chrX 111281066 0 0 0.0 0 +chrX 111354282 0 0 0.0 0 +chrX 111399235 0 2 0.05 0 +chrX 111435001 0 0 0.0 0 +chrX 111630618 0 0 0.0 0 +chrX 111823285 0 0 0.0 0 +chrX 112006212 0 0 0.0 0 +chrX 112020574 0 0 0.0 0 +chrX 112054346 0 0 0.0 0 +chrX 112187075 0 0 0.0 0 +chrX 112279844 0 0 0.0 0 +chrX 112315581 0 0 0.0 0 +chrX 112468290 0 0 0.0 0 +chrX 112814514 0 0 0.0 0 +chrX 113480137 0 0 0.0 0 +chrX 113558800 0 0 0.0 0 +chrX 113668281 0 0 0.0 0 +chrX 113716315 0 0 0.0 0 +chrX 113849888 0 1 0.027 0 +chrX 114066014 0 0 0.0 0 +chrX 114555579 0 0 0.0 0 +chrX 114579735 0 0 0.0 0 +chrX 114943083 0 0 0.0 0 +chrX 114964131 0 0 0.0 0 +chrX 115009187 1 24 0.8889 1 +chrX 115064597 0 0 0.0 0 +chrX 115072507 0 0 0.0 0 +chrX 115196883 0 0 0.0 0 +chrX 115325838 0 0 0.0 0 +chrX 115421794 0 0 0.0 0 +chrX 115495302 0 0 0.0 0 +chrX 115935077 0 0 0.0 0 +chrX 116266010 0 0 0.0 0 +chrX 116407622 0 0 0.0 0 +chrX 116546212 0 0 0.0 0 +chrX 116667887 0 1 0.0213 0 +chrX 117268641 0 0 0.0 0 +chrX 117269217 0 0 0.0 0 +chrX 117690616 0 0 0.0 0 +chrX 117864907 0 0 0.0 0 +chrX 118075551 0 0 0.0 0 +chrX 118233421 0 0 0.0 0 +chrX 118312507 0 0 0.0 0 +chrX 118465187 0 0 0.0 0 +chrX 118492202 0 0 0.0 0 +chrX 118572969 0 0 0.0 0 +chrX 118670067 0 0 0.0 0 +chrX 118676125 0 0 0.0 0 +chrX 118756252 0 0 0.0 0 +chrX 118826614 0 0 0.0 0 +chrX 118878320 0 1 0.0217 0 +chrX 118949975 0 0 0.0 0 +chrX 119068403 0 0 0.0 0 +chrX 119140003 0 0 0.0 0 +chrX 119167842 0 0 0.0 0 +chrX 119593762 0 0 0.0 0 +chrX 119854916 0 0 0.0 0 +chrX 119903536 0 0 0.0 0 +chrX 119972182 0 0 0.0 0 +chrX 120294043 0 0 0.0 0 +chrX 120636872 0 0 0.0 0 +chrX 120708374 0 0 0.0 0 +chrX 121017406 0 0 0.0 0 +chrX 121232059 0 0 0.0 0 +chrX 121260169 0 0 0.0 0 +chrX 121990588 0 0 0.0 0 +chrX 122029776 0 1 0.0286 0 +chrX 122045619 0 0 0.0 0 +chrX 122346931 0 0 0.0 0 +chrX 122441450 3 47 0.94 1 +chrX 122722877 0 0 0.0 0 +chrX 123016676 0 0 0.0 0 +chrX 123085878 0 0 0.0 0 +chrX 123107153 0 0 0.0 0 +chrX 123127510 0 0 0.0 0 +chrX 123136275 0 0 0.0 0 +chrX 123643093 0 0 0.0 0 +chrX 123776408 0 0 0.0 0 +chrX 123790950 0 0 0.0 0 +chrX 123807805 0 0 0.0 0 +chrX 123824207 0 0 0.0 0 +chrX 124095508 0 0 0.0 0 +chrX 124151215 0 0 0.0 0 +chrX 124282800 0 0 0.0 0 +chrX 124607627 0 0 0.0 0 +chrX 125134155 0 0 0.0 0 +chrX 125187658 0 0 0.0 0 +chrX 125284915 0 0 0.0 0 +chrX 125372620 0 0 0.0 0 +chrX 125416584 0 0 0.0 0 +chrX 125638741 0 0 0.0 0 +chrX 125656374 0 0 0.0 0 +chrX 125681278 0 0 0.0 0 +chrX 126034430 0 0 0.0 0 +chrX 126123354 0 0 0.0 0 +chrX 126141882 0 0 0.0 0 +chrX 126184715 0 0 0.0 0 +chrX 126666257 0 0 0.0 0 +chrX 126815760 0 0 0.0 0 +chrX 126816951 0 0 0.0 0 +chrX 127017742 0 0 0.0 0 +chrX 127025879 0 0 0.0 0 +chrX 127059981 0 0 0.0 0 +chrX 127249784 0 0 0.0 0 +chrX 127392716 0 0 0.0 0 +chrX 127565634 0 0 0.0 0 +chrX 127856525 0 0 0.0 0 +chrX 128172297 0 0 0.0 0 +chrX 128607000 0 0 0.0 0 +chrX 128686309 0 0 0.0 0 +chrX 129227275 0 0 0.0 0 +chrX 129364089 0 0 0.0 0 +chrX 129441206 0 0 0.0 0 +chrX 129747527 0 0 0.0 0 +chrX 129813819 0 0 0.0 0 +chrX 129957075 0 0 0.0 0 +chrX 130027033 0 0 0.0 0 +chrX 130081652 0 0 0.0 0 +chrX 130408677 0 0 0.0 0 +chrX 130528019 0 0 0.0 0 +chrX 130696886 0 0 0.0 0 +chrX 130713576 0 0 0.0 0 +chrX 130718134 0 0 0.0 0 +chrX 130814035 0 0 0.0 0 +chrX 130838870 0 0 0.0 0 +chrX 130900047 0 0 0.0 0 +chrX 130920632 0 0 0.0 0 +chrX 130988265 0 0 0.0 0 +chrX 131171810 0 0 0.0 0 +chrX 131180540 0 0 0.0 0 +chrX 131230368 0 0 0.0 0 +chrX 131415226 0 0 0.0 0 +chrX 131429117 0 0 0.0 0 +chrX 131560088 0 0 0.0 0 +chrX 131980902 0 0 0.0 0 +chrX 132084688 0 0 0.0 0 +chrX 132181406 0 0 0.0 0 +chrX 132260049 0 0 0.0 0 +chrX 132658893 0 0 0.0 0 +chrX 132750954 0 0 0.0 0 +chrX 132838308 0 0 0.0 0 +chrX 133096665 0 0 0.0 0 +chrX 133292726 0 0 0.0 0 +chrX 133332632 0 0 0.0 0 +chrX 133781823 0 0 0.0 0 +chrX 133994955 0 0 0.0 0 +chrX 134098958 0 0 0.0 0 +chrX 134222719 0 0 0.0 0 +chrX 134460897 0 0 0.0 0 +chrX 134962392 0 0 0.0 0 +chrX 135142167 0 0 0.0 0 +chrX 135230371 0 0 0.0 0 +chrX 135424177 0 0 0.0 0 +chrX 135436901 0 0 0.0 0 +chrX 136429530 0 0 0.0 0 +chrX 136433596 0 0 0.0 0 +chrX 136454464 1 4 0.0952 1 +chrX 136530891 0 0 0.0 0 +chrX 136794000 0 0 0.0 0 +chrX 136795601 0 0 0.0 0 +chrX 137115103 0 0 0.0 0 +chrX 137310761 0 0 0.0 0 +chrX 137453273 0 0 0.0 0 +chrX 137520787 0 0 0.0 0 +chrX 137562783 0 0 0.0 0 +chrX 137627589 0 0 0.0 0 +chrX 137758434 0 0 0.0 0 +chrX 137792882 0 0 0.0 0 +chrX 138240063 0 0 0.0 0 +chrX 138456709 0 0 0.0 0 +chrX 138752680 0 1 0.0256 0 +chrX 138850312 0 0 0.0 0 +chrX 138996478 0 0 0.0 0 +chrX 139002859 0 0 0.0 0 +chrX 139238259 0 0 0.0 0 +chrX 139282560 0 0 0.0 0 +chrX 139417540 0 0 0.0 0 +chrX 139476683 0 0 0.0 0 +chrX 139657003 0 0 0.0 0 +chrX 139723482 0 0 0.0 0 +chrX 139738006 0 0 0.0 0 +chrX 139927655 0 0 0.0 0 +chrX 140187030 0 0 0.0 0 +chrX 140415387 0 0 0.0 0 +chrX 140416623 0 0 0.0 0 +chrX 140432032 0 0 0.0 0 +chrX 140459246 0 0 0.0 0 +chrX 140466331 0 0 0.0 0 +chrX 140751953 0 0 0.0 0 +chrX 140829413 0 0 0.0 0 +chrX 141061494 0 0 0.0 0 +chrX 141271715 0 0 0.0 0 +chrX 141373397 0 0 0.0 0 +chrX 141383980 0 0 0.0 0 +chrX 141525919 0 0 0.0 0 +chrX 141604974 0 0 0.0 0 +chrX 141624877 0 0 0.0 0 +chrX 142116037 0 0 0.0 0 +chrX 142167260 0 0 0.0 0 +chrX 142199255 0 0 0.0 0 +chrX 142267970 0 0 0.0 0 +chrX 142521751 0 0 0.0 0 +chrX 142760423 0 0 0.0 0 +chrX 143176112 0 0 0.0 0 +chrX 143203122 0 0 0.0 0 +chrX 143409826 0 0 0.0 0 +chrX 143533481 0 0 0.0 0 +chrX 143726248 0 0 0.0 0 +chrX 143767530 0 0 0.0 0 +chrX 143980840 0 0 0.0 0 +chrX 144118553 0 0 0.0 0 +chrX 144500701 0 0 0.0 0 +chrX 144536221 0 0 0.0 0 +chrX 144773262 0 0 0.0 0 +chrX 144977777 0 0 0.0 0 +chrX 145037268 0 0 0.0 0 +chrX 145137975 0 0 0.0 0 +chrX 145281943 0 0 0.0 0 +chrX 145471451 0 0 0.0 0 +chrX 145562637 0 0 0.0 0 +chrX 145962892 0 0 0.0 0 +chrX 146206362 0 0 0.0 0 +chrX 146422622 0 0 0.0 0 +chrX 146677838 0 0 0.0 0 +chrX 147073976 0 1 0.0294 0 +chrX 147390482 0 0 0.0 0 +chrX 147542699 0 0 0.0 0 +chrX 147557013 0 0 0.0 0 +chrX 147856112 0 0 0.0 0 +chrX 147885088 0 0 0.0 0 +chrX 147929861 0 0 0.0 0 +chrX 147994239 0 0 0.0 0 +chrX 148095363 0 0 0.0 0 +chrX 148253745 0 0 0.0 0 +chrX 148571265 0 0 0.0 0 +chrX 148654909 0 0 0.0 0 +chrX 148689318 0 0 0.0 0 +chrX 148881581 0 0 0.0 0 +chrX 148898626 0 0 0.0 0 +chrX 148944350 0 0 0.0 0 +chrX 148999949 0 0 0.0 0 +chrX 149044707 0 0 0.0 0 +chrX 149118770 0 0 0.0 0 +chrX 149225288 0 0 0.0 0 +chrX 149232978 0 0 0.0 0 +chrX 149298689 0 0 0.0 0 +chrX 149344530 0 0 0.0 0 +chrX 149459501 0 0 0.0 0 +chrX 149496027 0 0 0.0 0 +chrX 149510036 0 0 0.0 0 +chrX 149533139 0 0 0.0 0 +chrX 149621138 0 0 0.0 0 +chrX 149903381 0 0 0.0 0 +chrX 149947091 0 0 0.0 0 +chrX 150027401 0 0 0.0 0 +chrX 150062669 0 1 0.037 0 +chrX 150093015 0 0 0.0 0 +chrX 150094393 0 1 0.0175 0 +chrX 150206656 0 0 0.0 0 +chrX 150453729 0 0 0.0 0 +chrX 150507636 0 0 0.0 0 +chrX 150632628 0 0 0.0 0 +chrX 150737430 0 0 0.0 0 +chrX 150794230 0 0 0.0 0 +chrX 150872978 0 0 0.0 0 +chrX 151022830 0 0 0.0 0 +chrX 151169143 0 0 0.0 0 +chrX 151282248 0 0 0.0 0 +chrX 151312244 0 0 0.0 0 +chrX 151353383 0 0 0.0 0 +chrX 151462940 0 0 0.0 0 +chrX 151737086 0 0 0.0 0 +chrX 151737253 0 0 0.0 0 +chrX 151799215 0 0 0.0 0 +chrX 151821237 0 0 0.0 0 +chrX 151977544 0 0 0.0 0 +chrX 151979042 0 0 0.0 0 +chrX 152203648 0 0 0.0 0 +chrX 152576010 0 0 0.0 0 +chrX 152595399 0 0 0.0 0 +chrX 152907820 0 0 0.0 0 +chrX 153106614 0 0 0.0 0 +chrX 153111269 0 0 0.0 0 +chrX 153288675 0 0 0.0 0 +chrX 153293330 0 0 0.0 0 +chrX 153491019 0 0 0.0 0 +chrX 153639551 0 0 0.0 0 +chrX 153714922 0 0 0.0 0 +chrX 153752748 0 0 0.0 0 +chrX 153773160 0 1 0.0196 0 +chrX 153817124 0 0 0.0 0 +chrX 153925295 0 0 0.0 0 +chrX 154351698 0 0 0.0 0 +chrX 154456309 0 0 0.0 0 +chrX 154467114 0 0 0.0 0 +chrX 154712496 0 0 0.0 0 +chrX 154747348 0 0 0.0 0 +chrX 154855637 0 0 0.0 0 +chrX 155007050 0 0 0.0 0 +chrX 155147879 0 0 0.0 0 +chrX 155242419 0 1 0.0278 0 +chrX 155260838 0 0 0.0 0 +chrX 155264234 0 0 0.0 0 +chrX 155310180 0 0 0.0 0 +chrX 155353102 0 0 0.0 0 +chrX 155368420 0 0 0.0 0 +chrX 155472830 0 0 0.0 0 +chrX 155488147 0 0 0.0 0 +chrX 155633451 0 0 0.0 0 +chrX 155755696 0 0 0.0 0 +chrX 155776164 0 0 0.0 0 +chrX 155910570 1 3 0.0526 1 +chrX 155999883 0 0 0.0 0 +chrX_KI270880v1_alt 39442 0 0 0.0 0 +chrX_KI270880v1_alt 69190 0 0 0.0 0 +chrX_KI270881v1_alt 53870 0 0 0.0 0 +chrX_KI270881v1_alt 70794 0 0 0.0 0 +chrX_KI270881v1_alt 133536 0 0 0.0 0 +chrX_KI270913v1_alt 28582 0 0 0.0 0 +chrX_KI270913v1_alt 58330 0 0 0.0 0 +chrY 20619 0 0 0.0 0 +chrY 282238 0 0 0.0 0 +chrY 356090 0 0 0.0 0 +chrY 370842 0 0 0.0 0 +chrY 385838 0 0 0.0 0 +chrY 461323 0 0 0.0 0 +chrY 651742 0 0 0.0 0 +chrY 658236 0 0 0.0 0 +chrY 788866 0 0 0.0 0 +chrY 792078 0 0 0.0 0 +chrY 831723 0 0 0.0 0 +chrY 833280 0 0 0.0 0 +chrY 884138 0 0 0.0 0 +chrY 936841 0 0 0.0 0 +chrY 1072125 0 0 0.0 0 +chrY 1114430 0 0 0.0 0 +chrY 1123555 0 0 0.0 0 +chrY 1138359 0 0 0.0 0 +chrY 1248383 0 0 0.0 0 +chrY 1444883 0 0 0.0 0 +chrY 1451010 0 0 0.0 0 +chrY 1510499 0 0 0.0 0 +chrY 1550070 0 0 0.0 0 +chrY 1574238 0 0 0.0 0 +chrY 1774953 0 0 0.0 0 +chrY 2192859 0 0 0.0 0 +chrY 2232322 0 0 0.0 0 +chrY 2256254 0 0 0.0 0 +chrY 2412345 0 0 0.0 0 +chrY 2679046 0 0 0.0 0 +chrY 3297999 0 0 0.0 0 +chrY 3415873 0 0 0.0 0 +chrY 3497322 0 0 0.0 0 +chrY 3650538 0 0 0.0 0 +chrY 3695102 0 0 0.0 0 +chrY 3773380 0 0 0.0 0 +chrY 3855431 0 0 0.0 0 +chrY 3955221 0 0 0.0 0 +chrY 4004855 0 0 0.0 0 +chrY 4023891 0 0 0.0 0 +chrY 4060823 0 0 0.0 0 +chrY 4110442 0 0 0.0 0 +chrY 4228458 0 0 0.0 0 +chrY 4247632 0 0 0.0 0 +chrY 4497879 0 0 0.0 0 +chrY 4512740 0 0 0.0 0 +chrY 4559038 0 0 0.0 0 +chrY 4676632 0 0 0.0 0 +chrY 4844207 0 0 0.0 0 +chrY 5230324 0 0 0.0 0 +chrY 5243818 0 0 0.0 0 +chrY 5647809 0 0 0.0 0 +chrY 5734507 0 0 0.0 0 +chrY 5818107 0 0 0.0 0 +chrY 5833093 0 0 0.0 0 +chrY 6399840 0 0 0.0 0 +chrY 6891376 0 0 0.0 0 +chrY 6996074 0 0 0.0 0 +chrY 7128444 0 0 0.0 0 +chrY 7199428 0 0 0.0 0 +chrY 7344915 0 0 0.0 0 +chrY 7625536 0 0 0.0 0 +chrY 7729720 0 0 0.0 0 +chrY 7956927 0 0 0.0 0 +chrY 8149159 0 0 0.0 0 +chrY 8276149 0 0 0.0 0 +chrY 8376998 0 0 0.0 0 +chrY 8495334 0 0 0.0 0 +chrY 8527085 0 0 0.0 0 +chrY 8629099 0 0 0.0 0 +chrY 8715408 0 0 0.0 0 +chrY 8773443 0 0 0.0 0 +chrY 8907608 0 0 0.0 0 +chrY 8912125 0 0 0.0 0 +chrY 8971316 0 0 0.0 0 +chrY 8976424 0 0 0.0 0 +chrY 9023842 0 0 0.0 0 +chrY 9300803 0 0 0.0 0 +chrY 9321788 0 0 0.0 0 +chrY 9623415 0 0 0.0 0 +chrY 9764881 0 0 0.0 0 +chrY 9935471 0 0 0.0 0 +chrY 9952638 0 0 0.0 0 +chrY 10057976 0 0 0.0 0 +chrY 10147855 0 0 0.0 0 +chrY 10182570 1 26 0.8966 1 +chrY 10655041 1 13 0.3023 1 +chrY 10655719 0 0 0.0 0 +chrY 10658204 0 0 0.0 0 +chrY 10663829 1 7 0.1707 1 +chrY 10671240 0 0 0.0 0 +chrY 10673845 0 1 0.0435 0 +chrY 10683527 0 0 0.0 0 +chrY 10691149 0 0 0.0 0 +chrY 10745242 0 0 0.0 0 +chrY 10750450 0 0 0.0 0 +chrY 10752351 0 0 0.0 0 +chrY 10759585 0 0 0.0 0 +chrY 10761050 0 0 0.0 0 +chrY 10767489 0 0 0.0 0 +chrY 10767888 0 0 0.0 0 +chrY 10768358 0 0 0.0 0 +chrY 10768915 0 0 0.0 0 +chrY 10770685 0 0 0.0 0 +chrY 10773338 0 0 0.0 0 +chrY 10773887 0 0 0.0 0 +chrY 10776097 1 5 0.4167 1 +chrY 10777175 0 0 0.0 0 +chrY 10777713 0 0 0.0 0 +chrY 10784433 0 0 0.0 0 +chrY 10786814 0 0 0.0 0 +chrY 10790550 0 0 0.0 0 +chrY 10794823 0 0 0.0 0 +chrY 10795888 0 0 0.0 0 +chrY 10797604 0 0 0.0 0 +chrY 10798258 0 0 0.0 0 +chrY 10799345 0 0 0.0 0 +chrY 10799647 1 17 0.9444 1 +chrY 10801744 0 0 0.0 0 +chrY 10803093 0 0 0.0 0 +chrY 10803253 0 0 0.0 0 +chrY 10805947 0 0 0.0 0 +chrY 10816314 0 0 0.0 0 +chrY 10823819 0 0 0.0 0 +chrY 10825177 0 0 0.0 0 +chrY 10826253 0 0 0.0 0 +chrY 10828389 0 0 0.0 0 +chrY 10838846 0 0 0.0 0 +chrY 10840128 0 0 0.0 0 +chrY 10840184 0 0 0.0 0 +chrY 10843117 0 0 0.0 0 +chrY 10845010 0 0 0.0 0 +chrY 10848534 0 0 0.0 0 +chrY 10848934 0 0 0.0 0 +chrY 10850867 0 0 0.0 0 +chrY 10857219 0 0 0.0 0 +chrY 10864117 0 0 0.0 0 +chrY 10869692 0 0 0.0 0 +chrY 10873360 0 0 0.0 0 +chrY 10876688 0 0 0.0 0 +chrY 10877805 0 1 0.0385 0 +chrY 10881255 0 0 0.0 0 +chrY 10884344 0 0 0.0 0 +chrY 10884699 0 0 0.0 0 +chrY 10887622 0 0 0.0 0 +chrY 10888473 0 0 0.0 0 +chrY 10892053 0 0 0.0 0 +chrY 10893903 1 3 0.1765 1 +chrY 10895356 0 0 0.0 0 +chrY 10898290 0 0 0.0 0 +chrY 10899706 0 0 0.0 0 +chrY 10926528 0 0 0.0 0 +chrY 10932917 0 0 0.0 0 +chrY 10940039 0 0 0.0 0 +chrY 10942649 0 0 0.0 0 +chrY 10949435 0 0 0.0 0 +chrY 10950544 0 0 0.0 0 +chrY 10953514 0 0 0.0 0 +chrY 10956686 0 0 0.0 0 +chrY 10959361 0 1 0.0385 0 +chrY 10962645 0 0 0.0 0 +chrY 10963494 0 0 0.0 0 +chrY 10969103 0 0 0.0 0 +chrY 10969906 0 0 0.0 0 +chrY 10984395 0 0 0.0 0 +chrY 10985981 0 0 0.0 0 +chrY 10992183 0 0 0.0 0 +chrY 11009071 0 0 0.0 0 +chrY 11040841 0 0 0.0 0 +chrY 11089011 0 0 0.0 0 +chrY 11092633 0 0 0.0 0 +chrY 11097799 0 0 0.0 0 +chrY 11108479 0 0 0.0 0 +chrY 11296080 0 0 0.0 0 +chrY 11359647 0 0 0.0 0 +chrY 11447244 0 0 0.0 0 +chrY 11679516 0 0 0.0 0 +chrY 11771336 0 0 0.0 0 +chrY 11821252 0 0 0.0 0 +chrY 12158456 0 0 0.0 0 +chrY 12277446 0 0 0.0 0 +chrY 12284082 0 0 0.0 0 +chrY 12414660 0 0 0.0 0 +chrY 12595272 0 0 0.0 0 +chrY 12837209 0 0 0.0 0 +chrY 12993647 0 0 0.0 0 +chrY 13081606 0 0 0.0 0 +chrY 13150370 0 0 0.0 0 +chrY 13175280 0 0 0.0 0 +chrY 13338614 0 0 0.0 0 +chrY 13389231 0 0 0.0 0 +chrY 13549344 0 0 0.0 0 +chrY 13592390 0 0 0.0 0 +chrY 13719284 0 0 0.0 0 +chrY 13926117 0 0 0.0 0 +chrY 13961158 0 0 0.0 0 +chrY 14008350 0 0 0.0 0 +chrY 14034381 0 0 0.0 0 +chrY 14075984 0 0 0.0 0 +chrY 14178091 0 0 0.0 0 +chrY 14317559 0 0 0.0 0 +chrY 14534318 0 0 0.0 0 +chrY 14613163 0 0 0.0 0 +chrY 14717034 0 0 0.0 0 +chrY 14808466 0 0 0.0 0 +chrY 14882692 0 0 0.0 0 +chrY 14920107 0 0 0.0 0 +chrY 14930794 0 0 0.0 0 +chrY 14997497 0 0 0.0 0 +chrY 15328726 0 0 0.0 0 +chrY 15343178 0 0 0.0 0 +chrY 15393867 0 0 0.0 0 +chrY 15455723 0 0 0.0 0 +chrY 15639383 0 0 0.0 0 +chrY 15852010 0 0 0.0 0 +chrY 16196739 0 0 0.0 0 +chrY 16289012 0 0 0.0 0 +chrY 16388604 0 0 0.0 0 +chrY 16593874 0 0 0.0 0 +chrY 16682065 0 0 0.0 0 +chrY 16692150 0 0 0.0 0 +chrY 16792180 0 0 0.0 0 +chrY 17007492 0 0 0.0 0 +chrY 17174175 0 0 0.0 0 +chrY 17185620 0 0 0.0 0 +chrY 17256574 0 0 0.0 0 +chrY 17289475 0 0 0.0 0 +chrY 17412089 0 0 0.0 0 +chrY 17491814 0 0 0.0 0 +chrY 17738920 0 0 0.0 0 +chrY 17768140 0 0 0.0 0 +chrY 18137870 0 0 0.0 0 +chrY 18167091 0 0 0.0 0 +chrY 18414194 0 0 0.0 0 +chrY 18880502 0 0 0.0 0 +chrY 19105694 0 0 0.0 0 +chrY 19206944 0 0 0.0 0 +chrY 19246099 0 0 0.0 0 +chrY 19269789 0 0 0.0 0 +chrY 19413052 0 0 0.0 0 +chrY 19472815 0 0 0.0 0 +chrY 19509364 0 0 0.0 0 +chrY 19690350 0 0 0.0 0 +chrY 19710756 0 0 0.0 0 +chrY 19890824 0 0 0.0 0 +chrY 19899585 0 0 0.0 0 +chrY 20763945 0 0 0.0 0 +chrY 21146305 0 0 0.0 0 +chrY 21174156 0 0 0.0 0 +chrY 21245628 0 0 0.0 0 +chrY 21273050 0 0 0.0 0 +chrY 21320770 0 0 0.0 0 +chrY 21400527 0 0 0.0 0 +chrY 21462773 0 0 0.0 0 +chrY 21506897 0 0 0.0 0 +chrY 21530437 0 0 0.0 0 +chrY 21559966 0 0 0.0 0 +chrY 21600663 0 0 0.0 0 +chrY 21824993 0 0 0.0 0 +chrY 21845716 0 0 0.0 0 +chrY 21869437 0 0 0.0 0 +chrY 21898967 0 0 0.0 0 +chrY 21922508 0 0 0.0 0 +chrY 22031697 0 0 0.0 0 +chrY 22152062 0 0 0.0 0 +chrY 22154399 0 0 0.0 0 +chrY 22199496 0 0 0.0 0 +chrY 22210474 0 0 0.0 0 +chrY 22311896 0 0 0.0 0 +chrY 22386923 0 0 0.0 0 +chrY 22432025 0 0 0.0 0 +chrY 22434363 0 0 0.0 0 +chrY 22554699 0 0 0.0 0 +chrY 22705574 0 0 0.0 0 +chrY 22992796 0 0 0.0 0 +chrY 22997514 0 0 0.0 0 +chrY 23036439 0 0 0.0 0 +chrY 23490617 0 0 0.0 0 +chrY 23713868 0 0 0.0 0 +chrY 23814277 0 0 0.0 0 +chrY 24105667 0 0 0.0 0 +chrY 24255813 0 0 0.0 0 +chrY 24258707 0 0 0.0 0 +chrY 24314988 0 0 0.0 0 +chrY 24626537 0 0 0.0 0 +chrY 24631256 0 0 0.0 0 +chrY 24670183 0 0 0.0 0 +chrY 24999921 0 0 0.0 0 +chrY 25038852 0 0 0.0 0 +chrY 25043572 0 0 0.0 0 +chrY 25355157 0 0 0.0 0 +chrY 25411436 0 0 0.0 0 +chrY 25414332 0 0 0.0 0 +chrY 25564473 0 0 0.0 0 +chrY 25855813 0 0 0.0 0 +chrY 25956207 0 0 0.0 0 +chrY 26179992 0 0 0.0 0 +chrY 26476716 0 0 0.0 0 +chrY 26539211 0 0 0.0 0 +chrY 26577686 0 0 0.0 0 +chrY 26643351 0 0 0.0 0 +chrY 26645731 0 0 0.0 0 +chrY 26646404 0 0 0.0 0 +chrY 26648611 0 0 0.0 0 +chrY 26649284 0 1 0.0078 0 +chrY 26656286 0 0 0.0 0 +chrY 26664407 0 0 0.0 0 +chrY 26666588 0 0 0.0 0 +chrY 26667260 0 0 0.0 0 +chrY 56830200 1 7 0.1667 1 +chrY 56942216 0 0 0.0 0 +chrY 56962684 0 0 0.0 0 +chrY 57186403 0 0 0.0 0 diff --git a/assets/offtarget_samplesheet_template.csv b/assets/offtarget_samplesheet_template.csv new file mode 100644 index 0000000..63948c7 --- /dev/null +++ b/assets/offtarget_samplesheet_template.csv @@ -0,0 +1,4 @@ +sample,datatype,guide,edited_cram,control_cram,target_file,vcf,spacer,pam +PLCB2_ecs_1,ecs,PLCB2_KO,/abs/path/PLCB2_edited_1.ecs.cram,/abs/path/PLCB2_control.ecs.cram,/abs/path/PLCB2.targets.vcf,,, +PLCB2_ecs_2,ecs,PLCB2_KO,/abs/path/PLCB2_edited_2.ecs.cram,/abs/path/PLCB2_control.ecs.cram,/abs/path/PLCB2.targets.vcf,,, +PLCB2_wgs_1,wgs,PLCB2_KO,/abs/path/PLCB2_1_tumor.cram,/abs/path/PLCB2_1.cram,,/abs/path/PLCB2_1.hard-filtered.vcf.gz,, diff --git a/assets/stub/analysis_mastersheet.csv b/assets/stub/analysis_mastersheet.csv new file mode 100644 index 0000000..31b7578 --- /dev/null +++ b/assets/stub/analysis_mastersheet.csv @@ -0,0 +1,2 @@ +id,dragen_path +EZH1-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/EZH1-KO-DNA/dragen diff --git a/assets/stub/offtarget_autowire.csv b/assets/stub/offtarget_autowire.csv new file mode 100644 index 0000000..23c6a89 --- /dev/null +++ b/assets/stub/offtarget_autowire.csv @@ -0,0 +1,3 @@ +sample,datatype,guide,edited_cram,control_cram,target_file,vcf,spacer,pam +AAVS1_ecs_1,ecs,AAVS1_site14,/abs/AAVS1_edited_1.ecs.cram,/abs/AAVS1_control.ecs.cram,,,GGGGCCACTAGGGACAGGAT,NGG +AAVS1_ecs_2,ecs,AAVS1_site14,/abs/AAVS1_edited_2.ecs.cram,/abs/AAVS1_control.ecs.cram,,,GGGGCCACTAGGGACAGGAT,NGG diff --git a/assets/stub/sample_mastersheet.csv b/assets/stub/sample_mastersheet.csv new file mode 100644 index 0000000..6ca7865 --- /dev/null +++ b/assets/stub/sample_mastersheet.csv @@ -0,0 +1,17 @@ +id,edited_id,control_id,fastq_list,edited_fastq1,edited_fastq2,control_fastq1,control_fastq2,edited_cram,control_cram,dragen_path + +# descriptions, note not all are specified for a single experiment (e.g., if edited_id and control_id and fastq_list are provided, then fastq1/fastq2 are not needed) +id: the output root sample name +edited_id: the id/name of the edited sample, if fastq_list is provided +control_id: the id/name of the control sample, if fastq_list is provided +fastq_list: path to an illumina-style fastq list csv file +edited_fastq1: path to edited_fastq1 fastq file +edited_fastq2: path to edited_fastq2 fastq file +control_fastq1: path to control_fastq1 fastq file +control_fastq2: path to control_fastq2 fastq file +edited_cram: path to edited_cram file +control_cram: path to control_cram file +dragen_path: path to somatic dragen output -- this driggers analysis only + + + diff --git a/assets/stub/tiny.fa b/assets/stub/tiny.fa new file mode 100644 index 0000000..f691cab --- /dev/null +++ b/assets/stub/tiny.fa @@ -0,0 +1,4 @@ +>chr19 +ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGT +>PLVM_CD19_CARv4_cd34 +ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGT diff --git a/assets/stub/tiny.fa.fai b/assets/stub/tiny.fa.fai new file mode 100644 index 0000000..9feb9b5 --- /dev/null +++ b/assets/stub/tiny.fa.fai @@ -0,0 +1,2 @@ +chr19 40 7 40 41 +PLVM_CD19_CARv4_cd34 40 70 40 41 diff --git a/bin/add_vep2targetfile.pl b/bin/add_vep2targetfile.pl index e172d24..560cdc7 100755 --- a/bin/add_vep2targetfile.pl +++ b/bin/add_vep2targetfile.pl @@ -1,57 +1,85 @@ #!/usr/bin/env perl + use strict; use warnings; -# This script reformats VEP tabular output to be compatible with extract_variant_reads_ML.py -# 1. Splits Location into chromosome, start, end -# 2. Moves Uploaded_variation (which contains source info) to the last column -# 3. Prints a compatible header using the provided argument as the last column name +# Main loop: reads line-by-line from STDIN (pipe) or input files +while (my $line = <>) { + chomp $line; + + # Skip VEP header lines starting with # + next if $line =~ /^#/; + + # Split the VEP line by tabs + # $F[0] is the ID, $F[3] is Gene, $F[13] is Extra, etc. + my @fields = split(/\t/, $line); -my $last_col_header = $ARGV[0] or die "Usage: $0 \n"; + my $chrom = $fields[0]; + my $start = $fields[1] + 1; -# Print Header -# extract_variant_reads_ML.py expects: #chromosome, start, end, ... [KeyString] -print "#chromosome\tstart\tend\tLocation\tAllele\tGene\tFeature\tFeature_type\tConsequence\tcDNA_position\tCDS_position\tProtein_position\tAmino_acids\tCodons\tExisting_variation\tExtra\t$last_col_header\n"; + my $full_id = $fields[2] // ""; # Prevent undef warning if column 2 is missing + my $strand = (defined $full_id && $full_id =~ /\+/) ? "+" : "-"; -while () { - # Skip VEP headers - next if /^#/; - chomp; + my $extra_info = $fields[7]; + my $end = extract_tag($extra_info, 'END'); + my $vep = extract_tag($extra_info, 'CSQ'); - my @cols = split /\t/; + # 5. Print the final Tab-Separated line + print join("\t", $chrom, $start, $end, "INS", $strand, $full_id) . ';' . sort_vep_string($vep) . "\n"; +} + +# --- Subroutines --- + +sub extract_tag { + my ($text, $tag_name) = @_; - # Safety check for column count - if (scalar @cols < 2) { - next; + # Attempt to match "TAG_NAME=value" up to the next semicolon or end of string + if ($text =~ /$tag_name=([^;]+)/) { + return $1; } - - my $info = $cols[0]; - my $loc = $cols[1]; - # Parse Location: chr:start-end or chr:start - my ($chr, $pos_str) = split /:/, $loc; - my ($start, $end); + # Return dot if not found or empty + return "."; +} + +sub sort_vep_string { + my ($input_string) = @_; - if (defined $pos_str && $pos_str =~ /-/) { - ($start, $end) = split /-/, $pos_str; - } elsif (defined $pos_str) { - $start = $pos_str; - $end = $pos_str; - } else { - # Fallback if location format is unexpected - $chr = $loc; - $start = 0; - $end = 0; - } + return "" unless defined $input_string; + + # 1. Split by comma + my @items = split(/,/, $input_string); + + # 2. Sort numerically + my @sorted = sort { + # Extract number from A + my ($num_a) = extract_number($a); + + # Extract number from B + my ($num_b) = extract_number($b); + + # Compare (Ascending) + $num_a <=> $num_b + } @items; + + # 3. Join back together + return join(',', @sorted); +} + +sub extract_number { + my ($str) = @_; - # Output: chr, start, end, [All cols except first], Info - print "$chr\t$start\t$end\t"; + # Split by pipe + my @cols = split(/\|/, $str); - # Print cols 1 to end (skipping Uploaded_variation which is at index 0) - if (scalar @cols > 1) { - print join("\t", @cols[1..$#cols]); + # Look for the first field that is purely digits + # This handles both cases: "|ENSG|Type|668|" and "Gene|ENSG|Type|...|" + foreach my $col (@cols) { + if ($col =~ /^\d+$/) { + return $col; + } } - # Print Info at the end - print "\t$info\n"; -} + # RETURN -1 IF NO NUMBER FOUND (Forces these to the front) + return -1; +} \ No newline at end of file diff --git a/bin/bnd_from_indels_to_vcf.py b/bin/bnd_from_indels_to_vcf.py new file mode 100755 index 0000000..9a29a43 --- /dev/null +++ b/bin/bnd_from_indels_to_vcf.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +""" +bnd_from_indels_to_vcf.py -- turn the breakend calls in an *.offtarget_analysis.tsv +into a VCF, one record per junction, for the per-sample SCGE report. + +This is the UNFILTERED breakend set: every junction the caller kept survives to the +VCF. The triaged view is a separate, cohort-level product (review_filter_bnd.py -> +bnd_review_queue.tsv); the two share a source column and nothing else. + +The bnd_info payload is 11 pipe-separated fields per junction, joined by ';', +written by find_edited_reads.py: + + chrom|pos|chrom2|pos2|strands|ref|alt|distance|distance2|counts|control_alt_counts + 0 1 2 3 4 5 6 7 8 9 10 + +Fields 5 and 6 are already a valid VCF REF and BND ALT -- find_edited_reads.py's +format_bnd() builds them, brackets and orientation included (e.g. "CCAC]chr2:32916560]" +or "]chr2:32916405]GCC"). We use them verbatim rather than re-deriving the bracket +convention from `strands`, which is both simpler and keeps the VCF consistent with the +caller that produced it. + +Mates are LINKED, not synthesized: bnd_info already carries a junction from both ends +as separate records, so the reciprocal partner is normally present in the same file and +carries its own correctly-oriented ALT. We pair them by coordinate and emit MATEID. +""" +import argparse +import csv +import sys + +# A pysam-free reader: this runs in docker-baseimage, which is a thinner image than the +# review processes use. +csv.field_size_limit(1 << 30) # bnd_info is one long field; the 128 KB default truncates it + + +def parse_junctions(path): + """Yield (chrom, pos, chrom2, pos2, strands, ref, alt, counts, control) per junction.""" + seen = set() + out = [] + with open(path, newline="") as fh: + for row in csv.DictReader(fh, delimiter="\t"): + info = (row.get("bnd_info") or ".").strip() + if not info or info == ".": + continue + for ev in info.split(";"): + f = ev.split("|") + if len(f) < 11: + continue + try: + chrom, pos, chrom2, pos2 = f[0], int(f[1]), f[2], int(f[3]) + counts, control = int(f[9]), int(f[10]) + except (ValueError, IndexError): + continue + ref, alt = f[5] or "N", f[6] + if not alt or alt == ".": + continue + # The same junction is reported from each end, and adjacent target sites + # can report it twice; collapse exact repeats so one junction is one record. + key = (chrom, pos, chrom2, pos2, f[4], alt) + if key in seen: + continue + seen.add(key) + out.append((chrom, pos, chrom2, pos2, f[4], ref, alt, counts, control)) + return out + + +def link_mates(records): + """Map record index -> mate index, pairing a junction with its reciprocal record.""" + by_end = {} + for i, r in enumerate(records): + by_end.setdefault((r[0], r[1], r[2], r[3]), i) + mate = {} + for i, r in enumerate(records): + j = by_end.get((r[2], r[3], r[0], r[1])) + if j is not None and j != i: + mate[i] = j + return mate + + +HEADERS = [ + "##fileformat=VCFv4.2", + '##INFO=', + '##INFO=', + '##INFO=', + '##INFO=', + '##INFO=', +] + + +def main(args): + records = parse_junctions(args.indels_path) + mate = link_mates(records) + + # Coordinate-sorted output, but IDs are assigned before sorting so a mate's ID does + # not depend on sort order. + ids = {i: f"BND{i + 1}" for i in range(len(records))} + order = sorted(range(len(records)), key=lambda i: (records[i][0], records[i][1])) + + with open(args.outfile, "w") as out: + for h in HEADERS: + out.write(h + "\n") + out.write(f"##sampleId={args.meta_id}\n") + out.write("#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\n") + for i in order: + chrom, pos, chrom2, pos2, _strands, ref, alt, counts, control = records[i] + info = [f"SVTYPE=BND", f"SR={counts}", f"CTRL={control}"] + if i in mate: + info.append(f"MATEID={ids[mate[i]]}") + info.append(f"EVENT=EVT{min(i, mate[i]) + 1}") + out.write(f"{chrom}\t{pos}\t{ids[i]}\t{ref}\t{alt}\t.\tPASS\t{';'.join(info)}\n") + + print(f"{args.meta_id}: {len(records)} breakend records -> {args.outfile}", file=sys.stderr) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Convert an offtarget analysis table to a BND VCF.") + parser.add_argument("--meta_id", required=True, help="Sample ID") + parser.add_argument("--indels_path", required=True, help="Path to *.offtarget_analysis.tsv") + parser.add_argument("--outfile", required=True, help="Path to output VCF file") + main(parser.parse_args()) diff --git a/bin/bnd_snapshots.py b/bin/bnd_snapshots.py new file mode 100644 index 0000000..d1ead35 --- /dev/null +++ b/bin/bnd_snapshots.py @@ -0,0 +1,333 @@ +#!/usr/bin/env python3 +""" +bnd_snapshots.py -- render a review packet for BREAKENDS, one figure per junction. + +The breakend sibling of review_snapshots.py, and deliberately not the same picture. +Three things make a junction different from an indel site: + +0. The picture must match the ORIENTATION. A +-/-+ junction is an inversion -- the segment + between the cuts is flipped and re-ligated, not removed -- and drawing the excision cartoon for + one is worse than drawing nothing, because a reader trusts the picture over the caption. The + schematic branches on `inverted`, set from `strands` in collapse(). + +1. A junction has TWO loci. review_snapshots.py draws one, and its + `int(r.get("end", r.get("start")))` idiom does not even parse the breakend schema + (which is chrom/pos + chrom2/pos2). So this is a 2x2 grid: left and right breakpoint, + each with the edited sample over its matched unedited control -- keeping the + self-adjudicating pairing the indel packet is built on. + +2. One junction is reported as several rows. bnd_review_queue.tsv carries each event + from BOTH ends, at +/- a few bp of jitter, under both strand orientations. On the + reference cohort that is 25 rows for 8 real junctions, and rendering per row gives + one sample five near-identical pictures. We collapse on (sample, {bin, partner_bin}) + -- columns review_filter_bnd.py already computes -- and sum the read support, because + the per-row count understates the event by up to 6x (ARID4A: rows say 3-4 reads, the + junction has 18). + +3. The evidence is split reads, which the default pileup hides. A breakend's signature + is a stack of soft clips terminating on one base whose clipped portion maps to the + partner locus. Those are usually supplementary alignments, and pileup_snapshot's + default filter drops them. We pass keep_supplementary=True and colour the reads whose + SA tag points at the partner green, so the junction is visible rather than inferred. + +On SA parsing: find_edited_reads.py has a far more capable SA handler +(get_sa_indel_vcf), but it reconstructs alleles and needs a fasta, target positions and +a target index, and importing that module pulls in edlib/joblib/pyranges/scipy. All we +need here is "does a segment of this read land near the partner locus", which is the +first two fields of the SA tag -- a SAM spec constant. Parsed inline on purpose. +""" +import os +import sys +import argparse +from argparse import RawDescriptionHelpFormatter +from collections import defaultdict + +import pandas as pd +import pysam +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +from matplotlib.patches import Rectangle + +# pileup_snapshot lives beside this script in bin/ +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from pileup_snapshot import snapshot # noqa: E402 + +BIN_SIZE = 1000 # must match review_filter_bnd.py's --bin-size +SA_SLOP = 1000 # how near the partner an SA segment must land to count + + +# --------------------------------------------------------------------------- junctions + +def junction_bins(row): + """The two 1 kb bins a junction connects, in canonical (sorted) order.""" + return tuple(sorted([str(row["bin"]), str(row["partner_bin"])])) + + +def end_of(group, wanted_bin): + """Resolve one end of a junction to (chrom, representative_pos, all_positions). + + Rows report the junction from both directions, so a given bin appears as `bin` in + some rows and `partner_bin` in others. The representative position is the one + carrying the most read support; the rest are drawn as faint marks so the jitter is + visible rather than hidden. + """ + acc = defaultdict(int) + chrom = None + for _, r in group.iterrows(): + if str(r["bin"]) == wanted_bin: + acc[int(r["pos"])] += int(r["reads"]) + chrom = str(r["chrom"]) + if str(r["partner_bin"]) == wanted_bin: + acc[int(r["pos2"])] += int(r["reads"]) + chrom = str(r["chrom2"]) + if not acc: + raise ValueError(f"no rows for bin {wanted_bin}") + best = max(acc.items(), key=lambda kv: (kv[1], -kv[0]))[0] + return chrom, best, sorted(acc) + + +def collapse(q): + """Group the queue into junctions. Returns a list of dicts, one per junction.""" + out = [] + q = q.copy() + q["_key"] = [junction_bins(r) for _, r in q.iterrows()] + for (sample, key), g in q.groupby(["sample_name", "_key"], sort=False): + b1, b2 = key + try: + c1, p1, marks1 = end_of(g, b1) + c2, p2, marks2 = end_of(g, b2) + except ValueError: + continue + # Canonical left/right so the figure reads the same way every time. + if (c1, p1) > (c2, p2): + (c1, p1, marks1), (c2, p2, marks2) = (c2, p2, marks2), (c1, p1, marks1) + top = g.loc[g["reads"].astype(int).idxmax()] + out.append({ + "sample": sample, + "left": (c1, p1, marks1), + "right": (c2, p2, marks2), + "reads": int(g["reads"].astype(int).sum()), + "n_rows": len(g), + "depth": int(pd.to_numeric(g["site_total_reads"], errors="coerce").max()), + "control": int(pd.to_numeric(g["control_reads_at_event"], + errors="coerce").fillna(0).max()), + "call": str(top.get("call", "") or "breakend"), + "strands": ",".join(sorted(set(g["strands"].astype(str)))), + # Orientation decides which cartoon to draw. +-/-+ means the far segment is inverted + # relative to the near one, so the segment was flipped, not excised -- drawing an + # excision there is simply the wrong picture. See review_filter_bnd.py's classifier. + "inverted": bool(set(g["strands"].astype(str)) & {"+-", "-+"}), + "span": None if c1 != c2 else abs(p2 - p1), + "interchrom": c1 != c2, + "far_on_target": int(pd.to_numeric(g["far_end_on_target"], + errors="coerce").fillna(0).max()), + }) + return out + + +# ------------------------------------------------------------------------------ SA tag + +def sa_supporters(cram, fasta, chrom, pos, window, pchrom, ppos, slop=SA_SLOP): + """Read names near (chrom,pos) with an SA segment landing near (pchrom,ppos). + + SA tag format is `rname,pos,strand,CIGAR,mapQ,NM;` repeated -- we need fields 0-1. + """ + names = set() + try: + bam = pysam.AlignmentFile(cram, "rc", reference_filename=fasta) + except Exception: + return names + try: + for r in bam.fetch(chrom, max(0, pos - window), pos + window): + if r.is_unmapped or r.is_duplicate or not r.has_tag("SA"): + continue + for seg in str(r.get_tag("SA")).rstrip(";").split(";"): + f = seg.split(",") + if len(f) < 2: + continue + try: + if f[0] == pchrom and abs(int(f[1]) - ppos) <= slop: + names.add(r.query_name) + break + except ValueError: + continue + finally: + bam.close() + return names + + +# ---------------------------------------------------------------------------- schematic + +def draw_schematic(ax, j): + """A to-scale cartoon of what happened, above the read panels.""" + ax.set_xlim(0, 1) + ax.set_ylim(0, 1) + ax.axis("off") + c1, p1, _ = j["left"] + c2, p2, _ = j["right"] + y = 0.55 + grey, cut, gone = "#4d4d4d", "#cc2b2b", "#bbbbbb" + + if j["interchrom"]: + ax.add_patch(Rectangle((0.04, y - 0.05), 0.38, 0.10, color=grey)) + ax.add_patch(Rectangle((0.58, y - 0.05), 0.38, 0.10, color=grey)) + ax.plot([0.42], [y], marker="v", color=cut, ms=9) + ax.plot([0.58], [y], marker="v", color=cut, ms=9) + ax.annotate("", xy=(0.575, y - 0.20), xytext=(0.425, y - 0.20), + arrowprops=dict(arrowstyle="<->", color=cut, lw=1.4)) + ax.text(0.5, y - 0.42, "interchromosomal junction", ha="center", + fontsize=8, color=cut) + ax.text(0.23, y + 0.22, f"{c1}:{p1:,}", ha="center", fontsize=8) + ax.text(0.77, y + 0.22, f"{c2}:{p2:,}", ha="center", fontsize=8) + return + + xl, xr = 0.30, 0.70 + ax.add_patch(Rectangle((0.04, y - 0.05), xl - 0.04, 0.10, color=grey)) + ax.add_patch(Rectangle((xr, y - 0.05), 0.96 - xr, 0.10, color=grey)) + for x in (xl, xr): + ax.plot([x], [y + 0.16], marker="v", color=cut, ms=9) + span = j["span"] + ax.text(xl, y - 0.22, f"{c1}:{p1:,}", ha="center", fontsize=8) + ax.text(xr, y - 0.22, f"{c2}:{p2:,}", ha="center", fontsize=8) + + if j.get("inverted"): + # The segment is still there, reversed. Draw it retained, with the direction arrow + # pointing back the other way, because the excision cartoon is the wrong picture and a + # reader takes the picture more seriously than the caption. + ax.add_patch(Rectangle((xl, y - 0.05), xr - xl, 0.10, + facecolor="#ffffff", edgecolor=cut, hatch="\\\\", lw=0.9)) + ax.annotate("", xy=(xl + 0.03, y), xytext=(xr - 0.03, y), + arrowprops=dict(arrowstyle="-|>", color=cut, lw=1.6, + mutation_scale=13)) + ax.text(0.5, y + 0.30, + f"{span:,} bp inverted" if span is not None else "segment inverted", + ha="center", fontsize=8, color=cut) + ax.text(0.5, y - 0.52, "flipped and re-ligated at both ends", ha="center", + fontsize=8, color=cut) + # Both junctions of the pair, so the two-per-event accounting is visible. + ax.text(0.5, y - 0.72, f"strands {j['strands']} — both junctions of the pair", + ha="center", fontsize=7, color="#777777") + return + + ax.add_patch(Rectangle((xl, y - 0.05), xr - xl, 0.10, + facecolor=gone, edgecolor=cut, hatch="///", lw=0.8)) + ax.text(0.5, y + 0.30, f"excised {span:,} bp" if span is not None else "excised", + ha="center", fontsize=8, color=cut) + ax.annotate("", xy=(xr, y - 0.36), xytext=(xl, y - 0.36), + arrowprops=dict(arrowstyle="-", color=cut, lw=1.2, + connectionstyle="bar,fraction=-0.25")) + ax.text(0.5, y - 0.52, "joined", ha="center", fontsize=8, color=cut) + + +# --------------------------------------------------------------------------------- main + +def render(j, ed, ct, fasta, window, outpath): + (c1, p1, m1), (c2, p2, m2) = j["left"], j["right"] + hlL = sa_supporters(ed, fasta, c1, p1, window, c2, p2) + hlR = sa_supporters(ed, fasta, c2, p2, window, c1, p1) + + fig = plt.figure(figsize=(13, 9)) + gs = fig.add_gridspec(3, 2, height_ratios=[0.75, 2.2, 2.2], + hspace=0.52, wspace=0.10) + draw_schematic(fig.add_subplot(gs[0, :]), j) + + axLe = fig.add_subplot(gs[1, 0]) + axRe = fig.add_subplot(gs[1, 1]) + # sharex per COLUMN only -- the two breakpoints have unrelated coordinates, so the + # global sharex=True that review_snapshots.py uses would be meaningless here. + axLc = fig.add_subplot(gs[2, 0], sharex=axLe) + axRc = fig.add_subplot(gs[2, 1], sharex=axRe) + + kw = dict(ref=fasta, window=window, keep_supplementary=True, clip_cap=None) + # NB the green count and the suptitle's junction-read count are different statistics + # and will not agree: this one is every read with an SA segment within SA_SLOP of the + # partner, the other is the caller's filtered support (MAPQ, cut distance, dedup). + # Labelled explicitly so the figure does not appear to contradict itself. + # Two-line titles: a single line does not fit a half-width column and the left and + # right panel titles run into each other. + snapshot(axLe, ed, c1, p1, highlight=hlL, mark=m1, **kw, + title=f"EDITED {j['sample']} LEFT {c1}:{p1:,}\n" + f"{len(hlL)} reads with SA at partner (green)") + snapshot(axRe, ed, c2, p2, highlight=hlR, mark=m2, **kw, + title=f"EDITED {j['sample']} RIGHT {c2}:{p2:,}\n" + f"{len(hlR)} reads with SA at partner (green)") + ctname = os.path.basename(str(ct)) + snapshot(axLc, ct, c1, p1, mark=m1, **kw, + title=f"MATCHED UNEDITED CONTROL\n({ctname})") + snapshot(axRc, ct, c2, p2, mark=m2, **kw, + title=f"MATCHED UNEDITED CONTROL\n({ctname})") + + bits = [j["call"].upper()] + if j["span"] is not None: + bits.append(f"span {j['span']:,} bp") + bits.append(f"{j['reads']} junction reads / {j['depth']}x") + bits.append(f"control {j['control']}") + bits.append(f"strands {j['strands']}") + if j["n_rows"] > 1: + bits.append(f"{j['n_rows']} queue rows") + fig.suptitle("BREAKEND REVIEW CANDIDATE\n" + " | ".join(bits), + fontsize=11, fontweight="bold") + fig.savefig(outpath, dpi=130, bbox_inches="tight") + plt.close(fig) + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=RawDescriptionHelpFormatter) + ap.add_argument("--queue", required=True, help="bnd_review_queue.tsv from review_filter_bnd.py") + ap.add_argument("--cram-map", required=True, + help="TSV: sampleedited_cramcontrol_cram") + ap.add_argument("--fasta", required=True) + ap.add_argument("--outdir", default="bnd_snapshots") + ap.add_argument("--window", type=int, default=150, + help="bp either side of each breakpoint (default 150; a clip stack " + "needs more flank than an indel)") + ap.add_argument("--max-junctions", type=int, default=200, + help="safety cap; a runaway queue should not render thousands of PNGs") + a = ap.parse_args() + + os.makedirs(a.outdir, exist_ok=True) + q = pd.read_csv(a.queue, sep="\t") + if q.empty: + print("breakend review queue is empty; nothing to render") + return + + junctions = collapse(q) + print(f"queue rows : {len(q)}") + print(f"junctions : {len(junctions)}") + if len(junctions) > a.max_junctions: + print(f"WARNING: {len(junctions)} junctions, rendering only the first " + f"{a.max_junctions}. A set this large usually means a filter is not " + f"firing -- check the review_filter_bnd.py warnings.", file=sys.stderr) + junctions = junctions[:a.max_junctions] + + cmap = pd.read_csv(a.cram_map, sep="\t", header=None, + names=["sample", "edited", "control"]).set_index("sample") + + made, skipped = 0, [] + for i, j in enumerate(junctions): + s = j["sample"] + if s not in cmap.index: + skipped.append(f"{s} (not in cram map)") + continue + c1, p1, _ = j["left"] + c2, p2, _ = j["right"] + tag = f"{i + 1:03d}_{s}_{c1}_{p1}_{c2}_{p2}".replace("/", "-") + try: + render(j, cmap.loc[s, "edited"], cmap.loc[s, "control"], + a.fasta, a.window, os.path.join(a.outdir, tag + ".png")) + made += 1 + except Exception as e: # one bad junction must not kill the packet + plt.close("all") + skipped.append(f"{s} {c1}:{p1}-{c2}:{p2} ({type(e).__name__}: {e})") + + print(f"snapshots made : {made} -> {a.outdir}/") + if skipped: + print(f"skipped : {len(skipped)}", file=sys.stderr) + for line in skipped[:10]: + print(f" {line}", file=sys.stderr) + + +if __name__ == "__main__": + main() diff --git a/bin/build_crisprme_index.sh b/bin/build_crisprme_index.sh new file mode 100755 index 0000000..93f2358 --- /dev/null +++ b/bin/build_crisprme_index.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# build_crisprme_index.sh — build the one-time, offline CRISPRme/CRISPRitz genome index that +# the CRISPRME pipeline module consumes read-only (params.crisprme_index_dir). +# +# CRISPRme's per-guide `complete-search` needs a TST index under `genome_library/__Genome/`, +# which is specific to the PAM and the *total* bulge budget (bMax = bDNA + bRNA). Building it is the +# slow, heavy step (tens of GB, minutes-to-hours for a full genome), so it is done ONCE here and then +# reused by every guide. This script is NOT part of the Nextflow pipeline — run it by hand on a +# compute node, then point --crisprme_index_dir at its output. +# +# It produces this layout (this whole directory is params.crisprme_index_dir): +# / +# Genome/ per-chromosome unzipped FASTAs (CRISPRme requires one file/contig) +# genome_library/__Genome/ the prebuilt TST index (.bin) reused by complete-search +# bp--.txt the PAM file (its NAME encodes the nuclease — CRISPRme parses it) +# +# Usage (inside the CRISPRme container): +# apptainer exec --writable-tmpfs -B /storage2,/scratch2 \ +# docker://pinellolab/crisprme:2.1.10 \ +# bash build_crisprme_index.sh [PAM] [SPACER_LEN] [bMax] [THREADS] [NUCLEASE] +# +# Example (SpCas9, 20 bp spacer, NGG, DNA+RNA bulge budget 2): +# bash build_crisprme_index.sh hg38_PLVM_CD19_CARv4_cd34.fa /storage2/.../refdata/crisprme NGG 20 2 8 SpCas9 +set -euo pipefail + +FASTA=${1:?usage: build_crisprme_index.sh [PAM] [SPACER_LEN] [bMax] [THREADS] [NUCLEASE]} +OUTDIR=${2:?missing } +PAM=${3:-NGG} +SPLEN=${4:-20} +BMAX=${5:-2} +THREADS=${6:-8} +NUCLEASE=${7:-SpCas9} + +# CRISPRme ships in a conda env that its entrypoint activates; Nextflow/apptainer exec bypasses that, +# so make the tools importable here too. +export PATH=/opt/conda/bin:${PATH} + +command -v crispritz.py >/dev/null || { echo "ERROR: crispritz.py not on PATH (run inside the CRISPRme container)"; exit 1; } + +mkdir -p "${OUTDIR}/Genome" +cd "${OUTDIR}" + +# --- 1. PAM file: ' ', named 'bp--.txt' ----------------- +# The filename is load-bearing: CRISPRme derives the nuclease from basename.split('.')[0].split('-')[2]. +PAMFILE="${SPLEN}bp-${PAM}-${NUCLEASE}.txt" +printf '%s%s %d\n' "$(printf 'N%.0s' $(seq 1 "${SPLEN}"))" "${PAM}" "${#PAM}" > "${PAMFILE}" +echo "PAM file: ${PAMFILE} -> $(cat "${PAMFILE}")" + +# --- 2. split the reference into one unzipped FASTA per contig under Genome/ ------------------------ +# CRISPRme requires per-chromosome files. Single awk pass over the (possibly multi-thousand-contig) +# reference; the contig name is the first whitespace token of the header. +if [ -z "$(ls -A Genome 2>/dev/null)" ]; then + echo "Splitting ${FASTA} into per-contig FASTAs under Genome/ ..." + awk '/^>/ { name=substr($1,2); close(f); f="Genome/" name ".fa" } + { print > f }' "${FASTA}" + echo " wrote $(ls Genome | wc -l) contig files" +else + echo "Genome/ already populated ($(ls Genome | wc -l) files) — skipping split" +fi + +# --- 3. build the TST index (the slow part) -------------------------------------------------------- +# Produces genome_library/__Genome/. The genome-dir basename ('Genome') becomes the index +# suffix, so the pipeline module must also pass --genome /Genome for the reuse lookup to match. +INDEX="genome_library/${PAM}_${BMAX}_Genome" +if [ -d "${INDEX}" ] && [ -n "$(ls -A "${INDEX}" 2>/dev/null)" ]; then + echo "Index ${INDEX} already exists — skipping build" +else + echo "Building CRISPRitz index ${INDEX} (bMax=${BMAX}, ${THREADS} threads) — this is the slow step ..." + crispritz.py index-genome Genome Genome/ "${PAMFILE}" -bMax "${BMAX}" -th "${THREADS}" +fi + +echo +echo "DONE. crisprme_index_dir = ${OUTDIR}" +echo " Genome/ $(ls Genome | wc -l) contigs" +echo " ${INDEX}/ $(ls "${INDEX}" 2>/dev/null | wc -l) index files" +echo " PAM file: ${PAMFILE}" diff --git a/bin/build_curated_wgs_label.py b/bin/build_curated_wgs_label.py new file mode 100755 index 0000000..9c2a2a9 --- /dev/null +++ b/bin/build_curated_wgs_label.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +""" +build_curated_wgs_label.py — the training label the shape model should actually learn. + +Why this exists +--------------- +`join_training_table.py` derives `label` from the ECS indel threshold. On the CART panel that +yields 73,770 "positives" out of 99,308 rows, most of them ECS assay noise or germline. A model +fit to that target scores *worse* in reality even while its AUC against the target goes up +(measured: swapping only the label cost 6x precision on the AAVS1 curated truth). + +The defensible label is the human one, and it is a genuine TWO-CLASS label -- which the code +previously assumed it was not. The manual WGS review worked like this: + + 1. take every called indel with `indel_fraction >= 0.05` AND `indel_reads >= 10` + 2. adjudicate every row in that set by eye in IGV + +So inside that stratum, a blank `manual_review` means **rejected**, not unreviewed. Those +rejects are the most valuable negatives available: sites that passed a rules filter and a human +still said no -- exactly the false positives the model exists to remove. + +The thresholds are confirmed by the data rather than assumed: among the 53 confirmed WGS edits +the minimum `indel_fraction` is 0.0561 and the minimum `indel_reads` is 11, both just inside the +stated cut-offs, and no confirmed edit falls outside the stratum. + + gold_wgs, indel_fraction >= 0.05 & indel_reads >= 10 + -> 241 rows: 53 confirmed edits, 188 human-rejected negatives + +Rows OUTSIDE the stratum are genuinely unreviewed and are dropped, not labelled 0. + +Note the ECS review used a lower VAF floor (7 of its confirmed edits sit below 0.05), which is +reasonable at 5000x. Do not reuse these thresholds for the ECS gold. + +Usage +----- + build_curated_wgs_label.py --training cart_training_newfeats.tsv \ + --gold-xlsx ".../cart_wgs/cart_wgs_merged.xlsx" --out cart_training_curated.tsv +""" +import argparse +import os +import sys + +import pandas as pd + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +# The gold sheets key samples by review-sheet name (`NS0011-ABTB1`) while the pipeline keys +# them by CRAM sample (`ABTB1-KO-DNA`). Joining on sample_name silently drops 15 of 25 gold +# samples. Both carry the GUIDE, so the guide is the join key -- the same resolution +# validate_recall.py already implements, alias table included. +from validate_recall import guide_from_sample, GUIDE_ALIAS # noqa: E402 + +CONFIRMED = {"1", "1.0"} +MIN_IF = 0.05 +MIN_INDEL_READS = 10 + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--training", required=True, help="training table carrying the WGS features") + ap.add_argument("--gold-xlsx", required=True, help="cart_wgs_merged.xlsx") + ap.add_argument("--sheet", default="gold_wgs") + ap.add_argument("--min-if", type=float, default=MIN_IF) + ap.add_argument("--min-indel-reads", type=int, default=MIN_INDEL_READS) + ap.add_argument("--out", required=True) + args = ap.parse_args() + + g = pd.read_excel(args.gold_xlsx, sheet_name=args.sheet) + g["chrom"] = g["chrom"].astype(str) + g["start"] = pd.to_numeric(g["start"], errors="coerce").astype("Int64") + conf = g["manual_review"].astype(str).str.strip().isin(CONFIRMED) + iv = pd.to_numeric(g["indel_fraction"], errors="coerce") + ir = pd.to_numeric(g["indel_reads"], errors="coerce") + in_stratum = (iv >= args.min_if) & (ir >= args.min_indel_reads) + + # sanity: the stratum must contain every confirmed edit, or the thresholds are wrong + lost = int((conf & ~in_stratum).sum()) + if lost: + sys.exit(f"ERROR: {lost} confirmed edit(s) fall OUTSIDE the stratum " + f"(if>={args.min_if}, indel_reads>={args.min_indel_reads}). The review filter " + f"must be wrong -- a confirmed edit cannot be outside the reviewed set.") + + rev = g[in_stratum].copy() + rev["curated_label"] = conf[in_stratum].astype(int) + rev["guide"] = rev["sample_name"].map(lambda x: guide_from_sample(x, GUIDE_ALIAS)) + # one site can be reviewed in several replicates of the same guide; if any replicate was + # confirmed the site is a real edit, so take the max + keys = (rev.groupby(["guide", "chrom", "start"], as_index=False)["curated_label"].max()) + print(f"reviewed stratum: {len(keys)} sites over {keys.guide.nunique()} guides " + f"({int(keys.curated_label.sum())} confirmed, " + f"{int((keys.curated_label == 0).sum())} human-rejected)") + + t = pd.read_csv(args.training, sep="\t", low_memory=False) + t["chrom"] = t["chrom"].astype(str) + t["start"] = pd.to_numeric(t["start"], errors="coerce").astype("Int64") + if "guide" not in t.columns: + sys.exit("ERROR: training table has no `guide` column to join on.") + m = t.merge(keys, on=["guide", "chrom", "start"], how="inner") + if m.empty: + sys.exit("ERROR: the gold/training join produced 0 rows -- check guide resolution.") + matched = set(keys.guide) & set(t.guide) + missing = sorted(set(keys.guide) - set(t.guide)) + print(f" guides matched: {len(matched)}/{keys.guide.nunique()}" + + (f"; absent from the scored cohort: {missing}" if missing else "")) + + # the curated label REPLACES the ECS-threshold label; keep the old one for comparison + m = m.rename(columns={"label": "label_ecs_threshold"}) + m["label"] = m["curated_label"] + m.to_csv(args.out, sep="\t", index=False) + n_pos = int((m.label == 1).sum()) + print(f"wrote {args.out}: {len(m)} rows joined to features " + f"({n_pos} positive / {len(m) - n_pos} negative) over {m['sample'].nunique()} samples") + if "label_ecs_threshold" in m.columns: + agree = int((m.label == m.label_ecs_threshold).sum()) + print(f" the ECS-threshold label agrees with the human on {agree}/{len(m)} of these rows") + + +if __name__ == "__main__": + main() diff --git a/bin/circos.conf b/bin/circos.conf index d161cbb..c3ec275 100755 --- a/bin/circos.conf +++ b/bin/circos.conf @@ -1,4 +1,6 @@ -karyotype = /circos-0.69-9/data/karyotype/karyotype.human.hg38.txt +# Relative path: circos resolves it against its own install dir, so this survives a container +# version bump. An absolute /circos-/... path does not -- see make_circos_plot.nf. +karyotype = data/karyotype/karyotype.human.hg38.txt @@ -44,8 +46,5 @@ glyph_stroke_thickness = 2p - - - <> <> diff --git a/bin/combine_offtarget_results.py b/bin/combine_offtarget_results.py new file mode 100755 index 0000000..fa1b7d4 --- /dev/null +++ b/bin/combine_offtarget_results.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 +"""Combine predicted off-target sites for one gRNA across tools into a single table. + +Merges the native outputs of Cas-OFFinder (bulge mode), CRISPRme, and (optionally) IDT +into the canonical off-target sites schema the OFFTARGET arm consumes as a per-guide +``target_file``: + + Source,DNA_Sequence,PAM,Chromosome,Strand,Start,Bulge_Type,Mismatch,Bulge_Size,On_target + +Sites predicted by more than one tool (same Chromosome+Start+PAM) collapse to one row +whose ``Source`` is the ``|``-joined list of contributing tools. This is the hardened, +argparse-driven successor to the ``Combine_offtarget_results.py`` prototype; at least one +source is required and any source may be omitted (IDT is off by default). + +The per-source coordinate adjustments (strand-dependent, and different for each tool) are +load-bearing and preserved verbatim from the validated prototype. + + combine_offtarget_results.py \\ + --casoffinder guide.casoffinder.txt \\ + --crisprme guide.crisprme.tsv \\ + [--idt guide_IDT_off-target.xlsx] \\ + -o guide.targets.csv +""" +import argparse +import sys + +import pandas as pd + +__version__ = "1.0.0" + +# The canonical schema (underscore headers, `Strand`) — matches assets/stub/*.targets.csv +# and what bin/make_hotspot_vcf.py / bin/find_edited_reads.py expect downstream. +COLUMNS = ["Source", "DNA_Sequence", "PAM", "Chromosome", "Strand", "Start", + "Bulge_Type", "Mismatch", "Bulge_Size", "On_target"] + + +def parse_idt(path): + """IDT off-target Excel export -> rows in the canonical schema. + + Expected columns: 'Sequence', 'PAM', '#MM', 'Locus' (e.g. 'chr19:+7900116'). + The on-target row has a blank/NaN '#MM'. + """ + rows = [] + idt = pd.read_excel(path) + for _, row in idt.iterrows(): + seq = str(row["Sequence"]) + pam = row["PAM"] + mismatch = str(row["#MM"]) # 'nan' for the on-target row + locus = str(row["Locus"]).split(":") + chrom = locus[0] + strand = locus[1][0] + loci = int(locus[1][1:]) + # IDT reports the PAM-distal end on '+' and needs +1 on '-' to reach the site start + adjusted = str(loci + len(seq)) if strand == "+" else str(loci + 1) + on_target = 1 if mismatch == "nan" else 0 + rows.append(["IDT", seq, pam, chrom, strand, adjusted, + "mismatch", mismatch, "NA", on_target]) + return rows + + +def parse_casoffinder(path): + """Cas-OFFinder v3 native bulge output (tab-sep, '#' header lines) -> canonical rows. + + Columns (v3): Id, Bulge Type, crRNA, DNA, Chromosome, Location, Direction, Mismatches, Bulge Size. + Cas-OFFinder >=3.0 does DNA/RNA bulges natively (no separate wrapper) and prepends an `Id` + column vs the old 2.4 / cas-offinder-bulge layout; its header/comment lines start with '#'. + """ + rows = [] + with open(path) as fh: + for line in fh: + if not line.strip() or line.startswith("#"): + continue + c = line.rstrip("\n").split("\t") + bulge_type = c[1] + dna = c[3] + dna_only = dna[0:len(dna) - 4] + pam = dna[len(dna) - 3:len(dna)] + chrom = c[4] + position = int(c[5]) + direction = c[6] + adjusted = str(position + (len(dna) - 3)) if direction == "+" else str(position + 4) + mismatches = c[7] + bulge_size = c[8] + on_target = 1 if (bulge_type == "X" and mismatches == "0" and bulge_size == "0") else 0 + rows.append(["CasOffFinder", dna_only, pam, chrom, direction, adjusted, + bulge_type, mismatches, bulge_size, on_target]) + return rows + + +def parse_crisprme(path): + """CRISPRme (>=2.1) *_integrated_results.tsv (one header line) -> canonical rows. + + complete-search writes this loose in Results//. Columns used: Spacer+PAM[0], + Chromosome[1], Start_coordinate[2], Strand[3], Aligned_protospacer+PAM_REF[5], PAM[7], + Mismatches[8], Bulges[9], Bulge_type[15]. Cas-OFFinder and CRISPRme report a site's + coordinate up to ~2 bp apart (bulge handling differs), so the same physical site may not + merge to one row across tools — harmless, since the downstream targets VCF windows each + site by +/- hotspot_window_size and merges overlapping intervals. + """ + rows = [] + with open(path) as fh: + fh.readline() # header (single line, no leading '#') + for line in fh: + if not line.strip(): + continue + c = line.rstrip("\n").split("\t") + bulge_type = c[15] + dna = c[5] + dna_only = dna[0:len(dna) - 3] + pam = c[7] + chrom = c[1] + start = int(c[2]) + direction = c[3] + adjusted = str(start + (len(dna) - 4)) if direction == "+" else str(start + 4) + mismatches = c[8] + bulge_size = c[9] + on_target = 1 if (bulge_type == "X" and mismatches == "0" and bulge_size == "0") else 0 + rows.append(["CrisprME", dna_only, pam, chrom, direction, adjusted, + bulge_type, mismatches, bulge_size, on_target]) + return rows + + +def combine(rows): + """Rows -> deduplicated DataFrame in canonical schema/column order.""" + df = pd.DataFrame(rows, columns=COLUMNS) + + # Numeric coercion so `min` is well-defined across mixed string inputs (IDT emits + # 'nan'/'NA'); NaNs are ignored by min, and an all-NaN group stays NaN. + df["Mismatch"] = pd.to_numeric(df["Mismatch"], errors="coerce") + df["Bulge_Size"] = pd.to_numeric(df["Bulge_Size"], errors="coerce") + + # Collapse the same physical site predicted by multiple tools into one row. + grouped = df.groupby(["Chromosome", "Start", "PAM"], as_index=False).agg({ + "Source": lambda x: "|".join(x), + "DNA_Sequence": "first", + "Strand": "first", + "Bulge_Type": "first", + "Mismatch": "min", + "Bulge_Size": "min", + "On_target": "max", + }) + # Nullable integer display: whole numbers (0, 3, …) not floats (0.0), and an empty + # cell for a genuinely-absent value (e.g. a pure-IDT on-target with no mismatch count). + for col in ("Mismatch", "Bulge_Size"): + grouped[col] = grouped[col].astype("Int64") + return grouped[COLUMNS] + + +def main(argv=None): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--casoffinder", help="Cas-OFFinder bulge output (.txt)") + ap.add_argument("--crisprme", help="CRISPRme targets/best-hits (.tsv)") + ap.add_argument("--idt", help="IDT off-target export (.xlsx); optional") + ap.add_argument("--pam", help="PAM used for the search (recorded for provenance only)") + ap.add_argument("-o", "--output", required=True, help="Output combined sites CSV") + ap.add_argument("--version", action="version", version=f"%(prog)s {__version__}") + args = ap.parse_args(argv) + + if not (args.casoffinder or args.crisprme or args.idt): + ap.error("provide at least one of --casoffinder / --crisprme / --idt") + + rows = [] + if args.idt: + rows += parse_idt(args.idt) + if args.casoffinder: + rows += parse_casoffinder(args.casoffinder) + if args.crisprme: + rows += parse_crisprme(args.crisprme) + + if not rows: + print("WARNING: no off-target sites parsed from the provided source(s); " + "writing header-only output", file=sys.stderr) + pd.DataFrame(columns=COLUMNS).to_csv(args.output, index=False) + return 0 + + combine(rows).to_csv(args.output, index=False) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/bin/compare_to_baseline.py b/bin/compare_to_baseline.py new file mode 100755 index 0000000..731c730 --- /dev/null +++ b/bin/compare_to_baseline.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 +""" +compare_to_baseline.py — does the ML actually buy anything over the rules? + +The question this answers +------------------------- +The SCGE pipeline already finds indels: `get_indels.nf` runs `bin/find_edited_reads.py` (with +`--enable-crispr-prediction` commented out, so it is rules only) and a human then reviews the +output in IGV. The cost of that workflow is the size of the review queue. So the claim for the +ML arm is NOT "it detects edits" — it is: + + same recall, far fewer sites to look at. + +That is a precision statement at matched recall, and this script measures it against the curated +AAVS1 truth (crispr_ml/AAVS1_training_{tp,tn}.tsv). + +Four arms, all scored on ONE denominator: unique curated hotspot sites +--------------------------------------------------------------------- + 1. ECS rules, ungated every site with any indel read <- what find_edited_reads.py emits + 2. ECS rules + somatic indel>0, control==0, indel_frac>t <- what a reviewer would prefilter + 3. WGS rules only the model's own stage-1 gate, no model + 4. WGS + ML verdict contains LIKELY EDIT + 5. WGS + ML + cut gate ... and the indel sits near the predicted cut site + +Arms 1-2 read the ECS analysis TSVs (5000x targeted). Arms 3-5 read training.tsv (30x WGS). +**That difference is the point and must be stated, not hidden:** the ML arm is doing a harder job +on ~150x less depth. Arm 3 exists so the model's contribution can be separated from the data +type — it is the same input as arms 4-5, rules only. + +Counting rule +------------- +Every arm is collapsed to **unique (chrom, start) sites** before counting, because the raw tables +are per-sample and the curated truth is per-site. Comparing a per-sample-call count against a +per-site count inflates the ratio; the plan for this work called that out explicitly. +""" +import argparse +import glob +import os +import sys + +import pandas as pd + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from validate_recall_aavs1 import load_truth, DEFAULT_TP, DEFAULT_TN, SLACK, _near + +# From wgs_shape_model.pkl's own `stage1_filter` metadata, minus the homology gate (at a hotspot +# panel every site is a predicted site by construction, so min_mm/is_target would be circular). +STAGE1_MIN_IFRAC = 0.05 +STAGE1_MAX_CTRL = 0.02 +STAGE1_MIN_SPAN = 8 + + +def site_set(df, chrom_col="chrom", pos_col="start"): + return {(c, int(p)) for c, p in zip(df[chrom_col], df[pos_col]) if pd.notna(p)} + + +def score_arm(name, sites, tp_set, tn_set, slack, note=""): + """Intersect a candidate site set with the curated truth.""" + tp = sum(1 for c, p in sites if _near(c, p, tp_set, slack)) + fp = sum(1 for c, p in sites if _near(c, p, tn_set, slack)) + n_tp_total = len(tp_set) + return {"arm": name, "queue": len(sites), "TP": tp, "FP": fp, + "recall": tp / n_tp_total if n_tp_total else float("nan"), + "precision": tp / (tp + fp) if (tp + fp) else float("nan"), + "note": note} + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--training", required=True, help="training.tsv (the WGS arm)") + ap.add_argument("--ecs-glob", required=True, + help="glob for *.offtarget_analysis.tsv (the rules-only ECS baseline)") + ap.add_argument("--tp", default=DEFAULT_TP) + ap.add_argument("--tn", default=DEFAULT_TN) + ap.add_argument("--slack", type=int, default=SLACK) + ap.add_argument("--somatic-min-ifrac", type=float, default=0.01, + help="ECS somatic prefilter: minimum indel_fraction (default 0.01)") + ap.add_argument("--max-cut-dist", type=float, default=10.0, + help="cut-site gate for the last arm (default 10 bp)") + ap.add_argument("--out", help="write the comparison table here as CSV") + args = ap.parse_args() + + tp_set, tn_set = load_truth(args.tp, args.tn) + slack = args.slack + rows = [] + + # ---- arms 1-2: the rules-only ECS baseline ----------------------------------------- + files = sorted(glob.glob(args.ecs_glob)) + if not files: + sys.exit(f"ERROR: no ECS analysis files matched {args.ecs_glob}") + any_indel, somatic = set(), set() + for f in files: + d = pd.read_csv(f, sep="\t", low_memory=False) + any_indel |= site_set(d[d["indel_reads"] > 0]) + m = ((d["indel_reads"] > 0) & (d["control_indel_reads"] == 0) + & (d["indel_fraction"] > args.somatic_min_ifrac)) + somatic |= site_set(d[m]) + print(f"\nECS baseline: {len(files)} sample tables") + rows.append(score_arm("ECS rules, any indel read", any_indel, tp_set, tn_set, slack, + "find_edited_reads.py raw output")) + rows.append(score_arm(f"ECS rules + somatic gate", somatic, tp_set, tn_set, slack, + f"indel>0, ctrl==0, if>{args.somatic_min_ifrac:g}")) + + # ---- arms 3-5: the WGS arm ---------------------------------------------------------- + t = pd.read_csv(args.training, sep="\t", low_memory=False) + t["_called"] = t["verdict"].astype(str).str.contains("LIKELY EDIT", na=False) + + stage1 = ((t["indel_frac"] > STAGE1_MIN_IFRAC) + & (t["ctrl_if"].fillna(0) < STAGE1_MAX_CTRL) + & (t["spanning"] >= STAGE1_MIN_SPAN)) + rows.append(score_arm("WGS rules only (no model)", site_set(t[stage1]), tp_set, tn_set, slack, + f"if>{STAGE1_MIN_IFRAC}, ctrl<{STAGE1_MAX_CTRL}, span>={STAGE1_MIN_SPAN}")) + rows.append(score_arm("WGS + ML shape ranker", site_set(t[t["_called"]]), tp_set, tn_set, slack, + "verdict = LIKELY EDIT")) + + if {"modal_pos", "start"} <= set(t.columns): + cut = (t["modal_pos"] - t["start"]).abs() + gated = t["_called"] & (cut <= args.max_cut_dist) + rows.append(score_arm(f"WGS + ML + cut gate <={args.max_cut_dist:g}bp", + site_set(t[gated]), tp_set, tn_set, slack, + "indel must sit near the predicted cut")) + + res = pd.DataFrame(rows) + base = res.loc[res["arm"].str.startswith("ECS rules + somatic"), "queue"] + base = float(base.iloc[0]) if len(base) else float("nan") + res["fold_vs_somatic_baseline"] = base / res["queue"].replace(0, pd.NA) + + print() + print("=" * 100) + print("REVIEW-QUEUE SIZE AT MATCHED RECALL (curated AAVS1 truth: " + f"{len(tp_set)} TP sites, {len(tn_set)} TN sites)") + print("=" * 100) + hdr = f"{'arm':<34} {'queue':>7} {'TP':>3} {'FP':>5} {'recall':>7} {'prec':>7} {'fold':>6} note" + print(hdr) + print("-" * 100) + for _, r in res.iterrows(): + fold = "" if pd.isna(r["fold_vs_somatic_baseline"]) else f"{r['fold_vs_somatic_baseline']:.0f}x" + print(f"{r['arm']:<34} {r['queue']:>7,d} {r['TP']:>3d} {r['FP']:>5,d} " + f"{r['recall']:>7.3f} {r['precision']:>7.3f} {fold:>6} {r['note']}") + print("-" * 100) + print(" 'queue' = unique sites a human would have to open in IGV.") + print(" 'fold' = shrinkage vs the ECS somatic-gated baseline.") + print(" Arms 1-2 use ECS (~5000x targeted); arms 3-5 use WGS (~30x). The ML arm reaches the") + print(" same recall on ~150x less depth. Arm 3 is the same input as 4-5 with no model, so") + print(" the 3 -> 4 step is the model's own contribution.") + + if args.out: + res.to_csv(args.out, index=False) + print(f"\nwrote {args.out}") + + +if __name__ == "__main__": + main() diff --git a/bin/compile_report_data.py b/bin/compile_report_data.py old mode 100644 new mode 100755 index 1f8c1c7..2d76115 --- a/bin/compile_report_data.py +++ b/bin/compile_report_data.py @@ -23,7 +23,6 @@ def parse_offtarget_file(file_path): records.append(row_dict) return records - def parse_coverage_file(file_path): """Parse a coverage file and return the coverage value.""" if not file_path: @@ -35,7 +34,6 @@ def parse_coverage_file(file_path): except (IOError, ValueError, IndexError): return None - def parse_vcf_file(file_path): """Parse a VCF file and return a list of dictionaries.""" records = [] @@ -70,34 +68,33 @@ def main(): """ parser = argparse.ArgumentParser(description="Compile data for Quarto report.") parser.add_argument("--sample_id", required=True, help="Sample ID.") - parser.add_argument("--transgene", required=True, help="Transgene description string.") - parser.add_argument("--cna_plot", required=False, default=None, help="Path to CNA plot PNG.") - parser.add_argument("--baf_plot", required=False, default=None, help="Path to BAF plot PNG.") - parser.add_argument("--circos_plot", required=False, default=None, help="Path to Circos plot PNG.") - parser.add_argument("--hotspot_file", required=False, default=None, help="Path to hotspot CSV file.") - parser.add_argument("--on_target_sv_transgene", required=True, help="Path to VEP-annotated on-target SV and transgene integration TSV.") - parser.add_argument("--vcf_tsv", required=True, help="Path to VEP-annotated small variant TSV for targeted gene mutations.") - parser.add_argument("--off_target_indels", required=True, help="Path to off-target indel analysis file.") - parser.add_argument("--bnd_vcf", required=False, help="Path to BND VCF file from indels.") - parser.add_argument("--control_sample", required=False, default="N/A", help="Control/normal sample identifier.") + parser.add_argument("--control_id", required=False, default="N/A", help="Control/normal sample identifier.") parser.add_argument("--grnas", required=False, default="", help="Comma-separated list of gRNAs.") parser.add_argument("--tumor_coverage", required=False, help="Path to tumor coverage metrics file.") parser.add_argument("--normal_coverage", required=False, help="Path to normal coverage metrics file.") + parser.add_argument("--cna_plot", required=False, default=None, help="Path to CNA plot PNG.") + parser.add_argument("--baf_plot", required=False, default=None, help="Path to BAF plot PNG.") + parser.add_argument("--circos_plot", required=False, default=None, help="Path to Circos plot PNG.") + parser.add_argument("--transgene_insertions", required=False, help="Path to VEP-annotated on-target SV and transgene integration TSV.") + parser.add_argument("--transgene_name", required=False, help="Transgene description string.") + parser.add_argument("--somatic_variants", required=True, help="Path to VEP-annotated small variant TSV for targeted gene mutations.") + parser.add_argument("--offtarget_indels", required=True, help="Path to off-target indel analysis file.") + parser.add_argument("--offtarget_svs", required=False, help="Path to BND VCF file from indels.") parser.add_argument("-o", "--output", required=True, help="Output JSON file path.") args = parser.parse_args() # Parse the off-target indel file - off_target_data = parse_offtarget_file(args.off_target_indels) + off_target_data = parse_offtarget_file(args.offtarget_indels) # Parse the BND VCF file - bnd_vcf_data = parse_vcf_file(args.bnd_vcf) + bnd_vcf_data = parse_vcf_file(args.offtarget_svs) # Parse the on-target SV and transgene data - on_target_sv_transgene_data = [] - if args.on_target_sv_transgene and os.path.exists(args.on_target_sv_transgene): + transgene_insertions = [] + if args.transgene_insertions and os.path.exists(args.transgene_insertions): lines = [] - with open(args.on_target_sv_transgene, 'r') as f: + with open(args.transgene_insertions, 'r') as f: for line in f: # Skip VEP header comments if line.startswith('##'): @@ -111,13 +108,13 @@ def main(): df = pd.read_csv(StringIO(data_str), sep='\\t', engine='python') # Clean the leading '#' from the first column name df.rename(columns={df.columns[0]: df.columns[0].lstrip('#')}, inplace=True) - on_target_sv_transgene_data = df.to_dict('records') + transgene_insertions = df.to_dict('records') # Parse targeted gene mutations (small variants) TSV if present targeted_gene_mutations = [] try: sv_df = pd.read_csv( - args.vcf_tsv, + args.somatic_variants, sep=' ', comment='#', keep_default_na=False, @@ -160,22 +157,22 @@ def main(): # Create a dictionary to hold all the report data. report_data = { "sample_id": args.sample_id, - "transgene_description": args.transgene, + "transgene_description": args.transgene_name, "plots": { "cna": args.cna_plot, "baf": args.baf_plot, "circos": args.circos_plot }, "tables": { - "on_target_sv_transgene": on_target_sv_transgene_data, + "on_target_sv_transgene": transgene_insertions, "off_target_indels": off_target_data, "targeted_gene_mutations": targeted_gene_mutations, "bnd_vcf": bnd_vcf_data }, "metadata": { "drug_product": args.sample_id, - "hotspot_file": args.hotspot_file, - "control_sample": args.control_sample, +# "hotspot_file": args.hotspot_file, + "control_sample": args.control_id, "assay": "WGS", "grnas": [s.strip() for s in args.grnas.split(",") if s.strip()], "mean_coverage": { @@ -201,6 +198,7 @@ def require(path, container): require(["plots","cna"], report_data) if args.baf_plot is not None: require(["plots","baf"], report_data) + require(["tables","on_target_sv_transgene"], report_data) require(["tables","off_target_indels"], report_data) require(["metadata","drug_product"], report_data) diff --git a/bin/convert_mgi_samplemap.py b/bin/convert_mgi_samplemap.py old mode 100644 new mode 100755 diff --git a/bin/create_fastq_list.py b/bin/create_fastq_list.py old mode 100644 new mode 100755 diff --git a/bin/cut_distance_model.py b/bin/cut_distance_model.py new file mode 100644 index 0000000..be68fbd --- /dev/null +++ b/bin/cut_distance_model.py @@ -0,0 +1,275 @@ +#!/usr/bin/env python3 +"""cut_distance_model.py — fit the distance-from-cut distribution empirically, as a spatial prior. + +The question +------------ +`review_filter.py` treats distance from the predicted cut as a boolean: keep if `cut_dist_min <= +10`, drop otherwise. That threshold was never derived from the data — it is inherited from the +caller's own `-d/--max-mutation-distance` default. This script asks what the distribution actually +looks like and what a properly-specified spatial model would say instead. + +The model +--------- +Two components, one for each physical process: + + P(d | background) an artifact has no reason to prefer any offset relative to a predicted cut + site, so the null is Uniform over the admissible window: P(d) = 1/W. + P(d | signal) Cas9 cuts blunt, 3 bp 5' of the PAM. A real edit therefore sits AT the cut, + broadened only by repair microhomology and by where the aligner chose to + place the indel. The prediction is a sharp spike at 0-1 bp. + +Given both, the evidence carried by an observed distance is the likelihood ratio + + LR(d) = P(d | signal) / P(d | background) + +which is a real likelihood ratio, unlike AQ -- see docs/NOISE_MODEL.md, which is careful about +that distinction. LR turns a boolean gate into a continuous quantity on the same evidence scale as +AQ, so the two can be added in log space instead of acting as independent hurdles. + +Estimation +---------- +The signal pmf is the empirical distribution with add-one smoothing (so no bin has zero +probability and LR stays finite). A discretised half-normal is also fitted and reported, because a +one-parameter form is easier to defend and to transfer to another cohort than 11 empirical bins. +The background is Uniform by construction; the script tests that assumption rather than asserting +it, with a chi-square over the observed off-target bins. + +TRUNCATION — read this before quoting anything about the tail +-------------------------------------------------------------- +The caller's `-d` default is 10 and `get_indels.nf` passes no override, so `min_cut_distance` is +only ever observed on events the caller already accepted at <= 10 bp. The window is 0..10 and the +distribution beyond it is not estimable from these tables: what is measured is the shape INSIDE +the window we are allowed to see, not the full spatial distribution. + +`indel_info` field 7 is a different and always-larger quantity -- the distance from the event's +ANCHOR rather than the minimum over the event's span -- and it is not capped, reaching 28 bp. It +is reported here for tail shape only, clearly separated, and must not be pooled with +`min_cut_distance`. + +usage: + cut_distance_model.py --tables 'results_cart_bnd/*/*.offtarget_analysis.tsv' \ + --queue-all results_cart_bnd/review/review_queue_all.tsv \ + --truth-wgs '.../cart_wgs_merged.xlsx' --figdir docs/images +""" +import argparse +import glob +import os +import sys + +import numpy as np +import pandas as pd +from scipy.stats import chisquare, norm + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import noise_model as nm # noqa: E402 + +WINDOW = 11 # admissible bins, 0..10 inclusive -- set by the caller's -d default + + +def hist(d, w=WINDOW): + d = pd.to_numeric(pd.Series(d), errors="coerce").dropna().astype(int) + d = d[(d >= 0) & (d < w)] + return np.array([int((d == i).sum()) for i in range(w)]) + + +def smoothed_pmf(counts): + """Add-one (Laplace) smoothing. Keeps LR finite in bins no signal event happened to land in.""" + c = counts.astype(float) + 1.0 + return c / c.sum() + + +def halfnormal_pmf(sigma, w=WINDOW): + """Discretised half-normal on 0..w-1: mass of [d-0.5, d+0.5) folded about zero.""" + edges = np.arange(w + 1) - 0.5 + edges[0] = 0.0 + cdf = 2 * norm.cdf(edges / sigma) - 1.0 + p = np.diff(cdf) + return p / p.sum() + + +def fit_halfnormal(d): + """MLE for a half-normal scale is sqrt(mean(d^2)); the continuity correction is left out + deliberately, since it moves sigma by less than the sampling error at these counts.""" + d = np.asarray(d, dtype=float) + return float(np.sqrt(np.mean(d ** 2))) if len(d) else float("nan") + + +def sweep(pos, neg, label_pos="confirmed", label_neg="rejected"): + print(f" threshold {label_pos} kept {label_neg} kept") + for t in range(0, WINDOW): + p = int((pos <= t).sum()) + n = int((neg <= t).sum()) + print(f" d<={t:<2d} {p:3d}/{len(pos):<3d} {n:3d}/{len(neg):<3d}") + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--tables", required=True, help="glob for *.offtarget_analysis.tsv") + ap.add_argument("--queue-all", required=True, help="review_queue_all.tsv") + ap.add_argument("--truth-wgs", help="cart_wgs_merged.xlsx") + ap.add_argument("--figdir") + a = ap.parse_args() + + paths = sorted(glob.glob(a.tables)) + df = nm.load_tables(paths) + ev = df[df.indel_reads > 0] + print(f"tables {len(paths)} site-rows {len(df)} rows with indel evidence {len(ev)}") + + # --------------------------------------------------------------------------------------- + # 1. Background: is it Uniform? + # --------------------------------------------------------------------------------------- + print("\n" + "=" * 94) + print("BACKGROUND — off-target rows with indel evidence") + print("=" * 94) + bg = hist(ev[ev.is_target == 0].min_cut_distance) + pct = bg / bg.sum() * 100 + print(f"n = {bg.sum()} bins 0..{WINDOW-1}") + print("counts :", bg.tolist()) + print("percent:", np.round(pct, 2).tolist(), f" uniform expectation {100/WINDOW:.2f}") + chi = chisquare(bg) + print(f"chi-square vs Uniform: stat {chi.statistic:.1f}, p = {chi.pvalue:.4f}") + print(f"spread: min {pct.min():.2f}% max {pct.max():.2f}% " + f"(largest deviation from uniform {np.abs(pct - 100/WINDOW).max():.2f} points)") + if chi.pvalue < 0.05: + print("NOTE: strict uniformity is rejected. At n = %d even a fraction-of-a-point wobble is" + % bg.sum()) + print(" detectable, and every bin is within ~1.1 points of flat, so Uniform remains a") + print(" good working null -- but it is an approximation, not an exact property.") + + # --------------------------------------------------------------------------------------- + # 2. Signal + # --------------------------------------------------------------------------------------- + print("\n" + "=" * 94) + print("SIGNAL — on-target rows with indel evidence (real Cas9 cuts)") + print("=" * 94) + on = ev[ev.is_target == 1] + sg = hist(on.min_cut_distance) + print(f"n = {sg.sum()}") + print("counts :", sg.tolist()) + print("percent:", np.round(sg / sg.sum() * 100, 2).tolist()) + print(f"mass at d <= 1: {sg[:2].sum()}/{sg.sum()} = {sg[:2].sum()/sg.sum()*100:.1f}%") + dvals = pd.to_numeric(on.min_cut_distance, errors="coerce").dropna().astype(int) + inw = dvals[dvals < WINDOW] + sigma = fit_halfnormal(inw) + print(f"discretised half-normal MLE: sigma = {sigma:.3f} bp") + print("half-normal pmf:", np.round(halfnormal_pmf(sigma), 4).tolist()) + # sqrt(mean(d^2)) is driven by the largest observation, so with n this small a single stray + # event moves it a long way. Say so rather than presenting the fit as if it were stable. + sig_trim = fit_halfnormal(inw[inw <= 2]) + print(f"same fit excluding events beyond 2 bp ({int((inw>2).sum())} of {len(inw)}): " + f"sigma = {sig_trim:.3f} bp") + print(f"The MLE is not robust here: it puts {halfnormal_pmf(sigma)[0]:.2f} at d=0 against an") + print(f"empirical {sg[0]/sg.sum():.2f}, because sqrt(mean(d^2)) is dominated by the tail. The") + print("LR below therefore uses the smoothed EMPIRICAL pmf; the half-normal is reported only as") + print("a transferable one-parameter summary, and should be refitted per cohort if used.") + + # --------------------------------------------------------------------------------------- + # 3. The likelihood ratio + # --------------------------------------------------------------------------------------- + print("\n" + "=" * 94) + print("LIKELIHOOD RATIO LR(d) = P(d|signal) / P(d|background)") + print("=" * 94) + p_sig = smoothed_pmf(sg) + p_bg = np.full(WINDOW, 1.0 / WINDOW) + lr = p_sig / p_bg + print(" d P(d|signal) P(d|bg) LR 10log10 LR (evidence, dB)") + for d in range(WINDOW): + print(f" {d:2d} {p_sig[d]:.4f} {p_bg[d]:.4f} {lr[d]:7.3f} " + f"{10*np.log10(lr[d]):+7.2f}") + print("\nThe last column is on the same decibel scale as AQ, which is the point: a distance of") + print(f"0 contributes {10*np.log10(lr[0]):+.1f} dB of evidence and a distance of 10 contributes") + print(f"{10*np.log10(lr[-1]):+.1f} dB, instead of both being 'inside the window, therefore fine'.") + + # --------------------------------------------------------------------------------------- + # 4. Validation against the curated label + # --------------------------------------------------------------------------------------- + if a.truth_wgs: + lab = nm.wgs_curated_label(a.truth_wgs) + q = pd.read_csv(a.queue_all, sep="\t") + q["guide"] = q.sample_name.map(nm.guide_of) + q["chrom"] = q.chrom.astype(str) + m = q.merge(lab, on=["guide", "chrom", "start"], how="inner") + pos = pd.to_numeric(m[m.curated_label == 1].cut_dist_min, errors="coerce") + neg = pd.to_numeric(m[m.curated_label == 0].cut_dist_min, errors="coerce") + print("\n" + "=" * 94) + print("VALIDATION — curated WGS label, gated rows") + print("=" * 94) + print(f"joined {len(m)} rows: {len(pos)} confirmed / {len(neg)} human-rejected") + sweep(pos, neg) + safe = [t for t in range(WINDOW) if int((pos <= t).sum()) == len(pos)] + if safe: + t0 = min(safe) + print(f"\ntightest threshold holding full recall: d <= {t0}") + print(f" at d <= {t0}: keeps {int((neg<=t0).sum())}/{len(neg)} rejected rows, " + f"vs {int((neg<=10).sum())}/{len(neg)} at the shipped d <= 10") + + # What it is worth AFTER the other rules have run -- the only number that decides anything. + kept = m[m.why_dropped.fillna("") == ""] + allq = q[q.why_dropped.fillna("") == ""] + kp = pd.to_numeric(kept[kept.curated_label == 1].cut_dist_min, errors="coerce") + kn = pd.to_numeric(kept[kept.curated_label == 0].cut_dist_min, errors="coerce") + aq = pd.to_numeric(allq.cut_dist_min, errors="coerce") + print("\n-- marginal effect on the FINAL queue, after every other rule has run --") + print(f"queue {len(allq)} rows; labelled subset {len(kp)} confirmed / {len(kn)} rejected") + for t in (1, 2, 3, 5, 10): + print(f" d<={t:2d}: queue {int((aq<=t).sum()):3d}/{len(allq)} " + f"confirmed {int((kp<=t).sum())}/{len(kp)} rejected {int((kn<=t).sum())}/{len(kn)}") + print("\nIf those rows barely move, the spatial rule is REDUNDANT with the rules ahead of") + print("it on this cohort, and its value is as a score for ranking and for the single-sample") + print("case where no matched control exists -- not as a tighter gate. Report it that way.") + + # --------------------------------------------------------------------------------------- + # 5. Tail, from the uncapped anchor distance -- a DIFFERENT quantity + # --------------------------------------------------------------------------------------- + print("\n" + "=" * 94) + print("TAIL — from indel_info field 7 (anchor distance, uncapped). NOT min_cut_distance.") + print("=" * 94) + tail = [] + for info in ev.indel_info.dropna(): + for e in str(info).split(";"): + f = e.split("|") + if len(f) >= 11: + try: + tail.append(abs(int(f[7]))) + except ValueError: + pass + tail = np.array(tail) + if len(tail): + bc = np.bincount(tail) + print(f"events {len(tail)} median {np.median(tail):.0f} max {tail.max()}") + print("counts 0..:", bc.tolist()) + print(f"fraction beyond 10 bp: {(tail>10).mean()*100:.2f}%") + print("The anchor distance is always >= min_cut_distance, so this over-states the tail of") + print("the quantity the filter uses. It shows the tail EXISTS and is thin; it does not") + print("give its shape for min_cut_distance. Only a re-run with a larger -d could do that.") + + # --------------------------------------------------------------------------------------- + if a.figdir: + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + os.makedirs(a.figdir, exist_ok=True) + fig, ax = plt.subplots(1, 3, figsize=(14, 4)) + x = np.arange(WINDOW) + ax[0].bar(x, bg / bg.sum(), color="#777") + ax[0].axhline(1 / WINDOW, ls="--", color="crimson", label="Uniform 1/11") + ax[0].set_title(f"background: off-target (n={bg.sum()})") + ax[0].set_xlabel("distance from predicted cut (bp)"); ax[0].legend() + ax[1].bar(x, sg / sg.sum(), color="#2a6") + ax[1].plot(x, halfnormal_pmf(sigma), "o--", color="k", + label=f"half-normal $\\sigma$={sigma:.2f}") + ax[1].set_title(f"signal: on-target (n={sg.sum()})") + ax[1].set_xlabel("distance from predicted cut (bp)"); ax[1].legend() + ax[2].bar(x, 10 * np.log10(lr), color="#36c") + ax[2].axhline(0, color="k", lw=0.8) + ax[2].set_title("evidence $10\\log_{10}$ LR(d)") + ax[2].set_xlabel("distance from predicted cut (bp)"); ax[2].set_ylabel("dB") + fig.tight_layout() + p = os.path.join(a.figdir, "cut_distance_model.png") + fig.savefig(p, dpi=150) + print(f"\nwrote {p}") + + +if __name__ == "__main__": + main() diff --git a/bin/extract_variant_reads.py b/bin/extract_variant_reads.py deleted file mode 100755 index ac49be4..0000000 --- a/bin/extract_variant_reads.py +++ /dev/null @@ -1,649 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import division -import pysam -import biotite.sequence.align as align -import biotite.sequence as seq -import argparse -import re -import string -import csv, sys -import scipy.stats as stats -import pandas as pd, pyranges as pr - -# reverse complement function -def revcomp(seq): - tab = str.maketrans('ACGTacgtRYMKrymkVBHDvbhd', 'TGCAtgcaYRKMyrkmBVDHbvdh') # maketrans <- maps the reverse complement - return seq.translate(tab)[::-1] # translate(x)[::-1] <- works backward through the string, effectively reversing the string - -# make cigar tuples from a cigar string -def make_cigar_tuples(cigar): - cigar_dict = {'M': 0, 'I': 1, 'D': 2, 'N': 3, 'S': 4, 'H': 5, 'P': 6, '=': 7, 'X': 8} - # use regex to parse cigar string into tuples - cigar_tuples = re.findall(r'(\d+)([MIDNSHP=X])', cigar) - cigar_tuples = [(cigar_dict[operation],int(length)) for length, operation in cigar_tuples] - return cigar_tuples - -def cigar_summary(cigar): - cigar_dict = {'M': 0, 'I': 1, 'D': 2, 'N': 3, 'S': 4, 'H': 5, 'P': 6, '=': 7, 'X': 8} - # use regex to parse cigar string into tuples - cigar_tuples = re.findall(r'(\d+)([MIDNSHP=X])', cigar) - cigar_sum = { 'M': 0, 'I': 0, 'D': 0, 'N': 0, 'S': 0, 'H': 0, 'P': 0, '=': 0, 'X': 0 } - for length, operation in cigar_tuples: - cigar_sum[operation] += int(length) - - return cigar_sum - -def make_aligned_pairs(sup_align,refseq): - """ - Converts a supplementary alignment string into a list of aligned pairs. - - Args: - supplementary_alignment (str): Supplementary alignment string (e.g., 'chr12,107092390,-,110M41S,60,0'). - - Returns: - List of tuples: Aligned pairs (e.g., [(0, 168391768, 'C'), (1, 168391769, 'C'), ...]). - """ - # Split the supplementary alignment string into components - ref_name, ref_start, strand, cigar, _, _ = supplementary_alignment.split(',') - - # Convert positions and CIGAR to appropriate types - ref_start = int(ref_start) - cigar_ops = parse_cigar(cigar) - - # Initialize variables - aligned_pairs = [] - read_pos = 0 - ref_pos = ref_start - - for op, length in cigar_ops: - if op == 'M': # Match/mismatch - for i in range(length): - aligned_pairs.append((read_pos, ref_pos, refseq[ref_pos - ref_start])) - read_pos += 1 - ref_pos += 1 - elif op == 'I': # Insertion - for i in range(length): - aligned_pairs.append((read_pos, None, refseq[ref_pos - ref_start])) - read_pos += 1 - elif op == 'D': # Deletion - for i in range(length): - aligned_pairs.append((None, ref_pos, refseq[ref_pos - ref_start])) - ref_pos += 1 - elif op == 'S': # Soft clipping - read_pos += length - # Skipping 'H' (hard clipping) and 'N' (skipped region) as they do not appear in the read - - return aligned_pairs - - -def indels_from_aligned_pairs(pairs,readseq): - - # remove leading soft clips - while pairs[0][0] is None: - pairs = pairs[1:] - - # remove training soft clips - while pairs[-1][0] is None: - pairs = pairs[:-1] - - pairs = [ (x[0],x[1],x[2].upper(),None) for x in pairs ] - for i in range(len(pairs)): - if pairs[i][0] is not None: - pairs[i] = (pairs[i][0],readseq[pairs[i][0]],pairs[i][1],pairs[i][2]) - - variant_start_index = j-1 - variant_end_index = j-1 - j = 0 - while j < len(pairs): - if pairs[j][0] is not None and pairs[j][2] is not None: - j+=1 - continue - - if pairs[j][0] is None or pairs[j][2] is None: # indel - variant_start_index = j-1 - variant_end_index = len(pairs) - break - - j+=1 - - # construct indel tuple - indel = (pairs[variant_start_index][2],''.join([ x[3] if x[3] else '' for x in pairs[variant_start_index:variant_end_index]]),''.join([ x[1] if x[1] else '' for x in pairs[variant_start_index:variant_end_index]])) - - return indel - -# function to count the number of reads that support an indel or BND event -def add_normal_counts(df, reads, fasta, maxreads=0,handicap=5,window=25,flank=150): - - # make ref and alt sequences for each indel/BND - df['refseq'] = '' - df['altseq'] = '' - for it, row in df.iterrows(): - df.at[it,'refseq'] = fasta.fetch(row['chrom'],row['pos']-1-flank,row['pos']+len(row['ref'])+flank) - if row['type'] in ['INDEL','DEL','INS']: - df.at[it,'altseq'] = fasta.fetch(row['chrom'],row['pos']-1-flank,row['pos']-1) + row['alt'] + fasta.fetch(row['chrom'],row['pos']+len(row['ref'])-1,row['pos']+len(row['ref'])+flank) - elif row['type'] == 'BND': - df.at[it,'altseq'] = fasta.fetch(row['chrom'],row['pos']-1-flank,row['pos']-1) + (fasta.fetch(row['chrom2'],row['pos2']-1,row['pos2']+flank) if row['strands']=='++' else revcomp(fasta.fetch(row['chrom2'],row['pos2']-1-flank,row['pos2']))) - - df['control_alt_counts'] = 0 - df['control_total_counts'] = 0 - - total_reads = set() - - # iterate through reads in bam file for the first position - for read in reads: - # skip if not primary alignment or a duplicate or alignment doesnt overlap start,end - if read.is_mapped is False or \ - read.is_duplicate is True or \ - read.is_secondary is True or \ - read.is_supplementary is True or \ - read.mapping_quality == 0: - continue - - total_reads.add(read.query_name) - - # for speed: if the read has no indels, add it to the ref_count set - if len(read.cigartuples) == 1 and read.cigartuples[0][0] == 0 and read.cigartuples[0][1] == len(read.query_sequence): - continue - - for it, row in df.iterrows(): - - if read.cigartuples[0][0]==0 and read.cigartuples[-1][0]==0: - if (len(row['ref']) > len(row['alt']) and 'D' not in read.cigarstring) or (len(row['alt']) > len(row['ref']) and 'I' not in read.cigarstring): - continue - - if row['type'] == 'BND' and not read.has_tag('SA'): - continue - - refseq = row['refseq'] - altseq = row['altseq'] - - ref_align = align.align_optimal(seq.NucleotideSequence(row['refseq']),seq.NucleotideSequence(read.query_sequence),matrix=align.SubstitutionMatrix.std_nucleotide_matrix(),gap_penalty=(-10,-1),local=True,terminal_penalty=False,max_number=1)[0] - - alt_align = align.align_optimal(seq.NucleotideSequence(row['altseq']),seq.NucleotideSequence(read.query_sequence),matrix=align.SubstitutionMatrix.std_nucleotide_matrix(),gap_penalty=(-10,-1),local=True,terminal_penalty=False,max_number=1)[0] - - if alt_align.score > 0 and alt_align.score - handicap > ref_align.score: - ref_align_cigar_sum = cigar_summary(align.write_alignment_to_cigar(ref_align)) - alt_align_cigar_sum = cigar_summary(align.write_alignment_to_cigar(alt_align)) - - if ((len(row['ref'])-len(row['alt']) > 0 and ref_align_cigar_sum['D']==len(row['ref'])-len(row['alt'])) or - (len(row['alt'])-len(row['ref']) > 0 and ref_align_cigar_sum['I']==len(row['alt'])-len(row['ref']))): - df.at[it,'control_alt_counts'] += 1 - # print to stderr: found control alt count - print(f"\tFound control alt count for {row['chrom']}:{row['pos']}:{row['ref']}:{row['alt']}:{read.query_name}", file=sys.stderr) - - df['control_total_counts'] = len(total_reads) - - return df.copy() - - -# function to get indels for one amplicon from bam file -def get_indels(bam,controlbam,chr,start,end,fasta,window=100,distance=25,pam_positions=pd.NA,minSecMapQual=10,maxNM=5,svDistanceThreshold=100000,saAlignmentTolerance=5,minSoftClipLength=5,deletionDistanceThreshold=1000,minreads=1,maxcontrol=0,strict=False,verbose=False): - - # window == flanking sequence to add to read search - # distance == max distance from start/end to consider an indel, BND, or call a read wild-type. - - cigarVarDict = {'0':'M','1':'I','2':'D','3':'N','4':'S','5':'H','6':'P','7':'=','8':'X'} - - readaln = pd.DataFrame(columns=['read','chrom','pos','chrom2','pos2','ref','alt','strands','type']) - - # if verbose, print to stderr: getting reads that align within window of start and end - if verbose: - print(f"\tGetting reads that align within window of {chr}:{start}-{end}", file=sys.stderr) - - regionStart = max(start - svDistanceThreshold,1) - regionEnd = min(end + svDistanceThreshold,fasta.get_reference_length(chr)) - regionSeq = fasta.fetch(chr,regionStart-1,regionEnd) - - # get reads that align within window of start and end - for read in bam.fetch(chr, start-window, end+window, multiple_iterators = True): - - # skip if not primary alignment or a duplicate or alignment doesnt overlap start,end - if read.is_mapped is False or \ - read.is_duplicate is True or \ - read.is_secondary is True or \ - read.is_supplementary is True or \ - read.mapping_quality == 0: - continue - - cigar = read.cigartuples # get cigar info - mate_cigar = make_cigar_tuples(read.get_tag('MC')) if read.has_tag('MC') else None - - # Quality filter: Get mismatches from NM tag and subtract deleted/skipped bases from cigar - # and skip if too many mismatches - if read.has_tag('NM') and int(read.get_tag('NM')) > maxNM: - if (int(read.get_tag('NM')) - sum([x[1] for x in cigar if x[0] == 2 or x[0]==3])) > maxNM: - continue - - read_strand = "+" - if read.is_reverse is True: - read_strand = "-" - - leftSoftClip = 0 - rightSoftClip = 0 - read_reference_start = read.reference_start + 1 - read_reference_end = read.reference_end - read_next_reference_start = read.next_reference_start + 1 - read_next_reference_end = None if mate_cigar is None else read_next_reference_start + sum([x[1] for x in mate_cigar if x[0] == 0 or x[0] == 2 or x[0] == 3]) - - read_query_start = 0 - read_query_end = len(read.query_sequence) - - # setup indelinfo dictionary - indelinfo = {'read':read.query_name,'chrom':'','pos':None,'chrom2':None,'pos2':None,'strands': '','ref':'','alt':'','type':''} - - # Get left soft clip length - if cigar[0][0] == 4: - leftSoftClip = cigar[0][1] - - # Get right soft clip length - if cigar[-1][0] == 4: - rightSoftClip = cigar[-1][1] - - # - # This adjusts alignment cigars for soft clips and supplementary alignments. - # It extends the cigar if the softclips map nearby and therefore the read has a deletion. - # - - # Process left soft clip, if present - if leftSoftClip > rightSoftClip: - - # first check for local supplementary alignments - sChr, sPos, sStrand, sCigar, sMq, sNm = read.get_tag('SA').split(';')[0].split(',') if read.has_tag('SA') else [None,None,None,None,None,None] - - if (sChr != None and int(sMq)>=minSecMapQual and - int(sNm)= 4 and sCigarTuples[0][0] == 0 and sCigarTuples[0][1] == cigar[0][1]: - cigar = sCigarTuples[:-1] + [(2,read_reference_start-sPos-1)] + cigar[1:] - - else: - # if there is a supplementary alignment, then realign the entire read to the reference sequence - cigar = make_cigar_tuples(align.write_alignment_to_cigar(align.align_optimal(seq.NucleotideSequence(regionSeq[sPos-regionStart:read_reference_end-regionStart+1]), #seq.NucleotideSequence(fasta.fetch(chr,sPos-1,read_reference_end)), - seq.NucleotideSequence(read.query_sequence), - matrix=align.SubstitutionMatrix.std_nucleotide_matrix(), - gap_penalty=(-10,-1),local=False,max_number=1)[0])) - read_reference_start = sPos - - else: - # if the left soft clip is long enough, see if it supports a deletion within window - # this performs an exact match and so isnt ideal, but should be good enough for now - if leftSoftClip >= minSoftClipLength: - clippedSeq = read.query_sequence[:leftSoftClip] - refSeq = regionSeq[read_reference_start - regionStart - window + 1:read_reference_start - regionStart + 1] #fasta.fetch(chr,read_reference_start - window,read_reference_start) - # find the position of the left-most occurance of clippedSeq in refSeq - leftClipPos = refSeq.rfind(clippedSeq) - if leftClipPos != -1: - delSeq = refSeq[leftClipPos + len(clippedSeq)-1:] - cigar = [(0,len(clippedSeq))] + [(2,len(delSeq))] + cigar[1:] - read_reference_start = read_reference_end - sum([x[1] for x in cigar if x[0] == 0 or x[0] == 2 or x[0] == 3]) + 1 - - # Process right soft clip, if present - if rightSoftClip > leftSoftClip: - - # first check for local supplementary alignments - sChr, sPos, sStrand, sCigar, sMq, sNm = read.get_tag('SA').split(';')[0].split(',') if read.has_tag('SA') else [None,None,None,None,None,None] - - if (sChr != None): - sPos = int(sPos) - sCigarTuples = make_cigar_tuples(sCigar) - - if (int(sMq)>=minSecMapQual and sCigarTuples[0][0] >= 4 and sCigarTuples[-1][0] == 0 and - int(sNm) read_reference_end and - int(sPos) - read_reference_end < svDistanceThreshold): - - if sCigarTuples[0][0] >= 4 and sCigarTuples[-1][0] == 0 and sCigarTuples[-1][1] == cigar[-1][1]: - cigar = cigar[:-1] + [(2,read_reference_end-sPos)] + sCigarTuples[1:] - - else: - cigar = make_cigar_tuples(align.write_alignment_to_cigar(align.align_optimal(seq.NucleotideSequence(regionSeq[read_reference_start-regionStart:sPos-regionStart+sum([x[1] for x in sCigarTuples if x[0] == 0 or x[0] == 2 or x[0] == 3])]), #fasta.fetch(chr,read_reference_start-1,sPos-1+sum([x[1] for x in sCigarTuples if x[0] == 0 or x[0] == 2 or x[0] == 3]))), - seq.NucleotideSequence(read.query_sequence), - matrix=align.SubstitutionMatrix.std_nucleotide_matrix(), - gap_penalty=(-10,-1),local=False,max_number=1)[0])) - - read_reference_end = read_reference_start + sum([x[1] for x in cigar if x[0] == 0 or x[0] == 2 or x[0] == 3]) - - else: - # if the left soft clip is long enough, see if it supports a deletion within deletionDistanceThreshold - # this performs an exact match and so isnt ideal, but should be good enough for now - if rightSoftClip >= minSoftClipLength: - clippedSeq = read.query_sequence[-rightSoftClip:] - refSeq = regionSeq[read_reference_end-regionStart:read_reference_end-regionStart + window] #fasta.fetch(chr,read_reference_end,read_reference_end + window) - # find the position of the left-most occurance of clippedSeq in refSeq - rightClipPos = refSeq.find(clippedSeq) - if rightClipPos != -1: - delSeq = refSeq[0:rightClipPos] - cigar = cigar[:-1] + [(2,len(delSeq))] + [(0,len(clippedSeq))] - read_reference_end = read_reference_start + sum([x[1] for x in cigar if x[0] == 0 or x[0] == 2 or x[0] == 3]) - - # Adjusted read has to be within distance of the start/end positions to consider - if read_reference_start - leftSoftClip >= end + distance or read_reference_end + rightSoftClip <= start - distance: - continue - - # remove leading or trailing soft clips - if cigar[0][0] >= 4: - read_query_start += cigar[0][1] - del cigar[0] - - if cigar[-1][0] >= 4: - read_query_end -= cigar[-1][1] - del cigar[-1] - - # there are multiple cigar operations bookened by matches, the process an indel - if len(cigar) > 1: - - # adjust alignment start for first aligned block and remove it - if cigar[0][0] == 0: - read_reference_start += cigar[0][1]# sets to position before event - read_query_start = read_query_start + cigar[0][1] - del cigar[0] - - # adjust alignment end for last aligned block and remove it - if cigar[-1][0] == 0: - read_reference_end = read_reference_end - cigar[-1][1] - read_query_end = read_query_end - cigar[-1][1] - del cigar[-1] - - # If there's only one cigar operation left, it's an insertion or deletion - if len(cigar) == 1: - - # theres one event, so record the coordinates - indelinfo['chrom'] = read.reference_name - indelinfo['pos'] = read_reference_start - indelinfo['strands'] = '++' - - # if insertion - if cigar[0][0] == 1: - indelinfo['ref'] = regionSeq[read_reference_start-regionStart-1:read_reference_start-regionStart] #fasta.fetch(chr,read_reference_start-1-1,read_reference_start-1) # 0 based and position before the isertion - indelinfo['alt'] = read.query_sequence[read_query_start-1:read_query_start+cigar[0][1]] - indelinfo['type'] = 'INDEL' - - # if deletion - elif cigar[0][0] == 2 or cigar[0][0] == 3: - indelinfo['ref'] = regionSeq[read_reference_start-regionStart:read_reference_start-regionStart + cigar[0][1] + 1] #fasta.fetch(chr,read_reference_start-1,read_reference_start+cigar[0][1]) - indelinfo['alt'] = indelinfo['ref'][0] - indelinfo['type'] = 'INDEL' - - # if its a complex indel - else: - indelinfo['chrom'] = read.reference_name - indelinfo['pos'] = read_reference_start - indelinfo['strands'] = '++' - indelinfo['type'] = 'INDEL' - - # iterate through cigar and get indels - varlen = sum([ x[1] for x in cigar ]) - indelinfo['ref'] = regionSeq[read_reference_start-regionStart:read_reference_start-regionStart+sum([ x[1] for x in cigar ])+1] #fasta.fetch(chr,read_reference_start-1,read_reference_start+sum([ x[1] for x in cigar ])) - indelinfo['alt'] = read.query_sequence[read_query_start+1:read_query_start+sum([x[1] if x[0] == 1 or x[0] == 0 else 0 for x in cigar])] - - # if the read is chimeric and has a supplementary alignment near the start/end, process the chimeric read - elif read.has_tag('SA') is True and (leftSoftClip > 0 or rightSoftClip > 0): - sChr, sPos, sStrand, sCigar, sMq, sNm = read.get_tag('SA').split(';')[0].split(',') if read.has_tag('SA') else [None,None,None,None,None,None] - - sCigarTuples = make_cigar_tuples(sCigar) - sPos = int(sPos) - sEnd = sPos + sum([x[1] for x in sCigarTuples if x[0] == 0 or x[0] == 2 or x[0] == 3]) - 1 - sLeftSoftClip = sCigarTuples[0][1] if sCigarTuples[0][0] >= 4 else 0 - sRightSoftClip = sCigarTuples[-1][1] if sCigarTuples[-1][0] >= 4 else 0 - - pSeq = read.query_alignment_sequence - sSeq = read.query_sequence[sLeftSoftClip:sLeftSoftClip+sum([x[1] for x in sCigarTuples if x[0] == 0 or x[0] == 1])] if sStrand == read_strand else revcomp(read.query_sequence[sLeftSoftClip:sLeftSoftClip+sum([x[1] for x in sCigarTuples if x[0] == 0 or x[0] == 1])]) - - # correct for overlapping alignments - if len(pSeq)+len(sSeq) > len(read.query_sequence): - trimLen = len(pSeq)+len(sSeq) - len(read.query_sequence) - if sLeftSoftClip > sRightSoftClip: - sPos += trimLen - sSeq = sSeq[trimLen:] - - elif sRightSoftClip > sLeftSoftClip: - sEnd -= trimLen - sSeq = sSeq[:-trimLen] - - if (int(sMq) >= minSecMapQual and int(sNm) <= maxNM and int(sMq)>0 and - (sChr != read.reference_name or abs(int(sPos) - read_reference_start) >= svDistanceThreshold) or sStrand != read_strand or - (rightSoftClip > 0 and sEnd < read_reference_start) or (leftSoftClip > 0 and sPos > read_reference_end)): - - indelinfo['chrom'] = read.reference_name - indelinfo['chrom2'] = sChr - indelinfo['strands'] = '++'if sStrand == read_strand else '+-' - indelinfo['type'] = 'BND' - - if indelinfo['strands'] == '++': - # if --->...> ...>---> or <---<... <...<--- - if rightSoftClip > leftSoftClip and sLeftSoftClip > sRightSoftClip: - indelinfo['pos'] = read_reference_end - indelinfo['pos2'] = sPos - - # if ...>---> --->...> or <...<--- <---<... - elif leftSoftClip > rightSoftClip and sRightSoftClip > sLeftSoftClip: - indelinfo['pos'] = read_reference_start - 1 - indelinfo['pos2'] = sEnd + 1 - - else: - print(f"Error: no proper soft clip orientation found: {read.query_name}: {str(read)}", file=sys.stderr) - if strict: - exit(1) - else: - continue - - elif indelinfo['strands'] == '+-': - # if --->...> <---<... or <---<... --->...> - if rightSoftClip > leftSoftClip and sRightSoftClip > sLeftSoftClip: - indelinfo['pos'] = read_reference_end - indelinfo['pos2'] = sEnd - - # if ...>---> <...<--- or <...<--- ...>---> - elif leftSoftClip > rightSoftClip and sLeftSoftClip > sRightSoftClip: - indelinfo['pos'] = read_reference_start - 1 - indelinfo['pos2'] = sPos - - else: - print(f"Error: no proper soft clip orientation found: {read.query_name}: {str(read)}", file=sys.stderr) - if strict: - exit(1) - else: - continue - - else: - print(f"Error: no proper soft clip orientation found: {read.query_name}: {str(read)}", file=sys.stderr) - if strict: - exit(1) - else: - continue - - elif read_reference_start < end and read_reference_end > start: - indelinfo['chrom'] = chr - indelinfo['pos'] = start - indelinfo['ref'] = '.' - indelinfo['alt'] = '.' - indelinfo['type'] = 'REF' - - else: - continue - - elif read_reference_start < end and read_reference_end > start: - indelinfo['chrom'] = chr - indelinfo['pos'] = start - indelinfo['ref'] = '.' - indelinfo['alt'] = '.' - indelinfo['type'] = 'REF' - - else: - continue - - # add indel info to dataframe - readaln = pd.concat([readaln, pd.DataFrame([indelinfo])], ignore_index=True) - - # if verbose, sorting indels - if verbose: - print("\tSorting indels", file=sys.stderr) - - # group by read and sort by cigar, then sv and get the first value in each group - readaln = readaln.sort_values(by=['read','chrom','pos','chrom2','pos2','strands','ref','alt','type'],key=lambda col: col != '',ascending=False).groupby('read').first().reset_index() - indelcounts = readaln.groupby(['chrom','pos','chrom2','pos2','strands','ref','alt','type'],dropna=False).size().reset_index(name='counts') - - # need to recast as int type, but allow for NA values - indelcounts['pos'] = indelcounts['pos'].astype(pd.Int64Dtype()) - indelcounts['pos2'] = indelcounts['pos2'].astype(pd.Int64Dtype()) - - # if verbose, get control counts - if verbose: - print("\tGetting control counts", file=sys.stderr) - - # get counts of reads in the controlbam for each indel/BND - if len(indelcounts) > 0: - # add pam positions to the df - if pam_positions is not pd.NA: - indelcounts['Positions'] = [pam_positions] * len(indelcounts) - indelcounts['Distance'] = indelcounts.apply(lambda r: min([abs(r['pos'] - x) for x in r['Positions']] + [abs(r['pos'] + len(r['ref']) - 1 - x) for x in r['Positions']] ) if r['pos'] is not pd.NA else pd.NA,axis=1) - else: - indelcounts['Positions'] = pd.NA - indelcounts['Distance'] = pd.NA - - indelcounts = add_normal_counts(indelcounts, [ x for x in controlbam.fetch(contig=chr,start=start-window,end=end) ], fasta, window=distance) - - else: - indelcounts['control_alt_counts'] = 0 - indelcounts['control_total_counts'] = 0 - indelcounts['Positions'] = pd.NA - indelcounts['Distance'] = pd.NA - - - # apply filters - indelcounts = indelcounts[(indelcounts['counts'] >= minreads) | (indelcounts['ref']=='.')] - indelcounts = indelcounts[(indelcounts['control_alt_counts'] <= maxcontrol) | (indelcounts['ref']=='.')] - indelcounts = indelcounts[(indelcounts['Distance'] <= distance) | (indelcounts['ref']=='.')] - indelcounts = indelcounts[~indelcounts['alt'].str.contains('N')] - - return(indelcounts) - - -def main(): - - parser = argparse.ArgumentParser(description='Find indels in a bam file at BED coordinates') - parser.add_argument('-f','--fasta',type=str,default="/storage2/fs1/dspencer/Active/clinseq/projects/scge/data/refdata/singh_v4.3.6/hg38_PLVM_CD19_CARv4_cd34.fa",help='Reference fasta file') - parser.add_argument('-w','--window',type=int,default=100,help='Distance between off-target sites for merging intervals.') - parser.add_argument('-d','--distance',type=int,default=25,help='Window size around off-target site to identify mutations') - parser.add_argument('-m','--minreads',type=int,default=1,help='Minimum supporting reads to report an indel/bnd event.') - parser.add_argument('-c','--chromosome',type=str,default=None,help='Chromosome to process.') - parser.add_argument('-x','--maxcontrol',type=int,default=0,help='Maximum supporting reads to to report an indel/bnd event.') - parser.add_argument('-s','--strict',action='store_true',help='Exit if a read cannot be properly parsed.') - # add verbosity argument - parser.add_argument('-v','--verbose',action='store_true',help='Print verbose output') - - # add outfile argument -o or --outfile - parser.add_argument('-o','--outfile',type=str,help='Output file (optional)') - parser.add_argument('bed',help='Off-target coordinate file') - parser.add_argument('expbamfile',help='BAM file') - parser.add_argument('conbamfile',help='BAM file') - - args = parser.parse_args() - - # TODO: - # Nihdi: We need to update this code to take the file and return 2 objects: - # 1. Take the positions and make intervals that are chr,(pos-distup),(pos+distdown) and then merge them into new list of non-redunant intervals (might use pyranges for this) - # 2. The individual entries need to be retained, though, along with the information about the off-target (the exact position, the mismatches, etc) - - # verbose to stderr: processing input file - if args.verbose: - print("Processing input file", file=sys.stderr) - - # open off-target file and create ranges to search - bedDf = pd.read_csv(args.bed) - bedDf['Pos'] = bedDf['Start'] - bedDf['End'] = bedDf['Start'] - bedDf['Start'] = bedDf['Start'] - 1 - bedDf['Info'] = bedDf.apply(lambda row: f"{row['Source']},{row['DNA Sequence']},{row['PAM']},{row['Chromosome']},{row['Pos']},{row['Strand Direction']},{row['Mismatch']},{row['Bulge Type']},{row['Bulge Size']}", axis=1) - bedDf['Ontarget'] = bedDf['On_target'] - - # make pyranges object - bedPr = pr.PyRanges(bedDf[['Chromosome','Start','End','Pos','Info','Ontarget']]) - - # cluster the intervals - bedPr = bedPr.cluster(slack=args.window) - mergedBedPr = bedPr.merge(by='Cluster',strand=False,slack=args.window) - mergedBedDf = mergedBedPr.df.join(bedPr.df.groupby('Cluster')['Pos'].agg(list).reset_index().set_index('Cluster'),on='Cluster',how='left') - mergedBedDf = mergedBedDf.join(bedPr.df.groupby('Cluster')['Info'].agg(list).reset_index().set_index('Cluster'),on='Cluster',how='left') - mergedBedDf = mergedBedDf.join(bedPr.df.groupby('Cluster')['Ontarget'].agg('first').reset_index().set_index('Cluster'),on='Cluster',how='left') - - if args.chromosome is not None: - print("Processing chromosome", args.chromosome, file=sys.stderr) - mergedBedDf = mergedBedDf[mergedBedDf['Chromosome'] == args.chromosome] - - # verbose: say done - if args.verbose: - print("Done processing input file", file=sys.stderr) - - # open bam file(s) - expsamfile = pysam.AlignmentFile(args.expbamfile,"rc",reference_filename=args.fasta) - consamfile = pysam.AlignmentFile(args.conbamfile,"rc",reference_filename=args.fasta) - # open fasta file - refFasta = pysam.FastaFile(args.fasta) - - # print to outfile or stdout - if args.outfile: - sys.stdout = open(args.outfile, 'w') - - print("\t".join('chrom start end pam_positions total_reads indel_reads indel_fraction control_reads control_indel_reads control_indel_fraction indel_count indel_info bnd_count bnd_info target_info is_target'.split(' ')),flush=True) - - # iterate over mergedBedPr intervals: - for index, row in mergedBedDf.iterrows(): - - # verbose to stderr: processing interval - if args.verbose: - print(f"Processing interval {row['Chromosome']}:{row['Start']}-{row['End']}", file=sys.stderr) - - indels = get_indels(bam=expsamfile,controlbam=consamfile,chr=row['Chromosome'],start=row['Start'],end=row['End'], - fasta=refFasta,window=args.window,distance=args.distance,pam_positions=row['Pos'],minreads=args.minreads,maxcontrol=args.maxcontrol,verbose=args.verbose) - - total_reads, indel_reads, control_total_reads, control_indel_reads = 0, 0, 0, 0 - indel_fraction, control_indel_fraction = 0, 0 - indel_keys, bnd_keys = '.', '.' - bnds = [] - - if len(indels) > 0: - # get total reads in this region - total_reads = sum(indels['counts']) - indel_reads = sum(indels[indels['type']!='REF']['counts']) - control_indel_reads = int(indels['control_alt_counts'].mean()) - control_total_reads = int(indels['control_total_counts'].mean()) - - # separate BNDs and indels - bnds = indels[indels['type']=='BND'].copy() - indels = indels[indels['type']=='INDEL'].copy() - - if len(indels) > 0: - indels['Key'] = indels.apply(lambda r: f"{r['chrom']}:{r['pos']}:{r['ref']}:{r['alt']}:{r['counts']}:{r['control_alt_counts']}:{r['Distance']}", axis=1) - - if len(bnds) > 0: - bnds['Key'] = bnds.apply(lambda r: f"{r['chrom']}:{r['pos']}:{r['chrom2']}:{r['pos2']}:{r['strands']}:{r['counts']}:{r['control_alt_counts']}:{r['Distance']}", axis=1) - - # print results to tab-delimited file - indel_fraction = round(indel_reads/total_reads,4) if total_reads > 0 else 0 - control_indel_fraction = round(control_indel_reads/control_total_reads,4) if control_total_reads > 0 else 0 - indel_keys = ';'.join(indels['Key'].tolist()) if len(indels) > 0 else '.' - bnd_keys = ';'.join(bnds['Key'].tolist()) if len(bnds) > 0 else '.' - ontarget = row['Ontarget'] - offtargetsites = ';'.join(row['Info']) if len(row['Info']) > 0 else '.' - - print(f"{row['Chromosome']}\t{row['Start']}\t{row['End']}\t{';'.join([ str(x) for x in row['Pos'] ])}\t{total_reads}\t{indel_reads}\t{indel_fraction}\t{control_total_reads}\t{control_indel_reads}\t{control_indel_fraction}\t{len(indels)}\t{indel_keys}\t{len(bnds)}\t{bnd_keys}\t{offtargetsites}\t{ontarget}",flush=True) - - - # close stdout or outfile - if args.outfile: - sys.stdout.close() - - expsamfile.close() - consamfile.close() - refFasta.close() - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/bin/extract_variant_reads_ML.py b/bin/extract_variant_reads_ML.py deleted file mode 100755 index 9ca76de..0000000 --- a/bin/extract_variant_reads_ML.py +++ /dev/null @@ -1,1083 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import division -import pysam -import biotite.sequence.align as align -import biotite.sequence as seq -import argparse -import re -import string -import csv, sys -import scipy.stats as stats -import pandas as pd, pyranges as pr -import joblib -import numpy as np - -# ============================================================================ -# SECTION 1: ORIGINAL INDEL CALCULATION FUNCTIONS -# ============================================================================ - -def revcomp(seq): - tab = str.maketrans('ACGTacgtRYMKrymkVBHDvbhd', 'TGCAtgcaYRKMyrkmBVDHbvdh') # maketrans <- maps the reverse complement - return seq.translate(tab)[::-1] # translate(x)[::-1] <- works backward through the string, effectively reversing the string - -def make_cigar_tuples(cigar): - cigar_dict = {'M': 0, 'I': 1, 'D': 2, 'N': 3, 'S': 4, 'H': 5, 'P': 6, '=': 7, 'X': 8} - # use regex to parse cigar string into tuples - cigar_tuples = re.findall(r'(\d+)([MIDNSHP=X])', cigar) - cigar_tuples = [(cigar_dict[operation],int(length)) for length, operation in cigar_tuples] - return cigar_tuples - -def cigar_summary(cigar): - cigar_dict = {'M': 0, 'I': 1, 'D': 2, 'N': 3, 'S': 4, 'H': 5, 'P': 6, '=': 7, 'X': 8} - # use regex to parse cigar string into tuples - cigar_tuples = re.findall(r'(\d+)([MIDNSHP=X])', cigar) - cigar_sum = { 'M': 0, 'I': 0, 'D': 0, 'N': 0, 'S': 0, 'H': 0, 'P': 0, '=': 0, 'X': 0 } - for length, operation in cigar_tuples: - cigar_sum[operation] += int(length) - - return cigar_sum - -def make_aligned_pairs(sup_align,refseq): - """ - Converts a supplementary alignment string into a list of aligned pairs. - - Args: - supplementary_alignment (str): Supplementary alignment string (e.g., 'chr12,107092390,-,110M41S,60,0'). - - Returns: - List of tuples: Aligned pairs (e.g., [(0, 168391768, 'C'), (1, 168391769, 'C'), ...]). - """ - # Split the supplementary alignment string into components - ref_name, ref_start, strand, cigar, _, _ = supplementary_alignment.split(',') - - # Convert positions and CIGAR to appropriate types - ref_start = int(ref_start) - cigar_ops = parse_cigar(cigar) - - # Initialize variables - aligned_pairs = [] - read_pos = 0 - ref_pos = ref_start - - for op, length in cigar_ops: - if op == 'M': # Match/mismatch - for i in range(length): - aligned_pairs.append((read_pos, ref_pos, refseq[ref_pos - ref_start])) - read_pos += 1 - ref_pos += 1 - elif op == 'I': # Insertion - for i in range(length): - aligned_pairs.append((read_pos, None, refseq[ref_pos - ref_start])) - read_pos += 1 - elif op == 'D': # Deletion - for i in range(length): - aligned_pairs.append((None, ref_pos, refseq[ref_pos - ref_start])) - ref_pos += 1 - elif op == 'S': # Soft clipping - read_pos += length - # Skipping 'H' (hard clipping) and 'N' (skipped region) as they do not appear in the read - - return aligned_pairs - -def indels_from_aligned_pairs(pairs,readseq): - - # remove leading soft clips - while pairs[0][0] is None: - pairs = pairs[1:] - - # remove training soft clips - while pairs[-1][0] is None: - pairs = pairs[:-1] - - pairs = [ (x[0],x[1],x[2].upper(),None) for x in pairs ] - for i in range(len(pairs)): - if pairs[i][0] is not None: - pairs[i] = (pairs[i][0],readseq[pairs[i][0]],pairs[i][1],pairs[i][2]) - - variant_start_index = j-1 - variant_end_index = j-1 - j = 0 - while j < len(pairs): - if pairs[j][0] is not None and pairs[j][2] is not None: - j+=1 - continue - - if pairs[j][0] is None or pairs[j][2] is None: # indel - variant_start_index = j-1 - variant_end_index = len(pairs) - break - - j+=1 - - # construct indel tuple - indel = (pairs[variant_start_index][2],''.join([ x[3] if x[3] else '' for x in pairs[variant_start_index:variant_end_index]]),''.join([ x[1] if x[1] else '' for x in pairs[variant_start_index:variant_end_index]])) - - return indel - -# function to count the number of reads that support an indel or BND event -def add_normal_counts(df, reads, fasta, maxreads=0,handicap=5,window=25,flank=150): - - # make ref and alt sequences for each indel/BND - df['refseq'] = '' - df['altseq'] = '' - for it, row in df.iterrows(): - df.at[it,'refseq'] = fasta.fetch(row['chrom'],row['pos']-1-flank,row['pos']+len(row['ref'])+flank) - if row['type'] in ['INDEL','DEL','INS']: - df.at[it,'altseq'] = fasta.fetch(row['chrom'],row['pos']-1-flank,row['pos']-1) + row['alt'] + fasta.fetch(row['chrom'],row['pos']+len(row['ref'])-1,row['pos']+len(row['ref'])+flank) - - elif row['type'] == 'BND': - df.at[it,'altseq'] = fasta.fetch(row['chrom'],row['pos']-1-flank,row['pos']-1) + (fasta.fetch(row['chrom2'],row['pos2']-1,row['pos2']+flank) if row['strands']=='++' else revcomp(fasta.fetch(row['chrom2'],row['pos2']-1-flank,row['pos2']))) - - df['control_alt_counts'] = 0 - df['control_total_counts'] = 0 - - total_reads = set() - - # iterate through reads in bam file for the first position - for read in reads: - # skip if not primary alignment or a duplicate or alignment doesnt overlap start,end - if read.is_mapped is False or \ - read.is_duplicate is True or \ - read.is_secondary is True or \ - read.is_supplementary is True or \ - read.mapping_quality == 0: - continue - - total_reads.add(read.query_name) - - # for speed: if the read has no indels, add it to the ref_count set - if len(read.cigartuples) == 1 and read.cigartuples[0][0] == 0 and read.cigartuples[0][1] == len(read.query_sequence): - continue - - for it, row in df.iterrows(): - if read.cigartuples[0][0]==0 and read.cigartuples[-1][0]==0: - if (len(row['ref']) > len(row['alt']) and 'D' not in read.cigarstring) or (len(row['alt']) > len(row['ref']) and 'I' not in read.cigarstring): - continue - - if row['type'] == 'BND' and not read.has_tag('SA'): - continue - - refseq = row['refseq'] - altseq = row['altseq'] - - ref_align = align.align_optimal(seq.NucleotideSequence(row['refseq']),seq.NucleotideSequence(read.query_sequence),matrix=align.SubstitutionMatrix.std_nucleotide_matrix(),gap_penalty=(-10,-1),local=True,terminal_penalty=False,max_number=1)[0] - - alt_align = align.align_optimal(seq.NucleotideSequence(row['altseq']),seq.NucleotideSequence(read.query_sequence),matrix=align.SubstitutionMatrix.std_nucleotide_matrix(),gap_penalty=(-10,-1),local=True,terminal_penalty=False,max_number=1)[0] - - if alt_align.score > 0 and alt_align.score - handicap > ref_align.score: - ref_align_cigar_sum = cigar_summary(align.write_alignment_to_cigar(ref_align)) - alt_align_cigar_sum = cigar_summary(align.write_alignment_to_cigar(alt_align)) - - if ((len(row['ref'])-len(row['alt']) > 0 and ref_align_cigar_sum['D']==len(row['ref'])-len(row['alt'])) or - (len(row['alt'])-len(row['ref']) > 0 and ref_align_cigar_sum['I']==len(row['alt'])-len(row['ref']))): - df.at[it,'control_alt_counts'] += 1 - # print to stderr: found control alt count - print(f"\tFound control alt count for {row['chrom']}:{row['pos']}:{row['ref']}:{row['alt']}:{read.query_name}", file=sys.stderr) - - df['control_total_counts'] = len(total_reads) - return df.copy() - -# function to get indels for one amplicon from bam file -def get_indels(bam,controlbam,chr,start,end,fasta,window=100,distance=25,pam_positions=pd.NA,minSecMapQual=10,maxNM=5,svDistanceThreshold=100000,saAlignmentTolerance=5,minSoftClipLength=5,deletionDistanceThreshold=1000,minreads=1,maxcontrol=0,strict=False,verbose=False): - - # window == flanking sequence to add to read search - # distance == max distance from start/end to consider an indel, BND, or call a read wild-type. - - cigarVarDict = {'0':'M','1':'I','2':'D','3':'N','4':'S','5':'H','6':'P','7':'=','8':'X'} - readaln = pd.DataFrame(columns=['read','chrom','pos','chrom2','pos2','ref','alt','strands','type']) - - # if verbose, print to stderr: getting reads that align within window of start and end - if verbose: - print(f"\tGetting reads that align within window of {chr}:{start}-{end}", file=sys.stderr) - - regionStart = max(start - svDistanceThreshold,1) - regionEnd = min(end + svDistanceThreshold,fasta.get_reference_length(chr)) - regionSeq = fasta.fetch(chr,regionStart-1,regionEnd) - - # get reads that align within window of start and end - for read in bam.fetch(chr, start-window, end+window, multiple_iterators = True): - - # skip if not primary alignment or a duplicate or alignment doesnt overlap start,end - if read.is_mapped is False or \ - read.is_duplicate is True or \ - read.is_secondary is True or \ - read.is_supplementary is True or \ - read.mapping_quality == 0: - continue - - cigar = read.cigartuples # get cigar info - mate_cigar = make_cigar_tuples(read.get_tag('MC')) if read.has_tag('MC') else None - - # Quality filter: Get mismatches from NM tag and subtract deleted/skipped bases from cigar - # and skip if too many mismatches - if read.has_tag('NM') and int(read.get_tag('NM')) > maxNM: - if (int(read.get_tag('NM')) - sum([x[1] for x in cigar if x[0] == 2 or x[0]==3])) > maxNM: - continue - - read_strand = "+" - if read.is_reverse is True: - read_strand = "-" - - leftSoftClip = 0 - rightSoftClip = 0 - read_reference_start = read.reference_start + 1 - read_reference_end = read.reference_end - read_next_reference_start = read.next_reference_start + 1 - read_next_reference_end = None if mate_cigar is None else read_next_reference_start + sum([x[1] for x in mate_cigar if x[0] == 0 or x[0] == 2 or x[0] == 3]) - - read_query_start = 0 - read_query_end = len(read.query_sequence) - - # setup indelinfo dictionary - indelinfo = {'read':read.query_name,'chrom':'','pos':None,'chrom2':None,'pos2':None,'strands': '','ref':'','alt':'','type':''} - - # Get left soft clip length - if cigar[0][0] == 4: - leftSoftClip = cigar[0][1] - - # Get right soft clip length - if cigar[-1][0] == 4: - rightSoftClip = cigar[-1][1] - - - if leftSoftClip > rightSoftClip: - sChr, sPos, sStrand, sCigar, sMq, sNm = read.get_tag('SA').split(';')[0].split(',') if read.has_tag('SA') else [None,None,None,None,None,None] - - if (sChr != None and int(sMq)>=minSecMapQual and - int(sNm)= 4 and sCigarTuples[0][0] == 0 and sCigarTuples[0][1] == cigar[0][1]: - cigar = sCigarTuples[:-1] + [(2,read_reference_start-sPos-1)] + cigar[1:] - else: - cigar = make_cigar_tuples(align.write_alignment_to_cigar(align.align_optimal(seq.NucleotideSequence(regionSeq[sPos-regionStart:read_reference_end-regionStart+1]), - seq.NucleotideSequence(read.query_sequence), - matrix=align.SubstitutionMatrix.std_nucleotide_matrix(), - gap_penalty=(-10,-1),local=False,max_number=1)[0])) - read_reference_start = sPos - - else: - if leftSoftClip >= minSoftClipLength: - clippedSeq = read.query_sequence[:leftSoftClip] - refSeq = regionSeq[read_reference_start - regionStart - window + 1:read_reference_start - regionStart + 1] - leftClipPos = refSeq.rfind(clippedSeq) - if leftClipPos != -1: - delSeq = refSeq[leftClipPos + len(clippedSeq)-1:] - cigar = [(0,len(clippedSeq))] + [(2,len(delSeq))] + cigar[1:] - read_reference_start = read_reference_end - sum([x[1] for x in cigar if x[0] == 0 or x[0] == 2 or x[0] == 3]) + 1 - - # Process right soft clip, if present - if rightSoftClip > leftSoftClip: - sChr, sPos, sStrand, sCigar, sMq, sNm = read.get_tag('SA').split(';')[0].split(',') if read.has_tag('SA') else [None,None,None,None,None,None] - - if (sChr != None): - sPos = int(sPos) - sCigarTuples = make_cigar_tuples(sCigar) - - if (int(sMq)>=minSecMapQual and sCigarTuples[0][0] >= 4 and sCigarTuples[-1][0] == 0 and - int(sNm) read_reference_end and - int(sPos) - read_reference_end < svDistanceThreshold): - - if sCigarTuples[0][0] >= 4 and sCigarTuples[-1][0] == 0 and sCigarTuples[-1][1] == cigar[-1][1]: - cigar = cigar[:-1] + [(2,read_reference_end-sPos)] + sCigarTuples[1:] - else: - cigar = make_cigar_tuples(align.write_alignment_to_cigar(align.align_optimal(seq.NucleotideSequence(regionSeq[read_reference_start-regionStart:sPos-regionStart+sum([x[1] for x in sCigarTuples if x[0] == 0 or x[0] == 2 or x[0] == 3])]), - seq.NucleotideSequence(read.query_sequence), - matrix=align.SubstitutionMatrix.std_nucleotide_matrix(), - gap_penalty=(-10,-1),local=False,max_number=1)[0])) - - read_reference_end = read_reference_start + sum([x[1] for x in cigar if x[0] == 0 or x[0] == 2 or x[0] == 3]) - - else: - if rightSoftClip >= minSoftClipLength: - clippedSeq = read.query_sequence[-rightSoftClip:] - refSeq = regionSeq[read_reference_end-regionStart:read_reference_end-regionStart + window] - rightClipPos = refSeq.find(clippedSeq) - if rightClipPos != -1: - delSeq = refSeq[0:rightClipPos] - cigar = cigar[:-1] + [(2,len(delSeq))] + [(0,len(clippedSeq))] - read_reference_end = read_reference_start + sum([x[1] for x in cigar if x[0] == 0 or x[0] == 2 or x[0] == 3]) - - # Check if adjusted read is within distance - if read_reference_start - leftSoftClip >= end + distance or read_reference_end + rightSoftClip <= start - distance: - continue - - # Remove leading or trailing soft clips - if cigar[0][0] >= 4: - read_query_start += cigar[0][1] - del cigar[0] - - if cigar[-1][0] >= 4: - read_query_end -= cigar[-1][1] - del cigar[-1] - - # Process indels if multiple cigar operations - if len(cigar) > 1: - # Adjust alignment start for first aligned block - if cigar[0][0] == 0: - read_reference_start += cigar[0][1] - read_query_start = read_query_start + cigar[0][1] - del cigar[0] - - # Adjust alignment end for last aligned block - if cigar[-1][0] == 0: - read_reference_end = read_reference_end - cigar[-1][1] - read_query_end = read_query_end - cigar[-1][1] - del cigar[-1] - - # Process single indel event - if len(cigar) == 1: - - # theres one event, so record the coordinates - indelinfo['chrom'] = read.reference_name - indelinfo['pos'] = read_reference_start - indelinfo['strands'] = '++' - - # if insertion - if cigar[0][0] == 1: - indelinfo['ref'] = regionSeq[read_reference_start-regionStart-1:read_reference_start-regionStart] #fasta.fetch(chr,read_reference_start-1-1,read_reference_start-1) # 0 based and position before the isertion - indelinfo['alt'] = read.query_sequence[read_query_start-1:read_query_start+cigar[0][1]] - indelinfo['type'] = 'INDEL' - - # if deletion - elif cigar[0][0] == 2 or cigar[0][0] == 3: - indelinfo['ref'] = regionSeq[read_reference_start-regionStart:read_reference_start-regionStart + cigar[0][1] + 1] #fasta.fetch(chr,read_reference_start-1,read_reference_start+cigar[0][1]) - # Check if ref is not empty before accessing first character - if indelinfo['ref']: - indelinfo['alt'] = indelinfo['ref'][0] - else: - # Handle empty ref case - could skip this indel or use a default value - indelinfo['alt'] = 'N' # or skip this indel entirely - indelinfo['type'] = 'INDEL' - - # if its a complex indel - else: - indelinfo['chrom'] = read.reference_name - indelinfo['pos'] = read_reference_start - indelinfo['strands'] = '++' - indelinfo['type'] = 'INDEL' - - # iterate through cigar and get indels - varlen = sum([ x[1] for x in cigar ]) - indelinfo['ref'] = regionSeq[read_reference_start-regionStart:read_reference_start-regionStart+sum([ x[1] for x in cigar ])+1] #fasta.fetch(chr,read_reference_start-1,read_reference_start+sum([ x[1] for x in cigar ])) - indelinfo['alt'] = read.query_sequence[read_query_start+1:read_query_start+sum([x[1] if x[0] == 1 or x[0] == 0 else 0 for x in cigar])] - - # Process chimeric reads with supplementary alignments - elif read.has_tag('SA') is True and (leftSoftClip > 0 or rightSoftClip > 0): - sChr, sPos, sStrand, sCigar, sMq, sNm = read.get_tag('SA').split(';')[0].split(',') if read.has_tag('SA') else [None,None,None,None,None,None] - - sCigarTuples = make_cigar_tuples(sCigar) - sPos = int(sPos) - sEnd = sPos + sum([x[1] for x in sCigarTuples if x[0] == 0 or x[0] == 2 or x[0] == 3]) - 1 - sLeftSoftClip = sCigarTuples[0][1] if sCigarTuples[0][0] >= 4 else 0 - sRightSoftClip = sCigarTuples[-1][1] if sCigarTuples[-1][0] >= 4 else 0 - - pSeq = read.query_alignment_sequence - sSeq = read.query_sequence[sLeftSoftClip:sLeftSoftClip+sum([x[1] for x in sCigarTuples if x[0] == 0 or x[0] == 1])] if sStrand == read_strand else revcomp(read.query_sequence[sLeftSoftClip:sLeftSoftClip+sum([x[1] for x in sCigarTuples if x[0] == 0 or x[0] == 1])]) - - # Correct for overlapping alignments - if len(pSeq)+len(sSeq) > len(read.query_sequence): - trimLen = len(pSeq)+len(sSeq) - len(read.query_sequence) - if sLeftSoftClip > sRightSoftClip: - sPos += trimLen - sSeq = sSeq[trimLen:] - elif sRightSoftClip > sLeftSoftClip: - sEnd -= trimLen - sSeq = sSeq[:-trimLen] - - if (int(sMq) >= minSecMapQual and int(sNm) <= maxNM and int(sMq)>0 and - (sChr != read.reference_name or abs(int(sPos) - read_reference_start) >= svDistanceThreshold) or sStrand != read_strand or - (rightSoftClip > 0 and sEnd < read_reference_start) or (leftSoftClip > 0 and sPos > read_reference_end)): - - indelinfo['chrom'] = read.reference_name - indelinfo['chrom2'] = sChr - indelinfo['strands'] = '++'if sStrand == read_strand else '+-' - indelinfo['type'] = 'BND' - - if indelinfo['strands'] == '++': - if rightSoftClip > leftSoftClip and sLeftSoftClip > sRightSoftClip: - indelinfo['pos'] = read_reference_end - indelinfo['pos2'] = sPos - elif leftSoftClip > rightSoftClip and sRightSoftClip > sLeftSoftClip: - indelinfo['pos'] = read_reference_start - 1 - indelinfo['pos2'] = sEnd + 1 - else: - print(f"Error: no proper soft clip orientation found: {read.query_name}: {str(read)}", file=sys.stderr) - if strict: - exit(1) - else: - continue - - elif indelinfo['strands'] == '+-': - if rightSoftClip > leftSoftClip and sRightSoftClip > sLeftSoftClip: - indelinfo['pos'] = read_reference_end - indelinfo['pos2'] = sEnd - elif leftSoftClip > rightSoftClip and sLeftSoftClip > sRightSoftClip: - indelinfo['pos'] = read_reference_start - 1 - indelinfo['pos2'] = sPos - else: - print(f"Error: no proper soft clip orientation found: {read.query_name}: {str(read)}", file=sys.stderr) - if strict: - exit(1) - else: - continue - else: - print(f"Error: no proper soft clip orientation found: {read.query_name}: {str(read)}", file=sys.stderr) - if strict: - exit(1) - else: - continue - - elif read_reference_start < end and read_reference_end > start: - indelinfo['chrom'] = chr - indelinfo['pos'] = start - indelinfo['ref'] = '.' - indelinfo['alt'] = '.' - indelinfo['type'] = 'REF' - else: - continue - - elif read_reference_start < end and read_reference_end > start: - indelinfo['chrom'] = chr - indelinfo['pos'] = start - indelinfo['ref'] = '.' - indelinfo['alt'] = '.' - indelinfo['type'] = 'REF' - else: - continue - - # Add indel info to dataframe - readaln = pd.concat([readaln, pd.DataFrame([indelinfo])], ignore_index=True) - - if verbose: - print("\tSorting indels", file=sys.stderr) - - # Group by read and process results - readaln = readaln.sort_values(by=['read','chrom','pos','chrom2','pos2','strands','ref','alt','type'],key=lambda col: col != '',ascending=False).groupby('read').first().reset_index() - indelcounts = readaln.groupby(['chrom','pos','chrom2','pos2','strands','ref','alt','type'],dropna=False).size().reset_index(name='counts') - - # Recast as int type, allowing for NA values - indelcounts['pos'] = indelcounts['pos'].astype(pd.Int64Dtype()) - indelcounts['pos2'] = indelcounts['pos2'].astype(pd.Int64Dtype()) - - if verbose: - print("\tGetting control counts", file=sys.stderr) - - # Get counts from control BAM - if len(indelcounts) > 0: - # Add pam positions to the df - if pam_positions is not pd.NA: - indelcounts['Positions'] = [pam_positions] * len(indelcounts) - indelcounts['Distance'] = indelcounts.apply( - lambda r: min( - [abs(r['pos'] - int(x)) for x in r['Positions']] + - [abs(r['pos'] + len(r['ref']) - 1 - int(x)) for x in r['Positions']] - ) if pd.notna(r['pos']) and r['Positions'] else pd.NA, - axis=1 - ) - - else: - indelcounts['Positions'] = pd.NA - indelcounts['Distance'] = pd.NA - - indelcounts = add_normal_counts(indelcounts, [ x for x in controlbam.fetch(contig=chr,start=start-window,end=end) ], fasta, window=distance) - else: - indelcounts['control_alt_counts'] = 0 - indelcounts['control_total_counts'] = 0 - indelcounts['Positions'] = pd.NA - indelcounts['Distance'] = pd.NA - - # Apply filters - indelcounts = indelcounts[(indelcounts['counts'] >= minreads) | (indelcounts['ref']=='.')] - indelcounts = indelcounts[(indelcounts['control_alt_counts'] <= maxcontrol) | (indelcounts['ref']=='.')] - indelcounts = indelcounts[(indelcounts['Distance'] <= distance) | (indelcounts['ref']=='.')] - indelcounts = indelcounts[~indelcounts['alt'].str.contains('N')] - - return(indelcounts) - -# ============================================================================ -# SECTION 2: CRISPR PREDICTION FUNCTIONS -# ============================================================================ - -def detect_deletion_from_softclips(read, min_softclip_size=3, max_gap=50): - """Detect potential large deletions from soft-clips and supplementary alignments.""" - if not read.cigartuples: - return 0 - - total_deletion = 0 - - # Parse CIGAR operations - cigar_ops = [] - for op, length in read.cigartuples: - cigar_ops.append((op, length)) - - # Count soft-clips as potential deletions - for op, length in cigar_ops: - if op == 4: # Soft-clip - if length >= min_softclip_size: - total_deletion += length - - # Look for patterns: softclip -> deletion -> softclip - for i in range(len(cigar_ops) - 2): - op1, len1 = cigar_ops[i] - op2, len2 = cigar_ops[i + 1] - op3, len3 = cigar_ops[i + 2] - - if op1 == 4 and op2 == 2 and op3 == 4: # Softclip -> Deletion -> Softclip - if len1 >= min_softclip_size and len2 <= max_gap and len3 >= min_softclip_size: - total_deletion += len2 - elif op1 == 2 and op2 == 4 and op3 == 2: # Deletion -> Softclip -> Deletion - if len2 >= min_softclip_size and len1 <= max_gap and len3 <= max_gap: - total_deletion += (len1 + len3) - - # Look for single softclip patterns with nearby deletions - for i in range(len(cigar_ops) - 1): - op1, len1 = cigar_ops[i] - op2, len2 = cigar_ops[i + 1] - - if op1 == 4 and op2 == 2: # Softclip -> Deletion - if len1 >= min_softclip_size and len2 <= max_gap: - total_deletion += len2 - elif op1 == 2 and op2 == 4: # Deletion -> Softclip - if len2 >= min_softclip_size and len1 <= max_gap: - total_deletion += len1 - - # Look for end soft-clips (left/right) representing large deletions - if len(cigar_ops) >= 1: - # Left soft-clip - if cigar_ops[0][0] == 4: - left_softclip = cigar_ops[0][1] - if left_softclip >= min_softclip_size: - middle_align = sum(length for op, length in cigar_ops[1:] if op == 0) - if middle_align > 5: - total_deletion += left_softclip - - # Right soft-clip - if cigar_ops[-1][0] == 4: - right_softclip = cigar_ops[-1][1] - if right_softclip >= min_softclip_size: - middle_align = sum(length for op, length in cigar_ops[:-1] if op == 0) - if middle_align > 5: - total_deletion += right_softclip - - # Look for internal soft-clips - for i, (op, length) in enumerate(cigar_ops): - if op == 4 and length >= min_softclip_size: - left_align = sum(cigar_ops[j][1] for j in range(i) if cigar_ops[j][0] == 0) - right_align = sum(cigar_ops[j][1] for j in range(i+1, len(cigar_ops)) if cigar_ops[j][0] == 0) - - if left_align > 2 and right_align > 2: - total_deletion += length - - # Check supplementary alignments (SA tags) for soft-clip deletions - if read.has_tag('SA'): - sa_tag = read.get_tag('SA') - sa_entries = sa_tag.split(';') - - for sa_entry in sa_entries: - if not sa_entry: - continue - - sa_parts = sa_entry.split(',') - if len(sa_parts) >= 4: - sa_cigar = sa_parts[3] - sa_softclips = parse_cigar_for_softclips(sa_cigar) - for softclip_size in sa_softclips: - if softclip_size >= min_softclip_size: - total_deletion += softclip_size - - return total_deletion - -def parse_cigar_for_softclips(cigar_string): - """Parse CIGAR string to extract soft-clip sizes.""" - softclips = [] - import re - - cigar_parts = re.findall(r'(\d+)([MIDNSHP=X])', cigar_string) - - for length_str, operation in cigar_parts: - if operation == 'S': # Soft-clip - softclips.append(int(length_str)) - - return softclips - -def parse_cigar_once(read): - """Parse CIGAR operations to extract insertion, deletion, and soft-clip counts.""" - cigar_summary = {'M': 0, 'I': 0, 'D': 0, 'N': 0, 'S': 0, 'H': 0, 'P': 0, '=': 0, 'X': 0} - if not hasattr(read, 'cigartuples') or read.cigartuples is None: - return {'insertions': 0, 'deletions': 0, 'softclips': 0} - - for op, length in read.cigartuples: - if op == 1: - cigar_summary['I'] += length - elif op == 2: - cigar_summary['D'] += length - elif op == 4: - cigar_summary['S'] += length - - # Total deletions = explicit deletions + deletions from soft-clips - total_deletions = cigar_summary['D'] + detect_deletion_from_softclips(read) - - return { - 'insertions': cigar_summary['I'], - 'deletions': total_deletions, - 'softclips': cigar_summary['S'] - } - -def count_mismatches_fast(read): - """Count mismatches from MD tag.""" - if not read.has_tag('MD'): - return 0 - md = read.get_tag('MD') - return sum(1 for c in md if c.isalpha()) - -def calculate_control_fractions(control_bam, chrom, position, window=50): - """Calculate fractions of control reads with different variant types.""" - fractions = { - 'fraction_control_reads_del': 0.0, - 'fraction_control_reads_ins': 0.0, - 'fraction_control_reads_mismatch': 0.0, - 'fraction_control_reads_softclip': 0.0 - } - if not control_bam: - return fractions - - total = del_count = ins_count = mismatch_count = softclip_count = 0 - - for read in control_bam.fetch(chrom, position - window, position + window): - if read.is_unmapped or read.is_duplicate: - continue - total += 1 - if read.cigartuples: - if any(op == 2 for op, _ in read.cigartuples): - del_count += 1 - if any(op == 1 for op, _ in read.cigartuples): - ins_count += 1 - if any(op == 4 for op, _ in read.cigartuples): - softclip_count += 1 - if read.has_tag('MD') and any(c.isalpha() for c in read.get_tag('MD')): - mismatch_count += 1 - - if total > 0: - fractions.update({ - 'fraction_control_reads_del': del_count / total, - 'fraction_control_reads_ins': ins_count / total, - 'fraction_control_reads_mismatch': mismatch_count / total, - 'fraction_control_reads_softclip': softclip_count / total - }) - return fractions - -def calculate_exclusivity_features(read, control_bam, chrom, position, window=100): - """Calculate whether variants are exclusive to edited samples.""" - exclusivity = { - 'variant_exclusive_to_edited': 0, - 'insertion_exclusive_to_edited': 0, - 'deletion_exclusive_to_edited': 0, - 'control_has_same_variant': 0, - } - if not control_bam or read.is_unmapped or read.is_duplicate or not read.cigartuples: - return exclusivity - - has_insertion = any(op == 1 for op, _ in read.cigartuples) - has_deletion = any(op == 2 for op, _ in read.cigartuples) - - read_start, read_end = read.reference_start, read.reference_end - - control_has_same_ins = False - control_has_same_del = False - - for control_read in control_bam.fetch(chrom, position - window, position + window): - if control_read.is_unmapped or control_read.is_duplicate or not control_read.cigartuples: - continue - ctrl_start, ctrl_end = control_read.reference_start, control_read.reference_end - - # Check for overlapping reads - if not (read_end < ctrl_start or ctrl_end < read_start): - if has_insertion and any(op == 1 for op, _ in control_read.cigartuples): - control_has_same_ins = True - if has_deletion and any(op == 2 for op, _ in control_read.cigartuples): - control_has_same_del = True - - insertion_exclusive = has_insertion and not control_has_same_ins - deletion_exclusive = has_deletion and not control_has_same_del - - any_exclusive = insertion_exclusive or deletion_exclusive - control_has_similar = control_has_same_ins or control_has_same_del - - exclusivity['deletion_exclusive_to_edited'] = 1 if deletion_exclusive else 0 - exclusivity['control_has_same_variant'] = 1 if control_has_similar else 0 - return exclusivity - -def calculate_distance_to_closest_pam(position, targets_df, chrom): - """Calculate distance to closest PAM site.""" - if targets_df is None or len(targets_df) == 0: - return -1 - distances = np.abs(targets_df['Start'] - position) - return distances.min() if len(distances) > 0 else -1 - -def predict_reads_at_position(bam_file, chrom, start, end, pampos, model, fasta, is_on_target=0, control_bam=None, threshold=0.80): - - reads = [] - for read in bam_file.fetch(chrom, start, end): - if read.is_unmapped or read.is_duplicate: - continue - reads.append(read) - if not reads: - return 0, 0.0 - - # Extract features for each read - features_list = [] - for read in reads: - cigar_data = parse_cigar_once(read) - - read_start = read.reference_start - read_end = read.reference_end - - # Check if read overlaps with target sites - is_at_any_target = 0 - if pampos is not None: - for p in pampos: - if read_start <= p + 25 and read_end >= p - 25: - is_at_any_target = 1 - - - # Get control fractions - control_fractions = calculate_control_fractions(control_bam, chrom, start, window=50) if control_bam else { - 'fraction_control_reads_del': 0.0, - 'fraction_control_reads_ins': 0.0, - 'fraction_control_reads_mismatch': 0.0, - 'fraction_control_reads_softclip': 0.0 - } - - # Calculate exclusivity features - exclusivity = calculate_exclusivity_features(read, control_bam, chrom, start, window=100) if control_bam else { - 'deletion_exclusive_to_edited': 0, - 'control_has_same_variant': 0, - } - - # Convert read features to binary - read_has_deletion = 1 if cigar_data['deletions'] > 0 else 0 - read_has_insertion = 1 if cigar_data['insertions'] > 0 else 0 - read_has_mismatch = 1 if count_mismatches_fast(read) > 0 else 0 - - # Calculate indel characteristics - total_indel_size = cigar_data['insertions'] + cigar_data['deletions'] - - # Indel size category - indel_size_category = 0 - if total_indel_size > 0: - if total_indel_size <= 3: - indel_size_category = 1 - elif total_indel_size <= 10: - indel_size_category = 2 - else: - indel_size_category = 3 - - # Insertion to deletion ratio - insertion_to_deletion_ratio = 0.0 - if cigar_data['deletions'] > 0: - insertion_to_deletion_ratio = cigar_data['insertions'] / cigar_data['deletions'] - elif cigar_data['insertions'] > 0: - insertion_to_deletion_ratio = 10.0 - else: - insertion_to_deletion_ratio = 0.0 - - # Indel complexity score - indel_complexity_score = 0.0 - if read.cigartuples: - indel_operations = [op for op, length in read.cigartuples if op in [1, 2]] - complexity = len(indel_operations) + (total_indel_size / 10.0) - indel_complexity_score = min(complexity, 10.0) - - # Create features dictionary - features = { - 'read_pair_gap': abs(read.template_length) if hasattr(read, 'template_length') and read.is_paired and read.is_proper_pair else -1, - 'read_insertion': cigar_data['insertions'], - 'read_deletion': cigar_data['deletions'], - 'read_mismatch': count_mismatches_fast(read), - 'read_softclip': cigar_data['softclips'], - 'read_del_vs_control': read_has_deletion - control_fractions['fraction_control_reads_del'], - 'read_ins_vs_control': read_has_insertion - control_fractions['fraction_control_reads_ins'], - 'read_mismatch_vs_control': read_has_mismatch - control_fractions['fraction_control_reads_mismatch'], - 'deletion_exclusive_to_edited': exclusivity['deletion_exclusive_to_edited'], - 'control_has_same_variant': exclusivity['control_has_same_variant'], - 'distance_to_closest_pam': min(abs(x-start) for x in pampos) if pampos is not None else -1, - 'is_on_target_site': is_on_target, - 'is_at_any_target_site': is_at_any_target, - 'total_indel_size': total_indel_size, - 'indel_size_category': indel_size_category, - 'insertion_to_deletion_ratio': insertion_to_deletion_ratio, - 'indel_complexity_score': indel_complexity_score - } - - features_list.append(features) - - if not features_list: - return 0, 0.0 - - # Get expected features for the model - if hasattr(model, 'feature_names_in_'): - expected_features = list(model.feature_names_in_) - else: - expected_features = ['read_pair_gap', 'read_insertion', 'read_deletion', 'read_mismatch', 'read_softclip', 'read_del_vs_control', 'read_ins_vs_control', 'read_mismatch_vs_control', 'deletion_exclusive_to_edited', 'control_has_same_variant', 'is_on_target_site', 'is_at_any_target_site', 'distance_to_closest_pam', 'total_indel_size', 'indel_size_category', 'insertion_to_deletion_ratio', 'indel_complexity_score'] - - features_df = pd.DataFrame(features_list) - features_df = features_df.reindex(columns=expected_features, fill_value=0) - - # Get model predictions - preds = model.predict_proba(features_df)[:, 1] - - # Calculate results - avg_probability = float(preds.mean() * 100) - - return int((preds >= threshold).sum()), avg_probability - -# ============================================================================ -# SECTION 3: MAIN FUNCTION -# ============================================================================ - -def main(): - - parser = argparse.ArgumentParser(description='Extract variant reads and predict CRISPR reads') - parser.add_argument('-f','--fasta',type=str,default="/storage2/fs1/dspencer/Active/clinseq/projects/scge/data/refdata/singh_v4.3.6/hg38_PLVM_CD19_CARv4_cd34.fa",help='Reference fasta file') - parser.add_argument('-w','--window',type=int,default=100,help='Window size') - parser.add_argument('-d','--distance',type=int,default=25,help='Distance') - parser.add_argument('-m','--minreads',type=int,default=1,help='Minimum reads') - parser.add_argument('-c','--chromosome',type=str,default=None,help='Chromosome to process') - parser.add_argument('-x','--maxcontrol',type=int,default=0,help='Maximum supporting reads to report an indel/bnd event.') - parser.add_argument('-s','--strict',action='store_true',help='Exit if a read cannot be properly parsed.') - parser.add_argument('-v','--verbose',action='store_true',help='Print verbose output') - parser.add_argument('-o','--outfile',type=str,help='Output file (optional)') - - # CRISPR prediction arguments - parser.add_argument('--crispr-model',type=str,default='models/site14_site5_combined_model.pkl',help='Trained CRISPR ML model file (.pkl) for read prediction (default: site14_site5_combined_model.pkl)') - parser.add_argument('--crispr-threshold',type=float,default=0.70,help='Probability threshold for CRISPR prediction (default: 0.70)') - parser.add_argument('--enable-crispr-prediction',action='store_true',help='Enable CRISPR read prediction (uses default model and target-file as targets)') - parser.add_argument('--targets-csv',type=str,help='Alternative target sites CSV file for feature extraction (optional - uses target-file if not specified)') - parser.add_argument('--filter-off-target-fp', action='store_true', help='Filter off-target sites that are likely false positives (indel reads > 0 but no predicted CRISPR reads).') - parser.add_argument('--fp-log', type=str, help='Log file for filtered false positive off-target sites.') - - # Required BAM files and target file - parser.add_argument('--edited-bam',type=str,required=True,help='Edited/experimental BAM/CRAM file') - parser.add_argument('--control-bam',type=str,required=True,help='Control BAM/CRAM file') - parser.add_argument('--target-file',type=str,required=True,help='Target sites coordinate file (CSV/BED format) - used for both bed coordinates and CRISPR targets') - - args = parser.parse_args() - - if args.verbose: - print("Processing input file", file=sys.stderr) - - # ======================================================================== - # STEP 1: Process input BED file and create genomic intervals - # ======================================================================== - - bedDf = pd.read_csv(args.target_file, sep='\t') - # remove # from first column header - bedDf.columns = bedDf.columns.str.replace('#', '', regex=False) - - # Check for empty input data - if len(bedDf) == 0: - print("Warning: Input target file has no data rows. Writing empty output.", file=sys.stderr) - # Write empty output file with header only - output_columns = ['Cluster', 'Chromosome', 'Start', 'End', 'Ontarget', 'Gene', 'indel_type', - 'indel_fraction', 'indel_allele_fraction', 'indel_size', 'indel_bases', - 'num_edited', 'num_control', 'total_edited', 'total_control', 'significance', - 'prediction', 'probability', 'model_info'] - empty_df = pd.DataFrame(columns=output_columns) - if args.outfile: - empty_df.to_csv(args.outfile, sep='\t', index=False) - else: - empty_df.to_csv(sys.stdout, sep='\t', index=False) - sys.exit(0) - - info_header = bedDf.columns[-1].split(',') - bedDf.rename(columns={'chromosome':'Chromosome', 'start':'Start', 'end':'End', bedDf.columns[-1]: 'Info'}, inplace=True) - bedDf['Info'] = bedDf['Info'].apply(lambda x, h=info_header: dict(zip(h, str(x).split(',')))) - # Support both old and new column naming conventions - bedDf['Pos'] = bedDf['Info'].apply(lambda x: int(x.get('pos', x.get('Start', 0)))) - bedDf['Ontarget'] = bedDf['Info'].apply(lambda x: int(x.get('is_target', x.get('On_target', 0)))) - - # Create PyRanges object and cluster intervals - bedPr = pr.PyRanges(bedDf[['Chromosome','Start','End','Pos','Info','Ontarget']]) - bedPr = bedPr.cluster(slack=args.window) - mergedBedPr = bedPr.merge(by='Cluster',strand=False,slack=args.window) - mergedBedDf = mergedBedPr.df.join(bedPr.df.groupby('Cluster')['Pos'].agg(list).reset_index().set_index('Cluster'),on='Cluster',how='left') - mergedBedDf = mergedBedDf.join(bedPr.df.groupby('Cluster')['Info'].agg(list).reset_index().set_index('Cluster'),on='Cluster',how='left') - mergedBedDf = mergedBedDf.join(bedPr.df.groupby('Cluster')['Ontarget'].agg('max').reset_index().set_index('Cluster'),on='Cluster',how='left') - - # Filter by chromosome if specified - if args.chromosome is not None: - print("Processing chromosome", args.chromosome, file=sys.stderr) - if args.chromosome.startswith('chr'): - mergedBedDf = mergedBedDf[mergedBedDf['Chromosome'] == args.chromosome] - else: - mergedBedDf = mergedBedDf[(mergedBedDf['Chromosome'] == args.chromosome) | - (mergedBedDf['Chromosome'] == f"chr{args.chromosome}")] - - if len(mergedBedDf) == 0: - print(f"Warning: No data found for chromosome {args.chromosome}", file=sys.stderr) - all_chromosomes = sorted(bedPr.df['Chromosome'].unique()) - print(f"Available chromosomes: {all_chromosomes}", file=sys.stderr) - sys.exit(1) - else: - print(f"Found {len(mergedBedDf)} intervals for chromosome {args.chromosome}", file=sys.stderr) - - if args.verbose: - print("Done processing input file", file=sys.stderr) - - # ======================================================================== - # STEP 2: Open BAM files and reference - # ======================================================================== - - expsamfile = pysam.AlignmentFile(args.edited_bam,"rc",reference_filename=args.fasta) - consamfile = pysam.AlignmentFile(args.control_bam,"rc",reference_filename=args.fasta) - refFasta = pysam.FastaFile(args.fasta) - - # Redirect output if specified - if args.outfile: - sys.stdout = open(args.outfile, 'w') - - # ======================================================================== - # STEP 3: Load CRISPR prediction model and targets (if enabled) - # ======================================================================== - - crispr_model = None - if args.enable_crispr_prediction: - try: - print(f"Loading CRISPR ML model: {args.crispr_model}", file=sys.stderr) - crispr_model = joblib.load(args.crispr_model) - print(f"CRISPR model loaded successfully", file=sys.stderr) - print(f"CRISPR prediction enabled with threshold {args.crispr_threshold}", file=sys.stderr) - except Exception as e: - print(f"Error loading CRISPR model '{args.crispr_model}': {e}", file=sys.stderr) - print(f"Make sure the model file exists in the current directory or provide full path", file=sys.stderr) - sys.exit(1) - - # ======================================================================== - # STEP 4: Create output header - # ======================================================================== - - header_columns = ['chrom', 'start', 'end', 'pam_positions', 'total_reads', 'indel_reads', 'indel_fraction', - 'control_reads', 'control_indel_reads', 'control_indel_fraction', 'indel_count', 'indel_info', - 'bnd_count', 'bnd_info', 'target_info', 'is_target'] - if args.enable_crispr_prediction: - header_columns.extend(['crispr_predicted_reads', 'crispr_prediction_fraction', 'crispr_prediction_probability']) - print("\t".join(header_columns), flush=True) - - fp_log = None - if args.fp_log: - fp_log = open(args.fp_log, 'w') - fp_log.write("\t".join(header_columns) + "\n") - - # ======================================================================== - # STEP 5: Process each genomic interval - # ======================================================================== - - for index, row in mergedBedDf.iterrows(): - if args.verbose: - print(f"Processing interval {row['Chromosome']}:{row['Start']}-{row['End']}", file=sys.stderr) - - # ORIGINAL INDEL CALCULATION - indels = get_indels(bam=expsamfile,controlbam=consamfile,chr=row['Chromosome'],start=row['Start'],end=row['End'], - fasta=refFasta,window=args.window,distance=args.distance,pam_positions=row['Pos'],minreads=args.minreads,maxcontrol=args.maxcontrol,verbose=args.verbose) - - # Process indel results - total_reads, indel_reads, control_total_reads, control_indel_reads = 0, 0, 0, 0 - indel_fraction, control_indel_fraction = 0, 0 - indel_keys, bnd_keys = '.', '.' - bnds = [] - - if len(indels) > 0: - total_reads = sum(indels['counts']) - indel_reads = sum(indels[indels['type']!='REF']['counts']) - control_indel_reads = int(indels['control_alt_counts'].mean()) - control_total_reads = int(indels['control_total_counts'].mean()) - - # Separate BNDs and indels - bnds = indels[indels['type']=='BND'].copy() - indels = indels[indels['type']=='INDEL'].copy() - - if len(indels) > 0: - indels['Key'] = indels.apply(lambda r: f"{r['chrom']}:{r['pos']}:{r['ref']}:{r['alt']}:{r['counts']}:{r['control_alt_counts']}:{r['Distance']}", axis=1) - - if len(bnds) > 0: - bnds['Key'] = bnds.apply(lambda r: f"{r['chrom']}:{r['pos']}:{r['chrom2']}:{r['pos2']}:{r['strands']}:{r['counts']}:{r['control_alt_counts']}:{r['Distance']}", axis=1) - - # Calculate fractions and prepare output - indel_fraction = round(indel_reads/total_reads,4) if total_reads > 0 else 0 - control_indel_fraction = round(control_indel_reads/control_total_reads,4) if control_total_reads > 0 else 0 - indel_keys = ';'.join(indels['Key'].tolist()) if len(indels) > 0 else '.' - bnd_keys = ';'.join(bnds['Key'].tolist()) if len(bnds) > 0 else '.' - ontarget = row['Ontarget'] - positions = row['Pos'] - offtargetsites = ';'.join([','.join(d.values()) for d in row['Info']]) if row['Info'] else '.' - - # CRISPR PREDICTION (if enabled) - crispr_predicted_reads = 0 - crispr_prediction_fraction = 0.0 - crispr_prediction_probability = 0.0 - if args.enable_crispr_prediction and crispr_model: - if args.verbose: - print(f" Predicting CRISPR reads for {row['Chromosome']}:{row['Start']}-{row['End']} (total_reads: {total_reads})", file=sys.stderr) - - crispr_predicted_reads, crispr_prediction_probability = predict_reads_at_position( - expsamfile, row['Chromosome'], row['Start'], row['End'], positions, - crispr_model, refFasta, is_on_target=ontarget, control_bam=consamfile, threshold=args.crispr_threshold - ) - crispr_prediction_fraction = round(crispr_predicted_reads/total_reads, 4) if total_reads > 0 else 0.0 - - if args.verbose: - print(f" Predicted {crispr_predicted_reads}/{total_reads} reads as CRISPR-related (≥{args.crispr_threshold})", file=sys.stderr) - print(f" Average prediction probability: {crispr_prediction_probability:.1f}%", file=sys.stderr) - - # Filter off-target false positives if enabled - if args.filter_off_target_fp: - if ontarget == 0 and indel_reads > 0 and crispr_predicted_reads == 0: - if args.verbose: - print(f" Filtering FP off-target site {row['Chromosome']}:{row['Start']}-{row['End']} (indel_reads: {indel_reads}, predicted_reads: {crispr_predicted_reads})", file=sys.stderr) - - if fp_log: - log_fields = [ - row['Chromosome'], row['Start'], row['End'], - ';'.join([str(x) for x in row['Pos']]), total_reads, indel_reads, indel_fraction, - control_total_reads, control_indel_reads, control_indel_fraction, - len(indels), indel_keys, len(bnds), bnd_keys, offtargetsites, ontarget - ] - if args.enable_crispr_prediction: - log_fields.extend([crispr_predicted_reads, crispr_prediction_fraction, round(crispr_prediction_probability, 1)]) - fp_log.write("\t".join([str(field) for field in log_fields]) + "\n") - continue - - # Output results - output_fields = [ - row['Chromosome'], row['Start'], row['End'], - ';'.join([str(x) for x in row['Pos']]), total_reads, indel_reads, indel_fraction, - control_total_reads, control_indel_reads, control_indel_fraction, - len(indels), indel_keys, len(bnds), bnd_keys, offtargetsites, ontarget - ] - if args.enable_crispr_prediction: - output_fields.extend([crispr_predicted_reads, crispr_prediction_fraction, round(crispr_prediction_probability, 1)]) - print("\t".join([str(field) for field in output_fields]), flush=True) - - # ======================================================================== - # STEP 6: Cleanup - # ======================================================================== - - if args.outfile: - sys.stdout.close() - - if fp_log: - fp_log.close() - - expsamfile.close() - consamfile.close() - refFasta.close() - -if __name__ == "__main__": - main() diff --git a/bin/features.py b/bin/features.py new file mode 100755 index 0000000..2067c6e --- /dev/null +++ b/bin/features.py @@ -0,0 +1,316 @@ +#!/usr/bin/env python3 +""" +pileup/features.py — count-free, coverage-invariant pileup featurizer. + +This is the featurizer for the read-based CRISPR-edit-vs-artifact model. It is a +cleaned successor to results/diag/pileup_probe.py:locus_features with two design +rules imposed for cross-assay (ECS deep-amplicon -> WGS ~30x) portability: + + 1. FEATURES ARE COUNT-FREE. Every model feature is a fraction, a ratio, a bp + spread, or a MAPQ — nothing that scales with sequencing depth. Raw read + counts (`spanning`) are returned ONLY as a coverage-adequacy GATE, never as + a model input. (`n_distinct_pos` from the old probe is dropped: it grows + with depth and does not transfer.) + + 2. DEPTH IS SIMULABLE. read_records() walks the CRAM once and returns per-read + records; features_from_records() can then recompute features at full depth + OR after downsampling to a target depth, WITHOUT re-fetching. This is the + ECS->WGS bridge: an ECS locus with 500 reads can be evaluated as if it had + 30, so the model sees the noisy low-depth concordance it will face on WGS. + +Concordance is POSITION-centric: a CRISPR cut puts indels at the SAME reference +position even when their lengths differ read-to-read; repeat slippage scatters +them. So the clonal signal is keyed on WHERE the indel sits, not its size. +""" +import re +import random +from collections import Counter +import numpy as np + +WIN = 25 # bp around the locus to search for indel events +FETCH_PAD = 200 # bp padding for read fetch (reads can start before the locus) +MIN_SPAN = 8 # default min spanning reads to score a locus (coverage gate) + + +# ── guide-homology parsing (assay-independent; from Cas-OFFinder/CRISPRme etc.) ─ +def parse_target_info(ti): + """Extract guide-homology annotation from the `target_info` string. + + Returns dict(min_mm, n_tools, pam). min_mm = fewest protospacer mismatches + across the tools that predicted this site (None if unannotated); n_tools = + number of predicting tools (SRC=...); pam = the PAM if present. + """ + s = "" if ti is None else str(ti) + mm = None + m = re.search(r"MISMATCHES=([0-9,]+)", s) + if m: + vals = [int(x) for x in m.group(1).split(",") if x != ""] + mm = min(vals) if vals else None + n_tools = 0 + m = re.search(r"SRC=([^;]+)", s) + if m: + n_tools = len([t for t in re.split(r"[|,]", m.group(1)) if t.strip()]) + pam = None + m = re.search(r"PAM=([ACGTN]+)", s) + if m: + pam = m.group(1) + return {"min_mm": mm, "n_tools": n_tools, "pam": pam} + + +# ── one CRAM walk -> per-read records ───────────────────────────────────────── +def read_records(bam, chrom, start, end, win=WIN, fetch_pad=FETCH_PAD): + """Walk the reads over a candidate locus ONCE; return (records, mid) or None. + + records: list of dicts, one per usable read: + {'spans': bool, # covers the locus midpoint + 'indel': (ref_pos, length) or None, # largest I/D in-window + 'mapq': int, + 'softclip': [ref_pos, ...]} # in-window soft-clip ref edges + Downstream featurizers subsample this list to simulate lower depth. + """ + lo, hi = start - win, end + win + fetch_lo = max(0, start - fetch_pad) + mid = (start + end) // 2 + try: + reads = bam.fetch(chrom, fetch_lo, end + fetch_pad) + except (ValueError, KeyError): + return None + records = [] + for r in reads: + if r.is_unmapped or r.is_secondary or r.is_supplementary or r.is_duplicate: + continue + spans = r.reference_start <= mid <= (r.reference_end or r.reference_start) + refpos = r.reference_start + best = None # (abs_ref_pos, length) of largest in-window indel + sc = [] + for op, ln in (r.cigartuples or []): + if op in (0, 7, 8): # M/=/X consume ref+query + refpos += ln + elif op == 2: # D consumes ref + if lo <= refpos <= hi and (best is None or ln > best[1]): + best = (refpos, ln) + refpos += ln + elif op == 1: # I consumes query only + if lo <= refpos <= hi and (best is None or ln > best[1]): + best = (refpos, ln) + elif op == 4: # S soft-clip; record ref edge + if lo <= refpos <= hi: + sc.append(refpos) + records.append({"spans": spans, "indel": best, + "mapq": r.mapping_quality, "softclip": sc}) + return records, mid + + +def _subsample(records, downsample_to, rng): + """Thin records to ~downsample_to spanning reads, modelling lower depth. + + Keeps each read independently with prob downsample_to/n_spanning, so both + spanning and indel reads are thinned together and fractions are preserved in + expectation while acquiring realistic low-depth sampling noise. + """ + n_span = sum(1 for r in records if r["spans"]) + if downsample_to is None or n_span <= downsample_to: + return records + p = downsample_to / n_span + return [r for r in records if rng.random() < p] + + +# ── records -> count-free feature dict ──────────────────────────────────────── +def features_from_records(records, min_span=MIN_SPAN, downsample_to=None, + rng=None, return_lowcov=False, cut_pos=None): + """Compute count-free features from read records (optionally downsampled). + + Returns a dict, or None (or {'spanning','lowcov':True} if return_lowcov) when + spanning coverage < min_span. `spanning` is included for GATING only — do not + feed it to a model. + + `cut_pos` is the PREDICTED cut site (the hotspot coordinate). When given, the + returned dict carries `cut_dist` = |modal_pos - cut_pos|: the "is the indel near + the PAM?" check that a human reviewer does first and that this feature set had no + equivalent for. Cas9 cuts ~3 bp from the PAM, so a genuine edit sits within a few + bp; measured on 146 human-confirmed CART edit rows the median is 1 bp and 98.6% + are within 20 bp, while sites called at curated-negative AAVS1 loci run to a median + of 24 bp. NaN when there is no indel to measure — NOT 0, because 0 would claim the + indel sits exactly on the cut. HistGradientBoostingClassifier handles NaN natively. + """ + if downsample_to is not None: + records = _subsample(records, downsample_to, rng or random.Random(0)) + + spanning = sum(1 for r in records if r["spans"]) + if spanning < min_span: + return {"spanning": spanning, "lowcov": True} if return_lowcov else None + + indel = [r for r in records if r["indel"] is not None] + n_indel = len(indel) + if n_indel: + pos = np.array([r["indel"][0] for r in indel]) + length = np.array([r["indel"][1] for r in indel]) + mapq = np.array([r["mapq"] for r in indel]) + center = Counter(pos.tolist()).most_common(1)[0][0] # modal cut (robust) + near = np.abs(pos - center) <= 2 + conc_ratio = float(near.sum()) / n_indel # count-free clonality + pos_conc = float(near.sum()) / spanning # frac of all reads + pos_mad = float(np.median(np.abs(pos - center))) + modal_len = int(Counter(length[near].tolist()).most_common(1)[0][0]) + modal_mapq = float(np.median(mapq[near])) + modal_pos = int(center) # OBSERVED indel ref pos + cut_dist = (abs(modal_pos - int(cut_pos)) if cut_pos is not None else np.nan) + else: + conc_ratio = pos_conc = pos_mad = modal_mapq = 0.0 + modal_len = 0 + modal_pos = None + cut_dist = np.nan # no indel observed: distance is undefined, not zero + + sc_all = [p for r in records for p in r["softclip"]] + sc_modal = (Counter(sc_all).most_common(1)[0][1] / spanning) if sc_all else 0.0 + + return dict( + spanning=spanning, # GATE ONLY (not a model feature) + lowcov=False, + indel_frac=n_indel / spanning, # fraction ✓ + conc_ratio=conc_ratio, # of indel reads, frac at modal cut ✓ count-free + pos_conc=pos_conc, # of spanning reads, frac at modal cut ✓ + pos_mad=pos_mad, # bp spread of indel positions ✓ + modal_len=modal_len, # bp size of modal indel ✓ + modal_mapq=modal_mapq, # repeat => low MAPQ ✓ + softclip_frac=sc_modal, # fraction ✓ + modal_pos=modal_pos, # OBSERVED indel ref pos (for control recompute/snapshot) + cut_dist=cut_dist, # bp from observed indel to PREDICTED cut ✓ (NaN if none) + ) + + +# ── reference sequence context (the "is it in a repeat?" review rule) ───────── +# The first thing a reviewer checks in IGV is whether the site sits in or beside a +# repetitive region: indels there are overwhelmingly alignment artifacts rather than +# CRISPR edits, because a polymerase slipping in a homopolymer and an aligner placing +# a read ambiguously in a tandem repeat both manufacture indel-looking evidence. +# +# The feature set had no direct measure of this — only `modal_mapq`, which is an +# indirect proxy (repeats mismap, so MAPQ falls) and misses short homopolymers and +# STRs entirely, since those still map uniquely at high MAPQ. These two features read +# the reference directly and need no external annotation track. +REPEAT_WIN = 25 # bp each side of the site to characterise +MAX_STR_UNIT = 4 # look for tandem repeats of unit length 1..4 + + +def homopolymer_run(seq, centre_idx): + """Longest single-base run overlapping or adjacent to `centre_idx`.""" + if not seq: + return 0 + best = 0 + i = 0 + n = len(seq) + while i < n: + j = i + while j + 1 < n and seq[j + 1] == seq[i]: + j += 1 + # only runs that touch the site of interest matter; a homopolymer 20 bp away + # does not explain an indel here + if i - 1 <= centre_idx <= j + 1: + best = max(best, j - i + 1) + i = j + 1 + return best + + +def repeat_context(fasta, chrom, pos, win=REPEAT_WIN, max_unit=MAX_STR_UNIT): + """Reference-sequence repeat features around a site. + + `fasta` is an open pysam.FastaFile; `pos` a 0-based reference position. + Returns {'homopolymer_len', 'repeat_frac'}; zeros if the sequence cannot be read + (unplaced contig, off the end) so a missing reference never fabricates signal. + """ + try: + lo = max(0, int(pos) - win) + seq = fasta.fetch(str(chrom), lo, int(pos) + win + 1).upper() + except (ValueError, KeyError, IndexError): + return {"homopolymer_len": 0, "repeat_frac": 0.0} + if not seq: + return {"homopolymer_len": 0, "repeat_frac": 0.0} + + centre = int(pos) - lo + hp = homopolymer_run(seq, centre) + + # fraction of the window inside a tandem repeat of unit length 1..max_unit with at + # least two consecutive copies. Union across unit sizes, so nested repeats are not + # double counted. + covered = bytearray(len(seq)) + for unit in range(1, max_unit + 1): + i = 0 + while i + 2 * unit <= len(seq): + if seq[i:i + unit] == seq[i + unit:i + 2 * unit]: + j = i + unit + while j + unit <= len(seq) and seq[j:j + unit] == seq[i:i + unit]: + j += unit + for k in range(i, j): + covered[k] = 1 + i = j + else: + i += 1 + return {"homopolymer_len": int(hp), + "repeat_frac": round(sum(covered) / len(seq), 4)} + + +# ── convenience one-shot wrapper (fetch + compute) ──────────────────────────── +def locus_features(bam, chrom, start, end, min_span=MIN_SPAN, + downsample_to=None, rng=None, return_lowcov=False, cut_pos=None): + """Fetch reads at a locus and return count-free features (or None/lowcov).""" + rr = read_records(bam, chrom, start, end) + if rr is None: + return None + records, _ = rr + return features_from_records(records, min_span=min_span, + downsample_to=downsample_to, rng=rng, + return_lowcov=return_lowcov, cut_pos=cut_pos) + + +# count-free features safe to feed a model (spanning/lowcov are gates, not inputs) +MODEL_FEATURES = ["indel_frac", "conc_ratio", "pos_conc", "pos_mad", + "modal_len", "modal_mapq", "softclip_frac", + # added after auditing the model against the manual-review rules: + # cut_dist = "is the indel near the PAM?" (validated held-out on CART) + # homopolymer_len / repeat_frac = "is it in a repeat?" + "cut_dist", "homopolymer_len", "repeat_frac"] +HOMOLOGY_FEATURES = ["min_mm", "n_tools"] + + +def check_sklearn_version(model, name="model", raise_on_backward=True): + """Loudly flag a scikit-learn version skew between a pickled model and the + runtime, so a container/library bump can't silently mis-score. + + No-op for non-sklearn models (e.g. xgboost) or when the pickle did not record + a version. Behaviour on a (major, minor) mismatch: + * runtime OLDER than the pickle -> raise RuntimeError (the backward- + incompatible load is the case that silently corrupts predictions); + * any other skew (e.g. the intended 1.6.1 model under a 1.8.0 runtime) + -> RuntimeWarning on stderr and proceed. + """ + import warnings + pickled = getattr(model, "_sklearn_version", None) + if pickled is None: # unwrap a Pipeline and inspect its final estimator + steps = getattr(model, "steps", None) + if steps: + try: + pickled = getattr(steps[-1][1], "_sklearn_version", None) + except Exception: + pickled = None + if pickled is None: + return # not an sklearn estimator, or version not recorded in the pickle + try: + import sklearn + runtime = sklearn.__version__ + r = tuple(int(x) for x in runtime.split(".")[:2]) + p = tuple(int(x) for x in pickled.split(".")[:2]) + except Exception: + return + if r == p: + return + msg = (f"[sklearn version guard] {name}: model pickled under scikit-learn " + f"{pickled} but the runtime is {runtime}.") + if raise_on_backward and r < p: + raise RuntimeError( + msg + " The runtime is OLDER than the model — loading it can silently " + f"produce wrong scores. Rebuild the image with scikit-learn>={pickled} " + "or re-pickle the model.") + warnings.warn( + msg + " Proceeding with a forward-compatible load; sanity-check outputs if " + "this skew is unexpected.", RuntimeWarning) diff --git a/bin/find_edited_reads.py b/bin/find_edited_reads.py new file mode 100755 index 0000000..13344b4 --- /dev/null +++ b/bin/find_edited_reads.py @@ -0,0 +1,2422 @@ +#!/usr/bin/env python3 + +from __future__ import division +import edlib +import argparse, re, string, csv, os, sys +import scipy.stats as stats +import joblib +import pandas as pd +import pyranges as pr +import numpy as np +import pysam +import bisect +from collections import defaultdict + +class GenomicDistanceIndex: + def __init__(self, df): + """ + Input: Pandas DataFrame with columns 'Chromosome' and 'Pos' + """ + self.index = {} + + # 1. Group by Chromosome and extract positions + # This is vectorized and significantly faster than iterating rows + for chrom, group in df.groupby('Chromosome'): + # Convert the 'Pos' column to a sorted list + # Sorting is mandatory for binary search (bisect) to work + self.index[chrom] = sorted(group['Pos'].tolist()) + + def get_min_dist(self, query_chrom, query_pos): + """ + Returns the minimum distance from query_pos to any target on query_chrom. + Returns float('inf') if chromosome not found. + """ + # Fast Dictionary Lookup + if query_chrom not in self.index: + return float('inf') + + positions = self.index[query_chrom] + + # Binary Search (O(log N)) + idx = bisect.bisect_left(positions, query_pos) + + # Edge Case 1: Insertion point is 0 (closest is the first item) + if idx == 0: + return abs(positions[0] - query_pos) + + # Edge Case 2: Insertion point is end (closest is the last item) + if idx == len(positions): + return abs(positions[-1] - query_pos) + + # Normal Case: Check neighbors (left and right of insertion point) + before = positions[idx - 1] + after = positions[idx] + + return min(abs(before - query_pos), abs(after - query_pos)) + +# ============================================================================= +# Constants & Helpers +# ============================================================================= + +BAM_CMATCH = 0 +BAM_CINS = 1 +BAM_CDEL = 2 +BAM_CREF_N = 3 +BAM_CSOFT_CLIP = 4 +BAM_CHARD_CLIP = 5 +BAM_CPAD = 6 +BAM_CEQUAL = 7 +BAM_CDIFF = 8 + +CONSUMES_REF = {BAM_CMATCH, BAM_CDEL, BAM_CREF_N, BAM_CEQUAL, BAM_CDIFF} +CONSUMES_READ = {BAM_CMATCH, BAM_CINS, BAM_CSOFT_CLIP, BAM_CEQUAL, BAM_CDIFF} + +# Define globals once to avoid rebuilding them on every function call +CIGAR_OPS = {'M':0, 'I':1, 'D':2, 'N':3, 'S':4, 'H':5, 'P':6, '=':0, 'X':0} +CIGAR_REGEX = re.compile(r'(\d+)([MIDNSHP=X])') + +BND_REGEX = re.compile(r"([ACGTNacgtn]*)(\[|\])([^:]+:\d+)(\[|\])([ACGTNacgtn]*)") + +def reverse_complement(seq): + """Returns the reverse complement of a DNA string.""" + complement = str.maketrans('ACGTNacgtn', 'TGCANtgcan') + return seq.translate(complement)[::-1] + +def parse_region_string(region_string): + """ + Parses a genomic region string in the format 'chrom:start-end'. + """ + if not region_string: + raise ValueError("Region string is empty.") + + clean_region = region_string.replace(',', '') + + if ':' not in clean_region: + raise ValueError(f"Invalid format: '{region_string}'. Expected 'chrom:start-end'.") + + chrom, coords = clean_region.rsplit(':', 1) + + if not chrom: + raise ValueError(f"Invalid format: '{region_string}'. Chromosome name is empty.") + + if '-' not in coords: + raise ValueError(f"Invalid format: '{region_string}'. Expected 'start-end'.") + + try: + start_str, end_str = coords.split('-') + start = int(start_str) + end = int(end_str) + except ValueError: + raise ValueError(f"Invalid coordinates in '{region_string}'.") + + if start > end: + raise ValueError(f"Invalid coordinates: Start ({start}) cannot be greater than End ({end}).") + + return chrom, start, end + +def get_sequence(fasta_handle, chrom, start, end): + """Safe fetch from fasta.""" + if not fasta_handle: + return None + try: + return fasta_handle.fetch(chrom, start, end).upper() + except (ValueError, KeyError, IndexError): + return None + +def parse_cigar_string(cigar_str): + """Parses CIGAR string into list of tuples.""" + if not cigar_str or cigar_str == '*': + return [] + # Use findall (which runs in C) and a list comprehension + return [(CIGAR_OPS[op], int(length)) for length, op in CIGAR_REGEX.findall(cigar_str)] + +def cigar_summary(cigar_str): + # Map back the ints from parse_cigar_string to letters + # CIGAR_OPS = {'M':0, 'I':1, 'D':2, 'N':3, 'S':4, 'H':5, 'P':6, '=':0, 'X':0} + INV_CIGAR_OPS = {0: 'M', 1: 'I', 2: 'D', 3: 'N', 4: 'S', 5: 'H', 6: 'P'} + + cigar_sum = { 'M': 0, 'I': 0, 'D': 0, 'N': 0, 'S': 0, 'H': 0, 'P': 0, '=': 0, 'X': 0 } + + # Use your fast pre-compiled regex parser + tuples = parse_cigar_string(cigar_str) + + for op_int, length in tuples: + cigar_sum[INV_CIGAR_OPS.get(op_int, 'M')] += length + + return cigar_sum + +def cigar_to_coords(cigar, r_name, r_start_pos, strand, is_primary=False): + """ + Calculates query (read) and reference coordinates for an alignment. + Expects CIGAR to be normalized to the Query 5'->3' orientation. + """ + q_start = 0 + if cigar and cigar[0][0] in [BAM_CSOFT_CLIP, BAM_CHARD_CLIP]: + q_start = cigar[0][1] + + q_consumed_aligned = sum(l for op, l in cigar if op in {BAM_CMATCH, BAM_CINS, BAM_CEQUAL, BAM_CDIFF}) + r_aligned = sum(l for op, l in cigar if op in CONSUMES_REF) + + q_end = q_start + q_consumed_aligned - 1 + + return { + 'q_start': q_start, + 'q_end': q_end, + 'r_name': r_name, + 'r_start': r_start_pos, + 'r_end': r_start_pos + r_aligned - 1, + 'strand': strand, + 'is_primary': is_primary + } + +def make_info_string(data): + """ + Converts a single dict or a list of dicts into a VCF INFO string. + Aggregates values for shared keys across a list. + Handles pysam types (tuples for lists, booleans for flags). + """ + if not data: + return "." + + # Normalize input: ensure we always iterate over a list of dicts + if isinstance(data, dict): + data_list = [data] + elif isinstance(data, list): + data_list = data + else: + return "." + + info_parts = [] + + # 1. Identify all unique keys present across the input + all_keys = sorted(set().union(*(d.keys() for d in data_list))) + + for k in all_keys: + vals = [] + is_flag = False + + for d in data_list: + if k in d: + v = d[k] + # Handle pysam Flags (boolean True implies presence) + if isinstance(v, bool): + if v: + is_flag = True + # Handle pysam Tuples/Lists (e.g., AF=0.1,0.2) + elif isinstance(v, (tuple, list)): + vals.extend([str(x) for x in v]) + # Handle scalars (int, str, float) + else: + vals.append(str(v)) + + # 2. Format string based on content + # If it was a flag and we collected no value data (pure flag) + if is_flag and not vals: + info_parts.append(k) + # If we have values, join them (e.g. KEY=val1,val2) + elif vals: + info_parts.append(f"{k}={','.join(vals)}") + + return ';'.join(info_parts) + +def get_bnd_parts(alt_str): + """ + Parses VCF BND strings (e.g., ]chr1:123]T) into components. + Returns: (pre_bases, bracket_char, remote_chrom, remote_pos, post_bases) + """ + # Regex captures: 1=Pre, 2=Bracket, 3=RemoteLoc, 4=Bracket, 5=Post + match = BND_REGEX.fullmatch(alt_str) + if not match: + return None + return match.groups() + +def format_bnd(ref, alt, chrom_mate, pos_mate, fragment, strand_self, strand_mate): + """ + Formats VCF breakend string. + strand_self: Strand of the anchor (current VCF record) + strand_mate: Strand of the target (mate) + """ + + # REF ALT Meaning + # s t[p[ piece extending to the right of p is joined after t + # s t]p] reverse comp piece extending left of p is joined after t + # s ]p]t piece extending to the left of p is joined before t + # s [p[t reverse comp piece extending right of p is joined before t + + # Simplified logic matching typical caller output: + if fragment == "left": + if strand_self == '+' and strand_mate == '+': + return f"{ref}{alt}[{chrom_mate}:{pos_mate + 1}[" + elif strand_self == '+' and strand_mate == '-': + return f"{ref}{alt}]{chrom_mate}:{pos_mate + 1}]" + elif strand_self == '-' and strand_mate == '-': + return f"{ref}{alt}[{chrom_mate}:{pos_mate + 1}[" + elif strand_self == '-' and strand_mate == '+': + return f"[{chrom_mate}:{pos_mate + 1}[{alt}{ref}" + + else: # right + if strand_self == '+' and strand_mate == '+': + return f"]{chrom_mate}:{pos_mate + 1}]{alt}{ref}" + elif strand_self == '+' and strand_mate == '-': + return f"[{chrom_mate}:{pos_mate + 1}[{alt}{ref}" + elif strand_self == '-' and strand_mate == '-': + return f"]{chrom_mate}:{pos_mate + 1}]{alt}{ref}" + elif strand_self == '-' and strand_mate == '+': + return f"{ref}{alt}]{chrom_mate}:{pos_mate + 1}]" + + return f"<{chrom_mate}:{pos_mate + 1}>" + +def generate_contig(chrom,pos,ref_base,alt_base,svtype,ref_file,flank_length): + """ + Constructs the theoretical alternate sequence (Contig) using the Reference genome. + Logic: + 1. Identify SV type (Linear vs BND). + 2. Fetch Local Flank (Left or Right depending on break orientation). + 3. Fetch Remote Flank (and RC if necessary based on bracket direction). + 4. Stitch them together. + """ + # chrom = record['chrom'] #record.chrom + # pos = record['pos'] #record.pos # 1-based + # ref_base = record['ref'] #record.ref + # alt_base = record['alt'] #record.alts[0] + # svtype = record['type'] #record.info.get('SVTYPE', 'Unknown') + #strand = record['info']['STRAND'] #record.info.get('STRAND', '') + + # Pysam 0-based conversion + start_idx = pos - 1 + end_idx = start_idx + len(ref_base) + + try: + # --- Handle Breakends (BND) --- + if svtype == 'BND' or '[' in alt_base or ']' in alt_base: + parts = get_bnd_parts(alt_base) + if not parts: + return "Error: Unparseable BND string" + + pre_bases, bracket, remote_loc, _, post_bases = parts + r_chrom, r_pos = remote_loc.split(':') + r_pos = int(r_pos) + + # 1. Get Local Sequence + if pre_bases: + # Local is upstream (Left) -> Break + local_seq = ref_file.fetch(chrom, max(0, start_idx - flank_length), end_idx - 1) + + if bracket == '[': + r_start_0 = r_pos - 1 + remote_seq = ref_file.fetch(r_chrom, r_start_0, r_start_0 + flank_length) + else: # bracket == ']' + # Remote points Reverse (Left/Upstream of r_pos) -> RC needed + r_end_0 = r_pos + raw_remote = ref_file.fetch(r_chrom, max(0, r_end_0 - flank_length), r_end_0) + remote_seq = reverse_complement(raw_remote) + + return local_seq + pre_bases + remote_seq #if strand=="+" else reverse_complement(local_seq + pre_bases + remote_seq) + + else: # joined before t (ref is downstream) + if bracket == '[': + local_seq = ref_file.fetch(chrom, start_idx, end_idx + flank_length) + # Remote points Forward (Right/Downstream of r_pos) + r_start_0 = r_pos - 1 + raw_remote = ref_file.fetch(r_chrom, r_start_0 + 1, r_start_0 + flank_length) + remote_seq = reverse_complement(raw_remote) + + else: # bracket == ']' + local_seq = ref_file.fetch(chrom, start_idx + 1, end_idx + flank_length) + # Remote points Reverse (Left/Upstream of r_pos) -> RC needed + r_end_0 = r_pos + remote_seq = ref_file.fetch(r_chrom, max(0, r_end_0 - flank_length), r_end_0) + + return remote_seq + post_bases + local_seq #if strand=="+" else reverse_complement(remote_seq + post_bases + local_seq) + + # --- Handle Linear SVs (DEL, INS, etc) --- + else: + + left_flank = '' + right_flank = '' + + if len(alt_base) > len(ref_base) or svtype == 'INS' or svtype == 'DUP': + left_flank = ref_file.fetch(chrom, max(0, start_idx - flank_length), start_idx) + right_flank = ref_file.fetch(chrom, end_idx, end_idx + flank_length) + # For linear SVs, we sandwich the ALT string between the flanks + + elif len(alt_base) < len(ref_base) or svtype == 'DEL': + left_flank = ref_file.fetch(chrom, max(0, start_idx - flank_length), start_idx) + right_flank = ref_file.fetch(chrom, end_idx, end_idx + flank_length) + # For linear SVs, we sandwich the ALT string between the flanks + + seq = f"{left_flank}{alt_base}{right_flank}" # if strand=="+" else reverse_complement(f"{left_flank}{alt_base}{right_flank}") + + return seq + + except KeyError as e: + return f"Error: Chromosome/Region not found in reference ({e})" + except Exception as e: + return f"Error: {str(e)}" + +# ============================================================================= +# Main function to call SV from a split read alignment. +# Args are a dict of split alignment coordinates and returns a dict for VCF record generation +# ============================================================================= + +def call_sv_from_split_read(aln1, aln2, query_seq, fasta_handle=None): + """ + Core SV calling logic with Ref/Alt sequence generation and Primary alignment anchoring. + """ + # 1. Sort alignments by their position in the READ (Query Order) + if aln1['q_start'] < aln2['q_start']: + L, R = aln1, aln2 + else: + L, R = aln2, aln1 + + read_start = L['q_start'] + read_end = R['q_end'] + read_strand = L['strand'] if L['is_primary'] else R['strand'] + + # 2. Adjust for Overlap + read_gap = R['q_start'] - L['q_end'] - 1 + overlap = -read_gap if read_gap < 0 else 0 + + # Effective Ref coordinates + # R matches starting at R['r_start']. + # If there was an overlap, the 'true' breakpoint on the R side is pushed forward/backward. + if overlap > 0: + if L['strand'] == R['strand'] or R['strand'] == '+': # if event is a del/dup or a BND and right strand is FWD + R['r_start'] += overlap + R['q_start'] += overlap + else: # if the right strand is - then move it to the left and increase the R start pos. + R['r_end'] -= overlap + R['q_start'] += overlap + + read_gap = 0 + + # 3. Get SV positions, which are strand dependent. Note ++ and -- are equivalent here. + bp1_chrom = L['r_name'] + bp1_pos = L['r_end'] if L['strand'] == R['strand'] or L['strand'] == '+' else L['r_start'] # End of first segment (0-based, strand-specific) + + bp2_chrom = R['r_name'] + bp2_pos = R['r_start'] if L['strand'] == R['strand'] or R['strand'] == '+' else R['r_end'] # Start of second segment (0-based, strand-specific) + + # Base at the break (Anchor Base) + # For L, it is the last aligned base. + ref_base = get_sequence(fasta_handle, bp1_chrom, bp1_pos, bp1_pos + 1) or 'N' # note this is the base of the right end of the left segment, before the event. + + # Set SV data for now. This can change based on later analysis. + sv = { + 'chrom': bp1_chrom, + 'pos': bp1_pos, # VCF 1-based POS is usually this value (0-based index of base before) + 'chrom2': bp2_chrom, + 'pos2': bp2_pos, + 'strands': L['strand']+R['strand'] if L['is_primary'] else R['strand']+L['strand'], + 'ref': ref_base, + 'alt': '.', + 'info': {} + } + read_seq = query_seq[read_start : read_end + 1] + #sv['info']['SEQ'] = read_seq if read_strand == '+' else reverse_complement(read_seq) + + # CASE 1: BND (Translocation OR Opposite Orientation Junction) + # If chromosomes differ OR strands differ (opposite orientations), treat as BND. + if bp1_chrom != bp2_chrom or L['strand'] != R['strand']: + sv['alttype'] = 'BND' + alt_seq = query_seq[L['q_end'] : R['q_start'] - 1] if read_gap else '' + + # Primary Alignment Logic for BND: + # We must output the record anchored at the Primary Alignment. + if L['is_primary']: + + if L['strand'] == '-': + alt_seq = reverse_complement(alt_seq) + + # Anchor at bp1 (End of L) + sv['alt'] = format_bnd(ref_base, alt_seq, bp2_chrom, bp2_pos, "left", L['strand'], R['strand']) + #sv['info']['SVTYPE'] = 'BND' + #sv['info']['CHR2'] = bp2_chrom + #sv['info']['POS2'] = bp2_pos + + else: + # Anchor at bp2 (Start of R) + # We need the anchor base at bp2_pos - 1 + if R['strand'] == '-': + alt_seq = reverse_complement(alt_seq) + + if fasta_handle: + anchor_R = get_sequence(fasta_handle, bp2_chrom, bp2_pos, bp2_pos + 1) or 'N' + else: + anchor_R = 'N' + + sv['chrom'] = bp2_chrom + sv['pos'] = bp2_pos + sv['chrom2'] = bp1_chrom + sv['pos2'] = bp1_pos + sv['ref'] = anchor_R + sv['alt'] = format_bnd(anchor_R, alt_seq, bp1_chrom, bp1_pos, "right", R['strand'], L['strand']) + #sv['info']['SVTYPE'] = 'BND' + #sv['info']['CHR2'] = bp1_chrom + #sv['info']['POS2'] = bp1_pos + + return sv + + # Continue if not a BND + + # Calculate reference span + ref_span = bp2_pos - bp1_pos - 1 + + # CASE 3: Duplication + if ref_span <= 0 and read_gap >= 0: + + if bp2_pos < bp1_pos: + sv['chrom'] = bp2_chrom + sv['pos'] = bp2_pos - 1 # need to adjust to the base before because bp2_pos is the start of the R segment (0-based) + sv['chrom2'] = bp1_chrom + sv['pos2'] = bp1_pos # this is the end of the L segment, so is correct. + ref_base = get_sequence(fasta_handle, bp2_chrom, bp2_pos - 1, bp2_pos) # This is the base before the event, 0-based. + sv['ref'] = ref_base + + sv['alttype'] = 'DUP' if read_gap == 0 else 'INS' + #sv['info']['SVTYPE'] = 'DUP' if read_gap == 0 else 'INS' + # sv['info']['SVLEN'] = abs(ref_span) + # sv['info']['CHR2'] = sv['chrom2'] + # sv['info']['POS2'] = sv['pos2'] + # sv['info']['END'] = sv['pos2'] + + if fasta_handle: + alt_seq = ref_base + query_seq[L['q_end'] : R['q_start']] if read_gap > 0 else ref_base + # Fetch duplicated sequence + dup_seq = get_sequence(fasta_handle, bp1_chrom, bp2_pos, bp1_pos + 1) # using first part of R segment and last of L is correct here to get the exact duplicated sequence. +1 to bp1_pos because it is 0-based and need to specify the end coordinate. + if dup_seq: + sv['alt'] = alt_seq + dup_seq + else: + sv['alt'] = '' if read_gap == 0 else '' + else: + sv['alt'] = '' if read_gap == 0 else '' + + return sv + + # CASE 4: DEL + elif ref_span > 0: + + # DELETION + sv['alttype'] = 'DEL' + #sv['info']['SVTYPE'] = 'DEL' + # sv['info']['SVLEN'] = -ref_span + # sv['info']['CHR2'] = sv['chrom2'] + # sv['info']['POS2'] = sv['pos2'] + # sv['info']['END'] = sv['pos2'] + + # REF: Anchor + Deleted Sequence + # ALT: Anchor + if fasta_handle: + del_seq = get_sequence(fasta_handle, bp1_chrom, bp1_pos + 1, bp2_pos) # Sequence strictly between + if del_seq: + + # Sanity check to see if del_seq is right length + if len(del_seq) != abs(ref_span): + print("error creating deleted sequence.",file=sys.stderr) + + sv['ref'] = ref_base + del_seq + + if read_gap == 0: + sv['alt'] = ref_base + + elif read_gap > 0: + alt_base = query_seq[L['q_end'] : L['q_end']+read_gap] + if L['strand'] == '-': + alt_base = reverse_complement(alt_base) + + sv['alt'] = ref_base + alt_base + + else: + sv['alt'] = '' + else: + sv['alt'] = '' + + return sv + + return None + +# ============================================================================= +# 1. Indels from CIGAR +# ============================================================================= + +def get_cigar_indel_vcf(read, fasta_file, target_positions, target_index=None): + """ + Detects complex indels directly from the CIGAR string. + """ + cigar = read.cigartuples + if not cigar: return None + + if isinstance(target_positions, int): + target_positions = [target_positions] + + # Identify indices of all Indels (I or D) + indel_indices = [i for i, (op, length) in enumerate(cigar) if op in [BAM_CINS, BAM_CDEL]] + if not indel_indices: return None + + first_indel_idx = indel_indices[0] + last_indel_idx = indel_indices[-1] + left_flank_idx = first_indel_idx - 1 + + # Must have a left flank that consumes reference (Match/Eq/Diff) + if left_flank_idx < 0 or cigar[left_flank_idx][0] not in [BAM_CMATCH, BAM_CEQUAL, BAM_CDIFF]: + return None + + current_ref = read.reference_start + current_read = 0 + anchor_ref_pos, anchor_read_pos = None, None + end_ref_pos, end_read_pos = None, None + + for i, (op, length) in enumerate(cigar): + ref_consumed = length if op in CONSUMES_REF else 0 + read_consumed = length if op in CONSUMES_READ else 0 + + if i == left_flank_idx: + anchor_ref_pos = current_ref + ref_consumed - 1 + anchor_read_pos = current_read + read_consumed - 1 + + current_ref += ref_consumed + current_read += read_consumed + + if i == last_indel_idx: + end_ref_pos = current_ref + end_read_pos = current_read + break + + if anchor_ref_pos is None or end_ref_pos is None: return None + + try: + # Construct VCF record info + out_dict = {} + out_dict['read'] = read.query_name + out_dict['chrom'] = read.reference_name + out_dict['pos'] = anchor_ref_pos + out_dict['distance'] = min(abs(out_dict['pos'] - x) for x in target_positions) + out_dict['ref'] = fasta_file.fetch(read.reference_name, anchor_ref_pos, end_ref_pos).upper() + out_dict['alt'] = read.query_sequence[anchor_read_pos : end_read_pos].upper() + out_dict['chrom2'] = read.reference_name + out_dict['pos2'] = out_dict['pos'] + len(out_dict['ref']) + out_dict['distance2'] = min(abs(out_dict['pos2'] - x) for x in target_positions) + out_dict['strands'] = '++' + out_dict['alttype'] = 'DEL' if len(out_dict['ref']) > len(out_dict['alt']) else 'INS' + out_dict['info'] = {'Source':'CIGAR', + 'Read':read.query_name, + 'Cigar':read.cigarstring, + 'ReadStrand': "+" if read.is_forward else "-", + 'ReadSeq':read.query_sequence} + return out_dict + except (ValueError, IndexError): + return None + +# ============================================================================= +# 2. Indels/BNDs from Supplementary Alignment (SA) +# ============================================================================= + +# Get indels/BNDs from SA tag +def get_sa_indel_vcf(read, fasta_file, target_positions, target_index): + """ + Detects events by merging Primary and Supplementary Alignments. + Handles DEL/INS for collinear events and BND for translocations/inversions. + """ + if not read.has_tag("SA"): return None + + sa_tag = read.get_tag('SA') + + # 1. Get Read Seq + query_seq = read.query_sequence + if read.is_reverse: + query_seq = reverse_complement(query_seq) + + # 2. Parse Primary Alignment (ALN1) - Mark as PRIMARY + cigar1 = read.cigar + aln1 = cigar_to_coords( + cigar1, + read.reference_name, + read.reference_start, # start position of alignment, 0-based + '-' if read.is_reverse else '+', + is_primary=True + ) + + # 3. Parse Secondary Alignment(s) from SA tag (ALN2) + sa_records = [s for s in sa_tag.split(';') if s] + + if not sa_records: return None + + sa = sa_records[0] + parts = sa.split(',') + if len(parts) < 4: + print(f"Error parsing SA tag {sa} in read {read.query_name}", file=sys.stderr) + return None + + rname_2 = parts[0] + pos_2 = int(parts[1]) - 1 # pos is 1-based in SA tags. Convert to 0-based. This is the left-most mapping pos. + strand_2 = parts[2] + cigar_str_2 = parts[3] + sa_mapq = int(parts[4]) + sa_nm = int(parts[5]) + + cigar2 = parse_cigar_string(cigar_str_2) + + aln2 = cigar_to_coords( + cigar2, + rname_2, + pos_2, + strand_2, + is_primary=False + ) + + # The cigars are not aligned if aln1 and aln2 are different directions + # so flip the aln2 coordinates on the read. + if aln1['strand'] != aln2['strand']: + if aln1['strand'] == '-': + q_end = read.query_length - aln1['q_start'] - 1 + q_start = read.query_length - aln1['q_end'] - 1 + aln1['q_start'] = q_start + aln1['q_end'] = q_end + else: + q_end = read.query_length - aln2['q_start'] - 1 + q_start = read.query_length - aln2['q_end'] - 1 + aln2['q_start'] = q_start + aln2['q_end'] = q_end + + # 4. Call SV + sv = call_sv_from_split_read(aln1, aln2, query_seq, fasta_handle=fasta_file) + + if sv: + # Add detailed read info to tagsx + sv['read'] = read.query_name + sv['info']['Read'] = read.query_name + sv['info']['ReadSeq'] = read.query_sequence + sv['info']['ReadStrand'] = aln1['strand'] + sv['info']['Cigar'] = read.cigarstring + # Sanitize SA tag (replace semicolons to preserve VCF format) + sv['info']['SA'] = sa.replace(';', '') + sv['info']['SAMAPQ'] = sa_mapq + + sv['distance'] = min(abs(sv['pos'] - x) for x in target_positions) + sv['distance2'] = target_index.get_min_dist(sv['chrom2'],sv['pos2'])# min(abs(sv['pos2'] - x) for x in target_positions) + + # Common Info Fields + sv['info']['Source'] = 'SA' + + return sv + + return None + +# ============================================================================= +# 3. Indels from Softclips +# ============================================================================= + +def get_softclip_indel_vcf(read, fasta_file, target_positions, search_range, min_clip=8): + """ + Detects indels by realigning soft-clipped sequences to the reference. + """ + if read.is_supplementary or read.has_tag("SA") or not read.cigartuples: + return None + + # get primary alignment + cigar1 = read.cigar + aln1 = cigar_to_coords( + cigar1, + read.reference_name, + read.reference_start, # start position of alignment, 0-based + '-' if read.is_reverse else '+', + is_primary=True + ) + + clip_side = None + clip_seq_str = None + clip_len = 0 + ref_start = 0 + ref_end = 0 + clip_read_start = 0 + clip_read_end = 0 + + # Check Right Clip + if cigar1[-1][0] == BAM_CSOFT_CLIP and cigar1[-1][1] >= min_clip: + clip_side = 'Right' + clip_len = cigar1[-1][1] + clip_seq_str = read.query_sequence[-clip_len:] + ref_start = read.reference_end + clip_read_start = read.query_alignment_end + + # Check Left Clip + elif cigar1[0][0] == BAM_CSOFT_CLIP and cigar1[0][1] >= min_clip: + clip_side = 'Left' + clip_len = cigar1[0][1] + clip_seq_str = read.query_sequence[:clip_len] + ref_end = read.reference_start + clip_read_end = read.query_alignment_start + + else: + return None + + # Get search window origin + clip_ref_pos = read.reference_end if clip_side == 'Right' else read.reference_start + window_start_genomic = clip_ref_pos - search_range + + query_chunk = clip_seq_str + try: + ref_window = fasta_file.fetch(read.reference_name, window_start_genomic, clip_ref_pos + search_range).upper() + except ValueError: + return None + + # Simple exact match search first + aln2 = None + match_count = ref_window.count(query_chunk) + match_index = ref_window.find(query_chunk) + + if match_count > 1: + return None + + elif match_count == 1 and match_index > 0: + if clip_side == 'Right': + aln2 = cigar_to_coords([(4,read.query_length - clip_len),(0,len(query_chunk))], + read.reference_name, + window_start_genomic + match_index, + '-' if read.is_reverse else '+', + False) + else: # Left + aln2 = cigar_to_coords([(0,len(query_chunk)),(4,read.query_length - clip_len)], + read.reference_name, + window_start_genomic + match_index, + '-' if read.is_reverse else '+', + False) + + else: + result = edlib.align(query_chunk, ref_window, mode="HW", task="path", k=-1) + if result['locations'] and len(result['locations']) == 0: + match_cigar = parse_cigar_string(result['cigar']) + if clip_side == "Right" and match_cigar[-1][0] == BAM_CMATCH and match_cigar[-1][1] >= min_clip: # get ref coordinate of right-most anchor of the match + aln2 = cigar_to_coords([(4,read.query_length - match_cigar[-1][1]),(0,match_cigar[-1][1])], + read.reference_name, + window_start_genomic + result['locations'][0][1] - match_cigar[-1][1] + 1, + '-' if read.is_reverse else '+', + False) + + elif clip_side == "Left" and match_cigar[0][0] == BAM_CMATCH and match_cigar[0][1] >= min_clip: # get ref coordinate of left + aln2 = cigar_to_coords([(0,match_cigar[-1][1]),(4,read.query_length - match_cigar[0][1])], + read.reference_name, + window_start_genomic + result['locations'][0][0], + '-' if read.is_reverse else '+', + False) + + else: + return None + else: + return None + + query_seq = read.query_sequence + if read.is_reverse: + query_seq = reverse_complement(query_seq) + + sv = call_sv_from_split_read(aln1, aln2, query_seq, fasta_handle=fasta_file) + + if sv: + sv['read'] = read.query_name + sv['distance'] = min(abs(sv['pos'] + 1 - x) for x in target_positions) + sv['distance2'] = min(abs(sv['pos2'] - x) for x in target_positions) + sv['info']['Source'] = 'SoftClip' + sv['info']['Read'] = read.query_name + sv['info']['ReadSeq'] = read.query_sequence + sv['info']['ReadStrand'] = aln1['strand'] + sv['info']['Cigar'] = read.cigarstring + + return sv + + return None + +def add_normal_counts(df, reads, fasta, flank=300, debug=False): + + # 1. PRE-COMPUTE: Move DataFrame data into a native Python list of dicts. + # Native Python objects are 100x faster to iterate and update than Pandas DataFrames. + variants = [] + for idx, row in df.iterrows(): + pos = int(row['pos']) + # The indel and breakend paths disagree by one base in what they store as 'pos', and + # generate_contig's linear and BND branches inherit that disagreement, so a single + # convention here cannot serve both. Settled by measurement rather than by reading: run the + # caller with --edited-bam and --control-bam set to the SAME file, where every called event + # must by construction be supported in the control, and count what escapes `-x`. + # indels as-is 12 escapes / 3925 control reads | with +1 72 / 2000 + # breakends as-is 5 control reads | with +1 40 + # So +1 belongs to breakends only. Applying it to both leaves indel calling six times worse; + # applying it to neither leaves breakend control support all but dead, which is why + # control_bnd_reads read zero across every site when it was first added. + if str(row.get('alttype', '')) == 'BND': + pos += 1 + chrom = row['chrom'] + ref = row['ref'] + alt = row['alt'] + + start_idx = pos - 1 + ref_seq = fasta.fetch(chrom, max(0, start_idx - flank), start_idx + len(ref) + flank) + + alt_seq = ref_seq + if alt != '.': + alt_seq = generate_contig(chrom, pos, ref, alt, row['alttype'], fasta, flank) + + variants.append({ + 'idx': idx, + 'chrom': chrom, + 'pos': pos, + 'ref': ref, + 'alt': alt, + 'ref_len': len(ref), + 'alt_len': len(alt), + 'refseq': ref_seq, + 'altseq': alt_seq, + # Supporting FRAGMENT names, not a read tally. Depth below is len(total_reads), a set + # of query_name, so it counts fragments; counting alt per read made an overlapping + # mate pair contribute 2 to the numerator and 1 to the denominator, biasing the + # background upward wherever mates overlap. Both sides are fragments now. + 'control_alt_frags': set() + }) + + total_reads = set() + + # 2. READ LOOP: Iterate reads and filter irrelevant ones early + for read in reads: + if not read.is_mapped or read.is_duplicate or read.is_secondary or read.is_supplementary or read.mapping_quality == 0: + continue + + total_reads.add(read.query_name) + + cigar = read.cigartuples + # Fast exit: perfectly matched reads with no SA tag + if cigar and len(cigar) == 1 and cigar[0][0] == 0 and not read.has_tag('SA'): + continue + + # Extract sequence once per read + read_seq = read.query_sequence + if not read_seq: + continue + + # Extract location data for spatial filtering + read_chrom = read.reference_name + read_start = read.reference_start + + # Check for indels using tuples (1=I, 2=D) instead of string parsing (much faster) + has_indel = any(op in (1, 2) for op, length in cigar) if cigar else False + + # 3. VARIANT LOOP + for v in variants: + + # --- OPTIMIZATION: Spatial Overlap Filter --- + # Don't align reads to variants on different chromosomes or out of range + if read_chrom != v['chrom']: + continue + + # Read must be roughly within the variant's flanking window to be relevant + if not ((v['pos'] - flank - len(read_seq)) <= read_start <= (v['pos'] + flank)): + continue + + # Process VCF via CIGAR if read has indels + if has_indel: + vcf_dict = get_cigar_indel_vcf(read, fasta, v['pos']) + if vcf_dict and vcf_dict['pos'] == v['pos'] and vcf_dict['ref'] == v['ref'] and vcf_dict['alt'] == v['alt']: + v['control_alt_frags'].add(read.query_name) + continue + + # Fast string search + if read_seq in v['refseq']: + continue + + if read_seq in v['altseq']: + v['control_alt_frags'].add(read.query_name) + continue + + # Expensive alignments (only reached if all fast filters fail) + ref_align = edlib.align(read_seq, v['refseq'], mode="HW", task="path") + alt_align = edlib.align(read_seq, v['altseq'], mode="HW", task="path") + + # Skip CIGAR summary logic if edit distance is clearly worse or equal + if alt_align['editDistance'] >= ref_align['editDistance']: + continue + + ref_cigar_sum = cigar_summary(ref_align['cigar']) + alt_cigar_sum = cigar_summary(alt_align['cigar']) + + # .get('=', 0) safely handles cases where that operation doesn't exist in the CIGAR + if alt_cigar_sum.get('=', 0) > ref_cigar_sum.get('=', 0): + + is_alt = False + ref_D = ref_cigar_sum.get('D', 0) + alt_D = alt_cigar_sum.get('D', 0) + ref_I = ref_cigar_sum.get('I', 0) + alt_I = alt_cigar_sum.get('I', 0) + + if v['ref_len'] > v['alt_len'] and ref_D >= alt_D: + is_alt = True + elif v['ref_len'] < v['alt_len'] and ref_I >= alt_I: + is_alt = True + elif v['ref_len'] == v['alt_len']: + is_alt = True + + if is_alt: + v['control_alt_frags'].add(read.query_name) + if debug: + print(f"\tFound control alt count for {v['chrom']}:{v['pos']}:{v['ref']}:{v['alt']}:{ref_D}:{alt_D}:{ref_I}:{alt_I}:{read.query_name}:{read_seq}", file=sys.stderr) + + # 4. REBUILD DATAFRAME: Map calculated data directly back to new columns + df['refseq'] = [v['refseq'] for v in variants] + df['altseq'] = [v['altseq'] for v in variants] + df['control_alt_counts'] = [len(v['control_alt_frags']) for v in variants] + df['control_total_counts'] = len(total_reads) + + return df.copy() + +# ============================================================================ +# SECTION 2: CRISPR PREDICTION FUNCTIONS +# ============================================================================ + +def detect_deletion_from_softclips(read, min_softclip_size=3, max_gap=50): + """Detect potential large deletions from soft-clips and supplementary alignments.""" + if not read.cigartuples: + return 0 + + total_deletion = 0 + + # Parse CIGAR operations + cigar_ops = [] + for op, length in read.cigartuples: + cigar_ops.append((op, length)) + + # Count soft-clips as potential deletions + for op, length in cigar_ops: + if op == 4: # Soft-clip + if length >= min_softclip_size: + total_deletion += length + + # Look for patterns: softclip -> deletion -> softclip + for i in range(len(cigar_ops) - 2): + op1, len1 = cigar_ops[i] + op2, len2 = cigar_ops[i + 1] + op3, len3 = cigar_ops[i + 2] + + if op1 == 4 and op2 == 2 and op3 == 4: # Softclip -> Deletion -> Softclip + if len1 >= min_softclip_size and len2 <= max_gap and len3 >= min_softclip_size: + total_deletion += len2 + elif op1 == 2 and op2 == 4 and op3 == 2: # Deletion -> Softclip -> Deletion + if len2 >= min_softclip_size and len1 <= max_gap and len3 <= max_gap: + total_deletion += (len1 + len3) + + # Look for single softclip patterns with nearby deletions + for i in range(len(cigar_ops) - 1): + op1, len1 = cigar_ops[i] + op2, len2 = cigar_ops[i + 1] + + if op1 == 4 and op2 == 2: # Softclip -> Deletion + if len1 >= min_softclip_size and len2 <= max_gap: + total_deletion += len2 + elif op1 == 2 and op2 == 4: # Deletion -> Softclip + if len2 >= min_softclip_size and len1 <= max_gap: + total_deletion += len1 + + # Look for end soft-clips (left/right) representing large deletions + if len(cigar_ops) >= 1: + # Left soft-clip + if cigar_ops[0][0] == 4: + left_softclip = cigar_ops[0][1] + if left_softclip >= min_softclip_size: + middle_align = sum(length for op, length in cigar_ops[1:] if op == 0) + if middle_align > 5: + total_deletion += left_softclip + + # Right soft-clip + if cigar_ops[-1][0] == 4: + right_softclip = cigar_ops[-1][1] + if right_softclip >= min_softclip_size: + middle_align = sum(length for op, length in cigar_ops[:-1] if op == 0) + if middle_align > 5: + total_deletion += right_softclip + + # Look for internal soft-clips + for i, (op, length) in enumerate(cigar_ops): + if op == 4 and length >= min_softclip_size: + left_align = sum(cigar_ops[j][1] for j in range(i) if cigar_ops[j][0] == 0) + right_align = sum(cigar_ops[j][1] for j in range(i+1, len(cigar_ops)) if cigar_ops[j][0] == 0) + + if left_align > 2 and right_align > 2: + total_deletion += length + + # Check supplementary alignments (SA tags) for soft-clip deletions + if read.has_tag('SA'): + sa_tag = read.get_tag('SA') + sa_entries = sa_tag.split(';') + + for sa_entry in sa_entries: + if not sa_entry: + continue + + sa_parts = sa_entry.split(',') + if len(sa_parts) >= 4: + sa_cigar = sa_parts[3] + sa_softclips = parse_cigar_for_softclips(sa_cigar) + for softclip_size in sa_softclips: + if softclip_size >= min_softclip_size: + total_deletion += softclip_size + + return total_deletion + +def parse_cigar_for_softclips(cigar_string): + """Parse CIGAR string to extract soft-clip sizes.""" + softclips = [] + import re + + cigar_parts = re.findall(r'(\d+)([MIDNSHP=X])', cigar_string) + + for length_str, operation in cigar_parts: + if operation == 'S': # Soft-clip + softclips.append(int(length_str)) + + return softclips + +def parse_cigar_once(read): + """Parse CIGAR operations to extract insertion, deletion, and soft-clip counts.""" + cigar_summary = {'M': 0, 'I': 0, 'D': 0, 'N': 0, 'S': 0, 'H': 0, 'P': 0, '=': 0, 'X': 0} + if not hasattr(read, 'cigartuples') or read.cigartuples is None: + return {'insertions': 0, 'deletions': 0, 'softclips': 0} + + for op, length in read.cigartuples: + if op == 1: + cigar_summary['I'] += length + elif op == 2: + cigar_summary['D'] += length + elif op == 4: + cigar_summary['S'] += length + + # Total deletions = explicit deletions + deletions from soft-clips + total_deletions = cigar_summary['D'] + detect_deletion_from_softclips(read) + + return { + 'insertions': cigar_summary['I'], + 'deletions': total_deletions, + 'softclips': cigar_summary['S'] + } + +def count_mismatches_fast(read): + """ + Returns the number of single-base mismatches (SNPs) in the alignment. + Excludes Indels. Extremely fast version using pre-parsed cigartuples. + """ + try: + nm = read.get_tag("NM") + if nm == 0: + return 0 + + cigar = read.cigartuples + if not cigar: + return nm + + # Operation 1 is Insertion, 2 is Deletion + indels = sum(length for op, length in cigar if op in (1, 2)) + return max(0, nm - indels) + except KeyError: + return 0 + +def calculate_control_fractions(control_bam, chrom, position, window=50): + """Calculate fractions of control reads with different variant types.""" + fractions = { + 'fraction_control_reads_del': 0.0, + 'fraction_control_reads_ins': 0.0, + 'fraction_control_reads_mismatch': 0.0, + 'fraction_control_reads_softclip': 0.0 + } + if not control_bam: + return fractions + + total = del_count = ins_count = mismatch_count = softclip_count = 0 + + for read in control_bam.fetch(chrom, position - window, position + window): + if read.is_unmapped or read.is_duplicate: + continue + total += 1 + if read.cigartuples: + if any(op == 2 for op, _ in read.cigartuples): + del_count += 1 + if any(op == 1 for op, _ in read.cigartuples): + ins_count += 1 + if any(op == 4 for op, _ in read.cigartuples): + softclip_count += 1 + if read.has_tag('MD') and any(c.isalpha() for c in read.get_tag('MD')): + mismatch_count += 1 + + if total > 0: + fractions.update({ + 'fraction_control_reads_del': del_count / total, + 'fraction_control_reads_ins': ins_count / total, + 'fraction_control_reads_mismatch': mismatch_count / total, + 'fraction_control_reads_softclip': softclip_count / total + }) + return fractions + +def calculate_exclusivity_features(read, control_bam, chrom, position, window=100): + """Calculate whether variants are exclusive to edited samples.""" + exclusivity = { + 'variant_exclusive_to_edited': 0, + 'insertion_exclusive_to_edited': 0, + 'deletion_exclusive_to_edited': 0, + 'control_has_same_variant': 0, + } + if not control_bam or read.is_unmapped or read.is_duplicate or not read.cigartuples: + return exclusivity + + has_insertion = any(op == 1 for op, _ in read.cigartuples) + has_deletion = any(op == 2 for op, _ in read.cigartuples) + + read_start, read_end = read.reference_start, read.reference_end + + control_has_same_ins = False + control_has_same_del = False + + for control_read in control_bam.fetch(chrom, max(0, position - window), position + window): + if control_read.is_unmapped or control_read.is_duplicate or not control_read.cigartuples: + continue + ctrl_start, ctrl_end = control_read.reference_start, control_read.reference_end + + # Check for overlapping reads + if not (read_end < ctrl_start or ctrl_end < read_start): + if has_insertion and any(op == 1 for op, _ in control_read.cigartuples): + control_has_same_ins = True + if has_deletion and any(op == 2 for op, _ in control_read.cigartuples): + control_has_same_del = True + + insertion_exclusive = has_insertion and not control_has_same_ins + deletion_exclusive = has_deletion and not control_has_same_del + + any_exclusive = insertion_exclusive or deletion_exclusive + control_has_similar = control_has_same_ins or control_has_same_del + + exclusivity['deletion_exclusive_to_edited'] = 1 if deletion_exclusive else 0 + exclusivity['control_has_same_variant'] = 1 if control_has_similar else 0 + return exclusivity + +def calculate_distance_to_closest_pam(position, targets_df, chrom): + """Calculate distance to closest PAM site.""" + if targets_df is None or len(targets_df) == 0: + return -1 + distances = np.abs(targets_df['Start'] - position) + return distances.min() if len(distances) > 0 else -1 + +def predict_reads_at_position(bam_file, chrom, start, end, pampos, model, fasta, is_on_target=0, control_bam=None, threshold=0.80, read_probs=None): + """Score reads at one locus with the CRISPR model. + + Returns (reads at or above threshold, mean probability as a percentage). If + ``read_probs`` is a dict it is additionally filled with per-read + probabilities keyed by read_tag_key(), keeping the highest score seen for a + record across overlapping loci -- used to emit the optional XP BAM tag. + """ + + reads = [] + for read in bam_file.fetch(chrom, start, end): + if read.is_unmapped or read.is_duplicate: + continue + reads.append(read) + if not reads: + return 0, 0.0 + + # Get control fractions + control_fractions = calculate_control_fractions(control_bam, chrom, start, window=50) if control_bam else { + 'fraction_control_reads_del': 0.0, + 'fraction_control_reads_ins': 0.0, + 'fraction_control_reads_mismatch': 0.0, + 'fraction_control_reads_softclip': 0.0 + } + + # Extract features for each read + features_list = [] + for read in reads: + cigar_data = parse_cigar_once(read) + + read_start = read.reference_start + read_end = read.reference_end + + # Check if read overlaps with target sites + is_at_any_target = 0 + if pampos is not None: + for p in pampos: + if read_start <= p + 25 and read_end >= p - 25: + is_at_any_target = 1 + + # Calculate exclusivity features + exclusivity = calculate_exclusivity_features(read, control_bam, chrom, start, window=100) if control_bam else { + 'deletion_exclusive_to_edited': 0, + 'control_has_same_variant': 0, + } + + # Convert read features to binary + read_has_deletion = 1 if cigar_data['deletions'] > 0 else 0 + read_has_insertion = 1 if cigar_data['insertions'] > 0 else 0 + read_has_mismatch = 1 if count_mismatches_fast(read) > 0 else 0 + + # Calculate indel characteristics + total_indel_size = cigar_data['insertions'] + cigar_data['deletions'] + + # Indel size category + indel_size_category = 0 + if total_indel_size > 0: + if total_indel_size <= 3: + indel_size_category = 1 + elif total_indel_size <= 10: + indel_size_category = 2 + else: + indel_size_category = 3 + + # Insertion to deletion ratio + insertion_to_deletion_ratio = 0.0 + if cigar_data['deletions'] > 0: + insertion_to_deletion_ratio = cigar_data['insertions'] / cigar_data['deletions'] + elif cigar_data['insertions'] > 0: + insertion_to_deletion_ratio = 10.0 + else: + insertion_to_deletion_ratio = 0.0 + + # Indel complexity score + indel_complexity_score = 0.0 + if read.cigartuples: + indel_operations = [op for op, length in read.cigartuples if op in [1, 2]] + complexity = len(indel_operations) + (total_indel_size / 10.0) + indel_complexity_score = min(complexity, 10.0) + + # Create features dictionary + features = { + 'read_pair_gap': abs(read.template_length) if hasattr(read, 'template_length') and read.is_paired and read.is_proper_pair else -1, + 'read_insertion': cigar_data['insertions'], + 'read_deletion': cigar_data['deletions'], + 'read_mismatch': count_mismatches_fast(read), + 'read_softclip': cigar_data['softclips'], + 'read_del_vs_control': read_has_deletion - control_fractions['fraction_control_reads_del'], + 'read_ins_vs_control': read_has_insertion - control_fractions['fraction_control_reads_ins'], + 'read_mismatch_vs_control': read_has_mismatch - control_fractions['fraction_control_reads_mismatch'], + 'deletion_exclusive_to_edited': exclusivity['deletion_exclusive_to_edited'], + 'control_has_same_variant': exclusivity['control_has_same_variant'], + 'distance_to_closest_pam': min(abs(x-start) for x in pampos) if pampos is not None else -1, + 'is_on_target_site': is_on_target, + 'is_at_any_target_site': is_at_any_target, + 'total_indel_size': total_indel_size, + 'indel_size_category': indel_size_category, + 'insertion_to_deletion_ratio': insertion_to_deletion_ratio, + 'indel_complexity_score': indel_complexity_score + } + + features_list.append(features) + + if not features_list: + return 0, 0.0 + + # Get expected features for the model + if hasattr(model, 'feature_names_in_'): + expected_features = list(model.feature_names_in_) + else: + expected_features = ['read_pair_gap', 'read_insertion', 'read_deletion', 'read_mismatch', 'read_softclip', 'read_del_vs_control', 'read_ins_vs_control', 'read_mismatch_vs_control', 'deletion_exclusive_to_edited', 'control_has_same_variant', 'is_on_target_site', 'is_at_any_target_site', 'distance_to_closest_pam', 'total_indel_size', 'indel_size_category', 'insertion_to_deletion_ratio', 'indel_complexity_score'] + + features_df = pd.DataFrame(features_list) + features_df = features_df.reindex(columns=expected_features, fill_value=0) + + # Get model predictions + preds = model.predict_proba(features_df)[:, 1] + + if read_probs is not None: + for read, prob in zip(reads, preds): + key = read_tag_key(read) + prob = float(prob) + if prob > read_probs.get(key, -1.0): + read_probs[key] = prob + + # Calculate results + avg_probability = float(preds.mean() * 100) + + return int((preds >= threshold).sum()), avg_probability + +def merge_dicts_to_tuples(data): + """ + Merges a list of dictionaries into a single dictionary. + Values are aggregated into tuples. + If a value is already a list/tuple, it is flattened to avoid nesting ((x,),). + """ + # 1. Validation & Normalization + if not data: + return {} + if isinstance(data, dict): + data = [data] + if not isinstance(data, list): + return {} + + # 2. Identify all unique keys + all_keys = {k for d in data if isinstance(d, dict) for k in d.keys()} + + merged = {} + + # 3. Aggregation with Flattening + for k in all_keys: + collected = [] + for d in data: + if not isinstance(d, dict) or k not in d: + continue + + val = d[k] + + # If the value is already a list or tuple, extend (flatten) + # We explicitly exclude strings, which are technically iterable but should be treated as atomic here + if isinstance(val, (list, tuple)): + collected.extend(val) + else: + collected.append(val) + + merged[k] = tuple(collected) + + return merged + +def write_vcf_output(df, outfile_name, vcf_header=None, sample_name="EDITED"): + """ + Writes a VCF file using pysam.VariantFile. + Dynamically generates the VCF header based on keys found in the 'info' column. + """ + + info_tags = { + 'SVTYPE': 'SV type.', + 'SVLEN': 'SV length.', + 'Read': 'Names of reads supporting this event.', + 'ReadSeq':'Read sequences.', + 'ReadStrand':'Read strands.', + 'Source':'Event sources.', + 'Cigar': 'Read CIGAR strings.', + 'SA': 'Read supplementary alignments from SA tags.', + 'SAMAPQ': 'Mapping qualities of supplementary alignments.' + } + + fmt_tags = { + 'DP': 'Read depth at this position in edited sample.', + 'CDP': 'Read depth at this position in the control sample.', + 'AD': 'Number of edited reads in this sample.', + 'AC': 'Number of unique editing events in this sample (includes BNDs).', + 'EF': 'Fraction of edited reads in the edited sample (includes BNDs).', + 'CAD': 'Number of edited reads in the control sample.', + 'CEF': 'Fraction of edited reads in the control sample.' + } + + # --- 1. PREPARE HEADER --- + # Create a stub header + header = vcf_header + if header is None: + header = pysam.VariantHeader() + header.add_line('##fileformat=VCFv4.2') + + vcf_out = pysam.VariantFile(outfile_name, 'w', header=header) + vcf_out.header.add_sample(sample_name) + + # DYNAMIC INFO FIELD DETECTION + # We scan the 'info' column to find all unique keys and guess their types + # This prevents 'KeyError' or 'ValueError' in pysam + all_info_keys = set() + + # Collect all keys from the dataframe + for info_dict in df['info']: + if isinstance(info_dict, dict): + all_info_keys.update(info_dict.keys()) + + + all_info_keys.add('SVTYPE') + all_info_keys.add('SVLEN') + all_info_keys.difference_update(fmt_tags.keys()) + + # Add standard/known fields with specific types + # You can expand this list for other known integer/float fields + known_integers = {'SVLEN', 'END', 'MISMATCHES', 'BULGE_SIZE'} + flags = {'TARGET'} + + for key in all_info_keys: + if key in known_integers: + if key not in header.info.keys(): + vcf_out.header.info.add(key, 1, "Integer", f"{info_tags[key]}") + else: + # Default to unlimited string for flexibility + if key not in header.info.keys(): + vcf_out.header.info.add(key, ".", "String", f"{info_tags[key]}") + + for key in fmt_tags: + if key not in header.formats.keys(): + vcf_out.header.formats.add(key, 1, "Integer", f"{fmt_tags[key]}") + + counter = {} + + for _, row in df.iterrows(): + # Create a new record + # Note: We need to handle the contig (chrom). + # If the contig isn't in the header, pysam usually adds it automatically or warns. + # Ideally, we add contigs to header, but here we let pysam handle it on the fly. + + if row['alttype'] == 'REF': + continue + + # Make ID field for this variant + id = ':'.join([str(row['chrom']), str(row['pos']+1), row['alttype']]) + counter[id] = counter.get(id, 0) + 1 + + rec = vcf_out.new_record() + rec.chrom = str(row['chrom']) + rec.pos = int(row['pos']+1) + rec.ref = str(row['ref']) if pd.notna(row['ref']) else "N" + rec.alts = (str(row['alt']),) if pd.notna(row['alt']) else ("",) + rec.id = f"{id}_{counter[id]}" + + rec.info['SVTYPE'] = row['alttype'] + if row['alttype'] != 'BND': + rec.info['SVLEN'] = row['pos'] - row['pos2'] + + # -- HANDLE INFO FIELDS -- + if isinstance(row['info'], dict): + for k, v in row['info'].items(): + + if k not in all_info_keys: + continue + + # Pysam is strict about types. + # The input 'v' is a tuple like ('TGG',) or (3,) + + # Unpack single-element tuples for cleaner VCF output + val_to_set = v + if isinstance(v, tuple) and len(v) == 1: + val_to_set = v[0] + + # Safety: Ensure val_to_set matches the header expectation + # If we defined it as Integer, ensure it's an int + if k in known_integers: + try: + val_to_set = int(val_to_set) + if k == 'END': + val_to_set += 1 + + rec.info[k] = val_to_set + except (ValueError, TypeError): + continue # Skip if bad data (e.g. '.' or None) + elif k in flags: + rec.info[k] = True + + else: + # For string fields, join tuples if there are multiple items + if isinstance(val_to_set, tuple): + val_to_set = ','.join(map(str, val_to_set)) + else: + val_to_set = str(val_to_set) + + rec.info[k] = val_to_set + + for key in fmt_tags: + if key in row['info']: + rec.samples[sample_name][key] = int(row['info'][key]) + + vcf_out.write(rec) + + vcf_out.close() + + +# ============================================================================ +# SECTION 2b: READ-LEVEL TAGS (optional, for IGV review) +# ============================================================================ +# +# The per-target read loop in main() already decides, for every read it sees, +# whether that read supports an edit -- and then throws the decision away, so a +# reviewer only ever sees the aggregated indel_fraction. These helpers keep the +# per-read verdict so it can be written back out as a string BAM tag that IGV +# can colour by (Color alignments by -> tag -> XC). +# +# Two properties of the read loop shape this code: +# +# 1. The loop fetches per target with a +/- target_window pad and +# multiple_iterators=True, so overlapping targets make it visit the *same* +# alignment record more than once. Writing from inside the loop would emit +# that record repeatedly, which IGV renders as inflated depth. So tags are +# only accumulated during the loop; the BAM is written in a second pass +# that visits each record exactly once (see write_tagged_bam). +# +# 2. query_name is not a unique key -- it collides between mates of a pair and +# between the primary and supplementary records of one fragment. The key is +# (query_name, flag, reference_start). + +# Tag precedence, most specific first. When the same record is classified +# differently at two overlapping targets, the lowest-index prefix wins: real edit +# evidence beats a plain reference call, which beats a read a classifier looked at +# but could not place, which beats a read that simply sat in the padding. Matching +# is by prefix and first-match, so the specific Skipped_ entries must precede the +# generic one. +TAG_PRECEDENCE = ( + 'Edited_BND', + 'Edited_Deletion', + 'Edited_Insertion', + 'Edited_Duplication', + 'Edited_Complex', + 'Edited_SoftClip', + 'Unedited_WT', + 'Skipped_Unevaluable', + 'Skipped_NoSpan', + 'Skipped_', +) + +# The tag assumed for any record not present in the tag map. This is the single +# biggest category by far -- at a 1 bp target the +/-150 bp fetch pad means most +# records neither span the target nor carry an event (69% of records at the AAVS1 +# on-target) -- so leaving it implicit rather than storing it cuts the tag map to +# roughly a third of its size on a real panel. It is safe to leave implicit only +# because it is *last* in TAG_PRECEDENCE among the tags a read can also receive +# elsewhere: anything else recorded for the same read outranks it anyway. +DEFAULT_TAG = 'Skipped_NoSpan' + + +def read_tag_rank(tag): + """Precedence rank of a tag string; lower wins. Unknown tags rank last.""" + for i, prefix in enumerate(TAG_PRECEDENCE): + if tag.startswith(prefix): + return i + return len(TAG_PRECEDENCE) + + +def read_tag_key(read): + """Unique key for one alignment record. + + query_name alone is not unique: read1/read2 of a pair share it, as do the + primary and supplementary records of a split read. Including the flag and + the start position makes the key identify exactly one record. + """ + return (read.query_name, read.flag, read.reference_start) + + +def classify_read_tag(vcf_dict, source): + """Map one per-read classification onto an IGV-colourable tag string. + + ``source`` is the branch of the read loop that produced ``vcf_dict``: + 'CIGAR', 'SA', 'SOFTCLIP' or 'REF'. + """ + if vcf_dict is None: + return 'Skipped_Unevaluable' + + alttype = vcf_dict.get('alttype') + + if alttype == 'REF': + return 'Unedited_WT' + + # A breakend is named by its partner contig -- that is what the reviewer is + # looking for (e.g. a junction into the transgene contig). + if alttype == 'BND': + return 'Edited_BND_{}'.format(vcf_dict.get('chrom2') or 'NA') + + # Soft-clip-derived calls are realignments rather than direct observations, + # so they are reported by mechanism and not by an implied exact size. + if source == 'SOFTCLIP': + return 'Edited_SoftClip' + + ref = vcf_dict.get('ref') or '' + alt = vcf_dict.get('alt') or '' + + # Symbolic alleles (, , ) carry no length; fall back to the + # reference span between the two breakpoints. + if alt.startswith('<') or ref.startswith('<'): + try: + size = abs(int(vcf_dict['pos2']) - int(vcf_dict['pos'])) + except (KeyError, TypeError, ValueError): + size = 0 + else: + size = abs(len(ref) - len(alt)) + + if alttype == 'DEL': + return 'Edited_Deletion_{}bp'.format(size) + if alttype == 'INS': + return 'Edited_Insertion_{}bp'.format(size) + if alttype == 'DUP': + return 'Edited_Duplication_{}bp'.format(size) + + return 'Edited_Complex' + + +def record_read_tag(read_tags, read, tag): + """Keep the highest-precedence tag seen for this record across all targets.""" + key = read_tag_key(read) + previous = read_tags.get(key) + if previous is None or read_tag_rank(tag) < read_tag_rank(previous): + read_tags[key] = tag + + +def merge_windows(windows): + """Collapse (chrom, start, end) windows into disjoint, sorted intervals. + + Padded target windows overlap each other; fetching them as-is would visit + some records twice. Merging first keeps the second pass close to a single + linear sweep and makes the output naturally near-coordinate-order. + """ + by_chrom = defaultdict(list) + for chrom, start, end in windows: + by_chrom[chrom].append((max(0, int(start)), int(end))) + + merged = [] + for chrom in sorted(by_chrom): + current_start, current_end = None, None + for start, end in sorted(by_chrom[chrom]): + if current_end is not None and start <= current_end: + current_end = max(current_end, end) + continue + if current_end is not None: + merged.append((chrom, current_start, current_end)) + current_start, current_end = start, end + if current_end is not None: + merged.append((chrom, current_start, current_end)) + + return merged + + +def write_tagged_bam(source_bamfile, out_path, windows, read_tags, tag_name, + probabilities=None, prob_tag='XP', verbose=False): + """Second pass: emit a sorted, indexed BAM of the target windows, tagged. + + Restricted to the target windows on purpose. Tagging whole CRAMs would be + enormous, and the windows are all IGV needs to show the reviewer why a site + was called. Returns the number of records written. + """ + merged = merge_windows(windows) + if not merged: + print("No target windows were processed; not writing a tagged BAM.", file=sys.stderr) + return 0 + + if out_path.endswith('.bam'): + final_path = out_path + else: + final_path = out_path + '.bam' + unsorted_path = final_path[:-4] + '.unsorted.bam' + + written = 0 + # Merged windows are disjoint and ascending, so the only record that can be + # fetched twice is one that runs past the end of a window into the next. + # Carrying just those keys (key -> reference_end) is enough to write each + # record exactly once, and costs far less than remembering every key written. + carry = {} + current_chrom = None + + out_bam = pysam.AlignmentFile(unsorted_path, 'wb', template=source_bamfile) + try: + for chrom, start, end in merged: + if chrom != current_chrom: + carry.clear() + current_chrom = chrom + elif carry: + # anything ending at or before this window cannot re-appear + carry = {k: e for k, e in carry.items() if e > start} + + for read in source_bamfile.fetch(chrom, start, end, multiple_iterators=True): + key = read_tag_key(read) + if key in carry: + # already emitted from the previous window -- writing it again + # would show up in IGV as doubled depth + continue + + read.set_tag(tag_name, read_tags.get(key, DEFAULT_TAG), value_type='Z') + if probabilities is not None and key in probabilities: + read.set_tag(prob_tag, float(probabilities[key]), value_type='f') + out_bam.write(read) + written += 1 + + read_end = read.reference_end + if read_end is not None and read_end > end: + carry[key] = read_end + finally: + out_bam.close() + + # Windows are visited in target order, which is not guaranteed to be + # coordinate order, and IGV needs coordinate-sorted + indexed input. + pysam.sort('-o', final_path, unsorted_path) + pysam.index(final_path) + os.remove(unsorted_path) + + if verbose: + print(f"Wrote {written} tagged reads over {len(merged)} merged windows to {final_path}", + file=sys.stderr) + + return written + + +# ============================================================================ +# SECTION 3: MAIN FUNCTION +# ============================================================================ + +def main(): + + parser = argparse.ArgumentParser(description='Extract variant reads and predict CRISPR reads') + + # BAM files, target VCF, and reference FASTA. + parser.add_argument('--edited-bam',type=str,required=True,help='Edited/experimental BAM/CRAM file') + parser.add_argument('--control-bam',type=str,required=True,help='Control BAM/CRAM file') + parser.add_argument('--target-file',type=str,required=True,help='Target sites coordinate file (CSV/BED format) - used for both bed coordinates and CRISPR targets') + parser.add_argument('-f','--fasta',type=str,default="/storage2/fs1/dspencer/Active/clinseq/projects/scge/data/refdata/singh_v4.3.6/hg38_PLVM_CD19_CARv4_cd34.fa",help='Reference fasta file') + + # Search and filtering parameters + parser.add_argument('-w','--target-window',type=int,default=150,help='Window size') + # ONE distance rule, and it lives here. Cas9 cuts ~3 bp from the PAM, so an indel more than + # 10 bp away is not the edit -- review_filter.py used to re-apply a 10 bp cut downstream on a + # DIFFERENT quantity (derived from indel_info, measured from the anchor base only, always + # larger), which meant two thresholds named the same thing disagreeing on 162 of 1,498 rows. + # The value filtered here is `Distance` = min(|pos - PAM|, |pos + len(ref) - 1 - PAM|), the + # true minimum, and it is what min_cut_distance reports. Recalibrated on the 32-sample CAR-T + # cohort against the curated review label: 6, 8, 10, 12 and 15 all hold 64/64 confirmed edits + # at precision 0.877; only 25 degrades it (0.831). 10 sits inside that plateau and matches the + # cut biology, so it is the default rather than a filter-side afterthought. + parser.add_argument('-d','--max-mutation-distance',type=int,default=10,help='Maximum distance (bp) from a PAM position for an indel to be called. This is the pipeline\'s only cut-distance threshold.') + parser.add_argument('-s','--mutation-search-window',type=int,default=20000,help='Search window') + parser.add_argument('-l','--min-softclip-length',type=int,default=8,help='Minimum softclip length') + parser.add_argument('-b','--min-bnd-mapqual',type=int,default=40,help='Minimum BND mapping quality') + parser.add_argument('-m','--min-coverage',type=int,default=1,help='Minimum reads') + parser.add_argument('-x','--max-in-control',type=int,default=0,help='Maximum supporting reads in control/unedited sample to report an indel/bnd event.') + parser.add_argument('-q','--min-mapqual',type=int,default=20,help='Minimum mapping quality') + parser.add_argument('-n','--max-read-mismatches',type=int,default=4,help='Maximum number of mismatches') + + # Optionally search at targets from one chromosome + parser.add_argument('-c','--chromosome',type=str,default=None,help='Chromosome to process') + # add option to accept a list of regions to process (chr:pos1-pos2,chr:pos1:pos2, etc) + parser.add_argument('-r','--regions',type=str,default=None,help='Regions to process (chr:pos1-pos2,chr:pos1:pos2, etc)') + + # Outputs + parser.add_argument('-o','--outfile',type=str,help='Output file (optional)') + parser.add_argument('-u','--unevaluable-reads-logfile',type=str,help='File with information on reads that were not evaluable.') + parser.add_argument('-V','--vcf-out',type=str,help="VCF output file with all passing events.") + parser.add_argument('--tagged-bam-out',type=str,default=None, + help=('Write a coordinate-sorted, indexed BAM in which every read carries a string tag ' + 'recording how this script classified it (Edited_Deletion_5bp, Unedited_WT, ...), ' + 'for review in IGV via Color alignments by -> tag. Off by default. Output is ' + 'restricted to the target windows only (target +/- --target-window), not the whole ' + 'genome: expect roughly (number of targets) x (2 x window + read length) x depth ' + 'bytes, i.e. a few hundred MB for a typical deep ECS panel, but it scales with your ' + 'target count -- check the size before enabling it across a cohort.')) + parser.add_argument('--tagged-bam-tag',type=str,default='XC', + help='Two-character tag name to write the per-read classification into (default: XC)') + parser.add_argument('-v','--verbose',action='store_true',help='Print verbose output') + # add vv option for debugging + parser.add_argument('-vv','--debug',action='store_true',help='Print debug output') + + # CRISPR prediction arguments + parser.add_argument('--crispr-model',type=str,default='models/site14_site5_combined_model.pkl',help='Trained CRISPR ML model file (.pkl) for read prediction (default: site14_site5_combined_model.pkl)') + parser.add_argument('--crispr-threshold',type=float,default=0.70,help='Probability threshold for CRISPR prediction (default: 0.70)') + parser.add_argument('--enable-crispr-prediction',action='store_true',help='Enable CRISPR read prediction (uses default model and target-file as targets)') + parser.add_argument('--targets-csv',type=str,help='Alternative target sites CSV file for feature extraction (optional - uses target-file if not specified)') + parser.add_argument('--filter-off-target-fp', action='store_true', help='Filter off-target sites that are likely false positives (indel reads > 0 but no predicted CRISPR reads).') + parser.add_argument('--fp-log', type=str, help='Log file for filtered false positive off-target sites.') + + args = parser.parse_args() + + if args.verbose: + print("Processing input file", file=sys.stderr) + + # ======================================================================== + # STEP 1: Process input BED file and create genomic intervals + # ======================================================================== + + # target regions, in VCF format. + vcf_data = [] + vcf_out_df = pd.DataFrame() + + try: + # Open VCF file with pysam + vcf_in = pysam.VariantFile(args.target_file) + + for rec in vcf_in: + start = rec.pos - 1 + end = rec.pos + info_dict = dict(rec.info) + is_target = 1 if info_dict.get('TARGET', False) else 0 + + vcf_data.append({ + 'Chromosome': rec.chrom, + 'Start': start, + 'End': end, + 'Pos': rec.pos, # Keep 1-based POS for reference/output + 'Info': info_dict, + 'Ontarget': is_target + }) + + except Exception as e: + print(f"Error reading VCF input: {e}", file=sys.stderr) + + # Create DataFrame from list of dicts + bedDf = pd.DataFrame(vcf_data) + + # Generate coordinate lookup index: + target_index = GenomicDistanceIndex(bedDf) + + # Check for empty input data + if len(bedDf) == 0: + print("Warning: Input target file has no data rows. Writing empty output.", file=sys.stderr) + # Write empty output file with header only + output_columns = ['Cluster', 'Chromosome', 'Start', 'End', 'Ontarget', 'Gene', 'indel_type', + 'indel_fraction', 'indel_allele_fraction', 'indel_size', 'indel_bases', + 'num_edited', 'num_control', 'total_edited', 'total_control', 'significance', + 'prediction', 'probability', 'model_info'] + empty_df = pd.DataFrame(columns=output_columns) + if args.outfile: + empty_df.to_csv(args.outfile, sep='\t', index=False) + else: + empty_df.to_csv(sys.stdout, sep='\t', index=False) + sys.exit(0) + + # Create PyRanges object and cluster intervals + bedPr = pr.PyRanges(bedDf[['Chromosome', 'Start', 'End', 'Pos', 'Info', 'Ontarget']]) + bedPr = bedPr.cluster(slack=args.target_window) + mergedBedPr = bedPr.merge(by='Cluster', strand=False, slack=args.target_window) + + # Join aggregated data back to the merged intervals + mergedBedDf = mergedBedPr.df.join( + bedPr.df.groupby('Cluster')['Pos'].agg(list).reset_index().set_index('Cluster'), + on='Cluster', how='left' + ) + mergedBedDf = mergedBedDf.join( + bedPr.df.groupby('Cluster')['Info'].agg(list).reset_index().set_index('Cluster'), + on='Cluster', how='left' + ) + mergedBedDf = mergedBedDf.join( + bedPr.df.groupby('Cluster')['Ontarget'].agg('max').reset_index().set_index('Cluster'), + on='Cluster', how='left' + ) + + if args.verbose: + print("Done processing input file", file=sys.stderr) + + # ======================================================================== + # STEP 2: Open BAM files and reference + # ======================================================================== + + edited_bamfile = pysam.AlignmentFile(args.edited_bam,"rc",reference_filename=args.fasta) + control_bamfile = pysam.AlignmentFile(args.control_bam,"rc",reference_filename=args.fasta) + refFasta = pysam.FastaFile(args.fasta) + + # make outfile to print to, or use stdout + if args.outfile: + fp = open(args.outfile, 'w') + else: + fp = sys.stdout + + # ======================================================================== + # STEP 3: Load CRISPR prediction model and targets (if enabled) + # ======================================================================== + + crispr_model = None + if args.enable_crispr_prediction: + try: + print(f"Loading CRISPR ML model: {args.crispr_model}", file=sys.stderr) + crispr_model = joblib.load(args.crispr_model) + print(f"CRISPR model loaded successfully", file=sys.stderr) + print(f"CRISPR prediction enabled with threshold {args.crispr_threshold}", file=sys.stderr) + from features import check_sklearn_version + check_sklearn_version(crispr_model, name=os.path.basename(args.crispr_model)) + except Exception as e: + print(f"Error loading CRISPR model '{args.crispr_model}': {e}", file=sys.stderr) + print(f"Make sure the model file exists in the current directory or provide full path", file=sys.stderr) + sys.exit(1) + + # ======================================================================== + # STEP 4: Create output header + # ======================================================================== + + header_columns = ['chrom', 'start', 'end', 'pam_positions', 'total_reads', 'indel_reads', 'indel_fraction', + 'control_reads', 'control_indel_reads', 'control_indel_fraction', 'indel_count', 'indel_info', + 'bnd_count', 'bnd_info', 'control_bnd_reads', 'n_control_filtered', + 'min_cut_distance', 'target_info', 'is_target'] + if args.enable_crispr_prediction: + header_columns.extend(['crispr_predicted_reads', 'crispr_prediction_fraction', 'crispr_prediction_probability']) + + print("\t".join(header_columns), file=fp, flush=True) + + fp_log = None + if args.fp_log: + fp_log = open(args.fp_log, 'w') + fp_log.write("\t".join(header_columns) + "\n") + + unevaluable_read_log = None + if args.unevaluable_reads_logfile: + unevaluable_read_log = open(args.unevaluable_reads_logfile, 'w') + + # ======================================================================== + # STEP 5: Process each genomic interval + # ======================================================================== + + region_list = [parse_region_string(region) for region in args.regions.split(',')] if args.regions else None + + total_intervals = len(mergedBedDf) + + # This stores all indel records to print as a VCF at the end. + all_indel_records = [] + + # Optional read-level tagging (see SECTION 2b). Tags are only accumulated + # here; the BAM is written afterwards in a second pass, because this loop + # visits overlapping targets and would otherwise emit duplicate records. + read_tags = {} if args.tagged_bam_out else None + read_probs = {} if (args.tagged_bam_out and args.enable_crispr_prediction) else None + tagged_windows = [] + + # Use enumerate(..., start=1) to keep track of the current loop index + for i, (_, row) in enumerate(mergedBedDf.iterrows(), 1): + + # List of indels for this interval + indel_vcf_records = [] + + # Print an update every 10 intervals, or on the very last interval + if i % 10 == 0 or i == total_intervals: + print(f"Progress: [{i}/{total_intervals}] intervals processed ({(i/total_intervals)*100:.1f}%)", file=sys.stderr) + + # Process single chromosome, if specified + if args.chromosome is not None: + # skip row if Chromosome != args.chromosome + if row['Chromosome'] != args.chromosome: + continue + + # Process specific regions, if specified + if region_list: + overlaps = False + for r_chrom, r_start, r_end in region_list: + # Standard overlap logic: StartA < EndB AND EndA > StartB + if row['Chromosome'] == r_chrom and row['Start'] <= r_end and row['End'] >= r_start: + overlaps = True + break # Found an overlap, no need to check other regions + + # If the current row doesn't overlap any region in region_list, skip it + if not overlaps: + continue + + if args.verbose: + print(f"Processing interval {row['Chromosome']}:{row['Start']}-{row['End']}", file=sys.stderr) + + # Set up edit df + readaln = pd.DataFrame(columns=['read','chrom','pos','distance','chrom2','pos2','distance2','strands','ref','alt','alttype']) + + if args.verbose: + print(f"\tGetting reads that align within window of {row['Chromosome']}:{row['Start']}-{row['End']}", file=sys.stderr) + + window_start = max(0, row['Start'] - args.target_window) + window_end = row['End'] + args.target_window + if read_tags is not None: + tagged_windows.append((row['Chromosome'], window_start, window_end)) + + # get reads that align within a defined region containing the merged target interval + for read in edited_bamfile.fetch(row['Chromosome'], window_start, window_end, multiple_iterators = True): + + # skip if not primary alignment or a duplicate or poor mapping quality. + # Same predicates and same short-circuit order as a single boolean + # chain; split out so a skipped read can say which filter caught it. + skip_reason = None + if read.is_mapped is False: + skip_reason = 'Skipped_Unmapped' + elif read.is_duplicate is True: + skip_reason = 'Skipped_Duplicate' + elif read.is_secondary is True: + skip_reason = 'Skipped_Secondary' + elif read.is_supplementary is True: + skip_reason = 'Skipped_Supplementary' + elif read.mapping_quality < args.min_mapqual: + skip_reason = 'Skipped_LowMapQ' + elif count_mismatches_fast(read) > args.max_read_mismatches: + skip_reason = 'Skipped_Mismatches' + + if skip_reason is not None: + # tag it rather than dropping it, so a reviewer sees that the + # read was excluded on purpose instead of just missing + if read_tags is not None: + record_read_tag(read_tags, read, skip_reason) + continue + + # Determine whether the read pair has the proper orientation, that is: ---> <--- + proper_paired_read = (read.is_paired and + read.is_forward != read.is_reverse and + ((read.is_forward and read.reference_start <= read.next_reference_start) or + (read.is_reverse and read.reference_start >= read.next_reference_start))) + + cigar = read.cigartuples # get cigar info + mate_cigar = parse_cigar_string(read.get_tag('MC')) if read.has_tag('MC') else None # get mate_cigar + + read_strand = "+" + if read.is_reverse is True: + read_strand = "-" + + # dict to store mutation info in VCF record format + vcf_dict = None + # which classifier produced vcf_dict; only used for read-level tags + vcf_source = None + + # if cigar has any D/I operations + if any(op in (1, 2) for op, _ in cigar) and proper_paired_read: + vcf_source = 'CIGAR' + + if args.verbose: + print(f"\tAnalyzing cigars in {read.query_name} from {row['Chromosome']}:{row['Start']-args.target_window}-{row['End']+args.target_window}", file=sys.stderr) + + vcf_dict = get_cigar_indel_vcf(read, refFasta, row['Pos'], target_index) + + # if no indel is found or its too far away from the closest PAM position + if (vcf_dict is None or + vcf_dict['distance'] > args.max_mutation_distance and vcf_dict['distance2'] > args.max_mutation_distance): + # print abbreviated read info (name, cigar, mapping info, sequence) to unevaluable read log + if unevaluable_read_log: + print(f"{str(read)}\t{vcf_dict}", file=unevaluable_read_log) + + if read_tags is not None: + record_read_tag(read_tags, read, 'Skipped_Unevaluable') + + continue + + # read has supplementary alignments + elif read.has_tag('SA'): + vcf_source = 'SA' + + if args.verbose: + print(f"\tAnalyzing SA in {read.query_name}, {read.get_tag('SA') if read.has_tag('SA') else 'None'} from {row['Chromosome']}:{row['Start']-args.target_window}-{row['End']+args.target_window}", file=sys.stderr) + + vcf_dict = get_sa_indel_vcf(read, refFasta, row['Pos'], target_index) + + # skip if indel is too far away from the PAM position + if (vcf_dict is None or + (vcf_dict['alttype'] in ['DEL','DUP','INS'] and + vcf_dict['distance'] > args.max_mutation_distance and vcf_dict['distance2'] > args.max_mutation_distance)): + + # print abbreviated read info (name, cigar, mapping info, sequence) to unevaluable read log + if unevaluable_read_log: + print(f"{str(read)}\t{vcf_dict}", file=unevaluable_read_log) + + if read_tags is not None: + record_read_tag(read_tags, read, 'Skipped_Unevaluable') + + continue + + # if SA is an indel then it should be bounded by the read pair ends. If not then continue. + if (vcf_dict['alttype'] in ['DEL','DUP','INS'] and proper_paired_read and + (min([vcf_dict['pos'],vcf_dict['pos2']]) < min([read.reference_start,read.next_reference_start]) or + max([vcf_dict['pos'],vcf_dict['pos2']]) > min([read.reference_start,read.next_reference_start])+read.template_length)): + + # print abbreviated read info (name, cigar, mapping info, sequence) to unevaluable read log + if unevaluable_read_log: + print(f"{str(read)}\t{vcf_dict}", file=unevaluable_read_log) + + if read_tags is not None: + record_read_tag(read_tags, read, 'Skipped_Unevaluable') + + continue + + # if SA is a BND, check to see if the other end is in the target list + if (vcf_dict['alttype']=='BND' and + (read.mapping_quality < args.min_bnd_mapqual or vcf_dict['info']['SAMAPQ'] < args.min_bnd_mapqual and + vcf_dict['distance'] > args.max_mutation_distance and vcf_dict['distance2'] > args.max_mutation_distance)): + + # print abbreviated read info (name, cigar, mapping info, sequence) to unevaluable read log + if unevaluable_read_log: + print(f"{str(read)}\t{vcf_dict}", file=unevaluable_read_log) + + if read_tags is not None: + record_read_tag(read_tags, read, 'Skipped_Unevaluable') + + continue + + # read has softclips + elif cigar[0][0] >= 4 and cigar[0][1] >= args.min_softclip_length or \ + cigar[-1][0] >= 4 and cigar[-1][1] >= args.min_softclip_length: + vcf_source = 'SOFTCLIP' + + if args.verbose: + print(f"\tAnalyzing softclips in {read.query_name}, {read.cigarstring}, from {row['Chromosome']}:{row['Start']-args.target_window}-{row['End']+args.target_window}", file=sys.stderr) + + vcf_dict = get_softclip_indel_vcf(read, refFasta, row['Pos'], args.mutation_search_window, args.min_softclip_length) + + if (vcf_dict is None or + (vcf_dict['distance'] > args.max_mutation_distance and vcf_dict['distance2'] > args.max_mutation_distance)): + + # print abbreviated read info (name, cigar, mapping info, sequence) to unevaluable read log + if unevaluable_read_log: + print(f"{str(read)}\t{vcf_dict}", file=unevaluable_read_log) + + if read_tags is not None: + record_read_tag(read_tags, read, 'Skipped_Unevaluable') + + continue + + # read spans start and end and has no softclips + elif read.reference_start < row['End'] and read.reference_end > row['Start'] and cigar[0][0] == 0 and cigar[-1][0] == 0: + vcf_source = 'REF' + + if args.verbose: + print(f"\tThis read is reference {read.query_name}, {read.cigarstring}, from {row['Chromosome']}:{row['Start']-args.target_window}-{row['End']+args.target_window}", file=sys.stderr) + + vcf_dict = { + 'read': read.query_name, + 'chrom': row['Chromosome'], + 'pos': row['Start'], + 'distance': '.', + 'chrom2': row['Chromosome'], + 'pos2': row['End'], + 'distance2': '.', + 'ref': '.', + 'alt': '.', + 'strands': '.', + 'info': '.', + 'alttype': 'REF' + } + + # If read doesnt meet any of the criteria then skip it. + else: + # Sits in the padded window but carries no event and does not span + # the target, so it is evidence for neither call. This is the bulk + # of the records in a window, and it is exactly DEFAULT_TAG -- so + # it is deliberately NOT recorded, which keeps the tag map small + # enough to survive a full panel. See DEFAULT_TAG. + continue + + # Record the per-read verdict *before* the alleles below are truncated + # for display, since the truncation overwrites alt with a length label + # and would make the indel size in the tag meaningless. + if read_tags is not None: + record_read_tag(read_tags, read, classify_read_tag(vcf_dict, vcf_source)) + + # truncate ref or alt allele for readbility in Excel, etc. + if len(vcf_dict['ref']) > 20: + vcf_dict['alt'] = f"DEL{len(vcf_dict['ref'])-1}" + vcf_dict['ref'] = vcf_dict['ref'][0] + + if len(vcf_dict['alt']) > 20: + vcf_dict['alt'] = f"INS{len(vcf_dict['alt'])-1}" + + # Add indel info to dataframe + indel_vcf_records.append(vcf_dict) + + # + # End loop over reads for this region + # + + + # make df of all indel records + readaln = pd.DataFrame(indel_vcf_records) + + if args.verbose: + print("\tSorting indels", file=sys.stderr) + + if len(readaln) > 0: + + indelcounts = readaln.sort_values(by=['read','chrom','pos','distance','chrom2','pos2','distance2','strands','ref','alt','alttype'],key=lambda col: col != '',ascending=False).groupby('read').first().reset_index() + indelcounts = indelcounts.groupby(['chrom','pos','distance','chrom2','pos2','distance2','strands','ref','alt','alttype'],dropna=False).size().reset_index(name='counts') + indelcounts = indelcounts.merge(readaln.drop(columns=['read']).groupby(['chrom','pos','distance','chrom2','pos2','distance2','strands','ref','alt','alttype'],dropna=False).agg(list).reset_index(),on=['chrom','pos','distance','chrom2','pos2','distance2','strands','ref','alt','alttype'],how='left') + + # Recast as int type, allowing for NA values + indelcounts['pos'] = indelcounts['pos'].astype(pd.Int64Dtype()) + indelcounts['pos2'] = indelcounts['pos2'].astype(pd.Int64Dtype()) + + if args.verbose: + print("\tGetting control counts", file=sys.stderr) + + # Add pam positions to the df + if row['Pos'] is not pd.NA: + indelcounts['Positions'] = [row['Pos']] * len(indelcounts) + indelcounts['Distance'] = indelcounts.apply( + lambda r: min( + [abs(r['pos'] - int(x)) for x in r['Positions']] + + [abs(r['pos'] + len(r['ref']) - 1 - int(x)) for x in r['Positions']] + ) if pd.notna(r['pos']) and r['Positions'] else pd.NA, + axis=1 + ) + + else: + indelcounts['Positions'] = pd.NA + indelcounts['Distance'] = pd.NA + + indelcounts = add_normal_counts(indelcounts, [ x for x in control_bamfile.fetch(contig=row['Chromosome'], start=row['Start']-args.target_window, end=row['End']+args.target_window) ], refFasta, debug=args.debug) + + else: # in cases there are no evaluable reads + + indelcounts = pd.DataFrame(columns=['chrom','pos','distance','chrom2','pos2','distance2','ref','alt','alttype','info','counts','control_alt_counts','control_total_counts','Positions','Distance']) + indelcounts['chrom'] = row['Chromosome'] + indelcounts['pos'] = row['Start'] + indelcounts['distance'] = '.' + indelcounts['chrom2'] = row['Chromosome'] + indelcounts['pos2'] = row['End'] + indelcounts['distance2'] = '.' + indelcounts['ref'] = '.' + indelcounts['alt'] = '.' + indelcounts['alttype'] = 'REF' + indelcounts['info'] = row['Info'] + indelcounts['counts'] = 0 + indelcounts['control_alt_counts'] = 0 + indelcounts['control_total_counts'] = 0 + indelcounts['Positions'] = pd.NA + indelcounts['Distance'] = pd.NA + + # Apply filters. These are independent row masks, so the order does not change which + # events survive -- but max_in_control is applied last on purpose, see below. + indelcounts = indelcounts[(indelcounts['counts'] >= args.min_coverage) | (indelcounts['ref']=='.')] + indelcounts = indelcounts[(indelcounts['Distance'] <= args.max_mutation_distance) | (indelcounts['ref']=='.')] + indelcounts = indelcounts[~indelcounts['alt'].str.contains('N')] + + # Summarise control support BEFORE max_in_control removes the very events that carry it. + # That filter exists to drop control-supported events from calling, but the reported + # control columns must still describe what the control actually held -- summing after it + # writes control_indel_reads = 0 for every site at the default -x 0, which silently + # disables any downstream germline filtering that relies on the column. + control_alt_observed = int(indelcounts['control_alt_counts'].sum()) if len(indelcounts) > 0 else 0 + control_tot_observed = int(indelcounts['control_total_counts'].mean()) if len(indelcounts) > 0 else 0 + + # Same summation, restricted to breakends. control_alt_observed above spans every event type + # -- indels, BNDs and REF placeholder rows -- because the indel/BND split does not happen + # until ~35 lines below, so control_indel_reads has always silently included breakend support. + # Reported separately here so the matched-control rule can be applied to breakends, which it + # could not be before: there was no site-level control statistic for them at all. + # The mask must stay identical to the one used for `bnds` below or the two will disagree. + control_bnd_observed = ( + int(indelcounts.loc[(indelcounts['alttype'] == 'BND') & (indelcounts['ref'] != '.'), + 'control_alt_counts'].sum()) + if len(indelcounts) > 0 else 0 + ) + + # How many real events this filter is about to discard, and the cut distance the caller + # actually filtered on. Neither was recoverable downstream before. + # + # -x/--max-in-control removes control-supported events entirely, so a site reports + # indel_count = 5 whether one event was suppressed or fifty. Measured on a 92-site KLF12 + # subset at the default -x 0: 81 events suppressed across 42 sites, indel_count 170 -> 90 + # and indel_reads 2,966 -> 412. That is the caller doing most of the germline removal before + # review_filter's rule 1 ever runs, with no record that it happened. Counting it here does + # not change the filter -- it just stops the evidence disappearing silently. + # + # min_cut_distance is the value in `Distance`, which is what line ~2229 filters on: + # min over |pos - PAM| AND |pos + len(ref) - 1 - PAM|. The per-event `distance` reported in + # indel_info is a different, always-larger quantity measured from the anchor base only, so + # downstream cannot reproduce the caller's own -d decision from the reported field -- 32 + # cohort rows report cut_dist_min > 25 under a nominal 25 bp cap for exactly this reason. + _real = indelcounts['ref'] != '.' + n_control_filtered = int((_real & (indelcounts['control_alt_counts'] > args.max_in_control)).sum()) + _dist = pd.to_numeric(indelcounts.loc[_real, 'Distance'], errors='coerce').dropna() + min_cut_distance = int(_dist.min()) if len(_dist) else -1 + + indelcounts = indelcounts[(indelcounts['control_alt_counts'] <= args.max_in_control) | (indelcounts['ref']=='.')] + + # Process indel results + total_reads, indel_reads, control_total_reads, control_indel_reads = 0, 0, 0, 0 + indel_fraction, control_indel_fraction = 0, 0 + control_bnd_reads = 0 + # NOTE: n_control_filtered and min_cut_distance are computed above, before the -x filter, + # and must NOT be re-initialised here -- doing so silently blanked both columns. + indel_keys, bnd_keys = '.', '.' + bnds = [] + + total_reads = sum(indelcounts['counts']) if len(indelcounts) > 0 else 0 + indel_reads = sum(indelcounts[indelcounts['alttype']!='REF']['counts']) if len(indelcounts) > 0 else 0 + control_indel_reads = control_alt_observed + control_total_reads = control_tot_observed + control_bnd_reads = control_bnd_observed + + # combine info from multiple reads for this position + indelcounts['info'] = indelcounts['info'].apply(merge_dicts_to_tuples) + info_to_add = merge_dicts_to_tuples(row['Info']) + info_to_add['DP'] = total_reads + info_to_add['CDP'] = control_total_reads + + indelcounts['info'] = indelcounts.apply( + lambda row: { + **(row['info'] if isinstance(row['info'], dict) else {}), + **info_to_add, + 'AD': row['counts'], + 'CAD': row['control_alt_counts'] + }, + axis=1 + ) + + if not indelcounts.empty: + all_indel_records.append(indelcounts) + + # Separate BNDs and indels + bnds = indelcounts[(indelcounts['alttype']=='BND') & (indelcounts['ref']!='.')].copy() + indels = indelcounts[(indelcounts['alttype']!='BND') & (indelcounts['ref']!='.')].copy() + + if len(indels) > 0: + indels['Key'] = indels.apply(lambda r: f"{r['chrom']}|{r['pos']+1}|{r['chrom2']}|{r['pos2']+1}|{r['strands']}|{r['ref']}|{r['alt']}|{r['distance']}|{r['distance2']}|{r['counts']}|{r['control_alt_counts']}", axis=1) + + if len(bnds) > 0: + bnds['Key'] = bnds.apply(lambda r: f"{r['chrom']}|{r['pos']+1}|{r['chrom2']}|{r['pos2']+1}|{r['strands']}|{r['ref']}|{r['alt']}|{r['distance']}|{r['distance2']}|{r['counts']}|{r['control_alt_counts']}", axis=1) + + # Calculate fractions and prepare output + indel_fraction = round(indel_reads/total_reads,4) if total_reads > 0 else 0 + control_indel_fraction = round(control_indel_reads/control_total_reads,4) if control_total_reads > 0 else 0 + indel_keys = ';'.join(indels['Key'].tolist()) if len(indels) > 0 else '.' + bnd_keys = ';'.join(bnds['Key'].tolist()) if len(bnds) > 0 else '.' + ontarget = row['Ontarget'] + positions = row['Pos'] + offtargetsites = make_info_string(row['Info']) if row['Info'] else '.' + + # CRISPR PREDICTION (if enabled) + crispr_predicted_reads = 0 + crispr_prediction_fraction = 0.0 + crispr_prediction_probability = 0.0 + if args.enable_crispr_prediction and crispr_model: + if args.verbose: + print(f" Predicting CRISPR reads for {row['Chromosome']}:{row['Start']}-{row['End']} (total_reads: {total_reads})", file=sys.stderr) + + crispr_predicted_reads, crispr_prediction_probability = predict_reads_at_position( + edited_bamfile, row['Chromosome'], row['Start'], row['End'], positions, + crispr_model, refFasta, is_on_target=ontarget, control_bam=control_bamfile, threshold=args.crispr_threshold, + read_probs=read_probs + ) + crispr_prediction_fraction = round(crispr_predicted_reads/total_reads, 4) if total_reads > 0 else 0.0 + + if args.verbose: + print(f" Predicted {crispr_predicted_reads}/{total_reads} reads as CRISPR-related (≥{args.crispr_threshold})", file=sys.stderr) + print(f" Average prediction probability: {crispr_prediction_probability:.1f}%", file=sys.stderr) + + # Filter off-target false positives if enabled + if args.filter_off_target_fp: + if ontarget == 0 and indel_reads > 0 and crispr_predicted_reads == 0: + if args.verbose: + print(f" Filtering FP off-target site {row['Chromosome']}:{row['Start']}-{row['End']} (indel_reads: {indel_reads}, predicted_reads: {crispr_predicted_reads})", file=sys.stderr) + + if fp_log: + log_fields = [ + row['Chromosome'], row['Start'], row['End'], + ';'.join([str(x) for x in row['Pos']]), total_reads, indel_reads, indel_fraction, + control_total_reads, control_indel_reads, control_indel_fraction, + len(indels), indel_keys, len(bnds), bnd_keys, control_bnd_reads, + n_control_filtered, min_cut_distance, offtargetsites, ontarget + ] + if args.enable_crispr_prediction: + log_fields.extend([crispr_predicted_reads, crispr_prediction_fraction, round(crispr_prediction_probability, 1)]) + fp_log.write("\t".join([str(field) for field in log_fields]) + "\n") + continue + + # Output results + output_fields = [ + row['Chromosome'], row['Start'], row['End'], + ';'.join([str(x) for x in row['Pos']]), total_reads, indel_reads, indel_fraction, + control_total_reads, control_indel_reads, control_indel_fraction, + len(indels), indel_keys, len(bnds), bnd_keys, control_bnd_reads, + n_control_filtered, min_cut_distance, offtargetsites, ontarget + ] + if args.enable_crispr_prediction: + output_fields.extend([crispr_predicted_reads, crispr_prediction_fraction, round(crispr_prediction_probability, 1)]) + + print("\t".join([str(field) for field in output_fields]), file=fp, flush=True) + + # Second pass: write the read-level tagged BAM, if requested. This has to be + # a separate sweep -- the loop above revisits the same records at overlapping + # targets, so writing there would emit duplicates and inflate IGV depth. + if read_tags is not None: + write_tagged_bam(edited_bamfile, args.tagged_bam_out, tagged_windows, read_tags, + args.tagged_bam_tag, probabilities=read_probs, verbose=True) + + # Write VCF output if requested. + if args.vcf_out: + vcf_out_df = pd.concat(all_indel_records, axis=0, ignore_index=True) + write_vcf_output(vcf_out_df,args.vcf_out,vcf_header=vcf_in.header,sample_name="EDITED") + + # ======================================================================== + # STEP 6: Cleanup + # ======================================================================== + + vcf_in.close() + edited_bamfile.close() + control_bamfile.close() + refFasta.close() + + fp.close() + if fp_log: + fp_log.close() + + if unevaluable_read_log: + unevaluable_read_log.close() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/bin/generate_cna_baf_plots.R b/bin/generate_cna_baf_plots.R index 4df92cc..4072b50 100755 --- a/bin/generate_cna_baf_plots.R +++ b/bin/generate_cna_baf_plots.R @@ -2,11 +2,70 @@ # generate_cna_baf_plots.R # This script generates copy number and B-allele frequency plots from a BAF bedgraph file and a CN ratio TSV file. -# It creates two PNG files: cna_plot.png and baf_plot.png. +# If inputs are missing, it generates placeholder PNGs to prevent pipeline failures. script_version <- "1.0.0" -# suppress warnings and messages +# Load optparse first to handle arguments before loading heavy libraries +suppressPackageStartupMessages(require(optparse)) + +# --- Argument Parsing Logic --- + +option_list <- list( + make_option(c("-i", "--id"), type="character", default=NULL, + help="Case ID (used for titles and filenames)", metavar="character"), + make_option(c("-b", "--baf"), type="character", default=NULL, + help="Path to BAF bedgraph input file", metavar="file"), + make_option(c("-c", "--cn"), type="character", default=NULL, + help="Path to CN ratio TSV input file", metavar="file"), + make_option(c("-v", "--version"), action="store_true", default=FALSE, + help="Print the script version and exit") +) + +opt_parser <- OptionParser(option_list=option_list) +opt <- parse_args(opt_parser) + +# --- Check for Version Flag --- +if (opt$version) { + cat(paste0(script_version, "\n")) + quit(save="no", status=0) +} + +# Helper function to check validity +inputs_valid <- function(opt) { + if (is.null(opt$id) || is.null(opt$baf) || is.null(opt$cn)) return(FALSE) + if (!file.exists(opt$baf)) return(FALSE) + if (!file.exists(opt$cn)) return(FALSE) + return(TRUE) +} + +# --- Validation & Placeholder Logic --- + +if (!inputs_valid(opt)) { + # Determine a safe ID for filenames/logging (fallback to "placeholder" if ID is missing) + safe_id <- if (!is.null(opt$id)) opt$id else "placeholder" + + # Print warning to stderr + cat(sprintf("[GENERATE_CNA_BAF_PLOTS] Missing BAF/CNV inputs for %s; creating placeholder plots\n", safe_id), file=stderr()) + + # Generate Placeholder CNA Plot + png(paste0(safe_id, ".cna_plot.png"), width=1800, height=900, res=150) + par(mar=c(0,0,0,0)) + plot.new(); text(0.5, 0.5, "CNA plot unavailable", cex=2) + dev.off() + + # Generate Placeholder BAF Plot + png(paste0(safe_id, ".baf_plot.png"), width=1800, height=900, res=150) + par(mar=c(0,0,0,0)) + plot.new(); text(0.5, 0.5, "BAF plot unavailable", cex=2) + dev.off() + + # Exit successfully (0) so pipeline does not crash + quit(save="no", status=0) +} + +# --- Normal Execution (Only loads if inputs are valid) --- + suppressPackageStartupMessages({ require(dplyr) require(ggplot2) @@ -14,81 +73,69 @@ suppressPackageStartupMessages({ require(GenomicRanges) }) -args <- commandArgs(trailingOnly = TRUE) - -if (args[1]=="--version"){ - cat(paste0(script_version,"\n")) - quit(status = 0) -} +# Assign to variables +caseid <- opt$id +baf_bedgraph <- opt$baf +cn_ratio_tsv <- opt$cn -if (length(args) < 3) { - stop("Usage: generate_cna_baf_plots.R ") -} - -caseid <- args[1] -baf_bedgraph <- args[2] -cn_ratio_tsv <- args[3] - -bafs <- read.table(baf_bedgraph,sep="\t",col.names = c("chrom","start","end","value")) %>% - mutate(type=NA,category="baf",csyntax=NA,known_genes=NA,filters=NA) %>% - select(chrom,start,category,type,value,csyntax,known_genes,filters) +# Read BAF bedgraph file +bafs <- read.table(baf_bedgraph, sep="\t", col.names = c("chrom","start","end","value")) %>% + mutate(type=NA, category="baf", csyntax=NA, known_genes=NA, filters=NA) %>% + select(chrom, start, category, type, value, csyntax, known_genes, filters) bafs$filters <- NA bafs$baf <- bafs$value bafs$cnratio <- NA # Read CN ratio TSV file -cn <- read.table(cn_ratio_tsv,skip=3,sep="\t", +cn <- read.table(cn_ratio_tsv, skip=3, sep="\t", col.names = c("chrom","start","end","name","value","improper_pairs")) # make GRanges object for CN ratio -cn_gr <- GRanges(cn$chrom,IRanges(cn$start,cn$end)) +cn_gr <- GRanges(cn$chrom, IRanges(cn$start, cn$end)) cn_gr$score <- cn$value # format cn -cn <- cn %>% mutate(start=round(start + (end-start)/2,0),type=NA,category="cn",csyntax=NA,known_genes=NA,filters=NA) %>% - select(chrom,start,category,type,value,csyntax,known_genes,filters) +cn <- cn %>% mutate(start=round(start + (end-start)/2, 0), type=NA, category="cn", csyntax=NA, known_genes=NA, filters=NA) %>% + select(chrom, start, category, type, value, csyntax, known_genes, filters) cn$filters <- NA cn$baf <- NA cn$cnratio <- cn$value -# For now, we will not perform the centering of the cnratio, as it depends on the SV calls from the JSON report. -# This can be added back later if needed. - -dat <- rbind(cn,bafs) %>% - mutate(chrom=factor(chrom,levels=paste0("chr",c(1:22,"X","Y")),ordered=T),start=as.numeric(start)) %>% - arrange(chrom,start) %>% mutate(value=ifelse(category %in% c("baf","cn"),NA,value)) +dat <- rbind(cn, bafs) %>% + mutate(chrom=factor(chrom, levels=paste0("chr", c(1:22, "X", "Y")), ordered=T), start=as.numeric(start)) %>% + arrange(chrom, start) %>% mutate(value=ifelse(category %in% c("baf", "cn"), NA, value)) dat$index <- 1:nrow(dat) -label_pos <- round(rowMeans(cbind(c(0,dat$index[which(dat$chrom != lag(dat$chrom))]),c(dat$index[which(dat$chrom != lag(dat$chrom))],max(dat$index)))),0) +label_pos <- round(rowMeans(cbind(c(0, dat$index[which(dat$chrom != lag(dat$chrom))]), c(dat$index[which(dat$chrom != lag(dat$chrom))], max(dat$index)))), 0) labelDf <- data.frame(pos=label_pos, - label=as.character(dat[round(rowMeans(cbind(c(0,dat$index[which(dat$chrom != lag(dat$chrom))]),c(dat$index[which(dat$chrom != lag(dat$chrom))],max(dat$index)))),0),"chrom"]), - csyntax=NA,filters=NA) - -p_cn <- ggplot(dat,aes(x=index,y=cnratio)) + - geom_bin2d(bins=1000,na.rm=TRUE) + - geom_vline(xintercept = dat$index[which(dat$chrom != lag(dat$chrom))],linetype=2,col="gray") + - scale_x_continuous(limits=c(1,max(dat$index)),breaks=dat$index[which(dat$chrom != lag(dat$chrom))],labels = NULL,expand = expansion(mult=0.02), - sec.axis = dup_axis(breaks=labelDf$pos,labels = labelDf$label)) + + label=as.character(dat[round(rowMeans(cbind(c(0, dat$index[which(dat$chrom != lag(dat$chrom))]), c(dat$index[which(dat$chrom != lag(dat$chrom))], max(dat$index)))), 0), "chrom"]), + csyntax=NA, filters=NA) + +p_cn <- ggplot(dat, aes(x=index, y=cnratio)) + + geom_bin2d(bins=1000, na.rm=TRUE) + + geom_vline(xintercept = dat$index[which(dat$chrom != lag(dat$chrom))], linetype=2, col="gray") + + scale_x_continuous(limits=c(1, max(dat$index)), breaks=dat$index[which(dat$chrom != lag(dat$chrom))], labels = NULL, expand = expansion(mult=0.02), + sec.axis = dup_axis(breaks=labelDf$pos, labels = labelDf$label)) + scale_y_continuous(name="copy number ratio", - limits=c(min(-2,round(quantile(dat$cnratio,0.05,na.rm = TRUE),0)), - max(2,round(quantile(dat$cnratio,0.95,na.rm = TRUE),0))),expand = expansion(mult=c(0.01,0.02))) + - scale_fill_stepsn(values=c(0,0.0001,1),colors = c(NA,"darkblue","darkblue")) + - ggtitle(paste0("Copy number for ",caseid)) + - theme_classic() + theme(plot.title = element_text(hjust=0.5),legend.position = "none",axis.ticks.x = element_blank(),axis.text.y = element_text(color = "black",size=10),axis.text.x.bottom = element_blank(), - axis.title.x = element_blank(),axis.text.x = element_text(angle=90,color="black"),plot.margin = margin(t=20, l=10)) + coord_cartesian(clip = "off") - -p_baf <- ggplot(dat,aes(x=index,y=baf)) + - geom_bin2d(binwidth=c(2000,0.005),na.rm=TRUE) + - geom_vline(xintercept = dat$index[which(dat$chrom != lag(dat$chrom))],linetype=2,col="gray") + - scale_x_continuous(limits=c(1,max(dat$index)),breaks=dat$index[which(dat$chrom != lag(dat$chrom))],labels = NULL,expand = expansion(mult=0.02), + limits=c(min(-2, round(quantile(dat$cnratio, 0.05, na.rm = TRUE), 0)), + max(2, round(quantile(dat$cnratio, 0.95, na.rm = TRUE), 0))), expand = expansion(mult=c(0.01, 0.02))) + + scale_fill_stepsn(values=c(0, 0.0001, 1), colors = c(NA, "darkblue", "darkblue")) + + ggtitle(paste0("Copy number for ", caseid)) + + theme_classic() + theme(plot.title = element_text(hjust=0.5), legend.position = "none", axis.ticks.x = element_blank(), axis.text.y = element_text(color = "black", size=10), axis.text.x.bottom = element_blank(), + axis.title.x = element_blank(), axis.text.x = element_text(angle=90, color="black"), plot.margin = margin(t=20, l=10)) + coord_cartesian(clip = "off") + +p_baf <- ggplot(dat, aes(x=index, y=baf)) + + geom_bin2d(binwidth=c(2000, 0.005), na.rm=TRUE) + + geom_vline(xintercept = dat$index[which(dat$chrom != lag(dat$chrom))], linetype=2, col="gray") + + scale_x_continuous(limits=c(1, max(dat$index)), breaks=dat$index[which(dat$chrom != lag(dat$chrom))], labels = NULL, expand = expansion(mult=0.02), sec.axis=dup_axis()) + scale_y_continuous(name="B-allele frequency", - limits=c(0,1),expand = expansion(mult=0.01)) + - scale_fill_stepsn(values=c(0,0.0001,1),colors = c(NA,"darkblue","darkblue")) + - ggtitle(paste0("B-allele frequency for ",caseid)) + - theme_classic() + theme(legend.position = "none",axis.ticks.x = element_blank(),axis.text.y = element_text(color = "black",size=10),plot.margin = margin(l=10), - axis.text.x = element_blank(),axis.title.x = element_blank()) + coord_cartesian(clip = "off") + limits=c(0, 1), expand = expansion(mult=0.01)) + + scale_fill_stepsn(values=c(0, 0.0001, 1), colors = c(NA, "darkblue", "darkblue")) + + ggtitle(paste0("B-allele frequency for ", caseid)) + + theme_classic() + theme(legend.position = "none", axis.ticks.x = element_blank(), axis.text.y = element_text(color = "black", size=10), plot.margin = margin(l=10), + axis.text.x = element_blank(), axis.title.x = element_blank()) + coord_cartesian(clip = "off") ggsave(paste0(caseid, ".cna_plot.png"), plot = p_cn, width = 11, height = 4, units = "in", dpi = 300) -ggsave(paste0(caseid, ".baf_plot.png"), plot = p_baf, width = 11, height = 4, units = "in", dpi = 300) \ No newline at end of file +ggsave(paste0(caseid, ".baf_plot.png"), plot = p_baf, width = 11, height = 4, units = "in", dpi = 300) \ No newline at end of file diff --git a/bin/getTransgeneJunctions.py b/bin/getTransgeneJunctions.py index 37748af..bcb9106 100755 --- a/bin/getTransgeneJunctions.py +++ b/bin/getTransgeneJunctions.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import argparse import re @@ -48,6 +48,9 @@ def get_chimeras(bam,contig,exclude=None,minSoftClip=20,minMq=1,maxMismatches=1) df = pd.DataFrame(columns=['Chromosome','Start','End','Var','Strand','Info']) + if not contig in bam.references: + return df + # format of output: # chr pos1 pos2 strand readname # iterate through once and get split reads and first end of discordant reads @@ -91,12 +94,13 @@ def get_chimeras(bam,contig,exclude=None,minSoftClip=20,minMq=1,maxMismatches=1) if read.has_tag('SA'): for sa in read.get_tag('SA').rstrip(';').split(';'): sChr, sPos, sStrand, sCigar, sMq, sNm = sa.split(',') + sPos = int(sPos) if sChr != read.reference_name and int(sMq)>=minMq and int(sNm) <= maxMismatches: readAligned = cigar_to_aligned_positions(read.cigarstring) saAligned = cigar_to_aligned_positions(sCigar) if len(readAligned.intersection(saAligned)) / len(readAligned) < 0.2: if sStrand == '+': - sPos = int(sPos) + len(saAligned) + sPos = sPos + len(saAligned) mateseq = '.' if read.reference_name != read.next_reference_name: @@ -104,7 +108,7 @@ def get_chimeras(bam,contig,exclude=None,minSoftClip=20,minMq=1,maxMismatches=1) mateseq = mate.query_sequence info = ['ID='+read.query_name, 'Type=PR', 'Read1Seq=' + read.query_sequence, 'Read2Seq=' + mateseq] - df = pd.concat([df,pd.DataFrame([{'Chromosome':sChr,'Start':sPos-1,'End':int(sPos),'Var':'INS','Strand':sStrand,'Info':';'.join(info)}])]).reset_index(drop=True) + df = pd.concat([df,pd.DataFrame([{'Chromosome':sChr,'Start':sPos-1,'End':sPos,'Var':'INS','Strand':sStrand,'Info':';'.join(info)}])]).reset_index(drop=True) elif read.is_proper_pair and read.is_reverse and rightSoftClip >= minSoftClip: if read.has_tag('SA'): @@ -130,15 +134,15 @@ def get_chimeras(bam,contig,exclude=None,minSoftClip=20,minMq=1,maxMismatches=1) return(pr.PyRanges(df).sort().df) parser = argparse.ArgumentParser(description='Find split and discordant reads that partially map to a transgene sequence') -parser.add_argument('contig',type=str,help='Contig name of transgene') -parser.add_argument('expbamfile',type=str,help='BAM file') +parser.add_argument('-n', '--name',type=str,help='Name of transgene contig in reference FASTA') parser.add_argument('-r','--reference',type=str,default=None,help='Reference FASTA file') parser.add_argument('-x','--exclude',type=str,default=None,help='Coordinates to exclude from transgene contig') parser.add_argument('-o','--outfile',type=str,default=None,help='Output to file [stdout]') +parser.add_argument('expbamfile',type=str,help='BAM file') args = parser.parse_args() -contig = args.contig +contig = args.name # open bam file(s) expsamfile = pysam.AlignmentFile(args.expbamfile,"rc",reference_filename=args.reference) diff --git a/bin/hotspot_to_table.py b/bin/hotspot_to_table.py new file mode 100755 index 0000000..47b1391 --- /dev/null +++ b/bin/hotspot_to_table.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +""" +hotspot_to_table.py — build a score.py-ready loci table to score WGS CRAMs at the +ECS-defined hotspot panel, and emit the matching ECS truth. + +The ECS `*.offtarget_analysis.tsv` files ARE the hotspot panel: each row carries a +predicted site (chrom,start,end,target_info,is_target) plus the ECS error-corrected +edit fraction (`indel_fraction`) = ground truth VAF at that site. This script: + 1. collapses those TSVs to the unique hotspot panel PER GUIDE, + 2. cross-joins each guide's hotspots with that guide's WGS sample(s), + 3. writes a score.py table whose `sample_name` = the WGS sample (so score.py looks up + the WGS CRAM). `indel_fraction` is forced to 1.0 so score.py's stage-1 gate keeps + every hotspot — the real WGS signal is recomputed from the CRAM, this is a + gate-passer only. +Separately writes the ECS truth (per guide/site VAF) for the training-table and +recall-vs-VAF joins, keyed on (guide, chrom, start). + +Guide<->sample mapping comes from the unified samplesheet (columns: sample,datatype,guide). +ECS table filenames are `.offtarget_analysis.tsv`. +""" +import os, sys, argparse, glob +import pandas as pd + +HOTSPOT_COLS = ["chrom", "start", "end", "is_target", "target_info"] + + +def load_samplesheet(path): + df = pd.read_csv(path) + df.columns = [c.strip().lower() for c in df.columns] + need = {"sample", "datatype", "guide"} + if not need.issubset(df.columns): + sys.exit(f"samplesheet must have columns {need}; got {list(df.columns)}") + df["datatype"] = df["datatype"].str.lower().str.strip() + return df + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--ecs-tables", nargs="+", required=True, + help="ECS .offtarget_analysis.tsv files (the hotspot panel + truth)") + ap.add_argument("--samplesheet", required=True) + ap.add_argument("--edit-threshold", type=float, default=0.0, + help="ECS indel_fraction strictly above this = a true edit (label=1)") + ap.add_argument("--out-table", default="wgs_hotspot_input_table.csv") + ap.add_argument("--out-truth", default="ecs_hotspot_truth.csv") + args = ap.parse_args() + + ss = load_samplesheet(args.samplesheet) + ecs_sample_guide = dict(zip(ss.loc[ss.datatype == "ecs", "sample"], + ss.loc[ss.datatype == "ecs", "guide"])) + wgs_by_guide = (ss[ss.datatype == "wgs"].groupby("guide")["sample"].apply(list).to_dict()) + + tables = [] + for f in args.ecs_tables: + ecs_sample = os.path.basename(f).replace(".offtarget_analysis.tsv", "") + guide = ecs_sample_guide.get(ecs_sample) + if guide is None: + print(f" WARN: {ecs_sample} not in samplesheet as ecs; skipping {f}", flush=True) + continue + t = pd.read_csv(f, sep="\t") + t["guide"] = guide + t["ecs_if"] = pd.to_numeric(t["indel_fraction"], errors="coerce").fillna(0.0) + # Read support, carried through so downstream can separate a real low-VAF edit + # from ECS noise. A VAF alone cannot: at ~5,000x, 3 stray indel reads and a + # genuine 0.5% edit both look "low", but only one has read support behind it. + t["ecs_indel_reads"] = pd.to_numeric(t.get("indel_reads"), errors="coerce").fillna(0) + t["ecs_total_reads"] = pd.to_numeric(t.get("total_reads"), errors="coerce").fillna(0) + tables.append(t) + if not tables: + sys.exit("no ECS tables matched samplesheet ecs samples") + ecs = pd.concat(tables, ignore_index=True) + + # ECS truth per (guide, site): take the strongest ECS evidence across replicates + truth = (ecs.groupby(["guide"] + HOTSPOT_COLS, as_index=False, dropna=False) + .agg(ecs_if=("ecs_if", "max"), + ecs_indel_reads=("ecs_indel_reads", "max"), + ecs_total_reads=("ecs_total_reads", "max"))) + truth["ecs_is_edit"] = (truth["ecs_if"] > args.edit_threshold).astype(int) + truth.to_csv(args.out_truth, index=False) + + # score.py input: unique hotspot panel per guide x that guide's WGS sample(s) + panel = ecs[["guide"] + HOTSPOT_COLS].drop_duplicates() + rows = [] + for _, h in panel.iterrows(): + for w in wgs_by_guide.get(h["guide"], []): + rows.append({"sample_name": w, "chrom": h["chrom"], "start": int(h["start"]), + "end": int(h["end"]), "indel_fraction": 1.0, + "control_indel_fraction": 0.0, "is_target": h["is_target"], + "target_info": h["target_info"], "guide": h["guide"]}) + out = pd.DataFrame(rows) + out.to_csv(args.out_table, index=False) + print(f"wrote {args.out_table}: {len(out)} (wgs_sample x hotspot) rows " + f"across {out['guide'].nunique() if len(out) else 0} guides") + print(f"wrote {args.out_truth}: {len(truth)} (guide x hotspot) truth rows " + f"({int(truth['ecs_is_edit'].sum())} ECS-positive)") + + +if __name__ == "__main__": + main() diff --git a/bin/indel_length_diversity.py b/bin/indel_length_diversity.py new file mode 100755 index 0000000..e07d964 --- /dev/null +++ b/bin/indel_length_diversity.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 +""" +indel_length_diversity.py — measure the "varied indel lengths at one cut" signature. + +The heuristic this quantifies +----------------------------- +From manual IGV review: **if every supporting read shows the exact same indel length, it is +probably a sequencing/alignment artifact.** A genuine CRISPR pileup carries indels of *different* +sizes at *slightly* different places, all overlapping the one position Cas9 cut. NHEJ repair is +stochastic, so real editing is heterogeneous; a systematic artifact is monotonous. + +The shape model has no such feature — it has `modal_len` (the mode) and nothing about the spread. +Note this is NOT the same thing as `conc_ratio`/`pos_conc`, which reward *positional* concordance. +Both are wanted, and they pull in opposite directions: + + position should be CONCORDANT (one cut site) + length should be DIVERSE (stochastic repair) + +Measured on the AAVS1 cohort (from the WGS tagged BAMs) — and the honest answer is that on +THIS cohort it does not yet separate: + + raw distinct-length count TP (n=2): 19, 16 TN (n=26): median 2, max 14 + depth-controlled at 30 TP: 8, 9 TN: 9, 5, 2 + +The raw count looks decisive, but it is confounded with depth: the TP sites carry 119-149 +edit-supporting reads while most TN sites carry 1-17. Only three TN sites have >=30 edit reads, +and once every site is rarefied to the same 30 reads the best TN (chr6:36797655) scores 9 -- +matching the two real edits at 8 and 9. **No separation survives the depth control.** This is the +same trap that removed `n_distinct_pos` from the old feature set (`features.py:12`, "it grows"). + +Which does not mean the heuristic is wrong. The two TN sites with the highest depth-controlled +diversity, chr6:36797655 and chr7:26760750, are also the two with the highest ECS VAF (0.248 and +0.302). They may be genuine off-target edits that curation never confirmed rather than artifacts, +in which case the feature is behaving correctly and the labels are incomplete. chr6:36797655 is +the site to open first in IGV: high length diversity and strong ECS support say "real", while +sitting 41 bp from the predicted cut says "artifact". + +**Do not use normalised Shannon entropy for this.** It divides by log(n_distinct), which cancels +the very signal we want: measured TP normalised entropy is 0.55-0.59 while several TN sites reach +1.000 — the ranking inverts. Report the raw distinct-length count together with the edit-read +depth and let the tree model learn the interaction; gradient boosting handles that natively and +needs no hand-chosen normalisation. + +Usage +----- + indel_length_diversity.py --outdir results_offtarget_aavs1_igv/offtarget [--out div.csv] +""" +import argparse +import collections +import math +import os +import random +import re +import statistics +import sys + +import pandas as pd +import pysam + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from validate_recall_aavs1 import load_truth, DEFAULT_TP, DEFAULT_TN, SLACK, _near + +TAG_LEN = re.compile(r"Edited_(Deletion|Insertion)_(\d+)bp") +WINDOW = 60 + + +def edit_lengths(bam, chrom, pos, window=WINDOW, tag="XC"): + """Indel lengths of the edit-supporting reads around a site, from their XC tags.""" + out = [] + try: + it = bam.fetch(chrom, max(0, pos - window), pos + window) + except (ValueError, KeyError): + return out + for r in it: + try: + m = TAG_LEN.match(r.get_tag(tag) or "") + except KeyError: + continue + if m: + out.append(int(m.group(2))) + return out + + +def summarise(lengths): + if not lengths: + return None + c = collections.Counter(lengths) + n = sum(c.values()) + return {"n_edit_reads": n, + "n_distinct_len": len(c), + "modal_len_frac": round(max(c.values()) / n, 3), + # unnormalised Shannon entropy: unlike the normalised form it keeps the + # "how many different lengths" signal instead of dividing it out + "len_entropy": round(-sum((v / n) * math.log(v / n) for v in c.values()), 3)} + + +def rarefy(lengths, k, draws=200, seed=0): + """Distinct lengths at a FIXED subsample size — the depth-controlled comparison.""" + if len(lengths) < k: + return None + rng = random.Random(seed) + return statistics.median(len(set(rng.sample(lengths, k))) for _ in range(draws)) + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--outdir", required=True, help="the run's offtarget/ directory") + ap.add_argument("--tp", default=DEFAULT_TP) + ap.add_argument("--tn", default=DEFAULT_TN) + ap.add_argument("--rarefy-to", type=int, default=30, + help="depth-controlled distinct-length count at this many edit reads") + ap.add_argument("--out", help="write the per-site table here") + args = ap.parse_args() + + tp_set, tn_set = load_truth(args.tp, args.tn) + t = pd.read_csv(os.path.join(args.outdir, "training.tsv"), sep="\t", low_memory=False) + t["called"] = t["verdict"].astype(str).str.contains("LIKELY EDIT", na=False) + t["curated"] = ["TP" if _near(c, p, tp_set, SLACK) else + ("TN" if _near(c, p, tn_set, SLACK) else "uncurated") + for c, p in zip(t["chrom"], t["start"])] + + tag_dir = os.path.join(args.outdir, "wgs_tagged") + if not os.path.isdir(tag_dir): + sys.exit(f"ERROR: {tag_dir} not found — rerun with --offtarget_wgs_tagged_bam true") + cache = {} + rows = [] + for _, r in t[t["called"] | (t["curated"] == "TP")].iterrows(): + s = r["sample"] + if s not in cache: + p = os.path.join(tag_dir, f"{s}.wgs_tagged.bam") + cache[s] = pysam.AlignmentFile(p) if os.path.exists(p) else None + if cache[s] is None: + continue + pos = int(r["modal_pos"]) if pd.notna(r.get("modal_pos")) else int(r["start"]) + lengths = edit_lengths(cache[s], str(r["chrom"]), pos) + summ = summarise(lengths) + if summ is None: + continue + rows.append({"curated": r["curated"], "site": f"{r['chrom']}:{int(r['start'])}", + "cut_dist": r.get("cut_dist"), "ecs_if": r.get("ecs_if"), + **summ, + f"distinct_at_{args.rarefy_to}": rarefy(lengths, args.rarefy_to)}) + + df = pd.DataFrame(rows).sort_values(["curated", "n_distinct_len"], + ascending=[True, False]) + with pd.option_context("display.width", 200, "display.max_rows", 60): + print() + print("=== indel-length diversity at called sites ===") + print(df.to_string(index=False)) + print() + for g, sub in df.groupby("curated"): + print(f"{g:9s} n={len(sub):2d} median distinct lengths={sub['n_distinct_len'].median():.1f}" + f" max={sub['n_distinct_len'].max()}" + f" median modal_len_frac={sub['modal_len_frac'].median():.3f}") + print() + print("Position should be concordant; length should not. A site whose every read carries the") + print("identical indel is more suspicious than one with varied lengths at the same cut.") + + if args.out: + df.to_csv(args.out, index=False) + print(f"\nwrote {args.out}") + + +if __name__ == "__main__": + main() diff --git a/bin/join_training_table.py b/bin/join_training_table.py new file mode 100755 index 0000000..a60bda9 --- /dev/null +++ b/bin/join_training_table.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +""" +join_training_table.py — the ECS⋈WGS join that makes the WGS-only model possible. + +Left : WGS per-hotspot features + shape score (score.py output; sample = WGS sample). +Right : ECS per-(guide,site) truth VAF + label (from hotspot_to_table.py). +Key : (guide, chrom, start). WGS sample -> guide via the samplesheet. + +Output: training.tsv, one row per (guide, WGS sample, hotspot) = WGS pileup features +(indel_frac, conc_ratio, score, spanning, ctrl_if, modal_len, verdict) + ecs_if (truth +VAF) + label. This feeds the OFFLINE trainer; the deployed model stays a fixed asset. +""" +import sys, argparse +import pandas as pd + +WGS_FEATURE_COLS = ["indel_frac", "conc_ratio", "pos_conc", "pos_mad", "modal_len", + "modal_mapq", "softclip_frac", "spanning", "ctrl_if", + "modal_pos", "min_mm", "score", "verdict", "call_basis", + # distance from the observed indel to the predicted cut site, and the + # reference-repeat context at that position. Carried so the offline + # trainer and the validators see them without a re-score. + "cut_dist", "homopolymer_len", "repeat_frac"] + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--wgs-scores", required=True, help="score.py output CSV (WGS at hotspots)") + ap.add_argument("--truth", required=True, help="ecs_hotspot_truth.csv from hotspot_to_table.py") + ap.add_argument("--samplesheet", required=True) + ap.add_argument("--germline-max-ctrl-if", type=float, default=0.05, + help="a hotspot whose matched-normal (WGS) indel fraction exceeds this is " + "germline/artifact, not a somatic edit -> label 0 even if ECS shows an indel") + ap.add_argument("--out", default="training.tsv") + args = ap.parse_args() + + ss = pd.read_csv(args.samplesheet) + ss.columns = [c.strip().lower() for c in ss.columns] + sample_guide = dict(zip(ss["sample"], ss["guide"])) + + wgs = pd.read_csv(args.wgs_scores) + wgs["guide"] = wgs["sample"].map(sample_guide) + keep = ["sample", "guide", "chrom", "start"] + [c for c in WGS_FEATURE_COLS if c in wgs.columns] + wgs = wgs[keep].copy() + + truth = pd.read_csv(args.truth) # guide, chrom, start, end, is_target, target_info, ecs_if, ecs_is_edit + + # normalize key dtypes + for d in (wgs, truth): + d["chrom"] = d["chrom"].astype(str) + d["start"] = pd.to_numeric(d["start"], errors="coerce").astype("Int64") + + truth_cols = ["guide", "chrom", "start", "ecs_if", "ecs_is_edit", "is_target"] + # read support is optional (older ecs_hotspot_truth.csv predates it) but is what + # lets recall_vs_vaf.py keep ECS noise out of its denominator + truth_cols += [c for c in ("ecs_indel_reads", "ecs_total_reads") if c in truth.columns] + merged = wgs.merge(truth[truth_cols], on=["guide", "chrom", "start"], how="inner") + + # Training label = a SOMATIC edit: ECS saw an indel AND it is absent from the matched WGS + # normal. ECS alone can't exclude germline here — its control is a different individual, so + # control_indel_fraction is ~0 everywhere — so the matched-normal WGS signal (ctrl_if) is the + # only thing that separates a real edit from a germline/recurrent variant. The raw ECS call is + # kept as `ecs_is_edit`; `label` (what the trainer + recall metric consume) is the somatic one. + is_edit = merged["ecs_is_edit"] == 1 + if "ctrl_if" in merged.columns: + ctrl = pd.to_numeric(merged["ctrl_if"], errors="coerce").fillna(0.0) + germline = is_edit & (ctrl > args.germline_max_ctrl_if) + merged["label"] = (is_edit & (ctrl <= args.germline_max_ctrl_if)).astype(int) + else: + print("WARN: no ctrl_if (matched-normal) column — cannot exclude germline; " + "label = raw ECS edit", file=sys.stderr) + germline = pd.Series(False, index=merged.index) + merged["label"] = is_edit.astype(int) + merged.to_csv(args.out, sep="\t", index=False) + + n_pos = int((merged["label"] == 1).sum()) + n_germ = int(germline.sum()) + print(f"wrote {args.out}: {len(merged)} rows " + f"({n_pos} somatic-edit positives, {n_germ} ECS edits demoted as germline/in-normal, " + f"{len(merged) - n_pos - n_germ} ECS-negative) across " + f"{merged['guide'].nunique() if len(merged) else 0} guides") + if len(merged) == 0: + msg = ("empty join — WGS sample->guide and hotspot coords do not line up with the " + "ECS truth (a coordinate off-by-one between the arms is the usual culprit)") + # If BOTH arms produced rows but nothing joined, this is a keying bug, not a + # legitimately empty run: fail loudly so a silent empty training.tsv can't pass. + # Only warn when one side is genuinely empty (e.g. an ECS- or WGS-less run). + if len(wgs) > 0 and len(truth) > 0: + sys.exit(f"ERROR: {msg} [{len(wgs)} WGS rows x {len(truth)} ECS truth rows -> 0 joined]") + print(f"WARN: {msg} [{len(wgs)} WGS rows, {len(truth)} ECS truth rows]", file=sys.stderr) + + +if __name__ == "__main__": + main() diff --git a/bin/make_hotspot_vcf.py b/bin/make_hotspot_vcf.py old mode 100644 new mode 100755 index 5c3e677..7fedaf0 --- a/bin/make_hotspot_vcf.py +++ b/bin/make_hotspot_vcf.py @@ -34,34 +34,56 @@ def add_sequence_column(row: pd.Series, fasta_handle: pysam.FastaFile) -> str: return "N" * (row['End'] - row['Start']) -def dataframe_to_vcf(df: pd.DataFrame, fasta_handle: pysam.FastaFile) -> str: +def dataframe_to_vcf(df: pd.DataFrame, fasta_handle: pysam.FastaFile, outfile_path: str) -> None: """ - Converts a DataFrame with genomic positions into a VCF formatted string, - including a proper header with contigs from the reference FASTA. + Converts a DataFrame with genomic positions into a VCF file using pysam. + Records are sorted based on the contig order in the provided fasta_handle. + + Args: + df: DataFrame containing 'Chromosome', 'Position', and 'Sequence' columns. + fasta_handle: Open pysam.FastaFile object. + outfile_path: Path to write the output VCF. """ - vcf_lines = ["##fileformat=VCFv4.2"] + # 1. Enforce Sorting Order based on Reference FASTA + # We create a categorical type for the 'Chromosome' column using the + # ordered list of references from the pysam FastaFile. + df_sorted = df.copy() + df_sorted['Chromosome'] = pd.Categorical( + df_sorted['Chromosome'], + categories=fasta_handle.references, + ordered=True + ) + + # Sort by Chromosome (ref order) then Position. + # DropNA ensures we don't crash on chroms not in the reference. + df_sorted = df_sorted.sort_values(by=['Chromosome', 'Position']).dropna(subset=['Chromosome']) - # Add contig lines to the header from the FASTA index + # 2. Create the VCF Header + header = pysam.VariantHeader() + + # Add contigs to header with lengths from the FASTA index for contig in fasta_handle.references: length = fasta_handle.get_reference_length(contig) - vcf_lines.append(f"##contig=") - - vcf_lines.append("#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO") - - # Prepare DataFrame for VCF format - df_vcf = df.copy() - df_vcf['#CHROM'] = df_vcf['Chromosome'] - df_vcf['POS'] = df_vcf['Position'] + 1 # VCF is 1-based - df_vcf['ID'] = '.' - df_vcf['REF'] = df_vcf['Sequence'] - df_vcf['ALT'] = '.' # No alternative allele for a hotspot VCF - df_vcf['QUAL'] = '.' - df_vcf['FILTER'] = 'PASS' - df_vcf['INFO'] = '.' + header.contigs.add(contig, length=length) - vcf_body = df_vcf[['#CHROM', 'POS', 'ID', 'REF', 'ALT', 'QUAL', 'FILTER', 'INFO']].to_csv(sep='\t', index=False, header=False) - - return "\n".join(vcf_lines) + "\n" + vcf_body + # 3. Write directly to the specified output file + # pysam.VariantFile handles opening the file for writing. + with pysam.VariantFile(outfile_path, 'w', header=header) as vcf_out: + for _, row in df_sorted.iterrows(): + # Create a new record object + rec = vcf_out.new_record() + + # Fill fields + rec.chrom = str(row['Chromosome']) + rec.pos = int(row['Position']) + rec.id = '.' + rec.ref = row['Sequence'] + rec.alts = ('N') + rec.filter.add('PASS') + + # Write record + vcf_out.write(rec) + # --- Main Application Logic --- @@ -89,13 +111,16 @@ def main(): # --- 2. Read and Merge Genomic Regions --- print(f"Reading and processing BED file: {args.bed}", file=sys.stderr) bed_df = pd.read_csv(args.bed, sep='\t', usecols=[0, 1, 2], names=['Chromosome', 'Start', 'End']) + bed_df['Start'] = bed_df['Start'] + 1 - # Read in editing targets, in the format: Source,DNA_Sequence,PAM,Chromosome,Strand,Start,Bulge_Type,Mismatch,Bulge_Size,On_target + # Read in editing targets in VCF format print(f"Reading editing targets: {args.targets}", file=sys.stderr) - targets_df = pd.read_csv(args.targets, sep=',')[['Chromosome','Start']] - targets_df['Start'] = targets_df['Start'].astype(int) - args.window - targets_df['End'] = targets_df['Start'] + (args.window * 2) - + vcf_in = pysam.VariantFile(args.targets) + vcf_data = [(record.chrom, record.pos) for record in vcf_in] + targets_df = pd.DataFrame(vcf_data, columns=['Chromosome', 'Start']) + targets_df['Start'] = targets_df['Start'] - args.window + targets_df['End'] = targets_df['Start'] + (args.window) + bed_df = pd.concat([bed_df,targets_df],ignore_index=True) merged_df = pr.PyRanges(bed_df).merge().sort().df @@ -124,12 +149,7 @@ def main(): }) # --- 5. Convert to VCF and Write to File --- - result_vcf_str = dataframe_to_vcf(vcf_df, fasta_handle) - output_filename = f"{args.outfile}" - - with open(output_filename, "w") as f: - f.write(result_vcf_str) - print(f"Successfully wrote hotspot VCF to '{output_filename}'", file=sys.stderr) + dataframe_to_vcf(vcf_df, fasta_handle, args.outfile) except Exception as e: sys.exit(f"An error occurred: {e}") diff --git a/bin/make_igv_session.py b/bin/make_igv_session.py new file mode 100755 index 0000000..07237e4 --- /dev/null +++ b/bin/make_igv_session.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 +""" +make_igv_session.py — a navigable index + IGV batch script for live review. + +The problem this solves +----------------------- +The review material is spread across three coordinate conventions that do not line up: + + * the hotspot table (`training.tsv`) keys a site by its **predicted cut site** + * the genome-wide worklist and the rendered snapshots key the same event by the + **observed VCF indel position** — e.g. `rank005_..._chr7_26760821.png` for the hotspot at + `chr7:26760750`, 71 bp away + * the tagged BAMs are just BAMs; you have to know where to look + +So there is no way to answer "show me the evidence for hotspot X" without doing the arithmetic by +hand, and three of the five strongest candidates have no snapshot at all. This emits one index +that carries all three, plus an IGV batch script so sites can be jumped to live. + +Ordering is by `cut_dist` ascending, deliberately: an indel far from the predicted cut is probably +an artifact regardless of how good its VAF looks, so the defensible sites come first. The +highest-ECS-VAF candidate on AAVS1 (`chr7:26760750`, ecs_if 0.302) sits 71 bp out and sorts near +the bottom, which is the correct outcome. + +Usage +----- + make_igv_session.py --outdir results_offtarget_aavs1_igv/offtarget \ + --out-prefix results_demo/igv_review +""" +import argparse +import glob +import os +import re +import sys + +import pandas as pd + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from validate_recall_aavs1 import load_truth, DEFAULT_TP, DEFAULT_TN, SLACK, _near + +WINDOW = 150 # bp each side, matches the tagged-BAM window +SNAP_RE = re.compile(r"^rank(\d+)_(.+?)_(chr[^_]+)_(\d+)\.png$") + + +def index_snapshots(snap_dir): + """(chrom, pos) -> filename, from the rank###___.png naming.""" + out = {} + for path in sorted(glob.glob(os.path.join(snap_dir, "*.png"))): + m = SNAP_RE.match(os.path.basename(path)) + if m: + out.setdefault((m.group(3), int(m.group(4))), os.path.basename(path)) + return out + + +def nearest_snapshot(snaps, chrom, pos, tol=120): + """Snapshots are keyed by VCF position, sites by cut site; allow real slack.""" + best, best_d = None, None + for (c, p), name in snaps.items(): + if c != chrom: + continue + d = abs(p - pos) + if d <= tol and (best_d is None or d < best_d): + best, best_d = name, d + return best, best_d + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--outdir", required=True, + help="the run's offtarget/ directory (training.tsv, snapshots/, *_tagged.bam)") + ap.add_argument("--out-prefix", required=True, help="prefix for the .csv and .bat outputs") + ap.add_argument("--tp", default=DEFAULT_TP) + ap.add_argument("--tn", default=DEFAULT_TN) + ap.add_argument("--genome", default="hg38", + help="IGV genome id or a path to the FASTA used for the run") + ap.add_argument("--window", type=int, default=WINDOW) + args = ap.parse_args() + + tp_set, tn_set = load_truth(args.tp, args.tn) + t = pd.read_csv(os.path.join(args.outdir, "training.tsv"), sep="\t", low_memory=False) + t["called"] = t["verdict"].astype(str).str.contains("LIKELY EDIT", na=False) + if "cut_dist" not in t.columns: + t["cut_dist"] = (t["modal_pos"] - t["start"]).abs() + + t["curated"] = ["TP" if _near(c, p, tp_set, SLACK) else + ("TN" if _near(c, p, tn_set, SLACK) else "uncurated") + for c, p in zip(t["chrom"], t["start"])] + + # everything worth opening: the confirmed edits plus every call + sel = t[t["called"] | (t["curated"] == "TP")].copy() + + snaps = index_snapshots(os.path.join(args.outdir, "snapshots")) + ecs_bams = sorted(glob.glob(os.path.join(args.outdir, "*.tagged.bam"))) + wgs_bams = sorted(glob.glob(os.path.join(args.outdir, "**", "*wgs_tagged.bam"), + recursive=True)) + + rows = [] + for _, r in sel.iterrows(): + obs = int(r["modal_pos"]) if pd.notna(r.get("modal_pos")) else int(r["start"]) + snap, snap_off = nearest_snapshot(snaps, str(r["chrom"]), int(r["start"])) + rows.append({ + "curated": r["curated"], + "sample": r.get("sample"), + "hotspot": f"{r['chrom']}:{int(r['start'])}", + "observed_indel": f"{r['chrom']}:{obs}", + "cut_dist": r["cut_dist"], + "modal_len": r.get("modal_len"), + "indel_frac": r.get("indel_frac"), + "ecs_if": r.get("ecs_if"), + "score": r.get("score"), + "verdict": r.get("verdict"), + "igv_locus": f"{r['chrom']}:{max(1, obs - args.window)}-{obs + args.window}", + "snapshot": snap or "MISSING", + "snapshot_offset_bp": snap_off if snap else "", + }) + idx = pd.DataFrame(rows) + # curated edits first, then by how defensible the site is + idx["_o"] = (idx["curated"] != "TP").astype(int) + idx = idx.sort_values(["_o", "cut_dist"], na_position="last").drop(columns="_o") + + csv_path = args.out_prefix + ".csv" + os.makedirs(os.path.dirname(csv_path) or ".", exist_ok=True) + idx.to_csv(csv_path, index=False) + + bat_path = args.out_prefix + ".bat" + with open(bat_path, "w") as fh: + fh.write("# IGV batch script — off-target review\n") + fh.write("# Run: IGV > Tools > Run Batch Script, or `igv.sh -b this_file`\n") + fh.write("# Reads are coloured by the XC tag: Edited_* vs Unedited_WT vs Skipped_*\n") + fh.write("new\n") + fh.write(f"genome {args.genome}\n") + for b in ecs_bams + wgs_bams: + fh.write(f"load {os.path.abspath(b)}\n") + if not (ecs_bams or wgs_bams): + fh.write("# WARNING: no tagged BAMs found in this run directory\n") + fh.write("colorBy TAG XC\n") + fh.write("maxPanelHeight 800\n") + for _, r in idx.iterrows(): + fh.write(f"\n# {r['curated']:9s} {r['hotspot']:24s} cut_dist={r['cut_dist']} " + f"ecs_if={r['ecs_if']} verdict={r['verdict']}\n") + fh.write(f"goto {r['igv_locus']}\n") + + n_tp = int((idx["curated"] == "TP").sum()) + print(f"\nwrote {csv_path} ({len(idx)} sites: {n_tp} curated edits, " + f"{int((idx['curated'] == 'TN').sum())} curated negatives, " + f"{int((idx['curated'] == 'uncurated').sum())} uncurated)") + print(f"wrote {bat_path} (loads {len(ecs_bams)} ECS + {len(wgs_bams)} WGS tagged BAM(s))") + print(f"snapshots matched: {int((idx['snapshot'] != 'MISSING').sum())} of {len(idx)}") + print() + show = ["curated", "hotspot", "cut_dist", "indel_frac", "ecs_if", "verdict", "snapshot"] + with pd.option_context("display.width", 200, "display.max_rows", 40): + print(idx[show].head(20).to_string(index=False)) + + +if __name__ == "__main__": + main() diff --git a/bin/make_scge_excel.py b/bin/make_scge_excel.py new file mode 100755 index 0000000..1aefd1c --- /dev/null +++ b/bin/make_scge_excel.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python3 +"""Compile the per-sample SCGE report JSON into a multi-sheet Excel workbook. + +Engine note: this runs on whichever of openpyxl / xlsxwriter the container provides. +docker-baseimage ships pandas + openpyxl + Pillow and NOT xlsxwriter, so openpyxl is the +path that actually executes; xlsxwriter is still supported if present. The two libraries +have different worksheet APIs (create_sheet/cell/add_image vs add_worksheet/write/ +insert_image), so every call below goes through a small adapter rather than being written +against one of them with the other bolted on. +""" + +import argparse +import json +import os +import sys + +import pandas as pd + + +def parse_args(): + parser = argparse.ArgumentParser(description='Generate Excel report for SCGE pipeline') + parser.add_argument('--report_json', required=True, help='Path to report JSON file') + parser.add_argument('--circos_plot', help='Path to Circos plot image') + parser.add_argument('--cna_plot', help='Path to CNA plot image') + parser.add_argument('--baf_plot', help='Path to BAF plot image') + parser.add_argument('--indel_freq_plot', help='Path to Indel Frequency plot image') + parser.add_argument('--off_targets_plot', help='Path to Off-targets plot image') + parser.add_argument('--output', required=True, help='Output Excel filename') + return parser.parse_args() + + +def usable(path): + """A plot argument is usable only if it was passed, exists and is non-empty. + + Upstream processes `touch` a placeholder when they have nothing to draw, so an empty + file is the normal 'no plot for this sample' signal, not an error. + """ + return bool(path) and os.path.exists(path) and os.path.getsize(path) > 0 + + +class SummarySheet: + """Minimal write/insert_image surface over either Excel engine.""" + + def __init__(self, workbook, engine, title='Summary'): + self.engine = engine + if engine == 'xlsxwriter': + self.ws = workbook.add_worksheet(title) + self.bold = workbook.add_format({'bold': True}) + self.title_fmt = workbook.add_format({'bold': True, 'font_size': 14}) + else: + from openpyxl.styles import Font + self.ws = workbook.create_sheet(title) + self.bold = Font(bold=True) + self.title_fmt = Font(bold=True, size=14) + + def write(self, row, col, value, style=None): + """Write a cell using 0-based (row, col), as xlsxwriter does throughout.""" + if self.engine == 'xlsxwriter': + self.ws.write(row, col, value, style) + else: + cell = self.ws.cell(row=row + 1, column=col + 1, value=value) + if style is not None: + cell.font = style + + def insert_image(self, path, row, col, scale=0.5): + if not usable(path): + return False + try: + if self.engine == 'xlsxwriter': + from xlsxwriter.utility import xl_rowcol_to_cell + self.ws.insert_image(xl_rowcol_to_cell(row, col), path, + {'x_scale': scale, 'y_scale': scale}) + else: + from openpyxl.drawing.image import Image + from openpyxl.utils import get_column_letter + img = Image(path) + # openpyxl has no scale factor; resize explicitly so a full-width plot does + # not swamp the sheet the way it would at native resolution. + img.width = int(img.width * scale) + img.height = int(img.height * scale) + self.ws.add_image(img, f"{get_column_letter(col + 1)}{row + 1}") + return True + except Exception as e: # noqa: BLE001 + print(f"Warning: could not insert image {path}: {e}") + return False + + +def main(): + args = parse_args() + + try: + with open(args.report_json, 'r') as f: + data = json.load(f) + except Exception as e: # noqa: BLE001 + print(f"Error loading JSON: {e}") + sys.exit(1) + + try: + import openpyxl # noqa: F401 + engine = 'openpyxl' + except ImportError: + try: + import xlsxwriter # noqa: F401 + engine = 'xlsxwriter' + except ImportError: + print("Error: neither openpyxl nor xlsxwriter is installed.") + sys.exit(1) + + writer = pd.ExcelWriter(args.output, engine=engine) + workbook = writer.book + + # --- Sheet 1: summary and plots --- + summary = SummarySheet(workbook, engine) + summary.write(0, 0, 'Somatic Editing Genome Report', summary.title_fmt) + + meta = data.get('metadata', {}) + coverage = meta.get('mean_coverage', {}) + metadata = [ + ('Sample ID', data.get('sample_id', 'N/A')), + ('Control Sample', meta.get('control_sample', 'N/A')), + ('Transgene', data.get('transgene_description', 'N/A')), + ('Tumor Mean Coverage', f"{coverage.get('tumor', 'N/A')}x"), + ('Normal Mean Coverage', f"{coverage.get('normal', 'N/A')}x"), + ] + row = 2 + for key, val in metadata: + summary.write(row, 0, key, summary.bold) + summary.write(row, 1, val) + row += 1 + + # Two columns of plots (A and I), each block given room for a half-scale image. + row += 2 + for label, path, col in [ + ('On-Target Indel Frequency', args.indel_freq_plot, 0), + ('Transgene Integrations (Circos)', args.circos_plot, 8), + ]: + summary.write(row, col, label, summary.bold) + summary.insert_image(path, row + 2, col) + + row += 25 + summary.write(row, 0, 'Off-Target Sites', summary.bold) + summary.insert_image(args.off_targets_plot, row + 2, 0) + + row += 25 + for label, path, col in [ + ('Copy Number Analysis (CNA)', args.cna_plot, 0), + ('B-Allele Frequency (BAF)', args.baf_plot, 8), + ]: + summary.write(row, col, label, summary.bold) + summary.insert_image(path, row + 2, col) + + # --- Sheets 2-4: the tables --- + tables = data.get('tables', {}) + + on_target = tables.get('on_target_sv_transgene', []) + if on_target: + df = pd.DataFrame(on_target if isinstance(on_target, list) else [on_target]) + cols = [c for c in ['Location', 'SYMBOL', 'Consequence', 'EXON', 'INTRON', + 'HGVSc', 'HGVSp'] if c in df.columns] + if cols: + df = df[cols] + else: + df = pd.DataFrame({'Message': ['No on-target variants found']}) + df.to_excel(writer, sheet_name='On-Target Variants', index=False) + + off_target = tables.get('off_target_indels', []) + (pd.DataFrame(off_target) if off_target + else pd.DataFrame({'Message': ['No off-target indels found']}) + ).to_excel(writer, sheet_name='Off-Target Indels', index=False) + + targeted = tables.get('targeted_gene_mutations', []) + (pd.DataFrame(targeted) if targeted + else pd.DataFrame({'Message': ['No targeted gene mutation data available']}) + ).to_excel(writer, sheet_name='Targeted Gene Mutations', index=False) + + writer.close() + print(f"Successfully generated {args.output} (engine: {engine})") + + +if __name__ == "__main__": + main() diff --git a/bin/make_scge_report.qmd b/bin/make_scge_report.qmd index 7e032f6..d8f23c0 100644 --- a/bin/make_scge_report.qmd +++ b/bin/make_scge_report.qmd @@ -2,6 +2,10 @@ params: report_json: "" off_target_threshold: 1.0 + cna_plot_file: "" + baf_plot_file: "" + circos_plot_file: "" + transgene_name: "" execute: echo: false warning: false @@ -37,6 +41,70 @@ include-in-header: text-align: left; width: auto; } + /* Restore original table styles */ + table { + border-collapse: collapse; + width: 100%; + table-layout: fixed; + border: 1px solid #6495ED; + border-spacing: 0; + } + th { + background-color: #6495ED; + color: white; + font-size: 1.2em; + border-bottom: 1px solid #6495ED; + padding: 8px; + text-align: left; + } + td { + background-color: #E6F3FF; + padding: 8px; + border-right: 1px solid #6495ED; + vertical-align: top; + } + td:last-child, th:last-child { + border-right: none; + } + + /* White background tables for content */ + .white-background-table td { + background-color: white; + text-align: center; + } + .white-background-table th { + background-color: #E6F3FF; + color: black; + border-top: 2px solid #6495ED; + border-bottom: 2px solid #6495ED; + } + + .equal-size-img { + width: 100%; + height: auto; + max-width: 100%; + display: block; + margin: 0 auto; + } + + .plot-unavailable { + text-align: center; + padding: 20px; + color: #666; + font-style: italic; + } + + /* Off-target subtable fixes */ + .off-target-subtable { + margin: 0; + } + .off-target-subtable td { + padding: 4px; + font-size: 0.9em; + word-wrap: break-word; + white-space: normal; + max-width: 300px; + } --- ```{r} @@ -51,24 +119,54 @@ library(dplyr) library(tidyr) library(knitr) -# Read JSON data -report_data <- fromJSON(params$report_json) -off_target_threshold_value <- as.numeric(params$off_target_threshold) +# -- Params Handling -- +if (!exists("params")) { + if (file.exists("params.yml")) { + lines <- readLines("params.yml") + params <- list() + for (line in lines) { + if (grepl(":", line)) { + parts <- strsplit(line, ":", fixed = TRUE)[[1]] + key <- trimws(parts[1]) + value <- trimws(paste(parts[-1], collapse = ":")) + value <- gsub('^"|"$', "", value) + params[[key]] <- value + } + } + } else { + # Last ditch + params <- list() + } +} + report_json_path <- params$report_json +# Fallback if params failed +if (is.null(report_json_path) && exists("report_json")) report_json_path <- report_json + +if (is.null(report_json_path)) stop("report_json parameter not found") + +off_target_threshold_value <- as.numeric(params$off_target_threshold) +if (is.na(off_target_threshold_value)) off_target_threshold_value <- 1.0 + +transgene_name_param <- params$transgene_name +if (is.null(transgene_name_param)) transgene_name_param <- "" -# Extract target gene from sample ID, assuming "GENE-KO-DNA" format +# Load data +report_data <- fromJSON(report_json_path) + +# Extract target gene target_gene_symbol <- sub("-KO-DNA", "", report_data$sample_id) -# Read hotspot file to get gRNA display string +# gRNA display string hotspot_file_path <- report_data$metadata$hotspot_file -grna_display_string <- target_gene_symbol # Default to gene name +grna_display_string <- target_gene_symbol if (!is.null(hotspot_file_path) && file.exists(hotspot_file_path)) { try({ hotspot_data <- read.csv(hotspot_file_path) if ("On_target" %in% colnames(hotspot_data)) { on_target_grnas <- subset(hotspot_data, On_target == 1) - if (nrow(on_target_grnas) > 0 && "Chromosome" %in% colnames(on_target_grnas) && "Start" %in% colnames(on_target_grnas)) { + if (nrow(on_target_grnas) > 0) { grna_locations <- paste0(on_target_grnas$Chromosome, ":", on_target_grnas$Start) grna_locations_str <- paste(unique(grna_locations), collapse=", ") if (nchar(grna_locations_str) > 0) { @@ -79,134 +177,111 @@ if (!is.null(hotspot_file_path) && file.exists(hotspot_file_path)) { }, silent = TRUE) } -# -- Prepare On- and Off-Target Coding Sequence Variants Tables -- +# -- Prepare SV Table -- sv_table_html <- "

No on-target SV/transgene data available in the report.

" transgene_df <- report_data$tables$on_target_sv_transgene -# The data is already parsed into a data frame from the JSON. if ((is.data.frame(transgene_df) && nrow(transgene_df) > 0) || (is.list(transgene_df) && length(transgene_df) > 0)) { - # Coerce to data.frame if it's a list (fromJSON behavior) if (is.list(transgene_df) && !is.data.frame(transgene_df)) { transgene_df <- dplyr::bind_rows(transgene_df) } - - # Filter for coding variants using a broad set of terms coding_terms <- c("coding_sequence", "frameshift", "missense", "inframe_insertion", "inframe_deletion", "stop_gained") coding_pattern <- paste(coding_terms, collapse = "|") - # Ensure the required columns exist if ("Consequence" %in% colnames(transgene_df) && "SYMBOL" %in% colnames(transgene_df)) { coding_variants <- transgene_df[grepl(coding_pattern, transgene_df$Consequence, ignore.case = TRUE), ] - if (nrow(coding_variants) > 0) { - # Handle multiple transcript annotations for a single variant - # Prioritize annotations with an EXON number and then de-duplicate. sv_display_data <- coding_variants %>% arrange(Location, desc(EXON != "-")) %>% distinct(Location, .keep_all = TRUE) %>% select(Location, SYMBOL, EXON) - colnames(sv_display_data) <- c("Location", "Gene Symbol", "Exon") - - # Generate HTML table - sv_table_html <- knitr::kable(sv_display_data, format = "html", row.names = FALSE, escape = FALSE, table.attr = 'class="table table-bordered"') + sv_table_html <- knitr::kable(sv_display_data, format = "html", row.names = FALSE, table.attr = 'class="table table-bordered variant-sub-table"') } else { sv_table_html <- "

No coding variants found

" } - } else { - sv_table_html <- paste0( - "

Required columns not found in the data.

", - "

Available: ", paste(colnames(transgene_df), collapse=", "), "

" - ) } } -# -- Prepare Circos plot HTML -- -circos_html <- "" -# The sv_data object is needed for the circos plot logic, so we must recreate it here. -sv_data <- report_data$tables$on_target_sv_transgene -if (!is.null(report_data$plots$circos) && file.exists(report_data$plots$circos)) { - file.copy(from = report_data$plots$circos, to = "circos.png", overwrite = TRUE) - img_tag <- 'circos plot' - p_tag <- paste0('

All Transgene Integrations

') - circos_html <- paste0(img_tag, p_tag) +# -- Determine Image Paths -- +# We don't generate HTML here, just check existence +circos_file <- params$circos_plot_file +# Handle empty/placeholder file +if (is.null(circos_file) || circos_file == "" || !file.exists(circos_file)) { + # Try finding by pattern in current dir + found_files <- list.files(pattern = ".*\\.transgene_insertions_circos\\.png$") + if (length(found_files) > 0) { + circos_file <- found_files[1] + } else { + circos_from_json <- report_data$plots$circos + if (!is.null(circos_from_json) && file.exists(basename(circos_from_json))) { + circos_file <- basename(circos_from_json) + } else { + circos_file <- NULL + } + } +} else if (file.info(circos_file)$size == 0) { + circos_file <- NULL } -# -- Prepare CNA/BAF plots HTML -- -cna_plot_html <- if (!is.null(report_data$plots$cna) && file.exists(report_data$plots$cna) && file.info(report_data$plots$cna)$size > 0) { - paste0('CNA Plot') -} else { - '

CNA plot not available

' -} -baf_plot_html <- if (!is.null(report_data$plots$baf) && file.exists(report_data$plots$baf) && file.info(report_data$plots$baf)$size > 0) { - paste0('BAF Plot') -} else { - '

BAF plot not available

' -} +cna_file <- params$cna_plot_file +if (is.null(cna_file) || !file.exists(cna_file)) cna_file <- NULL -# -- Prepare Targeted Gene Mutations table HTML -- +baf_file <- params$baf_plot_file +if (is.null(baf_file) || !file.exists(baf_file)) baf_file <- NULL + +# -- Prepare Targeted Gene Mutations -- targeted_gene_mutations_html <- "" +tgm <- NULL if (!is.null(report_data$tables$targeted_gene_mutations)) { tgm <- as.data.frame(report_data$tables$targeted_gene_mutations) - if (nrow(tgm) > 0 && all(c('gene','result') %in% colnames(tgm))) { - for (i in 1:nrow(tgm)) { - targeted_gene_mutations_html <- paste0(targeted_gene_mutations_html, '', tgm[i, 'gene'], '', tgm[i, 'result'], '') - } - } else { - default_genes <- c('TP53','DNMT3A','RUNX1','TET2') - for (g in default_genes) { - targeted_gene_mutations_html <- paste0(targeted_gene_mutations_html, '', g, 'no data') - } - } -} else { - default_genes <- c('TP53','DNMT3A','RUNX1','TET2') - for (g in default_genes) { - targeted_gene_mutations_html <- paste0(targeted_gene_mutations_html, '', g, 'no data') - } +} +if (is.null(tgm) || nrow(tgm) == 0) { + # Default rows if missing + tgm <- data.frame(gene = c("TP53", "DNMT3A", "RUNX1", "TET2"), result = "no data") +} +# Construct rows manually for the nested table structure if needed, or use kable +rows_html <- "" +for(i in 1:nrow(tgm)) { + rows_html <- paste0(rows_html, "", tgm$gene[i], "", tgm$result[i], "") } ``` + ```{python} #| include: false import json import matplotlib.pyplot as plt import pandas as pd +import os -# Load JSON directly to avoid R<->Python type conversion edge cases +# Load JSON report_json_path = r['report_json_path'] with open(report_json_path, 'r') as _fh: report_data = json.load(_fh) def parse_offtarget_data(data): - """Parse the off-target data and return x and y values.""" x_values, y_values = [], [] for record in data: - if not isinstance(record, dict): - continue + if not isinstance(record, dict): continue try: chrom, start, end = record['chrom'], record['start'], record['end'] indel_fraction = float(record.get('indel_fraction', 0) or 0) - is_target = int(record.get('is_target', record.get('is_target_site', 0)) or 0) - - if indel_fraction == 0: - continue - + if indel_fraction == 0: continue loci = f"{chrom}:{start}-{end}" x_values.append(loci) - y_values.append(indel_fraction * 100) # Convert to percentage - except (ValueError, IndexError, KeyError): - continue + y_values.append(indel_fraction * 100) + except (ValueError, IndexError, KeyError): continue return x_values, y_values offtarget_list = report_data.get('tables', {}).get('off_target_indels', []) -on_target_records = [rec for rec in offtarget_list if isinstance(rec, dict) and str(rec.get('is_target', rec.get('is_target_site', '0'))) == '1'] -off_target_records = [rec for rec in offtarget_list if isinstance(rec, dict) and str(rec.get('is_target', rec.get('is_target_site', '0'))) == '0'] +on_target_records = [rec for rec in offtarget_list if str(rec.get('is_target', rec.get('is_target_site', '0'))) == '1'] +off_target_records = [rec for rec in offtarget_list if str(rec.get('is_target', rec.get('is_target_site', '0'))) == '0'] on_target_x, on_target_y = parse_offtarget_data(on_target_records) off_target_x, off_target_y = parse_offtarget_data(off_target_records) -def plot_bar_chart(x_values, y_values, xlabel, ylabel, title, output_file, type, highlight_line=None): - """Create and save a bar chart.""" +def plot_bar_chart(x_values, y_values, xlabel, ylabel, output_file, type, highlight_line=None): if type == 'on target': plt.figure(figsize=(9, 9.5)) else: @@ -216,270 +291,210 @@ def plot_bar_chart(x_values, y_values, xlabel, ylabel, title, output_file, type, plt.axhline(y=highlight_line['value'], color=highlight_line['color'], linestyle='-', linewidth=2) plt.text(x=len(x_values)-0.5, y=highlight_line['value'], s=highlight_line['label'], color=highlight_line['color'], fontsize=12, va='bottom', ha='right') - plt.xlabel(rf"{xlabel}", fontsize=20) - plt.ylabel(rf"{ylabel}", fontsize=20) - plt.xticks([]) + plt.xlabel(rf"{xlabel}", fontsize=14) + plt.ylabel(rf"{ylabel}", fontsize=14) + plt.xticks(rotation=90) plt.tight_layout() plt.savefig(output_file, dpi=300, bbox_inches='tight') plt.close() if on_target_x: - plot_bar_chart(on_target_x, on_target_y, 'On-target loci', 'Indel frequency (%)', 'On-target editing', 'indel_freq.png', 'on target') + plot_bar_chart(on_target_x, on_target_y, 'On-target loci', 'Indel frequency (%)', 'indel_freq.png', 'on target') if off_target_x: thr = float(r['off_target_threshold_value']) - plot_bar_chart( - off_target_x, - off_target_y, - 'Predicted off-target sites', - 'Indel frequency (%)', - 'Off-target sites', - 'off_targets.png', - 'off target', - {'value': thr, 'color': 'red', 'label': f"{thr}%"} - ) + plot_bar_chart(off_target_x, off_target_y, 'Predicted off-target sites', 'Indel frequency (%)', 'off_targets.png', 'off target', {'value': thr, 'color': 'red', 'label': f"{thr}%"}) ``` +

Somatic Editing Genome Report


+ ```{r} #| echo: false #| results: 'asis' cat("") cat("") control_sample <- ifelse(!is.null(report_data$metadata$control_sample), report_data$metadata$control_sample, "N/A") -cat(paste0("")) + +# Use transgene_name_param if available, otherwise description from report_data +transgene_label <- ifelse(nchar(transgene_name_param) > 0, transgene_name_param, report_data$transgene_description) +if (is.null(transgene_label)) transgene_label <- "" + +cat(paste0("")) tumor_cov <- ifelse(!is.null(report_data$metadata$mean_coverage$tumor), paste0("Mean coverage: ", report_data$metadata$mean_coverage$tumor, "x"), "Mean coverage: N/A") normal_cov <- ifelse(!is.null(report_data$metadata$mean_coverage$normal), paste0("Mean coverage: ", report_data$metadata$mean_coverage$normal, "x"), "Mean coverage: N/A") -cat(paste0("")) +cat(paste0("")) cat("") cat(paste0("")) cat("
Drug ProductControl SampleModifications
", report_data$sample_id, "", control_sample, "Transgene:
", report_data$sample_id, "", control_sample, "Transgene: ", transgene_label, "
", tumor_cov, "", normal_cov, "", report_data$transgene_description, "
", tumor_cov, "", normal_cov, "
gRNA:
", grna_display_string, "
") ``` -

On-target editing (`r target_gene_symbol`)

- - +

On-target editing (`r target_gene_symbol`)

- - - - - - - - - - + + + + + + + + + +
Indel frequencyTransgene integrationsCoding Sequence Variants
Indel Frequency`r knitr::asis_output(circos_html)``r knitr::asis_output(sv_table_html)`
Indel frequencyTransgene integrationsCoding Sequence Variants
+```{r} +#| echo: false +#| results: "asis" +#| out.extra: 'class="equal-size-img"' +if (file.exists("indel_freq.png")) { + knitr::include_graphics("indel_freq.png") +} else { + cat('
Indel Frequency not available
') +} +``` +
+```{r} +#| echo: false +#| results: "asis" +#| out.extra: 'class="equal-size-img"' +if (!is.null(circos_file)) { + # Use standard markdown image syntax instead of knitr::include_graphics to avoid potential display issues + cat(paste0('

')) + cat('

All Transgene Integrations

') +} else { + cat('
Circos Plot not available
') +} +``` +
`r knitr::asis_output(sv_table_html)`
+

Off-target mutations (`r nrow(as.data.frame(report_data$tables$off_target_indels))` sites screened)

+ - - - - - - - + + + + + +
Off target sitesOff-target sites > `r off_target_threshold_value`% indel frequency
Sample Image +
Off target sitesOff-target sites > `r off_target_threshold_value`% indel frequency
+```{r} +#| echo: false +#| results: "asis" +#| out.extra: 'class="equal-size-img"' +if (file.exists("off_targets.png")) { + knitr::include_graphics("off_targets.png") +} else { + cat('
Off Target Sites not available
') +} +``` +
```{r} #| echo: false #| results: 'asis' off_target_df <- as.data.frame(report_data$tables$off_target_indels) if (is.data.frame(off_target_df) && nrow(off_target_df) > 0) { - is_target_col_name <- if("is_target" %in% colnames(off_target_df)) "is_target" else "is_target_site" - - if(is_target_col_name %in% colnames(off_target_df)) { - off_target_df[[is_target_col_name]] <- as.character(off_target_df[[is_target_col_name]]) + if("is_target" %in% colnames(off_target_df)) { + off_target_df$is_target <- as.character(off_target_df$is_target) } else { - off_target_df[[is_target_col_name]] <- '0' - } - - on_target_sites <- off_target_df[off_target_df[[is_target_col_name]] == '1', ] - potential_off_targets <- off_target_df[off_target_df[[is_target_col_name]] == '0', ] - - is_proximal_to_on_target <- function(chrom, start, on_targets) { - if(nrow(on_targets) == 0) return(FALSE) - same_chrom_on_targets <- on_targets[on_targets$chrom == chrom, ] - if(nrow(same_chrom_on_targets) == 0) return(FALSE) - min_dist <- min(abs(as.numeric(same_chrom_on_targets$start) - as.numeric(start))) - return(min_dist <= 3) - } - - if (nrow(potential_off_targets) > 0 && nrow(on_target_sites) > 0) { - proximal_mask <- mapply(is_proximal_to_on_target, - potential_off_targets$chrom, - potential_off_targets$start, - MoreArgs = list(on_targets = on_target_sites)) - true_off_targets <- potential_off_targets[!proximal_mask, ] - } else { - true_off_targets <- potential_off_targets + off_target_df$is_target <- '0' } - off_target_filtered <- true_off_targets[ - as.numeric(true_off_targets$indel_fraction) * 100 > as.numeric(params$off_target_threshold), + potential_off_targets <- off_target_df[off_target_df$is_target == '0', ] + + # Filter by threshold + off_target_filtered <- potential_off_targets[ + as.numeric(potential_off_targets$indel_fraction) * 100 > off_target_threshold_value, ] if(nrow(off_target_filtered) > 0){ - cat('') - cat("") + cat('
Genome Coordinate% IndelsAnnotation
\n') + cat("\n") for(i in 1:nrow(off_target_filtered)){ coord <- paste0(off_target_filtered[i, "chrom"], ":", off_target_filtered[i, "start"]) indels <- paste0(round(as.numeric(off_target_filtered[i, "indel_fraction"]) * 100, 1), "%") - annotation <- off_target_filtered[i, "Annotation"] - cat(paste0("")) + + raw_annotation <- off_target_filtered[i, "target_info"] + annotation <- raw_annotation + + # Parse Annotation + if (!is.na(raw_annotation) && raw_annotation != "" && raw_annotation != ".") { + parts <- strsplit(raw_annotation, ";")[[1]] + csq_part <- parts[grep("^CSQ=", parts)] + if(length(csq_part) > 0) { + csq_val <- sub("^CSQ=", "", csq_part[1]) + transcripts <- strsplit(csq_val, ",")[[1]] + t1 <- transcripts[1] + fields <- strsplit(t1, "\\|")[[1]] + # Assuming SYMBOL|Gene|Consequence|... based on observed VEP output + # ANNOTATE_OFFTARGETS specifies --fields "SYMBOL,Gene,Consequence,..." + # We found index 1 is Symbol, index 2 is Gene ID, index 3 is Consequence + if (length(fields) >= 3) { + gene_sym <- fields[1] + cons <- fields[3] + if (gene_sym == "") gene_sym <- fields[2] + if (gene_sym == "") gene_sym <- "N/A" + # Replace '&' with '
' in consequence string for better readability + cons <- gsub("&", "
", cons) + annotation <- paste0("Gene: ", gene_sym, "
Consequence: ", cons) + } + } + } + + cat(paste0("\n")) } - cat("
Genome Coordinate% IndelsAnnotation
", coord, "", indels, "", annotation, "
", coord, "", indels, "", annotation, "
") + cat("
\n") } else { - cat(paste0("

No off-target sites with > ", off_target_threshold_value, "% indel frequency found.

")) + cat(paste0("

No off-target sites with > ", off_target_threshold_value, "% indel frequency found.

\n")) } } else { - cat(paste0("

No off-target sites with > ", off_target_threshold_value, "% indel frequency found.

")) + cat(paste0("

No off-target sites with > ", off_target_threshold_value, "% indel frequency found.

\n")) } ``` - + +
- - - - - - - - - - - -

Genome integrity and gene mutation analysis

Genome-wide copy number analysisTargeted gene mutation analysis
- `r knitr::asis_output(cna_plot_html)` - `r knitr::asis_output(baf_plot_html)` - - - - - - - `r knitr::asis_output(targeted_gene_mutations_html)` -
GeneResult
-
- + +

Genome integrity and gene mutation analysis

+ + +Genome-wide copy number analysis +Targeted gene mutation analysis + + + +```{r} +#| echo: false +#| results: "asis" +#| out.extra: 'class="equal-size-img"' +if (!is.null(cna_file)) { + knitr::include_graphics(cna_file) +} else { + cat('
CNA Plot not available
') +} +if (!is.null(baf_file)) { + knitr::include_graphics(baf_file) +} else { + cat('
BAF Plot not available
') +} +``` + + + + + + + +`r knitr::asis_output(rows_html)` +
GeneResult
+ + + diff --git a/bin/noise_model.py b/bin/noise_model.py new file mode 100644 index 0000000..7cf48f3 --- /dev/null +++ b/bin/noise_model.py @@ -0,0 +1,434 @@ +#!/usr/bin/env python3 +""" +noise_model.py — score off-target calls against a probabilistic noise baseline. + +Why this exists +--------------- +`review_filter.py` treats every noise source as a boolean: rule 4 asks "is this site in the panel +of normals?", rule 6 asks "does this site touch the DRAGEN systematic-noise panel?". A boolean is +the wrong shape for the question. A site can carry 1% background in the controls and 40% signal in +the treated sample; existence-based filtering throws that edit away, and the measured cost is real +(a bare panel-interval hit flags 33.1% of artifacts but also 1.2% of genuine on-target edits). + +This script replaces existence with expectation. For a call with `k` indel reads out of `n`, it +asks how surprising `k` is under a per-locus background model, and reports the answer Phred-scaled: + + AQ = -10 log10 P(X >= k | n, background at this locus) + +High AQ = the observation cannot be explained by background = keep. Low AQ = indistinguishable from +this locus's known noise = drop. + +Why beta-binomial and not binomial +---------------------------------- +The noise is overdispersed, and demonstrably so: 61.3% of loci in the DRAGEN IDPF panel are flagged +in exactly ONE panel sample. A point-`p` binomial assumes every sample sees the same error rate, so +at a locus where 1 of 46 samples showed 17% and the other 45 showed nothing, it uses p = 0.0037 and +declares a 5% observation overwhelmingly significant. The beta-binomial carries the spread as well +as the mean, which is the only reason the tail probability means anything -- and the tail is the +entire output. + +Baselines (--baseline) +---------------------- + matched global prior + THIS sample's own matched control at the locus. Replaces rule 1: + a germline het sits near VAF 0.5 in the matched control, so a 0.5 observation in the + treated sample is unsurprising and scores low without a separate germline rule. + loo global prior + the OTHER samples' controls at the locus (leave-one-out). Replaces + rule 4: this is cohort recurrence expressed as a rate rather than a blacklist. + both both sets pooled. + panel the external DRAGEN panel, no controls at all -- the single-sample case. Combined + with --panel-p below. + +Empirical Bayes, which is also how the "no data here" case is handled +--------------------------------------------------------------------- +A Beta(a0, b0) prior is fitted once by method of moments over every control observation in the +input, then updated per locus: a = a0 + (control alt reads), b = b0 + (control ref reads). The +predictive distribution for a new sample is BetaBinom(n, a, b). + +This is what makes the floor principled rather than arbitrary. ~97% of genomic positions are absent +from the DRAGEN panel (it covers 3.16% of the genome), and a missing locus is NOT p=0 -- that would +make every observation infinitely significant. Here an unobserved locus simply keeps the global +prior, which is the honest statement that we know nothing beyond the assay-wide error rate. + +--panel-p, and why 'mean' is wrong +----------------------------------- +The panel's MEAN column is diluted by the whole panel: verified MAX/MEAN = 45.99 at NR=1, exactly +the 46-sample panel size, so MEAN = (sum of VAFs) / N_panel and includes the ~45 samples that showed +nothing. Using it as the background rate understates the rate an AFFECTED sample sees by up to N/NR. + mean p = MEAN (anti-conservative; provided for comparison) + max p = MAX (an order statistic over N draws; conservative) + corrected p = MEAN * N / NR (mean rate among the samples that actually showed noise) +N is read from the panel's own `##PON SAMPLES:` header. + +usage: + noise_model.py IN.tsv [IN2.tsv ...] -o scored.tsv --baseline loo + noise_model.py IN.tsv ... -o scored.tsv --baseline panel \ + --snv-noise IDPF_WGS_hg38_v.2.0.0_systematic_noise.snv.bed.gz --panel-p corrected +""" +import argparse +import collections +import glob +import gzip +import os +import sys + +import numpy as np +import pandas as pd +from scipy.stats import betabinom, binom + +SNV_NOISE_SLOP = 2 +# Floor on the prior mean. Without it a cohort with pristine controls yields a0/(a0+b0) ~ 0 and +# every call becomes infinitely significant -- the same failure as p=0 for an absent locus. +MIN_PRIOR_MEAN = 1e-5 + + +def sample_name_of(path): + return os.path.basename(path).split(".")[0] + + +def load_tables(paths): + frames = [] + for p in paths: + df = pd.read_csv(p, sep="\t") + df["sample_name"] = sample_name_of(p) + frames.append(df) + df = pd.concat(frames, ignore_index=True) + for c in ("total_reads", "indel_reads", "control_reads", "control_indel_reads"): + df[c] = pd.to_numeric(df[c], errors="coerce").fillna(0) + return df + + +def fit_global_prior(alt, depth): + """Method-of-moments Beta prior over per-observation control VAFs. + + Only observations with depth > 0 carry information. The variance is taken across observations, + so it absorbs both sampling noise and true locus-to-locus rate variation -- which is what we + want the prior to express. + """ + ok = depth > 0 + if ok.sum() < 2: + return 0.5, 500.0 + vaf = alt[ok] / depth[ok] + m = float(np.mean(vaf)) + v = float(np.var(vaf, ddof=1)) + m = max(m, MIN_PRIOR_MEAN) + if v <= 0 or v >= m * (1 - m): + # degenerate: fall back to a weakly-informative prior centred on the observed mean + return m * 100.0, (1 - m) * 100.0 + k = m * (1 - m) / v - 1 + return max(m * k, 1e-6), max((1 - m) * k, 1e-6) + + +def locus_control_support(df): + """(chrom, end) -> [(sample, control_alt, control_depth), ...]""" + d = collections.defaultdict(list) + for s, c, e, a, n in zip(df.sample_name, df.chrom, df.end, + df.control_indel_reads, df.control_reads): + d[(c, int(e))].append((s, float(a), float(n))) + return d + + +def load_panel(path, positions, slop=SNV_NOISE_SLOP): + """DRAGEN SNV panel -> {(chrom,pos): (mean, max, alleles, nr)} plus the panel sample count. + + Streams the file; only queried positions are retained. The `##PON SAMPLES:` header gives N, + which --panel-p corrected needs to undo the MEAN dilution. + """ + want = collections.defaultdict(set) + for c, e in positions: + for d in range(-slop, slop + 1): + want[c].add(int(e) + d) + hits, n_panel = {}, None + op = gzip.open if path.endswith(".gz") else open + with op(path, "rt") as f: + for line in f: + if line[0] == "#": + if line.startswith("##PON SAMPLES:"): + n_panel = len([x for x in line.split(":", 1)[1].split(",") if x.strip()]) + continue + p = line.rstrip("\n").split("\t") + if len(p) < 7: + continue + s = want.get(p[0]) + if s is None: + continue + try: + pos = int(p[2]) + if pos not in s: + continue + rec = (float(p[3]), float(p[4]), p[5], int(p[6])) + except ValueError: + continue + prev = hits.get((p[0], pos)) + if prev is None or rec[3] > prev[3]: + hits[(p[0], pos)] = rec + return hits, (n_panel or 46) + + +def panel_rate(hits, chrom, end, n_panel, mode, floor_p, slop=SNV_NOISE_SLOP): + """Background rate at one locus from the panel, or the floor when the panel says nothing. + + Only indel-capable records count: a locus that is noisy for substitutions says nothing about + an indel call at the same coordinate. + """ + best = None + for d in range(-slop, slop + 1): + rec = hits.get((chrom, int(end) + d)) + if rec and ("D" in rec[2] or "I" in rec[2]): + if best is None or rec[3] > best[3]: + best = rec + if best is None: + return floor_p, 0 + mean, mx, _alleles, nr = best + if mode == "mean": + p = mean + elif mode == "max": + p = mx + else: + p = mean * n_panel / max(nr, 1) + return min(max(p, floor_p), 0.999), nr + + +def control_posterior(df, q, baseline, a0, b0): + """Per-row Beta posterior over the background rate, from control observations. + + Returns (alpha, beta, n_observations, pooled_control_depth). The depth is returned because + it bounds how much the posterior is entitled to claim -- see apply_depth_floor. + """ + support = locus_control_support(df) + alpha = np.full(len(q), a0, dtype=float) + beta = np.full(len(q), b0, dtype=float) + nsup = np.zeros(len(q), dtype=int) + dep_out = np.zeros(len(q), dtype=float) + for i, (s, c, e) in enumerate(zip(q.sample_name, q.chrom, q.end)): + alt = dep = 0.0 + cnt = 0 + for samp, ca, cn in support.get((c, int(e)), ()): + if cn <= 0: + continue + if baseline == "matched" and samp != s: + continue + if baseline == "loo" and samp == s: + continue + alt += ca; dep += cn; cnt += 1 + alpha[i] = a0 + alt + beta[i] = b0 + max(dep - alt, 0.0) + nsup[i] = cnt + dep_out[i] = dep + return alpha, beta, nsup, dep_out + + +def apply_depth_floor(alpha, beta, control_depth): + """Stop the posterior claiming more resolution than the control actually has. + + A control with zero alt reads at depth d does NOT show the background is ~0. It shows the + background is below roughly 1/d, and nothing more. Left alone the posterior says otherwise: + with alpha = a0 and beta = b0 + d, the mean collapses to a0/(a0+d) -- on this cohort 3.5e-5 + against a 170x control, about 70x below the fitted prior and ~100x below what 170 reads can + support. That is the classic clean-control trap, and it inflates AQ for every call at a locus + the control simply never sampled deeply enough to speak about. + + So floor the posterior MEAN at 1/control_depth, holding the concentration (alpha+beta) fixed + so only the location moves and the strength of belief is preserved. Rows with no control depth + are left on the global prior -- there is no depth to derive a floor from. + + Today the VAF>=0.005 gate hides this (only 2 gated rows sit below a 170x control's 0.59% + resolution). It stops being hidden the moment anyone lowers the gate for a high-sensitivity run. + """ + alpha = np.asarray(alpha, dtype=float).copy() + beta = np.asarray(beta, dtype=float).copy() + depth = np.asarray(control_depth, dtype=float) + conc = alpha + beta + mean = alpha / conc + has_depth = depth > 0 + floor = np.where(has_depth, 1.0 / np.maximum(depth, 1.0), 0.0) + lift = has_depth & (mean < floor) + alpha[lift] = floor[lift] * conc[lift] + beta[lift] = conc[lift] - alpha[lift] + return alpha, beta, int(lift.sum()) + + +def aq_from_sf(sf): + """Phred-scale a survival probability, capped so log10(0) does not become inf.""" + sf = np.clip(np.asarray(sf, dtype=float), 1e-300, 1.0) + return -10.0 * np.log10(sf) + + +# --------------------------------------------------------------------------------------------- +# Truth. Two sources, deliberately kept separate because they answer different questions. +# --------------------------------------------------------------------------------------------- +GUIDE_ALIAS = {"CTLA41": "CTLA4"} +CHROM_REPAIR = {"c": "chr5"} # one corrupted cell in CART_NS0011-CREBRF (chr5q35.1) +CONFIRMED = {"1", "1.0", "1?"} +# The WGS review adjudicated every row inside this stratum by eye, so a blank manual_review +# there means REJECTED. Outside it, blank means unreviewed and the row carries no label. +WGS_STRATUM_IF, WGS_STRATUM_READS = 0.05, 10 + + +def guide_of(name): + """Pipeline sample or review-sheet name -> guide. + + `CART_NS0011-ABTB1` -> ABTB1, `CART_NS0027-CTLA41_2` -> CTLA4, `ABTB1-KO-DNA` -> ABTB1, + `ATF7IP-KO-CART-DNA` -> ATF7IP. + """ + s = str(name) + import re + if re.match(r"^(CART_)?NS\d+-", s): + g = s.split("-", 1)[1] + else: + g = s.split("-", 1)[0] + g = re.sub(r"_\d+$", "", g) + return GUIDE_ALIAS.get(g, g) + + +def wgs_curated_label(xlsx, sheet="gold_wgs"): + """(guide, chrom, start) -> 1 confirmed / 0 human-rejected, inside the reviewed stratum only.""" + g = pd.read_excel(xlsx, sheet_name=sheet) + iff = pd.to_numeric(g.indel_fraction, errors="coerce") + ir = pd.to_numeric(g.indel_reads, errors="coerce") + strat = (iff >= WGS_STRATUM_IF) & (ir >= WGS_STRATUM_READS) + conf = g["manual_review"].astype(str).str.strip().isin(CONFIRMED) + r = g[strat].copy() + r["curated_label"] = conf[strat].astype(int) + r["guide"] = r["sample_name"].map(guide_of) + r["chrom"] = r["chrom"].astype(str).replace(CHROM_REPAIR) + return r.groupby(["guide", "chrom", "start"], as_index=False)["curated_label"].max() + + +def ecs_confirmed(csv): + """(guide, chrom, start) for edits a human confirmed in the ECS assay. + + Positives only -- NaN in that table means NOT REVIEWED, not rejected -- so this supports + recall and nothing else. Its value is reach: ECS runs at ~1,960x, so it confirms edits well + below the 5% floor of the WGS review. + """ + g = pd.read_csv(csv, low_memory=False) + g = g[g["manual_review"].astype(str).str.strip().isin(CONFIRMED)].copy() + g["guide"] = g["sample_name"].map(guide_of) + g["chrom"] = g["chrom"].astype(str).replace(CHROM_REPAIR) + g["ecs_vaf"] = pd.to_numeric(g["indel_fraction"], errors="coerce") + return g[["guide", "chrom", "start", "ecs_vaf"]].drop_duplicates(["guide", "chrom", "start"]) + + +def evaluate(q, truth_wgs, truth_ecs): + q = q.copy() + q["guide"] = q.sample_name.map(guide_of) + q["chrom"] = q.chrom.astype(str) + + if truth_wgs: + lab = wgs_curated_label(truth_wgs) + m = q.merge(lab, on=["guide", "chrom", "start"], how="inner") + pos, neg = m[m.curated_label == 1], m[m.curated_label == 0] + print(f"\n== curated WGS label (two-class, VAF>=5% stratum) ==") + print(f"joined {len(m)} scored rows: {len(pos)} confirmed / {len(neg)} human-rejected") + if len(pos) and len(neg): + from sklearn.metrics import roc_auc_score, average_precision_score + y, s = m.curated_label.values, m.AQ.values + print(f"AUC {roc_auc_score(y, s):.3f} AP {average_precision_score(y, s):.3f}") + print(f"AQ confirmed: median {pos.AQ.median():.1f} min {pos.AQ.min():.1f}") + print(f"AQ rejected : median {neg.AQ.median():.1f} max {neg.AQ.max():.1f}") + for thr in (10, 20, 30, 60): + tp = int((pos.AQ >= thr).sum()); fp = int((neg.AQ >= thr).sum()) + prec = tp / (tp + fp) if tp + fp else float("nan") + print(f" AQ>={thr:<3d} recall {tp}/{len(pos)} = {tp/len(pos):.3f}" + f" precision {prec:.3f} (FP {fp})") + + if truth_ecs: + e = ecs_confirmed(truth_ecs) + m = q.merge(e, on=["guide", "chrom", "start"], how="inner") + sub = m[m.ecs_vaf < 0.05] + print(f"\n== ECS-confirmed edits (recall only; positives-only truth) ==") + print(f"joined {len(m)} confirmed edits, {len(sub)} of them below 5% ECS VAF") + for thr in (10, 20, 30, 60): + print(f" AQ>={thr:<3d} all {int((m.AQ>=thr).sum())}/{len(m)}" + + (f" sub-5% {int((sub.AQ>=thr).sum())}/{len(sub)}" if len(sub) else "")) + if len(sub): + print(" sub-5% edits (ECS VAF -> WGS AQ): " + + ", ".join(f"{v:.3f}->{aq:.1f}" for v, aq in zip(sub.ecs_vaf, sub.AQ))) + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("inputs", nargs="+", help="*.offtarget_analysis.tsv") + ap.add_argument("-o", "--out", required=True) + ap.add_argument("--baseline", default="loo", choices=["matched", "loo", "both", "panel"]) + ap.add_argument("--snv-noise", metavar="BED", help="DRAGEN SNV panel (--baseline panel)") + ap.add_argument("--panel-p", default="corrected", choices=["mean", "max", "corrected"]) + ap.add_argument("--floor-p", type=float, default=1e-3, + help="background rate for loci the panel does not mention (default 1e-3). " + "~97%% of positions are absent from the panel, so this governs most sites") + ap.add_argument("--min-reads", type=int, default=2) + ap.add_argument("--min-vaf", type=float, default=0.005) + ap.add_argument("--no-depth-floor", dest="depth_floor", action="store_false", + help="disable the 1/control_depth floor on the posterior background. The " + "floor is on by default; turning it off restores the clean-control trap " + "and is provided only to measure its effect") + ap.add_argument("--truth-wgs", metavar="XLSX", + help="cart_wgs_merged.xlsx -- two-class curated label, VAF>=5% stratum only") + ap.add_argument("--truth-ecs", metavar="CSV", + help="cart_ecs_merged.csv.gz -- confirmed edits incl. sub-5%% (recall only)") + a = ap.parse_args() + + paths = [] + for p in a.inputs: + paths.extend(sorted(glob.glob(p)) if any(ch in p for ch in "*?[") else [p]) + df = load_tables(paths) + n_in = len(df) + + vaf = df.indel_reads / df.total_reads.replace(0, np.nan) + q = df[(df.indel_reads >= a.min_reads) & (vaf.fillna(0) >= a.min_vaf)].copy().reset_index(drop=True) + print(f"input rows : {n_in}") + print(f"cleared the gate : {len(q)} (reads>={a.min_reads}, VAF>={a.min_vaf})") + + a0, b0 = fit_global_prior(df.control_indel_reads.values, df.control_reads.values) + print(f"global prior : Beta(a={a0:.4g}, b={b0:.4g}) mean={a0/(a0+b0):.6f}") + + k = q.indel_reads.values.astype(int) + n = q.total_reads.values.astype(int) + + if a.baseline == "panel": + if not a.snv_noise: + sys.exit("ERROR: --baseline panel requires --snv-noise") + hits, n_panel = load_panel(a.snv_noise, set(zip(q.chrom, q.end))) + print(f"panel : {len(hits)} records at queried positions, N={n_panel}") + ps, nrs = [], [] + for c, e in zip(q.chrom, q.end): + p, nr = panel_rate(hits, c, e, n_panel, a.panel_p, a.floor_p) + ps.append(p); nrs.append(nr) + ps = np.asarray(ps) + q["bg_rate"] = ps + q["panel_nr"] = nrs + q["from_panel"] = np.asarray(nrs) > 0 + # a point rate is all the panel gives, so this arm is an honest binomial + q["AQ"] = aq_from_sf(binom.sf(k - 1, n, ps)) + print(f"loci with panel support: {int(q.from_panel.sum())} / {len(q)} " + f"({q.from_panel.mean()*100:.1f}%) -- the rest use --floor-p {a.floor_p}") + else: + alpha, beta, nsup, dep = control_posterior(df, q, a.baseline, a0, b0) + if a.depth_floor: + alpha, beta, n_floored = apply_depth_floor(alpha, beta, dep) + print(f"depth floor : raised background on {n_floored} rows " + f"({n_floored/len(q)*100:.1f}%) to 1/control_depth") + q["bg_rate"] = alpha / (alpha + beta) + q["n_control_obs"] = nsup + q["control_depth"] = dep + q["AQ"] = aq_from_sf(betabinom.sf(k - 1, n, alpha, beta)) + print(f"control observations : median {int(np.median(nsup))} per locus " + f"({int((nsup == 0).sum())} loci with none -> global prior)") + + q["AQ"] = q["AQ"].round(2) + q["bg_rate"] = q["bg_rate"].round(6) + q.to_csv(a.out, sep="\t", index=False) + + for thr in (10, 20, 30, 60): + n_pass = int((q.AQ >= thr).sum()) + print(f" AQ >= {thr:<3d} : {n_pass:5d} rows kept " + f"(chance FPs at {len(q)} tests: {len(q) * 10 ** (-thr / 10):.1f})") + print(f"scored {len(q)} rows -> {a.out}") + + if a.truth_wgs or a.truth_ecs: + evaluate(q, a.truth_wgs, a.truth_ecs) + + +if __name__ == "__main__": + main() diff --git a/bin/noise_model_followup.py b/bin/noise_model_followup.py new file mode 100755 index 0000000..09700bb --- /dev/null +++ b/bin/noise_model_followup.py @@ -0,0 +1,264 @@ +#!/usr/bin/env python3 +"""noise_model_followup.py — chase the two findings that looked like defects in the prior. + +`noise_model_validate.py` reported two results that pointed at the model itself rather than at how +it is described: + + clean-locus under-prediction the coldest bin of the leave-one-donor-out reliability diagram + under-predicts observed alt reads by 11.7x, CI excluding 1. + assumption 8 scoring EDITED counts against the matched control at no-edit loci + gives KS D = 0.0343, ~7x the control-vs-control figure. + +Both dissolve on inspection, in different ways, and this script is what shows that. It is analysis +only: it imports the shipped model, changes nothing, and the pipeline does not call it. + + --part clean the reliability finding. Isolates the cold bins and tests four explanations that + make different, checkable predictions: donor-private germline, sequence context, + a few pathological loci, and a prior tail that is simply too thin. + --part a8 the assumption-8 finding. Stratifies the same rows by whether the caller reported + an event at that site, because conditioning on "an indel was called here" forces + k >= 1 and makes the p-value a spike rather than a distribution. + +The short version of both: the reliability finding is five loci carrying donor-private alleles the +caller had already suppressed, and the assumption-8 finding is a selection effect from pooling the +3% of rows that carry a called event into the 97% that do not. Neither is a defect in the prior. +See docs/NOISE_MODEL_ASSUMPTIONS.md, "Follow-up". + +usage: + noise_model_followup.py --tables 'results_cart_bnd/*/*.offtarget_analysis.tsv' \ + --fasta .../hg38_PLVM_CD19_CARv4_cd34.fa --part both +""" +import argparse +import collections +import glob +import os +import sys + +import numpy as np +import pandas as pd +from scipy.stats import betabinom, chi2, kstest + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import noise_model as nm # noqa: E402 +from noise_model_validate import BetaBinomMOM, homopolymer_len # noqa: E402 + +# The gate a row must clear before it can be a call at all. Rows below it are background by +# construction, so they bound how much of any miscalibration could be genuine off-target editing. +GATE_READS, GATE_VAF = 2, 0.005 +GERMLINE_VAF = 0.35 # a real heterozygote sits near 0.5; this is the generous edge of it +HP_SLIPPERY = 7 # homopolymer length at which slippage starts to dominate + + +def poisson_ci(k, conf=0.95): + """Exact (Garwood) interval on a Poisson count, so bins built on a few events say so.""" + a = 1 - conf + lo = 0.0 if k == 0 else chi2.ppf(a / 2, 2 * k) / 2 + return lo, chi2.ppf(1 - a / 2, 2 * (k + 1)) / 2 + + +def load(tables): + df = nm.load_tables(sorted(glob.glob(tables))) + d = df[df.control_reads > 0].copy() + d["control_indel_reads"] = np.minimum(d.control_indel_reads, d.control_reads) + return df, d + + +# ================================================================================================= +# Part 1 — the clean-locus under-prediction +# ================================================================================================= + +def part_clean(df, d, fasta_path): + shipped = BetaBinomMOM() + shipped.fit(d.control_indel_reads.values.astype(float), + d.control_reads.values.astype(float)) + print(f"prior Beta({shipped.a:.6g}, {shipped.b:.6g})") + + # Rebuild the reliability design: predict each donor from the OTHER donors at that locus. + obs = collections.defaultdict(list) + for c, e, s, kk, nn in zip(d.chrom.astype(str), d.end.astype(int), d.sample_name.astype(str), + d.control_indel_reads.values.astype(float), + d.control_reads.values.astype(float)): + obs[(c, int(e))].append((s, kk, nn)) + multi = {key: v for key, v in obs.items() if len(v) >= 2} + rows = [] + for (c, e), o in multi.items(): + tot_k, tot_n = sum(x[1] for x in o), sum(x[2] for x in o) + for s, kk, nn in o: + al, be = shipped.posterior(tot_k - kk, tot_n - nn) + rows.append((c, e, s, kk, nn, nn * al / (al + be))) + r = pd.DataFrame(rows, columns=["chrom", "pos", "sample", "k", "n", "exp"]) + r["vaf"] = r.k / r.n + print(f"loci with >=2 donors {len(multi)} observations {len(r)}") + print(f"aggregate: predicted {r.exp.sum():,.1f} observed {r.k.sum():,.0f} " + f"ratio {r.k.sum()/r.exp.sum():.3f}") + + cold = r[r.exp < 3e-3].copy() # the two under-predicting bins + excess = cold.k.sum() - cold.exp.sum() + print(f"\ncold bins (expected < 3e-3): {len(cold):,} observations, " + f"{int((cold.k >= 1).sum())} carry any alt read, " + f"excess {excess:,.1f} reads over {cold.exp.sum():,.1f} predicted") + + print("\n-- is it concentrated? --") + per = (cold.groupby(["chrom", "pos"]) + .agg(k=("k", "sum"), exp=("exp", "sum"), nobs=("k", "size")) + .assign(exc=lambda x: x.k - x.exp).sort_values("exc", ascending=False)) + tot_exc = per.exc[per.exc > 0].sum() + for cut in (1, 5, 10, 25): + print(f" top {cut:3d} loci of {len(per):,}: " + f"{per.exc.head(cut).sum()/max(tot_exc, 1)*100:5.1f}% of the positive excess") + + # Did the caller already know about these? n_control_filtered counts the events it dropped + # at -x 0 because the control supported them -- i.e. the ones it called germline. + nc = pd.to_numeric(df.get("n_control_filtered"), errors="coerce").fillna(0) + key = df.chrom.astype(str) + ":" + df.end.astype(int).astype(str) + "|" + df.sample_name.astype(str) + supp = dict(zip(key, nc)) + print(f"\n {'locus':<22} {'donor':<24} {'pred':>7} {'alt':>5} {'VAF':>6} {'suppressed':>11}") + for (c, p), row in per.head(5).iterrows(): + g = cold[(cold.chrom == c) & (cold.pos == p)].sort_values("k", ascending=False).iloc[0] + print(f" {c + ':' + format(int(p), ','):<22} {g['sample']:<24} {row.exp:7.3f} " + f"{int(row.k):5d} {g.vaf:6.3f} " + f"{int(supp.get(f'{c}:{int(p)}|' + g['sample'], 0)):11d}") + + print("\n-- the association, cohort-wide --") + dd = df[(df.control_reads > 0) & (df.total_reads > 0)] + if "is_target" in dd.columns: + dd = dd[dd.is_target == 0] + ncd = pd.to_numeric(dd.get("n_control_filtered"), errors="coerce").fillna(0) + cv = np.minimum(dd.control_indel_reads, dd.control_reads) / dd.control_reads + ev = dd.indel_reads / dd.total_reads + orph = (cv >= 0.05) & (ev < 0.01) + print(f" rows with control VAF >=5% and a near-empty edited library: {int(orph.sum())}") + print(f" with n_control_filtered > 0 : {(ncd[orph] > 0).mean()*100:.1f}%") + print(f" the same figure elsewhere : {(ncd[~orph] > 0).mean()*100:.2f}%") + print(" A real donor variant is in BOTH libraries; the edited count reads 0 because the") + print(" caller dropped the event at -x 0, not because the allele is absent.") + + print("\n-- the competing explanations --") + hits = cold[cold.k >= 1] + germ = hits[hits.vaf >= GERMLINE_VAF] + print(f" germline at VAF >= {GERMLINE_VAF}: {len(germ)} observations, " + f"{germ.k.sum():.0f} alt reads ({germ.k.sum()/max(excess,1)*100:.1f}% of the excess)") + try: + import pysam + fa = pysam.FastaFile(fasta_path) + except Exception as exc: # pragma: no cover + print(f" context: fasta unavailable ({exc}); skipped") + cold["hp"] = 0 + else: + sites = cold[["chrom", "pos"]].drop_duplicates() + hp = {(c, int(p)): homopolymer_len(fa, c, int(p)) + for c, p in zip(sites.chrom, sites.pos)} + cold["hp"] = [hp[(c, int(p))] for c, p in zip(cold.chrom, cold.pos)] + for lo, hi, lab in ((0, 5, "<5 bp"), (5, 7, "5-6 bp"), (7, 9, "7-8 bp"), (9, 999, ">=9 bp")): + g = cold[(cold.hp >= lo) & (cold.hp < hi)] + if not len(g) or g.exp.sum() <= 0: + continue + print(f" homopolymer {lab:>7}: {len(g):6d} obs, " + f"{(g.k.sum()-g.exp.sum())/max(excess,1)*100:5.1f}% of the excess") + + print("\n-- what is left once all three are removed --") + worst = set(per.head(10).index.tolist()) + keep = cold[(cold.vaf < GERMLINE_VAF) & (cold.hp < HP_SLIPPERY)] + keep = keep[[(c, int(p)) not in worst for c, p in zip(keep.chrom, keep.pos)]] + pe, po = keep.exp.sum(), keep.k.sum() + lo, hi = poisson_ci(int(po)) + print(f" {len(keep):,} observations, predicted {pe:.2f}, observed {po:.0f}, " + f"ratio {po/max(pe,1e-9):.2f} 95% CI [{lo/max(pe,1e-9):.2f}, {hi/max(pe,1e-9):.2f}]") + print(" At genuinely clean loci the model OVER-predicts. The prior's left tail is not too") + print(" thin; the 11.7x was five loci carrying alleles the caller had already suppressed.") + + +# ================================================================================================= +# Part 2 — assumption 8, stratified +# ================================================================================================= + +def part_a8(df, d, seed=0): + a0, b0 = nm.fit_global_prior(df.control_indel_reads.values, df.control_reads.values) + print(f"prior Beta({a0:.6g}, {b0:.6g})") + + e = df[(df.control_reads > 0) & (df.total_reads > 0)].copy() + if "is_target" in e.columns: + e = e[e.is_target == 0] + e["control_indel_reads"] = np.minimum(e.control_indel_reads, e.control_reads) + ic = pd.to_numeric(e.indel_count, errors="coerce").fillna(0).values + nc = pd.to_numeric(e.get("n_control_filtered"), errors="coerce").fillna(0).values + ca = e.control_indel_reads.values.astype(float) + cn = e.control_reads.values.astype(float) + ek = e.indel_reads.values.astype(int) + en = e.total_reads.values.astype(int) + print(f"no-target rows with depth in both libraries: {len(e):,}") + + def score(al, be): + rng = np.random.default_rng(seed) + return np.clip(betabinom.sf(ek, en, al, be) + + rng.random(len(ek)) * betabinom.pmf(ek, en, al, be), 0.0, 1.0) + + for floor_on in (False, True): + al, be = a0 + ca, b0 + np.maximum(cn - ca, 0.0) + lift = 0 + if floor_on: + al, be, lift = nm.apply_depth_floor(al, be, cn) + pv = score(al, be) + fin = np.isfinite(pv) + head = "WITH depth floor (production)" if floor_on else "RAW posterior (the model)" + print(f"\n-- {head} --" + (f" floor raised {lift:,}" if floor_on else "")) + print(f" {'population':<34} {'n':>7} {'KS D':>8} {'p<0.001':>10} {'excess':>8} {'obs/pred':>9}") + pops = [("pooled (as first reported)", fin), + ("indel_count == 0 no event called", fin & (ic == 0)), + ("indel_count == 1 one event", fin & (ic == 1)), + ("indel_count >= 2", fin & (ic >= 2)), + ("germline-suppressed removed", fin & (nc == 0))] + for lab, m in pops: + q = pv[m] + if not len(q): + continue + frac = (q < 0.001).mean() + pred = float((en * (al / (al + be)))[m].sum()) + print(f" {lab:<34} {len(q):7d} {kstest(q, 'uniform').statistic:8.4f} " + f"{frac:10.5f} {frac/0.001:7.1f}x {ek[m].sum()/max(pred,1e-9):9.3f}") + + al, be = a0 + ca, b0 + np.maximum(cn - ca, 0.0) + pv = score(al, be) + print("\n-- why indel_count >= 1 cannot be read as a calibration failure --") + m1 = ic == 1 + print(f" indel_count == 1 rows: {int(m1.sum()):,} share with k >= 1: " + f"{(ek[m1] >= 1).mean():.3f} (1.000 means selected on the outcome)") + print(f" their p-values: median {np.median(pv[m1]):.5g}, " + f"{(pv[m1] < 0.01).mean()*100:.1f}% below 0.01 — a spike at one value, not a spread") + + print("\n-- the stratum where the assumption CAN be tested --") + m0 = ic == 0 + print(f" {'threshold':>12} {'observed':>10} {'uniform':>10}") + for t in (0.5, 0.05, 0.01, 0.001): + print(f" {'P(p < ' + format(t, 'g') + ')':>12} {(pv[m0] < t).mean():10.5f} {t:10.5f}") + print(f" n = {int(m0.sum()):,} naive KS critical value " + f"{1.358/np.sqrt(int(m0.sum())):.4f} observed D " + f"{kstest(pv[m0], 'uniform').statistic:.4f}") + print(" Uniform in the bulk. Supported where testable; untestable where it bites, because") + print(" the rows the filter adjudicates are exactly the rows selected for carrying an event.") + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--tables", required=True) + ap.add_argument("--fasta") + ap.add_argument("--part", default="both", choices=["clean", "a8", "both"]) + a = ap.parse_args() + + df, d = load(a.tables) + print(f"site-rows {len(df):,} usable control observations {len(d):,}") + if a.part in ("clean", "both"): + print("\n" + "=" * 96) + print("PART 1 — the clean-locus under-prediction") + print("=" * 96) + part_clean(df, d, a.fasta) + if a.part in ("a8", "both"): + print("\n" + "=" * 96) + print("PART 2 — assumption 8, stratified by whether an event was called") + print("=" * 96) + part_a8(df, d) + + +if __name__ == "__main__": + main() diff --git a/bin/noise_model_validate.py b/bin/noise_model_validate.py new file mode 100644 index 0000000..027945d --- /dev/null +++ b/bin/noise_model_validate.py @@ -0,0 +1,956 @@ +#!/usr/bin/env python3 +"""noise_model_validate.py — test whether the shipped background model describes the data. + +The objection this answers +-------------------------- +`noise_model.py` fits ONE Beta(a0, b0) by method of moments across every control observation in +the run, and uses it as the prior on the per-locus background rate. The claim examined here is +that this conflates two physically distinct processes: + + machine physics sequencing, PCR and alignment error. A per-base Bernoulli process whose rate + is tiny, is NOT globally fixed, and varies with sequence context -- polymerase + slippage in a homopolymer being the textbook case. + biology germline variation in the donor. Not error at all: a real allele near VAF 0.5 + or 1.0, and specific to THAT donor. + +A single Beta fitted across both describes a population that does not exist. Method of moments +matches a mean and a variance; applied to a mixture of a point mass near 0 and a mode near 0.5 it +returns the parameters of a distribution that describes neither component. + +What is measured here +--------------------- + 1. the two populations, plotted against the fitted Beta + 2. calibration under a genuine null, built with no new data -- score each donor's own control + counts against the OTHER donors' controls at the same locus. Both are unedited, so anything + that scores as signal is a miscalibration. Randomised p-values are used, because with + discrete counts the ordinary survival function cannot be Uniform even under a perfect model. + 3. held-out log predictive likelihood for five candidate models, split BY LOCUS so a locus + cannot appear in both halves + 4. whether the rate depends on sequence context, by refitting per homopolymer stratum + 5. the depth floor, ablated -- is it a patch on a mis-specified model, or genuinely needed? + 6. what any of it changes operationally: queue size and recall against the curated label + +This script changes nothing. It is analysis only, run by hand, and the pipeline does not call it. + +usage: + noise_model_validate.py --tables 'results_cart_bnd/*/*.offtarget_analysis.tsv' \ + --queue-all results_cart_bnd/review/review_queue_all.tsv \ + --truth-wgs '.../cart_wgs_merged.xlsx' \ + --fasta .../hg38_PLVM_CD19_CARv4_cd34.fa --figdir docs/images +""" +import argparse +import collections +import glob +import os +import sys + +import numpy as np +import pandas as pd +from scipy.optimize import minimize +from scipy.stats import betabinom, binom, kstest + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import noise_model as nm # noqa: E402 + +RNG = np.random.default_rng(0) +HP_WINDOW = 12 # bp either side of the site to search for a homopolymer run + + +# ============================================================================================= +# Candidate models. Each exposes: +# fit(k, n) -> params, from control observations +# logpmf(k, n) -> marginal predictive log-likelihood of a new observation +# posterior(K, N) -> per-locus state after seeing that locus's other controls +# tail(k, n, state) -> (P(X > k), P(X == k)) for a randomised p-value +# ============================================================================================= +class BinomialGlobal: + """One fixed rate for every locus and every sample. The straw man -- this is what "just use + an error rate" means, and it is the model whose failure motivated the beta-binomial.""" + name = "Binomial, global p" + + def fit(self, k, n): + self.p = float(k.sum() / max(n.sum(), 1)) + return self + + def describe(self): + return f"p = {self.p:.6g}" + + def logpmf(self, k, n): + return binom.logpmf(k, n, self.p) + + def posterior(self, K, N): + return None # a point rate cannot learn from the locus + + def tail(self, k, n, state): + return binom.sf(k, n, self.p), binom.pmf(k, n, self.p) + + +class BinomialPlugin: + """A Binomial whose rate is the locus's OWN observed control fraction -- "we have the actual + probability of indels, so why not just use it?". + + We do not have it. We have an estimate from ~157 reads, and at a rate of 1e-3 that control + expects 0.157 alt reads, so observing zero is the NORM rather than evidence of a zero rate. + The plug-in takes that zero literally: p_hat = 0 makes P(X >= k) = 0 for any k >= 1, i.e. + EVERY alt read in the edited sample becomes infinitely significant. On this cohort that is + 86 of the 89 rows the AQ rule actually sees. + + MIN_P exists only so the model can be scored at all; without it the log-likelihood is -inf + wherever the control saw nothing, which is most of the genome. Note that the floor is doing + the prior's job -- badly, and with an arbitrary constant instead of a fitted one. That is the + whole argument for the Beta-Binomial in one line: it is this model with the plug-in replaced + by an integral over the uncertainty in p_hat, and it converges to this model as depth -> inf. + """ + name = "Binomial, plug-in per-locus p" + MIN_P = 1e-9 + + def fit(self, k, n): + self.p_global = float(k.sum() / max(n.sum(), 1)) + return self + + def describe(self): + return f"p_hat = control_alt/control_depth per locus, floored at {self.MIN_P:g}" + + def logpmf(self, k, n): + # No pooling: with nothing held out, the best a plug-in can do on a NEW observation is + # the global rate. Scoring it with each row's own p_hat would be scoring the training set. + return binom.logpmf(k, n, self.p_global) + + def posterior(self, K, N): + return max(K / N, self.MIN_P) if N > 0 else self.p_global + + def tail(self, k, n, state): + p = self.p_global if state is None else state + return binom.sf(k, n, p), binom.pmf(k, n, p) + + +class BetaBinomMOM: + """The shipped model: Beta prior by method of moments, conjugate per-locus update.""" + name = "Beta-Binomial, MOM prior (SHIPPED)" + + def fit(self, k, n): + self.a, self.b = nm.fit_global_prior(k, n) + return self + + def describe(self): + return f"Beta({self.a:.6g}, {self.b:.6g}) mean {self.a/(self.a+self.b):.6g}" + + def logpmf(self, k, n): + return betabinom.logpmf(k, n, self.a, self.b) + + def posterior(self, K, N): + return (self.a + K, self.b + max(N - K, 0.0)) + + def tail(self, k, n, state): + a, b = state if state else (self.a, self.b) + return betabinom.sf(k, n, a, b), betabinom.pmf(k, n, a, b) + + +class BetaBinomMML(BetaBinomMOM): + """Same family, but the prior is fitted by maximum marginal likelihood -- proper empirical + Bayes. Isolates how much of any failure is the ESTIMATOR rather than the FAMILY.""" + name = "Beta-Binomial, max marginal likelihood" + + def fit(self, k, n): + a0, b0 = nm.fit_global_prior(k, n) + + def nll(t): + a, b = np.exp(t) + if not np.isfinite(a) or not np.isfinite(b) or a <= 0 or b <= 0: + return 1e18 + v = betabinom.logpmf(k, n, a, b) + return -float(np.sum(v[np.isfinite(v)])) + + r = minimize(nll, np.log([max(a0, 1e-4), max(b0, 1e-4)]), method="Nelder-Mead", + options=dict(maxiter=4000, xatol=1e-6, fatol=1e-6)) + self.a, self.b = np.exp(r.x) + return self + + +class ZeroInflatedBB: + """The physically motivated model: two components, one per process. + + with prob pi the locus is machine-error-only, at a rate eps the control cannot resolve + with prob 1-pi the locus carries a real allele, drawn from Beta(a, b) + + This is the model that can SAY "this locus is clean", which a single Beta cannot -- and that + is exactly the statement the depth floor exists to fake. + """ + name = "Zero-inflated Beta-Binomial (2 components)" + + def fit(self, k, n): + p0 = float(k.sum() / max(n.sum(), 1)) + a0, b0 = nm.fit_global_prior(k, n) + + def nll(t): + lo, le, la, lb = t + pi = 1.0 / (1.0 + np.exp(-lo)) + eps, a, b = np.exp(le), np.exp(la), np.exp(lb) + if not all(np.isfinite([eps, a, b])) or min(eps, a, b) <= 0 or eps >= 1: + return 1e18 + l0 = np.log(pi + 1e-300) + binom.logpmf(k, n, eps) + l1 = np.log(1 - pi + 1e-300) + betabinom.logpmf(k, n, a, b) + m = np.maximum(l0, l1) + v = m + np.log(np.exp(l0 - m) + np.exp(l1 - m)) + return -float(np.sum(v[np.isfinite(v)])) + + r = minimize(nll, [0.0, np.log(max(p0, 1e-6)), np.log(max(a0, 1e-3)), + np.log(max(b0, 1e-3))], + method="Nelder-Mead", options=dict(maxiter=20000, fatol=1e-6)) + lo, le, la, lb = r.x + self.pi = float(1 / (1 + np.exp(-lo))) + self.eps, self.a, self.b = float(np.exp(le)), float(np.exp(la)), float(np.exp(lb)) + return self + + def describe(self): + return (f"pi(clean) = {self.pi:.4f} eps = {self.eps:.3g} " + f"Beta({self.a:.4g}, {self.b:.4g}) mean {self.a/(self.a+self.b):.4f}") + + def logpmf(self, k, n): + l0 = np.log(self.pi + 1e-300) + binom.logpmf(k, n, self.eps) + l1 = np.log(1 - self.pi + 1e-300) + betabinom.logpmf(k, n, self.a, self.b) + m = np.maximum(l0, l1) + return m + np.log(np.exp(l0 - m) + np.exp(l1 - m)) + + def posterior(self, K, N): + """Both the component weights and the Beta update on that locus's other controls.""" + l0 = np.log(self.pi + 1e-300) + binom.logpmf(K, N, self.eps) + l1 = np.log(1 - self.pi + 1e-300) + betabinom.logpmf(K, N, self.a, self.b) + m = max(l0, l1) + if not np.isfinite(m): + # Both components assign this locus's other controls zero probability -- eps is driven + # to the denormal floor, so any K > 0 is impossible under component 0. Fall back to the + # prior weights rather than propagating a NaN. + return (self.pi, 1 - self.pi, self.a + K, self.b + max(N - K, 0.0)) + w0, w1 = np.exp(l0 - m), np.exp(l1 - m) + s = w0 + w1 + return (w0 / s, w1 / s, self.a + K, self.b + max(N - K, 0.0)) + + def tail(self, k, n, state): + if state is None: + w0, w1, a, b = self.pi, 1 - self.pi, self.a, self.b + else: + w0, w1, a, b = state + sf = w0 * binom.sf(k, n, self.eps) + w1 * betabinom.sf(k, n, a, b) + pm = w0 * binom.pmf(k, n, self.eps) + w1 * betabinom.pmf(k, n, a, b) + return sf, pm + + +# ============================================================================================= +def randomised_tails(model, obs_by_locus, a_global=None): + """Leave-one-donor-out p-values under a null where every observation is noise by construction. + + For each locus with >= 2 donors carrying control depth, each donor's own control counts are + scored against a background built from the OTHER donors' controls at that locus. Both sides + are unedited material, so a correct model must return Uniform(0,1). + + With discrete counts the plain survival function CANNOT be uniform even under a perfect model + -- it is bounded below by P(X = k), and with 99% of observations at k = 0 the mass piles at 1. + The randomised p-value U*P(X = k) + P(X > k), U ~ Uniform(0,1), is exactly uniform under a + correct discrete model, so it is what makes this test meaningful at all. + + The randomisation has a cost: any single realisation is ONE DRAW from the test, and at + n ~ 72,000 the KS p-value swings widely across seeds while the KS D statistic barely moves. + + So this returns the two SEED-INDEPENDENT components, P(X > k) and P(X = k), rather than a + p-value. Drawing a realisation is then `sf + U * pm` (see draw_pvalues), which is cheap, so the + caller can sweep seeds without repeating the expensive per-observation betabinom evaluation. + """ + sfs, pms, depth, ndon = [], [], [], [] + for _, obs in obs_by_locus.items(): + if len(obs) < 2: + continue + tot_k = sum(o[0] for o in obs) + tot_n = sum(o[1] for o in obs) + for k, n in obs: + K, N = tot_k - k, tot_n - n + state = model.posterior(K, N) + sf, pm = model.tail(k, n, state) + sfs.append(float(sf)) + pms.append(float(pm)) + depth.append(n) + ndon.append(len(obs) - 1) + return np.array(sfs), np.array(pms), np.array(depth), np.array(ndon) + + +def draw_pvalues(sf, pm, seed=0): + """One realisation of the randomised p-value: sf + U * pm, U ~ Uniform(0,1).""" + return np.clip(sf + np.random.default_rng(seed).random(len(sf)) * pm, 0.0, 1.0) + + +def homopolymer_len(fa, chrom, pos, pad=HP_WINDOW, margin=40): + """Longest homopolymer run OVERLAPPING the +/-pad window around the site, measured in full. + + The site coordinate is the protospacer anchor, not where the indel lands -- the caller accepts + events up to 10 bp away -- so a +/-3 bp neighbourhood would miss the run the polymerase is + actually slipping in. chrX:11,849,670 is the case in point: its four events are +/-1-2 T's in a + 15 bp T run that starts 9 bp downstream of the site coordinate. + + A run is measured over a window `margin` bp wider than the one used to decide overlap, so a + run that straddles the window edge is reported at its true length rather than clipped to what + happens to fall inside. Clipping would systematically shorten exactly the long runs the + stratification is trying to isolate, and would empty the top stratum. + """ + lo = max(0, pos - 1 - pad - margin) + try: + s = fa.fetch(chrom, lo, pos - 1 + pad + margin + 1).upper() + except (ValueError, KeyError): + return 0 + if not s: + return 0 + core_lo = (pos - 1 - pad) - lo # window bounds in local coordinates + core_hi = (pos - 1 + pad) - lo + best, start = 0, 0 + for j in range(1, len(s) + 1): + if j < len(s) and s[j] == s[j - 1]: + continue + if s[start] in "ACGT" and start <= core_hi and (j - 1) >= core_lo: + best = max(best, j - start) + start = j + return best + + +def ks_parametric_bootstrap(obs_locus, obs_n, a0, b0, d_observed, n_boot=200, seed=0): + """Empirical null distribution of the KS statistic, for the test as it is actually run. + + The classical KS null is wrong here for two reasons that pull in OPPOSITE directions: + + dependence 71,755 observations come from 6,876 loci, and each is scored against a + background built from the other donors AT THAT LOCUS. Positive coupling + lets the empirical CDF wander further from uniform, INFLATING D. + estimated params a0, b0 are fitted by method of moments on the same observations the test + then scores (the Lilliefors problem). A fitted distribution tracks its + own data too closely, DEFLATING D. + + Neither the magnitude nor the net direction is knowable analytically, which is what the + locus-level critical value in the main output can only bound conservatively. So: simulate + under the fitted model, PRESERVING the locus structure (one shared rate per locus, exactly + the dependence the null claims) and REPEATING the method-of-moments fit on every synthetic + dataset (so the estimation bias is reproduced too). The resulting spread of D is the null + this test actually has, and both problems are handled at once. + + Vectorised: the per-observation betabinom evaluation is the whole cost, and it accepts arrays, + so an iteration is ~2 s rather than the ~90 s a Python loop would take. + """ + rng = np.random.default_rng(seed) + n_loci = int(obs_locus.max()) + 1 + obs_n = obs_n.astype(int) + Ds = np.empty(n_boot) + for i in range(n_boot): + # 1. one true rate per locus -- this IS the dependence structure the model asserts + p_loc = rng.beta(a0, b0, size=n_loci) + k = rng.binomial(obs_n, p_loc[obs_locus]) + # 2. refit the prior on the synthetic data, exactly as the real analysis does + a_s, b_s = fit_prior_mom(k, obs_n) + # 3. the same leave-one-donor-out scoring + tot_k = np.bincount(obs_locus, weights=k, minlength=n_loci) + tot_n = np.bincount(obs_locus, weights=obs_n, minlength=n_loci) + K = tot_k[obs_locus] - k + N = tot_n[obs_locus] - obs_n + al = a_s + K + be = b_s + np.maximum(N - K, 0.0) + sf = betabinom.sf(k, obs_n, al, be) + pm = betabinom.pmf(k, obs_n, al, be) + pv = np.clip(sf + rng.random(len(sf)) * pm, 0.0, 1.0) + Ds[i] = kstest(pv, "uniform").statistic + p_boot = float((Ds >= d_observed).mean()) + return Ds, p_boot + + +def fit_prior_mom(k, n): + """nm.fit_global_prior on plain arrays, so the bootstrap can refit without a DataFrame.""" + return nm.fit_global_prior(np.asarray(k, float), np.asarray(n, float)) + + +def poisson_ci(k, conf=0.95): + """Exact (Garwood) Poisson interval on a count. Wide at small k, which is the whole point.""" + from scipy.stats import chi2 + lo = 0.0 if k == 0 else chi2.ppf((1 - conf) / 2, 2 * k) / 2 + hi = chi2.ppf(1 - (1 - conf) / 2, 2 * (k + 1)) / 2 + return lo, hi + + +def qq(ax, p, label): + p = np.sort(p[np.isfinite(p)]) + if not len(p): + return + e = (np.arange(1, len(p) + 1) - 0.5) / len(p) + ax.plot(e, p, lw=1.4, label=f"{label} (n={len(p)})") + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--tables", required=True) + ap.add_argument("--queue-all", required=True) + ap.add_argument("--truth-wgs") + ap.add_argument("--fasta") + ap.add_argument("--figdir") + ap.add_argument("--ks-bootstrap", type=int, default=0, metavar="N", + help="parametric-bootstrap iterations for the KS null (0 = off, 200 is " + "plenty). Simulates under the fitted model preserving locus structure " + "and refits the prior each time, so BOTH the dependence and the " + "estimated-parameter bias are accounted for. ~2 s per iteration.") + ap.add_argument("--calib-seeds", type=int, default=20, + help="randomised-p-value seeds to sweep in the calibration test. The KS " + "p-value is one draw per seed; D is what is stable. Default 20.") + ap.add_argument("--kn-policy", default="clip", choices=["clip", "drop"], + help="what to do with rows where control_indel_reads > control_reads") + a = ap.parse_args() + + paths = sorted(glob.glob(a.tables)) + df = nm.load_tables(paths) + print(f"tables {len(paths)} site-rows {len(df)}") + + # ----------------------------------------------------------------------------------------- + # Data hazards, handled explicitly rather than silently + # ----------------------------------------------------------------------------------------- + print("\n" + "=" * 94) + print("DATA HAZARDS") + print("=" * 94) + n_nodepth = int((df.control_reads <= 0).sum()) + bad = df.control_indel_reads > df.control_reads + print(f"rows with no control depth : {n_nodepth} (left on the global prior; there is " + f"no depth to derive a floor from)") + print(f"rows with control alt > depth : {int(bad.sum())}") + print(" The caller SUMS alt counts over the events at a site but takes the MEAN of control") + print(" depth, so these are not a clean (k, n) pair. betabinom is undefined for k > n.") + d = df[df.control_reads > 0].copy() + if a.kn_policy == "clip": + d["control_indel_reads"] = np.minimum(d.control_indel_reads, d.control_reads) + print(f" policy: CLIP k to n ({int((bad & (df.control_reads>0)).sum())} rows affected)") + else: + d = d[d.control_indel_reads <= d.control_reads] + print(f" policy: DROP those rows") + + k = d.control_indel_reads.values.astype(float) + n = d.control_reads.values.astype(float) + print(f"usable control observations : {len(d)}") + + # ----------------------------------------------------------------------------------------- + # 1. The two populations + # ----------------------------------------------------------------------------------------- + print("\n" + "=" * 94) + print("1. THE TWO POPULATIONS THE SINGLE BETA IS FITTED ACROSS") + print("=" * 94) + rate = k / n + nz = rate[rate > 0] + print(f"zero control alt reads : {int((k==0).sum())} / {len(k)} = {(k==0).mean()*100:.2f}%") + print(f"nonzero : {len(nz)} median {np.median(nz):.4f} " + f"q25 {np.quantile(nz,.25):.4f} q75 {np.quantile(nz,.75):.4f}") + print(f"smallest nonzero rate : {nz.min():.6f} (= 1 read at that depth)") + for lo, hi in ((0, 1e-3), (1e-3, 1e-2), (1e-2, 5e-2)): + print(f"observations in ({lo:g}, {hi:g}) : {int(((rate>lo)&(rate one read = {1/med_dep*100:.2f}% VAF") + print("The control cannot RESOLVE a rate below that. Everything the machine-error process") + print("actually does lives underneath it, which is why the zero bin is a detection limit and") + print("not a measurement of zero.") + + a0, b0 = nm.fit_global_prior(df.control_indel_reads.values, df.control_reads.values) + print(f"\nfitted prior : Beta({a0:.6g}, {b0:.6g}) mean {a0/(a0+b0):.6g}") + print("That mean sits between the two modes, where no locus lives.") + + # ----------------------------------------------------------------------------------------- + # 2. Model fits and held-out likelihood, split BY LOCUS + # ----------------------------------------------------------------------------------------- + print("\n" + "=" * 94) + print("2. MODEL COMPARISON — held-out log predictive likelihood (split by locus)") + print("=" * 94) + loci = pd.factorize(d.chrom.astype(str) + ":" + d.end.astype(str))[0] + held = (loci % 2) == 1 + print(f"train {int((~held).sum())} observations / test {int(held.sum())}, " + f"{len(set(loci))} distinct loci") + + models = [BinomialGlobal(), BinomialPlugin(), BetaBinomMOM(), BetaBinomMML(), + ZeroInflatedBB()] + fitted = [] + for m in models: + m.fit(k[~held], n[~held]) + ll = m.logpmf(k[held], n[held]) + ll = ll[np.isfinite(ll)] + fitted.append((m, float(ll.mean()))) + print(f"\n{m.name}") + print(f" {m.describe()}") + print(f" held-out mean log-lik: {ll.mean():.6f} (higher is better)") + + best = max(fitted, key=lambda t: t[1]) + print(f"\nbest by held-out likelihood: {best[0].name}") + + # Is the mixture actually identified? A Beta with a < 1 is ALREADY spike-at-zero-shaped, so + # the "clean" component and the low end of the Beta component explain the same observations. + # Refitting on the full data and comparing pi is the cheapest test of that, and if pi swings + # while the likelihood barely moves, the two components are not separately estimable. + zi_tr = [m for m in models if isinstance(m, ZeroInflatedBB)][0] + pi_train = zi_tr.pi + zi_all = ZeroInflatedBB().fit(k, n) + print(f"\nmixture identifiability: pi = {pi_train:.4f} on the training half vs " + f"{zi_all.pi:.4f} on all data,") + print(f" while held-out log-lik differs from plain MML by " + f"{fitted[-1][1]-fitted[-2][1]:+.6f} nats per observation.") + print(" pi swings while the fit does not move: the two components are NOT separately") + print(" identified. A Beta with a < 1 is already spike-at-zero shaped, so the explicit") + print(" mixture is re-describing what the shipped prior's shape already encodes.") + + # ----------------------------------------------------------------------------------------- + # 3. Calibration under the leave-one-donor-out null + # ----------------------------------------------------------------------------------------- + print("\n" + "=" * 94) + print("3. CALIBRATION — leave-one-donor-out null (every observation is noise by construction)") + print("=" * 94) + obs = collections.defaultdict(list) + for c, e, kk, nn in zip(d.chrom.astype(str), d.end.astype(int), k, n): + obs[(c, int(e))].append((kk, nn)) + multi = {key: v for key, v in obs.items() if len(v) >= 2} + print(f"loci with >= 2 donors: {len(multi)} observations: {sum(len(v) for v in multi.values())}") + # Flat (locus index, depth) arrays describing the SAME design, for the parametric bootstrap. + boot_locus, boot_n = [], [] + for li, (_, obs) in enumerate(multi.items()): + for _kk, nn in obs: + boot_locus.append(li) + boot_n.append(nn) + boot_locus = np.asarray(boot_locus, dtype=int) + boot_n = np.asarray(boot_n, dtype=float) + print("p-values are RANDOMISED; see randomised_tails() for why the plain sf cannot be used.") + + pv = {} + a0_all, b0_all = nm.fit_global_prior(k, n) # the production prior, reused by 3c below + for m in models: + m.fit(k, n) # refit on everything for the calibration test + sf, pm, dep, nd = randomised_tails(m, multi) + p = draw_pvalues(sf, pm, seed=0) # the reference realisation, seed 0 + pv[m.name] = (p, dep, nd) + ks = kstest(p, "uniform") + print(f"\n{m.name}") + print(f" KS vs Uniform(0,1): D = {ks.statistic:.4f} p = {ks.pvalue:.3g}" + f" (D near 0 = calibrated)") + print(f" mean {p.mean():.4f} (0.5 if calibrated) " + f"frac < 0.05: {(p<0.05).mean():.4f} (0.05 if calibrated) " + f"frac < 0.001: {(p<0.001).mean():.5f} (0.001 if calibrated)") + for lab, mask in (("thin support (1 other donor)", nd == 1), + ("thick support (>1 donor)", nd > 1), + (f"control depth < {med_dep:.0f}x", dep < med_dep), + (f"control depth >= {med_dep:.0f}x", dep >= med_dep)): + if mask.sum(): + print(f" {lab:32s} D = {kstest(p[mask],'uniform').statistic:.4f} " + f" frac<0.05 = {(p[mask]<0.05).mean():.4f} (n={int(mask.sum())})") + + # The p-value above is one draw. Sweep the seed so the reported figure is a range, not a + # coincidence: D is stable across seeds, the KS p-value is not, and quoting a single p + # invites a reader to read significance into RNG state. + sweep = [kstest(draw_pvalues(sf, pm, seed=sd), "uniform") + for sd in range(a.calib_seeds)] + Ds = np.array([r.statistic for r in sweep]) + ps = np.array([r.pvalue for r in sweep]) + print(f" seed sweep (n={a.calib_seeds}): D min {Ds.min():.4f} median {np.median(Ds):.4f}" + f" max {Ds.max():.4f}") + print(f" KS p min {ps.min():.3f} median {np.median(ps):.3f}" + f" max {ps.max():.3f} rejects at 0.05: {(ps<0.05).sum()}/{a.calib_seeds}") + # The KS null assumes INDEPENDENT observations, and these are not: every locus contributes + # one observation per donor, and each is scored against a background built from the other + # donors AT THAT LOCUS. The locus, not the observation, is the independent unit. Print the + # critical value both ways -- the verdict should not depend on which one you believe. + n_obs, n_loc = len(sf), len(multi) + d_obs, d_loc = 1.358 / np.sqrt(n_obs), 1.358 / np.sqrt(n_loc) + worst = Ds.max() + print(f" KS D_crit(0.05): {d_obs:.4f} treating all {n_obs} observations as independent, " + f"{d_loc:.4f} treating the {n_loc} loci as the unit") + print(f" worst seed D = {worst:.4f} -> {'REJECT' if worst > d_obs else 'pass'} " + f"(naive) {'REJECT' if worst > d_loc else 'pass'} (locus-level, " + f"{d_loc/max(worst,1e-9):.1f}x margin)") + if a.ks_bootstrap and isinstance(m, BetaBinomMOM) and not isinstance(m, BetaBinomMML): + d_med = float(np.median(Ds)) + boot, p_boot = ks_parametric_bootstrap( + boot_locus, boot_n, m.a, m.b, d_med, n_boot=a.ks_bootstrap) + crit = float(np.quantile(boot, 0.95)) + print(f" parametric bootstrap ({a.ks_bootstrap} sims under the fitted model, " + f"locus structure preserved, prior refit each time):") + print(f" null D: median {np.median(boot):.4f} 95th pct {crit:.4f} " + f"max {boot.max():.4f}") + print(f" observed D (median seed) {d_med:.4f} -> bootstrap p = {p_boot:.3f} " + f"({'REJECT' if d_med > crit else 'pass'})") + print(f" for reference the analytic criticals were {d_obs:.4f} (naive) and " + f"{d_loc:.4f} (locus-level)") + + # ----------------------------------------------------------------------------------------- + # 3b. Does the predicted rate match the observed rate? (the direct gut check) + # + # Must be OUT-OF-SAMPLE. Scoring a locus against a posterior built from that same locus's + # control is circular -- the model would be graded on data it already absorbed. So the + # prediction for each donor uses only the OTHER donors at that locus, exactly as the + # calibration null does. + # ----------------------------------------------------------------------------------------- + print("\n" + "=" * 94) + print("3b. PREDICTED vs OBSERVED RATE — leave-one-donor-out, so nothing is graded on itself") + print("=" * 94) + shipped = [m for m in models if isinstance(m, BetaBinomMOM) + and not isinstance(m, BetaBinomMML)][0] + rel_k, rel_n, rel_pred = [], [], [] + for _, obs in multi.items(): + tot_k = sum(o[0] for o in obs) + tot_n = sum(o[1] for o in obs) + for kk, nn in obs: + K, N = tot_k - kk, tot_n - nn + al, be = shipped.posterior(K, N) + rel_k.append(kk) + rel_n.append(nn) + rel_pred.append(al / (al + be)) + rel_k = np.asarray(rel_k, float) + rel_n = np.asarray(rel_n, float) + rel_pred = np.asarray(rel_pred, float) + exp_ct = rel_n * rel_pred + + tot_exp, tot_obs = exp_ct.sum(), rel_k.sum() + se = np.sqrt(max(tot_obs, 1.0)) # Poisson se on the observed total + print(f"aggregate: predicted {tot_exp:,.1f} alt reads observed {tot_obs:,.0f} " + f"ratio {tot_obs/tot_exp:.3f} (+/- {se/tot_exp:.3f} Poisson)") + + # Bin by PREDICTED EXPECTED COUNT, not by rate: a rate bin can hold thousands of observations + # carrying no events at all, and a ratio computed there is noise wearing a number's clothes. + edges = np.array([0, 1e-3, 3e-3, 1e-2, 3e-2, 1e-1, 3e-1, 1.0, 1e9]) + idx = np.digitize(exp_ct, edges[1:-1]) + print(f"\n{'expected alt reads/obs':>26} {'n':>7} {'pred':>9} {'obs':>7} " + f"{'ratio':>7} {'95% Poisson CI on ratio':>26}") + rel_bins = [] + for b in range(len(edges) - 1): + m_ = idx == b + if not m_.sum(): + continue + pe, po = exp_ct[m_].sum(), rel_k[m_].sum() + if pe <= 0: + continue + ratio = po / pe + lo, hi = poisson_ci(po) + rel_bins.append((edges[b], edges[b + 1], int(m_.sum()), pe, po, ratio, lo / pe, hi / pe)) + print(f" [{edges[b]:.0e},{edges[b+1]:.0e})".rjust(26) + + f" {int(m_.sum()):7d} {pe:9.1f} {po:7.0f} {ratio:7.2f}" + f" [{lo/pe:8.2f}, {hi/pe:8.2f}]") + print("\n A bin whose CI spans 1.0 is consistent with the model. Bins built on a handful of") + print(" events have enormous CIs -- that is the point of showing them rather than the ratio.") + + # Posterior-predictive check: simulate under the fitted model and compare the SHAPE of the + # count distribution, not just its total. A model can get the mean right and the tail wrong. + print("\n-- posterior-predictive check (simulate k ~ BetaBinom(n, alpha, beta) per locus) --") + rng_pp = np.random.default_rng(0) + al_pp, be_pp = [], [] + for _, obs in multi.items(): + tot_k = sum(o[0] for o in obs) + tot_n = sum(o[1] for o in obs) + for kk, nn in obs: + al, be = shipped.posterior(tot_k - kk, tot_n - nn) + al_pp.append(al) + be_pp.append(be) + al_pp, be_pp = np.asarray(al_pp), np.asarray(be_pp) + sims = np.array([betabinom.rvs(rel_n.astype(int), al_pp, be_pp, random_state=rng_pp) + for _ in range(20)]) + stats = [("fraction k == 0", lambda x: float((x == 0).mean())), + ("fraction k >= 1", lambda x: float((x >= 1).mean())), + ("fraction k >= 2", lambda x: float((x >= 2).mean())), + ("fraction k >= 5", lambda x: float((x >= 5).mean())), + ("mean k", lambda x: float(x.mean())), + ("max k", lambda x: float(x.max()))] + print(f" {'statistic':<18} {'observed':>10} {'simulated (20 draws)':>26} verdict") + pp_rows = [] + for lab, fn in stats: + o = fn(rel_k) + sim = np.array([fn(row) for row in sims]) + lo, hi = np.percentile(sim, [2.5, 97.5]) + ok = lo <= o <= hi + pp_rows.append((lab, o, sim.mean(), lo, hi, ok)) + print(f" {lab:<18} {o:10.5f} {sim.mean():12.5f} [{lo:.5f}, {hi:.5f}] " + f"{'ok' if ok else 'OUTSIDE'}") + + # ----------------------------------------------------------------------------------------- + # 3c. Do the EDITED and CONTROL libraries actually share a background rate? + # + # This is the assumption the whole model rests on -- alpha,beta are built entirely from control + # counts and applied unmodified as the null for edited counts -- and nothing else in this + # script tests it. The calibration null above is control-vs-control across donors, a different + # comparison. Here we score the EDITED counts against that sample's OWN matched control at + # loci with no nominated cut site, where no edit is expected. Under the assumption those + # randomised p-values are Uniform(0,1). + # ----------------------------------------------------------------------------------------- + print("\n" + "=" * 94) + print("3c. ASSUMPTION CHECK — do the edited and control libraries share a background rate?") + print("=" * 94) + if "is_target" not in df.columns: + print("no is_target column; skipped") + else: + e = df[(df.control_reads > 0) & (df.is_target == 0) & (df.total_reads > 0)].copy() + e["control_indel_reads"] = np.minimum(e.control_indel_reads, e.control_reads) + ca = e.control_indel_reads.values.astype(float) + cn = e.control_reads.values.astype(float) + ek = e.indel_reads.values.astype(int) + en = e.total_reads.values.astype(int) + evaf = np.divide(ek, np.maximum(en, 1), dtype=float) + # Rows that could never be called are background by construction of the gate, so they + # bound how much of any miscalibration could be real off-target editing. + callable_ = (ek >= 2) & (evaf >= 0.005) + rng_a8 = np.random.default_rng(0) + print(f"no-target rows with control depth: {len(e)} " + f"(of which {int(callable_.sum())} could be called at all)") + for floor_on in (False, True): + al = a0_all + ca + be = b0_all + np.maximum(cn - ca, 0.0) + if floor_on: + al, be, n_lift = nm.apply_depth_floor(al, be, cn) + sf_e = betabinom.sf(ek, en, al, be) + pm_e = betabinom.pmf(ek, en, al, be) + pv_e = sf_e + rng_a8.random(len(sf_e)) * pm_e + fin = np.isfinite(pv_e) + lab = "WITH depth floor (production)" if floor_on else "RAW posterior (the model)" + print(f"\n -- {lab} --" + (f" floor raised {n_lift}" if floor_on else "")) + for pop, msk in (("all no-target", fin), ("sub-gate only", fin & ~callable_)): + q_ = np.clip(pv_e[msk], 0.0, 1.0) + if not len(q_): + continue + D_ = kstest(q_, "uniform").statistic + pred = float((en * (al / (al + be)))[msk].sum()) + obs = float(ek[msk].sum()) + print(f" {pop:<14} n={len(q_):6d} KS D={D_:.4f} " + f"p<0.001 = {(q_ < 0.001).mean():.5f} ({(q_ < 0.001).mean()/0.001:.1f}x) " + f"obs/pred = {obs/max(pred, 1e-9):.3f}") + print("\n Uniform p-values would mean the two libraries share a background. They do not:") + print(" the raw posterior is far too aggressive at clean loci, and the depth floor") + print(" over-corrects. AQ is a conservative bound, not a calibrated edited-vs-control p.") + + # ----------------------------------------------------------------------------------------- + # 4. Is the rate context-dependent? + # ----------------------------------------------------------------------------------------- + if a.fasta: + print("\n" + "=" * 94) + print("4. CONTEXT — is the Bernoulli rate a constant of the assay?") + print("=" * 94) + import pysam + fa = pysam.FastaFile(a.fasta) + uniq = d.drop_duplicates(["chrom", "end"])[["chrom", "end"]] + hp = {(c, int(e)): homopolymer_len(fa, c, int(e)) + for c, e in zip(uniq.chrom.astype(str), uniq.end.astype(int))} + d["hp"] = [hp[(c, int(e))] for c, e in zip(d.chrom.astype(str), d.end.astype(int))] + strata = [("no run (<=3 bp)", d.hp <= 3), ("4-5 bp", d.hp.between(4, 5)), + ("6-8 bp", d.hp.between(6, 8)), (">=9 bp", d.hp >= 9)] + print(f"{'stratum':18s} {'n':>7s} {'obs rate':>10s} {'a0':>12s} {'b0':>10s} " + f"{'prior mean':>12s} {'nonzero %':>10s}") + for lab, mask in strata: + s = d[mask] + if len(s) < 50: + print(f"{lab:18s} {len(s):7d} (too few to fit)") + continue + sa, sb = nm.fit_global_prior(s.control_indel_reads.values, s.control_reads.values) + r = s.control_indel_reads.sum() / max(s.control_reads.sum(), 1) + nzp = (s.control_indel_reads > 0).mean() * 100 + print(f"{lab:18s} {len(s):7d} {r:10.6f} {sa:12.6g} {sb:10.4g} " + f"{sa/(sa+sb):12.6g} {nzp:10.2f}") + print("\nIf the strata separate, the rate is NOT a constant of the assay and a single") + print("global prior necessarily under-penalises slippage-prone context while") + print("over-penalising clean unique sequence.") + + # What a context-conditioned prior would actually do to the rows under review. Without + # this the stratification is an interesting table with no consequence attached. + qh = pd.read_csv(a.queue_all, sep="\t") + qh["hp"] = [homopolymer_len(fa, c, int(e)) + for c, e in zip(qh.chrom.astype(str), qh.end.astype(int))] + wd_ = qh.why_dropped.fillna("") + print(f"\n-- the same strata among the {len(qh)} gated rows --") + for lab, mask in [("no run (<=3 bp)", qh.hp <= 3), ("4-5 bp", qh.hp.between(4, 5)), + ("6-8 bp", qh.hp.between(6, 8)), (">=9 bp", qh.hp >= 9)]: + print(f" {lab:16s} gated {int(mask.sum()):4d} in the queue " + f"{int((mask & (wd_ == '')).sum()):3d}") + hi = qh[(qh.hp >= 9) & (wd_ == "")] + if len(hi): + sa, sb = nm.fit_global_prior(d[d.hp >= 9].control_indel_reads.values, + d[d.hp >= 9].control_reads.values) + al2 = sa + hi.control_indel_reads.values + be2 = sb + np.maximum(hi.control_reads.values - hi.control_indel_reads.values, 0) + aq2 = nm.aq_from_sf(betabinom.sf(hi.indel_reads.values.astype(int) - 1, + hi.total_reads.values.astype(int), al2, be2)) + al1, be1, _, dep1 = nm.control_posterior(df, hi, "matched", a0, b0) + al1, be1, _ = nm.apply_depth_floor(al1, be1, dep1) + aq1 = nm.aq_from_sf(betabinom.sf(hi.indel_reads.values.astype(int) - 1, + hi.total_reads.values.astype(int), al1, be1)) + print(f"\n-- queue rows in a >=9 bp homopolymer: {len(hi)} --") + print(f" AQ under the GLOBAL prior : {np.round(aq1, 1).tolist()}") + print(f" AQ under the >=9 bp STRATUM prior: {np.round(aq2, 1).tolist()}") + print(f" would newly fall below AQ 5: {int(((aq1>=5)&(aq2<5)).sum())} row(s)") + print(" This is the concrete cost of a global prior: these rows are scored against") + print(" an assay-wide rate that their own sequence context says is far too low.") + else: + print("\nNo queue row sits in a >=9 bp homopolymer on this cohort, so the") + print("mis-specification is real but currently costs nothing at the queue.") + + # ----------------------------------------------------------------------------------------- + # 5. The depth floor, ablated + # ----------------------------------------------------------------------------------------- + print("\n" + "=" * 94) + print("5. THE DEPTH FLOOR — patch, or genuine requirement?") + print("=" * 94) + q = pd.read_csv(a.queue_all, sep="\t") + alpha, beta, nsup, dep = nm.control_posterior(df, q, "matched", a0, b0) + kq = q.indel_reads.values.astype(int) + nq = q.total_reads.values.astype(int) + aq_off = nm.aq_from_sf(betabinom.sf(kq - 1, nq, alpha, beta)) + af, bf, n_lift = nm.apply_depth_floor(alpha, beta, dep) + aq_on = nm.aq_from_sf(betabinom.sf(kq - 1, nq, af, bf)) + clean = dep > 0 + print(f"gated rows {len(q)}; floor raises the background on {n_lift} of them " + f"({n_lift/len(q)*100:.1f}%)") + print(f"posterior mean WITHOUT the floor, on floored rows: " + f"min {np.min((alpha/(alpha+beta))[dep>0]):.3g}, " + f"median {np.median((alpha/(alpha+beta))[dep>0]):.3g}") + print(f"the fitted prior mean is {a0/(a0+b0):.3g}, and 1/median_control_depth is " + f"{1/med_dep:.3g} -- the unfloored posterior claims a rate far below what the control " + f"can support") + print(f"AQ with floor OFF: median {np.median(aq_off):.1f}, rows AQ<5: " + f"{int((aq_off<5).sum())}") + print(f"AQ with floor ON : median {np.median(aq_on):.1f}, rows AQ<5: {int((aq_on<5).sum())}") + + zi = [m for m in models if isinstance(m, ZeroInflatedBB)][0] + print(f"\nThe mixture can state 'this locus is clean' directly: it puts weight " + f"pi = {zi.pi:.4f} on a\ncomponent at rate eps = {zi.eps:.3g}, which is what the floor " + f"is imitating by clamping.") + if zi.eps < 1e-12: + print("\nAND THAT eps IS THE POINT, not a fitting failure. The MLE drove it to the") + print("optimiser's floor because NO observation in the data constrains it from below: at") + print(f"{med_dep:.0f}x, a rate of 1e-4 and a rate of 1e-40 both predict zero alt reads") + print("with probability ~1. The control is blind to the machine-error rate, so the data") + print("cannot estimate it -- which is exactly the argument for taking that component from") + print("a pooled population panel instead of from one matched control.") + + # ----------------------------------------------------------------------------------------- + # 6. Operational consequence + # ----------------------------------------------------------------------------------------- + if a.truth_wgs: + print("\n" + "=" * 94) + print("6. OPERATIONAL CONSEQUENCE — does any of this move the queue?") + print("=" * 94) + lab = nm.wgs_curated_label(a.truth_wgs) + qq_ = q.copy() + qq_["guide"] = qq_.sample_name.map(nm.guide_of) + qq_["chrom"] = qq_.chrom.astype(str) + + # The AQ rule is 4th in review_filter's np.select, and first match wins -- so it only ever + # sees rows that rules 1-3 (germline / far from PAM / single indel length) left alone. + # Scoring all 479 gated rows would badly overstate what changing the model does, because + # most of those rows never reach the AQ test in the shipped pipeline. + wd = q.why_dropped.fillna("") + earlier = {"germline (present in control)", "far from PAM", "single indel length"} + reaches = ~wd.isin(earlier) + print(f"gated rows {len(q)}; rules 1-3 remove {int((~reaches).sum())}; " + f"rows that actually reach the AQ rule: {int(reaches.sum())}") + print("Scoring all 479 would overstate the effect -- most never reach this test.") + + m0 = qq_[reaches.values].merge(lab, on=["guide", "chrom", "start"], how="inner") + print(f"labelled among those: {len(m0)} " + f"({int((m0.curated_label==1).sum())} confirmed / " + f"{int((m0.curated_label==0).sum())} rejected)") + print(f"\n{'model':42s} {'AQ<5 drops':>11s} {'queue':>7s} {'confirmed':>12s} " + f"{'rejected':>11s}") + key = ["sample_name", "chrom", "start"] + for m in models: + if isinstance(m, BinomialGlobal): + sf = binom.sf(kq - 1, nq, m.p) + elif isinstance(m, ZeroInflatedBB): + sf = np.array([m.tail(kk - 1, nn, m.posterior(al - a0, (al - a0) + (be - b0)))[0] + for kk, nn, al, be in zip(kq, nq, alpha, beta)]) + else: + sf = betabinom.sf(kq - 1, nq, m.a + (alpha - a0), m.b + (beta - b0)) + keep = pd.Series(nm.aq_from_sf(sf) >= 5, index=q.index) & reaches + drops = int((reaches & ~keep).sum()) + kmap = q.assign(_k=keep.values).set_index(key)["_k"].to_dict() + mk = np.array([bool(kmap.get(t, False)) + for t in zip(m0.sample_name, m0.chrom, m0.start)]) + ck = int((mk & (m0.curated_label == 1).values).sum()) + rk = int((mk & (m0.curated_label == 0).values).sum()) + print(f"{m.name:42s} {drops:11d} {int(keep.sum()):7d} " + f"{ck:>7d}/{int((m0.curated_label==1).sum()):<4d} " + f"{rk:>6d}/{int((m0.curated_label==0).sum()):<4d}") + print("\n('queue' here counts rows surviving the AQ rule only; the shipped queue is that") + print(" number minus the repeat-region and external-panel rules, which run after it.)") + print("A model that is statistically better but moves these columns by a row or two has") + print("not earned a pipeline change on this cohort. Report it as such.") + + # ----------------------------------------------------------------------------------------- + if a.figdir: + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + from scipy.stats import beta as beta_dist + os.makedirs(a.figdir, exist_ok=True) + + fig, ax = plt.subplots(1, 2, figsize=(12, 4.2)) + edges = np.linspace(0, 1, 101) + ax[0].hist(rate, bins=edges, color="#444", log=True) + ax[0].set_xlabel("control indel rate k/n"); ax[0].set_ylabel("observations (log)") + ax[0].set_title(f"empirical: {(k==0).mean()*100:.1f}% at exactly 0, " + f"a second mode near {np.median(nz):.2f}") + x = np.linspace(1e-4, 1 - 1e-4, 500) + ax[1].plot(x, beta_dist.pdf(x, a0, b0), color="crimson", + label=f"fitted Beta({a0:.4g}, {b0:.3g})") + ax[1].axvline(a0 / (a0 + b0), ls="--", color="k", + label=f"prior mean {a0/(a0+b0):.5f}") + ax[1].axvline(float(np.median(nz)), ls=":", color="#2a6", + label=f"germline mode {np.median(nz):.2f}") + ax[1].set_yscale("log"); ax[1].set_xlabel("background rate p") + # a < 1 and b > 1 makes this strictly decreasing -- infinite at 0, zero at 1. It is + # spike-at-zero shaped, NOT U-shaped, and that is precisely why it survives the + # calibration test: the shape already encodes the zero inflation. + ax[1].set_title(f"Beta(a<1, b>1): spike at 0 with a heavy tail\n" + f"prior mean {a0/(a0+b0):.5f} lies between the two modes") + ax[1].legend(fontsize=8) + fig.tight_layout() + p1 = os.path.join(a.figdir, "noise_two_populations.png") + fig.savefig(p1, dpi=150) + + fig, ax = plt.subplots(figsize=(5.4, 5.2)) + for name, (p, _, _) in pv.items(): + qq(ax, p, name) + ax.plot([0, 1], [0, 1], "k--", lw=1) + ax.set_xlabel("expected quantile under Uniform(0,1)") + ax.set_ylabel("observed randomised p-value") + ax.set_title("calibration under the leave-one-donor-out null") + ax.legend(fontsize=7, loc="lower right") + fig.tight_layout() + p2 = os.path.join(a.figdir, "noise_calibration_qq.png") + fig.savefig(p2, dpi=150) + + # Reliability: predicted vs observed alt counts, out-of-sample, with Poisson intervals. + fig, (axL, axR) = plt.subplots(1, 2, figsize=(11, 4.6)) + if rel_bins: + xs = np.array([r[3] for r in rel_bins]) # predicted count in the bin + ys = np.array([r[4] for r in rel_bins]) # observed count + lo = np.array([r[6] * r[3] for r in rel_bins]) + hi = np.array([r[7] * r[3] for r in rel_bins]) + axL.errorbar(xs, ys, yerr=[ys - lo, hi - ys], fmt="o", ms=6, lw=1.2, + capsize=3, color="#0b5394", label="LOO bins (95% Poisson)") + span = [min(xs.min(), ys.min()) * 0.5, max(xs.max(), ys.max()) * 2] + axL.plot(span, span, "k--", lw=1, label="perfect calibration") + axL.set_xscale("log"); axL.set_yscale("log") + axL.set_xlabel("predicted alt reads (out-of-sample)") + axL.set_ylabel("observed alt reads") + axL.set_title(f"reliability: aggregate ratio {tot_obs/tot_exp:.3f}") + axL.legend(fontsize=8, loc="upper left") + axL.grid(alpha=.25, which="both") + labs = [r[0] for r in pp_rows[:4]] + obs_v = [r[1] for r in pp_rows[:4]] + sim_v = [r[2] for r in pp_rows[:4]] + sim_lo = [r[1] - r[3] for r in pp_rows[:4]] + sim_hi = [r[4] - r[1] for r in pp_rows[:4]] + xpos = np.arange(len(labs)) + axR.bar(xpos - .18, obs_v, .36, label="observed", color="#0b5394") + axR.bar(xpos + .18, sim_v, .36, label="simulated", color="#9dc3e6", + yerr=[np.abs(sim_lo), np.abs(sim_hi)], capsize=3, ecolor="#444") + axR.set_xticks(xpos) + axR.set_xticklabels([l.replace("fraction ", "") for l in labs], fontsize=8) + axR.set_yscale("log") + axR.set_ylabel("fraction of observations") + axR.set_title("posterior-predictive check") + axR.legend(fontsize=8) + axR.grid(alpha=.25, axis="y") + fig.tight_layout() + p3 = os.path.join(a.figdir, "noise_reliability.png") + fig.savefig(p3, dpi=150) + print(f"\nwrote {p1}\nwrote {p2}\nwrote {p3}") + + +if __name__ == "__main__": + main() diff --git a/bin/offtarget_metrics.py b/bin/offtarget_metrics.py new file mode 100755 index 0000000..ac475d9 --- /dev/null +++ b/bin/offtarget_metrics.py @@ -0,0 +1,547 @@ +#!/usr/bin/env python3 +""" +offtarget_metrics.py — the metrics a recall-first diagnostic is actually judged on. + +Reports PR-AUC and recall-weighted F-beta (F2, F5) for the WGS shape score, plus the +precision/recall/F1 at the operating point the pipeline actually reports (verdict = +LIKELY EDIT). ROC-AUC is carried for continuity but is deliberately NOT the headline: +at low positive prevalence it is dominated by the true-negative mass and flatters the +ranker. PR-AUC has no such property, which is why it leads here. + + F_beta = (1 + beta^2) * P * R / (beta^2 * P + R) + +beta weights recall beta^2x more than precision (beta=2 -> 4x, beta=5 -> 25x). F_beta is +MONOTONE in beta: it rises with beta when R > P and falls when P > R, and always lies +between min(P, R) and max(P, R). So F1 is always an endpoint of {F1, F2, F5}, never the +middle value — if you see F1 in the middle, the beta wiring is inverted. + +WHY THESE METRICS ARE NOT COMPUTED AGAINST THE MANUAL REVIEW +------------------------------------------------------------ +This is the trap this script exists to avoid. The human-reviewed gold standard +(`cart_ecs_merged.csv.gz`) has 55 rows with manual_review == '1', 1 with '1?', and +80,440 NaN. **NaN means NOT REVIEWED, not reviewed-and-rejected.** There are no +confirmed negatives in it at all. + +Precision therefore CANNOT be computed against that table. Treating NaN as negative +would count every genuine discovery the reviewers never got to as a false positive and +manufacture a confidently wrong number. That is why `validate_recall.py` reports recall +only, and why it stays the gold standard for recall. Do not "fix" it by filling NaN. + +So there are two denominators, and this script keeps them strictly apart: + + 1. RANKING + PRECISION -> training.tsv, which has a genuine two-class ECS label. + That is what this script computes. Precision here is + precision against the ECS label, NEVER against human review. + 2. RECALL vs HUMAN REVIEW -> `validate_recall.py`, reported as recall alone, unchanged. + +Both denominators are stamped into the JSON and the text report so a reader months later +cannot mistake one for the other. + +THE POSITIVE SET (same credibility gates as the recall curve) +------------------------------------------------------------- +A raw `label == 1` counts ANY nonzero ECS indel fraction as an edit, which at ECS depth +is overwhelmingly noise. Positives are therefore gated exactly as `recall_vs_vaf.py` +gates its denominator: + + label == 1 AND ecs_if >= --min-ecs-vaf AND ecs_indel_reads >= --min-ecs-reads + +`label == 1` rows failing those gates are AMBIGUOUS, not negative: ECS saw something, +below the credibility floor. They are EXCLUDED and counted, for the same reason the +unreviewed manual-review rows are excluded — asserting they are negatives is an +assumption the data does not support. `--ambiguous-as-negative` reports the alternative, +and the JSON always carries it as a labelled sensitivity block so the choice is visible. + +THE NEGATIVE SET +---------------- +`label == 0` is two different things: + * ecs_is_edit == 0 — a genuine ECS-negative at a scored hotspot (a true negative); + * ecs_is_edit == 1 — an ECS edit DEMOTED because the indel is in the matched normal + (germline/artifact). +The germline-demoted rows carry a real indel, so the shape model correctly scores their +pileup shape high — germline rejection is a separate downstream gate (their verdict is +`GERMLINE/ARTIFACT (in normal)`, and none are called LIKELY EDIT). Ranking the shape +score against them charges it with a job it does not do and is not asked to do, so the +default negative set is `ecs_negative`. `--negatives all_label0` gives the stricter view +and is reported as a sensitivity block either way. +""" +import argparse +import json +import sys + +import numpy as np +import pandas as pd + +# VAF floors for the stratified view. A single PR-AUC over all credible positives is +# dominated by sub-1% VAF sites that WGS at ~30x genuinely cannot see, so it understates +# the ranker exactly where the ranker is usable. Stratifying by ECS VAF separates +# "the model cannot rank" from "the data has no signal at this depth". +VAF_FLOORS = [0.005, 0.01, 0.02, 0.05, 0.10] + +DETECT_PATTERN = "LIKELY EDIT" +UNEVALUABLE_PATTERN = "INSUFFICIENT COVERAGE|NO CRAM" + +MANUAL_REVIEW_NOTE = ( + "Precision is NOT computable against the human manual review: that table has 55 " + "confirmed positives ('1'), 1 '1?', and 80,440 NaN, where NaN means UNREVIEWED, not " + "rejected. It contains no confirmed negatives, so any precision computed from it " + "would score every discovery the reviewers never reached as a false positive. All " + "precision/PR-AUC/F-beta figures in this file use the ECS label in training.tsv as " + "their denominator. Recall against human review is reported separately, and as " + "recall only, by bin/validate_recall.py." +) + + +def fbeta(precision, recall, beta): + """F_beta = (1 + b^2) * P * R / (b^2 * P + R); 0 when the denominator vanishes.""" + denom = (beta * beta * precision) + recall + if denom <= 0: + return 0.0 + return float((1.0 + beta * beta) * precision * recall / denom) + + +def build_masks(df, args): + """Split the training table into credible positives / negatives / ambiguous.""" + label = pd.to_numeric(df.get("label"), errors="coerce") + vaf = pd.to_numeric(df.get("ecs_if"), errors="coerce").fillna(0.0) + + gate = vaf >= args.min_ecs_vaf + warn = None + if "ecs_indel_reads" in df.columns: + reads = pd.to_numeric(df["ecs_indel_reads"], errors="coerce").fillna(0) + gate &= reads >= args.min_ecs_reads + elif args.min_ecs_reads > 0: + # Same guard as recall_vs_vaf.py: a table built before read support was carried + # through silently disables half the credibility gate. Warn, never pass quietly. + warn = (f"training table has no ecs_indel_reads column (produced before read " + f"support was carried through) — the --min-ecs-reads {args.min_ecs_reads} " + f"filter is INACTIVE and the positive set may still contain ECS noise") + print(f"WARN: {warn}", file=sys.stderr) + + pos = (label == 1) & gate + ambiguous = (label == 1) & ~gate + + if args.negatives == "ecs_negative" and "ecs_is_edit" in df.columns: + ecs_edit = pd.to_numeric(df["ecs_is_edit"], errors="coerce").fillna(0) + neg = (label == 0) & (ecs_edit == 0) + neg_germline = (label == 0) & (ecs_edit != 0) + else: + neg = (label == 0) + neg_germline = pd.Series(False, index=df.index) + + if args.ambiguous_as_negative: + neg = neg | ambiguous + ambiguous = pd.Series(False, index=df.index) + + return pos, neg, ambiguous, neg_germline, warn + + +def score_and_calls(df, hi): + """Continuous score + the reported operating point + the unevaluable mask. + + The operating point must be what the pipeline actually REPORTS. The scorer can call + a LIKELY EDIT via the high-evidence rescue at a sub-`hi` model score, so scoring the + raw threshold alone would under-count exactly those recovered edits. Prefer the + verdict; fall back to `score >= hi` only for verdict-less tables. Same precedence as + recall_vs_vaf.py, so the two files agree on what "detected" means. + """ + score = pd.to_numeric(df.get("score"), errors="coerce") + if "verdict" in df.columns: + verdict = df["verdict"].astype(str) + called = verdict.str.contains(DETECT_PATTERN, na=False) + uneval = verdict.str.contains(UNEVALUABLE_PATTERN, na=False) + criterion = f"verdict contains '{DETECT_PATTERN}'" + else: + called = (score >= hi).fillna(False) + uneval = score.isna() + criterion = f"score >= {hi} (table has no verdict column)" + return score, called, uneval, criterion + + +def ranking_metrics(y, s): + """PR-AUC / ROC-AUC on a finite-score, two-class subset. None when undefined.""" + from sklearn.metrics import average_precision_score, roc_auc_score + out = {"pr_auc": None, "roc_auc": None} + if len(y) == 0 or len(np.unique(y)) < 2: + return out + out["pr_auc"] = float(average_precision_score(y, s)) + out["roc_auc"] = float(roc_auc_score(y, s)) + return out + + +def evaluate(df, pos, neg, score, called, uneval, betas, criterion=None): + """Full metric block for one positive/negative definition.""" + m = pos | neg + y_all = pos[m].astype(int).to_numpy() + s_all = score[m].to_numpy() + called_all = called[m].to_numpy() + uneval_all = uneval[m].to_numpy() + + # Rows with no score (INSUFFICIENT COVERAGE / NO CRAM) are excluded from the ranking + # metrics: average_precision_score needs a continuous score, and filling them with 0 + # would fabricate confident negatives. They are counted, not hidden. + finite = np.isfinite(s_all) + y, s, pred = y_all[finite], s_all[finite], called_all[finite].astype(int) + + n_pos, n_neg = int((y == 1).sum()), int((y == 0).sum()) + block = { + "n_pos": n_pos, + "n_neg": n_neg, + "n_total": n_pos + n_neg, + "prevalence": float(y.mean()) if len(y) else None, + "n_excluded_no_score": int((~finite).sum()), + "n_excluded_no_score_pos": int((y_all[~finite] == 1).sum()), + "n_excluded_no_score_neg": int((y_all[~finite] == 0).sum()), + "n_unevaluable": int(uneval_all.sum()), + } + block.update(ranking_metrics(y, s)) + + tp = int(((pred == 1) & (y == 1)).sum()) + fp = int(((pred == 1) & (y == 0)).sum()) + fn = int(((pred == 0) & (y == 1)).sum()) + tn = int(((pred == 0) & (y == 0)).sum()) + precision = tp / (tp + fp) if (tp + fp) else 0.0 + recall = tp / (tp + fn) if (tp + fn) else 0.0 + + op = { + "criterion": criterion or f"verdict contains '{DETECT_PATTERN}'", + "tp": tp, "fp": fp, "fn": fn, "tn": tn, + "precision": float(precision), + "recall": float(recall), + "f1": fbeta(precision, recall, 1.0), + # Pessimistic view: charge the no-score positives against recall as well, the + # same split recall_vs_vaf.csv makes with recall vs recall_incl_unevaluable. + "recall_incl_unevaluable": ( + float(tp / int((y_all == 1).sum())) if int((y_all == 1).sum()) else None), + } + for b in betas: + op[f"f{_beta_key(b)}"] = fbeta(precision, recall, b) + block["operating_point"] = op + + # PR-AUC below prevalence is the "useless ranker or a bug" tripwire from the design + # notes. Here it is usually neither: it is the WGS depth floor showing up, because + # the credible-positive set is dominated by sub-1% VAF sites. Say so rather than + # emit a bare number that reads as a broken model. + if block["pr_auc"] is not None and block["prevalence"] is not None: + block["pr_auc_lift_over_prevalence"] = ( + float(block["pr_auc"] / block["prevalence"]) if block["prevalence"] else None) + return block + + +def _beta_key(b): + """2.0 -> '2', 2.5 -> '2.5' — keeps the common case reading as f2/f5.""" + return str(int(b)) if float(b).is_integer() else str(b) + + +def vaf_stratified(df, pos, neg, score, called, uneval, betas, args): + """PR-AUC vs prevalence as the ECS VAF floor on the POSITIVE set rises.""" + vaf = pd.to_numeric(df.get("ecs_if"), errors="coerce").fillna(0.0) + rows = [] + for floor in VAF_FLOORS: + if floor < args.min_ecs_vaf: + continue + p = pos & (vaf >= floor) + if int(p.sum()) == 0: + continue + b = evaluate(df, p, neg, score, called, uneval, betas) + rows.append({ + "ecs_vaf_floor": floor, + "n_pos": b["n_pos"], "n_neg": b["n_neg"], + "prevalence": b["prevalence"], "pr_auc": b["pr_auc"], + "pr_auc_lift_over_prevalence": b.get("pr_auc_lift_over_prevalence"), + "roc_auc": b["roc_auc"], + "recall": b["operating_point"]["recall"], + "precision": b["operating_point"]["precision"], + }) + return rows + + +def fmt(v, spec=".4f"): + return "n/a" if v is None or (isinstance(v, float) and not np.isfinite(v)) \ + else format(v, spec) + + +def render_text(out, betas): + """One screen. Every number carries the denominator it was computed against.""" + m = out["metrics"] + op = m["operating_point"] if m else None + L = [] + A = L.append + A("=" * 78) + A("OFF-TARGET CLINICAL METRICS — PR-AUC and recall-weighted F-beta") + A("=" * 78) + A(f"training table : {out['inputs']['training']}") + A(f"rows : {out['inputs']['n_rows']}") + A("") + A("-- DENOMINATOR 1 of 2: the ECS label (this is what every number below uses) --") + A(f" positives : label==1 AND ecs_if >= {out['inputs']['min_ecs_vaf']} " + f"AND ecs_indel_reads >= {out['inputs']['min_ecs_reads']}") + A(f" negatives : {out['inputs']['negatives']}" + f"{' (label==0 AND ecs_is_edit==0)' if out['inputs']['negatives'] == 'ecs_negative' else ' (all label==0)'}") + counts = out.get("counts") or {} + A(f" ambiguous : {counts.get('n_ambiguous', 0)} label==1 rows below the credibility " + f"floor — EXCLUDED, not counted as negatives") + if counts.get("n_germline_demoted_excluded"): + A(f" excluded : {counts['n_germline_demoted_excluded']} germline-demoted " + f"label==0 rows (indel in the matched normal; rejected by a separate gate)") + A("") + A("-- DENOMINATOR 2 of 2: the human manual review --") + for line in _wrap(MANUAL_REVIEW_NOTE, 74): + A(f" {line}") + A("") + if not m: + A(f"NOTE: {out['note']}") + A("=" * 78) + return "\n".join(L) + "\n" + + A("-- RANKING (score as a continuous ranker; ECS-label denominator) --") + A(f" n_pos / n_neg : {m['n_pos']} / {m['n_neg']} prevalence {fmt(m['prevalence'])}") + A(f" PR-AUC : {fmt(m['pr_auc'])}" + + (f" ({fmt(m.get('pr_auc_lift_over_prevalence'), '.2f')}x prevalence)" + if m.get("pr_auc_lift_over_prevalence") is not None else "")) + A(f" ROC-AUC : {fmt(m['roc_auc'])} (kept for continuity; not the headline " + f"at low prevalence)") + A(f" excluded, no score : {m['n_excluded_no_score']} " + f"({m['n_excluded_no_score_pos']} pos / {m['n_excluded_no_score_neg']} neg) — " + f"INSUFFICIENT COVERAGE / NO CRAM, never filled with 0") + A("") + A(f"-- OPERATING POINT ({op['criterion']}; ECS-label denominator) --") + A(f" TP {op['tp']} FP {op['fp']} FN {op['fn']} TN {op['tn']}") + A(f" precision (vs ECS label, NOT vs human review) : {fmt(op['precision'])}") + A(f" recall : {fmt(op['recall'])}") + A(f" recall incl. unevaluable : {fmt(op['recall_incl_unevaluable'])}") + A(f" {'F1':<44s}: {fmt(op['f1'])}") + for b in betas: + k = f"f{_beta_key(b)}" + A(f" {f'F{_beta_key(b)} (recall weighted {b * b:g}x)':<44s}: {fmt(op[k])}") + A("") + if out["by_vaf_floor"]: + A("-- BY ECS VAF FLOOR ON THE POSITIVE SET --") + A(" (a single PR-AUC over all credible positives is dominated by sub-1% VAF") + A(" sites that WGS at ~30x cannot see; this separates ranker from depth floor)") + A(f" {'vaf>=':>7} {'n_pos':>6} {'n_neg':>6} {'prev':>7} {'PR-AUC':>7} {'lift':>6} {'ROC':>6}") + for r in out["by_vaf_floor"]: + A(f" {r['ecs_vaf_floor']:>7g} {r['n_pos']:>6} {r['n_neg']:>6} " + f"{fmt(r['prevalence'], '.3f'):>7} {fmt(r['pr_auc'], '.3f'):>7} " + f"{fmt(r.get('pr_auc_lift_over_prevalence'), '.2f'):>6} " + f"{fmt(r['roc_auc'], '.3f'):>6}") + A("") + if out["sensitivity"]: + A("-- SENSITIVITY: the same score under other defensible denominators --") + for s in out["sensitivity"]: + A(f" {s['definition']:<34} n_pos {s['n_pos']:>5} n_neg {s['n_neg']:>5} " + f"prev {fmt(s['prevalence'], '.3f')} PR-AUC {fmt(s['pr_auc'], '.3f')}") + A("") + if out["notes"]: + A("-- NOTES --") + for n in out["notes"]: + for line in _wrap(n, 74): + A(f" {line}") + A("") + A("=" * 78) + return "\n".join(L) + "\n" + + +def _wrap(text, width): + words, line, lines = text.split(), "", [] + for w in words: + if line and len(line) + 1 + len(w) > width: + lines.append(line) + line = w + else: + line = f"{line} {w}".strip() + if line: + lines.append(line) + return lines + + +def main(): + ap = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--training", required=True, + help="training.tsv from join_training_table.py (needs label + score)") + ap.add_argument("--hi", type=float, default=0.60, + help="score threshold; used only when the table has no verdict column") + ap.add_argument("--min-ecs-vaf", type=float, default=0.005, + help="positive set: ECS VAF floor below which a call is assay noise") + ap.add_argument("--min-ecs-reads", type=int, default=5, + help="positive set: ECS indel reads required to believe a site") + ap.add_argument("--beta", type=float, action="append", default=None, metavar="B", + help="F-beta weight; repeatable (default: 2 and 5)") + ap.add_argument("--betas", help="comma-separated F-beta weights, e.g. '2,5'") + ap.add_argument("--negatives", choices=["ecs_negative", "all_label0"], + default="ecs_negative", + help="ecs_negative (default) = label==0 AND ecs_is_edit==0; " + "all_label0 also includes germline-demoted ECS edits") + ap.add_argument("--ambiguous-as-negative", action="store_true", + help="treat sub-credibility label==1 rows as negatives (NOT the " + "default: ECS saw something there, so calling them negative is " + "an assumption the data does not support)") + ap.add_argument("--out-json", default="offtarget_metrics.json") + ap.add_argument("--out-txt", default="offtarget_metrics.txt") + ap.add_argument("--out-curve", default=None, help="optional PR-curve PNG") + args = ap.parse_args() + + betas = [] + if args.betas: + betas += [float(b) for b in args.betas.replace(" ", "").split(",") if b] + if args.beta: + betas += list(args.beta) + betas = sorted(set(betas)) or [2.0, 5.0] + + df = pd.read_csv(args.training, sep="\t") + notes = [] + + out = { + "inputs": { + "training": args.training, + "n_rows": int(len(df)), + "min_ecs_vaf": args.min_ecs_vaf, + "min_ecs_reads": args.min_ecs_reads, + "negatives": args.negatives, + "ambiguous_as_negative": bool(args.ambiguous_as_negative), + "betas": betas, + "hi": args.hi, + }, + "denominators": { + "metrics_denominator": ( + "ECS label in training.tsv: positives are label==1 gated to credible ECS " + "edits (ecs_if >= min_ecs_vaf AND ecs_indel_reads >= min_ecs_reads); " + f"negatives are '{args.negatives}'."), + "manual_review_denominator": MANUAL_REVIEW_NOTE, + }, + "counts": {}, "metrics": None, "by_vaf_floor": [], "sensitivity": [], + "notes": notes, "note": None, + } + + if "label" not in df.columns or "score" not in df.columns: + out["note"] = ("training table lacks a 'label' and/or 'score' column — no metrics " + "computable") + _emit(out, betas, args) + return + + pos, neg, ambiguous, neg_germline, warn = build_masks(df, args) + if warn: + notes.append(warn) + score, called, uneval, criterion = score_and_calls(df, args.hi) + + out["counts"] = { + "n_positives_credible": int(pos.sum()), + "n_negatives": int(neg.sum()), + "n_ambiguous": int(ambiguous.sum()), + "n_germline_demoted_excluded": int(neg_germline.sum()), + "n_somatic_label1_total": int((pd.to_numeric(df["label"], errors="coerce") == 1).sum()), + } + + # Degenerate cases are legitimate results, not errors: a run with no credible edits + # still has to publish a file. Emit nulls plus an explanatory note and exit 0. + if int(pos.sum()) == 0 or int(neg.sum()) == 0: + out["note"] = ( + f"single-class evaluation set ({int(pos.sum())} credible positives, " + f"{int(neg.sum())} negatives) — PR-AUC and F-beta are undefined. This is a " + f"legitimate outcome for a run with no credible ECS edits, not a failure.") + _emit(out, betas, args) + return + + out["metrics"] = evaluate(df, pos, neg, score, called, uneval, betas, criterion) + + if out["metrics"]["n_pos"] == 0 or out["metrics"]["n_neg"] == 0: + out["note"] = ("every row of one class had a NaN score (INSUFFICIENT COVERAGE / " + "NO CRAM) — ranking metrics undefined on the evaluable subset") + + out["by_vaf_floor"] = vaf_stratified(df, pos, neg, score, called, uneval, betas, args) + + # Sensitivity: show what the other defensible denominators would give, so the one + # judgement call in here is visible rather than buried in a default. + for definition, p2, n2 in _alternatives(df, pos, neg, ambiguous, neg_germline, args): + b = evaluate(df, p2, n2, score, called, uneval, betas) + out["sensitivity"].append({ + "definition": definition, "n_pos": b["n_pos"], "n_neg": b["n_neg"], + "prevalence": b["prevalence"], "pr_auc": b["pr_auc"], "roc_auc": b["roc_auc"], + }) + + m = out["metrics"] + if m["pr_auc"] is not None and m["prevalence"] and m["pr_auc"] <= m["prevalence"]: + notes.append( + f"PR-AUC ({m['pr_auc']:.3f}) does not exceed prevalence " + f"({m['prevalence']:.3f}): over this positive set the score adds no ranking " + f"power. Check the by-VAF-floor table before concluding the model is broken " + f"— the credible-positive set is usually dominated by sub-1% VAF sites that " + f"WGS at ~30x cannot see, and the lift typically rises sharply with the VAF " + f"floor. A flat lift at every floor does indicate a real problem.") + + _emit(out, betas, args) + + +def _alternatives(df, pos, neg, ambiguous, neg_germline, args): + """(label, positives, negatives) triples for the sensitivity block.""" + alts = [] + if int(neg_germline.sum()): + alts.append(("negatives = all label==0", pos, neg | neg_germline)) + if int(ambiguous.sum()) and not args.ambiguous_as_negative: + alts.append(("+ sub-credibility as negative", pos, neg | ambiguous)) + label = pd.to_numeric(df.get("label"), errors="coerce") + ungated = (label == 1) + if int(ungated.sum()) != int(pos.sum()): + alts.append(("ungated label==1 (ECS noise incl.)", ungated, neg)) + return alts + + +def _emit(out, betas, args): + with open(args.out_json, "w") as fh: + json.dump(out, fh, indent=2) + text = render_text(out, betas) + with open(args.out_txt, "w") as fh: + fh.write(text) + print(text) + print(f"wrote {args.out_json} and {args.out_txt}") + if args.out_curve: + _plot(out, args) + + +def _plot(out, args): + """PR curve with the operating point marked. A nicety — the JSON is the truth.""" + try: + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + from sklearn.metrics import precision_recall_curve + + df = pd.read_csv(args.training, sep="\t") + pos, neg, _amb, _gd, _w = build_masks(df, args) + score, called, _u, _c = score_and_calls(df, args.hi) + m = pos | neg + y = pos[m].astype(int).to_numpy() + s = score[m].to_numpy() + ok = np.isfinite(s) + y, s, pred = y[ok], s[ok], called[m].to_numpy()[ok] + if len(np.unique(y)) < 2: + print("(PR curve not rendered: single-class evaluation set)") + return + p, r, _ = precision_recall_curve(y, s) + op = out["metrics"]["operating_point"] + fig, ax = plt.subplots(figsize=(7, 4.5)) + ax.plot(r, p, "-", color="#2b6cb0", label=f"PR-AUC = {out['metrics']['pr_auc']:.3f}") + ax.axhline(out["metrics"]["prevalence"], ls="--", color="#a0aec0", + label=f"prevalence = {out['metrics']['prevalence']:.3f}") + ax.plot([op["recall"]], [op["precision"]], "o", color="#c53030", ms=9, + label=f"LIKELY EDIT (P={op['precision']:.2f}, R={op['recall']:.2f})") + ax.set_xlabel("recall") + ax.set_ylabel("precision (vs ECS label — NOT vs human review)") + ax.set_xlim(-0.02, 1.02) + ax.set_ylim(-0.02, 1.02) + ax.set_title("WGS shape score — precision/recall vs the ECS label") + fig.text(0.5, 0.005, + f"denominator = {out['metrics']['n_pos']} credible ECS edits vs " + f"{out['metrics']['n_neg']} ECS-negatives; precision here is against the " + f"ECS label, never against human review", + ha="center", fontsize=7, color="#4a5568") + ax.legend(loc="upper right", fontsize=8) + fig.tight_layout() + fig.savefig(args.out_curve, dpi=130) + print(f"wrote {args.out_curve}") + except Exception as e: + print(f"(PR curve not rendered: {e})") + + +if __name__ == "__main__": + main() diff --git a/bin/panel_overlap.py b/bin/panel_overlap.py new file mode 100644 index 0000000..22f2bb6 --- /dev/null +++ b/bin/panel_overlap.py @@ -0,0 +1,506 @@ +#!/usr/bin/env python3 +"""panel_overlap.py — measure the DRAGEN systematic-noise panels as standalone filters. + +Why this exists +--------------- +Two questions were asked of the panels and answered once, in prose, in +docs/CALLER_INTEGRATION_LOG.md — but the script that produced those numbers was never kept, so +nothing could be re-measured when the caller changed underneath them. This restores that +capability and answers both questions on whatever run is handed to it: + + * indels — how many calls overlap a noisy SNV locus in + `IDPF_WGS_hg38_v.2.0.0_systematic_noise.snv.bed.gz`, and does that overlap track truth? + * breakends — how many junctions overlap a record in each of the three + `*_systematic_noise.sv.bedpe.gz` panels? + +What it is NOT +-------------- +This does not filter anything and is not called by the pipeline. It reuses the shipped matching +code (`review_filter.load_snv_noise` / `snv_noise_mask`, `review_filter_bnd.load_sv_noise` / +`in_noise`) so that what it reports is what the pipeline would do, not a second implementation +that could drift. + +The one deliberate departure, and why +------------------------------------- +The shipped SNV loader keeps ONE record per position — the one with the most donors — because the +shipped rule only ever asks a single yes/no question. That is lossy for the question asked here: +an SNV-only record with 20 donors shadows an indel record with 2 at the same coordinate, so the +counts for "any indel-capable record" would come out too low. This script therefore loads every +record per position via `load_snv_noise_all`, reports the three overlap definitions honestly, and +then re-runs the shipped loader + mask and reports whether the two agree. A disagreement is a real +defect in the shipped rule, not a bookkeeping detail, so it is printed rather than smoothed over. + +BREAKENDS: the on-target exemption is DISABLED here, on purpose. The shipped rule exempts +`is_target == 1` junctions from the panel check, and on this cohort every gated junction is +on-target — so with the exemption on, the answer to "how many junctions does the panel flag?" is +trivially zero and tells you nothing about the panel. The question is about the panel's +discrimination, so the exemption is turned off and that is stated in the output. + +usage: + panel_overlap.py --tables 'results_cart_bnd/*/*.offtarget_analysis.tsv' \ + --queue-all results_cart_bnd/review/review_queue_all.tsv \ + --snv-noise .../IDPF_WGS_hg38_v.2.0.0_systematic_noise.snv.bed.gz \ + --truth-wgs '.../cart_wgs_merged.xlsx' \ + --sv-noise .../WGS_hg38_v3.1.0_systematic_noise.sv.bedpe.gz \ + --sv-noise .../IDPF_WGS_hg38_v3.0.0_systematic_noise.sv.bedpe.gz \ + --sv-noise .../WGS_FF_Heme_hg38_v3.1.0_systematic_noise.sv.bedpe.gz +""" +import argparse +import collections +import glob +import bisect +import gzip +import os +import sys + +import numpy as np +import pandas as pd + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import noise_model as nm # noqa: E402 +import review_filter as rf # noqa: E402 +import review_filter_bnd as rfb # noqa: E402 + +SLOP = rf.SNV_NOISE_SLOP +MIN_DONORS = 3 + + +# --------------------------------------------------------------------------------------------- +# SNV panel +# --------------------------------------------------------------------------------------------- +def load_snv_noise_all(path, positions, slop=SLOP): + """Same file and same columns as review_filter.load_snv_noise, but keeps EVERY record. + + -> {(chrom, pos): [(max_noise, n_donors, alleles), ...]} + + The shipped loader keeps only the record with the most donors; see the module docstring for + why that is not good enough to count overlap definitions against each other. + """ + want = collections.defaultdict(set) + for c, e in positions: + for d in range(-slop, slop + 1): + want[c].add(int(e) + d) + hits = collections.defaultdict(list) + op = gzip.open if str(path).endswith(".gz") else open + with op(path, "rt") as f: + for line in f: + if line[0] == "#": + continue + p = line.rstrip("\n").split("\t") + if len(p) < 7: + continue + s = want.get(p[0]) + if s is None: + continue + try: + pos = int(p[2]) + if pos not in s: + continue + hits[(p[0], pos)].append((float(p[4]), int(p[6]), p[5])) + except ValueError: + continue + return hits + + +def is_indel_record(rec): + """The panel's allele column is a comma list; D and I are its indel codes.""" + return "D" in rec[2] or "I" in rec[2] + + +def overlap_flags(hits_all, chroms, ends, min_donors=MIN_DONORS, slop=SLOP): + """Three nested overlap definitions per site, as boolean arrays. + + any -- the panel says anything at all here + indel -- the panel says something indel-capable here + shipped -- indel-capable AND recurrent in >= min_donors donors (what review_filter uses) + """ + a, i, s = [], [], [] + for c, e in zip(chroms, ends): + recs = [] + for d in range(-slop, slop + 1): + recs.extend(hits_all.get((c, int(e) + d), ())) + ind = [r for r in recs if is_indel_record(r)] + a.append(bool(recs)) + i.append(bool(ind)) + s.append(any(r[1] >= min_donors for r in ind)) + return np.array(a), np.array(i), np.array(s) + + +def confusion(flag, label): + """2x2 for the panel used as a standalone filter. + + The panel flags NOISE, so a flagged row is a predicted negative. Reported from the point of + view of the filter's job: does flagging remove rejected rows and spare confirmed ones? + """ + flag, label = np.asarray(flag, bool), np.asarray(label, int) + tp = int((flag & (label == 0)).sum()) # correctly flagged an artifact + fp = int((flag & (label == 1)).sum()) # flagged a real edit -- the expensive error + fn = int((~flag & (label == 0)).sum()) # missed an artifact + tn = int((~flag & (label == 1)).sum()) # correctly spared a real edit + div = lambda a, b: a / b if b else float("nan") # noqa: E731 + return dict(flagged_rejected=tp, flagged_confirmed=fp, missed_rejected=fn, + spared_confirmed=tn, + sensitivity=div(tp, tp + fn), # of artifacts, how many caught + specificity=div(tn, tn + fp), # of real edits, how many spared + precision=div(tp, tp + fp)) # of flagged rows, how many really artifacts + + +def snv_report(df, queue_all, snv_noise, truth_wgs, min_donors, out, cache=None): + print("\n" + "=" * 94) + print("ASK #2 — the SNV panel as an indel filter") + print("=" * 94) + print(f"panel : {snv_noise}") + print(f"slop : +/-{SLOP} bp shipped rule: indel-capable AND >= {min_donors} donors") + + positions = set(zip(df.chrom.astype(str), df.end.astype(int))) + if cache and os.path.exists(cache): + hits_all = pd.read_pickle(cache) + print(f"\npanel hits loaded from cache {cache}") + else: + print(f"\nstreaming the panel for {len(positions)} distinct positions (~1 GB, 2-3 min)...") + hits_all = load_snv_noise_all(snv_noise, positions) + if cache: + pd.to_pickle(dict(hits_all), cache) + print(f"panel records retained at queried positions: {sum(len(v) for v in hits_all.values())} " + f"at {len(hits_all)} positions") + + # The shipped path, run exactly as review_filter runs it, for the agreement check below. + # Derived from the same full record set so the file is streamed once, not twice: keeping only + # the highest-donor record per position is precisely what load_snv_noise does. + hits_shipped = {k: max(v, key=lambda r: r[1]) for k, v in hits_all.items()} + + levels = [("all site-rows", df)] + if queue_all is not None: + levels.append(("gated rows", queue_all)) + kept = queue_all[queue_all.why_dropped.fillna("") == ""] + levels.append(("review queue", kept)) + + rows = [] + for name, d in levels: + any_, ind, ship = overlap_flags(hits_all, d.chrom.astype(str), d.end.astype(int), + min_donors) + rows.append(dict(population=name, n=len(d), + any_record=int(any_.sum()), indel_record=int(ind.sum()), + shipped_rule=int(ship.sum()))) + tab = pd.DataFrame(rows) + for c in ("any_record", "indel_record", "shipped_rule"): + tab[c + "_pct"] = (tab[c] / tab.n * 100).round(2) + print("\n-- overlap counts at three population levels --") + print(tab.to_string(index=False)) + + # Agreement between the two loaders. A mismatch means the shipped rule missed an indel record + # because a higher-donor SNV record at the same position shadowed it. + _, _, ship_full = overlap_flags(hits_all, df.chrom.astype(str), df.end.astype(int), min_donors) + ship_pipe = np.array(rf.snv_noise_mask(hits_shipped, df.chrom.astype(str), + df.end.astype(int), min_donors)) + shadowed = int((ship_full & ~ship_pipe).sum()) + print(f"\n-- shipped-loader agreement --") + print(f"shipped rule, all records kept : {int(ship_full.sum())}") + print(f"shipped rule, as the pipeline runs it : {int(ship_pipe.sum())}") + if shadowed: + print(f"*** {shadowed} site(s) carry an indel record that the one-record-per-position " + f"loader discards ***\n (an SNV-only record with more donors shadows it; the " + f"pipeline under-flags by this much)") + else: + print("identical — no indel record is shadowed at any queried position on this run") + + # ---- truth ---- + # Scored against TWO populations, because they answer different questions and the panel looks + # materially different on each. All site-rows asks "could this replace the noise model as a + # general filter?"; gated rows asks "what does it add where the pipeline actually applies it?" + # -- review_filter.py only ever runs this rule on gated rows, so the second is the operational + # number. Sensitivity is roughly 1.5x higher on gated rows, because those are already enriched + # for the recurrent-locus artifacts the panel can see, while the full table is dominated by + # sites carrying no indel evidence at all. Quoting one without naming it invites the reader to + # apply it to the other. + if truth_wgs: + lab = nm.wgs_curated_label(truth_wgs) + pops = [("ALL site-rows", df)] + if queue_all is not None: + pops.append(("GATED rows (operational)", queue_all)) + for pop_name, frame in pops: + d = frame.copy() + d["guide"] = d.sample_name.map(nm.guide_of) + d["chrom"] = d.chrom.astype(str) + m = d.merge(lab, on=["guide", "chrom", "start"], how="inner") + if not len(m): + continue + n_neg = int((m.curated_label == 0).sum()) + print(f"\n-- the panel against the curated WGS label: {pop_name} --") + print(f"joined {len(m)} labelled rows: {int((m.curated_label==1).sum())} confirmed / " + f"{n_neg} human-rejected") + # Precision on a mostly-negative set is flattered by prevalence, so print what a filter + # that flagged EVERY row would score. Anything at or below that line has learned nothing. + print(f"base rate: flagging every row would score precision {n_neg/len(m):.3f} " + f"at sensitivity 1.000") + any_, ind, ship = overlap_flags(hits_all, m.chrom, m.end.astype(int), min_donors) + for defn, flag in (("any panel record", any_), ("indel-capable record", ind), + (f"shipped rule (>={min_donors} donors & D/I)", ship)): + c = confusion(flag, m.curated_label.values) + print(f" {defn:38s} flagged {int(flag.sum()):4d} " + f"sens {c['sensitivity']:.3f} spec {c['specificity']:.3f} " + f"prec {c['precision']:.3f} (real edits flagged: {c['flagged_confirmed']})") + + # ---- the decomposition that settles the substitution question ---- + if queue_all is not None: + print("\n-- can the panel stand in for rule 1 (germline in the matched control)? --") + wd = queue_all.why_dropped.fillna("") + germ = queue_all[wd == "germline (present in control)"] + any_, ind, ship = overlap_flags(hits_all, germ.chrom.astype(str), germ.end.astype(int), + min_donors) + print(f"rows rule 1 dropped as germline: {len(germ)}") + print(f" of those, panel flags: any {int(any_.sum())} indel-capable {int(ind.sum())}" + f" shipped rule {int(ship.sum())}") + print(" Germline is a property of ONE donor. A 46-donor panel reports a population") + print(" average, so it cannot represent one donor's genotype at any panel size.") + # Which germline sites the panel DOES see is the informative half: a population panel can + # only recognise a population-common allele, so the overlap should concentrate on the + # sites where many donors carry it. + dons = [] + for c, e in zip(germ.chrom.astype(str), germ.end.astype(int)): + best = 0 + for d in range(-SLOP, SLOP + 1): + for r in hits_all.get((c, int(e) + d), ()): + best = max(best, r[1]) + dons.append(best) + dons = np.array(dons) + print(f" donor support at the germline sites the panel does see: " + f"median {int(np.median(dons[dons>0])) if (dons>0).any() else 0}, " + f"max {int(dons.max())} (of 46 panel donors)") + print(f" germline rows invisible to the panel entirely: {int((dons==0).sum())}" + f"/{len(germ)} = {(dons==0).mean()*100:.0f}%") + + if out: + tab.to_csv(out, sep="\t", index=False) + print(f"\nwrote {out}") + + +# --------------------------------------------------------------------------------------------- +# SV panels +# --------------------------------------------------------------------------------------------- +def sv_donor_index(path): + """Breakpoint intervals with the set of DONORS supporting each, plus total bp covered. + + The BEDPE carries no donor-count column and no `##PON SAMPLES` header, so there is no direct + analogue of the SNV panel's `n_donors` -- which is the very statistic that makes the SNV panel + usable, since it is what separates a recurrent artifact from a one-donor coincidence. + + It is recoverable anyway: field 7 is a candidate NAME that embeds the donor it came from, + e.g. `ImpreciseNoiseCandidate_LP7108672-DNA_A06_42_DRAGEN:BND:...`. One record is one candidate + from one donor, so pooling records by interval and counting distinct donors reconstructs the + missing column. This measures whether doing so would rescue the large panels. + + -> ({chrom: (starts, ends, donorsets)}, covered_bp, n_records) + """ + iv = collections.defaultdict(list) + n_rec = 0 + op = gzip.open if str(path).endswith(".gz") else open + with op(path, "rt") as f: + for line in f: + if line.startswith("#"): + continue + p = line.rstrip("\n").split("\t") + if len(p) < 7: + continue + name = p[6] + # strip the NoiseCandidate prefix and the trailing __DRAGEN:... suffix + d = name.split("_", 1)[-1] + d = d.split("_DRAGEN:")[0] + d = d.rsplit("_", 1)[0] if d.rsplit("_", 1)[-1].isdigit() else d + try: + iv[p[0]].append((int(p[1]), int(p[2]), d)) + iv[p[3]].append((int(p[4]), int(p[5]), d)) + except ValueError: + continue + n_rec += 1 + merged, covered = {}, 0 + for c, v in iv.items(): + v.sort() + st, en, ds = [], [], [] + for s, e, d in v: + if st and s <= en[-1]: + en[-1] = max(en[-1], e) + ds[-1].add(d) + else: + st.append(s); en.append(e); ds.append({d}) + merged[c] = (st, en, ds) + covered += sum(b - a for a, b in zip(st, en)) + return merged, covered, n_rec + + +def donors_at(merged, chrom, pos, slop): + if chrom not in merged: + return set() + st, en, ds = merged[chrom] + i = bisect.bisect_right(st, pos + slop) - 1 + if i >= 0 and st[i] - slop <= pos <= en[i] + slop: + return ds[i] + return set() + + +def sv_report(junctions, panels, slops, extra_artifacts=None): + print("\n" + "=" * 94) + print("ASK #3 — the SV panels as a breakend filter") + print("=" * 94) + print("ON-TARGET EXEMPTION DISABLED. Every gated junction on this cohort is is_target==1, so") + print("the shipped rule flags nothing by construction; that would answer the wrong question.") + + gated = junctions[junctions.reads >= rfb.MIN_READS] + sets = [("all junctions", junctions), (f"gated (reads>={rfb.MIN_READS})", gated)] + if extra_artifacts is not None and len(extra_artifacts): + sets.append(("dropped junctions (artifacts)", extra_artifacts)) + + rows, donor_rows = [], [] + cache = {} # path -> (name, merged, covered); the BEDPEs are 2.6M + # records and parsing one twice costs minutes + gate_slop = rfb.SV_NOISE_SLOP + for path in panels: + name = os.path.basename(path).replace("_systematic_noise.sv.bedpe.gz", "") + print(f"\nloading {name} ...") + merged = rfb.load_sv_noise(path) + n_iv = sum(len(v[0]) for v in merged.values()) + dmerged, covered, n_rec = sv_donor_index(path) + cache[path] = (name, merged, covered) + print(f" {n_rec} BEDPE records -> {n_iv} merged breakpoint intervals over " + f"{len(merged)} contigs") + print(f" genome covered by those intervals: {covered/1e6:.1f} Mb " + f"({covered/3.1e9*100:.2f}% of hg38)") + for slop in slops: + for label, s in sets: + flag = [rfb.in_noise(merged, c, p, slop) or rfb.in_noise(merged, c2, p2, slop) + for c, p, c2, p2 in zip(s.chrom, s.pos, s.chrom2, s.pos2)] + rows.append(dict(panel=name, slop=slop, population=label, n=len(s), + flagged=int(np.sum(flag)), covered_mb=round(covered / 1e6, 1))) + + # Donor support behind the hits on the gated junctions, at the shipped slop. + nd = [] + for c, p, c2, p2 in zip(gated.chrom, gated.pos, gated.chrom2, gated.pos2): + d = donors_at(dmerged, c, p, gate_slop) | donors_at(dmerged, c2, p2, gate_slop) + nd.append(len(d)) + nd = np.array(nd) + donor_rows.append(dict(panel=name, hit=int((nd > 0).sum()), + single_donor=int((nd == 1).sum()), + ge2=int((nd >= 2).sum()), ge3=int((nd >= 3).sum()), + max_donors=int(nd.max()) if len(nd) else 0)) + + # -------------------------------------------------------------------------------------- + # Is a hit INFORMATIVE? Two things have to be true, and the raw flag count shows neither. + # + # against the null a junction has two endpoints, so a panel covering fraction c of the + # genome flags a randomly placed junction 1-(1-c)^2 of the time. At + # c = 0.63 that is 86% before any biology. A flag rate at the null is + # not evidence, however large it looks. + # right direction a noise panel must flag ARTEFACTS more than REAL events. The closest + # contrast available here is off-target (mostly noise at these depths) + # vs on-target (a nominated cut site, so a genuine editing outcome). + # An odds ratio below 1 means the panel prefers the real edits, which + # is worse than useless -- and is survivable only because rule 4 + # exempts on-target sites. That exemption is load-bearing, not tidying. + # + # The contrast is a PROXY, not ground truth: not every off-target row is an artefact and + # not every on-target row is real. It is sound for direction, not for a precision figure. + # -------------------------------------------------------------------------------------- + print("\n-- is a hit informative? flag rate vs the coverage null, and which way it points --") + print(f" {'panel':<22} {'cov':>7} {'null':>7} {'obs':>7} {'obs/null':>9} " + f"{'on-tgt':>8} {'off-tgt':>8} {'OR':>7} {'95% CI':>16} direction") + on = (junctions.is_target == 1).to_numpy() + for path in panels: + name, merged, covered = cache[path] + cov = covered / 3.1e9 + null = 1 - (1 - cov) ** 2 + flag = np.array([rfb.in_noise(merged, c, p, gate_slop) + or rfb.in_noise(merged, c2, p2, gate_slop) + for c, p, c2, p2 in zip(junctions.chrom, junctions.pos, + junctions.chrom2, junctions.pos2)]) + obs = flag.mean() + a11, a10 = int((flag & ~on).sum()), int((~flag & ~on).sum()) + a01, a00 = int((flag & on).sum()), int((~flag & on).sum()) + h = 0.5 if min(a11, a10, a01, a00) == 0 else 0.0 + lor = np.log(((a11 + h) * (a00 + h)) / ((a10 + h) * (a01 + h))) + se = np.sqrt(sum(1.0 / (x + h) for x in (a11, a10, a01, a00))) + lo, hi = np.exp(lor - 1.96 * se), np.exp(lor + 1.96 * se) + direction = ("enriches artefacts (useful)" if lo > 1 else + "ENRICHES REAL EDITS (backwards)" if hi < 1 else + "no discrimination (CI spans 1)") + print(f" {name:<22} {cov*100:6.1f}% {null*100:6.1f}% {obs*100:6.1f}% " + f"{obs/max(null,1e-9):9.2f} {flag[on].mean()*100:7.1f}% " + f"{flag[~on].mean()*100:7.1f}% {np.exp(lor):7.2f} [{lo:5.2f},{hi:6.2f}]" + f" {direction}") + print(" on-target n = %d, off-target n = %d" % (int(on.sum()), int((~on).sum()))) + + tab = pd.DataFrame(rows) + tab["pct"] = (tab.flagged / tab.n * 100).round(1) + print("\n-- flagged counts (either end in a panel interval) --") + for slop in slops: + print(f"\nslop {slop} bp:") + print(tab[tab.slop == slop].pivot(index="panel", columns="population", + values="flagged").to_string()) + + print(f"\n-- donor support behind the hits on the {len(gated)} gated junctions " + f"(slop {gate_slop}) --") + print("reconstructed from the BEDPE name field; see sv_donor_index()") + print(pd.DataFrame(donor_rows).to_string(index=False)) + print("\nIf a panel's hits are mostly SINGLE-donor, a min_donors rule -- the same thing that") + print("makes the SNV panel usable -- would restore its specificity. If they are multi-donor,") + print("the panel genuinely covers these loci and no threshold rescues it.") + return tab + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--tables", required=True, + help="glob for *.offtarget_analysis.tsv (quote it)") + ap.add_argument("--queue-all", help="review_queue_all.tsv (gated rows with why_dropped)") + ap.add_argument("--snv-noise", help="systematic_noise.snv.bed.gz") + ap.add_argument("--min-donors", type=int, default=MIN_DONORS) + ap.add_argument("--truth-wgs", help="cart_wgs_merged.xlsx") + ap.add_argument("--sv-noise", action="append", default=[], + help="systematic_noise.sv.bedpe.gz (repeatable)") + ap.add_argument("--sv-slop", type=int, nargs="+", default=[0, 50, 200]) + ap.add_argument("--extra-bnd-queue", action="append", default=[], + help="bnd_review_queue_all.tsv from another run, to recover an artifact set " + "(rows with a non-empty why_dropped)") + ap.add_argument("--snv-cache", help="pickle the streamed panel hits here and reuse them") + ap.add_argument("--outdir", default=".") + a = ap.parse_args() + + paths = sorted(glob.glob(a.tables)) + if not paths: + sys.exit(f"no tables matched {a.tables}") + df = nm.load_tables(paths) + print(f"tables {len(paths)} site-rows {len(df)}") + + queue_all = pd.read_csv(a.queue_all, sep="\t") if a.queue_all else None + if queue_all is not None: + print(f"gated rows {len(queue_all)} queue " + f"{int((queue_all.why_dropped.fillna('') == '').sum())}") + + os.makedirs(a.outdir, exist_ok=True) + + if a.snv_noise: + snv_report(df, queue_all, a.snv_noise, a.truth_wgs, a.min_donors, + os.path.join(a.outdir, "panel_overlap_snv.tsv"), a.snv_cache) + + if a.sv_noise: + events = [] + for p in paths: + d = pd.read_csv(p, sep="\t") + events += rfb.parse_bnds(d, os.path.basename(p).split(".offtarget")[0]) + junctions = pd.DataFrame(events) + print(f"\njunction entries {len(junctions)}") + + arts = [] + for p in a.extra_bnd_queue: + q = pd.read_csv(p, sep="\t") + arts.append(q[q.why_dropped.fillna("") != ""]) + extra = pd.concat(arts, ignore_index=True) if arts else None + + tab = sv_report(junctions, a.sv_noise, a.sv_slop, extra) + o = os.path.join(a.outdir, "panel_overlap_sv.tsv") + tab.to_csv(o, sep="\t", index=False) + print(f"\nwrote {o}") + + +if __name__ == "__main__": + main() diff --git a/bin/parse_input_samplesheet.py b/bin/parse_input_samplesheet.py index 0b6da55..a13247a 100755 --- a/bin/parse_input_samplesheet.py +++ b/bin/parse_input_samplesheet.py @@ -60,10 +60,8 @@ def process_input(input_file: str, output_dir: str) -> None: tumor_df = df[common_cols].copy() tumor_df['sample_type'] = 'tumor' - tumor_df['individual_id'] = tumor_df['id'] normal_df = df[common_cols].copy() normal_df['sample_type'] = 'normal' - normal_df['individual_id'] = normal_df['id'] tumor_df['id'] = df['tumor_id'] normal_df['id'] = df['normal_id'] diff --git a/bin/pileup_snapshot.py b/bin/pileup_snapshot.py new file mode 100755 index 0000000..9c598b7 --- /dev/null +++ b/bin/pileup_snapshot.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +""" +pileup_snapshot.py — render an IGV-style read-pileup image at a locus straight +from the CRAM, so a reviewer confirms an edit by eye without opening IGV. Designed +to be a PIPELINE STEP: point it at score.py's worklist and it emits one PNG per +candidate (auto-review packet). + +Reads are packed into rows (IGV-style), aligned blocks drawn as grey bars, +deletions as red gaps, insertions as purple ticks, soft-clips as faint blue. The +candidate position is a dashed vertical line. Title carries the call metadata. +""" +import os, sys, argparse +import numpy as np +import pysam +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +from matplotlib.patches import Rectangle + +REF = "/storage2/fs1/dspencer/Active/spencerlab/rotating_students/btyler/seqs/hg38_mgi_patch.fa" + +# CIGAR: 0=M 1=I 2=D 3=N 4=S 5=H 7== 8=X +REF_CONSUME = {0, 2, 3, 7, 8} +QUERY_CONSUME = {0, 1, 4, 7, 8} + + +def read_blocks(read): + """Return (aligned_blocks, deletions, insertions, softclips) in ref coords. + + Soft clips are (anchor, length, is_leading). A LEADING clip hangs off the left + edge of the alignment and must be drawn leftwards from reference_start; a + TRAILING clip hangs off the right edge and is drawn rightwards from the end. + Getting this right matters most at a breakend, where a stack of clips all + terminating on one base is the whole signal. + """ + blocks, dels, ins, soft = [], [], [], [] + ref = read.reference_start + cig = read.cigartuples or [] + for i, (op, ln) in enumerate(cig): + if op in (0, 7, 8): # match/mismatch + blocks.append((ref, ref + ln)); ref += ln + elif op == 2 or op == 3: # deletion / skip + dels.append((ref, ref + ln)); ref += ln + elif op == 1: # insertion (0-width in ref) + ins.append((ref, ln)) + elif op == 4: # soft clip + soft.append((ref, ln, i == 0)) + return blocks, dels, ins, soft + + +def pack_rows(reads, pad=3): + """Greedy IGV-style row packing by reference start.""" + rows = [] # list of last-end per row + placed = [] + for r in sorted(reads, key=lambda x: x.reference_start): + for ri, end in enumerate(rows): + if r.reference_start > end + pad: + rows[ri] = r.reference_end; placed.append((ri, r)); break + else: + rows.append(r.reference_end); placed.append((len(rows) - 1, r)) + return placed, len(rows) + + +def snapshot(ax, cram, chrom, pos, ref=REF, window=60, max_rows=120, title="", + *, keep_supplementary=False, highlight=None, clip_cap=8, mark=None): + """Draw an IGV-style pileup at one locus into `ax`. + + The keyword-only arguments exist for the breakend view (bnd_snapshots.py) and + default to the historical behaviour, so the indel callers are unaffected: + + keep_supplementary keep split-read segments. A junction's supporting reads are + usually supplementary alignments, so the default filter hides + exactly the evidence a breakend figure is meant to show. + highlight set of read names to draw in green instead of strand-tint. + clip_cap max drawn soft-clip length; None draws the true length, which + keeps clip length readable as a cue at a breakpoint. + mark extra positions to mark with a faint dashed vertical, e.g. the + jittered breakpoint calls belonging to the same junction. + """ + highlight = highlight or set() + bam = pysam.AlignmentFile(cram, "rc", reference_filename=ref) + lo, hi = pos - window, pos + window + + def drop(r): + if r.is_unmapped or r.is_secondary or r.is_duplicate: + return True + return r.is_supplementary and not keep_supplementary + + reads = [r for r in bam.fetch(chrom, max(0, lo), hi) if not drop(r)] + placed, nrows = pack_rows(reads) + n_indel = 0 + for ri, r in placed: + if ri > max_rows: + continue + y = -ri + blocks, dels, ins, soft = read_blocks(r) + fwd = not r.is_reverse + hot = r.query_name in highlight + if hot: + col, clipcol = ("#31a354" if fwd else "#a1d99b"), "#006d2c" + else: + col, clipcol = ("#8fb3d9" if fwd else "#d9a68f"), "#bcd4ec" + for a, b in blocks: + ax.add_patch(Rectangle((a, y - 0.4), b - a, 0.8, color=col, lw=0)) + for a, b in dels: # deletion = red span + if a <= hi and b >= lo: + ax.plot([a, b], [y, y], color="#cc2b2b", lw=1.6, solid_capstyle="butt") + if lo <= a <= hi: + n_indel += 1 + for a, ln in ins: # insertion = purple tick + if lo <= a <= hi: + ax.plot([a, a], [y - 0.45, y + 0.45], color="#7a3fbf", lw=1.4) + n_indel += 1 + for a, ln, leading in soft: # soft clip = stub off the read edge + w = ln if clip_cap is None else min(ln, clip_cap) + ax.add_patch(Rectangle((a - w if leading else a, y - 0.4), w, 0.8, + color=clipcol, lw=0, alpha=0.9 if hot else 0.6)) + for m in (mark or ()): + if m != pos and lo <= m <= hi: + ax.axvline(m, color="k", ls=":", lw=0.6, alpha=0.35) + ax.axvline(pos, color="k", ls="--", lw=0.8, alpha=0.7) + ax.set_xlim(lo, hi); ax.set_ylim(-min(nrows, max_rows) - 1, 1) + ax.set_yticks([]); ax.set_xlabel(f"{chrom}:{pos:,}") + ax.set_title(title, fontsize=9) + bam.close() + return nrows + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--cram", required=True) + ap.add_argument("--chrom", required=True) + ap.add_argument("--pos", type=int, required=True) + ap.add_argument("--ref", default=REF) + ap.add_argument("--window", type=int, default=60) + ap.add_argument("--title", default="") + ap.add_argument("--out", required=True) + args = ap.parse_args() + fig, ax = plt.subplots(figsize=(9, 6)) + n = snapshot(ax, args.cram, args.chrom, args.pos, args.ref, args.window, title=args.title) + fig.tight_layout(); fig.savefig(args.out, dpi=130) + print(f"wrote {args.out} ({n} read rows)") + + +if __name__ == "__main__": + main() diff --git a/bin/pon_filter.py b/bin/pon_filter.py new file mode 100755 index 0000000..3b0123e --- /dev/null +++ b/bin/pon_filter.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 +""" +pon_filter.py — Panel-of-Normals post-filter for the genome-wide worklist. + +The matched-normal check (score.py control_check) subtracts germline using ONE +donor's normal, which here is ~1/5 the tumor depth. At the VAF we care about a +single shallow normal cannot reliably see a germline/mosaic indel, so the +homology-blind LIKELY-EDIT tail is contaminated by germline that the matched +normal missed. Pooling ALL 25 unedited normals restores the depth: an indel that +is truly germline/mosaic will show up in SOME donor's normal (and in the pooled +pileup) even if the one matched normal was too shallow to call it. + +Rule (textbook PoN): a candidate LIKELY-EDIT indel that appears at the observed +position in ANY donor's normal, or in the pooled cross-donor pileup, is +germline/mosaic/recurrent-artifact -> demote. A real Cas9 off-target is somatic +and donor-private: it is absent from every unedited normal. + +Only re-checks sites that already survived (LIKELY EDIT / POSSIBLE); pooling is a +cheap per-site scan (~sites x 25 normals), not a genome-wide re-run. +""" +import os, sys, argparse +from collections import Counter +import numpy as np +import pandas as pd +import pysam + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from features import read_records, WIN +import score as S + +REF = S.REF +# a normal read "supports the indel" if it carries an in-window indel within this +# many bp of the candidate's observed modal position (matches the tumor caller's +# +/-2 bp concordance window, widened by 1 for shallow-normal position jitter) +POS_TOL = 3 +PON_PRESENT_IF = 0.03 # per-normal indel_frac >= this (with >= MIN_SPAN) = present +PON_MIN_SPAN = 4 # per-normal spanning floor to count that normal as evaluable +PON_POOL_IF = 0.02 # pooled cross-donor indel_frac >= this = germline/artifact + + +def normals_from_map(cram_map): + """sample -> matched-normal CRAM path (drops the tumor, keeps .cram).""" + crams = S.cram_index(cram_map) + out = {} + for s, tp in crams.items(): + np_ = S.normal_cram_path(tp) + if np_: + out[s] = np_ + return out + + +def normal_support(bam, chrom, pos): + """(n_indel_near_pos, spanning) in one normal at the candidate position. + + n_indel = reads whose largest in-window indel sits within POS_TOL bp of pos; + spanning = reads covering pos. Returns (0, 0) if the locus can't be fetched + (e.g. contig/ref decode failure) so a bad normal never masks a real edit.""" + try: + rr = read_records(bam, str(chrom), int(pos) - 1, int(pos) + 1) + except OSError: + return 0, 0 + if rr is None: + return 0, 0 + records = rr[0] + spanning = sum(1 for r in records if r["spans"]) + n_indel = sum(1 for r in records + if r["indel"] is not None and abs(r["indel"][0] - int(pos)) <= POS_TOL) + return n_indel, spanning + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--worklist", default="wgs_offtarget_worklist_genomewide.csv") + ap.add_argument("--cram-list", + default=f"{os.path.dirname(os.path.abspath(__file__))}/wgs_cram_map.tsv") + ap.add_argument("--ref", default=REF) + ap.add_argument("--verdicts", default="LIKELY EDIT,POSSIBLE — review", + help="comma-list of verdicts to re-check against the PoN") + ap.add_argument("--out", default="wgs_offtarget_worklist_pon.csv") + ap.add_argument("--top", type=int, default=60) + args = ap.parse_args() + + df = pd.read_csv(args.worklist) + normals = normals_from_map(args.cram_list) + print(f"Panel of Normals: {len(normals)} unedited normals", flush=True) + + check_verds = set(v.strip() for v in args.verdicts.split(",")) + todo = df[df["verdict"].isin(check_verds)].copy() + print(f"re-checking {len(todo)} candidates ({', '.join(sorted(check_verds))}) " + f"against the PoN\n", flush=True) + + # open all normals once + bams = {s: pysam.AlignmentFile(p, "rc", reference_filename=args.ref) + for s, p in normals.items()} + + pon = {} # rank -> dict of pon metrics + for i, (_, r) in enumerate(todo.iterrows(), 1): + chrom = str(r["chrom"]) + pos = int(r["modal_pos"]) if pd.notna(r.get("modal_pos")) else int(r["start"]) + own = r["sample"] + n_hit = 0 # normals (excluding own, already checked) with the indel + pooled_i = pooled_s = 0 + worst_if = 0.0 + for s, bam in bams.items(): + ni, sp = normal_support(bam, chrom, pos) + if s == own: # own matched normal already vetted in stage-1 ctrl_if + continue + if sp >= PON_MIN_SPAN: + pooled_i += ni + pooled_s += sp + fi = ni / sp + worst_if = max(worst_if, fi) + if fi >= PON_PRESENT_IF: + n_hit += 1 + pool_if = (pooled_i / pooled_s) if pooled_s else 0.0 + pon[r["rank"]] = dict(pon_n_hit=n_hit, pon_pool_if=round(pool_if, 4), + pon_worst_if=round(worst_if, 3), pon_span=pooled_s) + if i % 40 == 0: + print(f" ...{i}/{len(todo)}", flush=True) + for b in bams.values(): + b.close() + + # merge pon metrics; sites not re-checked get NaN + for col in ("pon_n_hit", "pon_pool_if", "pon_worst_if", "pon_span"): + df[col] = df["rank"].map(lambda k: pon.get(k, {}).get(col, np.nan)) + + # PoN verdict: demote survivors that show germline in the cross-donor panel + def revised(r): + v = r["verdict"] + if v not in check_verds: + return v + if pd.isna(r["pon_n_hit"]): + return v + if r["pon_n_hit"] >= 1 or r["pon_pool_if"] >= PON_POOL_IF: + return "GERMLINE/ARTIFACT (in PoN)" + return v + df["verdict_pon"] = df.apply(revised, axis=1) + + df.to_csv(args.out, index=False) + + # report + surv = df[df["verdict_pon"].isin(check_verds)] + demoted = df[(df["verdict"].isin(check_verds)) & + (df["verdict_pon"] == "GERMLINE/ARTIFACT (in PoN)")] + le0 = df[df["verdict"] == "LIKELY EDIT"] + le1 = df[df["verdict_pon"] == "LIKELY EDIT"] + print(f"\nwrote {args.out}") + print(f"LIKELY EDIT: {len(le0)} -> {len(le1)} " + f"(PoN demoted {len(le0) - len(le1)} as germline/artifact)") + print(f"total survivors ({'/'.join(sorted(check_verds))}): " + f"{len(todo)} -> {len(surv)}") + + # positive control must survive + pc = df[df.get("truth") == True] if "truth" in df.columns else df.iloc[0:0] + for _, k in pc.iterrows(): + print(f"POSITIVE CONTROL {k['chrom']}:{k['start']} ({k['sample']}): " + f"verdict_pon='{k['verdict_pon']}' pon_n_hit={k['pon_n_hit']} " + f"pon_pool_if={k['pon_pool_if']}") + + cols = ["rank", "sample", "chrom", "start", "alt", "dragen_af", "min_mm", + "is_target", "indel_frac", "ctrl_if", "pon_n_hit", "pon_pool_if", + "pon_worst_if", "score", "verdict_pon"] + cols = [c for c in cols if c in df.columns] + surv_ot = surv[surv["is_target"] == 0] if "is_target" in surv.columns else surv + print(f"\n== PoN survivors, off-target, top {args.top} ==") + with pd.option_context("display.max_rows", None, "display.width", 200): + print(surv_ot.sort_values("score", ascending=False)[cols] + .head(args.top).to_string(index=False)) + if "min_mm" in surv_ot.columns and len(surv_ot): + print("\nsurvivor off-target min_mm dist:", + surv_ot["min_mm"].value_counts().to_dict()) + + +if __name__ == "__main__": + main() diff --git a/bin/recall_vs_vaf.py b/bin/recall_vs_vaf.py new file mode 100755 index 0000000..0c1181d --- /dev/null +++ b/bin/recall_vs_vaf.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python3 +""" +recall_vs_vaf.py — the honest limit, measured. + +From the ECS⋈WGS training table, compute how often the WGS shape score recovers an +ECS-confirmed edit as a function of the ECS (error-corrected) VAF. This is THE +deliverable that keeps the WGS-only promise credible: it names the VAF above which +WGS-only detection is trustworthy, rather than implying WGS sees everything ECS sees. + +WGS "detected" = the pipeline reported LIKELY EDIT (model score >= --hi, or the +high-evidence rescue). Sites with no spanning WGS reads are UNEVALUABLE rather than +missed, and are reported in their own column instead of being charged against recall — +the WGS depth floor is a property of the data, not of the scorer. `recall` is therefore +over evaluable sites; `recall_incl_unevaluable` keeps the pessimistic view. + +THE DENOMINATOR (this is what makes the number mean anything) +------------------------------------------------------------ +A recall figure is only as honest as the set of "real edits" it divides by. The raw ECS +label counts ANY nonzero indel fraction as an edit (`offtarget_ecs_edit_threshold` +defaults to 0.0), and at ECS depth that is overwhelmingly noise: in a real AAVS1 run, +10,780 of the 12,067 sites with any indel sat below 0.5% VAF with a MEDIAN of 3 indel +reads out of ~5,000. Dividing by those produced a headline recall of ~0.002 that said +nothing about whether the pipeline finds edits — it only measured how much ECS noise it +(correctly) ignores. + +So the denominator here is a CREDIBLE ECS edit: + label == 1 somatic (ECS indel, absent from the matched normal) + ecs_if >= --min-ecs-vaf above the ECS noise floor + ecs_indel_reads >= --min-ecs-reads with actual read support behind it +Read support is the load-bearing half: VAF alone cannot separate a genuine 0.5% edit at +5,000x from 3 stray reads, but read support can. Excluded sites are reported, and the +thresholds are written into the output CSV so the file is self-describing. +""" +import argparse +import numpy as np +import pandas as pd + +BINS = [0.0, 0.005, 0.01, 0.02, 0.05, 0.10, 0.20, 0.50, 1.01] + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--training", required=True, help="training.tsv from join_training_table.py") + ap.add_argument("--hi", type=float, default=0.60, help="WGS score >= HI counts as detected") + ap.add_argument("--detect-by-score", action="store_true", + help="score >= HI is the ONLY detection criterion; ignore the verdict " + "column (so high-evidence rescues do not count as detected)") + ap.add_argument("--target-recall", type=float, default=0.80, + help="report the VAF floor where binned recall first reaches this") + ap.add_argument("--min-ecs-vaf", type=float, default=0.005, + help="denominator: ECS VAF floor below which a call is assay noise, " + "not a real edit (0 = keep every ECS call)") + ap.add_argument("--min-ecs-reads", type=int, default=5, + help="denominator: ECS indel reads required to believe the site is a " + "real edit rather than noise (0 = no read-support requirement)") + ap.add_argument("--out-metrics", default="recall_vs_vaf.csv") + ap.add_argument("--out-curve", default="recall_vs_vaf.png") + args = ap.parse_args() + + df = pd.read_csv(args.training, sep="\t") + somatic = df[df["label"] == 1].copy() + + # Restrict to CREDIBLE ECS edits (see module docstring). Anything failing these is + # ECS noise, not a miss, and must not sit in the denominator. + vaf = pd.to_numeric(somatic.get("ecs_if"), errors="coerce").fillna(0.0) + keep = vaf >= args.min_ecs_vaf + if "ecs_indel_reads" in somatic.columns: + reads = pd.to_numeric(somatic["ecs_indel_reads"], errors="coerce").fillna(0) + keep &= reads >= args.min_ecs_reads + elif args.min_ecs_reads > 0: + print(f"WARN: training table has no ecs_indel_reads column (produced before read " + f"support was carried through) — the --min-ecs-reads {args.min_ecs_reads} " + f"filter is INACTIVE and the denominator may still contain ECS noise.") + pos = somatic[keep].copy() + n_excluded = int(len(somatic) - len(pos)) + print(f"denominator: {len(pos)} credible ECS edits " + f"(ecs_if>={args.min_ecs_vaf}, ecs_indel_reads>={args.min_ecs_reads}); " + f"excluded {n_excluded} sub-threshold/no-support ECS calls as noise, " + f"from {len(somatic)} somatic ECS-positive rows") + + if len(pos) == 0: + print("no credible ECS edits in training table; nothing to measure") + pd.DataFrame(columns=["vaf_bin", "n", "n_detected", "recall"]).to_csv( + args.out_metrics, index=False) + return + + pos["score"] = pd.to_numeric(pos["score"], errors="coerce") + # "Detected" must mean what the pipeline actually REPORTS. The scorer can call a + # LIKELY EDIT via the high-evidence rescue at a sub-HI model score, so scoring recall + # on the raw model score alone under-counts exactly those recovered edits. Prefer the + # verdict when it is present; fall back to the score for verdict-less tables. + by_score = (pos["score"] >= args.hi).fillna(False) + if "verdict" in pos.columns and not args.detect_by_score: + pos["detected"] = pos["verdict"].astype(str).str.contains( + "LIKELY EDIT", na=False).astype(int) + n_extra = int((pos["detected"].astype(bool) & ~by_score).sum()) + if n_extra: + print(f"detection = verdict contains 'LIKELY EDIT' " + f"({n_extra} rescued below score {args.hi})") + else: + pos["detected"] = by_score.astype(int) + pos["vaf_bin"] = pd.cut(pd.to_numeric(pos["ecs_if"], errors="coerce"), bins=BINS, + right=False) + + # A site with no spanning WGS reads is UNEVALUABLE, not missed — the pipeline was + # never given the chance to call it. Counting those as recall failures conflates the + # WGS depth floor with scoring quality, so they are split out: `recall` is over sites + # WGS could actually judge, and `recall_incl_unevaluable` keeps the pessimistic view. + unevaluable = pos["verdict"].astype(str).str.contains( + "INSUFFICIENT COVERAGE|NO CRAM", na=False) if "verdict" in pos.columns \ + else pd.Series(False, index=pos.index) + pos["_uneval"] = unevaluable.astype(int) + + g = (pos.groupby("vaf_bin", observed=True) + .agg(n=("detected", "size"), n_unevaluable=("_uneval", "sum"), + n_detected=("detected", "sum")) + .reset_index()) + g["n_evaluable"] = g["n"] - g["n_unevaluable"] + g["recall"] = (g["n_detected"] / g["n_evaluable"]).where(g["n_evaluable"] > 0) + g["recall_incl_unevaluable"] = g["n_detected"] / g["n"] + g = g[["vaf_bin", "n", "n_unevaluable", "n_evaluable", "n_detected", + "recall", "recall_incl_unevaluable"]] + # Stamp the denominator definition into the file itself. This CSV gets read months + # later out of context; without these columns a reader cannot tell whether a low + # recall means "missed real edits" or "divided by ECS noise". + g["denom_min_ecs_vaf"] = args.min_ecs_vaf + g["denom_min_ecs_reads"] = args.min_ecs_reads + g["denom_excluded_as_noise"] = n_excluded + g.to_csv(args.out_metrics, index=False) + + n_eval = int((~pos["_uneval"].astype(bool)).sum()) + overall = (pos.loc[~pos["_uneval"].astype(bool), "detected"].mean() + if n_eval else float("nan")) + floor = None + for _, r in g.iterrows(): + if r["n"] >= 1 and r["recall"] >= args.target_recall: + floor = r["vaf_bin"].left + break + print(f"overall WGS recall of credible ECS edits: {overall:.2f} over {n_eval} " + f"EVALUABLE sites ({len(pos) - n_eval} of {len(pos)} had no WGS coverage)") + print(f"VAF floor for >= {args.target_recall:.0%} binned recall: " + f"{'>%.3f' % floor if floor is not None else 'not reached in these bins'}") + print(g.to_string(index=False)) + + try: + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + centers = [iv.left for iv in g["vaf_bin"]] + fig, ax = plt.subplots(figsize=(7, 4.5)) + ax.plot(centers, g["recall"], "o-", color="#2b6cb0") + ax.axhline(args.target_recall, ls="--", color="#a0aec0", + label=f"target recall {args.target_recall:.0%}") + ax.set_xscale("symlog", linthresh=0.005) + ax.set_xlabel("ECS error-corrected VAF (lower bin edge)") + # NOT "score >= hi": detection is the reported verdict, which includes + # high-evidence rescues below that score. And the ratio is over EVALUABLE sites. + ax.set_ylabel("WGS recall (LIKELY EDIT / evaluable)") + ax.set_ylim(-0.02, 1.02) + # The figure travels further than the CSV (slides, papers), so it has to carry + # its own denominator definition too. + ax.set_title("WGS-only recovery of ECS-confirmed edits vs VAF") + fig.text(0.5, 0.005, + f"denominator = {len(pos)} credible ECS edits " + f"(VAF ≥ {args.min_ecs_vaf:g}, ≥ {args.min_ecs_reads} ECS indel reads); " + f"{n_excluded} sub-threshold ECS calls excluded as assay noise", + ha="center", fontsize=7, color="#4a5568") + for _, r in g.iterrows(): + # Annotate the EVALUABLE count — the denominator this point was actually + # computed from. Labelling the credible total instead reads as "n/n detected" + # and hides the depth floor (e.g. a bin of 4 credible edits with 2 uncovered + # plots at recall 1.0 off 2 sites, not 4). + lab = f"n={int(r['n_evaluable'])}" + if r["n_unevaluable"]: + lab += f" (+{int(r['n_unevaluable'])} uncov.)" + ax.annotate(lab, (r["vaf_bin"].left, r["recall"]), + textcoords="offset points", xytext=(0, 6), fontsize=8, ha="center") + ax.legend() + fig.tight_layout() + fig.savefig(args.out_curve, dpi=130) + print(f"wrote {args.out_curve}") + except Exception as e: # plotting is a nicety; metrics CSV is the source of truth + print(f"(curve not rendered: {e})") + + +if __name__ == "__main__": + main() diff --git a/bin/reconcile_offtarget_report.py b/bin/reconcile_offtarget_report.py new file mode 100755 index 0000000..61bf4e8 --- /dev/null +++ b/bin/reconcile_offtarget_report.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +""" +reconcile_offtarget_report.py — the joined off-target deliverable. + +Annotates the genome-wide, PoN-filtered WGS worklist with: + - is_hotspot : the candidate falls within --pad bp of a predicted (ECS-panel) site + - ecs_confirmed : that hotspot has ECS error-corrected evidence (ecs_if > 0) + - ecs_if : the ECS VAF at the matched hotspot (NaN if none) +so a reviewer sees at a glance whether a homology-free WGS hit is a known predicted +site (ECS-backed) or a novel, unpredicted candidate. Writes the annotated worklist and +a short summary. +""" +import argparse +import numpy as np +import pandas as pd + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--worklist", required=True, help="PoN-filtered genome-wide worklist CSV") + ap.add_argument("--truth", help="ecs_hotspot_truth.csv (guide,chrom,start,ecs_if,...)") + ap.add_argument("--pad", type=int, default=25, help="bp window to match a candidate to a hotspot") + ap.add_argument("--verdict-col", default="verdict_pon", + help="which verdict column to summarize (falls back to 'verdict')") + ap.add_argument("--out", default="offtarget_report.csv") + args = ap.parse_args() + + wl = pd.read_csv(args.worklist) + vcol = args.verdict_col if args.verdict_col in wl.columns else "verdict" + + wl["is_hotspot"] = 0 + wl["ecs_confirmed"] = 0 + wl["ecs_if"] = np.nan + + if args.truth: + truth = pd.read_csv(args.truth) + truth["chrom"] = truth["chrom"].astype(str) + # index hotspots per chrom for a padded nearest-site match + by_chrom = {c: t.sort_values("start") for c, t in truth.groupby("chrom")} + for i, r in wl.iterrows(): + t = by_chrom.get(str(r["chrom"])) + if t is None: + continue + d = (t["start"] - int(r["start"])).abs() + j = d.idxmin() if len(d) else None + if j is not None and d.loc[j] <= args.pad: + wl.at[i, "is_hotspot"] = 1 + ecs_if = float(t.loc[j, "ecs_if"]) + wl.at[i, "ecs_if"] = ecs_if + wl.at[i, "ecs_confirmed"] = int(ecs_if > 0) + + wl.to_csv(args.out, index=False) + + n = len(wl) + likely = wl[wl[vcol].astype(str).str.contains("LIKELY EDIT", na=False)] + print(f"wrote {args.out} ({n} candidates)") + print(f" LIKELY EDIT ({vcol}): {len(likely)}") + print(f" on a predicted hotspot: {int(wl['is_hotspot'].sum())} " + f"(ECS-confirmed: {int(wl['ecs_confirmed'].sum())})") + novel = likely[likely["is_hotspot"] == 0] + print(f" LIKELY EDIT & NOT on any predicted hotspot (novel candidates): {len(novel)}") + if len(novel): + cols = [c for c in ["rank", "sample", "chrom", "start", "alt", "score", vcol] + if c in novel.columns] + print(novel[cols].head(20).to_string(index=False)) + + +if __name__ == "__main__": + main() diff --git a/bin/review_filter.py b/bin/review_filter.py new file mode 100755 index 0000000..f9a7fc5 --- /dev/null +++ b/bin/review_filter.py @@ -0,0 +1,469 @@ +#!/usr/bin/env python3 +"""Automate the manual review of CRISPR off-target hotspot calls. + +Takes find_edited_reads.py output (*.offtarget_analysis.tsv) and returns the subset a human +still needs to look at. Four rules, each one a statement you can defend: + + 1. the matched control is clean -- if the variant is in the unedited sample from the + same donor, Cas9 did not make it + 2. within 10 bp of a PAM position -- Cas9 cuts ~3 bp from the PAM; real edits sit at + the cut, background indels do not + 3. at least 3 distinct indel lengths -- NHEJ produces a spectrum of deletion sizes; one + length repeated across every read is an artifact + 4. not a known-bad site -- a site carrying indels in samples that were never + edited is germline or a repeat, not an edit + 5. not in a repeat region -- the off-target panel is built from homology, so it + is enriched for the sequence aligners misplace + indels in + +Measured on the 25-sample CAR-T WGS cohort against the corrected truth set (61 real edits, +177 artifacts): + + review queue 238 -> 62 rows, 61/61 real edits retained + precision 0.256 -> 0.984, recall 1.000 + +RULE 1 REQUIRES THE FIXED CALLER. Before the control-reporting fix, find_edited_reads.py summed +control support *after* the -x/--max-in-control filter had removed the events carrying it, so +control_indel_reads was 0 at every site and this rule was a no-op. The script warns if it sees +that signature. + +RULE 2 IS NOT DECIDED HERE. The pipeline has ONE cut-distance threshold and the caller owns it +(find_edited_reads.py -d, default 10). cut_dist_min is the caller's own min_cut_distance, so the +check below is a consistency guard that drops nothing on a current table. It used to be a second, +differently-computed threshold sharing the name, which disagreed with the caller's on 162 of 1,498 +gated rows. + +RULE 4 HAS TWO SOURCES: + --noise-model matched a beta-binomial test against the sample's OWN unedited control + (bin/noise_model.py). Needs no cohort. THE DEFAULT in the pipeline. + It replaced a panel of normals, which it matched exactly on the + 32-sample CAR-T cohort: 64/64 confirmed retained, 9 rejected, + precision 0.877. The PoN has since been removed outright -- it needed + a cohort of unedited samples that a single-sample submission does not + have, and bought nothing the model does not. + (auto) cross-guide recurrence -- a site under >=2 distinct guides is a bad + region. Needs several differently-guided samples in ONE invocation, so + it CANNOT fire for a single guide; the script says so loudly. + +WITH NO CONTROL MATERIAL AT ALL, use --repeats and --snv-noise. Neither needs a cohort, a guide +context or an unedited sample. The GATK 1000g PoN was tested for this role and rejected: it flags +15 artifacts but also 4 of the 61 real edits, because it is a Mutect2 SNV panel from blood normals +rather than an indel-artifact map. + +usage: + review_filter.py IN.tsv [IN2.tsv ...] -o queue.tsv --noise-model matched + [--repeats rmsk.bed trf.bed] [--snv-noise panel.bed.gz] +""" +import argparse +import bisect +import collections +import gzip +import os +import re +import sys + +import numpy as np +import pandas as pd + +GATE_READS, GATE_VAF = 10, 0.05 +SNV_NOISE_MIN_DONORS = 3 +SNV_NOISE_SLOP = 2 +MAX_CUT_DIST, MIN_DISTINCT_LEN, MAX_GUIDES = 10, 3, 2 +MAX_CONTROL_VAF = 0.05 +# Default AQ cut for --noise-model. Measured on the 32-sample cohort with the depth floor on: +# 3, 5 and 8 all reproduce the panel-of-normals result exactly (91 rows, 64 confirmed, 9 rejected, +# precision 0.877); 10 drops a confirmed edit. 5 sits in the middle of that plateau. +AQ_MIN = 5.0 + + +def _indel_len(ref, alt): + m = re.fullmatch(r'DEL(\d+)', str(alt)) + if m: + return -int(m.group(1)) + m = re.fullmatch(r'INS(\d+)', str(alt)) + if m: + return int(m.group(1)) + if str(alt).startswith('<') or str(ref) == '.' or str(alt) == '.': + return None + return len(str(alt)) - len(str(ref)) + + +def parse_events(s): + """indel_info -> [(distance_to_pam, indel_length, supporting_reads), ...] + + Field layout per ';'-separated event: + chrom|pos|chrom2|pos2|strands|ref|alt|distance|distance2|counts|control_alt_counts + 'distance' (index 7) is min(|pos - PAM_position|) over the site's PAM positions. + """ + out = [] + if not isinstance(s, str): + return out + for ev in s.split(';'): + f = ev.split('|') + if len(f) < 10: + continue + try: + dist, cnt = abs(int(f[7])), int(f[9]) + except ValueError: + continue + L = _indel_len(f[5], f[6]) + if L: + out.append((dist, L, cnt)) + return out + + +def add_features(df): + """Attach cut_dist_min and n_distinct_len, preferring caller-supplied columns. + + ANNOTATE IN THE CALLER, FILTER HERE. Anything the caller can compute once while it already + has the pileup open should arrive as a column; this function only derives what is missing, so + a table from an older caller still works unchanged. + + THERE IS ONE CUT-DISTANCE METRIC and the caller owns it. cut_dist_min is the caller's + `min_cut_distance` = min(|pos - PAM|, |pos + len(ref) - 1 - PAM|), the same value its -d cutoff + acts on. Rule 2 here is therefore a consistency guard, not a second threshold: with the caller + at -d 10 every surviving event is already within 10 bp and the rule drops nothing. + + The legacy path below derives a distance from indel_info instead. That is a DIFFERENT quantity + -- measured from the anchor base only, so always larger -- and the two disagreed on 162 of + 1,498 gated rows. It exists solely so tables written before min_cut_distance existed still + run; it warns when it fires, because on those tables rule 2 is stricter than the caller's. + """ + df = df.copy() + if "min_cut_distance" in df.columns: + cut = pd.to_numeric(df.min_cut_distance, errors="coerce") + cut = cut.where(cut >= 0, np.nan) # the caller writes -1 for "no real indel" + else: + print("NOTE: no min_cut_distance column (table predates it) -- falling back to the " + "indel_info\n distance, which is anchor-only and always larger, so rule 2 will " + "be stricter\n than the caller's own -d cutoff.", file=sys.stderr) + cut = None + ndl_supplied = "n_distinct_len" in df.columns and not df.n_distinct_len.isna().any() + + ndl = None + if cut is None or not ndl_supplied: + _cut, _ndl = [], [] + for s in df.indel_info: + ev = parse_events(s) + if not ev: + _cut.append(np.nan) + _ndl.append(0) + continue + _cut.append(min(e[0] for e in ev)) + _ndl.append(len({e[1] for e in ev})) + if cut is None: + cut = pd.Series(_cut, index=df.index) + if not ndl_supplied: + ndl = _ndl + # Assign in this order: cut_dist_min before n_distinct_len, matching the column layout every + # existing review_queue.tsv already has. Swapping them changes nothing but the header, and a + # gratuitous header change makes real diffs between runs harder to read. + df["cut_dist_min"] = cut.values if hasattr(cut, "values") else cut + if ndl is not None: + df["n_distinct_len"] = ndl + return df + + +def load_snv_noise(path, positions, slop=SNV_NOISE_SLOP): + """DRAGEN systematic-noise BED -> {(chrom, pos): (max_noise, n_donors, alleles)}. + + Columns: chrom, start, end, mean_noise, max_noise, alleles, n_donors. `end` is the 1-based + position, matching the `end` column of the caller's table. + + Despite the "snv" in the filename this panel is NOT SNV-only: the allele column carries D + (1,299,670 records) and I (892,925) codes, so it covers indel noise too. Measured against the + 1,498 gated rows of the 32-sample cohort, a bare interval hit flags 33.1% of artifacts but also + 1.2% of real on-target edits -- 27x enrichment, but not clean enough to use as-is. + + The panel's own fields separate the two cases, which is why this returns them rather than a + boolean: + + IKZF2 chr2:213,147,790 on-target, n_donors=1, alleles 'G', max 0.027 <- coincidence + B2M chr1:28,580,333 off-target, n_donors=17, alleles 'C,D', max 0.078 <- real warning + + The file is ~1 GB and is not shipped with a tabix index, so this streams it once (~2-3 min). + Only positions in `positions` are retained, so memory stays small. + """ + want = collections.defaultdict(set) + for c, e in positions: + for d in range(-slop, slop + 1): + want[c].add(int(e) + d) + hits = {} + op = gzip.open if path.endswith(".gz") else open + with op(path, "rt") as f: + for line in f: + if line[0] == "#": + continue + p = line.rstrip("\n").split("\t") + if len(p) < 7: + continue + c = p[0] + if c not in want: + continue + try: + pos = int(p[2]) + except ValueError: + continue + if pos not in want[c]: + continue + try: + prev = hits.get((c, pos)) + rec = (float(p[4]), int(p[6]), p[5]) + # keep the strongest record if several land on one position + if prev is None or rec[1] > prev[1]: + hits[(c, pos)] = rec + except ValueError: + continue + return hits + + +def snv_noise_mask(hits, chroms, ends, min_donors, slop=SNV_NOISE_SLOP): + """True where a site sits on a recurrent indel-noise locus. + + Two conditions beyond a plain interval hit, both derived from the measurement above: + * the locus recurs in at least `min_donors` panel donors -- drops the n=1 coincidences + * the noise involves an insertion or deletion -- an SNV-only locus says nothing about an + indel call at the same coordinate + """ + out = [] + for c, e in zip(chroms, ends): + flag = False + for d in range(-slop, slop + 1): + rec = hits.get((c, int(e) + d)) + if rec and rec[1] >= min_donors and ("D" in rec[2] or "I" in rec[2]): + flag = True + break + out.append(flag) + return out + + +def guide_of(sample): + """NS0011-ABTB1 / CART_NS0027-B2M_1 -> ABTB1 / B2M""" + return re.sub(r'_\d+$', '', re.sub(r'^(CART_)?NS\d+-', '', str(sample))) + + +class RepeatIndex: + """Point-in-interval lookup over one or more BED files. + + Intervals are held as per-chromosome sorted (start, end) arrays and queried with bisect, + which keeps a 120 MB RepeatMasker BED usable without pulling in pybedtools. + """ + + def __init__(self, paths): + self.iv = {} + self.n = 0 + for p in paths: + op = gzip.open if str(p).endswith(".gz") else open + with op(p, "rt") as fh: + for line in fh: + if line.startswith(("#", "track", "browser")): + continue + f = line.split("\t") + if len(f) < 3: + continue + try: + self.iv.setdefault(f[0], []).append((int(f[1]), int(f[2]))) + except ValueError: + continue + self.n += 1 + for c in self.iv: + self.iv[c].sort() + + def __contains__(self, key): + chrom, pos = key + a = self.iv.get(chrom) + if not a: + return False + # rightmost interval whose start <= pos + i = bisect.bisect_right(a, (pos, float("inf"))) - 1 + return i >= 0 and a[i][0] <= pos <= a[i][1] + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("inputs", nargs="+", help="*.offtarget_analysis.tsv") + ap.add_argument("-o", "--out", required=True, help="filtered review queue (TSV)") + ap.add_argument("--min-reads", type=int, default=GATE_READS) + ap.add_argument("--min-vaf", type=float, default=GATE_VAF) + ap.add_argument("--max-cut-dist", type=int, default=MAX_CUT_DIST) + ap.add_argument("--min-distinct-len", type=int, default=MIN_DISTINCT_LEN) + ap.add_argument("--max-guides", type=int, default=MAX_GUIDES, + help="off-target sites appearing in >= this many distinct guides are dropped " + "(fallback only, ignored when --noise-model is set)") + ap.add_argument("--max-control-vaf", type=float, default=MAX_CONTROL_VAF, + help="drop sites whose matched control carries indels at >= this fraction") + ap.add_argument("--snv-noise", metavar="BED", + help="DRAGEN systematic-noise BED (rule 6). Supplements the run's own PoN with " + "an external panel; on-target sites are exempt. Streams a ~1 GB file.") + ap.add_argument("--snv-noise-min-donors", type=int, default=SNV_NOISE_MIN_DONORS, + help="a noise locus must recur in at least this many panel donors to count " + "(default 3; at 1 it starts flagging real on-target edits)") + ap.add_argument("--repeats", nargs="*", default=None, metavar="BED", + help="repeat-annotation BED(s); off-target sites inside a repeat are dropped. " + "Needs no controls, cohort or guide context, so this is the rule-4 " + "substitute for a brand-new guide with nothing else available.") + ap.add_argument("--noise-model", default="off", choices=["off", "matched", "loo", "both"], + help="REPLACE rule 4 with a beta-binomial test against a control-derived " + "background (bin/noise_model.py). 'matched' uses the sample's own " + "unedited control and needs no cohort, which is the point: it matches " + "the PoN's measured performance (64/64 recall, 9 rejects, precision " + "0.877) without one. Default off, so existing runs are unchanged.") + ap.add_argument("--aq-min", type=float, default=AQ_MIN, + help=f"drop sites scoring below this AQ under --noise-model (default " + f"{AQ_MIN}). With the depth floor on, 3-8 all reproduce the PoN exactly; " + f"10 starts costing confirmed edits") + ap.add_argument("--no-depth-floor", dest="depth_floor", action="store_false", + help="disable the 1/control_depth floor on the posterior background " + "(see apply_depth_floor in noise_model.py -- leaving it off lets a clean " + "control claim a background it has no power to support)") + ap.add_argument("--strict-fallback", action="store_true", + help="exit non-zero instead of warning when rule 4 has no usable source " + "(no --noise-model and only one guide in this invocation)") + ap.add_argument("--keep-all", action="store_true", + help="emit every gated row with a why_dropped column instead of filtering") + a = ap.parse_args() + + frames = [] + for p in a.inputs: + d = pd.read_csv(p, sep="\t") + d["sample_name"] = os.path.basename(p).split(".offtarget")[0] + frames.append(d) + df = pd.concat(frames, ignore_index=True) + + gate = (df.indel_reads >= a.min_reads) & (df.indel_fraction >= a.min_vaf) + q = add_features(df[gate]) + if q.empty: + pd.DataFrame(columns=list(df.columns)).to_csv(a.out, sep="\t", index=False) + print("no rows cleared the gate; wrote an empty queue") + return + q["guide"] = q.sample_name.map(guide_of) + q = q.join(q.groupby(["chrom", "start"]).guide.nunique().rename("n_guides"), + on=["chrom", "start"]) + n_guides_total = q.guide.nunique() + + # Rule 1. Control VAF, not a bare count: a couple of stray reads in a 60x normal is noise, + # a third of them is germline. + ctrl_vaf = q.control_indel_reads.fillna(0) / q.control_reads.replace(0, np.nan) + q["control_vaf"] = ctrl_vaf.fillna(0).round(4) + ctrl = q.control_vaf >= a.max_control_vaf + + # Rules 2 and 3, shape at the cut site. + far = ~(q.cut_dist_min <= a.max_cut_dist) + mono = q.n_distinct_len < a.min_distinct_len + + # Rule 4. On-target sites are exempt from both forms: they are shared by design. + is_off = q.get("is_target", pd.Series(0, index=q.index)) == 0 + if a.noise_model != "off": + # Rule 4 as a statistical test rather than a blacklist. Imported lazily so that a run + # without --noise-model never needs scipy. + sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + from noise_model import (fit_global_prior, control_posterior, apply_depth_floor, + aq_from_sf) + from scipy.stats import betabinom + + a0, b0 = fit_global_prior(df.control_indel_reads.fillna(0).values, + df.control_reads.fillna(0).values) + alpha, beta, _nsup, dep = control_posterior(df, q, a.noise_model, a0, b0) + n_floored = 0 + if a.depth_floor: + alpha, beta, n_floored = apply_depth_floor(alpha, beta, dep) + q["bg_rate"] = (alpha / (alpha + beta)).round(6) + q["AQ"] = aq_from_sf(betabinom.sf(q.indel_reads.values.astype(int) - 1, + q.total_reads.values.astype(int), alpha, beta)).round(2) + known_bad = q.AQ < a.aq_min + rule4 = f"beta-binomial vs {a.noise_model} control (AQ<{a.aq_min:g})" + print(f"noise model : prior Beta({a0:.4g},{b0:.4g}), " + f"depth floor {'on' if a.depth_floor else 'OFF'} ({n_floored} rows raised)") + else: + known_bad = is_off & (q.n_guides >= a.max_guides) + rule4 = "cross-guide recurrence" + + # Rule 5. Repeat context. Measured on the CAR-T cohort: RepeatMasker flags 100 of 177 + # artifacts and 0 of 61 real edits, tandem repeats 54 and 0 -- the homology-built off-target + # panel is enriched for exactly the sequence aligners misplace indels in. On-target exempt. + if a.repeats: + rep_idx = RepeatIndex(a.repeats) + in_repeat = is_off & pd.Series([(c, int(p)) in rep_idx for c, p in zip(q.chrom, q.end)], + index=q.index) + else: + rep_idx = None + in_repeat = pd.Series(False, index=q.index) + + # Rule 6. External systematic-noise panel. Placed LAST in the np.select order deliberately: + # first match wins, so appending it here cannot change how any previously-dropped row is + # attributed -- it can only claim rows the five existing rules kept. + if a.snv_noise: + _hits = load_snv_noise(a.snv_noise, set(zip(q.chrom, q.end))) + snv_noise = is_off & pd.Series( + snv_noise_mask(_hits, q.chrom, q.end, a.snv_noise_min_donors), index=q.index) + else: + snv_noise = pd.Series(False, index=q.index) + + rule4_label = (f"indistinguishable from control noise (AQ<{a.aq_min:g})" + if a.noise_model != "off" else "known-bad site (%s)" % rule4) + q["why_dropped"] = np.select( + [ctrl, far, mono, known_bad, in_repeat, snv_noise], + ["germline (present in control)", "far from PAM", "single indel length", + rule4_label, "repeat region", + "systematic noise (external panel)"], default="") + keep = q.why_dropped == "" + + (q if a.keep_all else q[keep]).to_csv(a.out, sep="\t", index=False) + + print(f"input rows : {len(df)}") + print(f"cleared the gate : {len(q)} (reads>={a.min_reads}, VAF>={a.min_vaf})") + print(f"samples / guides : {q.sample_name.nunique()} / {n_guides_total}") + print(f"rule 4 source : {rule4}") + for lab, m in [("germline (in control)", ctrl), ("far from PAM", far & ~ctrl), + ("single indel length", mono & ~ctrl & ~far), + ("known-bad site", known_bad & ~ctrl & ~far & ~mono), + ("repeat region", in_repeat & ~ctrl & ~far & ~mono & ~known_bad), + ("systematic noise (panel)", + snv_noise & ~ctrl & ~far & ~mono & ~known_bad & ~in_repeat)]: + print(f" dropped, {lab:24s}: {int(m.sum())}") + if rep_idx is not None: + print(f"repeat annotation : {rep_idx.n} intervals from {len(a.repeats)} file(s)") + if a.keep_all: + print(f"REVIEW QUEUE : {int(keep.sum())} " + f"(all {len(q)} gated rows written with why_dropped -> {a.out})") + else: + print(f"REVIEW QUEUE : {int(keep.sum())} -> {a.out}") + + # --- guards against the two ways this silently degrades --------------------------------- + if (q.control_indel_reads.fillna(0) == 0).all(): + print("\nWARNING: control_indel_reads is 0 at every site, so the germline rule did " + "nothing.\n These inputs predate the find_edited_reads.py control-reporting " + "fix, which\n summed control support *after* the -x filter removed it. " + "Re-run the caller;\n the germline rule is the single biggest filter " + "(238 -> 84 on its own).", file=sys.stderr) + + # Rule 4 has two possible sources and one dangerous hole. The hole is a SILENT one: with no + # PoN, no noise model and a single guide in the invocation, cross-guide recurrence cannot fire + # and the output looks identical to a clean result -- so the user reads an unfiltered queue as + # a precise one. Say so loudly, and let a caller make it fatal. + if a.noise_model != "off": + pass # rule 4 is covered by the statistical test + elif n_guides_total < 2: + msg = (f"\n{'=' * 78}\n" + f"WARNING: RULE 4 IS NOT ACTIVE. No --noise-model, and only " + f"{n_guides_total} guide in this\n" + f" invocation -- cross-guide recurrence needs >=2 guides passed TOGETHER,\n" + f" so it cannot fire. Known-bad sites are NOT being removed and this queue\n" + f" is less precise than it looks.\n" + f" Fix, in order of preference:\n" + f" --noise-model matched (needs only this sample's own control)\n" + f" pass all guides in ONE invocation\n" + f"{'=' * 78}") + print(msg, file=sys.stderr) + if a.strict_fallback: + sys.exit("ERROR: --strict-fallback set and rule 4 has no usable source") + else: + print(f"\nNOTE: using cross-guide recurrence for rule 4 across {n_guides_total} guides. " + f"--noise-model\n matched is strictly better and " + f"is not affected\n by how many guides you pass in one invocation.", + file=sys.stderr) + + +if __name__ == "__main__": + main() diff --git a/bin/review_filter_bnd.py b/bin/review_filter_bnd.py new file mode 100755 index 0000000..405d36f --- /dev/null +++ b/bin/review_filter_bnd.py @@ -0,0 +1,323 @@ +#!/usr/bin/env python3 +"""Shortlist the breakend (BND) calls a human still needs to look at, and name what they are. + +Takes find_edited_reads.py output (*.offtarget_analysis.tsv), expands the `bnd_info` column into one +row per junction, and applies the breakend analogue of the indel review filter. The interesting +output is not only the shortlist: on this cohort every surviving junction is a **multi-cut +inversion** -- two cuts from the same guide's target set with the intervening segment flipped and +re-ligated -- which the pipeline has always emitted and never labelled correctly. Orientation is +read from `strands`; see the classification block for why a same-chromosome junction in this queue +can only ever be inverted. + + 1. enough support -- >= 3 reads. Breakend support is thin (cohort median 1 read), so + this is the single most discriminating cut available. + 2. near the cut -- within 10 bp of a PAM position, same rule as indels. The caller + applies the SAME 10 bp cutoff via -d/--max-mutation-distance + (default 10; get_indels.nf passes no override), so this rule is + very nearly redundant with it. Not exactly: the caller keeps an + event when EITHER end is in range, this tests one end. But on the + 32-sample cohort no junction has a cut distance above 10 at all, + so rule 2 never fires. "0 dropped" here is structural. + 3. breakpoint not promiscuous-- a breakpoint partnering with many unrelated loci is an alignment + hub, not a junction. On-target sites are EXEMPT (see below). + 4. matched control clean -- NOT applied here. It is already applied per event upstream: the + caller's -x/--max-in-control (default 0) drops any junction with + control support before it is written to bnd_info. + +Rule 4 only started working for breakends once the position handed to add_normal_counts was +corrected for BND rows (see docs/CALLER_INTEGRATION_LOG.md). Before that fix, control support at a +breakend was structurally unmeasurable and every junction survived it. + +ON-TARGET SITES MUST BE EXEMPT FROM RULE 3. A real Cas9 cut generates junctions to many places, so +the true cut sites are among the most promiscuous breakpoints in the cohort -- measured on the +32-sample CAR-T set, 6 of the 10 breakpoints with >=5 distinct partners are the intended TRAC, +TRBC1, TRBC2 and B2M cut sites. Applying rule 3 without the exemption deletes the real edits. + +CALIBRATION NOTE, worth knowing before tuning rule 3. On the 32-sample cohort, once rule 1 is +applied, the ONLY promiscuous breakpoint left is chr1:246,009,98x -- and the caller's control filter +now removes that one on its own. Rule 3 is therefore **currently non-binding**: it changes nothing +on this data. It is kept because it costs nothing, it is the only defence against an alignment hub +that happens to be absent from the matched control, and its column is worth reporting either way. +Do not read "0 dropped by rule 3" as the rule being broken. + +usage: + review_filter_bnd.py IN.tsv [IN2.tsv ...] -o bnd_queue.tsv [--keep-all] +""" +import argparse +import bisect +import collections +import gzip +import os +import sys + +import numpy as np +import pandas as pd + +MIN_READS = 3 +MAX_CUT_DIST = 10 +MAX_PARTNERS = 5 +BIN_SIZE = 1000 +ONTARGET_SLOP = 500 +SV_NOISE_SLOP = 50 + + +def parse_bnds(df, sample): + """bnd_info -> one row per junction. + + Field layout per ';'-separated event, identical to indel_info: + chrom|pos|chrom2|pos2|strands|ref|alt|distance|distance2|counts|control_alt_counts + 'distance' (index 7) is min(|pos - PAM_position|) over the site's PAM positions. + """ + out = [] + for _, r in df[df.bnd_count > 0].iterrows(): + for ev in str(r.bnd_info).split(';'): + f = ev.split('|') + if len(f) < 11: + continue + try: + out.append({ + 'sample_name': sample, + 'chrom': f[0], 'pos': int(f[1]), + 'chrom2': f[2], 'pos2': int(f[3]), + 'strands': f[4], + 'cut_dist': abs(int(f[7])), + 'reads': int(f[9]), + 'control_reads_at_event': int(f[10]), + 'site_start': r.start, 'site_end': r.end, + 'is_target': int(r.is_target), + 'site_total_reads': r.total_reads, + }) + except ValueError: + continue + return out + + +def load_sv_noise(path): + """BEDPE -> {chrom: (starts, ends)} of merged breakpoint intervals, both ends pooled. + + Re-measured on the 2026-08-17 32-sample CAR-T run (1,022 junctions, 25 gated) by + bin/panel_overlap.py, with the on-target exemption disabled so the panels can be compared at + all -- every gated junction here is is_target==1, so with the exemption on the answer is + trivially zero: + + panel genome covered all 1,022 gated 25 (slop 50) + WGS_hg38_v3.1.0 (311k rec) 33.7 Mb 1.1% 58 ( 6%) 0 / 25 + IDPF_WGS_v3.0.0 (2.6M rec) 1942.4 Mb 62.7% 852 (83%) 25 / 25 + WGS_FF_Heme_v3.1.0 (2.2M rec) 1553.8 Mb 50.1% 709 (69%) 25 / 25 + + Only the small WGS panel discriminates, and COVERAGE is why: IDPF's intervals blanket 63% of + hg38, so a hit against it carries almost no information -- it flags 83% of everything, real and + artifactual alike. Slop matters too: at 0 or 50 bp the WGS panel flags no real junction, at + 200 bp it flags 3. + + A min_donors rule does NOT rescue the large panels, though the BEDPE hides the statistic needed + to check: it has no donor-count column and no ##PON SAMPLES header, but field 7 embeds the + donor, so donors per interval can be reconstructed. Doing so, all 25 of IDPF's hits on real + junctions carry >= 3 donors (max 17). These are genuinely recurrent loci in its baseline, not + one-donor coincidences, so no threshold helps. See docs/PANEL_AS_FILTER.md. + + NOTE: the "11 / 11 artifacts" column of the earlier version of this table came from the + 2026-08-10 run and is no longer reproducible -- no run on disk retains that artifact set, and + the current run drops zero junctions to rules 2-4, so it has none. Do not quote it. + """ + iv = collections.defaultdict(list) + op = gzip.open if path.endswith(".gz") else open + with op(path, "rt") as f: + for line in f: + if line.startswith("#"): + continue + p = line.rstrip("\n").split("\t") + if len(p) < 6: + continue + try: + iv[p[0]].append((int(p[1]), int(p[2]))) + iv[p[3]].append((int(p[4]), int(p[5]))) + except ValueError: + continue + merged = {} + for c, v in iv.items(): + v.sort() + out = [] + for s, e in v: + if out and s <= out[-1][1]: + out[-1][1] = max(out[-1][1], e) + else: + out.append([s, e]) + merged[c] = ([x[0] for x in out], [x[1] for x in out]) + return merged + + +def in_noise(merged, chrom, pos, slop): + if chrom not in merged: + return False + st, en = merged[chrom] + i = bisect.bisect_right(st, pos + slop) - 1 + return i >= 0 and st[i] - slop <= pos <= en[i] + slop + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("inputs", nargs="+", help="*.offtarget_analysis.tsv") + ap.add_argument("-o", "--out", required=True, help="breakend review queue (TSV)") + ap.add_argument("--min-reads", type=int, default=MIN_READS) + ap.add_argument("--max-cut-dist", type=int, default=MAX_CUT_DIST) + ap.add_argument("--max-partners", type=int, default=MAX_PARTNERS, + help="breakpoints with >= this many distinct partner loci are alignment hubs") + ap.add_argument("--bin-size", type=int, default=BIN_SIZE, + help="breakpoints are binned at this resolution before counting partners") + ap.add_argument("--sv-noise", metavar="BEDPE", + help="DRAGEN systematic-noise SV panel (BEDPE, optionally gzipped). Use " + "WGS_hg38_v3.1.0_systematic_noise.sv.bedpe.gz -- see the note below on " + "which panels are safe.") + ap.add_argument("--sv-noise-slop", type=int, default=SV_NOISE_SLOP, + help="bp of tolerance when matching a breakpoint to a noise interval " + "(default 50; do NOT raise to 200, it starts hitting real junctions)") + ap.add_argument("--keep-all", action="store_true", + help="write every gated junction with a why_dropped column, for auditing") + a = ap.parse_args() + + events, ontarget = [], {} + for p in a.inputs: + d = pd.read_csv(p, sep="\t") + s = os.path.basename(p).split(".offtarget")[0] + events += parse_bnds(d, s) + # The intended cut sites for this sample, used both to exempt them from the promiscuity + # rule and to recognise a junction whose FAR end also lands on a cut site. + ontarget[s] = d.loc[d.is_target == 1, ['chrom', 'start', 'end']].values.tolist() + + if not events: + pd.DataFrame(columns=['sample_name', 'chrom', 'pos', 'chrom2', 'pos2']).to_csv( + a.out, sep="\t", index=False) + print("no breakend events in the input; wrote an empty queue") + return + + b = pd.DataFrame(events) + n_in = len(b) + + # Promiscuity: distinct partner loci per binned breakpoint, counted across everything supplied + # in this invocation. Cohort-wide is stronger than per-sample -- an alignment hub recurs. + b['bin'] = b.chrom + ':' + (b.pos // a.bin_size).astype(str) + b['partner_bin'] = b.chrom2 + ':' + (b.pos2 // a.bin_size).astype(str) + b = b.join(b.groupby('bin').partner_bin.nunique().rename('n_partners'), on='bin') + + b['span'] = np.where(b.chrom == b.chrom2, (b.pos2 - b.pos).abs(), pd.NA) + b['interchromosomal'] = (b.chrom != b.chrom2).astype(int) + + def far_end_on_target(row): + for c, s, e in ontarget.get(row.sample_name, []): + if c == row.chrom2 and (s - ONTARGET_SLOP) <= row.pos2 <= (e + ONTARGET_SLOP): + return 1 + return 0 + + b['far_end_on_target'] = b.apply(far_end_on_target, axis=1) + + gate = b.reads >= a.min_reads + q = b[gate].copy() + if q.empty: + b.head(0).to_csv(a.out, sep="\t", index=False) + print(f"input junctions : {n_in}\nno junction cleared >= {a.min_reads} reads") + return + + noise = pd.Series(False, index=q.index) + if a.sv_noise: + merged = load_sv_noise(a.sv_noise) + # Either end landing in a known-noise interval condemns the junction. On-target sites are + # exempt for the same reason they are exempt from the promiscuity rule. + noise = pd.Series( + [(in_noise(merged, c, p, a.sv_noise_slop) or in_noise(merged, c2, p2, a.sv_noise_slop)) + for c, p, c2, p2 in zip(q.chrom, q.pos, q.chrom2, q.pos2)], + index=q.index) & (q.is_target == 0) + + far = ~(q.cut_dist <= a.max_cut_dist) + # On-target breakpoints are the most promiscuous in the cohort by construction -- a real cut + # throws junctions everywhere. Exempt them, exactly as rules 4 and 5 do for indels. + hub = (q.n_partners >= a.max_partners) & (q.is_target == 0) + + q["why_dropped"] = np.select([far, hub, noise], + ["far from PAM", "promiscuous breakpoint", + "DRAGEN systematic noise"], default="") + keep = q.why_dropped == "" + + # Classify what survives, on TWO axes: where the ends are, and how they are oriented. + # + # `is_target` describes the NEAR end -- the site the junction was found at -- so a junction + # anchored at a cut site is an on-target editing outcome even when its far end is nowhere in + # particular. Only a junction whose near end is not a cut site is off-target. + # + # ORIENTATION IS NOT OPTIONAL, and leaving it out is how this labelled a cohort of inversions + # "multi-cut deletion" for three releases. `strands` is the pair (near, far) recorded by + # find_edited_reads.py:call_sv_from_split_read from the two aligned segments of the split read: + # + # ++ / -- collinear. The two retained flanks keep their original orientation, which is + # what a deletion (or a tandem duplication) looks like. + # +- / -+ the far segment is inverted relative to the near one. That is an INVERSION + # junction, and a balanced inversion produces TWO of them between the same cut + # pair -- one per end of the flipped segment -- in opposite orientations. + # + # Note which of these can actually arrive here: a same-chromosome, same-strand split read is + # resolved to DEL/DUP/INS by call_sv_from_split_read (find_edited_reads.py:420) and never + # becomes a BND at all. So on the same chromosome this queue only ever sees +-/-+, and a + # "deletion" label on a same-chromosome junction was unreachable-by-construction wrong. The + # collinear branches below are kept because interchromosomal junctions do reach them. + at_cut = q.is_target == 1 + inverted = q.strands.astype(str).isin(["+-", "-+"]) + same_chrom = q.interchromosomal == 0 + both_ends = q.far_end_on_target == 1 + + q["orientation"] = np.where(inverted, "inverted", "collinear") + q["call"] = np.select( + [keep & at_cut & both_ends & same_chrom & inverted, + keep & at_cut & same_chrom & inverted, + keep & at_cut & both_ends & same_chrom, + keep & at_cut & same_chrom, + keep & at_cut, + keep], + ["multi-cut inversion", + "inversion at cut site", + "multi-cut deletion", + "deletion at cut site", + "translocation at cut site", + "off-target junction"], + default="") + + (q if a.keep_all else q[keep]).to_csv(a.out, sep="\t", index=False) + + print(f"input junctions : {n_in}") + print(f"cleared the gate : {len(q)} (reads>={a.min_reads})") + print(f"samples : {b.sample_name.nunique()}") + for lab, m in [("far from PAM", far), ("promiscuous breakpoint", hub & ~far), + ("DRAGEN systematic noise", noise & ~far & ~hub)]: + print(f" dropped, {lab:24s}: {int(m.sum())}") + if int((hub & ~far).sum()) == 0: + print(" (rule 3 is currently non-binding on this data -- see the module docstring)") + print(f"BREAKEND QUEUE : {int(keep.sum())} -> {a.out}") + for lab in ("multi-cut inversion", "inversion at cut site", "multi-cut deletion", + "deletion at cut site", "translocation at cut site", "off-target junction"): + sub = q[keep & (q.call == lab)] + if len(sub): + extra = "" + if (lab.endswith("deletion") or lab.endswith("inversion")) and sub.span.notna().any(): + sp = pd.to_numeric(sub.span, errors="coerce").dropna() + noun = "span" if lab.endswith("deletion") else "segment" + extra = f" {noun} {int(sp.min()):,}-{int(sp.max()):,} bp" + print(f" {lab:24s}: {len(sub):4d} in {sub.sample_name.nunique()} sample(s){extra}") + + # An inversion is reported from both of its junctions, so the sample-level count of DISTINCT + # rearrangements is smaller than the row count. Say so here rather than let a reader multiply. + inv = q[keep & q.call.str.contains("inversion", na=False)] + if len(inv): + pairs = inv.groupby("sample_name").strands.nunique() + both = int((pairs >= 2).sum()) + print(f" of the inversions, {both} sample(s) show BOTH junctions of the pair " + f"(+- and -+), the signature of a balanced inversion") + + if int((q.control_reads_at_event > 0).sum()) == 0: + print("\nNote: control support is 0 on every junction, as expected -- the caller's " + "-x/--max-in-control\n filter removes control-supported junctions before they " + "reach bnd_info. That is the\n matched-control rule, applied upstream, not a " + "missing check.", file=sys.stderr) + + +if __name__ == "__main__": + main() diff --git a/bin/review_snapshots.py b/bin/review_snapshots.py new file mode 100755 index 0000000..7ef9df8 --- /dev/null +++ b/bin/review_snapshots.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +"""Render a review packet: one IGV-style pileup PNG per site in the review queue. + +The queue TSV names sites; this turns each one into a picture a human can adjudicate without +opening IGV. Each figure is TWO panels -- the edited sample on top, its matched unedited control +below, same locus, same scale. That layout is the point: most of the calls that survive the +filters are settled by looking at the control panel, because germline and shared alignment +artifacts appear in both while a real edit appears in only one. + +Reads --cram-map, a TSV of `sampleedited_cramcontrol_cram` (absolute paths), matching +the convention score_hotspots.nf already uses for its cram list. + +usage: + review_snapshots.py --queue review_queue.tsv --cram-map map.tsv --fasta ref.fa --outdir snapshots +""" +import argparse +import os +import sys + +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import pandas as pd + +# pileup_snapshot lives beside this script in bin/ +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from pileup_snapshot import snapshot # noqa: E402 + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--queue", required=True, help="review_queue.tsv from review_filter.py") + ap.add_argument("--cram-map", required=True, + help="TSV: sampleedited_cramcontrol_cram") + ap.add_argument("--fasta", required=True) + ap.add_argument("--outdir", default="snapshots") + ap.add_argument("--window", type=int, default=80, help="bp either side of the site") + ap.add_argument("--max-sites", type=int, default=500, + help="safety cap; a runaway queue should not render thousands of PNGs") + a = ap.parse_args() + + os.makedirs(a.outdir, exist_ok=True) + q = pd.read_csv(a.queue, sep="\t") + if q.empty: + print("review queue is empty; nothing to render") + return + + cmap = pd.read_csv(a.cram_map, sep="\t", header=None, + names=["sample", "edited", "control"]).set_index("sample") + + if len(q) > a.max_sites: + print(f"WARNING: queue has {len(q)} sites, rendering only the first {a.max_sites}. " + f"A queue this large usually means a filter is not firing -- check the " + f"review_filter.py warnings.", file=sys.stderr) + q = q.head(a.max_sites) + + made, skipped = 0, [] + for i, r in q.reset_index(drop=True).iterrows(): + s = r.get("sample_name") + if s not in cmap.index: + skipped.append(f"{s} (not in cram map)") + continue + ed, ct = cmap.loc[s, "edited"], cmap.loc[s, "control"] + pos = int(r.get("end", r.get("start"))) + tag = f"{i + 1:03d}_{s}_{r.chrom}_{pos}".replace("/", "-") + try: + fig, ax = plt.subplots(2, 1, figsize=(11, 8.5), sharex=True) + snapshot(ax[0], ed, r.chrom, pos, ref=a.fasta, window=a.window, + title=f"EDITED {s} {int(r.indel_reads)}/{int(r.total_reads)} indel reads" + f" VAF {float(r.indel_fraction):.3f}") + snapshot(ax[1], ct, r.chrom, pos, ref=a.fasta, window=a.window, + title=f"MATCHED UNEDITED CONTROL ({os.path.basename(str(ct))})") + bits = [f"{r.chrom}:{pos:,}"] + if pd.notna(r.get("cut_dist_min")): + bits.append(f"{float(r.cut_dist_min):.0f} bp from PAM") + if pd.notna(r.get("n_distinct_len")): + bits.append(f"{int(r.n_distinct_len)} indel lengths") + if pd.notna(r.get("control_vaf")): + bits.append(f"control VAF {float(r.control_vaf):.3f}") + fig.suptitle("REVIEW CANDIDATE\n" + " | ".join(bits), + fontsize=11, fontweight="bold") + plt.tight_layout(rect=[0, 0, 1, 0.93]) + fig.savefig(os.path.join(a.outdir, tag + ".png"), dpi=130) + plt.close(fig) + made += 1 + except Exception as e: # one bad locus must not kill the packet + plt.close("all") + skipped.append(f"{s} {r.chrom}:{pos} ({type(e).__name__}: {e})") + + print(f"review sites : {len(q)}") + print(f"snapshots made : {made} -> {a.outdir}/") + if skipped: + print(f"skipped : {len(skipped)}", file=sys.stderr) + for s in skipped[:10]: + print(f" {s}", file=sys.stderr) + + +if __name__ == "__main__": + main() diff --git a/bin/score.py b/bin/score.py new file mode 100755 index 0000000..206bac4 --- /dev/null +++ b/bin/score.py @@ -0,0 +1,452 @@ +#!/usr/bin/env python3 +""" +pileup/score.py — deploy the middle model: Stage-1 filter + learned Stage-2 +shape ranker, on ANY candidate table (ECS .csv.gz or WGS .xlsx/.xlsm) + CRAMs. + +Pipeline (matches issue_011 design): + Stage 1 (no ML): keep off-target candidates with real, control-clean indel + signal — is_target==0, min_mm<=MAX_MM, indel_fraction in (MIN_IFRAC,1], and + control_indel_fraction P(edit)-like score. + +Verdicts: + LIKELY EDIT score >= HI, clonal — OR the high-evidence rescue (below) + POSSIBLE — review MID <= score < HI + ARTIFACT (shape) score < MID (scattered / low-MAPQ / not clonal) + INSUFFICIENT COVERAGE < min-span spanning reads (cannot call — NOT artifact) + NO CRAM sample has no CRAM in the list + +The `call_basis` column records WHY a LIKELY EDIT was called: "model" (the learned +shape ranker cleared HI) or "high-evidence" (the rescue rule below fired). Everything +else is "". + +This RANKS candidate sites to review; it is not an off-target recall estimate +(that needs GUIDE-seq/CIRCLE-seq). On WGS, low-VAF off-targets can sit below the +depth detection floor and surface as INSUFFICIENT COVERAGE, by design. +""" +import os, sys, argparse +import numpy as np +import pandas as pd +import pysam +import joblib + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from features import (read_records, features_from_records, parse_target_info, MODEL_FEATURES, + check_sklearn_version, repeat_context) + +REPO = "/storage2/fs1/dspencer/Active/clinseq/projects/scge" +CRAM_LIST = f"{REPO}/cram_list.txt" +REF = "/storage2/fs1/dspencer/Active/spencerlab/rotating_students/btyler/seqs/hg38_mgi_patch.fa" +MODEL = f"{os.path.dirname(os.path.abspath(__file__))}/middle_model.pkl" +HI, MID = 0.60, 0.25 + + +def cram_index(path): + """Map sample_name -> cram path. Accepts either a 1-column list of cram paths + (key = basename without .cram) or a 2-column 'sample_namepath' map (e.g. + pileup/wgs_cram_map.tsv, needed when table sample_name != cram basename).""" + m = {} + for line in open(path): + line = line.rstrip("\n") + if not line.strip(): + continue + parts = line.split("\t") if "\t" in line else line.split() + if len(parts) >= 2: + m[parts[0]] = parts[1] + else: + m[os.path.basename(parts[0]).replace(".cram", "")] = parts[0] + return m + + +def load_table(path, sample=None, sheet=None): + """Load ECS csv(.gz) or WGS xlsx/xlsm into a common frame with a _truth col.""" + if path.endswith((".xlsx", ".xlsm")): + xl = pd.ExcelFile(path) + sh = sheet or ("gold_wgs" if "gold_wgs" in xl.sheet_names else xl.sheet_names[0]) + df = xl.parse(sh) + else: + df = pd.read_csv(path, low_memory=False) + if "sample_name" not in df.columns: + df["sample_name"] = sample or os.path.basename(path).split(".")[0] + # unify a truth column across cohorts (present only for validation) + truth = None + for c in ("manual_review", "pass"): + if c in df.columns: + truth = c; break + df["_truth"] = (df[truth].astype(str).str.strip().isin(["1", "1.0", "1?", "yes", "True", "true", "pass"]) + if truth else False) + df["_if"] = pd.to_numeric(df["indel_fraction"], errors="coerce") + df["_cif"] = pd.to_numeric(df.get("control_indel_fraction"), errors="coerce").fillna(0.0) + df["_tgt"] = df["is_target"].astype(str).str.strip().isin(["1", "1.0", "True", "true"]) + hom = df["target_info"].apply(parse_target_info) + df["_min_mm"] = [h["min_mm"] if h["min_mm"] is not None else 99 for h in hom] + return df + + +def stage1(df, max_mm, min_ifrac, max_control, include_ontarget, no_homology_gate=False): + """Stage-1 candidate filter. The homology gate (min_mm<=max_mm) is what ties + discovery to a predicted candidate list; --no-homology-gate drops it so a + somatic, control-clean indel qualifies regardless of guide homology (WGS doing + GUIDE-seq's nomination job). min_mm survives as a ranking annotation, not a gate.""" + m = (df["_if"] > min_ifrac) & (df["_if"] <= 1.0) & (df["_cif"] < max_control) + if not no_homology_gate: + m &= (df["_min_mm"] <= max_mm) + if not include_ontarget: + m &= ~df["_tgt"] + return df[m].copy() + + +def add_recurrence(res): + """Cross-sample recurrence: a real off-target is GUIDE-specific; a site recurring + across many unrelated guides is germline/mapping, whatever its pileup shape. The + per-locus model cannot see this — it's a cohort-level signal added here.""" + res = res.copy() + res["site"] = res["chrom"].astype(str) + ":" + res["start"].astype(str) + res["guide"] = res["sample"].str.replace(r"_[12]$", "", regex=True) + res["n_samples_at_site"] = res.groupby("site")["sample"].transform("nunique") + res["n_guides_at_site"] = res.groupby("site")["guide"].transform("nunique") + + def tier(r): + if r["n_guides_at_site"] >= 3: + return "C-recurrent-artifact" + if r["verdict"] == "LIKELY EDIT": + return "A-review-first" + if str(r["verdict"]).startswith("POSSIBLE"): + return "B-review" + return "D-artifact" + res["priority"] = res.apply(tier, axis=1) + return res + + +# ── normal-subtraction verification (automates the IGV manual-review decision) ── +# A real somatic edit is present in the EDITED sample and absent in the matched +# NORMAL. The table's precomputed control column is measured at the ANNOTATED +# position and misses indels offset by a few bp; here we recompute in the normal +# CRAM at the OBSERVED modal indel position — exactly the check a human does in IGV. +NORMAL_MAX_IF = 0.03 # control indel_frac above this => germline/artifact, not edit +MIN_EDIT_RATIO = 3.0 # edited must exceed control by this ratio + +# ── high-evidence rescue (the recall floor) ──────────────────────────────────── +# The learned shape ranker is a RANKER, not a detector: it is trained to sort review +# queues and it demotes some unambiguous edits (measured: 5 of 52 manual-review- +# confirmed CART edits scored 0.27-0.50 despite indel_frac 0.25-1.00, ctrl_if 0.00 and +# 130-244 spanning reads). Those are not close calls — a human reviewing that pileup in +# IGV calls them instantly. So a site carrying unambiguous somatic indel evidence is +# called regardless of what the model thinks: +# indel_frac >= RESCUE_MIN_IFRAC a substantial fraction of reads carry the indel +# conc_ratio >= RESCUE_MIN_CONC they agree on ONE position (clonal, not scattered) +# spanning >= RESCUE_MIN_SPAN enough depth for those fractions to mean anything +# The rescue runs AFTER the low-MAPQ and matched-normal gates, so it can never +# resurrect a germline variant or a repeat pile-up — it only overrides the *model +# score*, never the evidence-based vetoes. +# Cost, measured across both real cohorts: +5 calls in 99,308 CART rows (all 5 are the +# confirmed edits above; zero other rows promoted) and +1 in 5,088 AAVS1 rows. +RESCUE_MIN_IFRAC = 0.15 +RESCUE_MIN_CONC = 0.5 +RESCUE_MIN_SPAN = 20 +# Positional concordance required to call a site "clonal" on the model path. A site can +# clear HI and still fail this when several indel alleles share one cut site — genuine +# multi-allelic editing — so strong depth/burden evidence substitutes for it (see +# verdict()). Measured cost of that substitution: 1 extra call in 96,327 CART rows (a +# confirmed edit) and 0 in 4,933 AAVS1 rows. +CLONAL_MIN = 0.5 +# NOTE: modal_len is NOT gated. A 1bp indel is the MOST common Cas9 outcome (the +# confirmed PLCB2 off-target is 1bp) — length is reported as an annotation only. +# The matched-normal recompute is the real edit-vs-artifact arbiter here. + + +def normal_cram_path(tumor_path): + """Matched normal for a dragen '..._tumor.cram' is '....cram' in the same dir.""" + if tumor_path.endswith("_tumor.cram"): + cand = tumor_path[:-len("_tumor.cram")] + ".cram" + return cand if os.path.exists(cand) else None + return None + + +def control_check(normal_path, chrom, pos, ref, min_span=4, bam_cache=None): + """Recompute indel_frac in the matched normal at the OBSERVED indel position. + Returns (control_if, control_spanning) or (None, 0) if no normal / no coverage. + Pass bam_cache (dict) to reuse open normal handles across candidates.""" + if normal_path is None: + return None, 0 + if bam_cache is not None and normal_path in bam_cache: + bam = bam_cache[normal_path] + else: + bam = pysam.AlignmentFile(normal_path, "rc", reference_filename=ref) + if bam_cache is not None: + bam_cache[normal_path] = bam + rr = read_records(bam, str(chrom), int(pos) - 1, int(pos) + 1) + if rr is None: + return None, 0 + f = features_from_records(rr[0], min_span=min_span, return_lowcov=True) + if f is None or f.get("lowcov"): + return None, f.get("spanning", 0) if f else 0 + return float(f["indel_frac"]), int(f["spanning"]) + + +def verdict(score, feats, ctrl_if=None, rescue=None): + """Returns (verdict, score, call_basis). + + `rescue` is a dict of the high-evidence thresholds (min_ifrac/min_conc/min_span), + or None to disable the rescue and score purely on the model. + """ + if feats is None or feats.get("lowcov"): + return "INSUFFICIENT COVERAGE", np.nan, "" + if feats["modal_mapq"] < 20 and feats["indel_frac"] > 0: + return "ARTIFACT (low-MAPQ repeat)", score, "" + # normal-subtraction: present in matched control => germline/artifact + if ctrl_if is not None: + if ctrl_if >= NORMAL_MAX_IF or feats["indel_frac"] < MIN_EDIT_RATIO * ctrl_if: + return "GERMLINE/ARTIFACT (in normal)", score, "" + # Depth + allele burden: enough reads to judge, and a real share of them edited. + strong = rescue is not None and (feats["indel_frac"] >= rescue["min_ifrac"] + and feats["spanning"] >= rescue["min_span"]) + clonal = feats["conc_ratio"] >= CLONAL_MIN + if score >= HI: + if clonal: + return "LIKELY EDIT", score, "model" + # The model is confident but the reads do not share ONE breakpoint. That is what + # multi-allelic Cas9 editing looks like (several indel alleles at one cut site), + # so clonality is not required when the depth/burden evidence is strong. + if strong: + return "LIKELY EDIT", score, "high-evidence" + # high-evidence rescue: unambiguous somatic indel the ranker under-scored. Gated + # behind the two vetoes above, so this can only override the model, not the evidence. + if strong and feats["conc_ratio"] >= rescue["min_conc"]: + return "LIKELY EDIT", score, "high-evidence" + if score >= MID: + return "POSSIBLE — review", score, "" + return "ARTIFACT (shape)", score, "" + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--table", required=True) + ap.add_argument("--sample") + ap.add_argument("--sheet") + ap.add_argument("--cram-list", default=CRAM_LIST) + ap.add_argument("--ref", default=REF) + ap.add_argument("--model", default=MODEL) + ap.add_argument("--max-mismatch", type=int, default=2) + ap.add_argument("--min-ifrac", type=float, default=0.05) + ap.add_argument("--max-control", type=float, default=0.02) + ap.add_argument("--min-span", type=int, default=8) + ap.add_argument("--include-ontarget", action="store_true") + ap.add_argument("--no-homology-gate", action="store_true", + help="drop the min_mm<=max_mismatch gate (homology-free discovery); " + "min_mm kept as a ranking annotation only") + ap.add_argument("--no-normal-check", action="store_true", + help="skip the matched-normal indel recompute (edited-vs-control)") + ap.add_argument("--max-cut-dist", type=float, default=None, + help="demote LIKELY EDIT calls whose observed indel sits further than this " + "many bp from the predicted cut site (default: off). 10 is a good " + "starting point: on AAVS1 it dropped 23 of 28 false positives without " + "losing either curated edit.") + ap.add_argument("--no-rescue", action="store_true", + help="disable the high-evidence rescue; call LIKELY EDIT on the model " + "score alone (reproduces pre-rescue behaviour)") + ap.add_argument("--rescue-min-ifrac", type=float, default=RESCUE_MIN_IFRAC, + help="rescue: minimum indel fraction in the edited sample") + ap.add_argument("--rescue-min-conc", type=float, default=RESCUE_MIN_CONC, + help="rescue: minimum positional concordance (clonality)") + ap.add_argument("--rescue-min-span", type=int, default=RESCUE_MIN_SPAN, + help="rescue: minimum spanning reads") + ap.add_argument("--tagged-bam-dir", + help="write one per-sample, window-restricted BAM whose reads carry an XC " + "tag naming the per-read call, for colouring the pileup in IGV. Same " + "tag vocabulary as the ECS arm. Windows cover the LIKELY EDIT sites " + "only, so this stays small.") + ap.add_argument("--snapshot-dir", + help="render an IGV-style pileup PNG for each surviving LIKELY-EDIT " + "candidate (edited vs matched normal) into this dir") + ap.add_argument("--top", type=int, default=40) + ap.add_argument("--out") + ap.add_argument("--validate", action="store_true", + help="report where known edits (_truth) land") + args = ap.parse_args() + + rescue = None if args.no_rescue else {"min_ifrac": args.rescue_min_ifrac, + "min_conc": args.rescue_min_conc, + "min_span": args.rescue_min_span} + bundle = joblib.load(args.model) + model, feat_names = bundle["model"], bundle["features"] + # one handle reused for every site; repeat_context reads a ~50bp window per call + ref_fa = pysam.FastaFile(args.ref) + check_sklearn_version(model, name=os.path.basename(args.model)) + crams = cram_index(args.cram_list) + df = load_table(args.table, args.sample, args.sheet) + cand = stage1(df, args.max_mismatch, args.min_ifrac, args.max_control, + args.include_ontarget, args.no_homology_gate) + gate = "NO homology gate" if args.no_homology_gate else f"min_mm<={args.max_mismatch}" + print(f"Stage-1: {len(df)} rows -> {len(cand)} candidates " + f"({gate}, if>{args.min_ifrac}, control<{args.max_control}" + f"{', off-target only' if not args.include_ontarget else ''})", flush=True) + print(f"high-evidence rescue: " + ("DISABLED (model score only)" if rescue is None else + f"indel_frac>={rescue['min_ifrac']}, conc_ratio>={rescue['min_conc']}, " + f"spanning>={rescue['min_span']} (after the normal/MAPQ vetoes)"), flush=True) + + bam_cache, normal_cache, rows = {}, {}, [] + for _, r in cand.iterrows(): + s = r["sample_name"] + rec = {"sample": s, "chrom": r["chrom"], "start": int(r["start"]), + "min_mm": int(r["_min_mm"]), "tbl_if": float(r["_if"]), + "truth": bool(r["_truth"]), "is_target": int(bool(r["_tgt"]))} + if s not in crams: + rec.update(score=np.nan, verdict="NO CRAM", spanning=np.nan, + conc_ratio=np.nan, indel_frac=np.nan); rows.append(rec); continue + if s not in bam_cache: + bam_cache[s] = pysam.AlignmentFile(crams[s], "rc", reference_filename=args.ref) + rr = read_records(bam_cache[s], str(r["chrom"]), int(r["start"]), int(r["end"])) + # cut_pos is the PREDICTED cut (the hotspot coordinate), so features_from_records + # can emit cut_dist against the OBSERVED modal indel position. + feats = None if rr is None else features_from_records( + rr[0], min_span=args.min_span, return_lowcov=True, cut_pos=int(r["start"])) + if feats is None or feats.get("lowcov"): + v, sc, basis = verdict(0.0, feats, rescue=rescue) + rec.update(score=np.nan, verdict=v, call_basis=basis, + spanning=(feats or {}).get("spanning", 0), + conc_ratio=np.nan, indel_frac=np.nan, modal_len=np.nan, + modal_pos=np.nan, ctrl_if=np.nan, cut_dist=np.nan, + homopolymer_len=np.nan, repeat_frac=np.nan) + else: + # The observed indel position is needed BEFORE scoring, because the reference + # context features are measured there and are model inputs. + opos = feats.get("modal_pos") or int(r["start"]) + # merge into feats (not just into the output row): feat_names comes from the + # model bundle, so a model trained with these features looks them up here. + feats.update(repeat_context(ref_fa, r["chrom"], opos)) + sc = float(model.predict_proba(pd.DataFrame([{k: feats[k] for k in feat_names}]))[0, 1]) + ctrl_if, ctrl_span = (None, 0) + if not args.no_normal_check: + ctrl_if, ctrl_span = control_check(normal_cram_path(crams[s]), + r["chrom"], opos, args.ref, + bam_cache=normal_cache) + v, sc, basis = verdict(sc, feats, ctrl_if, rescue=rescue) + rec.update(score=sc, verdict=v, call_basis=basis, spanning=feats["spanning"], + conc_ratio=round(feats["conc_ratio"], 3), + indel_frac=round(feats["indel_frac"], 3), + modal_len=feats.get("modal_len"), modal_pos=opos, + # cut_dist now comes from features_from_records so the model input and + # the reported column can never disagree. NaN when no indel was seen. + cut_dist=feats.get("cut_dist"), + # reference-context features, already merged into feats above so the + # model input and the reported column cannot diverge + homopolymer_len=feats.get("homopolymer_len"), + repeat_frac=feats.get("repeat_frac"), + ctrl_if=(round(ctrl_if, 3) if ctrl_if is not None else np.nan), + ctrl_span=ctrl_span, + # remaining MODEL_FEATURES, emitted so the training table (via + # join_training_table.py) carries the full shape-model feature set + # for the offline trainer (-entry TRAIN). NaN in the lowcov/NO-CRAM + # branches is filled automatically by the DataFrame union. + pos_conc=round(feats["pos_conc"], 4), + pos_mad=round(feats["pos_mad"], 3), + modal_mapq=round(feats["modal_mapq"], 1), + softclip_frac=round(feats["softclip_frac"], 4)) + rows.append(rec) + + res = add_recurrence(pd.DataFrame(rows)) + # Optional cut-site gate, OFF by default so no existing run changes silently. This is a + # DEMOTION, not a deletion: the row, its score and its features all stay in the table, so + # a reviewer can still see what was set aside and why. + if args.max_cut_dist is not None and "cut_dist" in res.columns: + far = (res["verdict"].astype(str).str.contains("LIKELY EDIT", na=False) + & (res["cut_dist"] > args.max_cut_dist)) + res.loc[far, "call_basis"] = f"demoted: cut_dist > {args.max_cut_dist:g}" + res.loc[far, "verdict"] = "ARTIFACT (far from cut)" + print(f"cut-site gate <= {args.max_cut_dist:g}bp: demoted {int(far.sum())} " + f"LIKELY EDIT call(s) whose indel sits far from the predicted cut") + # tier first (A>B>C>D), then score within tier + torder = {"A-review-first": 0, "B-review": 1, "C-recurrent-artifact": 2, "D-artifact": 3} + res["_o"] = res["priority"].map(torder).fillna(3) + res = res.sort_values(["_o", "score", "min_mm"], ascending=[True, False, True], + na_position="last").drop(columns="_o").reset_index(drop=True) + res.insert(0, "rank", res.index + 1) + + cols = ["rank", "priority", "sample", "chrom", "start", "min_mm", "indel_frac", + "ctrl_if", "modal_len", "conc_ratio", "score", "verdict", "call_basis", + "n_guides_at_site"] + cols = [c for c in cols if c in res.columns] + if res["truth"].any(): + cols.append("truth") + print(f"\nTop {min(args.top, len(res))} candidates (tiered):") + with pd.option_context("display.max_rows", None, "display.width", 190): + print(res[cols].head(args.top).to_string(index=False)) + print("\ntiers: " + res["priority"].value_counts().reindex( + ["A-review-first", "B-review", "C-recurrent-artifact", "D-artifact"]).dropna().to_string()) + if "call_basis" in res.columns: + n_resc = int((res["call_basis"] == "high-evidence").sum()) + n_model = int((res["call_basis"] == "model").sum()) + print(f"LIKELY EDIT by basis: model={n_model}, high-evidence rescue={n_resc}") + + if args.out: + res.to_csv(args.out, index=False) + print(f"\nwrote {args.out} ({len(res)} scored)") + + # Per-read XC-tagged BAMs for the WGS arm, so a reviewer can interrogate the pileup in IGV + # rather than only look at a rendered PNG. Windows cover the called sites only. + if args.tagged_bam_dir: + from wgs_tag_reads import tag_wgs_bam + os.makedirs(args.tagged_bam_dir, exist_ok=True) + called = res[res["verdict"].astype(str).str.contains("LIKELY EDIT", na=False)] + if called.empty: + print("\nno LIKELY EDIT calls; no WGS tagged BAM written") + for s_name, grp in called.groupby("sample"): + if s_name not in bam_cache: + if s_name not in crams: + continue + bam_cache[s_name] = pysam.AlignmentFile(crams[s_name], "rc", + reference_filename=args.ref) + # tag at the OBSERVED indel position where we have one: that is where the reviewer + # needs to look, and it can sit tens of bp from the predicted cut (see cut_dist). + sites = [(row["chrom"], + int(row["modal_pos"]) if pd.notna(row.get("modal_pos")) + else int(row["start"])) + for _, row in grp.iterrows()] + out_bam = os.path.join(args.tagged_bam_dir, f"{s_name}.wgs_tagged.bam") + n = tag_wgs_bam(bam_cache[s_name], sites, out_bam) + print(f" WGS tagged BAM: {n} reads over {len(sites)} called site(s) -> {out_bam}") + + # auto-render IGV-style edited-vs-normal snapshots for surviving LIKELY EDITs + if args.snapshot_dir: + import matplotlib; matplotlib.use("Agg") + import matplotlib.pyplot as plt + from pileup_snapshot import snapshot + os.makedirs(args.snapshot_dir, exist_ok=True) + surv = res[res["verdict"] == "LIKELY EDIT"] + print(f"\nrendering {len(surv)} LIKELY-EDIT snapshots -> {args.snapshot_dir}/") + for _, k in surv.iterrows(): + s = k["sample"]; tpath = crams.get(s) + if not tpath: + continue + pos = int(k["modal_pos"]) if pd.notna(k.get("modal_pos")) else int(k["start"]) + npath = normal_cram_path(tpath) + fig, axes = plt.subplots(1, 2 if npath else 1, figsize=(15 if npath else 8, 6.5), + squeeze=False) + snapshot(axes[0][0], tpath, str(k["chrom"]), pos, args.ref, window=45, + title=f"{s}_tumor (EDITED) score={k['score']:.2f}") + if npath: + snapshot(axes[0][1], npath, str(k["chrom"]), pos, args.ref, window=45, + title=f"{s} (NORMAL) ctrl_if={k.get('ctrl_if')}") + fig.suptitle(f"{s} {k['chrom']}:{pos:,} min_mm={k['min_mm']} {k['verdict']}", + fontweight="bold") + fig.tight_layout() + fig.savefig(f"{args.snapshot_dir}/rank{int(k['rank']):03d}_{s}_{k['chrom']}_{pos}.png", dpi=120) + plt.close(fig) + print(f" done ({len(surv)} PNGs)") + + if args.validate and res["truth"].any(): + kn = res[res["truth"]] + print(f"\n== VALIDATION: {len(kn)} known edit(s) among candidates ==") + for _, k in kn.iterrows(): + print(f" rank {int(k['rank'])}/{len(res)} {k['sample']} {k['chrom']}:{k['start']}" + f" is_target={k['is_target']} score={k['score']} verdict='{k['verdict']}'") + + print("\nNOTE: ranks sites to REVIEW; not an off-target recall estimate. Low-VAF " + "off-targets below the depth floor surface as INSUFFICIENT COVERAGE.") + + +if __name__ == "__main__": + main() diff --git a/bin/simulate_sv_reads.py b/bin/simulate_sv_reads.py new file mode 100755 index 0000000..83c05ac --- /dev/null +++ b/bin/simulate_sv_reads.py @@ -0,0 +1,164 @@ +import argparse +import pysam +import numpy as np +import gzip +import random +import sys + +def parse_args(): + parser = argparse.ArgumentParser(description="Simulate reads for a region defined by a center point and flanking size.") + parser.add_argument("-r", "--reference", required=True, help="Indexed Reference FASTA file") + parser.add_argument("-c", "--chrom", required=True, help="Chromosome") + + # NEW ARGUMENTS: Center + Flank + parser.add_argument("-p", "--position", type=int, required=True, help="Center genomic coordinate (1-based)") + parser.add_argument("-f", "--flank", type=int, required=True, help="Flanking size on either side of the position") + + parser.add_argument("--prob-del", type=float, default=0.1, help="Probability of a read having a Deletion") + parser.add_argument("--prob-dup", type=float, default=0.6, help="Probability of a read having a Duplication") + + parser.add_argument("--mean-insert", type=float, default=350, help="Mean insert size (default: 500)") + parser.add_argument("--std-insert", type=float, default=100, help="Std dev of insert size (default: 50)") + parser.add_argument("--read-count", type=int, default=10000, help="Total number of read pairs to simulate") + + # SV Size Control + parser.add_argument("--mean-sv-size", type=float, default=100, help="Mean (scale) for SV size (exponential)") + parser.add_argument("--min-sv-size", type=int, default=1, help="Hard minimum SV size") + parser.add_argument("--max-sv-size", type=int, default=5000, help="Hard maximum SV size") + + # SV Position Control + parser.add_argument("--mean-offset", type=float, default=3.0, help="Mean distance of SV center from the target Position (exponential)") + + parser.add_argument("--out-prefix", default="simulated_flanked", help="Output file prefix") + return parser.parse_args() + +def reverse_complement(seq): + complement = {'A': 'T', 'C': 'G', 'G': 'C', 'T': 'A', 'N': 'N', + 'a': 't', 'c': 'g', 'g': 'c', 't': 'a', 'n': 'n'} + return "".join(complement.get(base, base) for base in reversed(seq)) + +def get_exponential_sv_size(mean, min_val, max_val): + while True: + val = int(np.random.exponential(scale=mean)) + if min_val <= val <= max_val: + return val + +def generate_mutated_sequence(ref_seq, sv_type, args, region_start): + region_len = len(ref_seq) + buffer = 500 + + # 1. Determine SV Size + effective_max = min(args.max_sv_size, region_len - (2 * buffer)) + if effective_max < args.min_sv_size: + return ref_seq, 0, 0, 0 + + sv_size = get_exponential_sv_size(args.mean_sv_size, args.min_sv_size, effective_max) + + # 2. Determine Position + # Center logic: We want the SV to be near the MIDDLE of the fetched seq. + midpoint = region_len // 2 + offset_dist = int(np.random.exponential(scale=args.mean_offset)) + direction = random.choice([-1, 1]) + + sv_center = midpoint + (direction * offset_dist) + + rel_start = sv_center - (sv_size // 2) + rel_end = rel_start + sv_size + + # 3. Boundary Checks (Clamping) + min_valid_start = buffer + max_valid_start = region_len - buffer - sv_size + + if rel_start < min_valid_start: rel_start = min_valid_start + if rel_start > max_valid_start: rel_start = max_valid_start + rel_end = rel_start + sv_size + + # Absolute coords + abs_start = region_start + rel_start + abs_end = region_start + rel_end + + # 4. Construct Sequence + if sv_type == 'DEL': + new_seq = ref_seq[:rel_start] + ref_seq[rel_end:] + elif sv_type == 'DUP': + dup_block = ref_seq[rel_start:rel_end] + new_seq = ref_seq[:rel_end] + dup_block + ref_seq[rel_end:] + else: + new_seq = ref_seq + abs_start = 0 + abs_end = 0 + sv_size = 0 + + return new_seq, abs_start, abs_end, sv_size + +def main(): + args = parse_args() + + # --- Calculate Start/End from Position/Flank --- + region_start = max(1, args.position - args.flank) + region_end = args.position + args.flank + + print(f"Target: {args.chrom}:{args.position} +/- {args.flank}bp") + print(f"Fetching region: {args.chrom}:{region_start}-{region_end}") + + prob_wt = 1.0 - (args.prob_del + args.prob_dup) + if prob_wt < 0: prob_wt = 0.0 + + fasta = pysam.FastaFile(args.reference) + try: + ref_seq = fasta.fetch(args.chrom, region_start - 1, region_end) + except ValueError: + sys.exit(f"Error fetching region") + + r1_fn = f"{args.out_prefix}_R1.fastq.gz" + r2_fn = f"{args.out_prefix}_R2.fastq.gz" + read_len = 151 + + print(f"Simulating {args.read_count} reads...") + print(f"Probabilities -> WT: {prob_wt:.2f}, DEL: {args.prob_del:.2f}, DUP: {args.prob_dup:.2f}") + + with gzip.open(r1_fn, 'wt') as f1, gzip.open(r2_fn, 'wt') as f2: + for i in range(args.read_count): + + choice = random.choices(['WT', 'DEL', 'DUP'], weights=[prob_wt, args.prob_del, args.prob_dup])[0] + + if choice == 'WT': + current_seq = ref_seq + sv_info = "WT:0-0" + else: + current_seq, sv_s, sv_e, sv_len = generate_mutated_sequence(ref_seq, choice, args, region_start) + sv_info = f"{choice}:{sv_s}-{sv_e}" + + valid_frag = False + attempts = 0 + seq_len = len(current_seq) + + while not valid_frag and attempts < 10: + insert_size = int(np.random.normal(args.mean_insert, args.std_insert)) + if insert_size < read_len: insert_size = read_len + + if seq_len > insert_size: + frag_start = random.randint(0, seq_len - insert_size) + frag_end = frag_start + insert_size + fragment = current_seq[frag_start:frag_end] + valid_frag = True + attempts += 1 + + if not valid_frag: continue + + seq_r1 = fragment[:read_len] + seq_r2 = reverse_complement(fragment[-read_len:]) + + if len(seq_r1) < read_len: seq_r1 = seq_r1.ljust(read_len, 'N') + if len(seq_r2) < read_len: seq_r2 = seq_r2.ljust(read_len, 'N') + + qual = 'I' * read_len + header_base = f"@{i}:{args.chrom}:{region_start}-{region_end}_{sv_info}" + + f1.write(f"{header_base}/1\n{seq_r1}\n+\n{qual}\n") + f2.write(f"{header_base}/2\n{seq_r2}\n+\n{qual}\n") + + print(f"Done. Wrote to {r1_fn} and {r2_fn}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/bin/subset_noise_panel.py b/bin/subset_noise_panel.py new file mode 100644 index 0000000..e829ca6 --- /dev/null +++ b/bin/subset_noise_panel.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +""" +subset_noise_panel.py — cut a DRAGEN systematic-noise panel down to the sites a guide can query. + +Why this exists +--------------- +The IDPF SNV panel is 1 GB compressed / 97,851,753 records, and `load_snv_noise` streams it +whole because it ships without a tabix index. Paid once per cohort that is ~3 minutes and nobody +notices. Paid once per SAMPLE -- which is what happens if the panel lookup moves into the caller -- +it becomes ~3 minutes x N samples, and on the 32-sample CAR-T cohort that is over an hour of pure +re-reading of the same file. + +The fix is that the panel only ever gets asked about positions in the guide's target file, and a +target file is per-GUIDE, not per-sample. So subset once per guide panel and every sample sharing +that guide reads a file that fits in memory. + +Measured on the 32-sample CAR-T cohort: 97,851,753 records -> 4,891 (60 KB), a 20,000x reduction, +and `review_filter.py` produces byte-identical output from the subset. The reduction is lossless by +construction: `load_snv_noise` keeps a record only when its END column lands within +/-slop of a +queried position, so anything dropped here could never have been returned. + +This also retires the tabix question -- an index solves a problem the subset removes outright. + +usage: + # from a caller output table (uses its chrom/end columns) + subset_noise_panel.py --panel IDPF_...snv.bed.gz --sites SAMPLE.offtarget_analysis.tsv \\ + -o panel.subset.bed.gz + + # from the guide's target file, before any sample has been called + subset_noise_panel.py --panel IDPF_...snv.bed.gz --targets GUIDE.targets.csv \\ + -o panel.subset.bed.gz +""" +import argparse +import glob +import gzip +import sys + +import pandas as pd + +DEFAULT_SLOP = 2 + + +def positions_from_tables(paths, slop): + """Union of (chrom, end +/- slop) over caller output tables.""" + want = {} + n = 0 + for p in paths: + df = pd.read_csv(p, sep="\t", usecols=["chrom", "end"]) + n += len(df) + for c, e in zip(df.chrom, df.end): + s = want.setdefault(str(c), set()) + for d in range(-slop, slop + 1): + s.add(int(e) + d) + return want, n + + +def positions_from_targets(paths, slop, window): + """Union of target windows from a guide target file (CSV/BED/VCF-ish). + + A target file gives the site, not the exact indel position, so each target contributes a + window rather than a point -- `window` should be at least the caller's --target-window. + """ + want = {} + n = 0 + for p in paths: + sep = "\t" if p.endswith((".bed", ".tsv", ".txt")) else "," + df = pd.read_csv(p, sep=sep, comment="#") + cols = {c.lower(): c for c in df.columns} + cc = cols.get("chrom") or cols.get("chromosome") or cols.get("#chrom") or df.columns[0] + pc = cols.get("start") or cols.get("pos") or cols.get("position") or df.columns[1] + n += len(df) + for c, p0 in zip(df[cc], df[pc]): + try: + p0 = int(p0) + except (TypeError, ValueError): + continue + s = want.setdefault(str(c), set()) + for d in range(-window - slop, window + slop + 1): + s.add(p0 + d) + return want, n + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--panel", required=True, help="systematic_noise.snv.bed.gz") + ap.add_argument("--sites", nargs="*", default=[], help="*.offtarget_analysis.tsv") + ap.add_argument("--targets", nargs="*", default=[], help="guide target file(s)") + ap.add_argument("-o", "--out", required=True, help="output .bed.gz") + ap.add_argument("--slop", type=int, default=DEFAULT_SLOP, + help=f"must be >= the slop the consumer uses (default {DEFAULT_SLOP}); too " + f"small silently drops records the filter would have matched") + ap.add_argument("--window", type=int, default=150, + help="half-width around each target site for --targets (default 150, the " + "caller's --target-window)") + a = ap.parse_args() + + paths = lambda pats: [f for p in pats + for f in (sorted(glob.glob(p)) if any(ch in p for ch in "*?[") else [p])] + if a.sites: + want, n_in = positions_from_tables(paths(a.sites), a.slop) + src = f"{n_in} table rows" + elif a.targets: + want, n_in = positions_from_targets(paths(a.targets), a.slop, a.window) + src = f"{n_in} target sites (+/-{a.window} bp)" + else: + sys.exit("ERROR: give --sites or --targets") + + n_pos = sum(len(v) for v in want.values()) + print(f"queryable positions: {n_pos} from {src}") + + kept = seen = 0 + op = gzip.open if a.panel.endswith(".gz") else open + with op(a.panel, "rt") as fh, gzip.open(a.out, "wt") as og: + for line in fh: + if line[0] == "#": + og.write(line) # keep the header: ##PON SAMPLES gives N for --panel-p + continue + seen += 1 + f = line.split("\t", 3) + s = want.get(f[0]) + if s is None: + continue + try: + if int(f[2]) in s: + og.write(line) + kept += 1 + except (ValueError, IndexError): + continue + pct = kept / seen * 100 if seen else 0 + print(f"panel records {seen} -> {kept} ({pct:.4f}%) -> {a.out}") + + +if __name__ == "__main__": + main() diff --git a/bin/targets_csv_to_vcf.py b/bin/targets_csv_to_vcf.py new file mode 100755 index 0000000..9fa1a13 --- /dev/null +++ b/bin/targets_csv_to_vcf.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +"""Convert a combined off-target sites CSV into the per-base hotspot VCF the OFFTARGET +arm consumes as a ``target_file``. + +Each predicted site (a ``Start`` on a ``Chromosome`` in the combined sites table) is +expanded to a ``±window`` bp interval; overlapping intervals are merged; and every base in +the merged intervals becomes a VCF record ``CHROM POS . N . PASS`` with the reference +base fetched from the FASTA. Records are written with a contig header and sorted to the +reference's contig order, so the result opens cleanly with ``pysam.VariantFile`` in +``bin/find_edited_reads.py``. + +This is the productionized successor to ``workflow/make_hotspot_file/make_hotspot_file.py`` +(hardcoded FASTA path replaced by ``--fasta``; robust pysam writer from +``bin/make_hotspot_vcf.py``). + + targets_csv_to_vcf.py --csv guide.targets.csv --fasta ref.fa --window 200 -o guide.targets.vcf +""" +import argparse +import os +import sys + +import pandas as pd +import pysam + +__version__ = "1.0.0" + + +def check_file(path): + if not os.path.isfile(path): + raise argparse.ArgumentTypeError(f"File not found: {path}") + return path + + +def merged_intervals(df): + """[(chrom, start, end)] merged per chrom; inputs are 0-based half-open [start, end).""" + out = [] + for chrom, grp in df.sort_values(["Chromosome", "Start"]).groupby("Chromosome", sort=False): + cur_s = cur_e = None + for s, e in zip(grp["Start"], grp["End"]): + if cur_s is None: + cur_s, cur_e = s, e + elif s <= cur_e: # overlap or touch -> extend + cur_e = max(cur_e, e) + else: + out.append((chrom, cur_s, cur_e)) + cur_s, cur_e = s, e + if cur_s is not None: + out.append((chrom, cur_s, cur_e)) + return out + + +def main(argv=None): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--csv", type=check_file, help="Combined off-target sites CSV (needs Chromosome,Start).") + ap.add_argument("--bed", type=check_file, help="Optional BED of extra hotspot regions.") + ap.add_argument("--fasta", type=check_file, required=True, help="Indexed reference FASTA.") + ap.add_argument("--window", type=int, default=200, help="bp up/downstream of each site.") + ap.add_argument("-o", "--outfile", required=True, help="Output VCF.") + ap.add_argument("--version", action="version", version=f"%(prog)s {__version__}") + args = ap.parse_args(argv) + + if not (args.csv or args.bed): + ap.error("provide --csv and/or --bed") + + regions = [] + if args.csv: + csv = pd.read_csv(args.csv, usecols=["Chromosome", "Start"]) + csv = csv.dropna(subset=["Chromosome", "Start"]) + csv["Start"] = csv["Start"].astype(int) + # window around the site; clamp lower bound at 0 (0-based half-open) + r = pd.DataFrame({ + "Chromosome": csv["Chromosome"], + "Start": (csv["Start"] - args.window).clip(lower=0), + "End": csv["Start"] + args.window, + }) + regions.append(r) + if args.bed: + bed = pd.read_csv(args.bed, sep="\t", usecols=[0, 1, 2], + names=["Chromosome", "Start", "End"]) + regions.append(bed) + + df = pd.concat(regions, ignore_index=True) + if df.empty: + print("WARNING: no target regions; writing header-only VCF", file=sys.stderr) + + fasta = pysam.FastaFile(args.fasta) + valid = set(fasta.references) + + # Build the VCF header with contigs from the FASTA (needed for a sorted, indexable VCF). + header = pysam.VariantHeader() + for contig in fasta.references: + header.contigs.add(contig, length=fasta.get_reference_length(contig)) + + # Expand merged intervals to per-base records, collected then sorted to contig order. + records = [] # (contig_rank, pos, chrom, ref_base) + rank = {c: i for i, c in enumerate(fasta.references)} + for chrom, start, end in merged_intervals(df): + if chrom not in valid: + print(f"WARNING: {chrom} not in reference; skipping", file=sys.stderr) + continue + seq = fasta.fetch(chrom, start, end) + for i, base in enumerate(seq): + records.append((rank[chrom], start + i, chrom, base)) + records.sort(key=lambda t: (t[0], t[1])) + + with pysam.VariantFile(args.outfile, "w", header=header) as vcf_out: + for _, pos0, chrom, base in records: + rec = vcf_out.new_record() + rec.chrom = chrom + rec.pos = pos0 + 1 # VCF is 1-based; pos0 is 0-based + rec.id = "." + rec.ref = base if base and base.upper() in "ACGTN" else "N" + rec.alts = ("N",) + rec.filter.add("PASS") + vcf_out.write(rec) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/bin/train_shape_model.py b/bin/train_shape_model.py new file mode 100755 index 0000000..fbb179b --- /dev/null +++ b/bin/train_shape_model.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +""" +train_shape_model.py — offline trainer for the off-target WGS shape model. + +Reads a training.tsv (as emitted by BUILD_TRAINING_TABLE: WGS pileup features x +ECS-truth VAF + label) and fits the Stage-2 shape ranker consumed by score.py and +worklist_from_vcf.py. Emits a joblib bundle {model, features, ...} that is a drop-in +for --offtarget_shape_model. + +The bundle records exactly which features the model was trained on; score.py and +worklist_from_vcf.py select model inputs by bundle["features"], so a training table +that carries only a subset of MODEL_FEATURES still yields a deployable (if weaker) +model. Patch score.py / join_training_table.py to carry the full feature set for the +strongest model. + +Run inside the pipeline's off-target container so the pickle is written under the +same scikit-learn the pipeline runs — the version guard in features.check_sklearn_version +raises if the deployment runtime is OLDER than the pickle. +""" +import argparse +import json +import os +import sys + +import numpy as np +import pandas as pd + +# MODEL_FEATURES is defined once in features.py (the single source of truth). Import +# it if this script sits beside features.py (it does, in bin/); otherwise fall back to +# a literal copy kept in sync with features.MODEL_FEATURES. +try: + sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + from features import MODEL_FEATURES +except Exception: + MODEL_FEATURES = ["indel_frac", "conc_ratio", "pos_conc", "pos_mad", + "modal_len", "modal_mapq", "softclip_frac"] + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--training", required=True, + help="training.tsv from BUILD_TRAINING_TABLE (WGS features + label)") + ap.add_argument("--out", default="wgs_shape_model.pkl", help="output model bundle (.pkl)") + ap.add_argument("--metrics", default="train_metrics.json", help="output metrics JSON") + ap.add_argument("--learning-rate", type=float, default=0.05) + ap.add_argument("--max-iter", type=int, default=200) + ap.add_argument("--max-depth", type=int, default=3) + ap.add_argument("--max-leaf-nodes", type=int, default=31) + ap.add_argument("--l2", type=float, default=1.0, help="L2 regularization") + ap.add_argument("--holdout-frac", type=float, default=0.25, + help="stratified holdout fraction for reporting AUC/AP (0 = train on all, no holdout)") + ap.add_argument("--seed", type=int, default=1) + ap.add_argument("--allow-nan-features", action="store_true", + help="keep rows with NaN features instead of dropping them. " + "HistGradientBoostingClassifier supports missing values natively; " + "needed whenever a feature is meaningfully absent (cut_dist is NaN " + "wherever no indel was observed, i.e. ~90%% of a hotspot panel).") + args = ap.parse_args() + + import sklearn + import joblib + from sklearn.ensemble import HistGradientBoostingClassifier + from sklearn.metrics import average_precision_score, roc_auc_score + from sklearn.model_selection import train_test_split + + df = pd.read_csv(args.training, sep="\t") + if "label" not in df.columns: + sys.exit("ERROR: training table has no 'label' column") + + feats = [f for f in MODEL_FEATURES if f in df.columns] + if not feats: + sys.exit(f"ERROR: none of the model features {MODEL_FEATURES} are present in the " + f"training table (columns: {list(df.columns)})") + missing = [f for f in MODEL_FEATURES if f not in df.columns] + if missing: + print(f"WARN: training table is missing {missing}; training a {len(feats)}-feature model " + f"on {feats}. Patch score.py / join_training_table.py to carry the full feature set " + f"for the strongest model.", file=sys.stderr) + + X = df[feats].apply(pd.to_numeric, errors="coerce") + y = pd.to_numeric(df["label"], errors="coerce") + # HistGradientBoostingClassifier handles NaN natively (it learns a missing-value branch + # per split), so requiring every feature to be present is a choice, not a necessity -- + # and an expensive one now that the feature set includes cut_dist, which is legitimately + # NaN at any site with no observed indel. On the CART panel that is 90% of rows + # (9,278 of 99,308 have a cut_dist), so the default drops nine tenths of the training + # data the moment cut_dist is added. --allow-nan-features keeps those rows and lets the + # model treat "no indel to measure" as its own branch. Default is unchanged so existing + # models stay reproducible. + ok = y.notna() + if not args.allow_nan_features: + ok &= X.notna().all(axis=1) + dropped = int((~ok).sum()) + X, y = X[ok].reset_index(drop=True), y[ok].astype(int).reset_index(drop=True) + n_pos, n_neg = int((y == 1).sum()), int((y == 0).sum()) + if n_pos == 0 or n_neg == 0: + sys.exit(f"ERROR: need both classes to train; got {n_pos} positive / {n_neg} negative rows") + + def make_clf(): + return HistGradientBoostingClassifier( + learning_rate=args.learning_rate, max_iter=args.max_iter, max_depth=args.max_depth, + max_leaf_nodes=args.max_leaf_nodes, l2_regularization=args.l2, + random_state=args.seed, early_stopping=False) + + metrics = {"n_rows": int(len(y)), "n_pos": n_pos, "n_neg": n_neg, "n_dropped_incomplete": dropped, + "features": feats, "missing_features": missing, "sklearn": sklearn.__version__, + "hyperparams": {"learning_rate": args.learning_rate, "max_iter": args.max_iter, + "max_depth": args.max_depth, "max_leaf_nodes": args.max_leaf_nodes, + "l2_regularization": args.l2, "seed": args.seed}} + + # Optional stratified holdout to report generalization (AUC/AP) before the final fit. + if 0 < args.holdout_frac < 1 and n_pos >= 2 and n_neg >= 2: + X_tr, X_te, y_tr, y_te = train_test_split( + X, y, test_size=args.holdout_frac, random_state=args.seed, stratify=y) + p = make_clf().fit(X_tr, y_tr).predict_proba(X_te)[:, 1] + metrics["holdout_n"] = int(len(y_te)) + metrics["holdout_auc"] = float(roc_auc_score(y_te, p)) if y_te.nunique() > 1 else None + metrics["holdout_ap"] = float(average_precision_score(y_te, p)) + else: + metrics["holdout_auc"] = None + metrics["holdout_note"] = "holdout skipped (holdout_frac<=0 or too few of one class)" + + # Final model: fit on ALL rows for deployment. + clf = make_clf().fit(X, y) + + bundle = { + "model": clf, + "features": feats, + "role": "stage2_shape_ranker", + "depth_augmented": False, + "aug_depths": [], + "stage1_filter": "is_target==0, min_mm<=2, indel_fraction>0.05, control_if<0.02, spanning>=8", + "trained_on": (f"train_shape_model.py on {os.path.basename(args.training)} " + f"({n_pos} pos / {n_neg} neg loci, {len(feats)} features)"), + "n_pos_loci": n_pos, + "n_neg_loci": n_neg, + } + joblib.dump(bundle, args.out) + with open(args.metrics, "w") as fh: + json.dump(metrics, fh, indent=2) + + auc = metrics.get("holdout_auc") + print(f"wrote {args.out}: HistGradientBoostingClassifier on {len(feats)} features " + f"[{', '.join(feats)}], {n_pos} pos / {n_neg} neg" + + (f", holdout AUC={auc:.3f}" if auc is not None else " (no holdout AUC)")) + print(f"wrote {args.metrics}") + + +if __name__ == "__main__": + main() diff --git a/bin/validate_recall.py b/bin/validate_recall.py new file mode 100755 index 0000000..bc6e154 --- /dev/null +++ b/bin/validate_recall.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 +""" +validate_recall.py — WGS recall against the HUMAN-REVIEWED gold standard. + +Why this exists +--------------- +`recall_vs_vaf.py` measures recall against the ECS label (`ecs_is_edit`), whose +denominator is set by `offtarget_ecs_edit_threshold`. At the default of 0.0 ANY nonzero +ECS indel fraction counts as an edit, so the denominator fills with ECS noise: in the +CART run 47,170 of ~64,000 "positives" sit below 0.5% VAF. Recall against that +denominator (~2%) says nothing about whether the pipeline finds real CRISPR edits. + +The defensible denominator is the manual review: the per-sample `*.edited_reads.xlsm` +curation merged into `cart_ecs_merged.csv.gz`, where `manual_review == 1` marks a +human-confirmed real CRISPR edit. This script scores the pipeline against exactly that +set and prints the misses, so "100% recall" is a number anyone can re-derive rather than +a claim. + +Usage +----- + validate_recall.py --scores results/offtarget/wgs_hotspot_scores.csv \ + --gold "Manual Indel Review/cart_ecs/cart_ecs_merged.csv.gz" + +Why there is no precision / F-beta here +--------------------------------------- +Deliberate, and not an oversight. This table has confirmed POSITIVES only: 55 rows with +manual_review == '1', one '1?', and ~80,440 NaN — and NaN means NOT REVIEWED, not +reviewed-and-rejected. With no confirmed negatives there is no false-positive count, so +precision, F1 and F-beta are simply not defined against it. Computing them anyway (by +filling NaN with 0) would score every genuine discovery the reviewers never got to as a +false positive and produce a confidently wrong number. + +Precision-bearing metrics therefore live in `bin/offtarget_metrics.py`, which uses the +ECS label in training.tsv — a real two-class label — and says so on its own face. If a +curated negative set ever exists, add it here as an explicit `--negatives` source; until +then this script stays recall-only. + +Joins on (guide, chrom, start). The gold table keys samples by their review-sheet name +(`CART_NS0011-ABTB1`); the pipeline keys them by CRAM sample (`ABTB1-KO-DNA`). Both +carry the guide, so the guide is the join key and `--guide-alias` patches the handful of +sheet-name typos that would otherwise silently drop truth rows. +""" +import argparse +import re +import sys + +import pandas as pd + +# Sheet-name typos in the manual-review workbooks that do not match the pipeline's guide +# names. These are DATA fixes, not logic: without them the affected truth rows join to +# nothing and inflate recall by vanishing from the denominator. +GUIDE_ALIAS = {"CTLA41": "CTLA4"} + +# A single corrupted cell: CART_NS0011-CREBRF.edited_reads.xlsm carries chrom "c" for +# chr5:173,090,439 (CREBRF is chr5q35.1). Same reasoning — repair, do not drop. +CHROM_REPAIR = {"c": "chr5"} + +CONFIRMED = {"1", "1.0", "1?"} + + +def guide_from_sample(name, alias): + """`CART_NS0011-ABTB1` -> ABTB1; `CART_NS0027-CTLA41_2` -> CTLA4.""" + g = str(name).split("-", 1)[1] if "-" in str(name) else str(name) + g = re.sub(r"_\d+$", "", g) + return alias.get(g, g) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--scores", required=True, help="wgs_hotspot_scores.csv from score.py") + ap.add_argument("--gold", required=True, + help="merged manual-review table with a manual_review column") + ap.add_argument("--samplesheet", + help="offtarget samplesheet (sample,guide,...) — the AUTHORITATIVE " + "sample->guide map. Without it the scored table's own `guide` " + "column is used, which add_recurrence() derives from the sample " + "name and is only a recurrence proxy (e.g. 'ABTB1-KO-DNA').") + ap.add_argument("--training", + help="training.tsv — alternative sample->guide source (it carries the " + "samplesheet-resolved guide)") + ap.add_argument("--guide-alias", action="append", default=[], metavar="SHEET=PIPELINE", + help="extra guide-name alias; repeatable") + ap.add_argument("--hi", type=float, default=0.60, + help="model-score threshold, for the score-only comparison") + ap.add_argument("--out", help="write the per-site audit table here") + ap.add_argument("--require-recall", type=float, + help="exit non-zero if recall falls below this (for CI)") + args = ap.parse_args() + + alias = dict(GUIDE_ALIAS) + for a in args.guide_alias: + k, _, v = a.partition("=") + alias[k] = v + + gold = pd.read_csv(args.gold, low_memory=False) + if "manual_review" not in gold.columns: + sys.exit("ERROR: --gold has no manual_review column; this is not a review table") + gold = gold[gold["manual_review"].astype(str).str.strip().isin(CONFIRMED)].copy() + gold["guide"] = gold["sample_name"].map(lambda s: guide_from_sample(s, alias)) + gold["chrom"] = gold["chrom"].astype(str).replace(CHROM_REPAIR) + gold["start"] = pd.to_numeric(gold["start"], errors="coerce").astype("Int64") + gold = gold.rename(columns={"indel_fraction": "ecs_if"}) + + sc = pd.read_csv(args.scores, low_memory=False) + # Resolve sample -> guide. The scored table's own `guide` column comes from + # add_recurrence(), which just strips a _1/_2 replicate suffix off the sample name — + # fine for the recurrence grouping it was built for, wrong as a join key against the + # review sheets. Prefer a real map when one is supplied. + smap = None + if args.samplesheet: + ss = pd.read_csv(args.samplesheet) + ss.columns = [c.strip().lower() for c in ss.columns] + smap = dict(zip(ss["sample"], ss["guide"])) + elif args.training: + tt = pd.read_csv(args.training, sep="\t") + smap = dict(zip(tt["sample"], tt["guide"])) + if smap: + sc["guide"] = sc["sample"].map(smap) + elif "guide" not in sc.columns: + sys.exit("ERROR: --scores has no guide column; pass --samplesheet or --training") + sc["chrom"] = sc["chrom"].astype(str) + sc["start"] = pd.to_numeric(sc["start"], errors="coerce").astype("Int64") + sc["score"] = pd.to_numeric(sc["score"], errors="coerce") + sc["_called"] = sc["verdict"].astype(str).str.contains("LIKELY EDIT", na=False) + + scored_guides = set(sc["guide"].dropna()) + unmatched = sorted(set(gold["guide"]) - scored_guides) + if unmatched: + print(f"NOTE: {len(unmatched)} gold guide(s) absent from the scored cohort " + f"(not run / no CRAM), excluded from the denominator: {unmatched}") + gold = gold[gold["guide"].isin(scored_guides)] + # An empty denominator means the join key is broken, NOT that the pipeline passed. + # Fail loudly — a silent 0/0 here would read as success. + if gold.empty: + sys.exit("ERROR: no gold guide matched the scored cohort — the sample->guide join " + "is broken. Pass --samplesheet (or --training) so guides resolve, and " + "check --guide-alias for review-sheet name typos.") + + if "call_basis" not in sc.columns: # pre-rescue scored table + sc["call_basis"] = "" + m = gold.merge(sc, on=["guide", "chrom", "start"], how="left", suffixes=("_gold", "")) + site = (m.groupby(["guide", "chrom", "start"], dropna=False) + .agg(called=("_called", "max"), best=("score", "max"), + evaluated=("score", "count"), + verdict=("verdict", lambda s: "|".join(sorted(set(s.dropna().astype(str))))), + basis=("call_basis", lambda s: "|".join(sorted(set(s.dropna().astype(str)) - {""}))), + ecs_if=("ecs_if", "first"), is_target=("is_target_gold", "first"), + indel_frac=("indel_frac", "max"), ctrl_if=("ctrl_if", "max"), + conc_ratio=("conc_ratio", "max"), spanning=("spanning", "max")) + .reset_index()) + site["called"] = site["called"].fillna(False).astype(bool) + + n = len(site) + n_called = int(site["called"].sum()) + n_scoreonly = int((site["best"] >= args.hi).sum()) + n_rescued = int(site["basis"].astype(str).str.contains("high-evidence").sum()) + n_noteval = int((site["evaluated"] == 0).sum()) + + print(f"\n== WGS recall vs manual review ({args.gold.split('/')[-1]}) ==") + print(f" human-confirmed edits in scored guides : {n}") + print(f" evaluated by the WGS arm : {n - n_noteval}/{n}") + print(f" RECALL (verdict = LIKELY EDIT) : {n_called}/{n} = {n_called / n:.3f}") + print(f" recall on model score >= {args.hi} alone : {n_scoreonly}/{n} = " + f"{n_scoreonly / n:.3f}") + print(f" recovered by the high-evidence rescue : {n_rescued}") + on = site[site["is_target"] == 1] + off = site[site["is_target"] != 1] + if len(on): + print(f" on-target : {int(on['called'].sum())}/{len(on)}") + if len(off): + print(f" off-target : {int(off['called'].sum())}/{len(off)}") + # Say the limitation out loud, every run. Anyone reading a bare recall number is one + # short step from asking "and the precision?" — the answer has to travel with it. + print(" (recall only: this table has no confirmed negatives — NaN means UNREVIEWED,") + print(" not rejected, so precision/F-beta are undefined here. For PR-AUC, precision") + print(" and F2/F5 against the ECS label, see offtarget_metrics.{json,txt}.)") + + miss = site[~site["called"]] + if len(miss): + print(f"\n-- {len(miss)} MISSED confirmed edit(s) --") + with pd.option_context("display.width", 220, "display.max_rows", None): + print(miss.drop(columns=["called"]).to_string(index=False)) + else: + print("\n-- no missed confirmed edits --") + + if args.out: + site.to_csv(args.out, index=False) + print(f"\nwrote {args.out} ({n} sites)") + + if args.require_recall is not None and (n_called / n) < args.require_recall: + sys.exit(f"FAIL: recall {n_called / n:.3f} < required {args.require_recall}") + + +if __name__ == "__main__": + main() diff --git a/bin/validate_recall_aavs1.py b/bin/validate_recall_aavs1.py new file mode 100755 index 0000000..bdffd47 --- /dev/null +++ b/bin/validate_recall_aavs1.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 +""" +validate_recall_aavs1.py — WGS performance against the CURATED AAVS1 truth set. + +Why this is separate from validate_recall.py +-------------------------------------------- +`validate_recall.py` scores the CART cohort: its `--gold` is a merged review workbook keyed by +`sample_name`/`manual_review`, joined on the guide, and it is deliberately RECALL-ONLY because +that table has no confirmed negatives (NaN there means "not reviewed", not "rejected"). + +AAVS1's curation is a different artifact entirely — two read-level tables, one of confirmed +edit-supporting reads and one of confirmed non-edit reads: + + crispr_ml/AAVS1_training_tp.tsv 77,317 reads + crispr_ml/AAVS1_training_tn.tsv 72,284 reads + +Because it has a real negative class, precision and specificity ARE defined here, unlike CART. +Different schema, different join, different metrics — hence a separate script rather than more +flags on the CART one. + +What the truth set actually contains +------------------------------------ +Collapsed to sites: 2 TP sites and 6,037 TN sites. Both TP sites (chr19:55115732 and +chr19:55115752) are **ON-TARGET** — AAVS1 site5 and site14. There are no human-confirmed +off-target edits in this cohort, so "100% recall" here means both on-target edits were recovered +from WGS alone. Say that out loud rather than letting it be discovered. + +Three traps, each of which silently produces a WRONG answer +----------------------------------------------------------- +1. The TSVs are RAGGED: the header names 4 columns but each row carries a full SAM record across + many unnamed ones. `usecols=['Label','VCF_Chrom','VCF_Pos']` returns an EMPTY frame — which + reads downstream as "0 TP sites", i.e. a passing-looking 0/0, not an error. Use positional + `usecols=[0,1,2]`. +2. These are READ-level labels. An edited site contains both edit-supporting reads AND ordinary + reference reads, so **both TP sites also appear in the TN table**. Subtract the TP sites from + the TN set or they score as 2 phantom false positives. +3. `VCF_Pos` is 1-based; the pipeline's `start` is a 0-based BED-style coordinate. Join with a + small slack (default +/-2) or every site misses. + +Usage +----- + validate_recall_aavs1.py \ + --training results_offtarget_aavs1_igv/offtarget/training.tsv \ + --tp /storage2/.../crispr_ml/AAVS1_training_tp.tsv \ + --tn /storage2/.../crispr_ml/AAVS1_training_tn.tsv \ + --out aavs1_audit.csv --require-recall 1.0 +""" +import argparse +import sys + +import pandas as pd + +DEFAULT_TP = ("/storage2/fs1/dspencer/Active/clinseq/projects/scge/" + "crispr_ml/AAVS1_training_tp.tsv") +DEFAULT_TN = ("/storage2/fs1/dspencer/Active/clinseq/projects/scge/" + "crispr_ml/AAVS1_training_tn.tsv") +DETECT_PATTERN = "LIKELY EDIT" +SLACK = 2 + + +def read_curated(path, what): + """Read a read-level curation TSV -> distinct (chrom, pos) sites. + + Positional usecols is deliberate: see trap 1 in the module docstring. + """ + d = pd.read_csv(path, sep="\t", usecols=[0, 1, 2], header=0, + names=["label", "chrom", "pos"], low_memory=False) + n_raw = len(d) + # the ragged tail can smear stray values into these columns; keep only real loci + d = d[d["chrom"].astype(str).str.match(r"^chr")] + d["pos"] = pd.to_numeric(d["pos"], errors="coerce") + d = d.dropna(subset=["pos"]) + d["pos"] = d["pos"].astype(int) + sites = d.drop_duplicates(["chrom", "pos"])[["chrom", "pos"]].reset_index(drop=True) + if sites.empty: + sys.exit(f"ERROR: {what} ({path}) yielded 0 sites from {n_raw} rows. The file is ragged; " + "this is what named usecols does. Read columns positionally.") + print(f" {what:<3} {n_raw:>7,d} reads -> {len(sites):>5,d} distinct sites") + return sites + + +def load_truth(tp_path, tn_path): + """Curated site sets, with the TP sites removed from the TN set (trap 2).""" + print("curated AAVS1 truth:") + tp = read_curated(tp_path, "TP") + tn = read_curated(tn_path, "TN") + tp_set = {(c, p) for c, p in zip(tp["chrom"], tp["pos"])} + before = len(tn) + tn = tn[[(c, p) not in tp_set for c, p in zip(tn["chrom"], tn["pos"])]] + dropped = before - len(tn) + if dropped: + print(f" removed {dropped} edit-site(s) from the TN set (a real edit also carries " + f"reference reads, so it appears in both tables)") + return tp_set, {(c, p) for c, p in zip(tn["chrom"], tn["pos"])} + + +def _near(chrom, pos, site_set, slack=SLACK): + """1-based VCF vs 0-based pipeline start (trap 3).""" + return any((chrom, pos + off) in site_set for off in range(-slack, slack + 1)) + + +def label_frame(df, tp_set, tn_set, slack=SLACK): + """Annotate a scored table with is_TP / is_TN / detected. Reused by compare_to_baseline.""" + out = df.copy() + out["detected"] = out["verdict"].astype(str).str.contains(DETECT_PATTERN, na=False) + out["is_TP"] = [_near(c, p, tp_set, slack) for c, p in zip(out["chrom"], out["start"])] + out["is_TN"] = [_near(c, p, tn_set, slack) for c, p in zip(out["chrom"], out["start"])] + return out + + +def confusion(df): + tp = int(df.loc[df["is_TP"], "detected"].sum()) + fn = int((~df.loc[df["is_TP"], "detected"]).sum()) + fp = int(df.loc[df["is_TN"], "detected"].sum()) + tn = int((~df.loc[df["is_TN"], "detected"]).sum()) + return tp, fn, fp, tn + + +def report(tp, fn, fp, tn): + recall = tp / (tp + fn) if (tp + fn) else float("nan") + spec = tn / (tn + fp) if (tn + fp) else float("nan") + prec = tp / (tp + fp) if (tp + fp) else float("nan") + print() + print("=" * 70) + print("WGS-ONLY PERFORMANCE vs CURATED AAVS1 TRUTH") + print("=" * 70) + print(f" TP {tp} FN {fn} FP {fp} TN {tn}") + print(f" recall = {tp}/{tp + fn} = {recall:.3f}") + print(f" specificity = {tn}/{tn + fp} = {spec:.4f}") + print(f" precision = {tp}/{tp + fp} = {prec:.3f}") + print() + print(" NOTE: both curated TP sites are ON-TARGET (AAVS1 site5 / site14). This cohort has") + print(" no human-confirmed off-target edits, so recall here is recovery of the") + print(" on-target edits from WGS alone.") + print(" NOTE: precision is against CURATED negatives. It is NOT comparable to the") + print(" precision in offtarget_metrics.txt, which uses the ECS label.") + return recall + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--training", required=True, help="training.tsv from the OFFTARGET run") + ap.add_argument("--tp", default=DEFAULT_TP, help="AAVS1_training_tp.tsv") + ap.add_argument("--tn", default=DEFAULT_TN, help="AAVS1_training_tn.tsv") + ap.add_argument("--slack", type=int, default=SLACK, + help="bp slack for the 1-based/0-based join (default 2)") + ap.add_argument("--max-cut-dist", type=float, default=None, + help="also report the confusion matrix with a |modal_pos - start| gate " + "applied, i.e. require the observed indel to sit near the predicted cut") + ap.add_argument("--out", help="write the per-site audit table here") + ap.add_argument("--require-recall", type=float, + help="exit non-zero if recall falls below this (for CI)") + args = ap.parse_args() + + tp_set, tn_set = load_truth(args.tp, args.tn) + df = pd.read_csv(args.training, sep="\t", low_memory=False) + lab = label_frame(df, tp_set, tn_set, args.slack) + + matched_tp = int(lab["is_TP"].sum()) + if matched_tp == 0: + sys.exit("ERROR: no curated TP site matched the scored table. The join is broken — check " + "the chrom naming and --slack. An empty denominator is not a pass.") + print(f" matched in scored table: {matched_tp} TP row(s), {int(lab['is_TN'].sum())} TN row(s)") + + tp, fn, fp, tn = confusion(lab) + recall = report(tp, fn, fp, tn) + + print() + print("--- the curated TP sites ---") + cols = [c for c in ("sample", "chrom", "start", "modal_pos", "indel_frac", "spanning", + "ctrl_if", "score", "verdict", "ecs_if") if c in lab.columns] + print(lab.loc[lab["is_TP"], cols].to_string(index=False)) + + if args.max_cut_dist is not None and {"modal_pos", "start"} <= set(lab.columns): + g = lab.copy() + g["cut_dist"] = (g["modal_pos"] - g["start"]).abs() + # a site fails the gate if it was called but the indel sits far from the predicted cut + g["detected"] = g["detected"] & (g["cut_dist"] <= args.max_cut_dist) + print() + print(f"### with cut-site gate |modal_pos - start| <= {args.max_cut_dist:g} ###") + report(*confusion(g)) + + if args.out: + keep = lab[lab["is_TP"] | lab["is_TN"]].copy() + if {"modal_pos", "start"} <= set(keep.columns): + keep["cut_dist"] = (keep["modal_pos"] - keep["start"]).abs() + keep["curated"] = ["TP" if t else "TN" for t in keep["is_TP"]] + keep.to_csv(args.out, index=False) + print(f"\nwrote per-site audit -> {args.out} ({len(keep)} rows)") + + if args.require_recall is not None and recall < args.require_recall: + sys.exit(f"FAIL: recall {recall:.3f} < required {args.require_recall:.3f}") + + +if __name__ == "__main__": + main() diff --git a/bin/validate_sv.py b/bin/validate_sv.py new file mode 100755 index 0000000..dff6007 --- /dev/null +++ b/bin/validate_sv.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python3 +import sys +import argparse +import pysam +import re +import edlib + +def reverse_complement(seq): + """Returns the reverse complement of a DNA sequence.""" + if not seq: return "" + complement = str.maketrans('ACGTNacgtn', 'TGCANtgcan') + return seq.translate(complement)[::-1] + +def get_bnd_parts(alt_str): + """ + Parses VCF BND strings (e.g., ]chr1:123]T) into components. + Returns: (pre_bases, bracket_char, remote_chrom, remote_pos, post_bases) + """ + # Regex captures: 1=Pre, 2=Bracket, 3=RemoteLoc, 4=Bracket, 5=Post + pattern = re.compile(r"([ACGTNacgtn]*)(\[|\])([^:]+:\d+)(\[|\])([ACGTNacgtn]*)") + match = pattern.fullmatch(alt_str) + if not match: + return None + return match.groups() + +def generate_contig(record, ref_file, flank_length): + """ + Constructs the theoretical alternate sequence (Contig) using the Reference genome. + Logic: + 1. Identify SV type (Linear vs BND). + 2. Fetch Local Flank (Left or Right depending on break orientation). + 3. Fetch Remote Flank (and RC if necessary based on bracket direction). + 4. Stitch them together. + """ + chrom = record.chrom + pos = record.pos # 1-based + ref_base = record.ref + alt_base = record.alts[0] + svtype = record.info.get('SVTYPE', 'Unknown') + strand = record.info.get('STRAND', '') + + # Pysam 0-based conversion + start_idx = pos - 1 + end_idx = start_idx + len(ref_base) + + try: + # --- Handle Breakends (BND) --- + if svtype == 'BND' or '[' in alt_base or ']' in alt_base: + parts = get_bnd_parts(alt_base) + if not parts: + return "Error: Unparseable BND string" + + pre_bases, bracket, remote_loc, _, post_bases = parts + r_chrom, r_pos = remote_loc.split(':') + r_pos = int(r_pos) + + # 1. Get Local Sequence + if pre_bases: + # Local is upstream (Left) -> Break + local_seq = ref_file.fetch(chrom, max(0, start_idx - flank_length), end_idx - 1) + + if bracket == '[': + r_start_0 = r_pos - 1 + remote_seq = ref_file.fetch(r_chrom, r_start_0, r_start_0 + flank_length) + else: # bracket == ']' + # Remote points Reverse (Left/Upstream of r_pos) -> RC needed + r_end_0 = r_pos + raw_remote = ref_file.fetch(r_chrom, max(0, r_end_0 - flank_length), r_end_0) + remote_seq = reverse_complement(raw_remote) + + return local_seq + pre_bases + remote_seq if strand=="+" else reverse_complement(local_seq + pre_bases + remote_seq) + + else: # joined before t (ref is downstream) + if bracket == '[': + local_seq = ref_file.fetch(chrom, start_idx, end_idx + flank_length) + # Remote points Forward (Right/Downstream of r_pos) + r_start_0 = r_pos - 1 + raw_remote = ref_file.fetch(r_chrom, r_start_0 + 1, r_start_0 + flank_length) + remote_seq = reverse_complement(raw_remote) + + else: # bracket == ']' + local_seq = ref_file.fetch(chrom, start_idx + 1, end_idx + flank_length) + # Remote points Reverse (Left/Upstream of r_pos) -> RC needed + r_end_0 = r_pos + remote_seq = ref_file.fetch(r_chrom, max(0, r_end_0 - flank_length), r_end_0) + + return remote_seq + post_bases + local_seq if strand=="+" else reverse_complement(remote_seq + post_bases + local_seq) + + # --- Handle Linear SVs (DEL, INS, etc) --- + else: + if len(alt_base) > len(ref_base) or record.info.get('SVLEN', 0) > 0: # DUP + left_flank = ref_file.fetch(chrom, max(0, start_idx - flank_length), start_idx) + right_flank = ref_file.fetch(chrom, end_idx, end_idx + flank_length) + # For linear SVs, we sandwich the ALT string between the flanks + + elif len(alt_base) < len(ref_base) or record.info.get('SVLEN', 0) < 0: #DEL + left_flank = ref_file.fetch(chrom, max(0, start_idx - flank_length), start_idx) + right_flank = ref_file.fetch(chrom, end_idx, end_idx + flank_length) + # For linear SVs, we sandwich the ALT string between the flanks + + seq = f"{left_flank}{alt_base}{right_flank}" if strand=="+" else reverse_complement(f"{left_flank}{alt_base}{right_flank}") + + return seq + + except KeyError as e: + return f"Error: Chromosome/Region not found in reference ({e})" + except Exception as e: + return f"Error: {str(e)}" + +def print_alignment(query_seq, target_seq): + """ + Aligns Query (Generated) to Target (VCF SEQ) using Edlib and prints visualization. + Mode: NW (Global) - forces end-to-end alignment to show flank discrepancies. + """ + # Use Needleman-Wunsch (global) to force end-to-end comparison + # This highlights if the flanks in the VCF SEQ differ from the Reference flanks + result = edlib.align(query_seq, target_seq, mode="NW", task="path") + + if result['editDistance'] == 0: + return True, 0 + + # Get visual alignment + nice = edlib.getNiceAlignment(result, query_seq, target_seq) + + print("\n Alignment (Top: Generated, Bottom: VCF SEQ):") + print(f" Q: {nice['query_aligned']}") + print(f" {nice['matched_aligned']}") + print(f" T: {nice['target_aligned']}") + + return False, result['editDistance'] + +def main(): + parser = argparse.ArgumentParser(description="Reconstruct SV contigs and align to VCF SEQ using Edlib.") + parser.add_argument("vcf") + parser.add_argument("-r", "--reference", required=True, help="Path to indexed reference FASTA (.fa)") + parser.add_argument("-f", "--flank", type=int, default=200, help="Flank length for reconstruction (default: 50)") + args = parser.parse_args() + + # Open Reference + try: + ref_file = pysam.FastaFile(args.reference) + except ValueError: + sys.stderr.write(f"CRITICAL ERROR: Could not open/index reference file: {args.reference}\n") + sys.exit(1) + + # Open VCF from Stdin + try: + vcf_in = pysam.VariantFile(args.vcf) + except Exception as e: + sys.stderr.write(f"CRITICAL ERROR: Could not read VCF from stdin. {e}\n") + sys.exit(1) + + # Header + print(f"{'CHROM':<10} {'POS':<10} {'SVTYPE':<10} {'EDITS':<6} {'STATUS':<10}") + print("-" * 80) + + for record in vcf_in: + vcf_seq = record.info.get('SEQ', None) + if record.info.get("STRAND","+") == "-": + vcf_seq = reverse_complement(vcf_seq) + + svtype = record.info.get('SVTYPE', 'UNK') + + # Generate the theoretical sequence from Reference + generated_seq = generate_contig(record, ref_file, args.flank) + + # Handle Errors in generation + if "Error" in generated_seq: + print(f"{record.chrom:<10} {str(record.pos):<10} {svtype:<10} {'-':<6} {'ERROR':<10}") + print(f" > {generated_seq}\n") + continue + + if not vcf_seq: + print(f"{record.chrom:<10} {str(record.pos):<10} {svtype:<10} {'-':<6} {'NO_SEQ':<10}") + continue + + # Perform Alignment + # We print the row first to keep logs organized, then print alignment details if mismatched + + # Run alignment silently first to get score + result = edlib.align(vcf_seq, generated_seq, mode="HW", task="path") + edit_dist = result['editDistance'] + status = "MATCH" if edit_dist == 0 else "MISMATCH" + + if status == "MISMATCH": + print(f"{str(record.id)}\t{record.chrom:<10} {str(record.pos):<10} {record.alts[0]} {svtype:<10} {str(edit_dist):<6} {status:<10}") + + # Call helper to print the nice visualization + align = edlib.getNiceAlignment(result, vcf_seq, generated_seq, gapSymbol='-') + print(align['query_aligned']) + print(align['matched_aligned']) + print(align['target_aligned']) + print(f"SEQ: {vcf_seq}") + print(f"contig: {generated_seq}") + print("") # spacer + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/bin/wgs_tag_reads.py b/bin/wgs_tag_reads.py new file mode 100755 index 0000000..8800247 --- /dev/null +++ b/bin/wgs_tag_reads.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +""" +wgs_tag_reads.py — per-read XC tags for the WGS arm, for live IGV review. + +The ECS arm has had this since the read-level-tags work: every read in the target windows +carries an `XC` tag naming how the caller classified it, so a reviewer can colour the pileup +(Color alignments by -> tag -> XC) and see *why* a site was called instead of taking the +caller's word for it. The WGS arm had only rendered PNGs, which cannot be interrogated. + +This closes that gap, and deliberately reuses the ECS machinery — `merge_windows`, +`write_tagged_bam`, `record_read_tag`, `read_tag_key` are imported from find_edited_reads.py +rather than reimplemented — so **one IGV colour scheme works for both arms**. Only the per-read +classification is WGS-specific, because the WGS caller works from pileup shape at a candidate +locus rather than from per-read VCF records. + +Why not reuse features.py:read_records() +--------------------------------------- +It returns `{'spans','indel','mapq','softclip'}` with the read identity discarded, and it +`continue`s past duplicate/secondary/supplementary reads — so the `Skipped_*` classes, which are +the most useful thing a reviewer can see, never reach it. It is also the version-pinned model +input path. A separate read walk is both easier and safer than perturbing that. + +Tag vocabulary (identical to the ECS arm) +----------------------------------------- + Edited_Deletion_bp / Edited_Insertion_bp read carries an indel at the cut + Edited_SoftClip soft-clip edge at the cut (realignment) + Unedited_WT spans the cut, no indel: the reference class + Skipped_Duplicate / Skipped_LowMapQ / + Skipped_Mismatches / Skipped_NoSpan excluded, and visibly so +""" +import os +import sys + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from find_edited_reads import (read_tag_key, record_read_tag, # noqa: E402 + merge_windows, write_tagged_bam, + count_mismatches_fast) + +# Match the WGS caller's own read filters (features.py read_records / score.py defaults) so the +# tags explain the SAME denominator the features were computed from. If these drift from the +# caller, the BAM stops being an explanation of the call. +MIN_MAPQ = 20 +MAX_NM = 4 +WINDOW = 150 # bp each side of the cut to emit; matches the ECS target window +CUT_SLACK = 25 # an indel this close to the cut counts as "at" the cut + + +def classify_wgs_read(read, cut_pos, cut_slack=CUT_SLACK, + min_mapq=MIN_MAPQ, max_nm=MAX_NM): + """One read -> one XC tag string, in the caller's own precedence order.""" + if read.is_duplicate: + return "Skipped_Duplicate" + if read.is_unmapped or read.is_secondary or read.is_supplementary: + return "Skipped_Unevaluable" + if (read.mapping_quality or 0) < min_mapq: + return "Skipped_LowMapQ" + # NM counts indel bases as well as substitutions, so a genuine 5 bp deletion carries NM>=5 + # and a raw `NM > max_nm` test rejects precisely the reads we are looking for. The ECS + # caller solves this with count_mismatches_fast(), which subtracts the CIGAR indel lengths + # to leave true single-base mismatches; reuse it rather than re-deriving it. + if count_mismatches_fast(read) > max_nm: + return "Skipped_Mismatches" + end = read.reference_end or read.reference_start + if not (read.reference_start <= cut_pos <= end): + return "Skipped_NoSpan" + + # walk the CIGAR for the largest indel near the cut, plus soft-clip edges + refpos = read.reference_start + best = None # (op, length) + softclip_at_cut = False + for op, ln in (read.cigartuples or []): + if op in (0, 7, 8): # M/=/X consume ref and query + refpos += ln + elif op == 2: # D consumes ref only + if abs(refpos - cut_pos) <= cut_slack and (best is None or ln > best[1]): + best = (2, ln) + refpos += ln + elif op == 1: # I consumes query only + if abs(refpos - cut_pos) <= cut_slack and (best is None or ln > best[1]): + best = (1, ln) + elif op == 4: # S soft-clip; record the ref edge + if abs(refpos - cut_pos) <= cut_slack: + softclip_at_cut = True + if best is not None: + return ("Edited_Deletion_%dbp" if best[0] == 2 else "Edited_Insertion_%dbp") % best[1] + if softclip_at_cut: + return "Edited_SoftClip" + return "Unedited_WT" + + +def tag_wgs_bam(bam, sites, out_path, tag_name="XC", window=WINDOW, + cut_slack=CUT_SLACK, verbose=True): + """Tag every read in the windows around `sites` and write one indexed BAM. + + `bam` an open pysam.AlignmentFile (reused from the caller's cache — reopening a CRAM + per site is the slow way to do this). + `sites` iterable of (chrom, cut_pos) 0/1-based-agnostic reference positions. + Returns the number of records written. + """ + read_tags, windows = {}, [] + for chrom, cut in sites: + chrom, cut = str(chrom), int(cut) + lo, hi = max(0, cut - window), cut + window + windows.append((chrom, lo, hi)) + try: + fetched = bam.fetch(chrom, lo, hi) + except (ValueError, KeyError): + # contig absent from this CRAM (alt contigs are a real case here) + continue + for read in fetched: + # record_read_tag keeps the highest-precedence tag when windows overlap, so a read + # visited by two nearby candidate sites is still written exactly once. + record_read_tag(read_tags, read, classify_wgs_read(read, cut, cut_slack)) + if not read_tags: + if verbose: + print(" no reads in any candidate window; not writing a WGS tagged BAM", + file=sys.stderr) + return 0 + return write_tagged_bam(bam, out_path, windows, read_tags, tag_name, verbose=verbose) diff --git a/bin/worklist_from_vcf.py b/bin/worklist_from_vcf.py new file mode 100755 index 0000000..80d94ae --- /dev/null +++ b/bin/worklist_from_vcf.py @@ -0,0 +1,267 @@ +#!/usr/bin/env python3 +""" +worklist_from_vcf.py — GENOME-WIDE, HOMOLOGY-FREE off-target worklist. + +Candidate source = DRAGEN somatic tumor/normal small-variant VCFs +(`.hard-filtered.vcf.gz`, tumor=edited, normal=-unedited). These are +genome-wide indels already normal-subtracted + systematic-noise-filtered by DRAGEN — +so candidates come from edited-vs-control evidence, NOT a guide-homology list. Guide +homology (min_mm / is_target) is attached only as an ANNOTATION by cross-referencing +the Cas-OFFinder table, so homology-blind real off-targets can't be excluded. + +Per PASS somatic indel: walk the tumor CRAM -> count-free pileup shape -> shape +ranker; recompute in matched normal at the observed indel pos (cross-check on top of +DRAGEN's somatic call); cross-sample recurrence; verdict. Optionally auto-render an +edited-vs-normal pileup PNG per LIKELY EDIT. + +Reuses score.py (control_check, normal_cram_path, add_recurrence, verdict, HI/MID) +and features.py. Known PLCB2 off-target (chr12:32679408) = built-in positive control. +""" +import os, sys, argparse +import numpy as np +import pandas as pd +import pysam +import joblib + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from features import (read_records, features_from_records, MODEL_FEATURES, + parse_target_info, check_sklearn_version, repeat_context) +import score as S + +REF = S.REF +MODEL = S.MODEL +STD_CHROMS = {f"chr{c}" for c in list(range(1, 23)) + ["X", "Y"]} + + +def vcf_for_tumor(tumor_cram): + """/_tumor.cram -> /.hard-filtered.vcf.gz""" + if tumor_cram.endswith("_tumor.cram"): + base = tumor_cram[:-len("_tumor.cram")] + v = base + ".hard-filtered.vcf.gz" + return v if os.path.exists(v) else None + return None + + +def tumor_sample_id(vcf): + """DRAGEN somatic: the non-'*-unedited' sample column is the tumor/edited one.""" + v = pysam.VariantFile(vcf) + ids = list(v.header.samples) + v.close() + tum = [s for s in ids if not s.endswith("-unedited")] + return tum[-1] if tum else (ids[-1] if ids else None) + + +def is_indel(rec): + return any(len(a) != len(rec.ref) for a in (rec.alts or [])) + + +def build_homology_index(table_path, sheet=None, pad=25): + """chrom -> sorted list of (pos, min_mm, is_target) from the Cas-OFFinder table, + for annotating VCF indels with the nearest predicted-homology site (within pad).""" + df = S.load_table(table_path, sheet=sheet) + idx = {} + for _, r in df.iterrows(): + idx.setdefault(str(r["chrom"]), []).append( + (int(r["start"]), int(r["_min_mm"]), int(bool(r["_tgt"])))) + for c in idx: + idx[c].sort() + return idx, pad + + +def annotate_homology(idx_pad, chrom, pos): + """Nearest table site within pad -> (min_mm, is_target, dist) or (99, 0, None).""" + if idx_pad is None: + return 99, 0, None + idx, pad = idx_pad + lst = idx.get(str(chrom)) + if not lst: + return 99, 0, None + import bisect + starts = [x[0] for x in lst] + i = bisect.bisect_left(starts, pos) + best = None + for j in (i - 1, i, i + 1): + if 0 <= j < len(lst): + d = abs(lst[j][0] - pos) + if d <= pad and (best is None or d < best[2]): + best = (lst[j][1], lst[j][2], d) + return best if best else (99, 0, None) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--cram-list", default=f"{os.path.dirname(os.path.abspath(__file__))}/wgs_cram_map.tsv") + ap.add_argument("--ref", default=REF) + ap.add_argument("--model", default=MODEL) + ap.add_argument("--homology-table", + default="/storage2/fs1/dspencer/Active/clinseq/projects/scge/" + "Manual Indel Review/cart_wgs/cart_wgs_merged.xlsx", + help="Cas-OFFinder table for min_mm/is_target ANNOTATION only") + ap.add_argument("--sample", help="limit to one sample_name (testing)") + ap.add_argument("--min-af", type=float, default=0.05, help="DRAGEN tumor AF floor") + ap.add_argument("--min-span", type=int, default=8) + ap.add_argument("--include-weak", action="store_true", + help="also include weak_evidence-filtered indels (depth-floor tail)") + ap.add_argument("--no-normal-check", action="store_true") + # High-evidence rescue — same contract as score.py, so the genome-wide discovery arm + # and the hotspot arm agree on what counts as a call. See score.py for the rationale. + ap.add_argument("--no-rescue", action="store_true", + help="disable the high-evidence rescue; call on the model score alone") + ap.add_argument("--rescue-min-ifrac", type=float, default=S.RESCUE_MIN_IFRAC) + ap.add_argument("--rescue-min-conc", type=float, default=S.RESCUE_MIN_CONC) + ap.add_argument("--rescue-min-span", type=int, default=S.RESCUE_MIN_SPAN) + ap.add_argument("--snapshot-dir") + ap.add_argument("--top", type=int, default=50) + ap.add_argument("--out", default="wgs_offtarget_worklist_genomewide.csv") + args = ap.parse_args() + rescue = None if args.no_rescue else {"min_ifrac": args.rescue_min_ifrac, + "min_conc": args.rescue_min_conc, + "min_span": args.rescue_min_span} + + bundle = joblib.load(args.model) + model, feat_names = bundle["model"], bundle["features"] + # one handle reused for every candidate; repeat_context reads a ~50bp window per call + ref_fa = pysam.FastaFile(args.ref) + check_sklearn_version(model, name=os.path.basename(args.model)) + crams = S.cram_index(args.cram_list) + if args.sample: + crams = {args.sample: crams[args.sample]} + homidx = build_homology_index(args.homology_table) if args.homology_table else None + + rows, n_pass_indel = [], 0 + for s, tpath in crams.items(): + vcf = vcf_for_tumor(tpath) + if not vcf: + print(f" {s}: no VCF", flush=True); continue + tid = tumor_sample_id(vcf) + npath = S.normal_cram_path(tpath) + tbam = pysam.AlignmentFile(tpath, "rc", reference_filename=args.ref) + ncache = {} + v = pysam.VariantFile(vcf) + sc = 0 + for rec in v.fetch(): + if not is_indel(rec): + continue + filt = list(rec.filter.keys()) + ispass = (not filt) or ("PASS" in filt) + if not ispass and not (args.include_weak and "weak_evidence" in filt): + continue + af = rec.samples[tid].get("AF") + af = (af[0] if isinstance(af, tuple) else af) or 0.0 + if af < args.min_af: + continue + chrom, pos = str(rec.chrom), int(rec.pos) + # off-targets are genomic; skip vector/transgene + non-standard contigs + # (the DRAGEN ref carries the CAR vector, which our hg38 REF can't decode) + if chrom not in STD_CHROMS: + continue + n_pass_indel += 1 + mm, tgt, dist = annotate_homology(homidx, chrom, pos) + try: + rr = read_records(tbam, chrom, pos - 1, pos + 1) + # Deliberately NO cut_pos here. In this arm the candidate IS the observed + # indel, so |modal_pos - pos| is ~0 by construction and carries no + # information. The meaningful "distance to a predicted cut" is the distance + # to the nearest predicted homology site, which annotate_homology already + # returns as `dist`; it is assigned to cut_dist below. + feats = None if rr is None else features_from_records( + rr[0], min_span=args.min_span, return_lowcov=True) + except OSError: # CRAM/ref decode failure at this locus + continue + rec_d = {"sample": s, "chrom": chrom, "start": pos, "ref": rec.ref, + "alt": ",".join(rec.alts or []), "dragen_af": round(float(af), 3), + "min_mm": mm, "is_target": tgt, "hom_dist": dist, "truth": False} + if feats is None or feats.get("lowcov"): + vd, _, basis = S.verdict(0.0, feats, rescue=rescue) + rec_d.update(score=np.nan, verdict=vd, call_basis=basis, + spanning=(feats or {}).get("spanning", 0), + conc_ratio=np.nan, indel_frac=np.nan, modal_len=np.nan, + modal_pos=np.nan, ctrl_if=np.nan, cut_dist=np.nan, + homopolymer_len=np.nan, repeat_frac=np.nan) + else: + opos = feats.get("modal_pos") or pos + # reference context is a model input, so it must be in feats before scoring + feats.update(repeat_context(ref_fa, chrom, opos)) + # in this arm the meaningful "distance to a predicted cut" is the homology + # distance, so inject it under the shared feature name before scoring + feats["cut_dist"] = (float("nan") if dist is None else float(dist)) + psc = float(model.predict_proba(pd.DataFrame([{k: feats[k] for k in feat_names}]))[0, 1]) + ctrl_if = None + if not args.no_normal_check: + ctrl_if, _ = S.control_check(npath, chrom, opos, args.ref, bam_cache=ncache) + vd, psc, basis = S.verdict(psc, feats, ctrl_if, rescue=rescue) + rec_d.update(score=psc, verdict=vd, call_basis=basis, spanning=feats["spanning"], + conc_ratio=round(feats["conc_ratio"], 3), + indel_frac=round(feats["indel_frac"], 3), + modal_len=feats.get("modal_len"), modal_pos=opos, + ctrl_if=(round(ctrl_if, 3) if ctrl_if is not None else np.nan), + # same feature name as the hotspot arm, same meaning: bp from the + # observed indel to the nearest PREDICTED site. NaN when no + # predicted site is within the annotation pad -- honest, since the + # true distance is then unbounded rather than large-but-known. + cut_dist=feats.get("cut_dist"), + homopolymer_len=feats.get("homopolymer_len"), + repeat_frac=feats.get("repeat_frac")) + # built-in positive control + if chrom == "chr12" and abs(pos - 32679408) <= 3 and "PLCB2" in s: + rec_d["truth"] = True + rows.append(rec_d); sc += 1 + v.close(); tbam.close() + for b in ncache.values(): + b.close() + print(f" {s}: {sc} PASS somatic indels scored (AF>={args.min_af})", flush=True) + + res = S.add_recurrence(pd.DataFrame(rows)) + torder = {"A-review-first": 0, "B-review": 1, "C-recurrent-artifact": 2, "D-artifact": 3} + res["_o"] = res["priority"].map(torder).fillna(3) + res = res.sort_values(["_o", "score"], ascending=[True, False], + na_position="last").drop(columns="_o").reset_index(drop=True) + res.insert(0, "rank", res.index + 1) + res.to_csv(args.out, index=False) + print(f"\ngenome-wide PASS somatic indels featurized: {n_pass_indel}") + print(f"wrote {args.out} ({len(res)} rows)") + + cols = ["rank", "priority", "sample", "chrom", "start", "alt", "dragen_af", + "indel_frac", "ctrl_if", "min_mm", "is_target", "conc_ratio", "score", + "verdict", "n_guides_at_site", "truth"] + cols = [c for c in cols if c in res.columns] + print(f"\nTop {min(args.top, len(res))} (tiered):") + with pd.option_context("display.max_rows", None, "display.width", 200): + print(res[cols].head(args.top).to_string(index=False)) + print("\ntiers: " + res["priority"].value_counts().to_string()) + # homology-blind survivors = the GUIDE-seq-analog finds + le = res[res.verdict == "LIKELY EDIT"] + blind = le[le.min_mm == 99] + print(f"\nLIKELY EDIT: {len(le)} | of those homology-blind (no table site within 25bp): {len(blind)}") + if res["truth"].any(): + for _, k in res[res.truth].iterrows(): + print(f"POSITIVE CONTROL PLCB2: rank {int(k['rank'])}/{len(res)} score={k['score']} verdict='{k['verdict']}'") + + if args.snapshot_dir: + import matplotlib; matplotlib.use("Agg") + import matplotlib.pyplot as plt + from pileup_snapshot import snapshot + os.makedirs(args.snapshot_dir, exist_ok=True) + surv = res[res.verdict == "LIKELY EDIT"] + for _, k in surv.iterrows(): + tp = crams.get(k["sample"]) + if not tp: + continue + pos = int(k["modal_pos"]) if pd.notna(k.get("modal_pos")) else int(k["start"]) + npath = S.normal_cram_path(tp) + fig, ax = plt.subplots(1, 2 if npath else 1, figsize=(15 if npath else 8, 6.5), squeeze=False) + snapshot(ax[0][0], tp, str(k["chrom"]), pos, args.ref, window=45, + title=f"{k['sample']}_tumor AF={k['dragen_af']} score={k['score']:.2f}") + if npath: + snapshot(ax[0][1], npath, str(k["chrom"]), pos, args.ref, window=45, + title=f"NORMAL ctrl_if={k.get('ctrl_if')}") + fig.suptitle(f"{k['sample']} {k['chrom']}:{pos:,} min_mm={k['min_mm']} {k['verdict']}", + fontweight="bold") + fig.tight_layout() + fig.savefig(f"{args.snapshot_dir}/rank{int(k['rank']):03d}_{k['sample']}_{k['chrom']}_{pos}.png", dpi=120) + plt.close(fig) + print(f"\nrendered {len(surv)} snapshots -> {args.snapshot_dir}/") + + +if __name__ == "__main__": + main() diff --git a/cart_wgs_analysis_samplesheet.csv b/cart_wgs_analysis_samplesheet.csv new file mode 100644 index 0000000..8ddc258 --- /dev/null +++ b/cart_wgs_analysis_samplesheet.csv @@ -0,0 +1,33 @@ +id,dragen_path,target_file +ABTB1-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/ABTB1-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/ABTB1_TRAC_TRBC.targets.vcf.gz +ARID4A-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/ARID4A-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/ARID4A_TRAC_TRBC.targets.vcf.gz +ATF7IP-KO-CART-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/ATF7IP-KO-CART-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/ATF7IP_TRAC_TRBC.targets.vcf.gz +BRAF-KO-CART-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/BRAF-KO-CART-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/BRAF_TRAC_TRBC.targets.vcf.gz +CART_NS0027-B2M_1,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CART_NS0027-B2M_1/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/B2M_TRAC_TRBC.targets.vcf.gz +CART_NS0027-B2M_2,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CART_NS0027-B2M_2/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/B2M_TRAC_TRBC.targets.vcf.gz +CART_NS0027-CTLA4_1,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CART_NS0027-CTLA4_1/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/CTLA4_TRAC_TRBC.targets.vcf.gz +CART_NS0027-CTLA4_2,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CART_NS0027-CTLA4_2/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/CTLA4_TRAC_TRBC.targets.vcf.gz +CART_NS0027-PD1_1,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CART_NS0027-PD1_1/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/PD1_TRAC_TRBC.targets.vcf.gz +CART_NS0027-PD1_2,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CART_NS0027-PD1_2/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/PD1_TRAC_TRBC.targets.vcf.gz +CART_NS0027-Regnase1_1,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CART_NS0027-Regnase1_1/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/Regnase1_TRAC_TRBC.targets.vcf.gz +CART_NS0027-Regnase1_2,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CART_NS0027-Regnase1_2/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/Regnase1_TRAC_TRBC.targets.vcf.gz +CART_NS0065-B2M_2,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CART_NS0065-B2M_2/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/B2M_TRAC_TRBC.targets.vcf.gz +CART_NS0065-PD1_2,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CART_NS0065-PD1_2/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/PD1_TRAC_TRBC.targets.vcf.gz +CART_NS0065-Regnase1_1,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CART_NS0065-Regnase1_1/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/Regnase1_TRAC_TRBC.targets.vcf.gz +CHD2-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CHD2-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/CHD2_TRAC_TRBC.targets.vcf.gz +CHD6-KO-CART,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CHD6-KO-CART/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/CHD6_TRAC_TRBC.targets.vcf.gz +CNNM3-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CNNM3-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/CNNM3_TRAC_TRBC.targets.vcf.gz +CREBRF-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/CREBRF-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/CREBRF_TRAC_TRBC.targets.vcf.gz +EZH1-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/EZH1-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/EZH1_TRAC_TRBC.targets.vcf.gz +HBP1-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/HBP1-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/HBP1_TRAC_TRBC.targets.vcf.gz +ID2-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/ID2-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/ID2_TRAC_TRBC.targets.vcf.gz +IKZF2-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/IKZF2-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/IKZF2_TRAC_TRBC.targets.vcf.gz +KDM7A-KO-CART-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/KDM7A-KO-CART-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/KDM7A_TRAC_TRBC.targets.vcf.gz +KLF12-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/KLF12-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/KLF12_TRAC_TRBC.targets.vcf.gz +PDCD4-KO-CART,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/PDCD4-KO-CART/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/PDCD4_TRAC_TRBC.targets.vcf.gz +PDE7A-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/PDE7A-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/PDE7A_TRAC_TRBC.targets.vcf.gz +PHF21A-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/PHF21A-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/PHF21A_TRAC_TRBC.targets.vcf.gz +PLCB2-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/PLCB2-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/PLCB2_TRAC_TRBC.targets.vcf.gz +RFX3-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/RFX3-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/RFX3_TRAC_TRBC.targets.vcf.gz +RXRB-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/RXRB-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/RXRB_TRAC_TRBC.targets.vcf.gz +ZEB2-KO-DNA,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_scge_wgs_results/ZEB2-KO-DNA/dragen/,/storage2/fs1/dspencer/Active/clinseq/projects/scge/cart_seq/cart_target_files/ZEB2_TRAC_TRBC.targets.vcf.gz diff --git a/conf/base.config b/conf/base.config index 7f198ee..eb91db1 100644 --- a/conf/base.config +++ b/conf/base.config @@ -15,8 +15,12 @@ process { memory = { check_max( 6.GB * task.attempt, 'memory' ) } time = { check_max( 4.h * task.attempt, 'time' ) } - errorStrategy = { task.exitStatus in ((130..145) + 104) ? 'retry' : 'finish' } - maxRetries = 1 + // Retry on the usual transient exit codes AND on null exit status, which is what + // Nextflow records when a task is "terminated by external system" (SLURM/cluster or + // shared-filesystem flake). Long ECS_INDELS tasks (~90 min, no checkpoint) were losing + // a whole cohort run to a single such blip; retrying re-runs just the affected task. + errorStrategy = { (task.exitStatus == null || task.exitStatus in ((130..145) + 104)) ? 'retry' : 'finish' } + maxRetries = 2 maxErrors = '-1' // Process-specific resource requirements diff --git a/conf/modules.config b/conf/modules.config index ffbd884..5e5ef32 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -41,4 +41,110 @@ process { ] } + // Unified CRISPR Off-Target Workflow (-entry OFFTARGET) + withName: 'WGS_WORKLIST|PON_OFFTARGET_FILTER|HOTSPOT_TO_TABLE|SCORE_HOTSPOTS|BUILD_TRAINING_TABLE|RECALL_VS_VAF|RECONCILE_OFFTARGET_REPORT|OFFTARGET_METRICS|ECS_INDELS' { + publishDir = [ + path: { "${params.outdir}/offtarget" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + + // ---- Automated review filter: the short list a human actually opens ---- + // review_queue.tsv is the deliverable; review_queue_all.tsv is the same rows unfiltered with + // a why_dropped column so a reviewer can audit what was removed without re-running anything. + withName: 'REVIEW_FILTER' { + publishDir = [ + path: { "${params.outdir}/review" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + + // The breakend queue lands beside the indel queue: same reviewer, same sitting. + withName: 'REVIEW_FILTER_BND' { + publishDir = [ + path: { "${params.outdir}/review" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + + // Per-site review packet: IGV-style pileup PNGs for exactly the sites in review_queue.tsv. + // path is .../review, not .../review/snapshots: the process emits `snapshots/*.png` and + // Nextflow preserves that relative prefix, so the deeper path nests snapshots/snapshots/. + withName: 'REVIEW_SNAPSHOTS' { + publishDir = [ + path: { "${params.outdir}/review" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + + // Breakend review packet: one PNG per JUNCTION (not per queue row). Same nesting caveat as + // above -- the process emits `bnd_snapshots/*.png`, so the path stops at .../review. + withName: 'REVIEW_BND_SNAPSHOTS' { + publishDir = [ + path: { "${params.outdir}/review" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + + // ---- Auto-hotspot finder (-entry HOTSPOTS): publish the per-guide targets.csv/.vcf ---- + withName: 'COMBINE_OFFTARGET_SITES|TARGETS_CSV_TO_VCF' { + publishDir = [ + path: { "${params.outdir}/hotspots" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + + // ---- Right-sized resources for the offtarget arm ---------------------------------- + // The offtarget modules borrow the generic process_* labels, which are sized for the + // heaviest DRAGEN/alignment steps of the default pipeline and vastly over-provision here. + // Values below are set from measured peak usage (sacct MaxRSS on the AAVS1 + CART runs) + // with generous headroom, and scale with task.attempt so a genuine outlier still retries + // into more memory. Resource directives are NOT part of a task's cache hash, so tightening + // them does not invalidate -resume. Measured peaks (RSS): ECS_INDELS 1.4 GB, WGS_WORKLIST + // 0.30 GB, PON 0.30 GB, SCORE_HOTSPOTS 0.68 GB, table/report steps <0.5 GB. The WGS-arm + // Python scripts are single-threaded, so they get 1 CPU (the process_medium label gave 4). + + // ECS truth arm — long-running (~15 min–2.5 h, no checkpoint) but light on RAM/CPU. + // --offtarget_tagged_bam is the exception: it holds a per-read tag map for the whole + // target panel until the second (write) pass, which measured ~4 GB on top of the 1.4 GB + // baseline for the 1149-interval AAVS1 site14 panel at ~11,000x. Give it room rather + // than let an opt-in review artifact OOM the truth arm. + withName: 'ECS_INDELS' { + cpus = { 1 } + memory = { check_max( (params.offtarget_tagged_bam ? 24.GB : 8.GB) * task.attempt, 'memory' ) } + time = { check_max( 8.h * task.attempt, 'time' ) } // longest observed run ~2.5 h + } + + // WGS discovery + PoN + hotspot scoring — single-threaded, seconds-to-minutes, sub-GB. + withName: 'WGS_WORKLIST|PON_OFFTARGET_FILTER|SCORE_HOTSPOTS' { + cpus = { 1 } // scripts are single-threaded (was 4) + memory = { check_max( 6.GB * task.attempt, 'memory' ) } // was process_medium = 36 GB + time = { check_max( 2.h * task.attempt, 'time' ) } + } + + // Table joins + report + recall curve — trivial pandas steps (finish in ~1 s–1.5 min). + withName: 'HOTSPOT_TO_TABLE|BUILD_TRAINING_TABLE|RECALL_VS_VAF|RECONCILE_OFFTARGET_REPORT|OFFTARGET_METRICS' { + cpus = { 1 } + memory = { check_max( 4.GB * task.attempt, 'memory' ) } // was process_low = 12 GB + time = { check_max( 1.h * task.attempt, 'time' ) } + } + + // Offline model trainer (-entry TRAIN): a HistGBM fit over the training table — light. + withName: 'TRAIN_SHAPE_MODEL' { + cpus = { 1 } + memory = { check_max( 4.GB * task.attempt, 'memory' ) } + time = { check_max( 1.h * task.attempt, 'time' ) } + publishDir = [ + path: { "${params.outdir}/train" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + } diff --git a/conf/stub.config b/conf/stub.config index 68d26af..b80148e 100644 --- a/conf/stub.config +++ b/conf/stub.config @@ -13,7 +13,32 @@ params { config_profile_name = 'Stub test profile' config_profile_description = 'Minimal test dataset to check pipeline function' - process.executor = "local" + + // workflows/scge.nf validates every reference path at PARSE time, via top-level + // `params.X ? Channel.fromPath(X, checkIfExists: true) : []` statements that run on + // EVERY entry — OFFTARGET and HOTSPOTS included, though neither uses DRAGEN or VEP. + // The defaults all point at /storage2, which exists on the cluster and nowhere else, + // so a stub run dies before scheduling a single process anywhere that path is absent + // (GitHub Actions, a laptop, a collaborator's cluster). Null short-circuits each + // ternary; stub runs never read any of these. + refdir = null + fasta = "${projectDir}/assets/stub/tiny.fa" + dbsnp = null + adapter1 = null + adapter2 = null + snv_noisefile = null + sv_noisefile = null + cram_reference = null + vepcache = null + nirvana_path = null + // file()'d unconditionally when run_crisprme is on, so it must EXIST (never null); + // stub processes only touch outputs, so any real directory satisfies it. + crisprme_index_dir = "${projectDir}/assets/stub" + + // The transgene contig lives only in the real hg38+transgene FASTA. Both contig + // checks early-return on a null contig, so this skips the .fai lookup for the stub + // runs that don't pass their own --fasta. + transgene_name = null // Limit resources so that this can run on GitHub Actions max_cpus = 2 @@ -21,3 +46,10 @@ params { max_time = '6.h' } + +// NB: this belongs in a `process` scope, not in `params`. Written as `params.process.executor` +// it silently set an unused parameter instead of the executor; stub runs only appeared to work +// because `local` is already the default. +process { + executor = 'local' +} diff --git a/conf/test.config b/conf/test.config index 2424674..30d570f 100644 --- a/conf/test.config +++ b/conf/test.config @@ -5,7 +5,11 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/scge -profile test, --outdir + nextflow run nf-core/scge -profile test, -stub-run --outdir + + The bundled inputs under assets/stub/ are truncated placeholders, not real data, so + this profile is a wiring check and expects `-stub-run`. It exercises the analysis-only + path (`run_alignment = false`), which needs no DRAGEN licence or FPGA hardware. ---------------------------------------------------------------------------------------- */ @@ -14,16 +18,20 @@ params { config_profile_name = 'Test profile' config_profile_description = 'Minimal test dataset to check pipeline function' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' + // Without an input the pipeline cannot start, so this profile could never pass. + // Repo-relative stub DRAGEN output; run from the pipeline root. + input = "${projectDir}/assets/stub/dragen_path_samplesheet.csv" + run_alignment = false - // Input data - // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets - // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = '/storage1/fs1/dspencer/Active/spencerlab/dnidhi/pipelines/nf-core-scge/assets/test_samplesheet.csv' + // Limit resources so that this can run on GitHub Actions + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' +} - // Genome references - genome = 'R64-1-1' +// NB: these are process directives, not params. Declared inside `params` they became +// `params.maxRetries` / `params.maxErrors` and had no effect on retry behaviour. +process { + maxRetries = 0 + maxErrors = -1 } diff --git a/containers/docker-casoffinder-bulge/Dockerfile b/containers/docker-casoffinder-bulge/Dockerfile new file mode 100644 index 0000000..e5a839b --- /dev/null +++ b/containers/docker-casoffinder-bulge/Dockerfile @@ -0,0 +1,35 @@ +# ghcr.io/dhslab/docker-casoffinder-bulge +# +# Cas-OFFinder (CPU/OpenCL) + the cas-offinder-bulge wrapper (DNA/RNA bulge enumeration, +# whose output columns the pipeline's combine_offtarget_results.py parses) + UCSC +# faToTwoBit (so PREP_CASOFFINDER_REF can build the .2bit from params.fasta in the same +# image). Satisfies `container` in prep_casoffinder_ref.nf and casoffinder.nf. +FROM ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates wget unzip git g++ cmake make \ + opencl-headers ocl-icd-opencl-dev pocl-opencl-icd \ + python3 python3-pip python-is-python3 \ + && rm -rf /var/lib/apt/lists/* +# cas-offinder-bulge ships a `#!/usr/bin/python` shebang; python-is-python3 provides +# /usr/bin/python -> python3 so the wrapper runs (its body is Python-3 clean). + +# --- Cas-OFFinder (3.0.0b3) built against pocl for CPU execution ----------------- +ARG CASOFFINDER_VERSION=3.0.0b3 +RUN git clone --depth 1 --branch ${CASOFFINDER_VERSION} \ + https://github.com/snugel/cas-offinder.git /opt/cas-offinder \ + && cmake -S /opt/cas-offinder -B /opt/cas-offinder/build \ + && cmake --build /opt/cas-offinder/build --target cas-offinder \ + && install -m755 /opt/cas-offinder/build/cas-offinder /usr/local/bin/cas-offinder + +# --- cas-offinder-bulge wrapper (DNA/RNA bulges; emits the Bulge type/Size columns) --- +RUN git clone --depth 1 https://github.com/hyugel/cas-offinder-bulge.git /opt/cas-offinder-bulge \ + && install -m755 /opt/cas-offinder-bulge/cas-offinder-bulge /usr/local/bin/cas-offinder-bulge + +# --- UCSC faToTwoBit (for PREP_CASOFFINDER_REF) -------------------------------------- +RUN wget -q http://hgdownload.soe.ucsc.edu/admin/exe/linux.x86_64/faToTwoBit \ + -O /usr/local/bin/faToTwoBit \ + && chmod +x /usr/local/bin/faToTwoBit + +CMD ["/bin/bash"] diff --git a/containers/docker-crisprme/Dockerfile b/containers/docker-crisprme/Dockerfile new file mode 100644 index 0000000..b95e299 --- /dev/null +++ b/containers/docker-crisprme/Dockerfile @@ -0,0 +1,14 @@ +# ghcr.io/dhslab/docker-crisprme +# +# Thin wrapper over the upstream CRISPRme image that adds `procps` (the `ps` command). Nextflow's +# per-task wrapper runs `ps` to collect resource metrics under `-euo pipefail`; the upstream +# micromamba-based pinellolab/crisprme image has no `ps`, so tasks abort before the payload runs +# ("Command 'ps' required by nextflow to collect task metrics cannot be found"). Everything else +# (crisprme.py, crispritz, samtools, bedtools in the base conda env) is inherited unchanged. +FROM pinellolab/crisprme:latest + +USER root +# Install procps via apt so `ps` lands in /usr/bin (on the container's default PATH). A +# micromamba/conda install would put it under /opt/conda/bin, which the image does NOT have on +# its default PATH, so Nextflow's wrapper (which bypasses conda activation) would not find it. +RUN apt-get update && apt-get install -y --no-install-recommends procps && rm -rf /var/lib/apt/lists/* diff --git a/docs/CALLER_INTEGRATION_LOG.md b/docs/CALLER_INTEGRATION_LOG.md new file mode 100644 index 0000000..af80dcc --- /dev/null +++ b/docs/CALLER_INTEGRATION_LOG.md @@ -0,0 +1,809 @@ +# Caller integration — working log + +Running notes for the work described in [`CALLER_INTEGRATION_PLAN.md`](CALLER_INTEGRATION_PLAN.md). +Newest entries at the bottom. Every claim here should be reproducible from a command in the entry. + +## Safety net + +| | | +|---|---| +| Restore point | commit `e9b81b9`, `bin/find_edited_reads.py` **tracked and clean** | +| Undo a bad edit | `git checkout bin/find_edited_reads.py` | +| Uncommitted before we start | `nextflow.config` (gate 2/0.005, `pon_min_reads` 2), `docs/CALLER_INTEGRATION_PLAN.md`, `docs/THRESHOLD_CHANGE_IMPACT.md` | +| Regression baselines | `results_cart_full/` (gate 10/0.05), `results_cart_lowgate/` (gate 2/0.005), `results_cart_ponfix/` (+ `pon_min_reads` 2) | + +**Rule for this work:** no edit to `find_edited_reads.py` lands without (a) a baseline capture before, +(b) a diff of the *outputs* after, not just an exit code. The caller is on the shared analysis path — +a regression here breaks the whole pipeline, not just the off-target arm. + +## Order of work + +Following the plan's own priority: + +1. **Item 2 — `control_bnd_reads`** (in progress) — smallest surface, unblocks item 3 +2. Item 3 — breakpoint promiscuity +3. Item 1 — consolidate rules 1–3 into the caller +4. Item 4 — DRAGEN noise panels + +--- + +## 2026-08-10 — Item 2 reconnaissance + +Goal: add a site-level `control_bnd_reads` column so rule 1 (matched control clean) can apply to +breakends. Today there is `control_indel_reads` but no BND equivalent, so rule 1 — which removes 352 +of 1,410 dropped rows on indels — cannot fire on breakends at all. + +### What we already know going in + +- Per-event `control_alt_counts` (field 11 of both `indel_info` and `bnd_info`) is **0 on every + event, always**, because `-x/--max-in-control` defaults to 0 and *removes* events with control + support before they are written. Verified across 2,802 indel and 892 BND events. +- The meaningful statistic is the site-level `control_indel_reads` column, nonzero on 313 rows. +- 2,403 BND events in the 32-sample cohort; median 1 supporting read; 51% interchromosomal. + +### Safety net established + +**Test suite is runnable and green: `30 passed`.** It was not runnable as documented — `pytest` is +absent from every container on this system (`docker-scge-offtarget`, `docker-scge`, +`docker-baseimage`) and from the system Python. Recipe that works: + +```bash +python3 -m venv --system-site-packages pyt # inherits pandas/pysam/sklearn/scipy/joblib +./pyt/bin/pip install pytest edlib pyranges # edlib + pyranges are the only real gaps +./pyt/bin/python -m pytest tests/ -q # -> 30 passed +``` + +This matters because `tests/conftest.py` builds a **synthetic aligned-read workspace** and +`tests/test_offtarget_glue.py` actually executes `find_edited_reads.py` against it. So we have a +real regression check on the file we are about to edit, not just an import smoke test. + +Baseline recorded **before any edit**: `30 passed, 1 warning`. Any change must keep that at 30. + +### Reconnaissance findings + +**F1 — the control-counting machinery for breakends already exists and is correct.** +`add_normal_counts` (:828) builds an `altseq` for every event via `generate_contig` (:269), and that +function has explicit BND handling (:291): it parses the bracket notation, fetches the local and +remote flanks, reverse-complements where the orientation demands it, and stitches a **chimeric +junction contig**. Control reads are then counted against that contig by the same three-tier match +used for indels. So control support at a breakend is *already being computed properly* — nothing +needs to be written from scratch. + +**F2 — it is computed, then silently folded into `control_indel_reads`.** + +``` +:2225 control_alt_observed = int(indelcounts['control_alt_counts'].sum()) # ALL event types +:2228 indelcounts = indelcounts[control_alt_counts <= max_in_control ...] # -x filter +:2238 control_indel_reads = control_alt_observed +:2261 bnds = indelcounts[(alttype == 'BND') & (ref != '.')] # split happens +:2262 indels = indelcounts[(alttype != 'BND') & (ref != '.')] # 36 lines later +``` + +The sum at :2225 runs over `indelcounts` **before** the indel/BND split, so it spans indels, BNDs +and REF placeholder rows alike. **`control_indel_reads` is therefore mislabelled** — it is "control +support at this site across all event types", not "control indel reads". + +The summation position itself is deliberate and correct (comment at :2220): it runs before the `-x` +filter so the reported column survives `-x 0`. That is the fix already made. The event-type split is +the part that was never done. + +**F3 — the required change is a split, not new logic.** Sum `control_alt_counts` separately over the +BND rows at :2225 and expose it. Roughly four lines. + +**F4 — no downstream consumer reads these tables positionally.** All 18 scripts that read +`*.offtarget_analysis.tsv` use `pd.read_csv(..., sep='\t')` with name-based access. The only +positional reads in `bin/` (`usecols=[0,1,2]`) are against **BED** files in `make_hotspot_vcf.py` +and `targets_csv_to_vcf.py`, which are unaffected. **Appending a column to the header is safe.** + +**F5 — evidence the mixing is real, but not yet proof it is numerically material.** 4 cohort sites +have `control_indel_reads > 0` with `indel_count == 0` and `bnd_count > 0` +(e.g. `CART_NS0027-B2M_2 chr9:106,439,687`, control 37/110). That is *consistent* with a BND +contribution, but equally consistent with an indel event that the `-x 0` filter removed after its +support was counted. **Do not claim BND contamination of `control_indel_reads` as measured** — the +structural fact (F2) is certain; the magnitude is not. Splitting the sum is what will measure it. + +### Proposed change (not yet applied) + +Purely **additive**. `control_indel_reads` keeps its current value bit-for-bit, so no existing +behaviour moves and the review filter is unaffected. + +1. `:2225` — alongside `control_alt_observed`, compute `control_bnd_observed` over BND rows only. +2. `:2231-2239` — carry it into a `control_bnd_reads` local. +3. `:1889-1891` — append `control_bnd_reads` to `header_columns`, after `bnd_count`/`bnd_info`. +4. `:2317-2322` and the `fp_log` block at `:2305-2310` — emit it in both row writers, in the same + position as the header. + +Deliberately **not** doing in this step: correcting `control_indel_reads` to be indel-only. That +changes existing numbers and needs its own before/after measurement. Logged as a separate decision. + +Risks to watch: the `fp_log` writer and the main writer are separate field lists that must stay in +lockstep with the header, and `--enable-crispr-prediction` appends three more columns after ours. + +### Applied — 5 edits + +`control_bnd_reads` inserted after `bnd_info` (col index 14 of 17), keeping the BND statistics +together. Edits: header (:1889), the BND-restricted sum (:2225), local init (:2231), assignment +(:2238), and **both** row writers. + +### Verification + +**V1 — structural.** `py_compile` clean. Header = 17 columns; main writer = 17; `fp_log` writer = 17. +The two writers and the header are independently parsed and counted, so they cannot silently drift. + +**V2 — regression suite.** `30 passed`, identical to the pre-edit baseline. + +**V3 — A/B on real data, identical inputs.** This is the one that matters. Extracted the HEAD version +(`git show HEAD:bin/find_edited_reads.py`) and ran **both** versions on the same CRAMs and the same +92-site target subset for `KLF12-KO-DNA`: + +``` +rows: HEAD 92, patched 92, same order +HEAD 16 cols, patched 17 cols, added: ['control_bnd_reads'] +ALL 16 PRE-EXISTING COLUMNS BIT-IDENTICAL +``` + +The change is provably additive on real data. + +> **Method note, worth remembering.** The first comparison was patched-output vs the *stored Aug 7 +> full-cohort* output, and it showed `bnd_info` differing on 11 rows plus 20 rows failing to join — +> `start` had shifted by 1 bp. That was **entirely an artifact of subsetting the target VCF**: +> adjacent targets merge into different intervals when their neighbours are absent, so the site +> boundaries move. It was not caused by the edit. Never A/B a subset run against a full run — +> re-run the baseline binary on the identical subset. + +**V4 — the column reads 0 everywhere, and chasing that found a pre-existing bug.** + +`control_bnd_reads` is 0 at **all 92 KLF12 sites** and at **all 204 CTLA4_1 sites** (203 of which +carry breakends, 234 events). That is not because breakends lack control support. It is an +**off-by-one in the position passed to `add_normal_counts`**, which predates this work. + +*Evidence, in order.* + +1. The control CRAM is not clean at these loci. At `chr1:246,009,900-246,010,060` the **control** has + 174 reads, of which 111 survive the read filters, **37 carry `SA` tags**, and **4 point at chr8** — + the exact partner of the breakend under test. +2. Called directly with the variant, the counting works: `add_normal_counts` returns + **`control_alt_counts = 11`**. +3. The variant is not a straw man. The pipeline's own `bnd_info` for that site contains + `pos=246009982 ref=T alt=T[chr8:94633103[ counts=5 ctrl=0` — byte-identical to the probe. +4. `control_total_counts = 104` from the probe equals the pipeline's `control_reads = 104`, so the + probe reproduces the pipeline's call exactly. +5. Sweeping the position is decisive: + + | position passed | `control_alt_counts` | + |---|---| + | 246,009,982 — 1-based, correct | **11** | + | 246,009,981 — what the pipeline passes | **0** | + | 246,009,983 | 3 | + +**Root cause.** `indelcounts['pos']` is **0-based** — `bnd_info`/`indel_info` keys are built as +`r['pos']+1` (:2265, :2268) precisely to convert it. But `add_normal_counts` treats its `pos` as +**1-based** (`start_idx = pos - 1`, :839). So every contig is built one base off. + +**Why this destroys breakends but only degrades indels.** `generate_contig` puts the junction at an +exact point, so a 1 bp shift means a junction-spanning read is no longer a substring of `altseq` and +tier 2 (`read_seq in v['altseq']`) fails outright. Tier 1 also fails, because it requires +`vcf_dict['pos'] == v['pos']` across the same mismatched convention. Tier 3 (edlib) is the only +survivor, and its accept test is indel-shaped — it branches on `ref_len` vs `alt_len`, where for a +breakend `alt_len` is the length of the *bracket string* (`len("T[chr8:94633103[") == 16`), not a +sequence length. So for BNDs nothing can fire. For indels tier 3 still recovers most cases, which is +why `control_indel_reads` is nonzero on 313 cohort rows despite the same shift. + +**Status of this item.** The `control_bnd_reads` column is correctly implemented, verified additive, +and currently reads 0 everywhere because of the above. **The column is not the blocker — the +off-by-one is.** + +**Deliberately not fixed in this step.** Correcting the position convention would change +`control_indel_reads` on real data, which feeds rule 1 of the review filter and therefore the queue. +That needs its own before/after measurement on the full cohort, exactly like the threshold change +did. Not measured yet: how much `control_indel_reads` moves once the shift is corrected. + +**Next actions, in order.** +1. Quantify the indel-side impact of the off-by-one on a full sample (`control_indel_reads` before + vs after) before touching the convention. +2. Fix the convention at the call site (:2193) rather than inside `add_normal_counts`, so the + function keeps its documented 1-based contract. +3. Give tier 3 a breakend-aware accept test, since the `ref_len`/`alt_len` comparison is meaningless + for bracket notation. +4. Only then re-measure `control_bnd_reads` and decide whether rule 1 is worth applying to BNDs. + +--- + +## 2026-08-10 — Measuring the off-by-one fix. **Verdict: do not ship it yet.** + +Built a candidate (`scratchpad/bndverify/cand_fer.py`, one line: `pos = int(row['pos']) + 1` in +`add_normal_counts`) and ran it against the current tree on the identical KLF12 92-site subset and +identical CRAMs. + +| column | current | candidate | sites changed | +|---|---|---|---| +| `total_reads` | 15,815 | 16,248 | 19 | +| `indel_reads` | 413 | **846** | 19 | +| `indel_count` | 90 | 123 | 17 | +| `control_indel_reads` | 1,100 | **541** | 40 | +| `control_bnd_reads` | 0 | **2** | 1 | +| rows passing gate (2, 0.005) | 24 | 28 | — | + +**The diagnosis was right: the fix does turn on breakend control counting** (0 → nonzero). That +confirms the off-by-one was the blocker, not the new column. + +**But the blast radius is far larger than the control columns.** `indel_reads` *doubles*. That is +not a side effect of counting — `total_reads`/`indel_reads`/`indel_count` are summed at :2236-2237, +**after** the `-x` filter at :2228. Change control support and you change which events survive the +filter, so the caller's primary variant calls move. This is not a "control column" fix; it changes +what the caller reports as edited. + +**Which version is correct is NOT established.** I tried to settle it on ground truth and could not: + +- At `chr4:183,359,487` the current build says 90 control indel reads and the candidate says 0. The + control genuinely is not clean there — 109 of 147 filtered reads carry a 1 bp deletion, and it + localises to a single germline event (0-based 183,359,514, anchor key 183,359,514, 88 reads). +- But neither number is obviously right, because the *events called at that site* are a 38 bp + deletion (`C|DEL38`, key 183,359,514) and a 1 bp deletion at a different anchor (key 183,359,510). + Neither is the germline deletion the control carries. So "the control has indels here" does not + decide whether either event is supported. +- The current build's 90 may be spurious matching by a mis-centred contig; the candidate's 0 may be + correct-but-strict. **Unresolved.** + +**Coordinate convention, as far as it is established.** `get_cigar_indel_vcf` sets +`out_dict['pos'] = anchor_ref_pos = current_ref + ref_consumed - 1`, seeded from +`read.reference_start` (pysam, 0-based), and fetches `ref` at that same 0-based coordinate. The +`+1` when building info keys converts to 1-based. `add_normal_counts` and `generate_contig` both do +`start_idx = pos - 1`, i.e. expect 1-based. **The inconsistency is real.** For the breakend case it +was verified end-to-end (correct position → 11 control reads and the control demonstrably carries 4+ +reads to the exact partner; the position the pipeline passes → 0). For indels the equivalent +end-to-end verification has *not* been done. + +### Decision + +**Do not apply the positional fix on the current evidence.** A change that doubles `indel_reads` +must be validated against known truth, not reasoned about. It feeds the evidence gate, the review +queue and every downstream number in the deck. + +**Validation set to use next:** the manual-review truth (`Manual Indel Review/`, the +`manual_review` column) and/or the AAVS1 curated truth (`crispr_ml/AAVS1_training_{tp,tn}.tsv`). +Run both builds over a cohort with known calls and compare recall/precision against the labels. +Whichever build agrees with the manual calls is correct. That is a measurable question and should +not be answered by inspection. + +### Repository state + +`bin/find_edited_reads.py` contains **only** the `control_bnd_reads` addition, which is verified +additive (all 16 pre-existing columns bit-identical). The positional fix exists solely as a +scratchpad candidate and has **not** been applied. Nothing is committed. + +--- + +## 2026-08-10 — The self-consistency test, and a correction to the entry above + +The manual-review truth turned out to be unusable for this question: `KLF12-KO-DNA.edited_reads.xlsm` +has 2,328 rows and a `pass` column with **2** annotations, both on-target. It is a positives-only +set — recall only, no negatives, so it cannot adjudicate over- vs under-counting. (Consistent with +what is already known: 55 confirmed positives against tens of thousands of NaNs.) + +**A label-free test settles it instead.** Run the caller with `--edited-bam` and `--control-bam` set +to the *same* CRAM. Every event called in "edited" is then, by construction, fully supported in +"control". Any event surviving the `-x 0` filter is a provable miss by the control matcher, and +`control_indel_reads` should be high. No labels needed. + +Both builds, KLF12 92-site subset, identical CRAM on both sides: + +| metric | current | global `+1` candidate | ideal | +|---|---|---|---| +| events escaping `-x 0` | **12** | 72 | ~0 | +| `indel_reads` | **77** | 465 | ~0 | +| `control_indel_reads` | **3925** | 2000 | high | +| `control_bnd_reads` | 5 | **40** | high | +| sites with ≥1 escape | **9 / 92** | 27 / 92 | 0 | + +### Correction to the previous entry + +**The earlier conclusion — "`add_normal_counts` receives 0-based positions and treats them as +1-based" — was too broad.** It holds for **breakends**, where it was verified end-to-end. It does +**not** hold for indels: the current handling is substantially *more* correct there, and the global +`+1` makes indels six times worse by this measure. The two producers of `pos` disagree by one base, +and `generate_contig`'s BND branch and linear branch inherit that disagreement: + +- BND path (`:395-410`): `bp1_pos = L['r_end']` (0-based), `ref_base` fetched at `bp1_pos`, and the + code comments `'pos': bp1_pos, # VCF 1-based POS is usually this value`. +- Indel path (`get_cigar_indel_vcf`): `pos = anchor_ref_pos` seeded from `read.reference_start`, + `ref` fetched at the same coordinate. + +They look alike on the surface, which is why reading the code was not enough and the measurement +was. **Do not fix this globally.** The `+1` belongs to breakends only. + +### The BND-only fix — confirmed and applied + +`if alttype == 'BND': pos += 1`. Self-consistency, all 92 sites: + +| metric | current | global `+1` | **BND-only** | ideal | +|---|---|---|---|---| +| `indel_count` (escapes) | 12 | 72 | **12** | ~0 | +| `indel_reads` | 77 | 465 | **54** | ~0 | +| `control_indel_reads` | 3925 | 2000 | **3960** | high | +| `control_bnd_reads` | 5 | 40 | **40** | high | +| `bnd_count` (escapes) | 38 | 22 | **22** | ~0 | +| sites with escaped indel events | 9 | 27 | **9** | 0 | + +It takes the best of both: **indel event calling identical to current** (`indel_count` equal +row-by-row, 9 sites with escapes either way) while breakend control support improves **8×** and +breakend escapes drop from 38 to 22. + +The cleanest confirmation is the arithmetic: `control_indel_reads` moves by **+35**, and +`control_bnd_reads` gains **+35**. Identical. Since `control_indel_reads` is summed over all event +types (finding **F2** at the top of this log), the *only* thing that changed is the newly-recovered +breakend support. Nothing on the indel side moved at all. + +**Applied to `bin/find_edited_reads.py`.** `py_compile` clean, test suite **30 passed**. + +### Real-data A/B (edited vs true control), KLF12, 92 sites + +| column | before | after | sites changed | +|---|---|---|---| +| `indel_count` | 90 | 90 | **0** | +| `total_reads` | 15,815 | 15,814 | 1 | +| `indel_reads` | 413 | 412 | 1 | +| `control_indel_reads` | 1,100 | 1,102 | 1 | +| `bnd_count` | 41 | 40 | 1 | +| `control_bnd_reads` | 0 | **2** | 1 | + +Precisely targeted: **one** breakend at **one** site is now correctly recognised as present in the +matched control and removed by `-x`. Indel event calling is untouched (`indel_count` 90 → 90 with +zero sites changed), and `control_indel_reads` moves by exactly the `control_bnd_reads` gain. + +Note the scale honestly: on this sample the change is nearly a no-op, because KLF12's breakends are +single-read junctions at homology sites where the control genuinely carries nothing. The fix matters +where the control *does* carry the junction. + +### Where it actually bites — CART_NS0027-CTLA4_1 + +Re-ran the sample's 204 breakend-bearing sites. At the `chr1:246,009,98x` alignment hub: + +| | before | after | +|---|---|---| +| `bnd_count` | **25** | **2** | +| `control_bnd_reads` | **0** | **197** | + +**23 of the 25 breakends at that site are now correctly identified as present in the matched control +and removed.** Across all 204 sites: + +| column | before | after | +|---|---|---| +| `indel_count` | 42 | **42** (identical row-by-row) | +| `bnd_count` | 233 | **210** | +| `control_bnd_reads` | 0 | **197** | +| `control_indel_reads` | 37 | 234 | + +23 spurious breakends removed cohort-wide for this sample, indels untouched. `control_indel_reads` +moves only because it sums over all event types (finding **F2**). + +This is the same locus flagged earlier by breakpoint promiscuity (45 distinct partners) and the same +one behind all four interchromosomal "off-target" breakend candidates in the CTLA4 samples. **Two +independent rules — matched control and promiscuity — now reject it.** That is the strongest +possible outcome: the artifact class item 3 was designed to catch is also caught by rule 1 once rule +1 can actually see breakends. + +### Why this was not findable by reading the code (item 2) + +Both producers look identical on inspection — each stores a 0-based coordinate and fetches `ref` at +it. The disagreement is in `generate_contig`, whose BND and linear branches consume `pos` +differently. Two careful code readings gave the wrong answer here; the self-consistency test gave +the right one in a single run. **For any further coordinate work in this file, measure it — the +edited==control trick costs about three minutes and needs no labels or truth set.** + +--- + +## 2026-08-10 — Item 3: breakpoint promiscuity. Built, and it is non-binding. + +New script: **`bin/review_filter_bnd.py`**. Same shape as `review_filter.py` — expands `bnd_info` +into one row per junction, gates, applies rules, writes a queue and an optional `--keep-all` audit. + +Cohort result (32 samples, pre-fix inputs): + +``` +input junctions : 2404 +cleared the gate : 36 (reads>=3) + dropped, far from PAM : 7 + dropped, promiscuous breakpoint : 4 +BREAKEND QUEUE : 25 + multi-cut deletion : 23 in 7 sample(s) span 413-125,747 bp + deletion at cut site : 2 in 1 sample(s) +``` + +**There are no off-target breakend junctions in this cohort.** Everything that survives is an +on-target editing outcome. + +### The promiscuity rule does not earn its keep — and that is item 2's doing + +Measured, not assumed: + +- After rule 1 (`reads >= 3`), the **only** promiscuous breakpoint cohort-wide is `chr1:246,009,98x`. + Every other breakpoint with ≥5 partners has a maximum of **1** supporting read, so rule 1 removes + them first. +- That one hub is exactly what item 2's control fix now removes on its own. Re-running three samples + through the fixed caller collapses the signal: + + | sample | junctions before → after | max partners before → after | + |---|---|---| + | CART_NS0027-CTLA4_1 | 234 → 210 | **25 → 3** | + | CART_NS0027-CTLA4_2 | 237 → 201 | **31 → 2** | + | CART_NS0027-Regnase1_2 | 192 → 191 | 2 → 2 (no hub to begin with) | + +So rule 3 is **kept but currently non-binding**: it costs nothing, it is the only defence against a +hub that happens to be absent from the matched control, and its `n_partners` column is worth +reporting. `0 dropped by rule 3` is the expected reading, not a broken rule. This is documented in +the script's docstring so nobody "fixes" it later. + +### The on-target exemption is not optional + +**6 of the 10 breakpoints with ≥5 distinct partners are the intended cut sites** — TRAC +(`chr14:22547`, 22 partners), TRBC1/TRBC2 (`chr7:142792`, `chr7:142801`), B2M (`chr15:44711`). +A real Cas9 cut throws junctions everywhere, so the true edits are among the most promiscuous +breakpoints in the cohort. Applying rule 3 without exempting on-target sites deletes the findings. + +### Classification, corrected once during development + +`is_target` describes the **near** end — the site the junction was found at — so a junction anchored +at a cut site is an on-target outcome even when its far end is unremarkable. The first version +labelled anything without a cut site at *both* ends "off-target junction", which mislabelled the +BRAF pair (`chr7:140,801,460 → chr7:140,834,645`, 33 kb, 7 and 3 reads). BRAF's six on-target sites +do not include the far end, so that is a single cut resected and joined 33 kb out — a real on-target +deletion, not an off-target. Final taxonomy: + +| both ends at cut sites, same chrom | multi-cut deletion | +|---|---| +| near end at a cut site, same chrom | deletion at cut site | +| near end at a cut site, other chrom | translocation at cut site | +| near end not a cut site | off-target junction | + +> **Superseded 2026-08-20 — these are inversions, not deletions.** The taxonomy above classifies on +> position only and never reads `strands`. Every same-chromosome row in this queue is `+-`/`-+`, +> the inverted adjacency; a deletion is collinear (`++`/`--`) and, on the same chromosome, is +> resolved to DEL/DUP/INS by `find_edited_reads.py:420` and never reaches the BND queue at all — so +> the two "deletion" rows were unreachable-by-construction wrong. Confirmed two ways: all eight +> events carry both junctions of the reciprocal pair (a deletion makes one), and there are zero +> collinear junctions at any of the eight cut pairs even unfiltered. The shipped labels are now +> `multi-cut inversion` / `inversion at cut site`. Kept here as written for the record. + + +### Not done + +- Not wired into the Nextflow pipeline. It runs standalone over `*.offtarget_analysis.tsv`. +- The cohort numbers above come from **pre-fix** inputs. A full re-run with the corrected caller + would drop the 4 promiscuity drops (removed upstream instead) and leave the 25-junction queue + unchanged. Worth confirming when the cohort is next re-run for another reason; not worth a + dedicated 32-sample run. + +--- + +## 2026-08-10 — Item 1: consolidate rules 1–3 into the caller. **Scoped down, deliberately.** + +The plan asked to move review rules 1–3 into `find_edited_reads.py`. Measuring first changed what +was worth doing. Two real defects surfaced; neither is fixed by moving a rule, and the fixes that +*would* move rules turn out to make things worse. + +### Finding A — rule 2 is duplicated *inside* the caller, and the two copies disagree + +There are three distance tests, not one: + +| where | formula | used for | +|---|---|---| +| `:2035`, `:2057`, `:2085`, `:2107` | `distance > max AND distance2 > max` | per-read rejection | +| `:2193` → filtered at `:2229` | `min(\|pos−PAM\|, \|pos+len(ref)−1−PAM\|)` — capital `Distance` | **the site filter** | +| `:593` | `min(\|pos−PAM\|)`, anchor base only — lowercase `distance` | **what is reported** | + +`Distance` is a minimum over a superset, so `Distance <= distance` always. The caller therefore +**filters on one quantity and reports a larger one**. Consequence, measured on the cohort audit +trail: **32 rows report `cut_dist_min > 25` under a nominal `-d 25` cap.** Downstream cannot +reproduce the caller's own rule-2 decision from the reported field. + +### Finding B — `-x` discards evidence without recording it + +`-x/--max-in-control` (default 0) removes control-supported events before they are written, so a +site reports `indel_count = 5` whether it suppressed one event or fifty. Measured on the 92-site +KLF12 subset: + +| | `-x 0` (default) | `-x` disabled | +|---|---|---| +| `indel_count` | 90 | **170** | +| `indel_reads` | 412 | **2,966** | +| `bnd_count` | 40 | 41 | + +**81 events and 2,554 indel reads suppressed across 42 of 92 sites, with no record.** That is the +caller performing most of the germline removal *before* `review_filter`'s rule 1 ever runs. + +Confirmed at the same time: `control_indel_reads` and `control_bnd_reads` are **identical with `-x` +on or off**, so the summation-before-filter fix works and the plan's second acceptance criterion — +"control columns always populated regardless of `-x`" — was already satisfied. + +### What was implemented: two audit columns, no behavioural change + +| column | meaning | +|---|---| +| `n_control_filtered` | events at this site removed by `-x` | +| `min_cut_distance` | the site minimum of `Distance` — the quantity actually filtered on | + +Header is now 19 columns; both writers verified at 19. Purely additive. + +**Verification, 92-site KLF12 A/B on identical CRAMs:** + +``` +cols 17 -> 19 | added ['n_control_filtered', 'min_cut_distance'] +pre-existing columns differing : NONE - bit-identical +CROSS-CHECK n_control_filtered 81 vs suppressed 81 -> AGREE +sites where -x suppressed something : 42 / 92 +min_cut_distance where events exist : n=68, min 0, max 25 +``` + +`min_cut_distance` maxes at exactly 25, matching `-d`, which is the point: the filtered quantity +never exceeds the cap, while the *reported* per-event `distance` does on 32 cohort rows. `-1` is the +sentinel for a site with no events. Test suite `30 passed`. + +### What was deliberately NOT done, and why + +**Rule 2 was not consolidated into the caller.** Tightening `-d` from 25 to 10 would delete the +audit trail's single largest drop category: of 1,498 gated cohort rows, **753 sit at 11–25 bp** and +680 are dropped by `review_filter` as "far from PAM". Filtering them in the caller means they are +never written and the reviewer can never see what was removed. The coarse-then-fine arrangement is +correct; the defect was that the two stages measured different things, which `min_cut_distance` now +exposes without changing behaviour. + +**Rule 3 was not moved.** It requires ≥3 distinct indel lengths, which a site with 2 indel reads can +never satisfy — it is a read-depth threshold in disguise (see the threshold-change entry: 837 rows, +zero survivors). `review_filter` computes it from `indel_info` at cohort level where the depth +context is visible. Moving it into the caller adds depth-sensitivity and buys nothing. + +**Rules 4 and 5 cannot move**, as the plan already noted: the panel of normals needs every unedited +sample in one pass, and `find_edited_reads.py` runs per-sample. + +**`-x` was left at its default.** Flipping it to report-only is the change that would truly +"let downstream decide", but it multiplies `indel_reads` by 7 and would require re-validating the +whole review filter and the panel of normals. It belongs with the off-by-one indel question as a +separate, measured piece of work — not bundled here. + +### A bug the cross-check caught, worth recording + +The first build of these two columns shipped **empty** — `n_control_filtered` 0 at every site, +`min_cut_distance` -1 at every site — while every pre-existing column stayed bit-identical. The A/B +would have passed on the "nothing regressed" criterion alone. + +Cause: the values are computed just before the `-x` filter, but the "Process indel results" block +below it re-initialises its locals, and the initialiser added there ran *after* the computation and +blanked both. `control_bnd_reads` survived the same pattern only because it is reassigned further +down. + +It was caught by an independent cross-check, not by the diff: + +``` +n_control_filtered = 0 (what the new column claimed) +(-x disabled) minus (-x 0) = 81 (what was actually suppressed) +``` + +**Lesson for additive columns: "pre-existing columns unchanged" is necessary but not sufficient.** +A new column also has to be checked against something computed a different way, or an empty column +looks exactly like a clean result — the same failure mode as the PoN coverage guard in +`review_filter.py`, and the same one that made `control_bnd_reads` read zero for a whole afternoon. + +--- + +## 2026-08-10 — Item 4: DRAGEN systematic-noise panels + +### Part A — SV panels for breakends + +Tested all three panels against the 36 gated junctions from item 3 (25 real queue, 11 artifacts). +The metric is **discrimination**, not coverage: a panel is only useful if it flags artifacts at a +higher rate than real junctions. + +| panel | records | real queue flagged | artifacts flagged | +|---|---|---|---| +| `WGS_hg38_v3.1.0` | 311,395 | **0 / 25** | **11 / 11** | +| `IDPF_WGS_v3.0.0` | 2,626,364 | 25 / 25 | 11 / 11 | +| `WGS_FF_Heme_v3.1.0` | 2,195,842 | 24 / 25 | 11 / 11 | + +**IDPF and FF_Heme are not merely useless — they are harmful.** Across the full 2,403-junction set +they flag the real queue at a *higher* rate than the noise (IDPF: 100% of real at every slop and +both matching modes). Used as a blacklist they would preferentially delete findings. The plan +already warned about IDPF at 200 bp; the measurement is worse than that — it fails at 0 bp too. + +**`WGS_hg38_v3.1.0` is perfect on this cohort**, and independently: it flags **every one of the 11 +artifacts and none of the 25 real junctions**, using no PAM distance, no cohort context and no +matched control. That makes it the only rule here that works on a **single sample on day one**, +which is exactly the gap the promiscuity rule cannot cover. + +Slop is load-bearing: + +| slop | real flagged | artifacts flagged | +|---|---|---| +| 0, either end | 0 | 11 | +| 50, either end | 0 | 11 | +| **200, either end** | **3** | 11 | + +Default set to **50**; the help text says not to raise it to 200. + +**Wired into `review_filter_bnd.py`** as optional `--sv-noise` / `--sv-noise-slop`, on-target +exempt. Verified: with and without the panel the queue is **identical (25 = 25)**. It reports +`dropped, DRAGEN systematic noise: 0` because `np.select` is first-match-wins and all 11 are already +attributed to rules 2 and 3 — the panel is **corroborating, not additive**, on this data. Its value +is (a) independent confirmation that every drop is a known artifact locus, and (b) a rule that still +works when there is one sample and no cohort. + +```bash +review_filter_bnd.py --sv-noise \ + /storage2/fs1/dspencer/Active/shared/refdata/hg38/dragenfiles/WGS_hg38_v3.1.0_systematic_noise.sv.bedpe.gz \ + -o bnd_queue.tsv +``` + +### Part B — the SNV noise BED + +`IDPF_WGS_hg38_v.2.0.0_systematic_noise.snv.bed.gz`, 1 GB, BGZF (tabix-able but shipped without an +index). Format is 7 columns: `chrom start end mean max alleles n_samples`, and the allele column +carries `D` codes alongside `A/C/G/T`, so it is **not purely an SNV panel** — worth testing after +all, contrary to the plan's prior. Provenance matters: `##PON SAMPLES` lists ~46 leukemia normals, +so it is a heme panel applied to CAR-T (T-cell) data. + +Streamed the whole file once (97,851,753 records) against all 1,498 gated indel rows, ±2 bp. + +**Allele vocabulary settles the first question:** `G` 30.3M, `C` 29.8M, `T` 15.1M, `A` 14.8M, +**`D` 1,299,670**, **`I` 892,925**, plus multi-allelic combinations. The `D`/`I` codes mean this is +**not purely an SNV panel** — it carries deletion and insertion noise, so the plan's prior ("expect +a negative result, it is an SNV map not an indel map") was wrong and the test was worth running. + +| class | rows | flagged | +|---|---|---| +| dropped (artifacts) | 1,410 | **467 (33.1%)** | +| off-target keeps | 7 | 1 (14.3%) | +| on-target keeps | 81 | **1 (1.2%)** | + +**27x enrichment for artifacts over real on-target edits.** That is genuine discrimination — far +better than the IDPF *SV* panel managed, and comparable in shape to the repeat masks already used by +rule 5. + +**It fails the strict acceptance bar, but only just:** it flags 1 of 81 on-target sites, +`IKZF2-KO-DNA chr2:213,147,790` — which is the IKZF2 cut site itself, and also one end of that +sample's multi-cut deletion. A real cut site can sit in a locus a generic panel calls noisy, for the +same mappability reasons that made it a predicted off-target in the first place. So this panel +**cannot be used as an unconditional blacklist**; it needs the same `is_off` exemption that rules 4 +and 5 already apply, and with that exemption it touches no on-target site by construction. + +### The two flagged keeps are not equivalent — and one is a real challenge to a finding + +| site | class | noise mean | noise max | alleles | PoN samples | +|---|---|---|---|---|---| +| `CART_NS0027-B2M_2` chr1:28,580,333 | **off-target keep** | 0.0136 | **0.0784** | **`C,D`** | **17** | +| `IKZF2-KO-DNA` chr2:213,147,790 | on-target keep | 0.0006 | 0.0269 | `G` | 1 | + +The on-target hit is a coincidence and dismissible on its own fields: **one** PoN sample, SNV-only +(`G`), max 2.7% — against an edit called at **74% VAF**. Nothing to answer. + +The off-target hit is substantive. `chr1:28,580,332` is one of the **7 off-target candidates in the +deck**, one of the two low-VAF "hard cases", called at **9.4% VAF**. The panel says that locus is +recurrently noisy in **17 of ~46 leukemia normals**, that the noise includes a **deletion (`D`)**, +and that it reaches **7.8%** there. Our candidate sits barely above that. This is independent +evidence — from a panel built on different donors, different chemistry, different lab — that the +B2M chr1 candidate may be systematic noise rather than an edit. **It does not settle it, but it is +the strongest external challenge to any of the 7.** + +Note this is the same site the earlier `pon_min_reads` work flagged as marginal: control VAF 0.0085, +1 control read, and it would have been blacklisted at `pon_min_reads = 1`. + +**Rule design follows from those two rows.** A bare interval hit is the wrong test — it fires on the +IKZF2 coincidence too. Sweeping both candidate conditions against the queue shows which one is +actually load-bearing: + +| `min_donors` (with `D`/`I` required) | dropped rows hit | off-target keeps hit | **on-target keeps hit** | +|---|---|---|---| +| 1 | 53 | 1 | **0** | +| 3 | 12 | 1 | **0** | +| 5 | 10 | 1 | **0** | +| 20 | 1 | 0 | **0** | + +**The `D`/`I` allele requirement alone excludes every on-target site, at every threshold including +1.** IKZF2's alleles are `G` — SNV-only noise, which says nothing about an indel call at the same +coordinate. Only 25 of the 359 panel records touching the query set carry `D`/`I` at all, so the +allele test is doing the protective work; the donor floor is a confidence knob controlling how many +already-dropped rows are additionally corroborated (53 → 12 → 10 going 1 → 3 → 5). + +Default set to **`--snv-noise-min-donors 3`**. + +**Recommendation.** Usable as a *supplement* to the run's own PoN for indels, never a replacement: +the self-built panel is guide-matched and donor-matched, this one is 46 leukemia normals. Worth +adding to `review_filter.py` as an optional `--snv-noise` rule behind the on-target exemption, and +worth measuring against the queue before enabling by default — it flags 1 of the 7 off-target +candidates, so it would change findings, not just drop noise. **Implemented** as optional rule 6 in `review_filter.py` +(`--snv-noise`, `--snv-noise-min-donors`), off by default. It is placed **last** in the `np.select` +order so first-match-wins guarantees it cannot re-attribute any existing drop — it can only claim +rows the five existing rules kept. Verified: without the flag the run is unchanged (88 queue, same +per-rule counts, `systematic noise: 0`). + +### Rule 6 in production — measured effect + +``` +review_filter.py --pon --repeats --min-reads 2 --min-vaf 0.005 \ + --snv-noise IDPF_WGS_hg38_v.2.0.0_systematic_noise.snv.bed.gz +``` + +| | without rule 6 | with rule 6 | +|---|---|---| +| queue | 88 | **87** | +| on-target | 81 | **81** (unchanged) | +| off-target | 7 | **6** | +| rows added | — | none | + +The single row it removes is **`CART_NS0027-B2M_2 chr1:28,580,332`**, dropped as +`systematic noise (external panel)`. Every on-target site is retained, and nothing is added or +re-attributed. + +**This changes a finding, so it is off by default.** Enabling it takes the off-target list from 7 to +6, and the site it removes is one of the two low-VAF hard cases. The evidence for removing it is +strong — 17 of ~46 unrelated donors show deletion noise at that exact locus, reaching 7.8% against +our 9.4% call — but it is an external heme panel judging a CAR-T sample, so the call belongs to +whoever is signing off on the cohort, not to a default. + +Cost: streams the 1 GB panel once per invocation, ~3 minutes. The file is BGZF and the directory is +writable, so `tabix -p bed` would make this instant; not done, to avoid writing into shared refdata +without asking. + +--- + +## Wiring into the pipeline (2026-08-11) + +Both rule 6 and the breakend filter were implemented as Python but were **not reachable from the +pipeline**: `modules/local/review_filter.nf` never passed `--snv-noise`, and `review_filter_bnd.py` +had no module, no subworkflow call and no params. A cohort rerun would have silently reproduced +`results_cart_ponfix`. That gap is now closed. + +### What changed + +| file | change | +|---|---| +| `nextflow.config` | `review_snv_noise`, `review_snv_noise_min_donors`; the `review_filter_bnd` / `review_bnd_*` / `review_sv_noise*` block | +| `nextflow_schema.json` | all of the above registered under `review_filter_options`; stale defaults corrected (`review_min_reads` 10→2, `review_min_vaf` 0.05→0.005, `pon_min_reads` 3→2) | +| `modules/local/review_filter.nf` | fourth input `path snv_noise`, threaded into **both** script invocations | +| `modules/local/review_filter_bnd.nf` | new process `REVIEW_FILTER_BND` | +| `conf/modules.config` | `REVIEW_FILTER_BND` publishes to `${params.outdir}/review` | +| `subworkflows/local/scge_analysis.nf` | `ch_snv_noise`, `ch_sv_noise`, and `ch_analysis_tsvs` shared by both processes | + +`ch_analysis_tsvs` is a `.collect()`, which yields a *value* channel, so the same staged list feeds +both review processes without being consumed by the first. + +The schema defaults were genuinely wrong before this, not merely untidy: nf-core lint compares +`nextflow_schema.json` defaults against `nextflow.config`, and all three had drifted when the gate +was lowered. + +### Verified before committing + +Both wired command lines were run against the 32 `results_cart_ponfix` analysis tables using the +exact arguments the modules emit. + +* `REVIEW_FILTER` with rule 6 → **87** rows (baseline 88), `is_target` 81 on-target / 6 off-target. + The one removed row is `chr1:28,580,333`; nothing added. Note this is the 1-based `end`; earlier + notes call the same site `28,580,332`, which is its 0-based start. +* `REVIEW_FILTER_BND` → **25** rows: 2,404 junctions → 36 gated → 25 queued (23 multi-cut deletions + in 7 samples spanning 413–125,747 bp, 2 deletions at a cut site). `dropped, DRAGEN systematic + noise: 0` — the WGS v3.1.0 panel flags none of the real junctions, which is the expected and + desired behaviour for the one safe panel. +* `nextflow run . -preview` with both panels wired builds the DAG with `REVIEW_FILTER` and + `REVIEW_FILTER_BND` present and completes successfully. +* `nextflow run . --help` lists every new param — the real test that schema registration is correct. +* `pytest tests/` → 30 passed. + +`-profile stub -stub-run` cannot be used as a wiring check here: the stub profile uses the local +executor without containers, so `PARSE_INPUT_SAMPLESHEET` (which has no stub block) dies on a +missing pandas long before the review processes. This is pre-existing and unrelated. `-preview` is +the check that works. + +### Defaults chosen, and why + +`review_filter_bnd` defaults to **true** — it is cheap and additive, producing a second queue file +without touching the indel result. `review_snv_noise` and `review_sv_noise` both default to **null**, +so the rules stay off unless a panel is passed. Rule 6 changes a finding (7 off-target → 6), and the +SV panel choice is dangerous enough to require a deliberate act: `IDPF_WGS_v3.0.0` flags 25/25 real +junctions and `FF_Heme_v3.1.0` flags 24/25, so wiring either would erase the entire breakend result. +Only `WGS_hg38_v3.1.0` is safe. If the breakend queue ever collapses toward zero, suspect the BEDPE. + +### Tabix: deliberately not done + +`load_snv_noise` streams the file line by line, so an index buys nothing without also adding a +pysam/tabix code path. Against a multi-hour cohort run the ~3 minutes (twice, since the module runs +the script for both the queue and the audit) is not worth a new code path plus writing into shared +refdata. Recorded as a known optimization, not a defect. diff --git a/docs/CALLER_INTEGRATION_PLAN.md b/docs/CALLER_INTEGRATION_PLAN.md new file mode 100644 index 0000000..1e3d62c --- /dev/null +++ b/docs/CALLER_INTEGRATION_PLAN.md @@ -0,0 +1,216 @@ +# Caller integration and breakend filtering — plan + +Four pieces of work, arising from the review of the 32-sample CAR-T WGS cohort. They are listed in +dependency order; item 2 is the one that unblocks the most. + +| # | Goal | Effort | Blocked by | +|---|---|---|---| +| 1 | Move review rules 1–3 into `find_edited_reads.py` | medium | — | +| 2 | Add a `control_bnd_reads` column | small | — | +| 3 | Breakpoint promiscuity rule for BNDs | small | 2 (to be useful) | +| 4 | Use the DRAGEN systematic-noise panels | medium | — | + +Everything below was measured on `results_cart_full/` (32 samples, median depth 205×) unless +stated otherwise. + +--- + +## 1. Move rules 1–3 into `find_edited_reads.py` + +### Why + +Two of the three already exist there in some form, and the duplication is a liability — the caller +and the filter can disagree about the same concept. + +| Review rule | Already in the caller? | +|---|---| +| 1. matched control clean | Partly. `-x/--max-in-control` (default 0) exists, but it *filters* rather than reports | +| 2. within N bp of a PAM | **Yes** — `-d/--max-mutation-distance`, default **25**. `review_filter.py` re-applies it at 10 | +| 3. ≥3 distinct indel lengths | No | + +Rule 2 is pure duplication: the caller already discards anything beyond 25 bp, then the filter +discards again at 10 bp. One knob, applied twice, in two files. + +### The `-x` problem, and why it matters here + +`-x/--max-in-control` defaults to `0` and **removes** any event with control support before the +event list is written. The consequence is that the per-event `control_alt_counts` field (field 11 +of `indel_info` and `bnd_info`) is **0 on every event, always** — verified across all 2,802 indel +events and 892 BND events in the cohort. It carries no information. + +The meaningful statistic is the site-level `control_indel_reads` column, which is computed +independently and is nonzero on 313 rows. That is the column the reporting fix repaired, and it is +what rule 1 actually reads. + +**Goal:** make the caller *report* control support rather than silently filter on it. Keep `-x` as +an opt-in, default it to off, and let downstream decide. A filter that erases its own evidence +cannot be audited. + +### Depth sensitivity — do not move rule 3 naively + +Rule 3 requires ≥3 distinct indel lengths at a site. **A site with 2 indel reads can produce at +most 2 distinct lengths, so it can never pass.** Measured: of the 837 cohort rows with exactly 2 +indel reads, the maximum `n_distinct_len` observed is 2, and **zero** pass rule 3. + +This makes rule 3 a *de facto* read-depth threshold wearing a different hat. It is safe at +`indel_reads ≥ 10` and meaningless below about 5. If it moves into the caller it must either carry +an explicit minimum-read guard or be expressed depth-independently — for example as a normalised +length-entropy rather than a raw distinct count. + +### What should *not* move + +Rules 4 and 5 must stay downstream. Both need the whole cohort: + +- The panel of normals is built by a separate pass over **all** unedited samples. `find_edited_reads.py` + runs per-sample, so hosting the PoN there means a two-pass design inside a single-pass script. +- The repeat mask is a static annotation and is cheap to apply once over a merged table. + +### Acceptance + +- `-d` is read from one place and applied once. +- `control_indel_reads` and `control_bnd_reads` are always populated regardless of `-x`. +- Rule 3 either carries a read-count guard or is replaced by a depth-normalised statistic, with the + cohort re-scored to confirm the 81-site queue is unchanged. + +--- + +## 2. Add a `control_bnd_reads` column + +### Why + +There is no site-level control statistic for breakends. `control_indel_reads` exists; +**`control_bnd_reads` does not.** Rule 1 — the workhorse, responsible for 49 of 79 drops (62%) on +indels — therefore has **no breakend equivalent at all**. + +Every one of the 2,403 BND events in the cohort reports control support of 0, which is an artifact +of `-x`, not a measurement. We currently cannot distinguish a breakend unique to the edited sample +from one present in the matched control. + +### Approach + +Mirror the existing indel path: count reads in the matched control that support the breakend +junction, at the site level, computed **before** any `-x` filtering. The junction has two ends, so +the natural statistic is reads spanning or clipped at either breakpoint that also carry the mate +signature. + +### Acceptance + +- The column is present and nonzero on at least some sites in a cohort known to contain germline SVs. +- Applied to the 32-sample cohort, it reduces the 2,403 BND events measurably. Any reduction is + informative; today the rule cannot fire at all. + +**This is the highest-value item on the list.** It is a small change that turns the single most +effective rule on for an entire event class. + +--- + +## 3. Breakpoint promiscuity rule + +### Why + +Breakend support is thin — median **1** supporting read across the cohort, only 36 of 2,403 events +have ≥3 — so read count alone does not separate signal from noise. But artifacts have a distinctive +shape: **one breakpoint partnering with many unrelated loci**, which is the signature of an +alignment hub rather than a real junction. + +Measured: binning breakpoints at 1 kb and counting distinct partner loci cohort-wide, +`chr1:246,009,982` has **45 distinct partners**. Ten bins of 1,718 have ≥5. + +### The rule + +``` +n_partners(bin) = |{ distinct partner loci for this 1 kb breakpoint bin }| +promiscuous = n_partners >= 5 +``` + +This is the breakend analogue of rule 3: not "do the reads agree on a length" but "does this +breakpoint agree on a partner". + +### Measured effect + +``` +2,403 BND events + → reads ≥ 3 36 + → within 10 bp of a PAM 29 + → not promiscuous (<5) 25 +``` + +It drops exactly the 4 interchromosomal CTLA4 artifacts — all of which share the +`chr1:246,009,982` hub — and nothing else. + +### What the 25 survivors are + +All same-chromosome, all on-target-to-on-target, in 8 samples (ARID4A, BRAF, IKZF2, KLF12, PDCD4, +PDE7A, RXRB, ZEB2), spanning **413 bp to 126 kb**, median 3 kb. + +These are **multi-cut deletions**: two cuts from the same guide's target set, with the intervening +segment excised. The pipeline has been emitting them all along without interpreting them. They +should be reported as an editing outcome in their own right, not as off-target candidates. + +> **Superseded 2026-08-20 — these are inversions.** Two cuts from the same guide's target set, with +> the intervening segment **flipped and re-ligated** rather than excised. Every queue row is the +> inverted adjacency (`+-`/`-+`), each event shows both junctions of the reciprocal pair, and no +> collinear (deletion-type) junction exists at any of the eight cut pairs. The conclusion that they +> are an editing outcome in their own right, and not off-target candidates, is unchanged. + +### Acceptance + +- Promiscuity is computed per run and written alongside the BND table. +- On-target-to-on-target junctions are classified as multi-cut deletions and reported separately + from off-target breakend candidates, the same way on-target sites are exempted from rules 4 and 5. + +--- + +## 4. DRAGEN systematic-noise panels + +Location: `/storage2/fs1/dspencer/Active/shared/refdata/hg38/dragenfiles` + +### SV noise — measured coverage of our breakends + +| File | Records | Either-end hit @200 bp slop | +|---|---|---| +| `WGS_hg38_v3.1.0_systematic_noise.sv.bedpe.gz` | 311,395 | 13.4% | +| `IDPF_WGS_hg38_v3.0.0_systematic_noise.sv.bedpe.gz` | 2,626,364 | **89.6%** | +| `WGS_FF_Heme_hg38_v3.1.0_systematic_noise.sv.bedpe.gz` | 2,195,842 | 80.4% | + +BEDPE columns: `chrom1 start1 end1 chrom2 start2 end2 name score strand1 strand2 precise|imprecise` + +### The trap + +**Do not apply IDPF naively.** At 200 bp slop it flags 90% of all breakends — including **all 25 of +the real multi-cut deletions**. Used as a blacklist it would delete the entire finding. + +The small `WGS_hg38_v3.1.0` panel is the specific one. Any use of these files needs: + +- tight slop (test 0 and 50 bp before 200), +- both-ends matching rather than either-end, +- an on-target exemption, exactly as rules 4 and 5 have. + +### Goal + +Treat the DRAGEN panels as a **supplement** to the run's own PoN, never a replacement. The +self-built PoN is guide-matched; these are generic. The existing `pon_coverage` guard already +distinguishes "this panel says clean" from "this panel does not cover these coordinates", and the +same discipline applies here. + +### Open question — the SNV noise BED + +`IDPF_WGS_hg38_v.2.0.0_systematic_noise.snv.bed.gz` (1 GB) is untested. It is an SNV panel, so the +prior is that it will behave like the GATK 1000G PoN did — flagging real edits alongside artifacts, +because an SNV-artifact map is not an indel-artifact map. That test was already run once for +GATK and it failed on exactly those grounds. + +**Investigate, but expect a negative result**, and measure it against real edits before adopting: +the acceptance bar is that it flags artifacts *without* flagging any of the 77 known on-target +sites. + +--- + +## Summary of what is worth doing first + +1. **`control_bnd_reads`** — small change, turns on the most effective rule for a whole event class. +2. **Promiscuity + multi-cut deletion reporting** — no new data needed, and it surfaces a finding + already sitting in the output. +3. **Caller consolidation of rules 1–3** — real cleanup, but carries the rule-3 depth trap. +4. **DRAGEN panels** — useful as a supplement, dangerous as a blacklist, and the SNV BED is likely + a dead end worth ruling out cheaply. diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md new file mode 100644 index 0000000..633e239 --- /dev/null +++ b/docs/HANDOFF.md @@ -0,0 +1,412 @@ +# Handoff — off-target arm, `feat/offtarget-wgs` + +**Last updated:** 2026-08-21 · **Branch:** `feat/offtarget-wgs` · **Not yet merged to `dev`.** + +This is the operational knowledge that was not otherwise written down: how to actually run the +thing, the landmines that cost days, which numbers are real, and what I would do next. The +scientific write-ups live in `docs/OFFTARGET.md`, `docs/NOISE_MODEL*.md` and `docs/PANEL_AS_FILTER.md` +— this file deliberately does not repeat them. + +--- + +## 1. State of play + +The pipeline runs end to end on real cohorts. Two arms, both working: + +- **Indel arm** — `find_edited_reads.py` → `review_filter.py`. Ran green on all 32 CAR-T WGS + samples (2026-08-07) and on the 8 AAVS1 samples. +- **Breakend arm** — SA-tag split reads → `review_filter_bnd.py` → `bnd_snapshots.py`. Completed + 2026-08-16, corrected 2026-08-20 (see §5). + +Everything is committed and pushed. The working tree is clean. + +**The one outstanding action: open the PR.** `feat/offtarget-wgs` is ~50 commits ahead of `dev` +and nothing merges it. + +--- + +## 2. How to run it + +### 2a. The default workflow (indel + breakend review) — SLURM + +This is the non-obvious one. **The review arm lives in `subworkflows/local/scge_analysis.nf`, +which is the DEFAULT workflow (`main.nf:36`), not `-entry OFFTARGET`.** So `run_offtarget.sh` is +the wrong wrapper, and every other `run_*.sh` in the repo is LSF/bsub. The working recipes are +durable at **`logs/run_cart_bnd.sh`** and **`logs/run_cart_nopon.sh.recovered`**: + +``` +sbatch --partition=condo-dspencer --account=compute2-dspencer ... + nextflow run main.nf -profile ris2,apptainer \ + -work-dir /scratch2/fs1/dspencer/abonney/cartfull_work -resume \ + --input --outdir --run_alignment false \ + --offtarget_tagged_bam true --review_repeat_beds ... --review_snv_noise ... --review_sv_noise ... +``` + +Everything else (`off_target_threshold`, `transgene_*`, `scge_report_qmd`, `run_analysis`) comes +from `nextflow.config` defaults. `params.queue` / `job_group_name` in old params dumps are LSF +leftovers that `ris2` never reads — do not conclude from them that a run was LSF. + +**Partition:** `general-cpu` is NOT permitted for this group; use **`condo-dspencer`**. Both the +wrapper *and* the child jobs Nextflow submits need it — pass `--slurm_partition condo-dspencer` +(`nextflow.config:42`, feeds the `ris2` profile's `process.queue` at `:345`). Account `compute2-dspencer`. +Cancelling the parent job does **not** kill the `nf-*` children; `scancel` them explicitly. + +### 2b. Environment + +- Compute nodes have java 17 at `/usr/bin/java`; **the JupyterLab exec node does not** — that is + why nextflow tiers SKIP there. There is **no `java17` module**; `module load nextflow/25.10.4` + brings its own OpenJDK 17. +- Modules: `apptainer/1.4.5`, `nextflow/25.10.4`, `labtools` (this is how you get `Rscript`). +- `export NXF_SINGULARITY_CACHEDIR=/scratch2/fs1/dspencer/apptainer_cache`, + `export APPTAINER_BINDPATH=/storage2,/scratch2,/home/`. +- **venvs on `/storage2` are not portable across nodes** (`bin/python3 -> /usr/local/bin/python3` + is per-node). Use the container for anything needing pandas/sklearn. +- `bash script.sh` does not inherit the `module` shell function; re-source `/etc/profile.d/lmod.sh`. +- **`sbatch --output` must point at shared storage, never `/tmp`.** `/tmp` is node-local: the log + lands on the compute node and is invisible from the submit host — indistinguishable from "the + job never started". Use `/logs/.%j.log`. This cost a full misdiagnosis once. + +### 2c. Tests + +`./run_offtarget_tests.sh` is container-first — pulls `ghcr.io/dhslab/docker-scge-offtarget:260710` +and runs the python tiers inside it (exact prod deps incl. sklearn 1.8.0; pytest injected as a +pure-python overlay since it is not in the prod image). The Nextflow stub tier uses `-profile stub` +(local executor), **not** `-profile ris` (LSF, fails off-scheduler). + +`-profile test` **alone fails** (no container engine → `ModuleNotFoundError: pandas`); the +`singularity`/`apptainer` profile is required. + +Current state: **nf-test 8/8 green. pytest has 3–6 pre-existing failures** in +`test_offtarget_glue.py` — the missing module is **`pyranges`, not edlib**, plus some `tagged_bam` +cases. They fail with or without any recent change (verified by reverting). Run pytest *inside* the +container to retire them; that has not been done. + +--- + +## 3. Landmines + +**Ranked by how much time they cost.** + +1. **Never pass `-u` / `--unevaluable-reads` to `find_edited_reads.py`.** It writes a debug log at + **0.5–1 TB per sample**. It filled `/storage2`, then blew the *shared* `dspencer` group quota on + `/scratch2` (9.1 TB across 13 concurrent tasks), and killed three CAR-T runs. It is write-only, + not an emitted output, not consumed downstream. Now gated behind + `params.offtarget_ecs_unevaluable_log`, **default false**. Leave it false. + `/scratch2/fs1/dspencer` has a shared group quota (~9–10 TB); `df` shows the whole 1.5 PB + filesystem and hides it. GPFS accounting lags 1–2 min after you delete. + +2. **Editing ANY file in `bin/` invalidates the entire `-resume` cache.** Nextflow stages the whole + `bin/` directory into every task and folds its hash into the task cache key. A one-line change to + one script forces a full cohort re-execution — not just the tasks that call it. Verified: five + changed files in `bin/`, everything else untouched, run reported **cached: 0**. Budget a full + re-run (~5 h for the 32-sample CAR-T cohort) whenever `bin/` is touched. Do not promise + "upstream tasks will still cache". + +3. **The RIS SLURM controller drops connections, and that kills whole runs.** A failed *submission* + is fatal to the run, not just to one task — one `Connection reset by peer` lost 160 pending tasks + after 104 had succeeded. Nextflow's default `executor.retry.reason` matches only + `Socket timed out on send/recv operation`. The **`ris2` profile widens it** to cover + "Connection reset by peer" / "Unable to contact slurm controller" / "Connection refused". Copy + that pattern into any other long grid run here. If `squeue` itself returns + `Unable to contact slurm controller`, the outage is cluster-side — wait, do not resubmit. + +4. **`-stub-run` does not execute `bin/*.py`.** It only touches output files, so it cannot catch a + Python runtime error. A real run is the only check that does. This is how a `verdict()` arity + change (2→3 return values) shipped past `py_compile` *and* the stub run and broke the + genome-wide arm two minutes into a cluster run. Guard added: + `tests/test_offtarget_glue.py::test_verdict_callers_unpack_three_values` walks the AST of every + `bin/*.py`. + +5. **A Nextflow driver does not exit when the pipeline errors.** It prints "Finishing pending tasks + before exit" and drains every in-flight task, which can take hours. `squeue` is the truth, not + the log. Two concurrent runs from the same launch dir share `.nextflow/` and will collide — use + `sbatch --dependency=afterany:` to serialize. Also: running stray `nextflow` commands + (`config`, `clean`, stub) in a **live launch dir** rotates `.nextflow.log` and can disturb the + running head. + +6. **Verify the artifact, not the exit code.** Five pre-existing bugs on the shared analysis path + all produced green-looking states with missing or empty outputs (missing `+x` bits → exit 126; + a hardcoded circos version → exit 127; quarto writing its cache to a read-only `$HOME`; + `pip install --user` at task time; an Excel writer whose openpyxl fallback was decorative and + silently skipped every plot). All fixed. Check file counts and embedded-image counts. + +7. **`bin/*.py` need the executable bit.** Nextflow puts `bin/` on PATH and invokes scripts bare. + `git` records 100755 but `core.fileMode` is off here, so `git status` is silent when the bit is + lost. This has bitten both this repo and `dragenflow`. + +--- + +## 4. Truth sets — which numbers are real + +**This is the single most important section.** Most of the "bad results" in this project's history +were truth-set artifacts, not detection failures. + +### Never validate against the ECS threshold label + +`recall_vs_vaf.py` used to score against `ecs_is_edit`, whose denominator counted **any** nonzero +ECS indel fraction — 47,170 "positives" below 0.5% VAF in the CAR-T run. That produced a reported +recall of ~2% for a pipeline that was actually at 90%. Same trap on AAVS1: the ~3% figure is a +germline-contaminated denominator (of 116 sites above 5% VAF, **94 carry the same indel in the +matched normal**, many homozygous). + +**Always validate against manual review.** + +### The real truth sources + +| cohort | file | notes | +|---|---|---| +| CAR-T ECS | `Manual Indel Review/cart_ecs/cart_ecs_merged.csv.gz` | `manual_review==1`; reaches 2.48% VAF; **positives-only** | +| CAR-T WGS | `Manual Indel Review/cart_wgs/cart_wgs_merged.xlsx`, sheet `gold_wgs` | two-class but ≥5% VAF only | +| AAVS1 | `crispr_ml/AAVS1_training_{tp,tn}.tsv` | **read-level**, not site-level | + +**AAVS1 gotchas:** the files are ragged — read with **positional** `usecols=[0,1,2]`; named usecols +silently yields an empty frame. Collapses to **2 TP sites, 6037 TN sites**; both TPs +(`chr19:55,115,732` and `chr19:55,115,752`) are **on-target**. Both TP sites also appear in the TN +set (an edited site contains reference reads too) — **subtract them or you get 2 phantom FPs**. +Join on the table's **`end`** column, not `start` (`start` is 0-based; `POS == end == pam_positions`, +1149/1149 exact — no slack needed, ±2 bp over-joins). + +**CAR-T gotchas:** join on **guide**, never `sample_name` — gold says `NS0011-ABTB1`, the pipeline +says `ABTB1-KO-DNA`, and joining on sample name silently drops 15 of 25 gold samples. Reuse +`guide_from_sample` + `GUIDE_ALIAS` from `validate_recall.py`. The `guide` column in +`wgs_hotspot_scores.csv` is a **recurrence proxy from `add_recurrence()`**, not a join key — pass +`--training` or `--samplesheet` or the denominator silently empties. Truth-side repairs needed: +sheet typo `CTLA41`→`CTLA4`, and `CART_NS0011-CREBRF.edited_reads.xlsm` has a corrupted `chrom` +cell (`"c"` for chr5:173,090,439). + +**`is_target` is not truth** — 10 on-target sites were reviewed and rejected. + +### Rebuilding the curated WGS label + +`bin/build_curated_wgs_label.py`. The manual review was **not** positive-unlabeled: the process was +take every indel with `indel_fraction >= 0.05` **AND** `indel_reads >= 10`, then adjudicate every +row by eye. So **inside that stratum a blank `manual_review` means REJECTED**, and those rejects are +the best negatives available — they fooled a rules filter but not a human. Confirmed by the data: +among the 53 confirmed WGS edits the minimum `indel_fraction` is 0.0561 and the minimum +`indel_reads` is 11, both just inside the stated cut-offs. `indel_count >= 10` is the **wrong** +column (loses 4 confirmed) — `indel_count` is allelic diversity, `indel_reads` is read support. + +### Numbers safe to quote + +- **CAR-T recall 52/52 = 1.000** vs manual review (49/49 on-target, 3/3 off-target). Model score + alone gives 47/52; the **high-evidence rescue supplies the last 6**. +- **Off-target review burden falls 20.8×** (83 gated → 4 kept) **with zero on-target loss** + (77 gated → 77 kept). *All 79 drops are off-target rows.* +- **Precision 0.889** — but say "production configuration", and see the caveat below. + +### Numbers that are traps + +- **Do NOT quote "99,238 → 81".** That credits the five rules with the evidence gate's work. The + gate (`bin/review_filter.py:334`, `indel_reads >= min_reads & indel_fraction >= min_vaf`) does 99,238 → 160 by + itself; the rules only ever see the 160. That gate is *exactly the filter the lab already applied + by hand in Excel*, so the honest baseline is the post-gate count — **160** for the 32-sample + cohort, **238** for the 25-sample one. "238 reviewed by hand" is defensible; "238 candidates" is + not. +- **0.877 vs 0.889 is not a conflict** — different rows of the `docs/NOISE_MODEL_EXPERIMENT.md` arm + table. 0.877 = the PoN-only / no-cohort-equivalence arm; **0.889 = production**. Never quote + either bare. Retained edits are 64/64 in every arm. +- **Precision 0.889 predates the current caller.** It was measured on `results_cart_ponfix` + (2026-08-13) where the same 99,238 rows and the same gate passed **1,498** rows; the current + caller passes **479**. `find_edited_reads.py` changed. **It has not been re-adjudicated against + the current 86-row queue.** Say so whenever quoting it. +- **Depth is ~202–205×, not 60×.** The "16% VAF floor at 61×" belongs to a *different* dataset + (the WGS negative control) and must not be quoted for the CAR-T cohort. At 202× the pipeline's + 2-read/0.5% gate is an effective floor of **0.99% VAF**. The lab's historical 10-read hand filter + is **4.95%** — *that* is where "5% detector" comes from, and it describes the old manual + threshold, not this pipeline. +- **A BND queue row is not an event.** The caller reports each junction from both ends, at ±4 bp + jitter, under both orientations. The CAR-T cohort's **25 rows are 8 junctions**. Never quote a row + count as an event count, and never quote a row's `reads` as event support — ARID4A's rows say 3–4 + each; the junction carries 18. +- **AAVS1's "8 real edits" are 2 distinct sites seen once per sample**, not 8 sites. + +--- + +## 5. The breakend result (corrected 2026-08-20) + +The PI uses "breakend" to mean *translocation*. The answer to "are any of these translocations?" is +**no — all 8 are intra-chromosomal.** + +Checking that exposed a shipped labelling bug: `review_filter_bnd.py`'s classifier keyed on +`(is_target, far_end_on_target, interchromosomal)` and **never read `strands`**, so it called +everything "multi-cut deletion". Every queue row is `+-`/`-+` — the **inverted** adjacency. +**The 8 junctions are inversions.** + +Two independent confirmations: (1) all 8 events carry **both junctions of the reciprocal pair** +(support balance 0.43–0.80), which a deletion cannot produce — it makes one junction; (2) across +every raw breakend record at the 8 cut pairs, unfiltered, there are **0 collinear junctions vs 5–16 +inverted**, so the deletion product is absent, not sub-threshold. Structural reason the old label +was wrong by construction: a same-chromosome, **same-strand** split read is resolved to DEL/DUP/INS +at `find_edited_reads.py:420` and never becomes a BND — so a same-chromosome BND can *only* be +inverted. + +**The coverage test is underpowered — do not cite it.** At 5–20% allele fraction the expected drop +is 3–10% and flank scatter is ±10%; it came back 0.87–1.01, uninformative. + +**Biology:** 7 of 8 target files carry two different guides against the KO gene (BRAF has one), so +these are dual-guide events where the intervening fragment was **flipped and re-ligated** rather +than lost. **No junction anywhere touches TRAC or TRBC** despite both being present in all 8 target +files — that is a real negative result about the two guides common to every construct. + +**Still open:** `bin/bnd_from_indels_to_vcf.py` was fixed (it wrote **zero records in every run +ever** — doubled escapes meant the header never split) and now emits **1,022 records across 32 +samples**. But **that does not populate the HTML report, and I said at one point that it did.** +`bin/make_scge_report.qmd` has **zero references to `bnd_vcf`**; the report's SV panel renders +`tables.on_target_sv_transgene`, an unrelated transgene-junction table that is empty in all 32 +samples. Two independent defects; only the VCF one is fixed. **Surfacing breakends in the report is +a QMD change with the data already waiting** — this is the single highest-value small task left. + +--- + +## 6. The noise model / panels + +Full treatment in `docs/NOISE_MODEL.md`, `docs/NOISE_MODEL_ASSUMPTIONS.md`, +`docs/NOISE_MODEL_VALIDATION.md`, `docs/PANEL_AS_FILTER.md`. Operational points only: + +- **The matched-control beta-binomial reproduces the panel-of-normals exactly** with no cohort + required. The PoN is gone. +- **`AQ_MIN` is 5, not 30.** The depth floor rescales AQ; AQ≥10 starts costing confirmed edits. +- **The clean-control trap:** a control with 0 alt reads at depth *d* bounds background at ~1/*d*, + not 0. `apply_depth_floor` handles it. Currently masked by the `VAF>=0.005` gate — **it stops + being masked if that gate is ever lowered.** +- **Omitting `--pon` does not disable rule 4** — it falls back to cross-guide recurrence. Use + `--max-guides 9999` to actually turn it off. +- **`review_filter.py`'s own defaults are 10 reads / 5% VAF, but the pipeline passes 2 / 0.005.** + Any offline rerun must pass them explicitly or it will not reproduce the baseline. +- **Cross-guide recurrence needs all guides in ONE invocation.** Single-guide runs silently get no + rule 4. It now warns; `--strict-fallback` makes it fatal. + +### Two different params, only one reaches rule 4 — this caused real confusion + +- **`params.sv_noisefile`** (`nextflow.config:213`) → **DRAGEN** `--sv-systematic-noise`. The + breakend arm never sees it. +- **`params.review_sv_noise`** (`nextflow.config:172`) → **rule 4**, default **null = OFF**. + +⇒ `dropped, DRAGEN systematic noise : 0` in a run means **the rule did not run**, not that nothing +matched. + +**`sv_noisefile` stays on IDPF v3.0.0. This is the PI's decision and the question is CLOSED.** It +is harmless for everything in these docs — the breakend caller reads SA-tag split reads only, never +DRAGEN SV calls. It only shapes DRAGEN's own `*.sv.annotated.vcf.gz` and the report SV table +(~56% of passing calls suppressed). + +**The real risk to guard: do not wire IDPF into `review_sv_noise`.** It flags **25/25 real +junctions** at every slop and would erase the entire breakend finding. IDPF covers 62.7% of the +genome, so its 85.9% flag rate is exactly its 86.1% coverage null (1.00×) — and it points +*backwards*, flagging on-target real edits more than off-target (OR 0.45, CI excludes 1). Warning +sits at `nextflow.config:160-171`. + +**The SNV/indel panel is the opposite case and does work.** `params.snv_noisefile` +(`IDPF_WGS_hg38_v.2.0.0_systematic_noise.snv.bed.gz`) is a *different file*. On AAVS1: 443 +candidates clear the gate, **54 flagged (12.2%), all 54 off-target, 0 confirmed edits flagged**, +212 left to review. It works because it is **specific** — only 2.05M of 97.85M records qualify +(≥3 donors + an indel-capable allele) = **≤0.332% of the genome**, so 12.2% is ~37× the null. +One-liner: *a noise filter is only useful if it is specific — ours is on indels, the SV one is not.* + +--- + +## 7. Open threads, ranked + +1. **Open the PR.** Nothing else on this list matters if the branch is never merged. +2. **Surface breakends in the HTML report** (§5). Small QMD change, data already produced. +3. **Retire the pytest failures** by running the suite inside + `ghcr.io/dhslab/docker-scge-offtarget:260710`. The missing module is `pyranges`. +4. **The model does not beat plain rules on AAVS1** (precision 0.067 vs 0.095). The 40× review-queue + win is real but it comes from **`cut_dist`, which is a rule**, not from the model. Be honest + about this. +5. **The ceiling is the label, not the features or the model.** Swapping only the training label + (7 features held fixed) costs 6× precision. A 10-feature curated model improves AAVS1 precision + 2.1× (28→12 FPs) **but regresses CAR-T recall 52/52 → 47/52**, so it was *not* shipped — + `assets/models/wgs_shape_model.pkl` is still v1. The 5 misses all sit below the rescue's + `indel_frac >= 0.15` floor. Two concrete next experiments: (a) draw positives from the ECS review + (all 56, including the 7 below WGS 0.05) with negatives from the WGS stratum — the current label + draws both classes from the WGS stratum and under-represents low-VAF positives; (b) lower or + depth-adapt the rescue floor. Also try fewer features given only 69 positives. + **A CNN is the wrong move** — more capacity fits the bad label better and performs worse. +6. **The hard false-positive set.** GM24385-unedited scored at AAVS1 hotspots gives **175 certain + FPs** (3.44%), no review needed. Of the 21 low-VAF ones, **7 survive every rule we have** — + chr6:29918619, chr7:73852004, chr8:10469359, chr8:142037418, chr11:113381806, chr12:116647121, + chr22:48757172. That is the model's actual job and its evaluation set. (chr22:48757172 has 18 + distinct indel lengths at cut_dist 8 with 2,769 reads — indistinguishable from a real edit by any + rule.) Note this also **tempers the `cut_dist` claim**: against a proper negative control the + median is 14 bp and **40.6% are within 10 bp**, so `cut_dist<=10` removes 59%, not the ~82% seen + against the curated TN set. +7. **The well-posed WGS sensitivity target, label-free:** reaching real 5% sensitivity in WGS needs + `reads>=3`, which costs **9 → 34 artifact FPs/sample**. The model's job is to win that ~4× back + at fixed sensitivity. Measurable with no manual review. +8. **The uncorrected-ECS rerun is verified GO but unexecuted.** See §8. + +--- + +## 8. The uncorrected-ECS rerun (verified, not run) + +Realign the AAVS1 ECS capture with UMI consensus disabled, to get a noisy WGS-like training set +labelled from the corrected run. **Verified 2026-07-31: the SLURM stub passes and the diff is +exactly one flag.** + +- Route: **AWS Batch via `dragenflow`**, `-profile dragenaws,alignonly,idtumi -c slurm.config + --readfamilysize 1`. Canonical checkout + `/storage2/fs1/dspencer/Active/spencerlab/abonney/git_runs/dragenflow`. +- Queue `dragen-queue_v4-4-6` **tested end-to-end from the SLURM node** — job SUCCEEDED, container + reports `dragen Version 13.021.779.4.4.6`, byte-identical to the corrected run. Only `-profile ris` + (LSF; `bsub` does not exist here) must become SLURM. +- **Pass `cpus 24` / `memory 240.GB` explicitly** or jobs stick in RUNNABLE forever + (`MISCONFIGURATION:JOB_RESOURCE_REQUIREMENT` — the job definition's default 256000 MB does not fit + an f2.6xlarge once ECS overhead is taken). +- **Use `readfamilysize = 1`, NOT `umi = null`.** `params.umi` is overloaded: when it is set the + pipeline runs fastp for adapter trimming; when null, DRAGEN does it instead. Unsetting `umi` + silently swaps trimmers *and* leaves ~3× PCR duplicates uncollapsed. `readfamilysize=1` changes + exactly one flag: `--umi-min-supporting-reads 3` → `1`. +- **Cost is not the risk** (~$12 incremental for the original Jan run; ceiling ~$30–50). **Staging + is**: a real run uploads ~853 GB to S3, and fastp writes a similar volume locally first (~900 GB + scratch). Do not test the queue with a full `-stub-run` — submit a trivial job directly. +- **Data gain is ~3×, not 15×.** 7.4× in raw reads, but independent molecules (families) are + 300,363,223 vs 99,904,287 emitted = **3.0×**, and only the molecule ratio bounds independent draws. + +--- + +## 9. Assets and reference data + +- Container: `ghcr.io/dhslab/docker-scge-offtarget:260710` (matplotlib 3.10.8, pysam 0.24.0, + sklearn 1.8.0 — **the pin must match the pickle**). `docker-scge:latest` has the caller deps but + **no matplotlib**, which is why figures run in the other image. +- `ghcr.io/dhslab/docker-casoffinder-bulge:latest` — pushed and working. +- Lab images all live in **one repo, `dhslab/dhslab-docker-images`**, one per `docker-*/` dir; + a push to main auto-builds any changed `**/Dockerfile` to `ghcr.io/dhslab/` with + `:latest` + `:YYMMDD`. **The directory name becomes the image name** the modules pin. +- CRISPRme prebuilt index (6.8 G, ~17 min to build): + `/storage2/fs1/dspencer/Active/clinseq/projects/scge/data/refdata/crisprme_hg38/`. **Reuse gotcha:** `complete-search` resolves `genome_library` + relative to **CWD**, not to `--genome` — an absolute `--genome` from a foreign CWD silently + *rebuilds* the index. `crisprme.nf` symlinks `Genome` and `genome_library` into the task CWD. +- Cas-OFFinder **3.0.0 does bulges natively**; the 2016 `cas-offinder-bulge` wrapper is obsolete and + crashes on v3. Call `cas-offinder C ` directly. Also: Nextflow launches apptainer with + `--no-home`, so pocl cannot write its kernel cache and dies with "No OpenCL devices found" — fixed + by `export POCL_CACHE_DIR="${PWD}/.pocl_cache"` in the module. +- DRAGEN noise files: `/storage2/fs1/dspencer/Active/spencerlab/refdata/hg38/dragenfiles` (this is + the one `nextflow.config` points at; a second copy exists under `Active/shared/refdata/hg38/`). +- References differ by cohort: AAVS1 ECS used `hg38_mgi_patch.fa` + refdir + `dragen_hg38_cg_rna_cnv_v4.4.6`; the CAR-T/WGS side uses `hg38_PLVM_CD19_CARv4_cd34.fa`. + **Do not mix them.** + +--- + +## 10. Things I got wrong, so you don't re-derive them + +- I said the 8 junctions were deletions. **They are inversions** (§5). +- I said the SV VCF fix populated the HTML report. **It does not** (§5). +- I said unedited WGS controls did not exist. **They do** — DRAGEN tumor/normal writes the normal to + `.cram` and the tumor to `_tumor.cram`, named after the output prefix rather than + its contents. Three donors: `CD34-CART-DNA` (21 samples), `CART_NS0027-unedited` (8), + `CART_NS0065-unedited` (3). +- I concluded "assumption 8 fails" in the noise-model audit. **That was a selection artifact** from + pooling 3% of rows selected for carrying a called indel. Assumption 8 holds where testable. +- The 11.7× clean-locus gap is **5 loci carrying donor-private germline** the caller had already + suppressed — not a model defect. +- `control_indel_reads` is **not** constant-0, but it is untrustworthy: `--max-in-control` defaults + to 5 (not 0), and the column is a floor-rounded *mean* over only variants that passed that filter, + so it silently drops the strongest germline evidence. The per-event `control_alt_counts` (field 11 + of `indel_info`) **is** 0 by construction and carries no information. +- **The test that settles coordinate questions here:** run the caller with `--edited-bam` and + `--control-bam` set to the **same file**. Every called event must then be control-supported, so + anything escaping `-x` is a provable miss. Label-free, ~3 min on a 92-site subset. Two careful + code readings gave the wrong answer on this; this test gave the right one first try. diff --git a/docs/NOISE_MODEL.md b/docs/NOISE_MODEL.md new file mode 100644 index 0000000..410ca10 --- /dev/null +++ b/docs/NOISE_MODEL.md @@ -0,0 +1,270 @@ +# The background model, and exactly how AQ is computed + +This is a methods document. It states where the background rate comes from, what AQ is as a +statistical object, and what the model does and does not claim. It is deliberately explicit about +the name of the distribution at every step, because the model has been described verbally more +than once and the verbal version keeps losing the part that matters. + +Companion documents: + +- [`NOISE_MODEL_VALIDATION.md`](NOISE_MODEL_VALIDATION.md) — does the model actually describe the + data? (calibration, model comparison, sequence context, the depth floor) +- [`PANEL_AS_FILTER.md`](PANEL_AS_FILTER.md) — can the DRAGEN systematic-noise panels replace the + matched control? + +Implementation: [`bin/noise_model.py`](../bin/noise_model.py). All numbers below are from the +32-sample CAR-T cohort in `results_cart_bnd` (2026-08-17). + +--- + +## 1. The sampling process is Binomial + +At a locus covered by `n` reads, each read either carries the alt allele or does not. Treat the +reads as independent, each with probability `p` of carrying it — a Bernoulli trial per read — and +the count of alt reads is + +``` +k ~ Binomial(n, p) +``` + +This is the machine drawing reads. It is the uncontroversial half of the model, and nothing below +disputes it. + +## 2. `p` is not one number, which is why the compound is Beta-Binomial + +The error rate is not a constant of the assay. It varies from locus to locus with what the +polymerase and the aligner are physically doing at that sequence — slippage in a homopolymer run +is the textbook case, and [it is measured on this cohort](NOISE_MODEL_VALIDATION.md#4-sequence-context): +sites inside a ≥9 bp homopolymer carry control indel evidence at **33× the rate seen in unique +sequence** (0.0392 vs 0.0012). + +So `p` is itself a random variable. Model the spread of rates with a continuous distribution on +(0,1) — the Beta — and compound: + +``` +p ~ Beta(α, β) +k ~ Binomial(n, p) ⟹ k ~ BetaBinomial(n, α, β) +``` + +**The Beta is the mixing distribution over rates. It is not a model of the read counts.** It is +what carries the overdispersion that a fixed-`p` Binomial cannot represent, and the overdispersion +is the entire point: the output of this model is a tail probability, and a tail is exactly where +the difference between "one rate" and "a distribution of rates" shows up. + +### Why a Binomial alone fails, in one line + +It assumes every locus and every sample share one rate. At a locus where 1 of 46 panel donors +showed 17% noise and 45 showed nothing, a Binomial uses `p = 0.0037` and declares a 5% observation +overwhelming. + +That is not a hypothetical. Under a null where every observation is noise by construction (see +[the validation doc](NOISE_MODEL_VALIDATION.md#3-calibration)), the Binomial produces **5.2× more +p-values below 0.001 than it should**, and fails a Kolmogorov–Smirnov test against Uniform with +D = 0.140. The Beta-Binomial sits at D ≈ 0.004 on the same test — a 35× smaller deviation, stable +across random seeds. (The test uses randomised p-values, so its *p*-value is seed-dependent and +only D should be quoted; the validation doc reports the full seed sweep.) + +![calibration](images/noise_calibration_qq.png) + +## 3. Where α and β come from + +Two steps, and both are in `noise_model.py`. + +**Step 1 — the global prior, fitted once per run.** `fit_global_prior()` takes every control +observation in the input (`control_indel_reads` out of `control_reads`, one pair per site-row) and +fits a Beta by **method of moments**: match the mean and variance of the observed per-observation +control VAFs. On this cohort: + +``` +Beta(a0 = 0.002034, b0 = 1.63924) prior mean = 0.00124 +``` + +Note `a0 < 1 < b0`. That makes the density **strictly decreasing** — infinite at `p = 0`, zero at +`p = 1`. The prior is spike-at-zero shaped with a heavy right tail. This matters and comes back in +[§2.1 of the validation doc](NOISE_MODEL_VALIDATION.md#1-the-two-populations). + +**Step 2 — the per-locus update, which is conjugate.** The Beta is conjugate to the Binomial, so +observing `control_alt` alt reads out of `control_depth` at a locus updates the prior in closed +form (`control_posterior()`, `noise_model.py:191-217`): + +``` +α = a0 + control_alt +β = b0 + (control_depth − control_alt) +``` + +Which controls are pooled is the `--baseline` switch: `matched` (this sample's own control — what +ships), `loo` (the other samples' controls), `both`, or `panel` (external panel, no controls). + +**Step 3 — the depth floor** (`apply_depth_floor()`). A control with zero alt reads at depth `d` +does not show the background is ~0; it shows it is below roughly `1/d`. The floor bounds the +posterior *mean* at `1/control_depth`, holding `α + β` fixed so only the location moves. It raises +the background on **306 of 479** gated rows in this run. Whether it is a principled step or a patch +on a mis-specified model is exactly [what the validation doc tests](NOISE_MODEL_VALIDATION.md#5-the-depth-floor). + +## 4. AQ, stated exactly + +``` +AQ = −10 · log₁₀ P(X ≥ k | n, α, β), X ~ BetaBinomial(n, α, β) +``` + +**AQ is the Phred-scaled tail probability under the null hypothesis that the observation is +background.** It is a survival function — a p-value expressed in decibels — and it measures +evidence *against* H₀, on the same log scale as every other quality score in genomics. + +> ⚠️ **AQ is not a likelihood ratio.** It is a p-value. The two are different objects and the +> distinction is not pedantic: a p-value asks "how extreme is this under H₀?" and never mentions +> the alternative, whereas a likelihood ratio compares two named hypotheses. A genuine likelihood +> ratio does appear in this work — in [§6](#6-distance-from-the-cut-as-a-spatial-prior), where the +> spatial model forms `P(d | signal) / P(d | background)`. Keep the two apart when describing this. + +### AQ to probability — the table to have in the room + +| AQ | P(X ≥ k \| H₀) | reading | +|---:|---:|---| +| 0 | 1.0 | certain under background | +| **5** | **0.316** | **the shipped cut** — ~1 in 3 by chance | +| 10 | 0.1 | 1 in 10 | +| 20 | 0.01 | 1 in 100 | +| 30 | 0.001 | 1 in 1,000 | +| 60 | 10⁻⁶ | 1 in a million | + +**The shipped threshold of AQ < 5 is extremely permissive.** It is not a p < 0.05 test — it drops +only observations that background explains *at least a third of the time*. That is why it removes +exactly **1 of the 479 gated rows** in this cohort. Anyone reading "the noise model filters the +calls" should know it is currently the weakest rule in the stack, by design: it was placed to catch +the unambiguous cases and leave the judgement calls to the reviewer. + +## 5. A worked example, end to end + +The single row the model rejected in the whole cohort: **chrX:11,849,670 in CART_NS0065-B2M_2**, +an intron of *FRMPD4*, guide B2M. + +``` +observed k = 6 indel reads out of n = 162 (VAF 3.70%) +matched control 3 indel reads out of 104 (VAF 2.88%) + +α = a0 + control_alt = 0.002034 + 3 = 3.002034 +β = b0 + control_ref = 1.639 + 101 = 102.639235 +background = α/(α+β) = 0.028417 (2.84%) + +P(X ≥ 6 | n = 162, α, β) = 0.328686 +AQ = −10 log₁₀(0.328686) = 4.83 → below 5 → dropped +``` + +This reproduces the pipeline's output exactly, and can be re-derived from the row in +`results_cart_bnd/review/review_queue_all.tsv`. + +![worked example](images/aq_worked_example.png) + +**It is also the cleanest illustration of the physics.** The four events at this site are ±1–2 T's +inside a **15 bp T homopolymer** — polymerase slippage, not a cut. That is why the unedited matched +control shows it at nearly the same rate (2.88% vs 3.70%), and why the model is right to reject it. +Had `k` been 7 instead of 6, AQ would be 6.16 and the row would have been kept: the threshold is +close, and the honest description is "this site is a coin-flip", not "this site is noise". + +## 6. Distance from the cut as a spatial prior + +The fourth ask was to model the distance-from-PAM distribution empirically rather than assert a +threshold. `bin/cut_distance_model.py` does that; this is the result. + +`review_filter.py` currently treats distance as a boolean: keep if `cut_dist_min ≤ 10`. That 10 is +inherited from the caller's own `-d/--max-mutation-distance` default and was never derived from +data. Modelled properly there are two components, one per process: + +| | n | median | shape | +|---|---:|---:|---| +| background (off-target rows with indel evidence) | 3,712 | 5 | **Uniform** — every bin within 1.1 points of 9.09% | +| signal (on-target rows, real Cas9 cuts) | 83 | 0 | **spike at the cut** — 96.4% at d ≤ 1 | + +**Background is Uniform because an artifact has no reason to prefer any offset** relative to a +predicted cut site. That is a prediction, and it holds: bins run 7.97%–10.10% against a uniform +expectation of 9.09%. (A chi-square over 3,712 observations does reject *exact* uniformity at +p = 0.02 — at that n a fraction-of-a-point wobble is detectable. Uniform is an excellent working +null, not an exact property, and it is quoted that way.) + +**Signal is a sharp spike at 0–1 bp**, set by Cas9 blunt-end geometry and broadened only by repair +microhomology and by where the aligner chose to place the indel. + +Given both, the evidence carried by an observed distance is a **genuine likelihood ratio**: + +``` +LR(d) = P(d | signal) / P(d | background) +``` + +![cut distance model](images/cut_distance_model.png) + +| d (bp) | P(d \| signal) | P(d \| bg) | LR | evidence (dB) | +|---:|---:|---:|---:|---:| +| 0 | 0.766 | 0.0909 | 8.43 | **+9.3** | +| 1 | 0.106 | 0.0909 | 1.17 | +0.7 | +| 2 | 0.032 | 0.0909 | 0.35 | −4.6 | +| 3–10 | ~0.011 | 0.0909 | 0.12 | −9.3 | + +> **The signal column is add-one (Laplace) smoothed**, so it will not match a raw histogram of the +> 83 on-target events — raw, d = 0 is 71/83 = 0.855, and bins 3–10 are empty. Smoothing spreads one +> pseudo-count over all 11 bins: (71+1)/(83+11) = 0.766 at d = 0, and 1/94 = 0.011 in the empty +> bins. Without it the LR is infinite wherever no on-target event happened to land, which is an +> artifact of n = 83 rather than a statement about Cas9. The background column is unsmoothed — +> at n = 3,712 no bin is empty. See [`cut_distance_model.py:75`](../bin/cut_distance_model.py). + +The last column is on the same decibel scale as AQ, which is the point: a distance of 0 contributes ++9.3 dB of evidence and a distance of 10 contributes −9.3 dB, instead of both being "inside the +window, therefore fine". That makes distance combinable with AQ in log space rather than a separate +boolean hurdle. + +### What it is worth in practice — reported honestly + +On the 135 labelled gated rows, distance alone is a much better filter than the shipped threshold: + +| threshold | confirmed kept | rejected kept | +|---|---|---| +| d ≤ 2 | **64/64** | 41/71 | +| d ≤ 10 (shipped) | 64/64 | 71/71 | + +The full-recall plateau extends all the way down to **d ≤ 2**, not just to 6 as previously +believed — at which point it removes 30 of the 71 human-rejected rows for free. + +**But it changes almost nothing operationally.** After rules 1–3 have run, tightening the threshold +to 2 moves the final queue from 86 rows to 85 and removes **zero** labelled negatives: all 8 +rejected rows that survive to the queue already sit at d ≤ 1. The spatial rule is largely +*redundant* with the germline and length-diversity rules on this cohort. + +So the recommendation is not "tighten the threshold". It is that the LR is worth having **as a +score**, for ranking the queue and for the single-sample case where no matched control exists and +rule 1 is unavailable. That is where a rule that needs no cohort and no control earns its place. + +### One limitation, stated rather than worked around + +The caller's `-d` default is 10 and `get_indels.nf` passes no override, so `min_cut_distance` is +only ever observed on events the caller already accepted at ≤ 10 bp. **The shape above is measured +inside the window we are allowed to see; the tail beyond 10 bp is not estimable from these tables.** + +`indel_info` field 7 is uncapped (4,811 events, reaching 28 bp, 7.8% beyond 10) and shows the tail +is real and thin — but it is the *anchor-only* distance, a different and always-larger quantity +than `min_cut_distance`. It is usable for tail shape with that caveat attached, and must not be +pooled with the numbers above. Only a re-run with a larger `-d` would settle it. + +--- + +## What this model does NOT claim + +1. **It does not claim the control measures the machine-error rate.** At the median control depth + of 157×, one read is 0.64% VAF, so the control cannot *resolve* any rate below ~0.6%. 99.4% of + control observations are exactly zero. That zero is a detection limit, not a measurement. + +2. **It does not claim a single Beta separates error from germline.** It demonstrably does not: + the control-rate distribution is a point mass at 0 plus a germline mode near 0.18, with nothing + between (zero observations in the interval (0, 0.001)). What the validation doc shows is that + the *fitted shape* still produces calibrated tail probabilities — which is a weaker and more + honest claim than "the model separates the two processes". + +3. **It does not claim AQ is a probability that a call is real.** It is P(data | background). Going + from there to P(real | data) needs a prior on how often a site is genuinely edited, which this + model does not supply. + +4. **It does not claim the prior is context-aware.** It is not. A single global prior + under-penalises slippage-prone sequence and over-penalises clean unique sequence, and the size + of that error is measured in the validation doc (33× between strata). + +5. **It does not claim AQ < 5 is a meaningful significance test.** It is a permissive backstop that + removes one row in 479. Do not present it as statistical filtering of the call set. diff --git a/docs/NOISE_MODEL_ASSUMPTIONS.md b/docs/NOISE_MODEL_ASSUMPTIONS.md new file mode 100644 index 0000000..b7869a8 --- /dev/null +++ b/docs/NOISE_MODEL_ASSUMPTIONS.md @@ -0,0 +1,604 @@ +# Every assumption in the background model, and whether it holds + +[`NOISE_MODEL.md`](NOISE_MODEL.md) says what the model *is*. +[`NOISE_MODEL_VALIDATION.md`](NOISE_MODEL_VALIDATION.md) shows it is calibrated. +Neither says what it **assumes**. This does, exhaustively, with the code location and the measured +consequence for each one. + +Reproduce everything here with: + +```bash +python3 bin/noise_model_validate.py \ + --tables 'results_cart_bnd/*/*.offtarget_analysis.tsv' \ + --queue-all results_cart_bnd/review/review_queue_all.tsv \ + --calib-seeds 20 --ks-bootstrap 200 --figdir docs/images +``` + +`--ks-bootstrap` is the parametric bootstrap of §Q1 (off by default; 200 sims ≈ 8 min). Sections +3b and 3c — the reliability check and the edited-vs-control assumption test — always run. Whole +thing is ~25 min. + +--- + +## Summary — what actually turned up + +Four findings change how the existing validation should be read, and one of them changes how the +model should be *described*. None is fatal; all are things a careful reader would find first. + +| # | finding | consequence | +|---|---|---| +| 1 | **Assumption 8 — that the edited and control libraries share a background rate — was never tested. It holds wherever it can be tested.** Scored edited-against-control at no-edit loci and stratified by whether the caller reported an event: at the **91,984** event-free rows the p-values are uniform in the bulk (0.5026 at the median, 0.0557 at 0.05) and the raw posterior is already **conservative**, predicting 3.9× more background than the edited library shows. | The pooled **D = 0.0343** that first looked like a failure is a **selection artifact** — see [§ the follow-up](#follow-up--what-findings-1-and-2-actually-were). The depth floor then adds a further ~40× of conservatism on top. **Precision still comes from conservatism rather than from the Bayes, but because the filter is stacked twice over, not because the posterior is wrong.** | +| 2 | **The ~12× under-prediction at clean loci is five loci out of 6,822** (ratio 11.71, CI [9.23, 14.66] — real, but not general). Each is a single donor carrying a 15–26% VAF indel that the caller found, saw control support for, and **dropped as germline**; every other donor at those loci is clean. | Donor-private germline, which the other-donor null structurally cannot represent — this **is** assumption 25, quantified. Remove those loci and the model **over**-predicts (ratio 0.33, CI [0.13, 0.68]): the conservative direction. Not a prior-tail defect. | +| 3 | **The count distribution has the wrong shape**, even though its mean is exactly right. Observed zeros 0.9934 vs simulated 0.9912; observed max 130 vs simulated 105. | The two-process objection, visible as a distributional mismatch rather than a histogram. Mean-matching hid it. | +| 4 | **The calibration test does not exercise the regime production runs in.** The leave-one-donor-out null hands the model **4,523×** pooled control depth and a null that is 99.3% event-free; production uses **157×** from one matched control and scores rows that are 100% events. | Passing that test is necessary, not sufficient. A model that is catastrophic in production passes it comfortably — demonstrated below. | + +**What survives unchanged:** the model is calibrated on the control-vs-control null it was tested +against, confirmed by a parametric bootstrap that handles both KS assumption violations at once +(p = 0.225), and no candidate replacement moves the review queue by more than the same single row. +The recommendation remains *do not change the shipped model* — but describe it accurately. + +> **Findings 1 and 2 were followed up and both changed.** Neither is a defect in the prior. The +> table above already states the corrected versions; the working is in +> [§ Follow-up](#follow-up--what-findings-1-and-2-actually-were), and the original reasoning is +> left in place below so the correction can be checked rather than taken on trust. + +And the answer to "why not just a Binomial per locus": at **86 of the 89** rows the AQ rule actually +sees, the matched control observed zero alt reads, so a plug-in `p̂ = 0` would score every one of +them at AQ = +∞. The test would pass everything. + +--- + +## The seven questions + +### Q1 — What does the Kolmogorov–Smirnov test assume? + +Three things. One is satisfied, two are violated, **and the two violations push in opposite +directions**. + +| assumption | status | +|---|---| +| Observations are **i.i.d.** under the null | **Violated.** 71,755 observations come from 6,876 loci, and at each locus every donor is scored against a background built from the *other donors at that same locus*. They are coupled by construction. | +| The null distribution is **fully specified** in advance | **Violated.** `a0, b0` are estimated by method of moments from the same observations the test then scores (`review_filter.py:365`). This is the Lilliefors problem. | +| The distribution is **continuous** | **Satisfied**, and handled properly. Discrete counts can never yield a uniform survival function, so randomised p-values `U·P(X=k) + P(X>k)` are used (`noise_model_validate.py:276`). | + +**The two biases oppose each other.** Positive dependence makes the empirical CDF wander further +from uniform, inflating D. Estimating parameters from the same data makes the fitted distribution +track the data too closely, deflating D. Neither the size nor the net direction is knowable +analytically — so it was measured. + +**The parametric bootstrap, which settles both at once** (`--ks-bootstrap 200`). Simulate 200 +datasets under the fitted model with the **locus structure preserved** — one shared rate per locus, +which is precisely the dependence the null asserts — and **refit the prior by method of moments on +every synthetic dataset**, so the estimation bias is reproduced too. The spread of D across those +simulations is the null this test actually has: + +``` +null D under the fitted model : median 0.0029 95th pct 0.0051 max 0.0062 +observed D (median seed) : 0.0037 -> bootstrap p = 0.225 PASS +``` + +**The two biases cancel almost exactly.** The bootstrap's 95th percentile, 0.0051, is +indistinguishable from the naive analytic critical value `1.358/√71755 = 0.0051` — and far below +the locus-level bound `1.358/√6876 = 0.0164`. So the naive number happened to be right, the +locus-level correction was sound but *loose*, and the honest statement is that neither analytic +route was trustworthy on its own; only the simulation shows they offset. + +| model | median D over 20 seeds | vs bootstrap 95th pct (0.0051) | +|---|---:|---| +| Binomial, global `p` | 0.1398 | **REJECT**, 27× over | +| Beta-Binomial, MOM (**shipped**) | 0.0037 | **pass**, bootstrap p = 0.225 | +| Beta-Binomial, MML | 0.0038 | pass | +| Zero-inflated BB | 0.0038 | pass | + +**What this does to the "1 seed in 20 rejects" caveat.** It explains it rather than dismissing it. +The worst seed (0.0062) does exceed 0.0051 — but so does the bootstrap's own maximum (0.0062) under +a model that is true by construction. Seed-to-seed variation of that size is what a correct model +looks like. **Report the median D (0.0037) and the bootstrap p (0.225); the worst seed is +randomisation variance, not evidence of misfit.** + +> An earlier draft of this section claimed the locus-level accounting was the correct one and the +> naive one wrong. The bootstrap shows the effective null sits at the naive value. The conclusion — +> the shipped model passes, the Binomial fails — never changed, but the reasoning did. + +### Q2 — What does conjugacy assume, and what does "closed form" buy? + +**Conjugacy** means that a Beta prior combined with a Binomial likelihood yields a Beta posterior, +in the same family, with parameters obtainable by addition: + +``` +p ~ Beta(a, b) and k | p ~ Binomial(n, p) ⇒ p | k ~ Beta(a + k, b + n − k) +``` + +and the marginal (what you predict a *new* observation with) is `BetaBinomial(n, a, b)`. + +**What it assumes.** Only that the likelihood really is Binomial with a single `p` — i.e. that +reads at a locus are exchangeable Bernoulli trials at one rate. It assumes **nothing** about +whether the Beta is the right prior. + +**What "closed form" buys.** An analytic posterior and predictive: no MCMC, no sampler, no +convergence diagnostics, deterministic output, and a cost of one `betabinom.sf` call per locus +across 99,238 of them. For a pipeline that must run unattended, that matters. + +**What it costs, and this is the honest part.** Conjugacy is a *computational* property, not +evidence. It is a reason to prefer the Beta among priors that fit, never a reason to believe it +fits. And the cost is expressive: the shape the data actually has — a point mass at zero plus a +mode near 0.18, with **nothing in between** — cannot be written as a Beta. Staying conjugate means +accepting a family that cannot represent the population. §Q7-11 covers why it works anyway. + +### Q3 — Why `α = a0 + control_alt` and `β = b0 + (control_depth − control_alt)`? + +Because that *is* the conjugate update, and the reason it takes that form is the pseudo-count +interpretation: **`a0` behaves exactly like `a0` alt reads you already saw, and `b0` like `b0` ref +reads.** Real observations then simply add to the imaginary ones. + +``` +α = a0 + (alt reads in control) β = b0 + (ref reads in control) +posterior mean = (a0 + alt) / (a0 + b0 + depth) +``` + +The fitted prior on this cohort is `Beta(0.002034, 1.639)`, so `a0 + b0 ≈ 1.64` — **the prior is +worth about 1.64 reads.** Any control deeper than ~2× overwhelms it immediately, which is the +intended behaviour: the prior exists to say something sane where there is no data, not to compete +with data where there is. + +`control_reads − control_indel_reads` is the ref count because every read is alt or ref. That +identity is what makes the pair a valid `(successes, trials)` observation — and §Q7-4 is where it +breaks. + +### Q4 — How is the per-locus update actually performed? + +Four steps, in `bin/noise_model.py`: + +1. **Fit the prior once** (`fit_global_prior`, `:100-118`) by method of moments over every control + observation in the run. +2. **Update per locus** (`control_posterior`, `:191-217`) — pool the control counts at that locus + under the chosen baseline and apply the conjugate update. Baselines: `matched` (this sample's + own control only — **the production default**), `loo` (every *other* sample), `both` (all). +3. **Apply the depth floor** (`apply_depth_floor`, `:220-247`) — where the posterior mean fell + below `1/control_depth`, relocate it to exactly `1/control_depth`, holding `α+β` fixed so only + the location moves. **This step is not Bayesian**; see §Q7-19. +4. **Test the edited count** against the posterior predictive, one-sided, and Phred-scale it: + +```python +AQ = -10*log10( betabinom.sf(k-1, n, alpha, beta) ) # review_filter.py:372-373 +``` + +where `k, n` are the **edited** sample's counts and `alpha, beta` come entirely from the +**control**. Using the posterior predictive rather than a plug-in point estimate is the correct +Bayesian move — it integrates over the remaining uncertainty in `p` instead of pretending it is +known. + +### Q5 — Why not just run a Binomial at every locus, since we have the actual probability? + +**Because we do not have it.** We have an estimate from a control of median depth 157×, and at a +rate of 1e-3 that control *expects*: + +``` +157 × 0.00124 = 0.195 alt reads +``` + +So observing **zero is the single most likely outcome** at a locus whose true rate is exactly the +cohort average. The plug-in reads that zero as "the rate here is 0". + +**What that does, measured.** Of the 89 rows that reach the AQ rule (rules 1–3 remove 390 of 479 +before it), **86 — 96.6% — have `control_alt = 0`.** Under `p̂ = 0`: + +``` +P(X ≥ k | p̂ = 0) = 0 for every k ≥ 1 ⇒ AQ = +∞ +``` + +**The test would declare 96.6% of the rows it sees infinitely significant, and filter nothing.** + +The Beta-Binomial is not a different philosophy — **it is this model with the plug-in replaced by +an integral over the uncertainty in `p̂`**, and it converges to the plug-in as control depth → ∞. +At 157× for a rate of 1e-3 we are nowhere near that limit. + +> **A result worth reporting because it went the other way.** Added as `BinomialPlugin` to the +> validation harness, the plug-in **passes** the leave-one-donor-out calibration test: +> D = 0.0047 against the shipped model's 0.0048, indistinguishable. It is not calibrated in any +> useful sense — it is calibrated *in that test*, because the test hands it **4,523×** of pooled +> other-donor depth (10.4 donors × ~157× each) and a null in which only **0.66%** of observations +> carry any event at all. Production gives it 157× from one control and scores rows that are 100% +> events. **A model that would filter nothing in production sails through the calibration test**, +> which is the sharpest available demonstration that passing that test is necessary and nowhere +> near sufficient. See §Q7-25. + +### Q6 — Can we compare the calculated p to the observed p as a gut check? + +Yes, and it is the most informative thing in this document. It has to be **out of sample** — a +locus's own control both builds and would be graded by its posterior, which is circular — so each +donor's rate is predicted from the *other* donors at that locus, reusing the existing LOO +structure. + +![reliability and posterior-predictive check](images/noise_reliability.png) + +**Aggregate: predicted 13,391.7 alt reads, observed 13,397 — ratio 1.000 ± 0.009.** Which looks +like a clean pass, and is why this was never noticed. It is carried almost entirely by one bin: +13,236 of the 13,392 predicted reads sit in the highest-expectation bin, the germline loci, where +the model is genuinely excellent. + +Binned by **predicted expected count** (a rate bin can hold tens of thousands of observations +carrying no events, where a ratio is noise wearing a number's clothes): + +| expected alt reads / obs | n | predicted | observed | ratio | 95% Poisson CI | +|---|---:|---:|---:|---:|---| +| [0, 1e-3) | 59,907 | 6.5 | 76 | **11.71** | [9.23, 14.66] | +| [1e-3, 3e-3) | 10,689 | 14.9 | 50 | **3.35** | [2.49, 4.42] | +| [1e-2, 3e-2) | 71 | 1.7 | 4 | 2.41 | [0.66, 6.17] | +| [3e-2, 1e-1) | 280 | 14.1 | 12 | 0.85 | [0.44, 1.49] | +| [1e-1, 3e-1) | 125 | 25.2 | 31 | 1.23 | [0.84, 1.75] | +| [3e-1, 1) | 163 | 93.6 | 68 | 0.73 | [0.56, 0.92] | +| [1, ∞) | 520 | 13,235.9 | 13,156 | 0.99 | [0.98, 1.01] | + +**The two lowest bins under-predict by 12× and 3.4×, and both confidence intervals exclude 1.** +This is not a small-numbers artifact — it rests on 76 and 50 observed events. + +> **Followed up, and the reading below is wrong.** The 76 events are 12 observations, and five +> loci carry 88% of the excess — each a donor-private allele the caller had already suppressed as +> germline. Removing them leaves a ratio of **0.33** [0.13, 0.68]: at genuinely clean loci the model +> **over**-predicts. See [§ Follow-up](#follow-up--what-findings-1-and-2-actually-were). The +> paragraph that follows is the original inference, kept so the correction can be checked. + +The model looks systematically too optimistic about loci it believes are clean, which would be the +**false-positive** direction: a background predicted 12× too low produces an AQ far too high, at +exactly the sites where a call looks most convincing. + +**Posterior-predictive check** — simulate `k ~ BetaBinomial(n, α, β)` per locus, 20 draws, and +compare the shape of the count distribution rather than its total: + +| statistic | observed | simulated (95% band) | | +|---|---:|---|---| +| fraction k = 0 | 0.99338 | [0.99092, 0.99144] | **outside** | +| fraction k ≥ 1 | 0.00662 | [0.00856, 0.00908] | **outside** | +| fraction k ≥ 2 | 0.00570 | [0.00703, 0.00739] | **outside** | +| fraction k ≥ 5 | 0.00507 | [0.00631, 0.00640] | **outside** | +| mean k | 0.18670 | [0.18379, 0.19016] | ok | +| max k | 130 | [101.5, 110.6] | **outside** | + +**The mean is exactly right and the shape is wrong.** The model spreads too little probability onto +zero, too much onto small non-zero counts, and too little into the extreme tail. That is the +two-process objection made quantitative: a single Beta cannot be simultaneously spiky enough at +zero and heavy enough at 0.5, so it compromises in the middle — and the middle is where no locus +actually lives. + +**Caveat, stated rather than buried.** Both checks use the LOO (pooled) baseline, because that is +the only construction giving a genuine out-of-sample prediction. Production uses `matched`, a +single 157× control. The direction of the finding should transfer; the magnitudes are not directly +production numbers. + +### Q7 — What else does the model assume? + +Below, by layer. **Bold** entries are violated in a way that has a measurable or mechanical +consequence. + +#### Read counting — `bin/find_edited_reads.py` + +1. **Reads are independent Bernoulli trials.** Duplicates are filtered (`is_duplicate`, `:875`), + but there is no UMI consensus and no correction for residual correlation. Overdispersion from + this source is absorbed into the prior rather than modelled. +2. **Control alt is counted per READ; control depth per FRAGMENT.** `total_reads` is a `set()` of + `query_name` (`:871`, added at `:878`, used at `:960`) so R1 and R2 of one fragment collapse to + a single unit of depth; but `control_alt_counts += 1` (`:913`, `:921`, `:952`) runs inside the + read loop with no such grouping. **An overlapping mate pair that both show the alt allele + increments alt twice and depth once.** Direction: background biased **upward** ⇒ AQ too low ⇒ + over-filtering. +3. **The edited and control libraries are counted by different rules.** The edited sample is + deduplicated to one row per fragment (`groupby('read').first()`, `:2189`); the control is not + (#2). The numerator of the test and the null it is tested against come from different counting + processes. +4. **`control_alt` is SUMMED over the events at a site while depth is a MEAN** of a single + site-level constant (`:2242-2248`). The per-event alt counts are not a partition of the depth, + so the pair need not satisfy `k ≤ n`. **3 of 99,238 rows have `control_alt > control_depth`.** +5. **Consequence of #4.** `control_posterior` computes `β = b0 + max(dep − alt, 0)`, so an + impossible count does not raise an error — it produces `Beta(155.0, 1.64)`, a posterior with + **mean 0.99**. The locus is declared 99% background and can never be called again. Verified on + the one affected gated row, chr1:246,009,987: `bg_rate` 0.9895, AQ −0.0. Rule 1 removed it first + as germline, so nothing changed *this* time. The mechanism is live regardless. +6. No strand-bias modelling anywhere in the caller or the noise model. + +#### The locus model + +7. One rate `p` per locus, constant across all reads covering it. +8. **The edited and control libraries share the same background rate.** The load-bearing + biological assumption: `α, β` come entirely from control counts and are applied unmodified as + the null for edited counts, with no library-specific term (`noise_model.py:386-415`). It was + **asserted by construction and never tested** — the LOO calibration tests + control-against-control. **It has now been tested, and it does not hold.** See + [§ Testing assumption 8](#testing-assumption-8-the-one-nothing-checked) below. +9. **Loci are exchangeable under one global Beta.** Violated: sites in a ≥9 bp homopolymer carry + control indel evidence 35.4% of the time against 0.53% in unique sequence. The multiplier is + convention-dependent (33× under the run-length definition in the validation script, 72× under a + window-clipped one) — the effect is robust, the exact number is not. +10. Loci are independent of one another. Nearby loci share reads, repeats and mapping behaviour. + +#### The prior + +11. **The Beta family is adequate.** Measured wrong: 99.40% of control observations sit at exactly + zero, a second mode sits at 0.179, and **nothing lies between**. It works anyway because + `a = 0.002 < 1` makes the Beta monotone decreasing — already spike-at-zero shaped — so it + mimics zero-inflation. The explicit mixture is unidentifiable (π swings 0.536 → 0.993 while + held-out likelihood moves 0.000002 nats). +12. **Method of moments takes the variance ACROSS observations**, which absorbs sampling noise as + well as true locus-to-locus rate variation (`:103-105`, stated as intentional). The prior is + therefore more diffuse than the real spread of rates warrants. +13. A degeneracy guard silently substitutes `Beta(100m, 100(1−m))` when `v ≥ m(1−m)` (`:114-116`). + Not triggered on this cohort. +14. `MIN_PRIOR_MEAN = 1e-5` floors the fitted prior mean (`:81`), so a pristine-control cohort + cannot drive it to zero. +15. **Empirical Bayes double-use of data.** Each locus's control counts enter the method-of-moments + fit *and* are then added again to that same locus's posterior. Standard empirical-Bayes + practice, but it understates uncertainty, and the effect grows as the cohort shrinks — a + single-sample submission is the worst case. + +#### The test + +16. `(control_alt, control_depth)` is a valid `(successes, trials)` pair — violated by #4. +17. The posterior predictive is the right null for the edited count. Correct, *conditional on* #8. +18. **The test is one-sided** — `sf(k-1, ...)` = `P(X ≥ k)`. It can only ask "is there too much + signal", never "is this locus improbably clean", so a locus that has lost coverage or been + over-filtered upstream cannot be flagged. +19. **The depth floor is not a Bayesian operation.** It relocates the posterior mean post hoc to + `1/control_depth`. It **raises the background on 306 of 479 gated rows (63.9%)** and moves the + median AQ from 31.1 to 4.1 — the single most consequential step in the whole model. It is + defensible (it encodes what a control of that depth can resolve) but it is a patch, and it is + doing more work than the prior. +20. AQ is capped at 3000 by the `1e-300` clip in `aq_from_sf` (`:250-253`). +21. **`AQ_MIN = 5` was chosen to reproduce the legacy panel-of-normals output**, per its own comment + (`review_filter.py:73-76`) — 3, 5 and 8 all matched, 10 lost a confirmed edit, and 5 sits mid + plateau. It is not derived from a target false-positive rate. +22. **No multiple-testing correction.** `noise_model.py:423-426` prints an expected-false-positive + count at several thresholds and never feeds it into any decision. +23. **Rule ordering.** AQ is 4th in a first-match-wins `np.select`, so it only ever sees the 89 of + 479 gated rows that rules 1–3 spared. Any evaluation over all 479 overstates its reach ~5×. + +#### The validation itself + +24. The KS assumptions — §Q1. +25. **The LOO null does not reproduce the production regime.** It pools ~10 donors (median 4,523× + of control) where production uses one (157×), and 99.34% of its observations carry no event + where every production row does. Demonstrated live by `BinomialPlugin` passing it (§Q5). It + also uses other donors as a proxy for this donor, which is sound for machine error and wrong + for germline — donor-private variants are, by definition, not in anyone else. + +--- + +## Testing assumption 8 — the one nothing checked + +The model builds its null entirely from the control library and applies it to the edited library. +Nothing verified that those two libraries share a background rate. This tests it directly. + +> **Followed up, and the headline number does not survive.** The pooled D = 0.0343 comes from +> mixing 2,937 rows that carry a *called* indel into 91,984 that do not. Conditioning on "an event +> was called here" forces `k ≥ 1`, which turns the p-value into a spike at ≈0.001 rather than a +> distribution. On the event-free rows — where the assumption can actually be tested — the +> p-values are uniform in the bulk (0.5026 at the median). See +> [§ Follow-up](#follow-up--what-findings-1-and-2-actually-were). The section below is the +> original analysis, kept intact so the correction can be checked; its **depth-floor** measurements +> stand and in fact strengthen. + +**Design.** Take every site-row with `is_target == 0` — no nominated cut site, so no edit is +expected — and score the **edited** counts against that sample's **own matched control**, exactly +as production does. Convert to randomised p-values. If the two libraries share a background, those +p-values are Uniform(0,1). 94,921 rows qualify. + +**Result — the raw posterior, i.e. the Bayesian model itself:** + +| | observed | expected if the assumption holds | +|---|---:|---:| +| KS D | **0.0342** | ~0.003 (what control-vs-control gives) | +| fraction p < 0.001 | **0.01022** | 0.001 — a **10.2× excess** | +| observed / predicted alt reads | 0.855 | 1.0 | + +**D = 0.0342 is seven times the control-vs-control figure (0.0037) and nearly seven times the +bootstrap's 95th percentile (0.0051).** The assumption fails in the comparison the pipeline +actually performs. + +> As in §Q1, **D is the stable statistic and the tail-excess figure is not** — it moves by about a +> point between randomisation draws (10.2× here, 11.2× on an independent implementation) while D +> holds to three decimals. Read the excess as "roughly an order of magnitude too many". + +**It is not explained by real edits.** Some `is_target == 0` rows could carry genuine off-target +editing, which would produce legitimately small p-values. Excluding every row that could possibly +be called — anything with ≥2 alt reads at VAF ≥ 0.005, i.e. the entire gate — barely moves it: + +| population | n | KS D | p < 0.001 excess | +|---|---:|---:|---:| +| all no-target rows | 94,921 | 0.0342 | 10.2× | +| **sub-gate only — cannot be a call** | 94,523 | **0.0320** | **7.9×** | +| zero edited alt reads | 91,209 | 0.0039 | 0.0× | + +The middle row is the meaningful one: rows that are background *by construction of the gate* still +carry **7.9× too many extreme p-values**. (The last row looks perfect only because conditioning on +`k = 0` makes the randomised p-value uniform by construction — it is included to show it is +uninformative, not as evidence.) + +**What is actually going wrong.** The direction is the tell: overall the edited sample has *fewer* +alt reads than predicted (ratio 0.856), yet the extreme tail is heavily over-populated. That is not +a library running uniformly hotter — it is the same **clean-locus under-prediction** measured in Q6. +Where the control saw nothing, the raw posterior claims a background near `a0/(a0+b0+depth) ≈ 1e-5`, +so one or two alt reads in the edited sample look extraordinary. The failure is concentrated at +precisely the loci the model is most confident about. + +**And this is what the depth floor is for.** Re-running the same test with the floor on, as +production has it: + +| | raw posterior | with depth floor (production) | +|---|---:|---:| +| KS D | 0.0342 | **0.4814** | +| fraction p < 0.001 | 0.01022 (10.2× too many) | 0.00012 (8× too **few**) | +| observed / predicted alt reads | 0.855 | **0.040** | + +The floor does not calibrate the model — **it over-corrects by a factor of ~25**, declaring a +background 25× larger than the edited sample actually shows. It raises the background on 94,435 of +these 94,921 rows. + +**The honest conclusion, and it matters for how the model is described.** In the comparison +production performs, the shipped configuration is **not calibrated in either direction** — the +Bayesian posterior is far too aggressive, and the depth floor that patches it is far too +conservative. What delivers the observed precision is **the conservatism of the floor, not the +Bayesian machinery underneath it.** The model's calibration credential comes from a +control-vs-control test that does not exercise this comparison at all (§Q7-25). + +That is not an argument for abandoning it — a deliberately conservative filter with 64/64 recall is +a perfectly respectable instrument, and being conservative is the right failure direction for a +screen. It is an argument for describing it accurately: **it is a conservative bound, not a +calibrated probability**, and the AQ values it reports should not be read as p-values in the +edited-vs-control sense. + +**Caveats.** Off-target rows may include an unknown number of genuine edits, though the sub-gate +result bounds their contribution. And the comparison uses a single matched control per row, which +is the production configuration but also the thinnest one. + +## Follow-up — what findings 1 and 2 actually were + +Findings 1 and 2 above were the two that pointed at a defect in the model rather than in its +description, so both were chased to a cause. Neither survived. Everything below is reproduced by + +``` +bin/noise_model_followup.py --tables 'results_cart_bnd/*/*.offtarget_analysis.tsv' \ + --fasta .../hg38_PLVM_CD19_CARv4_cd34.fa --part both +``` + +which, like `noise_model_validate.py`, is analysis only — it imports the shipped model, changes +nothing, and the pipeline never calls it. + +### Finding 2 — the clean-locus under-prediction is five loci + +The coldest reliability bin under-predicts by 11.71×. That ratio is computed over **59,907 +observations, of which 12 carry any alt read at all** — and five loci carry 88% of the excess: + +| locus | donors in bin | predicted | observed alt | VAF | events the caller suppressed | +|---|---:|---:|---:|---:|---:| +| chr12:131,404,130 | 1 | 0.001 | 29 | 0.257 | 1 | +| chr21:41,062,284 | 1 | 0.001 | 25 | 0.217 | 1 | +| chr8:85,438,605 | 1 | 0.001 | 21 | 0.198 | 1 | +| chr8:1,858,151 | 1 | 0.001 | 20 | 0.163 | 2 | +| chr17:14,952,680 | 1 | 0.001 | 16 | 0.145 | 1 | + +Every one is a *single* donor with a 15–26% VAF indel while every other donor at that locus is +clean — and in every case the caller **found the event, saw control support, and dropped it** at +`-x 0` (`find_edited_reads.py:2286`). The last column is the `n_control_filtered` the caller +records. Across the whole no-target set the association is not subtle: **100% of rows with control +VAF ≥ 5% and a near-empty edited library have `n_control_filtered > 0`, against 0.39% elsewhere.** + +So these are real donor-private alleles that the leave-one-donor-out null cannot represent, because +the null is built from *other* donors and germline is donor-private. That is +[assumption 25](#the-validation-itself) exactly, already documented as a known limitation, showing +up with a number attached. + +The three competing explanations were tested and are not it: + +| hypothesis | prediction | result | +|---|---|---| +| germline at VAF ~0.5 | excess at VAF ≥ 0.35 | **0** observations there; the outliers sit at 0.15–0.26 | +| sequence context | excess in long homopolymers | 96.4% of the excess is in runs **< 5 bp** | +| batch effect | NS0065 controls globally noisier | rate 0.00109 vs 0.00107 elsewhere; **NS0027 is the highest** at 0.00161 | + +**Strip the ten worst loci, anything germline-like, and any homopolymer ≥ 7 bp, and 70,334 +observations remain with a ratio of 0.33, 95% CI [0.13, 0.68].** At genuinely clean loci the model +**over**-predicts the background threefold. The prior's left tail is not too thin; if anything it is +too thick, which is the safe direction for a filter. + +### Finding 1 — assumption 8 was measured on a population selected for the outcome + +The pooled D = 0.0343 is real arithmetic, but it is not a calibration measurement. Stratify the +same 94,921 rows by whether the caller reported an indel at that site: + +| population | n | share | KS D | p < 0.001 | obs/pred | +|---|---:|---:|---:|---:|---:| +| `indel_count == 0` — no event called | 91,984 | 96.9% | **0.0079** | 0.00187 (1.9×) | 0.254 | +| `indel_count == 1` — one event called | 2,651 | 2.8% | **0.9476** | 0.287 (287×) | 1.830 | +| `indel_count ≥ 2` | 286 | 0.3% | 0.4674 | 0.465 (465×) | 1.050 | +| **pooled — as originally reported** | 94,921 | | 0.0343 | 0.0112 | 0.856 | + +**D = 0.9476 is not a miscalibration, it is a tautology.** `indel_count == 1` means an event was +called at that site, so 100% of those rows have `k ≥ 1` by construction. Against a background near +`1e-5` every such row scores p ≈ 0.001–0.003 — the median is 0.0013 and 95% fall below 0.01. That +is a **spike at one value**, not a distribution, and a KS statistic computed on it measures the +selection, not the model. Pooling those 3.1% of rows into the other 96.9% is what produced 0.0343. + +On the rows where the assumption *can* be tested — where nothing was called, so nothing is selected +— the p-values are close to uniform: + +| | observed | uniform | +|---|---:|---:| +| P(p < 0.5) | 0.5026 | 0.5 | +| P(p < 0.05) | 0.0557 | 0.05 | +| P(p < 0.01) | 0.0164 | 0.01 | +| P(p < 0.001) | 0.00187 | 0.001 | + +The bulk is uniform to three decimals. A residual ~1.9× sits in the extreme tail and D = 0.0079 is +still above the naive critical value (0.0045) — so this is "supported", not "proven". But it is not +the seven-fold failure originally reported. + +Two further controls: removing the germline-suppressed rows does **not** move it (D 0.0343 → +0.0345), so finding 2 is not the cause of finding 1 — they are separate; and the original sub-gate +population did not isolate the effect because most called events sit below the gate. + +**What this does not settle.** It tests the assumption only where no event was called. At rows that +*do* carry a called event — the rows the filter actually adjudicates — the assumption remains +untestable by this route, because that population is selected on the outcome. The right statement +is *supported where testable, untestable where it bites.* + +### What survives from the original conclusion + +The depth-floor measurement stands and gets stronger on the cleaner stratum: + +| | raw posterior | with depth floor (production) | +|---|---:|---:| +| all no-target — obs/pred | 0.856 | 0.040 | +| **event-free rows — obs/pred** | **0.254** | **0.006** | +| event-free rows — KS D | 0.0079 | 0.4996 | + +The raw posterior is already conservative on the event-free stratum, predicting **3.9× more** +background than the edited library shows. The floor then multiplies that by a further ~40×. So +**"precision comes from conservatism rather than from the Bayesian machinery" survives** — but the +mechanism is the opposite of what was first written. The posterior is not too aggressive and being +rescued by the floor; it is already conservative, and the floor stacks a second, much larger margin +on top of it. AQ remains a conservative bound rather than a calibrated edited-vs-control p-value, +and should still be described that way. + +## What to do about it + +Ordered by value, and none of it is applied here — this document changes no code. + +1. ~~**Fix the control counting asymmetry (#2, #3).**~~ **DONE, and its impact is measured and + small.** `add_normal_counts` now accumulates supporting **fragment names** in a set and reports + `len(...)`, so alt support is fragment-level exactly as depth already was. Regression tests in + `tests/test_control_counts.py` (they fail against the old code: 8 counted where 5 fragments + exist). + + **How much it actually changes.** Counting alt-supporting reads vs alt-supporting fragments + directly on control CRAMs at 12 real gated loci, the reduction is **5–14%** — e.g. 63→59, + 75→69, 21→18. That is far below the ~49% mate-overlap rate among *all* fragments, because both + mates must independently carry the indel *at that exact position* to double-count, which is + much rarer than merely overlapping. **No locus among the 12 crosses the rule-1 threshold.** + + Cohort-wide bound: of the 154 rows rule 1 drops as germline, the median control VAF is 0.201 — + four times the 0.05 cut — and only **8 sit within 20% of it**. So a 5–14% reduction moves + **1–8 rows of 479** back into the queue, and **recall cannot regress**: the fix only lowers the + background, so rows can move *into* the queue but no confirmed edit can be dropped. + + **A re-run is therefore not urgent.** Fold it into the next scheduled cohort run rather than + spending ~5 h now; every number in these docs predates the fix and would shift by at most that + much. +2. ~~**Test assumption #8.**~~ **DONE, and it fails** — see + [§ Testing assumption 8](#testing-assumption-8-the-one-nothing-checked). The practical + consequence is a description change, not a code change: AQ is a conservative bound, not a + calibrated probability in the edited-vs-control sense. +3. ~~**Investigate the clean-locus under-prediction (Q6).**~~ **DONE — it is five loci, and it is + germline.** See [§ Follow-up](#follow-up--what-findings-1-and-2-actually-were). Five loci of + 6,822 carry 88% of the excess, each a donor-private allele the caller had already suppressed; + remove them and the model over-predicts (0.33, CI [0.13, 0.68]). The assumption-8 corroboration + was independent of it and was itself a selection artifact. **No code change follows.** The one + thing worth carrying forward is a documentation point: the LOO reliability diagram cannot be + read at the cold end without excluding rows with `n_control_filtered > 0`, because those rows + are germline by construction. +4. **Condition the prior on sequence context (#9).** Largest measured context effect, computable + from the FASTA at zero cost, and currently free — no queue row sits in a long homopolymer. Fix + it before a cohort with homopolymeric targets makes it expensive. +5. **Leave the depth floor alone (#19)** until the zero-inflation ε can be sourced from the panel. + The principled replacement needs a number the matched control cannot supply. +6. **Do not change the shipped model on this evidence.** Every Beta-Binomial variant still moves + the queue by the same single row, and recall is 64/64 against the curated label for all of them, + including the models that are statistically worse. diff --git a/docs/NOISE_MODEL_EXPERIMENT.md b/docs/NOISE_MODEL_EXPERIMENT.md new file mode 100644 index 0000000..862a03e --- /dev/null +++ b/docs/NOISE_MODEL_EXPERIMENT.md @@ -0,0 +1,363 @@ +# Can a probabilistic noise model replace the panel of normals? + +Measured 2026-08-13 on the 32-sample CAR-T WGS cohort (`results_cart_ponfix`, 99,238 rows, +1,498 clearing the `reads>=2, VAF>=0.005` gate). + +**Short answer: yes, but not with the external DRAGEN panel.** A beta-binomial test against the +sample's *own matched control* reproduces the PoN's discriminative power exactly, with no cohort +required. The DRAGEN systematic-noise panel does not come close, and for a reason that is +structural rather than tunable. + +## Truth and its limits + +Two sources, kept separate because they answer different questions. + +- **Curated WGS label** — `Manual Indel Review/cart_wgs/cart_wgs_merged.xlsx`. Inside the stratum + `indel_fraction >= 0.05 AND indel_reads >= 10` every row was adjudicated by eye, so a blank + `manual_review` there is a **rejection**, not an absence. 241 rows → 41 confirmed / 138 rejected + truth keys. Two-class, but only at VAF ≥ 5%. +- **ECS review** — `cart_ecs/cart_ecs_merged.csv.gz`, 56 confirmed edits at ~1,960× depth, + reaching down to 2.48% VAF. **Positives only** (NaN = not reviewed), so it supports recall and + nothing else — but it is the only truth that reaches below the WGS review's 5% floor. + +Two caveats that affect every number below: + +- Truth is keyed by `(guide, chrom, start)`, so one truth key joins to several scored rows when a + guide has replicate samples. That is why 41 confirmed keys appear as 64 confirmed scored rows. +- 5 of 179 truth keys carry conflicting labels across replicates (2.8%); the key takes the max. + +## Part A — the PoN-off experiment + +Two traps, both real: the script's own defaults are `10 reads / 5% VAF` while the pipeline passes +`2 / 0.005`, and **omitting `--pon` does not disable rule 4** — it silently falls back to +cross-guide recurrence. Rule 4 is only truly off with `--max-guides 9999`. + +| # | Configuration | Queue | conf | rej | precision | +|---|---|---:|---:|---:|---:| +| 1 | PoN + DRAGEN panel (**what ships today**) | 87 | 64 | 8 | 0.889 | +| 2 | PoN only | 88 | 64 | 9 | 0.877 | +| 3 | cross-guide fallback + panel | 88 | 64 | 9 | 0.877 | +| 4 | rule 4 OFF + panel (**rule 6 standing alone**) | 91 | 64 | 9 | 0.877 | +| 5 | rule 4 OFF, no panel (the floor) | 92 | 64 | 10 | 0.865 | +| 6 | 32 × single-sample, no PoN (**the target user**) | 91 | 64 | 9 | 0.877 | + +Read off the table: + +- **Rule 6 standing alone removes exactly one site** (92 → 91) — the same site it removes when the + PoN is present (88 → 87). The PoN removes four *different* sites (92 → 88). The two are + **disjoint**: the external panel does not find what the PoN finds. +- The PoN's raw attribution says 10 drops, but disabling it only costs 4 queue rows, because the + repeat rule reclaims 6 of them (rule 5 drops rise 9 → 15). First-match-wins attribution + overstates any single rule's unique contribution. +- **Arm 6 = arm 4 exactly (91).** Rule 4 is the only cohort-dependent rule, so a single-sample + submission loses precisely the PoN and nothing else. + +## Part B — the beta-binomial scorer + +`bin/noise_model.py`. `AQ = -10 log10 P(X >= k | n, background)`, background from an +empirical-Bayes Beta prior fitted over every control observation (here Beta(0.0043, 1.774), mean +0.244%) and updated per locus. An unobserved locus keeps the prior — which is what makes the +"no data here" case principled instead of `p = 0`. + +Scored on the 232 rows carrying a curated label: + +| baseline | AUC | AP | AQ≥30 recall | AQ≥30 precision | +|---|---:|---:|---:|---:| +| **matched** (own control) | **0.977** | **0.944** | 64/64 | 0.681 | +| both | 0.971 | 0.908 | 64/64 | 0.674 | +| loo (cohort controls) | 0.936 | 0.801 | 51/64 | 0.739 | +| panel, `p = MAX` | 0.946 | 0.872 | 64/64 | 0.312 | +| panel, `p = MEAN × N/NR` | 0.945 | 0.869 | 64/64 | 0.312 | +| panel, `p = MEAN` | 0.930 | 0.847 | 64/64 | 0.306 | + +### Why the panel arms fail + +**Only 54 of 1,498 gated loci (3.6%) have any indel-capable panel record.** The other 96.4% are +scored against `--floor-p`, so the floor *is* the filter. Sweeping it proves the point: + +| `--floor-p` | AUC | AQ≥30 recall | precision | +|---|---:|---:|---:| +| 0.0001 | 0.954 | 64/64 | 0.283 | +| 0.001 | 0.945 | 64/64 | 0.312 | +| 0.01 | 0.928 | 63/64 | 0.423 | +| 0.05 | 0.918 | 56/64 | 0.629 | + +That swing dwarfs the choice of `--panel-p` (ΔAUC 0.016 across all three). The `MEAN`-vs-`MAX` +distinction is real — `MEAN` is diluted by the full panel, verified at MAX/MEAN = 45.99 for NR=1 +records, exactly the 46-sample panel size — and `MEAN` is indeed the worst of the three. But it is +a second-order effect when the panel only speaks for 3.6% of sites. + +### Sub-5% recall, the thing most at risk + +12 ECS-confirmed edits below 5% VAF joined the scored set. At AQ ≥ 30 the **matched** baseline keeps +**12/12**; the cohort baseline keeps 10/12. So the conservative test does *not* destroy low-VAF real +edits — the concern that motivated this check does not materialise for the matched baseline. + +### Germline + +Germline-like sites (matched-control VAF ≥ 30%), n = 132: + +- matched baseline: **0/132** reach AQ ≥ 30 — germline is filtered with no dedicated rule, exactly + as the binomial argument predicts. +- cohort baseline: **1/132** escapes. The cross-donor failure mode is real but rare here, because + pooling 31 donors' controls does capture most germline. Worked example — + `RXRB-KO-DNA chrX:105,625,831`, treated 9/14 (0.64 VAF), matched control 28/64 (0.44): + AQ 9.7 matched vs **31.2** cohort. + +## The decisive result + +Applying the scorer *in place of rule 4* — arm 5 (rules with rule 4 disabled) plus an AQ cut: + +| | Queue | conf | rej | precision | +|---|---:|---:|---:|---:| +| arm 5, no filter | 92 | 64 | 10 | 0.865 | +| **arm 5 + matched AQ ≥ 30** | **91** | **64** | **9** | **0.877** | +| arm 2 (the PoN), for reference | 88 | 64 | 9 | 0.877 | +| arm 5 + matched AQ ≥ 60 | 77 | 59 | 6 | 0.908 | +| arm 5 + matched AQ ≥ 100 | 59 | 47 | 1 | 0.979 | + +**AQ ≥ 30 on the matched-control baseline matches the panel of normals exactly** — same recall +(64/64), same rejected count (9), same precision (0.877) — while needing no cohort at all. Pushing +to AQ ≥ 60 buys precision 0.908 but costs 5 confirmed edits; that trade is not worth taking. + +## What this means for the single-sample user + +The distinction that matters is **matched control ≠ panel of normals**: + +- A user with **one edited sample and its paired unedited normal** can drop rule 4 entirely and lose + nothing. This is the realistic case and the recommendation. +- A user with **no control material whatsoever** falls back to the DRAGEN panel, where precision is + 0.31 rather than 0.68 and the result is governed by an arbitrary floor. The external panel is a + weak backstop, not a PoN substitute. + +## The failure mode Tier 1 actually has (and it is not missing controls) + +All 32 samples carry a matched control: median depth **170×** (range 99–172), and none shows the +degenerate "control depth present but zero alt reads anywhere" signature left by the pre-fix caller. +So the no-control tier does not arise for this assay. + +The real risk is the opposite of over-conservatism — it is **over-confidence on a clean control**. +66.4% of gated rows (995/1,498) have *zero* alt reads in the matched control. For those the +posterior collapses to a background of **3.5e-5**, roughly 70× below the fitted global prior mean of +2.44e-3. A clean control at 170× can honestly support a bound of about 1/170 = 0.59%; the posterior +instead asserts something near 1-in-28,000, because `alpha` stays at `a0` while `beta` grows with +depth. + +On this cohort that never bites, and the reason is the gate, not the model: only **2** gated rows sit +below the control's 0.59% resolution limit, and **neither reaches AQ ≥ 30**. The `VAF >= 0.005` gate +is what protects the result. + +That makes Tier 1 safe as currently configured and **fragile if the gate is ever lowered** — which is +exactly what a deliberate low-VAF off-target hunt would do. The fix is to floor the posterior +background at roughly `1 / control_depth` rather than let it run to `a0 / (a0 + depth)`, so the model +cannot claim more resolution than the control has. Not implemented here. + +## What was implemented + +The floor is on by default, and it **rescales AQ** — it does not cost anything at the operating +point, but it moves the threshold. Re-measured with the floor active: + +| | Queue | conf | rej | precision | +|---|---:|---:|---:|---:| +| rule 4 disabled, no AQ | 92 | 64 | 10 | 0.865 | +| + floored AQ ≥ 3 | 91 | 64 | 9 | 0.877 | +| **+ floored AQ ≥ 5** (default) | **91** | **64** | **9** | **0.877** | +| + floored AQ ≥ 8 | 90 | 64 | 9 | 0.877 | +| + floored AQ ≥ 10 | 87 | 63 | 9 | 0.875 | +| the PoN, for reference | 88 | 64 | 9 | 0.877 | + +3–8 form a plateau that reproduces the PoN exactly; 10 is the cliff where a confirmed edit is lost. +Default `review_aq_min = 5` sits in the middle. (Without the floor the equivalent threshold was 30 — +the same decision, different scale.) + +Shipped as: + +- `bin/noise_model.py` — `control_posterior`, `apply_depth_floor`, `fit_global_prior`, reused by + the filter rather than duplicated. +- `bin/review_filter.py` — `--noise-model {off,matched,loo,both}`, `--aq-min`, `--no-depth-floor`, + `--strict-fallback`. When the model is on it **replaces** rule 4 and the PoN is not passed + alongside it, so a run's provenance stays readable. `why_dropped` reads + `indistinguishable from control noise (AQ<5)`. +- Pipeline params `review_noise_model`, `review_aq_min`, `review_depth_floor`, + `review_strict_fallback`, wired through `modules/local/review_filter.nf` into **both** + invocations and registered in `nextflow_schema.json`. + +**Default is `off`.** Verified: with defaults the 88 and 87 baselines still reproduce, and the +87-row queue is byte-identical to the pre-change output. + +### The Tier 2 guardrail + +The dangerous state is silent: no PoN, no noise model, and a single guide in the invocation means +cross-guide recurrence cannot fire, and the unfiltered queue is indistinguishable from a precise +one. That now prints a boxed `RULE 4 IS NOT ACTIVE` warning naming the three fixes, and +`--strict-fallback` / `review_strict_fallback = true` turns it into a non-zero exit. It stays silent +when `--noise-model` covers rule 4. + +## Incidental, and worth shipping + +Restricting the 1 GB panel to the positions a cohort can query collapses it from **97,851,753 to +4,891 records (60 KB)** and produces **byte-identical** filter output. That removes the ~6 min +streaming cost and makes the tabix question moot. + +## Annotate in the caller, filter in the TSV + +With the PoN gone, nothing in the filter needs a cohort — so the two-stage split had to be +re-justified. It survives, on cost asymmetry: + +| stage | cost | +|---|---| +| `REVIEW_FILTER`, whole cohort, from TSVs | **1.78 s** | +| `GET_INDELS`, per sample, from CRAM | **50 min – 1h 28m** | + +~2,000×. Every threshold here (`min_reads`, `min_vaf`, `max_cut_dist`, `min_distinct_len`, +`aq_min`) was calibrated by re-running the filter; moving those decisions into the caller converts +each experiment from seconds into hours and deletes the `why_dropped` audit trail — including the +**753 of 1,498** rows sitting 11–25 bp from the cut, which are exactly the evidence for the 10 bp +threshold. The intermediate TSVs are **27 MB** total, so there is no I/O argument either way. + +So: computation moves to the caller, decisions stay in the filter. `add_features` now **consumes** +caller-supplied columns and derives them only as a fallback, which keeps tables from older callers +working unchanged. + +### The cut-distance trap + +`min_cut_distance` (caller) and `cut_dist_min` (filter) are **not the same quantity**, and swapping +one for the other silently changes results. The caller's is +`min(|pos − PAM|, |pos + len(ref) − 1 − PAM|)`; the filter's is derived from `indel_info`, measured +from the anchor base only, and therefore always larger (`find_edited_reads.py:2263` documents this). +Measured on the 32-sample cohort they disagree on **162 of 1,498** gated rows — rule 2 drops 838 vs +682 — while both retain all 64 confirmed edits. + +The caller's metric is the more correct one, but the 10 bp threshold was calibrated against the +other. So it is exposed as `--cut-dist-source {indel_info,caller}`, defaulting to the calibrated +one, pending recalibration. + +### What deliberately did NOT move into the caller + +- **The beta-binomial.** It reads `indel_reads`, `total_reads`, `control_indel_reads`, + `control_reads` — all already columns. It never opens a BAM, so putting it in the caller buys no + avoided work, forces a global-prior fit into a streaming writer (`find_edited_reads.py` writes + rows as it goes, `flush=True`), and freezes `bg_rate`/`AQ` behind a 1.5 h rerun. Verified + separately that the prior is not cohort-dependent: refitting per sample gives **0 of 1,498** + decision flips at AQ≥5 and an identical queue. +- **The repeat and panel intersects.** `RepeatIndex` loads 5.28M intervals and the panel is a 1 GB + stream, both currently paid **once per cohort**; per sample they become 32×. `bin/subset_noise_panel.py` + makes the panel side cheap enough to move later (once per *guide*, not per sample) if wanted. + +## Production configuration (2026-08-13) + +The PoN is off, the noise model is on, and there is one cut-distance threshold. + +| param | was | now | +|---|---|---| +| `review_noise_model` | `off` | **`matched`** | +| `review_auto_pon` | `true` | **`false`** | +| `find_edited_reads.py -d` | 25 | **10** | +| filter-side cut-distance metric | derived from `indel_info` | the caller's `min_cut_distance` | + +**One distance rule.** The caller enforces it at `-d 10` on `Distance` = +`min(|pos − PAM|, |pos + len(ref) − 1 − PAM|)`; the filter's rule 2 reads the same value from +`min_cut_distance` and is now a consistency guard that drops nothing. Recalibrated against the +curated label before changing the default: thresholds **6, 8, 10, 12 and 15 all hold 64/64 confirmed +edits at precision 0.877**; only 25 degrades it (0.831). 10 sits inside that plateau. + +**Quality is unchanged by dropping the PoN.** Same 32 tables, new config vs old: + +| | queue | confirmed | rejected | precision | ECS | sub-5% | on-target | +|---|---:|---:|---:|---:|---:|---:|---:| +| old (PoN, `indel_info` distance) | 87 | 64 | 8 | 0.889 | 70/70 | 12/12 | 81/81 | +| **new (no PoN, matched AQ, caller distance)** | 96 | 64 | 8 | **0.889** | 70/70 | 12/12 | 81/81 | + +Identical on every quality axis. The queue grows by 9 rows, all of them *unlabeled* candidates the +curated review never adjudicated — the cost of the correct, more permissive distance metric, not a +loss of precision. `PON_SCORE` and `BUILD_PON` no longer appear in the DAG, which also removes a +per-control scoring step from every run. + +The legacy path still works: tables written before `min_cut_distance` existed fall back to the +`indel_info` derivation, print a warning that rule 2 will be stricter than the caller's, and +reproduce the previous 87-row queue **byte-identically**. + +⚠️ Changing `-d` alters the caller's task hash, so the next run **re-executes all 32 `GET_INDELS` +tasks** (~50 min–1h 28m each) rather than resuming them. + +## Does rule 4 make rule 1 redundant? + +Fair question once rule 4 became a control-based statistical test: rule 1 (drop sites whose matched +control carries the indel at ≥5% VAF) is also a control-based germline check, so it looks like the +crude version of the same idea. **It is not, and it must stay.** Measured on the same 32 tables, +rule 1 disabled via `--max-control-vaf 1.1`: + +| | queue | confirmed | rejected | precision | ECS | sub-5% | on-target | +|---|---:|---:|---:|---:|---:|---:|---:| +| **rule 1 ON** (production) | 96 | 64/64 | 8 | **0.889** | 70/70 | 12/12 | 81/81 | +| rule 1 OFF (rule 4 only) | 99 | 64/64 | 9 | 0.877 | 70/70 | 12/12 | 81/81 | + +Recall is identical either way, so **rule 1 costs nothing** — it drops no confirmed edit, no +ECS-confirmed edit, and no on-target site. It buys back one human-rejected site and 0.012 precision. + +### Where the two rules diverge + +Of the 221 gated rows with matched-control VAF in [5%, 30%) — every one of which rule 1 drops — +rule 4 drops 195 but **keeps 26**. Other rules catch 23 of those (12 single indel length, 8 repeat, +3 far from PAM). **Three reach the queue**, and they are the whole argument: + +| sample | site | edited | matched control | AQ | +|---|---|---|---|---:| +| CART_NS0027-CTLA4_1 | chr8:50,010,776 | 15/81 (18.5%) | 8/97 (8.2%) | 17.13 | +| CHD2-KO-DNA | chr20:60,991,255 | 20/77 (26.0%) | 42/186 (**22.6%**) | 5.33 | +| CNNM3-KO-DNA | chr15:52,552,620 | 4/26 (15.4%) | 11/159 (6.9%) | 9.45 | + +CHD2 is the clearest: 26.0% in the edited sample against 22.6% in its *own* matched control — +near-identical fractions, plainly shared rather than edited — and the beta-binomial still passes it. + +That is structural, not a tuning miss. The binomial asks **"is k surprising given p?"**, and at 77 +reads a modest excess over a high background clears a low bar. Rule 1 asks a different question — +**"does the control carry this at all?"** — which is the right question for germline. Two different +tests, both load-bearing. + +### Raising `aq_min` cannot absorb rule 1 + +The obvious alternative fails, and fails expensively. Rule 1 off, sweeping the AQ cut: + +| `aq_min` | queue | confirmed | ECS | on-target | +|---|---:|---:|---:|---:| +| 6 | 98 | 64/64 | 70/70 | 81/81 | +| 10 | 93 | 63/64 | 70/70 | **80/81** | +| 18 | 90 | 63/64 | **69/70** | **79/81** | + +Catching all three needs `aq_min > 17.13`. By 10 a confirmed edit and an on-target site are already +gone; by 18 it is two on-target sites and an ECS-confirmed edit. **No AQ threshold separates those +germline sites from real edits** — they rank *above* genuine edits in AQ order, so no cut divides +them. Keep both rules. + +## Reproduce + +``` +# Part A, arm 4 (rule 6 standing alone) +bin/review_filter.py results_cart_ponfix/*/*.offtarget_analysis.tsv \ + --repeats rmsk.no_simple.bed GRCh38_no_alt.trf.bed \ + --max-guides 9999 --snv-noise IDPF_...snv.bed.gz \ + --min-reads 2 --min-vaf 0.005 -o arm4.tsv + +# Part B +bin/noise_model.py results_cart_ponfix/*/*.offtarget_analysis.tsv --baseline matched -o scored.tsv \ + --truth-wgs "Manual Indel Review/cart_wgs/cart_wgs_merged.xlsx" \ + --truth-ecs "Manual Indel Review/cart_ecs/cart_ecs_merged.csv.gz" + +# Rule 1 redundancy check -- disable rule 1 by putting its threshold out of reach. +# --keep-all then gives every gated row with its AQ, control VAF and why_dropped. +bin/review_filter.py /*.offtarget_analysis.tsv \ + --repeats rmsk.no_simple.bed GRCh38_no_alt.trf.bed --snv-noise panel.subset.bed.gz \ + --noise-model matched --max-control-vaf 1.1 \ + --min-reads 2 --min-vaf 0.005 --keep-all -o audit.tsv +``` + +Note when parsing `--keep-all` output: `why_dropped` is empty for surviving rows, and pandas reads +that as `NaN`, not `""`. Filtering with `== ""` silently returns nothing — `fillna("")` first. + +## Not done + +- `noise_model.py` is **offline**; the `np.select` chain in `review_filter.py` is unchanged. +- No sub-2.5% truth exists in either review, so behaviour below that VAF is still unmeasured. +- A custom baseline built with DRAGEN natively (`--build-sys-noise-vcfs-list`, + `--build-sys-noise-method=max`) would give the panel format from our own controls; not attempted. diff --git a/docs/NOISE_MODEL_VALIDATION.md b/docs/NOISE_MODEL_VALIDATION.md new file mode 100644 index 0000000..dfd5e16 --- /dev/null +++ b/docs/NOISE_MODEL_VALIDATION.md @@ -0,0 +1,340 @@ +# Does the background model describe the data? + +The model was described verbally and the objection raised back was, in substance, that it **mushes +two physically distinct processes into a single distribution**: + +- **Machine physics** — sequencing, PCR and alignment error. A per-base Bernoulli process whose + rate is tiny, is *not* globally fixed, and varies with the physical sequence context. +- **Biology** — germline variation in the donor. Not error at all: a real allele near VAF 0.5 or + 1.0, and specific to *that* donor. + +A single Beta fitted across both is being asked to describe a population that does not exist. + +**That reading of the data is correct, and this document confirms it directly.** What it also +shows — and this is the part that was not expected — is that the mis-specification does **not** +produce the failure it should, for a specific and interesting reason. The findings do not all point +the same way, and they are reported here in the order they came out rather than sorted to support a +conclusion. + +Everything below is reproducible with: + +```bash +python3 bin/noise_model_validate.py \ + --tables 'results_cart_bnd/*/*.offtarget_analysis.tsv' \ + --queue-all results_cart_bnd/review/review_queue_all.tsv \ + --truth-wgs '.../cart_wgs_merged.xlsx' \ + --fasta .../hg38_PLVM_CD19_CARv4_cd34.fa \ + --figdir docs/images --calib-seeds 20 +``` + +`--calib-seeds` controls the seed sweep in §3; the expensive per-observation tail is computed once +per model and only the uniform draw is repeated, so raising it is nearly free. Runtime ~6 min. See [`NOISE_MODEL.md`](NOISE_MODEL.md) for what the model *is*. + +--- + +## Summary of findings + +| # | question | answer | +|---|---|---| +| 1 | Are there two populations? | **Yes, unambiguously.** 99.4% at exactly zero, a second mode at 0.18, nothing between. | +| 2 | Does a better model fit better? | Marginally. Binomial is catastrophic; the three Beta-Binomial variants are within 0.003 nats. | +| 3 | Is the shipped model *calibrated*? | **Yes, by effect size.** KS D ≈ 0.004 against a genuine null vs **0.140** for the Binomial — a 35× gap, stable across seeds. (The KS *p*-value is seed-dependent and should not be quoted; see §3.) | +| 4 | Is the error rate context-dependent? | **Yes, strongly.** ≥9 bp homopolymers run at **33×** the cohort rate. | +| 5 | Is the depth floor a patch? | Yes in origin — but the explicit alternative is unidentifiable, so it stays. | +| 6 | Does any of it move the queue? | **No.** Every Beta-Binomial variant drops the same 1 row. | + +Every assumption behind these answers — including two that turn out to be violated with measurable +consequences — is enumerated in [`NOISE_MODEL_ASSUMPTIONS.md`](NOISE_MODEL_ASSUMPTIONS.md). Two +results there qualify what follows: the model **under-predicts the background at clean loci by +~12×** (CI excludes 1), and its count distribution has the wrong *shape* despite an exactly correct +mean. + +**The headline, stated plainly:** the objection is physically right and statistically inert on this +cohort. The two populations are real and visible; the sequence-context effect is real and large; +but the shipped prior's *shape* already absorbs both well enough that no candidate replacement +changes a single call. The one genuine gap — the sub-detection machine-error rate — cannot be +closed with a matched control at all, and that is where the DRAGEN panel has a principled role. + +--- + +## 1. The two populations + +Over the 95,073 site-rows carrying control depth: + +``` +zero control alt reads : 94,502 / 95,073 = 99.40% +nonzero : 571 median 0.179 q25 0.039 q75 0.292 +smallest nonzero rate : 0.004695 (= 1 read at that depth) + +observations in (0, 0.001) : 0 +observations in (0.001, 0.01 ) : 89 +observations in (0.01, 0.05 ) : 61 +``` + +**There is nothing between the two modes.** Not "few" — zero observations in (0, 0.001), and the +smallest nonzero rate is exactly one read. This is a point mass at zero (machine error, below +detection) plus a germline mode (biology), and nothing in between that a continuous unimodal +distribution could be describing. + +![two populations](images/noise_two_populations.png) + +Method of moments matches a mean and a variance. Applied to this mixture it returns +`Beta(0.002034, 1.639)`, whose mean of **0.00124 sits between the two modes, where no locus lives**. +The fit is not badly tuned; on its face it is fitting a population that does not exist. + +### Why the control cannot see the machine-error rate + +Median control depth is **157×**, so one read is **0.64% VAF**. The matched control physically +cannot resolve an error rate below that. Everything the machine-error process actually does lives +underneath the detection limit, and the zero bin is that limit, not a measurement of zero. + +**This is the real reason the ad-hoc depth floor exists** (§5), and the real argument for the panel +(§7). + +### Data hazards, handled explicitly + +- **4,165 rows have zero control depth.** They keep the global prior; there is no depth from which + to derive a floor. +- **3 rows have `control_indel_reads > control_reads`.** The caller *sums* alt counts over the + events at a site but takes the *mean* of control depth, so these are not a clean `(k, n)` pair + and `betabinom` is undefined for `k > n`. The script clips `k` to `n` by default + (`--kn-policy drop` to exclude them instead); at 3 rows the choice changes nothing, but it is a + choice and it is recorded. + +## 2. Model comparison — held-out log predictive likelihood + +Split **by locus** (so a locus cannot appear in both halves): 47,527 train / 47,546 test over +30,194 distinct loci. Higher is better. + +| model | fitted parameters | held-out mean log-lik | +|---|---|---:| +| Binomial, global `p` | p = 0.00123 | **−1.0293** | +| Beta-Binomial, MOM prior (**shipped**) | Beta(0.00268, 2.151) | −0.0562 | +| Beta-Binomial, max marginal likelihood | Beta(0.00142, 1.295) | −0.0530 | +| Zero-inflated Beta-Binomial | π=0.536, ε→0, Beta(0.0031, 1.30) | −0.0530 | + +**The Binomial is catastrophically worse — 18× the loss per observation.** That is the single +clearest quantitative vindication of using a compound distribution at all, and it settles "why not +just use an error rate?" on its own. + +**The three Beta-Binomial variants are indistinguishable.** Proper empirical Bayes (max marginal +likelihood) buys 0.003 nats over method of moments. The explicit two-component mixture buys +0.000002 nats over that — i.e. nothing. + +### The mixture is not identifiable, and that is the explanation + +Fitting the zero-inflated model on the training half gives π = 0.536; fitting it on all the data +gives π = **0.993**. The mixing weight swings by a factor of two while the held-out likelihood does +not move at all. + +The reason is in the shape of the shipped prior. **A Beta with `a < 1` is already spike-at-zero +shaped** — its density is infinite at `p = 0` and decreasing throughout. So the "clean" component +and the low end of the Beta component explain the same observations, and the data cannot apportion +between them. + +**The explicit mixture is re-describing what the fitted prior's shape already encodes.** That is +why the conflation of two processes does not produce the failure it should: method of moments, +applied to a bimodal population, happened to land on a family member whose shape mimics zero +inflation. The criticism is right about the population and wrong about the consequence. + +## 3. Calibration + +The decisive test, and it needs no new data. **Score each donor's own control counts against the +other donors' controls at the same locus.** Both sides are unedited material, so anything that +scores as signal is a miscalibration by construction. 6,876 loci carry ≥2 donors; 71,755 +observations. + +> **Why randomised p-values.** With discrete counts the ordinary survival function *cannot* be +> Uniform even under a perfect model — it is bounded below by P(X = k), and with 99% of +> observations at k = 0 the mass piles at 1. The randomised p-value `U·P(X = k) + P(X > k)` with +> `U ~ Uniform(0,1)` is exactly uniform under a correct discrete model, and is what makes this test +> meaningful at all. A naive QQ plot here would look broken for every model, including a correct one. + +> **A randomised test must be reported as a range, not a number.** Every p-value below is one +> *draw*. Re-running with a different seed gives a different answer, and at n = 71,755 the KS +> p-value swings across nearly the whole unit interval while the KS **D** statistic barely moves. +> So D is the statistic to read and p is not; the table reports both, swept over 20 seeds +> (`--calib-seeds`). All models are scored on the **same** draws, so differences between rows are +> differences between models rather than between random states. + +| model | KS D (seed 0) | mean | frac < 0.05 | frac < 0.001 | **D over 20 seeds** | **KS p over 20 seeds** | rejects at 0.05 | +|---|---:|---:|---:|---:|:---:|:---:|---:| +| *(calibrated)* | 0 | 0.500 | 0.0500 | 0.00100 | — | — | 1/20 expected | +| Binomial, global `p` | **0.1400** | 0.574 | 0.0060 | **0.00523** | 0.1383 – **0.1398** – 0.1414 | 0.000 – 0.000 – 0.000 | **20/20** | +| Beta-Binomial, MOM (**shipped**) | 0.0048 | 0.501 | 0.0508 | 0.00169 | 0.0028 – **0.0037** – 0.0062 | 0.009 – 0.277 – 0.624 | 1/20 | +| Beta-Binomial, MML | 0.0047 | 0.501 | 0.0510 | 0.00183 | 0.0028 – **0.0038** – 0.0062 | 0.007 – 0.242 – 0.629 | 2/20 | +| Zero-inflated BB | 0.0048 | 0.501 | 0.0510 | 0.00188 | 0.0028 – **0.0038** – 0.0063 | 0.007 – 0.238 – 0.614 | 2/20 | + +(ranges are min – **median** – max) + +![calibration](images/noise_calibration_qq.png) + +**The shipped Beta-Binomial is calibrated, and the honest way to say so is by effect size.** Its +deviation from Uniform is D ≈ 0.003–0.006 depending on the draw, against **0.1398** for the +Binomial — a **35× gap that is stable at every seed**, and the part of this result that carries no +caveat at all. That is the finding: it did not go the way the objection predicted. + +**What cannot be claimed is a clean pass on the naive p-value.** One seed in 20 rejects at +α = 0.05 — so "p = 0.08, it does not reject" was never a property of the model, only of seed 0. +**Quote D, not p.** An earlier version of this table quoted a single seed's p-value and is +superseded. + +> **That marginality has since been explained, and it is an artifact.** The KS null assumes +> independent observations; these are not. 71,755 observations come from 6,876 loci, and each is +> scored against a background built from the other donors *at that same locus*. Using the locus as +> the independent unit, `D_crit(0.05) = 1.358/√6876 = 0.0164` — the shipped model's **worst** seed +> is 0.0062, so it passes at every seed with 2.7× margin, while the Binomial (0.1414) still fails +> by 8.6×. The verdict does not depend on the accounting; only the comfort does. Full treatment, +> along with the other two KS assumptions, in +> [`NOISE_MODEL_ASSUMPTIONS.md`](NOISE_MODEL_ASSUMPTIONS.md#q1--what-does-the-kolmogorovsmirnov-test-assume). + +> **A correction this exposed.** That earlier table also showed MML at D = 0.0025 against MOM's +> 0.0047 and bolded MML as the best-calibrated model. That gap was **an artifact of the random +> draws**, not a real difference: the models were scored on independently drawn p-values rather +> than shared ones. Scored on the same draws, all three Beta-Binomials land within 0.0001 of each +> other at every seed. This *strengthens* §2's conclusion — the variants are indistinguishable by +> held-out likelihood **and** by calibration — but the earlier ranking should not be repeated. + +**The Binomial fails badly, and in the specific way that matters.** It produces **5.2× too many +p-values below 0.001** while producing 8× too *few* below 0.05. That is the exact failure mode the +model was built to avoid: a fixed `p` is systematically overconfident in the extreme tail, which is +the only region a variant filter reads. + +Stratifying by the conditions where mis-specification should bite hardest — thin donor support, and +control depth above/below the median — the shipped model stays calibrated in every stratum +(D ≤ 0.017). The worst stratum is thin support (1 other donor, D = 0.0162, n = 2,926), where the +prior dominates; that is the expected direction, and the size is small. Deep controls (≥ 157×, +D = 0.0083) are mildly worse than shallow ones, consistent with §1: more depth means more +opportunity to resolve the germline mode the single prior is not shaped for. + +## 4. Sequence context + +**This is where the objection is confirmed outright.** The Bernoulli rate is not a constant of the +assay. Homopolymer run length was derived from the reference FASTA with `pysam` +(longest run overlapping ±12 bp of the site, measured at full length rather than clipped to the +window): + +| stratum | n | observed rate | fitted prior mean | % nonzero | +|---|---:|---:|---:|---:| +| no run (≤3 bp) | 60,761 | 0.001177 | 0.001163 | 0.53% | +| 4–5 bp | 32,037 | 0.001107 | 0.001276 | 0.56% | +| 6–8 bp | 2,162 | 0.000572 | 0.000495 | 1.39% | +| **≥9 bp** | **113** | **0.039231** | **0.040122** | **35.40%** | + +**Sites in a ≥9 bp homopolymer carry indel evidence in the unedited control 35.4% of the time +against 0.53% in unique sequence (67× more often), at an indel rate of 0.0392 against 0.0012 +(33× higher).** A single global prior necessarily +under-penalises that context and over-penalises clean unique sequence. The worked example in +[`NOISE_MODEL.md`](NOISE_MODEL.md#5-a-worked-example-end-to-end) is exactly this case: a 15 bp T +homopolymer whose four "events" are ±1–2 T slippage. + +Two honest caveats: + +- **The trend is not monotone below 9 bp.** The 4–5 and 6–8 strata are not separated from the + baseline by rate (6–8 is actually *lower*), only by the fraction of nonzero observations. The + effect is a threshold at long runs, not a smooth gradient. +- **n = 113 in the top stratum.** The effect size is large enough that this is not a sampling + fluke, but the stratum-specific prior is fitted on little data. + +### What it would cost — nothing, today + +| stratum | gated rows | rows in the queue | +|---|---:|---:| +| ≤3 bp | 271 | 76 | +| 4–5 bp | 136 | 10 | +| 6–8 bp | 36 | 0 | +| ≥9 bp | 36 | **0** | + +**No queue row sits in a ≥9 bp homopolymer.** All 36 gated rows in that stratum are already removed +by earlier rules. The mis-specification is real, large, and currently free — which is an argument +for fixing it before it costs something, not for fixing it now. + +## 5. The depth floor + +Ablated on the 479 gated rows: + +``` +floor raises the background on 306 of 479 rows (63.9%) + +posterior mean WITHOUT the floor, on those rows: min 3.5e-06, median 2.0e-05 +the fitted prior mean is 1.2e-03 +1 / median control depth is 6.4e-03 +``` + +**Left alone, the posterior claims a background rate ~300× below what a 157× control can support.** +That is the clean-control trap: with `α = a0` and `β = b0 + d`, the mean collapses to `a0/(a0+d)`, +which says "the rate here is essentially zero" on the basis of a control that simply never sampled +deeply enough to say anything. + +The floor exists because **a single Beta has no way to say "this locus is clean; the true rate is +below what this control can resolve."** It is forced to extrapolate, produces an absurd number, and +the floor clamps it. + +The prediction was that an explicit zero-inflation component would make that statement +representable and render the clamp unnecessary. **It does make the statement representable —** the +mixture puts weight π = 0.993 on a component at rate ε — **but it does not make the clamp +unnecessary, because ε is not estimable.** The MLE drove ε to the denormal floor (10⁻³²⁴). No +observation constrains it from below: at 157×, a rate of 10⁻⁴ and a rate of 10⁻⁴⁰ both predict zero +alt reads with probability ≈ 1. + +**So the floor stays.** It encodes `1/d` as the resolution limit, which is a defensible statement +about what the data can support, and the principled alternative reduces to needing a number the +data does not contain. This is a case where the ad-hoc patch turns out to be the honest option, and +the right fix is to get ε from somewhere else entirely (§7). + +## 6. Operational consequence + +The AQ rule is 4th in `review_filter.py`'s `np.select`, and first match wins — so it only ever sees +rows that rules 1–3 left alone. Of 479 gated rows, rules 1–3 remove 390; **89 rows reach the AQ +test**, 74 of them labelled (64 confirmed / 10 rejected). + +| model | AQ<5 drops | surviving | confirmed | rejected | +|---|---:|---:|---:|---:| +| Binomial, global `p` | 0 | 89 | 64/64 | 10/10 | +| Beta-Binomial, MOM (**shipped**) | 1 | 88 | 64/64 | 9/10 | +| Beta-Binomial, MML | 1 | 88 | 64/64 | 9/10 | +| Zero-inflated BB | 1 | 88 | 64/64 | 9/10 | + +**Every Beta-Binomial variant drops the same single row.** Recall against the curated label is +64/64 for all four models, including the Binomial. + +> Scoring all 479 gated rows instead would show 151–282 rows below AQ 5 and look like a large +> effect. It is not: most of those rows never reach this test in the shipped pipeline. Any future +> comparison must use the 89, or it will overstate the model's reach by a factor of five. + +A model that is statistically better but moves the queue by zero rows has not earned a pipeline +change. **No change to the shipped default is recommended on this evidence.** + +## 7. What to actually do — each component gets the prior only the right instrument can supply + +The two processes need two different kinds of prior, and the reason the current model has a soft +spot is that one instrument is being asked to supply both. + +**Germline / real-allele component → the matched control.** A donor's genotype is a property of +that donor. The correct prior for "is there a real allele here in *this* person" can only come from +*this* person's own unedited material. A 46-donor panel reports a population average and is +structurally incapable of representing one donor's genotype, at any panel size. This is a category +distinction, not a tuning failure — and it is [measured directly](PANEL_AS_FILTER.md#can-the-panel-stand-in-for-rule-1): +the panel misses **64% of the germline calls rule 1 catches**, and the ones it does see are +typically single-donor coincidences. + +**Sub-detection machine-error component → the DRAGEN panel.** This is where the panel intuition is +right and should be adopted. Sub-detection error rate is donor-independent physics — the polymerase +slips the same way in every sample — so pooling donors is legitimate in a way it never is for +germline. One control at 157× cannot resolve it (§1) and the mixture's ε is unestimable from it +(§5); 46 donors pooled can. **The panel is the better instrument for exactly the component the +matched control is blind to**, and `noise_model.py` already has a `panel` baseline to build from. + +**Sequence context → the reference, not either instrument.** The 33× homopolymer effect (§4) is +computable from the FASTA at zero cost and needs no panel and no control. If any of this is +implemented, that is the cheapest piece and the one with the clearest physical basis. + +### Priority, given that nothing changes the queue today + +1. **Nothing urgent.** No candidate model moves a single call on this cohort. Say so. +2. **Context-conditioned prior** — largest measured effect (33×), cheapest to compute, currently + free because no queue row is affected. Fix it before a cohort with long homopolymer targets + makes it expensive. +3. **Panel-derived ε** — the only principled route to the machine-error component, and the answer + to "why not use the panel?" that is actually true. +4. **Leave the depth floor alone** until 3 exists. It is currently the honest option. diff --git a/docs/OFFTARGET.md b/docs/OFFTARGET.md new file mode 100644 index 0000000..c708a41 --- /dev/null +++ b/docs/OFFTARGET.md @@ -0,0 +1,567 @@ +# CRISPR off-target detection + +Everything about finding off-target edits lives here. There are **two separate things** in the +pipeline, and mixing them up is the most common confusion: + +| | what it is | when you use it | how to run | +|---|---|---|---| +| **Review filter** | turns a routine run's call table into a short list a human can actually read | every normal run | on by default | +| **`-entry OFFTARGET`** | a two-assay (ECS + WGS) investigation arm | building or checking the model | `-entry OFFTARGET` | + +Most people only ever need the first one. Start there. + +New to this? [`OFFTARGET_DEMO.md`](OFFTARGET_DEMO.md) runs the whole thing on a 5.5 KB toy genome +in about a minute — no cluster, no cohort data. + +--- + +# Part 1 — Automated review (the routine path) + +The pipeline predicts thousands of candidate sites per guide and scores them all. It used to hand +back a list you had to open one by one in IGV. Now five rules cut that down and draw you a picture +of each survivor. + +**On the 25-sample CAR-T WGS cohort: 238 sites to review became 62, keeping all 61 real edits.** + +| | queue | real edits | false positives | recall | precision | +|---|---|---|---|---|---| +| before | 238 | 61 | 177 | 1.000 | 0.256 | +| now | **62** | **61** | **1** | **1.000** | **0.984** | + +## What you get + +Run the pipeline normally, then look in `/review/`: + +``` +review_queue.tsv the sites to actually look at +review_queue_all.tsv every gated site + why_dropped (the audit trail) +bnd_review_queue.tsv the same triage applied to breakends +snapshots/ one PNG per site in review_queue.tsv +bnd_snapshots/ one PNG per JUNCTION in bnd_review_queue.tsv (not per row) +``` + +Each snapshot has two panels: **the edited sample on top, its matched unedited control below** — +same locus, same scale. That pairing is the whole point. Germline variants and alignment artifacts +show up in *both* panels; a real edit shows up in only one. Most calls are settled by glancing at +the bottom panel. + +Nothing is silently thrown away. `review_queue_all.tsv` lists every site that cleared the gate +along with the reason it was dropped, so you can check any decision without re-running anything. + +## The five rules + +Sites enter the queue at `indel_reads >= 10 AND indel_fraction >= 0.05`. Then: + +**1. The matched control must be clean** (control VAF < 5%) +If the variant is in the unedited sample from the same donor, Cas9 didn't make it. Biggest filter +by a wide margin. + +**2. The indel sits within 10 bp of a PAM** +Cas9 cuts ~3 bp from the PAM. Confirmed edits sit at a median of 2–4 bp; background indels don't. +Depth-stable — resample a real edit down to 3 reads and 100% still pass. + +**3. At least 3 distinct indel lengths** +NHEJ makes a spectrum of deletion sizes at one cut site. One length repeated across every read is +an alignment artifact. +⚠️ **Depth-sensitive.** At 3 supporting reads only ~49% of real edits still pass. Safe here because +everything in the queue already has ≥10 reads. Don't reuse this rule to chase lower-VAF events — it +quietly reimposes a read-count floor. + +**4. Not background noise** — see [the noise model](#the-noise-model). + +**5. Not in a repeat region** +The candidate panel is built from sequence homology, so it's deliberately enriched for repetitive +and paralogous sequence — exactly where aligners invent indels. + +On-target sites are exempt from rules 4 and 5, since they're shared across samples by design. + +## Breakends + +An indel is one cut healed badly. A **breakend** is two cut sites joined to each other — and on +this cohort that is overwhelmingly what survives triage: **23 of 25 queue rows are multi-cut +inversions**, two cuts from the same guide's own target set with the segment between them flipped +end-for-end and re-ligated at both cuts. The pipeline has always emitted these. Until now it never +labelled them and never drew them. + +> **Orientation is what separates an inversion from a deletion, and it is not optional.** Every +> queue row is `+-` or `-+`: the two joined segments run in opposite directions. A deletion joins +> its flanks *collinearly* (`++`/`--`) and makes ONE junction; an inversion makes a reciprocal +> PAIR, one per end of the flipped segment. All eight events here show both junctions of the pair, +> and across every raw breakend record at these eight cut pairs there are **zero** collinear +> (deletion-type) junctions, so the deletion product is absent rather than merely sub-threshold. +> Note also that a same-chromosome, same-strand split read never becomes a BND at all — it is +> resolved to DEL/DUP/INS at `find_edited_reads.py:420` — so a "deletion" label on a +> same-chromosome row in this queue was wrong by construction. It read that way until 2026-08-20. + +`bin/review_filter_bnd.py` applies the breakend analogue of the indel filter. Three rules, not +five, because a junction has two ends and no length spectrum: + +**1. At least 3 supporting reads.** Breakend support is thin — the cohort median is 1 read — so +this is the single most discriminating cut available, and it does most of the work. + +**2. Within 10 bp of a PAM position.** Same rule as indels — and the caller has already applied +the *same* 10 bp cutoff via `-d/--max-mutation-distance`, whose default is **10**, not 25; +`get_indels.nf` passes no override. The two tests are not quite identical (the caller keeps an +event if *either* end is within range, this rule tests one end), but on this cohort **no junction +has a cut distance above 10 at all**, so rule 2 can never fire. Treat "0 dropped" here as +structural, not as evidence the rule works. + +**3. The breakpoint is not promiscuous.** A breakpoint partnering with many unrelated loci is an +alignment hub, not a junction. **On-target sites are exempt**, and that exemption is not optional: +a real Cas9 cut generates junctions to many places, so the true cut sites are among the most +promiscuous breakpoints in the cohort — 6 of the 10 breakpoints with ≥5 distinct partners are the +intended TRAC, TRBC1, TRBC2 and B2M sites. Applying rule 3 without the exemption deletes the real +edits. + +There is no rule 4 here. The matched-control test is applied per event *upstream*: the caller's +`-x/--max-in-control` (default 0) drops any junction with control support before it ever reaches +`bnd_info`. + +> ⚠️ Rule 3 is currently **non-binding** — on this cohort it drops nothing once rule 1 has run. +> It is kept because it costs nothing and is the only defence against an alignment hub that +> happens to be absent from the matched control. Do not read "0 dropped by rule 3" as broken. + +### From 1,022 breakends to 8 junctions + +The SV VCF holds 1,022 records and the queue holds 25 rows, and the gap between those numbers has +been asked about more than once. **It is one threshold, not a cascade.** + +| stage | count | what removed the rest | +|---|---:|---| +| breakend entries in `bnd_info` (= VCF records) | **1,022** | — | +| after rule 1, `reads ≥ 3` | **25** | 997 junctions with 1–2 reads | +| after rules 2, 3, 4 | **25** | **nothing — all three dropped zero** | +| collapsed to events | **8** | grouping, not filtering | + +Support is the whole story. The distribution of reads per junction: + +``` +reads: 1 2 3 4 5 6 7 8 9 13 15 +count: 981 16 6 5 1 3 5 1 2 1 1 +``` + +**981 singletons and 16 doubletons — those 997 are the entire reduction.** The VCF is the *ungated* +sibling of the queue: both read the same `bnd_info` column, and the VCF simply writes every entry +without applying `--min-reads`. So 1,022 vs 25 is not two analyses disagreeing; it is one analysis +before and after its only real threshold. + +The last step, 25 → 8, is grouping and is described below — it is not a filter. + +> **All 25 gated rows are `is_target == 1`**, and rules 3 and 4 exempt on-target sites. Both rules +> were therefore *structurally* inert on this cohort, not merely inactive. "0 dropped" is not +> evidence that they work. + +### A queue row is not an event + +**The 25 rows in `bnd_review_queue.tsv` are 8 junctions.** The caller reports each event from both +ends, at a few bp of position jitter, and under both strand orientations, so one deletion arrives +as three to five rows. Two consequences, and both have bitten: + +- **Never quote a row count as an event count.** 25 breakends across 8 samples means 8 events, one + per sample. +- **Never quote a row's `reads` as the event's support.** ARID4A's rows say 3–4 reads each; the + junction carries 18 against 123–129× depth — a factor of 6. + +`bin/bnd_snapshots.py` collapses rows to junctions on `(sample, sorted([bin, partner_bin]))` — bins +the filter already computes — and renders one figure each. + +### Reading a junction figure + +Each PNG in `review/bnd_snapshots/` is a to-scale schematic of the rearrangement over a 2×2 grid: +left and right breakpoint across, edited sample over its matched unedited control down. Per-column +x-axes only — the two breakpoints have unrelated coordinates. The schematic branches on +orientation: an inverted junction is drawn with the segment **retained and its direction reversed**, +a collinear one as an excision. + +**The evidence is the green reads.** A read spanning a junction aligns in two pieces: a primary +clipped at one breakpoint and a supplementary segment at the partner, linked by an `SA` tag. Any +read whose `SA` lands near the partner locus is drawn green, so a junction reads as a stack of +green alignments all terminating on one base — present in the edited panel, absent from the +control directly below it. That pairing is what makes the figure self-adjudicating, exactly as in +the indel snapshots. + +⚠️ **This evidence used to be invisible.** `bin/pileup_snapshot.py` dropped `is_supplementary` +unconditionally, which filtered out precisely the alignments that constitute a junction. It is now +opt-in per caller (`keep_supplementary`), so indel snapshots are unchanged. The counts involved are +not marginal: at ARID4A, 48 of 60 SA-tagged reads point at the partner locus; at PDCD4, 67 of 71. + +Note the two read counts in a figure header are different statistics and will not agree: the +suptitle's *junction reads* is the caller's filtered support summed over the queue rows, while a +panel's *reads with SA at partner* is every SA-tagged read at that breakpoint. The first is the +conservative one. + +**Not shown: a coverage drop.** Considered and rejected on two independent grounds — these events +are 6–20% VAF, so there is no visible dent, and the per-sample `tagged.bam` is region-limited, so +coverage between the two target islands is zero whether or not anything was deleted. The panel +would have read as a deletion that isn't there. + +| parameter | default | what it does | +|---|---|---| +| `review_filter_bnd` | `true` | run the breakend filter at all | +| `review_bnd_min_reads` | `3` | rule 1 | +| `review_bnd_max_cut_dist` | `10` | rule 2 | +| `review_bnd_max_partners` | `5` | rule 3 | +| `review_bnd_bin_size` | `1000` | bp bin used to group breakpoints | +| `review_sv_noise` | `null` | external DRAGEN SV panel (BEDPE) | +| `review_bnd_snapshots` | `true` | render the junction figures | +| `review_bnd_snapshot_window` | `150` | bp either side of each breakpoint | +| `review_bnd_max_junctions` | `200` | safety cap on figures rendered | + +⚠️ **Only `WGS_hg38_v3.1.0` is safe for `review_sv_noise`.** Measured: `IDPF_WGS v3.0.0` flags 25 +of 25 real junctions and `FF_Heme v3.1.0` flags 24 of 25 — either erases the entire result. + +## The noise model + +Rule 4 asks whether a call is *statistically distinguishable from this locus's background*, not +whether it appears on a blacklist. That matters because a site can carry 1% background in the +control and 40% signal in the treated sample; an existence test throws that edit away. + + AQ = -10 log10 P(X >= k | n, background at this locus) + +The background is an empirical-Bayes Beta posterior built from the control's own reads +(`bin/noise_model.py`). `review_noise_model = 'matched'` (the default) uses **the sample's own +matched control**, so it needs no cohort at all — which is the entire reason the old panel of +normals could be deleted. On the 32-sample CAR-T cohort the two are equal: **64/64 confirmed edits +retained, 9 human-rejected, precision 0.877** — that is the PoN-only arm (queue 88) against the +32×single-sample arm (queue 91), `docs/NOISE_MODEL_EXPERIMENT.md` arms 2 and 6. Equal, and the +matched model does it without a cohort. + +> **Which precision figure to quote.** 0.877/9-rejected above is the *PoN-vs-matched equivalence* +> comparison. **Production is 0.889 with 8 rejected** (queue 96, 64/64 confirmed) — rule 1 on, +> matched AQ, caller-derived cut distance, `NOISE_MODEL_EXPERIMENT.md` "rule 1 ON (production)". +> Both numbers are measured on the same 32 tables and both are correct; they are different rows of +> the same experiment, and the retained-edit count (64/64) is identical in every arm. Always name +> the configuration — quoting either bare makes the two look like a contradiction, which is what an +> earlier version of this file and `README.md` between them managed to do. + +`review_aq_min` (default 5) is the cut. Measured with the depth floor on, 3-8 all reproduce the +PoN result exactly; 10 starts costing confirmed edits. + +**The depth floor.** A control with no alt reads at depth *d* shows the background is below ~1/*d*, +not that it is zero. Left alone the posterior collapses to 3.5e-5 against a 170x control, about +100x beyond what 170 reads can support, and every call at a locus the control never sampled deeply +starts looking significant. `review_depth_floor` (default true) bounds the posterior mean at +1/control_depth. It is harmless at the current `VAF >= 0.005` gate and essential if that gate is +ever lowered for a high-sensitivity run. + +**Germline falls out for free.** A germline het sits near 50% in the matched control, so a 50% +observation in the treated sample is unsurprising and scores low. Measured: 0 of 132 germline-like +sites survive the cut, with no dedicated germline rule. + +**Single guide and no noise model?** Rule 4 falls back to cross-guide recurrence, which needs >=2 +guides passed in ONE invocation and therefore **cannot fire for a single guide**. The filter prints +a boxed `RULE 4 IS NOT ACTIVE` warning in that state; `--strict-fallback` / +`review_strict_fallback` makes it a hard failure instead. + +**No unedited control at all?** Use rule 5 alone (`--review_repeat_beds`). Repeat annotation needs +no controls, no cohort and no guide context, and `--snv-noise` adds the external DRAGEN panel. +Both are weaker than the noise model — the DRAGEN panel has an indel-capable record for only 3.6% +of queried loci, so an arbitrary floor decides the rest — but they work on day one. + +**What about the GATK panel of normals?** Tested and rejected. `1000g_pon.hg38.vcf.gz` catches 15 +of our artifacts but also hits **4 of the 61 real edits** — it's a Mutect2 SNV panel from blood +normals, not an indel-artifact map, so it costs recall: + +| resource | artifacts caught (of 177) | real edits wrongly hit (of 61) | +|---|---|---| +| GATK 1000g PoN | 15 | **4** | +| RepeatMasker | 100 | 0 | +| Tandem repeats (TRF) | 54 | 0 | +| this run's own PoN | 163 | 0 | + +## Is there a model here? + +There's a trained one, and it is **not** what runs. A gradient-boosted classifier on the same +features reaches out-of-fold AUC 0.9992 under leave-one-sample-out validation, and at 100% recall +returns the same 62 sites with 1 false positive that the rules reach. It wins nothing worth a +pickle file and a scikit-learn version pin, so the rules ship. + +One finding from building it is worth keeping: **never give a model `is_target`.** The truth set is +52 confirmed on-target edits against 1 confirmed off-target, so the model learns "on-target ⇒ real" +and scored the cohort's only genuine off-target at p = 0.113 — it nearly threw away the one event +the assay exists to find. Dropping that feature raised AUC *and* moved that event to p = 1.000. + +## Parameters + +| parameter | default | what it does | +|---|---|---| +| `review_filter` | `true` | run the filter at all | +| `review_min_reads` / `review_min_vaf` | `2` / `0.005` | the entry gate | +| `review_max_control_vaf` | `0.05` | rule 1 | +| `review_max_cut_dist` | `10` | rule 2 | +| `review_min_distinct_len` | `3` | rule 3 | +| `review_noise_model` | `matched` | rule 4: beta-binomial vs the sample's own control | +| `review_aq_min` | `5` | AQ below this is background | +| `review_depth_floor` | `true` | bound the posterior at 1/control_depth | +| `review_strict_fallback` | `false` | fail, not warn, when rule 4 has no source | +| `review_snv_noise` | `null` | external DRAGEN noise panel for rule 6 | +| `review_repeat_beds` | `null` | comma-separated repeat BEDs for rule 5 | +| `review_snapshots` | `true` | render the snapshot packet | + +Run it standalone on existing call tables: + +```bash +bin/review_filter.py results/*.offtarget_analysis.tsv \ + --noise-model matched \ + --repeats /path/rmsk.no_simple.bed /path/trf.bed \ + --min-reads 2 --min-vaf 0.005 \ + -o review_queue.tsv +``` + +Add `--keep-all` to get every gated row with its `why_dropped` reason instead of a filtered list. + +## Two caveats before quoting a number + +**Thresholds were fitted on one cohort.** 10 bp and 3 distinct lengths come from 25 CAR-T WGS +samples, not from first principles. They hold across every sample in that cohort, but a new guide +panel deserves a re-check against its own controls. + +**This only operates above the existing gate.** It automates *review* of sites clearing +`reads >= 10 & VAF >= 0.05`; it does not change what's *detected*. At the cohort's ~207× depth that +gate is a genuine ~5% VAF detector. Going below 5% is a different problem this filter doesn't touch. + +## A bug worth knowing about + +Until recently `find_edited_reads.py` reported **no control support at any site, in every run ever +done**. `-x/--max-in-control` drops events seen in the matched control — correct, and still how it +works — but the per-site summary was totalled *after* that filter had already removed the very +events carrying the evidence, so `control_indel_reads` was always 0. + +Nothing was miscalled. But rule 1, the most powerful filter here, was a no-op against those tables. +The fix moves the summation before the filter; old and new output differ in exactly two columns +(`control_indel_reads`, `control_indel_fraction`) and are byte-identical everywhere else. + +**Call tables made before the fix still have zeroed control columns.** `review_filter.py` detects +this and warns. Re-run the caller to get rule 1 back. + +## A second one, in the VCF output + +Until now **every `*.offtarget_svs.vcf` this pipeline ever wrote contained zero records**. + +`bin/bnd_from_indels_to_vcf.py` had its tab and newline escapes written doubled — `'\\t'` and +`'\\n'`, which in Python source is a backslash followed by a letter, not a control character. The +header line was split on the two-character string backslash-t, never matched, so the `bnd_count` +lookup failed, defaulted to `'0'`, and **every row took the `continue` branch**. The output was a +single line of literal backslash-n text; `wc -l` reported 0. Nothing downstream checked, because a +VCF with no records is exactly what a sample with no breakends should produce. + +Nothing was miscalled and no analysis is affected — the triaged breakend queue is produced by a +different script from the same source column, and it was always correct. What was lost is a +published output file: the per-sample breakend VCF was empty for every sample ever run. + +The fix also carries evidence that the old code discarded: `SR=` and `CTRL=` now report supporting +and control read counts, and reciprocal junctions are linked with `MATEID` rather than emitted four +times. On the 32-sample CAR-T cohort this is **1022 breakend records where there were 0**, verified +in the 2026-08-17 run: 32/32 samples populated, 3–95 records each. + +Only the VCF step needs re-running, not the caller — the `bnd_info` column it reads from was never +wrong. + +### What this fix does *not* do + +It does not put breakends in the HTML report, and an earlier draft of this section wrongly said it +would. `COMPILE_REPORT_JSON` does consume the VCF, and the report JSON's `tables.bnd_vcf` is now +populated for all 32 samples — but **`bin/make_scge_report.qmd` never references `bnd_vcf`** (grep +it: zero hits), and neither does `bin/make_scge_excel.py`. The report's SV panel is driven by +`tables.on_target_sv_transgene`, a transgene-junction annotation table that is a different thing +entirely and is empty in **all 32** samples of this cohort — so that panel still reads "No on-target +SV/transgene data available in the report", and did so for its own unrelated reason all along. + +Surfacing breakends in the report is therefore a template change, not a data change, and the data +is now sitting there waiting for it. Two separate defects; only the first is fixed. + +> `bin/tsv_to_vcf.py` carries the same defect and is deliberately untouched: no module references +> it. Fix it before wiring it to anything. + +--- + +# Part 2 — `-entry OFFTARGET` (the investigation arm) + +A separate arm that runs via a named entry and does not touch the default pipeline. It pairs deep +error-corrected sequencing (**ECS — the truth arm**) against ordinary WGS (**the arm under test**) +to ask: could WGS alone have found these edits? + +## Running it + +```bash +sbatch run_offtarget.sh --input --outdir [--snapshots] +``` + +or directly (from somewhere that can `sbatch` — not the interactive exec node): + +```bash +nextflow run . -entry OFFTARGET -profile ris2,apptainer \ + --input offtarget_samplesheet.csv --outdir ./results_offtarget -resume +``` + +On Compute1 (LSF) use `-profile ris` under `bsub`. + +## Samplesheet + +Columns: `sample,datatype,guide,edited_cram,control_cram,target_file,vcf` +(template at `assets/offtarget_samplesheet_template.csv`) + +- `datatype` is `ecs` or `wgs` — this sorts each row into the right arm. +- `guide` links an ECS sample to its WGS partner; same guide means same experiment. +- For a WGS row, point `edited_cram` at the DRAGEN `_tumor.cram` and keep `.cram` (the + normal) and `.hard-filtered.vcf.gz` beside it. The scripts find them by name. +- Use absolute paths — CRAMs are read off storage, not copied in. + +What runs depends on what you give it: **ECS + WGS** → everything; **WGS only** → worklist and +report; **ECS only** → hotspot truth tables. The run logs which mode it picked, and fails +immediately with the offending file and row if a DRAGEN sidecar is missing. + +## What you get + +Everything lands in `/offtarget/`: + +- **`wgs_offtarget_worklist_pon.csv`** — the main result. Every candidate edit found in the WGS, + ranked, germline and artifacts already knocked out by the PoN. Start here. +- **`offtarget_report.csv`** — the worklist plus whether each hit is a known hotspot and whether + ECS confirmed it. +- **`.offtarget_analysis.tsv`** — the ECS answer at each hotspot: edited or not, at what VAF. +- **`recall_vs_vaf.csv` / `.png`** — how often WGS catches an ECS-confirmed edit, by VAF. +- **`offtarget_metrics.json` / `.txt`** — PR-AUC and F2/F5 for the shape score. **Read the + denominator section first** — precision here is against the ECS label, *not* human review. +- **`training.tsv`** — WGS features lined up against the ECS answer. Only used for retraining. + +The last three need both ECS and WGS. + +## Optional review aids + +**Snapshots** (`--offtarget_snapshots true`) — an IGV-style pileup per LIKELY EDIT, edited beside +matched normal. Off by default since it renders one image per hit. + +**Per-read tags** (`--offtarget_tagged_bam true`) — writes `.tagged.bam` where every read +carries an `XC` tag naming how the caller classified it. In IGV: load the BAM → right-click → +**Color alignments by → tag → `XC`**. + +| tag | meaning | +|---|---| +| `Edited_Deletion_bp` / `_Insertion_` / `_Duplication_` | the event that was called | +| `Edited_BND_` | breakend — the read's mate maps to `` (e.g. the transgene) | +| `Edited_SoftClip` | recovered by realigning a soft clip | +| `Unedited_WT` | spans the target cleanly — this is the denominator | +| `Skipped_*` | excluded by a read filter, shown so you can see *why* | + +Each alignment appears exactly once, so IGV's depth is real. + +**Don't expect tag counts to match the TSV.** Tags are per *alignment record*; `indel_reads` is per +*fragment* (R1/R2 collapsed) and taken after site-level filters — so `Edited_*` records run roughly +2× higher where both mates cover the cut. + +⚠️ **Keep it off for cohort sweeps.** Measured on one AAVS1 ECS sample (1,149 targets, ~11,000×): +800 MB BAM, peak RSS 1.4 GB → 6.3 GB, wall clock ~30 → ~46 min. The process gets 24 GB instead of +8 GB when the flag is set. Check one sample before enabling across a cohort. + +## The shape model + +`assets/models/wgs_shape_model.pkl` — a `HistGradientBoostingClassifier` (`max_depth=3`), not a +neural network. Role: `stage2_shape_ranker`. Trained on 51 positive / 383 negative loci from the +CAR-T ECS cohort, depth-augmented at 0/20/30/50× so it behaves at 30× WGS. + +**The deployed model uses 7 features:** +`indel_frac`, `conc_ratio`, `pos_conc`, `pos_mad`, `modal_len`, `modal_mapq`, `softclip_frac`. + +> ⚠️ **`features.py:MODEL_FEATURES` lists 10**, adding `cut_dist`, `homopolymer_len` and +> `repeat_frac`. Those three were built and evaluated but the 10-feature model was **never +> shipped** — it bought 2.1× precision at the cost of CAR-T recall (52/52 → 47/52). `score.py` +> selects inputs by `bundle["features"]`, so the deployed pickle stays at 7 regardless. **If you +> retrain today you will get a 10-feature model**, which is a different model from the one these +> numbers describe. The ideas weren't wasted: `cut_dist` and repeat context are now rules 2 and 5 +> of the review filter, where they're measurable and explainable. + +Two weaknesses worth volunteering before someone else finds them: + +- **51 positives is small.** Treat it as a prioritiser, not an oracle. +- **It's a ranker, not a detector** — it demotes some unambiguous edits. Which is why the rescue + exists. + +**The high-evidence rescue.** Scoring on the model alone recovered 47/52 confirmed CAR-T edits. The +five misses weren't close calls — indel fractions 0.25–1.00, clean controls, 130–244 spanning reads, +pileups a reviewer calls instantly — that the ranker scored 0.27–0.50. So `score.py` calls LIKELY +EDIT on unambiguous evidence regardless of model score, via two arms, both gated *behind* the +low-MAPQ and matched-normal vetoes. The rescue can override the **model**, never the **evidence**, +so it can't resurrect a germline variant: + +1. **under-scored** — `indel_frac ≥ 0.15`, `conc_ratio ≥ 0.5`, `spanning ≥ 20` +2. **multi-allelic** — model score ≥ `offtarget_hi_score` with the same depth/burden evidence, + waiving the clonality requirement + +`call_basis` records which fired. Across 99,308 scored CAR-T rows this promoted exactly 6 sites — +all 6 the confirmed edits, taking recall to **52/52**. Set `--offtarget_rescue false` for +model-only behaviour. + +## Retraining (`-entry TRAIN`) + +The deployed model is a fixed asset; training is deliberately not in the OFFTARGET DAG. + +```bash +# 1. paired run -> labeled training table +sbatch run_offtarget.sh --input paired_samplesheet.csv --outdir results +# 2. fit +nextflow run . -entry TRAIN -profile ris2,apptainer \ + --input results/offtarget/training.tsv --outdir results +# 3. deploy +sbatch run_offtarget.sh --input cohort.csv --outdir results2 \ + -- --offtarget_shape_model results/train/wgs_shape_model.pkl +``` + +It runs in the off-target container so the pickle is written under the same scikit-learn the +pipeline scores with. See the 7-vs-10 feature warning above before you deploy the result. + +## Reading the metrics (the denominator matters more than the number) + +There are **two denominators**, kept strictly apart: + +| | denominator | what it supports | where | +|---|---|---|---| +| 1 | ECS label (a real two-class label) | PR-AUC, precision, F-beta | `offtarget_metrics.{json,txt}` | +| 2 | human manual review (positives only) | **recall only** — the gold standard | `bin/validate_recall.py` | + +**You cannot compute precision from manual review.** It has 55 confirmed positives and 80,440 NaNs, +and NaN means *not reviewed*, not *reviewed and rejected*. There are no confirmed negatives in it. +Filling those NaNs with 0 would count every genuine discovery the reviewers never reached as a +false positive. That's why `validate_recall.py` reports recall only, and stays that way. + +**Why recall reads low against the ECS label.** The raw ECS label counts any nonzero indel fraction +as an edit, and at ECS depth that's overwhelmingly noise — most "edits" sit below 0.5% VAF with a +median of 3 indel reads out of ~5,000. Of the high-VAF ones, most carry the same indel in the +matched normal, i.e. they're **germline**. The WGS arm rejects those correctly. So the credible +denominator requires somatic status, a VAF floor and a read-count floor; sites with no spanning WGS +reads are reported as **unevaluable, not missed**. + +Report PR-AUC and recall-weighted F-beta, not ROC-AUC — at this prevalence ROC-AUC is dominated by +true negatives and reads flatteringly high. F-beta is monotone in beta, so F1 is always an +*endpoint* of {F1, F2, F5}. **F1 in the middle means the weights got applied backwards.** + +## What this arm is, and isn't + +- **It is** a hotspot edit-confirmation plus genome-wide screen. On-target recovery is proven + end-to-end: on the first real AAVS1 run the on-target came back from WGS alone. +- **It also** recovers the one confirmed *off*-target we have — PLCB2 chr12:32,679,410 (90% VAF, + ECS-confirmed) — the proof WGS-only can find a real homology-based off-target. +- **It is not** a workflow with a quantified low-VAF detection floor. Across both cohorts the + human-reviewed truth set holds only **2 confirmed off-targets, both >85% VAF**. There's no + low-abundance off-target population to measure against. That's editing being highly + on-target-specific, not a bug — but it means sub-5% sensitivity is unproven. **Trust WGS-only + calls at hotspots ≥5% VAF.** + +--- + +## Known gaps, stated once + +- **No curated low-VAF positives**, so the model's core claim is untested. +- **Sub-5% VAF at 30× WGS is physics**, not tuning — a 1% VAF edit yields ~0.3 supporting reads. +- **No de-novo off-target positive control**: the genome-wide LIKELY EDITs that aren't predicted + hotspots are unreviewed. (Of 49 genome-wide calls, 9 fall on predicted hotspots and all 9 are + ECS-confirmed.) +- **Base-editor (CBE/ABE) substitutions are not detected.** This pipeline calls indels only. + +## Container + +Every process runs in `ghcr.io/dhslab/docker-scge-offtarget:260710`, built from +`docker-scge-offtarget/` in [dhslab-docker-images](https://github.com/dhslab/dhslab-docker-images). +It pins scikit-learn 1.8.0, which is what `wgs_shape_model.pkl` was trained under. Change that pin +and the build's own model-load check (plus the runtime guard in `bin/features.py`) will complain +rather than quietly mis-score. diff --git a/docs/OFFTARGET_DEMO.md b/docs/OFFTARGET_DEMO.md new file mode 100644 index 0000000..182229d --- /dev/null +++ b/docs/OFFTARGET_DEMO.md @@ -0,0 +1,246 @@ +# Off-target CRISPR edit finder — a 5-minute demo + +A hands-on tour you can run on a login node in about a minute. Nothing here needs cohort +data, a cluster allocation, or the DRAGEN reference: every command below runs against a +**5.5 KB synthetic genome** committed to the repo. + +For the full writeup — what the workflow is and is not, how the shape model was trained, what the +AAVS1 cohort actually showed — see [`OFFTARGET.md`](OFFTARGET.md). This page is the "show me it +working" one. + +--- + +## What the finder does, in three sentences + +CRISPR cuts where you aimed it, and sometimes where you didn't. This workflow takes deep +error-corrected sequencing (ECS) at a panel of candidate sites and finds the reads that +carry an edit, then asks whether ordinary 30x whole-genome sequencing of the *same* sample +could have found those same edits on its own. + +Two arms, one join: **ECS is the truth arm**, **WGS is the arm under test**. + +--- + +## Setup (once) + +```bash +# nextflow + apptainer on the RIS cluster +S=/storage2/fs1/dspencer/Active/spencerlab/apps/modules/spack/software/linux-rhel9-x86_64_v4/gcc-13.3.0 +export PATH="$S/nextflow-25.10.4-fz3mazhspz5uruz5ymyxhcwcauohjgfm/bin:$S/apptainer-1.4.5-ifu7outvqr62l343tqfxuxcguzftiuqe/bin:$PATH" + +# nf-test (once, anywhere on PATH) +curl -fsSL https://code.askimed.com/install/nf-test | bash +``` + +--- + +## Demo 1 — the whole test suite, real execution, ~1 minute + +```bash +nf-test test --profile stub,apptainer +``` + +``` +OFFTARGET_METRICS + Test 'computes the real metrics and emits every declared channel' PASSED + Test '--betas reaches the script: a custom beta set changes the columns' PASSED + Test '--negatives all_label0 is honoured as a distinct negative set' PASSED +ECS_INDELS + Test 'calls the edit and reports the right VAF — tagged BAM off by default' PASSED + Test 'offtarget_tagged_bam=true emits a per-read tagged BAM and its index' PASSED + +SUCCESS: Executed 5 tests +``` + +These are not stubs. Each one starts the real container and runs the real Python. + +> **Why that distinction matters.** The repo also has `-stub-run` tests, and they are +> useful — but a stub process body only `touch`es its output files. It never executes a +> line of `bin/*.py`. A module that passes a flag the script does not accept stays green +> through every stub test in the repo. That exact bug class once survived CI and then died +> three hours into a cluster run. nf-test is the tier that catches it. + +--- + +## The toy genome + +Everything below runs on `tests/fixtures/ecs/` — 5.5 KB, regenerable with +`python tests/fixtures/make_ecs_fixture.py`: + +``` +chr1, 3000 bp + target A @ 1001 the EDITED site — 12 of 20 evaluable read pairs carry a 5 bp deletion + target B @ 1201 a QUIET site — no edit + +edited.cram 35 pairs / 70 records +control.cram 20 clean pairs (the matched normal) +``` + +The 35 pairs are awkward on purpose: + +| pairs | what they are | what should happen | +|---|---|---| +| 12 | carry a 5 bp deletion | counted as edited | +| 8 | clean, span the target | counted as reference | +| 2 | duplicate-flagged | **excluded** from the denominator | +| 2 | MAPQ 3 | **excluded** (floor is 20) | +| 2 | NM 6 | **excluded** (ceiling is 4) | +| 9 | sit where the two ±150 bp windows **overlap** | visited by both targets, must be counted once | + +That last row is the interesting one: targets A and B are 200 bp apart, so their fetch +windows overlap. Any per-read output has to survive being visited twice. + +--- + +## Demo 2 — find the edit + +```bash +IMG=/storage2/fs1/dspencer/Active/spencerlab/abonney/apptainer_cache/ghcr.io-dhslab-docker-scge-offtarget-260710.img +F=tests/fixtures/ecs + +apptainer exec -B /storage2 "$IMG" python bin/find_edited_reads.py \ + --fasta $F/ref.fa \ + --edited-bam $F/edited.cram --control-bam $F/control.cram \ + --target-file $F/targets.vcf \ + -o demo.tsv +``` + +``` +chrom start end total_reads indel_reads indel_fraction control_reads control_indel_reads +chr1 1000 1001 20 12 0.6 20 0 +chr1 1200 1201 23 0 0.0 20 0 +``` + +Read that as: **at the edited site, 12 of 20 evaluable reads carry the deletion (VAF 0.60), +and the matched control has none of them.** That last column is what makes the call somatic +rather than germline. The quiet site stays quiet. + +Note `total_reads` is 20, not 26 — the duplicate, low-MAPQ and high-mismatch pairs were +dropped before the denominator was formed. If a filter ever regresses, that number climbs +and the VAF silently falls. The test asserts on it for exactly that reason. + +--- + +## Demo 3 — per-read tags for IGV *(new)* + +Add one flag and every read gets an `XC` tag naming how the caller classified it: + +```bash +apptainer exec -B /storage2 "$IMG" python bin/find_edited_reads.py \ + --fasta $F/ref.fa \ + --edited-bam $F/edited.cram --control-bam $F/control.cram \ + --target-file $F/targets.vcf \ + --tagged-bam-out demo.tagged.bam -o demo.tsv +``` + +``` + 31 Unedited_WT + 15 Skipped_NoSpan + 12 Edited_Deletion_5bp + 4 Skipped_Duplicate + 4 Skipped_LowMapQ + 4 Skipped_Mismatches +────────────────────────── + 70 records, 35 unique read names +``` + +Load `demo.tagged.bam` in IGV and use **Color alignments by → tag → XC**. A reviewer can now +see *why* a read was or wasn't counted, instead of taking the caller's word for it. + +Two things worth pointing at on a slide: + +- **70 records, 35 unique names.** Every read is written exactly once, even the 9 pairs in + the window overlap that two different targets both visited. +- **The `Skipped_` classes are visible.** Reads that were excluded are in the file and + labelled, not silently missing. + +In the pipeline this is `--offtarget_tagged_bam`, and it is **off by default**: on a real +AAVS1 sample (1149 targets, ~11000x) it produces an 800 MB BAM and pushes the caller's peak +memory from 1.4 GB to 6.3 GB. Turn it on for review, not for a cohort sweep. + +--- + +## Demo 4 — clinical metrics *(new)* + +```bash +apptainer exec -B /storage2 "$IMG" python bin/offtarget_metrics.py \ + --training tests/fixtures/training_mini.tsv \ + --betas 2,5 --out-json m.json --out-txt m.txt && cat m.txt +``` + +``` +-- RANKING (score as a continuous ranker; ECS-label denominator) -- + n_pos / n_neg : 6 / 4 prevalence 0.6000 + PR-AUC : 0.8552 (1.43x prevalence) + excluded, no score : 1 (1 pos / 0 neg) — INSUFFICIENT COVERAGE, never filled with 0 + +-- OPERATING POINT (verdict contains 'LIKELY EDIT'; ECS-label denominator) -- + TP 5 FP 2 FN 1 TN 2 + precision : 0.7143 recall : 0.8333 recall incl. unevaluable : 0.7143 + F1 0.7692 F2 0.8065 F5 0.8280 +``` + +Three things this output is built to stop you getting wrong: + +**1. F-beta is recall-weighted, and you can see it.** Here recall (0.833) beats precision +(0.714), so F rises with beta: F1 < F2 < F5. For a screening assay a missed off-target edit +costs far more than a followed-up false one, which is the whole argument for reporting F2/F5 +rather than F1. F-beta is monotone in beta, so F1 is always an *endpoint* — if you ever see +F1 in the middle, the weights got applied backwards. + +**2. The uncovered site is excluded, not counted as zero.** One credible positive had no WGS +coverage at all. It is dropped from the ranking and reported separately, and `recall incl. +unevaluable` (0.7143) is printed next to `recall` (0.8333) so the depth floor can never hide +inside a good-looking number. + +**3. Precision is against the ECS label, never against manual review.** The report says so +out loud, in the file. Manual review has 55 confirmed positives and 80,440 NaNs, where NaN +means *unreviewed*, not *rejected* — it contains no confirmed negatives. Any precision +computed from it would score every discovery the reviewers never reached as a false +positive. Recall against manual review is reported separately, and as recall only, by +`bin/validate_recall.py`. + +--- + +## Where the tests live and what each tier is for + +```bash +bash run_offtarget_tests.sh # all five tiers, ~3 min +``` + +| tier | what it runs | what it proves | catches | +|---|---|---|---| +| 0 | `ast.parse`, `nextflow -preview` | it is syntactically valid | typos | +| 1 | `pytest tests/*.py` | **the science is right** | wrong math, wrong joins | +| 2 | unpickle the shape model | the sklearn pin holds | version drift | +| 3 | `nextflow -stub-run` | **the DAG wires up** | broken channels | +| 4 | `nf-test` | **the two halves connect** | module ↔ script contract | + +Tier 5 — a real AAVS1 cohort run on SLURM — is what proves it works on real data, but it needs a +cohort and an allocation, so it is deliberately **not** part of the command above: + +```bash +sbatch run_offtarget.sh --input offtarget_samplesheet_aavs1.csv --outdir results_offtarget_aavs1 +``` + +Tiers 1 and 3 are the two halves that tier 4 joins: pytest runs the Python but never through +Nextflow; the stub run goes through Nextflow but never runs the Python. + +Run one feature's tests only: + +```bash +nf-test test --tag metrics --profile stub,apptainer +nf-test test --tag tagged_bam --profile stub,apptainer +``` + +--- + +## Honest limits + +- The fixtures are **synthetic**. They prove the plumbing and the arithmetic, not that the + caller is right about real CRISPR biology — that is what the AAVS1 cohort run is for. +- The metrics fixture is hand-built to produce a specific confusion matrix. Its PR-AUC is + not a performance claim about the model; it is a fixed number chosen so the test can + assert on it. +- Two blind spots remain unmeasured on real data: the **sub-5% VAF floor**, and a **de-novo + off-target positive control**. Neither is addressed by anything on this page. diff --git a/docs/PANEL_AS_FILTER.md b/docs/PANEL_AS_FILTER.md new file mode 100644 index 0000000..f459474 --- /dev/null +++ b/docs/PANEL_AS_FILTER.md @@ -0,0 +1,321 @@ +# The DRAGEN systematic-noise panels as filters + +Two asks, answered by measurement: + +1. Use `IDPF_WGS_hg38_v.2.0.0_systematic_noise.snv.bed.gz` as a filter and count how many indel + calls overlap a noisy SNV locus. +2. The same for breakends, with `IDPF_WGS_hg38_v3.0.0_systematic_noise.sv.bedpe.gz`. + +And behind both, the standing question: **can the panel replace the matched control?** + +Everything here is reproducible with [`bin/panel_overlap.py`](../bin/panel_overlap.py), which also +restores a lost capability — the original three-panel measurement in +[`CALLER_INTEGRATION_LOG.md`](CALLER_INTEGRATION_LOG.md) had **no surviving generator**, so nothing +could be re-measured when the caller changed underneath it. + +```bash +python3 bin/panel_overlap.py \ + --tables 'results_cart_bnd/*/*.offtarget_analysis.tsv' \ + --queue-all results_cart_bnd/review/review_queue_all.tsv \ + --snv-noise .../IDPF_WGS_hg38_v.2.0.0_systematic_noise.snv.bed.gz \ + --truth-wgs '.../cart_wgs_merged.xlsx' \ + --sv-noise .../WGS_hg38_v3.1.0_systematic_noise.sv.bedpe.gz \ + --sv-noise .../IDPF_WGS_hg38_v3.0.0_systematic_noise.sv.bedpe.gz \ + --sv-noise .../WGS_FF_Heme_hg38_v3.1.0_systematic_noise.sv.bedpe.gz +``` + +--- + +## The short answer + +**No, and the reason is not panel quality — it is what kind of prior each instrument can supply.** + +- **Germline needs a *sample-specific* prior.** A donor's genotype is a property of that donor. + The correct prior for "is there a real allele here in *this* person" can only come from *this* + person's own unedited material. A 46-donor panel reports a population average and is + structurally incapable of representing one donor's genotype, at any panel size. +- **Machine error needs a *population* prior — and here the panel is the better instrument.** + Sub-detection error rate is donor-independent physics. One control at 157× cannot resolve it; + 46 donors pooled can. See [§7 of the validation doc](NOISE_MODEL_VALIDATION.md#7-what-to-actually-do). + +Both statements are true at once, and that is the whole answer. + +--- + +## Ask #1 — the SNV panel as an indel filter + +Panel: `IDPF_WGS_hg38_v.2.0.0_systematic_noise.snv.bed.gz` (~1 GB, 46 donors per its own +`##PON SAMPLES:` header). Matching at ±2 bp, as the pipeline does. + +Despite "snv" in the filename this panel is **not** SNV-only — its allele column carries `D` +(1,299,670 records) and `I` (892,925) codes. Three nested definitions of "overlap" are therefore +worth separating: + +| population | n | any panel record | indel-capable record | shipped rule (≥3 donors & D/I) | +|---|---:|---:|---:|---:| +| all site-rows | 99,238 | 11,757 (11.9%) | 152 (0.15%) | 19 (0.02%) | +| gated rows | 479 | 126 (26.3%) | 46 (9.6%) | 8 (1.7%) | +| **review queue** | **86** | **1 (1.2%)** | **0** | **0** | + +**The headline number the ask wanted: 152 of 99,238 indel calls (0.15%) sit on an indel-capable +noisy locus, and only 19 clear the shipped ≥3-donor bar.** Restricting to the rows a human actually +reviews, the queue is essentially panel-clean — one row touches any panel record at all, and none +touches an indel record. + +> **Loader check.** The shipped `load_snv_noise` keeps only ONE record per position (the one with +> the most donors), so an SNV-only record with 20 donors could shadow an indel record with 2 and +> make the rule silently under-flag. Measured directly: **19 sites either way — no record is +> shadowed at any queried position on this run.** The lossy retention is not costing anything here, +> but it is a latent defect worth knowing about. + +### Against the curated truth label + +Scored as a *standalone* filter — flagging means "call this an artifact". + +> **Two populations, and it matters which one is quoted.** The label can be joined against every +> site-row the caller emitted, or only against the rows that clear the gate. They answer different +> questions and the panel looks materially different on each, so both are given. **`review_filter.py` +> only ever runs this rule on gated rows**, so the second table is the operational one; the first +> answers the broader "could this replace the noise model outright?". Note that +> [`NOISE_MODEL.md` §6](NOISE_MODEL.md#what-it-is-worth-in-practice--reported-honestly) uses the +> gated population (135 rows) for the cut-distance work — quoting a sensitivity from one table +> against the other is the easy mistake here. + +**All site-rows** — 279 rows join the label (69 confirmed / 210 human-rejected): + +| definition | flagged | sensitivity | specificity | precision | real edits flagged | +|---|---:|---:|---:|---:|---:| +| *(flag everything)* | 279 | 1.000 | 0.000 | 0.753 | 69 | +| any panel record | 105 | 0.495 | 0.986 | 0.990 | **1** | +| indel-capable record | 36 | 0.171 | 1.000 | 1.000 | **0** | +| shipped rule (≥3 donors & D/I) | 7 | 0.033 | 1.000 | 1.000 | **0** | + +**Gated rows only — the operational population** — 135 rows join (64 confirmed / 71 rejected): + +| definition | flagged | sensitivity | specificity | precision | real edits flagged | +|---|---:|---:|---:|---:|---:| +| *(flag everything)* | 135 | 1.000 | 0.000 | 0.526 | 64 | +| any panel record | 53 | **0.732** | 0.984 | 0.981 | **1** | +| indel-capable record | 31 | **0.437** | 1.000 | 1.000 | **0** | +| shipped rule (≥3 donors & D/I) | 3 | 0.042 | 1.000 | 1.000 | **0** | + +**The panel is ~1.5× more sensitive on gated rows** (0.73 vs 0.50 at the loosest definition, 0.44 +vs 0.17 indel-capable). That is not the panel improving; it is the denominator changing. Gated rows +are already enriched for the recurrent-locus artifacts a population panel can see, whereas the full +table is dominated by sites carrying no indel evidence at all — artifacts the panel was never going +to catch. Read the base-rate row first in both cases: at 75% negative the all-rows table hands a +do-nothing filter precision 0.753, and at 53% negative the gated table hands it 0.526. + +The conclusions are the same under either denominator, which is the point: + +- **The panel is very safe and not very powerful.** Even the loosest definition flags exactly **1** + confirmed edit in both populations; the two indel-aware definitions flag **none** in both. But + sensitivity tops out at 0.73 even where the panel is strongest. +- **The rule that actually ships catches almost nothing** — 0.033 and 0.042. On this cohort it + claims **zero** queue rows. +- **It is a specificity instrument, not a sensitivity one.** That is a perfectly good thing to be — + it is why the rule sits last in `review_filter.py`, where it can only claim rows the other five + rules kept — but it means the panel cannot carry the filtering load on its own. + +For context, the previously published baseline stands: only **54 of 1,498 gated loci (3.6%)** had +an indel-capable record, and a panel-only noise model scored precision 0.312 against 0.681 for the +matched control ([`NOISE_MODEL_EXPERIMENT.md:62-76`](NOISE_MODEL_EXPERIMENT.md)). + +### Can the panel stand in for rule 1? + +Rule 1 — "germline, present in the matched control" — is the single biggest filter in the stack, +dropping **154 of 479** gated rows. If the panel could reproduce those drops, the matched control +would be replaceable. It cannot: + +``` +rows rule 1 dropped as germline : 154 + panel flags, any record : 55 (36%) + panel flags, indel-capable : 34 (22%) + panel flags, shipped rule : 6 ( 4%) + +germline rows invisible to the panel entirely : 99/154 = 64% +donor support where the panel DOES see them : median 1, max 35 (of 46) +``` + +**64% of the germline calls are invisible to the panel**, and of the 36% it does touch, the typical +record is supported by a **single donor** — i.e. a coincidence, not a population statement. The +shipped rule recovers 4%. + +This is exactly what the category distinction predicts. A population panel can only recognise a +population-*common* allele; a donor's private variants are, by definition, not in it. Growing the +panel does not fix this, because the thing being asked for is not in the panel's sampling frame. + +--- + +## Ask #2 — the SV panels as a breakend filter + +Three panels, on the 1,022 junctions the caller emitted and the 25 that clear `reads ≥ 3`. + +> **The on-target exemption is disabled for this measurement.** The shipped rule exempts +> `is_target == 1` junctions from the panel check, and **all 25 gated junctions on this cohort are +> `is_target == 1`** — so with the exemption on, the answer would be trivially zero and would say +> nothing about the panels. The question asked was about panel discrimination, so the exemption is +> turned off and the numbers below are for the panels themselves. + +| panel | BEDPE records | merged intervals | **genome covered** | +|---|---:|---:|---:| +| `WGS_hg38_v3.1.0` | 311,395 | 302,943 | **33.7 Mb — 1.09%** | +| `IDPF_WGS_v3.0.0` | 2,626,364 | 998,548 | **1,942 Mb — 62.66%** | +| `WGS_FF_Heme_v3.1.0` | 2,195,842 | 1,375,249 | **1,554 Mb — 50.12%** | + +Flagged counts (either end in a panel interval): + +| panel | slop | all 1,022 junctions | 25 gated | artifacts (n=2) | +|---|---:|---:|---:|---:| +| `WGS_hg38_v3.1.0` | 0 | 58 (5.7%) | **0 / 25** | 2 / 2 | +| | 50 | 77 (7.5%) | **0 / 25** | 2 / 2 | +| | 200 | 120 (11.7%) | 3 / 25 | 2 / 2 | +| `IDPF_WGS_v3.0.0` | 0 | 852 (83.4%) | 25 / 25 | 2 / 2 | +| | 50 | 878 (85.9%) | 25 / 25 | 2 / 2 | +| | 200 | 934 (91.4%) | 25 / 25 | 2 / 2 | +| `WGS_FF_Heme_v3.1.0` | 0 | 709 (69.4%) | 22 / 25 | 2 / 2 | +| | 50 | 745 (72.9%) | 25 / 25 | 2 / 2 | +| | 200 | 835 (81.7%) | 25 / 25 | 2 / 2 | + +### The mechanism, which is simpler than previously stated + +**IDPF v3.0.0 covers 62.66% of hg38.** A hit against it is close to uninformative by construction — +it flags 83% of *all* junctions, real and artifactual alike. `WGS_FF_Heme` covers 50% and behaves +the same way. Only `WGS_hg38_v3.1.0`, at **1.09% coverage**, is selective enough for a hit to mean +anything, and it is the only panel that discriminates: **0 of 25 real junctions, 2 of 2 available +artifacts**, at slop 0 and 50. + +This is a sharper explanation than the one in `CALLER_INTEGRATION_LOG.md`, which framed IDPF as +"actively harmful" because it flags real junctions at a higher rate than noise. That framing is +still arithmetically true, but the cause is not a population mismatch — it is that the panel's +intervals blanket most of the genome, so almost everything hits. + +### Against the null, and in which direction — the measurement that settles it + +A raw flag rate cannot be read on its own, because a junction has **two** endpoints. A panel +covering fraction `c` of the genome flags a randomly placed junction `1 − (1 − c)²` of the time. +For IDPF at `c = 0.627` that null is **86.1%** before any biology whatsoever. + +Splitting the 1,022 records by target status gives the direction as well as the magnitude +(`bin/panel_overlap.py`, slop 50, on-target n = 183, off-target n = 839): + +| panel | coverage | null (either end) | observed | obs/null | on-target flagged | off-target flagged | odds ratio | direction | +|---|---:|---:|---:|---:|---:|---:|---:|---| +| `WGS_hg38_v3.1.0` | 1.1% | 2.2% | 7.5% | **3.48×** | 4.4% | 8.2% | 1.96 [0.93, 4.15] | right way, CI spans 1 | +| `IDPF_WGS_v3.0.0` | 62.7% | 86.1% | 85.9% | **1.00×** | **92.3%** | 84.5% | **0.45 [0.25, 0.80]** | **backwards** | +| `WGS_FF_Heme_v3.1.0` | 50.1% | 75.1% | 72.9% | **0.97×** | **87.4%** | 69.7% | **0.33 [0.21, 0.53]** | **backwards** | + +Three things fall out, and the first two are worse than "uninformative": + +**IDPF's flag rate is its coverage.** 85.9% observed against an 86.1% null — a ratio of 1.00. The +panel is not detecting anything. It is reporting how much of the genome it covers. A permutation +null that preserves each junction's chromosomes and its inter-endpoint span (1,000 shifts) puts the +baseline at 80.8% and the observed at 1.06× it; the enrichment is real but negligible, and the +analytic null is the fairer comparison because the shift null cannot preserve mappability. + +**IDPF and FF_Heme point the wrong way.** Both flag *on-target* junctions — nominated cut sites, +i.e. the genuine editing outcomes — **more** often than off-target ones. IDPF: 92.3% vs 84.5%, +odds ratio 0.45, CI [0.25, 0.80], excluding 1. FF_Heme is worse at 0.33 [0.21, 0.53]. A noise panel +is supposed to enrich for artifacts. These enrich for the results. + +> The on-target/off-target contrast is a **proxy** for real-vs-artifact, not ground truth: not +> every off-target record is an artifact, and not every on-target record is real. It is sound for +> establishing *direction*, which is what is at issue, and should not be read as a precision figure. + +**`WGS_hg38_v3.1.0` is the only one that behaves.** 3.48× the null, and off-target flagged nearly +twice as often as on-target — the right direction. But its odds-ratio CI spans 1 (8 on-target hits +against 69 off-target), so on this cohort the discrimination is **suggestive, not demonstrated**. +It is the panel to use; the case for it rests on the coverage argument and on 0/25 real junctions +flagged, not on this odds ratio. + +**Why the on-target exemption is load-bearing.** With the exemption disabled, IDPF flags **25 of +25** real junctions at every slop tested (0, 50, 200) and FF_Heme 22–25 of 25; `WGS_hg38_v3.1.0` +flags **0 of 25** at slop 0 and 50, and 3 at 200. So under the shipped default panel, rule 4 without +the exemption would delete the entire breakend finding. The exemption is not a convenience — it is +the only thing standing between the current default and a null result. + +### Would a `min_donors` rule rescue the large panels? No. + +The BEDPE carries **no donor-count column and no `##PON SAMPLES:` header**, so there is no direct +analogue of the SNV panel's `n_donors` — the very statistic that makes the SNV panel usable. But it +is recoverable: field 7 is a candidate name that embeds the donor it came from +(`ImpreciseNoiseCandidate_LP7108672-DNA_A06_42_DRAGEN:BND:...`), so pooling records by interval and +counting distinct donors reconstructs the missing column. + +Donor support behind the hits on the 25 gated junctions (slop 50): + +| panel | hit | 1 donor | ≥2 donors | ≥3 donors | max | +|---|---:|---:|---:|---:|---:| +| `WGS_hg38_v3.1.0` | 0 | 0 | 0 | 0 | 0 | +| `IDPF_WGS_v3.0.0` | 25 | **0** | 25 | **25** | 17 | +| `WGS_FF_Heme_v3.1.0` | 25 | 6 | 19 | 12 | 9 | + +**No threshold rescues IDPF.** Every one of its hits on a real junction is supported by ≥3 donors +(up to 17), so these are genuinely recurrent loci in its baseline, not one-donor coincidences. A +`min_donors ≥ 3` rule would leave IDPF at 25/25 and take FF_Heme only from 25/25 to 12/25 — still +unusable. The panel *choice* is load-bearing on the SV side in a way it is not on the SNV side, and +no tuning substitutes for picking the right file. + +Also worth noting: matching is a bare either-end interval hit +([`review_filter_bnd.py:130-135`](../bin/review_filter_bnd.py)) — there is no requirement that the +*partner* end match too, which would be a much stronger test and is not currently available. + +### ⚠️ Flagged for a decision, not changed here + +`params.sv_noisefile` ([`nextflow.config:208`](../nextflow.config)) is **IDPF v3.0.0**, and it is +passed to DRAGEN itself as `--sv-systematic-noise`. That is the panel measured above as covering +63% of the genome and flagging 100% of the real junctions on the review side. + +**These are two different parameters and only one of them reaches rule 4.** + +| parameter | default | consumed by | +|---|---|---| +| `params.sv_noisefile` (`nextflow.config:208`) | **IDPF v3.0.0** | **DRAGEN**, as `--sv-systematic-noise` (`modules/local/dragen_scge.nf:52,112`) | +| `params.review_sv_noise` (`nextflow.config:167`) | **`null` — off** | `review_filter_bnd.py --sv-noise`, i.e. rule 4 | + +So the 63%-coverage panel never reaches the breakend filter, and rule 4 is **off by default**. That +has a consequence worth stating plainly: the `dropped, DRAGEN systematic noise : 0` line printed by +every run so far means *the rule did not run*, not *nothing matched*. `logs/run_cart_bnd.sh` sets +`review_sv_noise` to `WGS_hg38_v3.1.0` explicitly, which is why that run's zero is a real zero — but +that is a run script, not the shipped default. + +On the DRAGEN side, `params.sv_noisefile` hands DRAGEN a panel covering 63% of hg38, which +suppresses 55.8% of otherwise-passing DRAGEN SV calls. + +> **Decided 2026-08-20: `params.sv_noisefile` stays on IDPF v3.0.0.** This is the PI's call and the +> question is closed — do not re-raise it or "fix" the default. The measurements above argued for +> `WGS_hg38_v3.1.0`; they are retained as the record of what was known when the decision was made, +> not as a standing recommendation. + +**What that decision does and does not touch.** It affects DRAGEN's own SV output — the +`*.sv.annotated.vcf.gz` and the SV table in the per-sample report — where roughly half the +otherwise-passing calls are suppressed. It does **not** touch the breakend arm or anything else in +these docs, for two independent reasons: the breakend caller never consumes DRAGEN SV calls (it is +SA-tag split reads only), and `params.sv_noisefile` is not the parameter rule 4 reads. Rule 4 reads +`params.review_sv_noise`, which is `null`. + +**The one thing to protect.** Because IDPF is staying, the failure mode worth guarding is somebody +later wiring *it* into `review_sv_noise` on the assumption that one SV panel is as good as another. +That would flag 25 of 25 real junctions and erase the breakend finding entirely. The warning at +`nextflow.config:160` says so at the point of use. + +### Reproducibility note — an honest discrepancy + +`CALLER_INTEGRATION_LOG.md:587-595` published this table against **36 gated junctions (25 real, 11 +artifacts)** from the 2,403-junction set of 2026-08-10: + +| panel | published: real flagged | published: artifacts | **this run: real flagged** | +|---|---|---|---| +| `WGS_hg38_v3.1.0` | 0 / 25 | 11 / 11 | **0 / 25** ✓ | +| `IDPF_WGS_v3.0.0` | 25 / 25 | 11 / 11 | **25 / 25** ✓ | +| `WGS_FF_Heme_v3.1.0` | 24 / 25 | 11 / 11 | **25 / 25** ✗ | + +- Raw record counts reproduce exactly (311,395 / 2,626,364 / 2,195,842). +- Two of three "real flagged" figures reproduce exactly. +- **FF_Heme differs by one** (24 → 25). The junction set changed (2,403 → 1,022) and the caller + changed with it, so this is not the same 25 junctions. Reported, not reconciled. +- **The 11-artifact set no longer exists on disk.** No run retained it: the current run drops + *zero* junctions to rules 2–4, so it has no artifacts at all. The only recoverable artifact set + is 2 junctions from `results_cart_noise`, and all three panels flag both. **The artifact column + of the published table is therefore not currently reproducible**, and any future claim resting on + "11/11" should be re-derived rather than quoted. diff --git a/docs/README.md b/docs/README.md index 4b9aa26..a9f2565 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,5 +6,9 @@ The nf-core/scge documentation is split into the following pages: - An overview of how the pipeline works, how to run it and a description of all of the different command-line flags. - [Output](output.md) - An overview of the different results produced by the pipeline and how to interpret them. +- [Handoff](HANDOFF.md) + - Operational knowledge for the off-target arm: how to launch it on RIS SLURM, the landmines + (the multi-TB debug flag, the `bin/` cache rule, the SLURM controller drops), which truth sets + are authoritative, which published numbers are traps, and the open threads. You can find a lot more documentation about installing, configuring and running nf-core pipelines on the website: [https://nf-co.re](https://nf-co.re) diff --git a/docs/THRESHOLD_CHANGE_IMPACT.md b/docs/THRESHOLD_CHANGE_IMPACT.md new file mode 100644 index 0000000..a46e83f --- /dev/null +++ b/docs/THRESHOLD_CHANGE_IMPACT.md @@ -0,0 +1,170 @@ +# Lowering the evidence gate — expected impact + +> **PARTLY SUPERSEDED (2026-08-13).** The gate change this document measures was adopted and is +> still live (`review_min_reads = 2`, `review_min_vaf = 0.005`), and Finding 1 stands. But its +> recommendations about the **panel of normals are no longer actionable: the PoN has been removed.** +> Rule 4 is now a beta-binomial test against each sample's own control, so `pon_min_reads` / +> `pon_min_donors` no longer exist and the gate-vs-panel asymmetry in Finding 2 cannot arise — +> there is no read threshold on the panel side to fall out of step with the gate. Do not act on +> recommendations 1 or 3 below. See `docs/NOISE_MODEL_EXPERIMENT.md`. + +**Change:** `indel_reads >= 10 & indel_fraction >= 0.05` → `indel_reads >= 2 & indel_fraction >= 0.005` +(`review_min_reads`, `review_min_vaf` in `nextflow.config`). + +Every number below is **measured**, not projected: `review_filter.py` was run directly over the same +32 `*.offtarget_analysis.tsv` inputs, the same panel of normals and the same repeat BEDs, with only +the two thresholds changed. + +> **Confirmed by the pipeline.** SLURM job 2707025 (`-profile ris2,apptainer`, outdir +> `results_cart_lowgate/`) completed successfully, 2026-08-10. It produced **1,498 gated rows and a +> 91-site queue**, and the queue is **set-identical** to the simulation below — same samples, same +> coordinates, no losses against the previous 81. 91 snapshots rendered. The old run in +> `results_cart_full/` is untouched. + +--- + +## Headline + +| | old gate | new gate | | +|---|---|---|---| +| Rows clearing the gate | 160 | **1,498** | 9.4× | +| Review queue | 81 | **91** | +10 | +| On-target | 77 | 81 | +4 | +| **Off-target candidates** | **4** | **10** | **2.5×** | +| Sites lost | — | **0** | all 81 retained | + +**The queue grows 12%; the work grows 150%.** The 81 original sites all survive — no regression — +but the number of rows that actually need a human decision goes from 4 to 10, because on-target +sites are confirmations rather than decisions. That is the number to watch. + +### Per-rule drops + +| Rule | old | new | +|---|---|---| +| germline (in control) | 49 | 352 | +| far from PAM | 18 | **680** | +| single indel length | 9 | **359** | +| known-bad (PoN) | 1 | 6 | +| repeat region | 2 | 10 | +| **kept** | **81** | **91** | + +The five rules absorb 1,407 of the 1,498 gated rows. Rule 2 becomes the workhorse — at low VAF most +new material is scattered background indels that are simply nowhere near a cut site. + +--- + +## Finding 1 — the `indel_reads >= 2` half of the change is inert + +**Rule 3 requires ≥3 distinct indel lengths. A site with 2 indel reads carries at most 2 distinct +lengths, so it can never pass.** + +Measured: **837 rows** enter with exactly 2 indel reads. Maximum `n_distinct_len` observed among +them is 2. **Zero** survive. + +| indel_reads | rows | can satisfy rule 3? | +|---|---|---| +| 2 | 837 | **no — arithmetically impossible** | +| 3 | 225 | only if all 3 reads differ | +| 4+ | 272 | yes | + +So 56% of the newly admitted rows are dropped by arithmetic rather than by evidence. Every one of +the 10 new queue sites has **3–10** indel reads: they came from relaxing the *VAF* term, not the +read term. + +**Implication:** `indel_reads >= 3` would give an identical queue with 837 fewer rows to carry, +audit and store. If the intent of `>= 2` is genuinely to see 2-read sites, then rule 3 has to change +at the same time — it is currently acting as a hidden `indel_reads >= 3` filter. + +--- + +## Finding 2 — a new asymmetry between the gate and the panel of normals + +Lowering the review gate without lowering the PoN threshold makes the panel **systematically +blinder than the filter it feeds**. + +The PoN blacklists a site needing `>=3 reads AND >=2% VAF` in an unedited sample (`pon_min_reads`, +`pon_min_vaf`). The review gate now admits sites at 2 reads. So there is a band — 2 reads in the +control — where the filter can see a site but the panel structurally cannot flag it. + +**This is not hypothetical; it already leaks.** `chr18:61,959,927` appears in **28 of 32 samples +under 23 distinct guides** — the textbook definition of a recurrent artifact. Its PoN record: + +``` +chrom pos n_donors max_indel_reads max_indel_fraction blacklisted +chr18 61959928 0 2 0.0526 0 +``` + +The controls **do** carry it — 2 reads, 5.3% VAF — but `pon_min_reads = 3` misses it by a single +read, so it is not blacklisted. Under the old gate it never cleared and the gap was invisible. +Under the new gate **3 copies reach the queue** (CART_NS0027-B2M_1, IKZF2, PLCB2), and they are +3 of the 10 off-target candidates. + +### Two independent fixes, either of which closes it + +1. **Lower `pon_min_reads` 3 → 2** to match the gate. chr18 then has `max_indel_reads = 2 ≥ 2` and + `max_indel_fraction = 0.0526 ≥ 0.02`, so it blacklists. **Keeping the two thresholds in step is + the general principle**: the panel must be at least as sensitive as the filter consuming it. +2. **Apply cross-guide recurrence *alongside* the PoN, not instead of it.** `n_guides = 23` is + already computed and sitting in the output — it is simply unused whenever a PoN is supplied + (`review_filter.py:224` vs `:228`, an if/else). Making rule 4 + `is_off & (in_blacklist | n_guides >= max_guides)` drops all 3 chr18 rows. + +Either takes the queue **91 → 88** and off-target candidates **10 → 7**. + +--- + +## Finding 3 — what the 10 new sites actually are + +| Sample | Site | Reads | VAF | On-target | Verdict | +|---|---|---|---|---|---| +| CART_NS0027-CTLA4_2 | chr7:142,792,021 | 8 | 0.096 | ✓ | TRBC1, low-efficiency replicate | +| PLCB2 | chr18:61,959,927 | 8 | 0.079 | | **recurrent artifact** (23 guides) | +| IKZF2 | chr18:61,959,927 | 5 | 0.046 | | **recurrent artifact** | +| CART_NS0027-PD1_1 | chr2:241,852,750 | 8 | 0.040 | ✓ | | +| ZEB2 | chr4:26,561,342 | 6 | 0.040 | | new candidate | +| CART_NS0027-CTLA4_2 | chr2:203,870,831 | 10 | 0.039 | ✓ | CTLA4 | +| CART_NS0027-B2M_2 | chr15:44,711,599 | 5 | 0.023 | ✓ | **the second B2M cut site** | +| CART_NS0027-B2M_1 | chr18:61,959,927 | 3 | 0.021 | | **recurrent artifact** | +| CART_NS0027-CTLA4_1 | chr2:160,064,217 | 4 | 0.018 | | new candidate | +| PLCB2 | chr5:159,263,654 | 3 | 0.015 | | new candidate | + +**Two are genuinely valuable.** `chr15:44,711,599` in CART_NS0027-B2M_2 is the *second* B2M cut +site — the deck's TRAC/TRBC slide shows editing split across two candidate B2M positions, and this +change recovers the low-efficiency one, confirming both fired in that sample. The CTLA4 and PD1 +on-target additions similarly fill in low-efficiency replicates. + +**Three are the chr18 artifact** described above. + +**Three are new off-target candidates** (ZEB2 chr4, CTLA4 chr2, PLCB2 chr5) at 1.5–4.0% VAF, each +seen in a single sample. At 205× these rest on 3–6 reads. They are exactly the population the +system cannot currently adjudicate — real enough to demand a look, thin enough that a look will +not settle them. + +--- + +## Operational cost + +| | old | new | +|---|---|---| +| `review_queue_all.tsv` rows | 160 | 1,498 | +| Snapshots rendered | 81 | 91 | +| Runtime | ~9.5 min | ~unchanged | + +Snapshot rendering scales with the *queue*, not the gated set, so cost barely moves. The audit file +grows ~9×, which is still trivially small. + +--- + +## Recommendation + +1. **Use `indel_reads >= 3`, not 2.** Identical queue, 837 fewer inert rows. Going to 2 is only + meaningful if rule 3 is reworked at the same time. +2. **Lower `pon_min_reads` to match whatever the gate becomes.** The panel must never be less + sensitive than the filter reading it. +3. **Make rule 4 the union of PoN and cross-guide recurrence.** The signal is already computed and + currently thrown away, and it catches exactly the class the PoN's read threshold misses. +4. **Do not present the 10 off-target candidates as findings** until 1–3 are applied. Three of the + ten are one artifact counted three times, which would be a bad slide. + +With all three applied the queue is **88** — 81 on-target, 7 off-target — and every one of the +7 is a single-sample, non-recurrent, control-clean candidate. diff --git a/docs/images/aq_worked_example.png b/docs/images/aq_worked_example.png new file mode 100755 index 0000000..63bc416 Binary files /dev/null and b/docs/images/aq_worked_example.png differ diff --git a/docs/images/aq_worked_example_pileup.png b/docs/images/aq_worked_example_pileup.png new file mode 100755 index 0000000..975a731 Binary files /dev/null and b/docs/images/aq_worked_example_pileup.png differ diff --git a/docs/images/cut_distance_model.png b/docs/images/cut_distance_model.png new file mode 100644 index 0000000..a450e4f Binary files /dev/null and b/docs/images/cut_distance_model.png differ diff --git a/docs/images/noise_calibration_qq.png b/docs/images/noise_calibration_qq.png new file mode 100644 index 0000000..c7fbef5 Binary files /dev/null and b/docs/images/noise_calibration_qq.png differ diff --git a/docs/images/noise_reliability.png b/docs/images/noise_reliability.png new file mode 100644 index 0000000..bde427a Binary files /dev/null and b/docs/images/noise_reliability.png differ diff --git a/docs/images/noise_two_populations.png b/docs/images/noise_two_populations.png new file mode 100644 index 0000000..1e2ef79 Binary files /dev/null and b/docs/images/noise_two_populations.png differ diff --git a/docs/images/offtarget_metro.html b/docs/images/offtarget_metro.html new file mode 100644 index 0000000..07af3a6 --- /dev/null +++ b/docs/images/offtarget_metro.html @@ -0,0 +1,623 @@ + + + + +Unified CRISPR Off-Target Workflow + + + +
+
+

Unified CRISPR Off-Target Workflow

+ drag to pan, scroll to zoom, click a line to focus + + +
+
+ + + + +{"groups":[{"color":"#E6194B","id":"ecs","label":"ECS truth (hotspots)"},{"color":"#4363D8","id":"wgs","label":"WGS genome-wide discovery"},{"color":"#3CB44B","id":"model","label":"WGS-only model (ECS-trained)"}],"height":351,"match":{"flags":"i","target":"fqProcessName","type":"regex"},"nodes":[{"groups":["ecs","wgs"],"h":14.0,"id":"ss","label":"sample datatype guide crams vcf","patterns":[],"r":5.0,"region":"in","rx":5.0,"w":10.0,"x":221.0,"y":122.0},{"groups":["ecs"],"h":10.0,"id":"ecs","label":"ECS_INDELS","patterns":[],"r":5.0,"region":"ecsarm","rx":5.0,"w":10.0,"x":464.5,"y":120.0},{"groups":["ecs","model"],"h":14.0,"id":"truth","label":"ECS truth VAF","patterns":[],"r":5.0,"region":"ecsarm","rx":5.0,"w":10.0,"x":559.5,"y":122.0},{"groups":["wgs"],"h":10.0,"id":"wl","label":"WGS_WORKLIST","patterns":[],"r":5.0,"region":"wgsarm","rx":5.0,"w":10.0,"x":472.5,"y":274.0},{"groups":["wgs"],"h":10.0,"id":"pon","label":"PON_OFFTARGET_FILTER","patterns":[],"r":5.0,"region":"wgsarm","rx":5.0,"w":10.0,"x":567.5,"y":274.0},{"groups":["wgs"],"h":10.0,"id":"worklist","label":"PoN worklist","patterns":[],"r":5.0,"region":"wgsarm","rx":5.0,"w":10.0,"x":662.5,"y":274.0},{"groups":["model"],"h":10.0,"id":"h2t","label":"HOTSPOT_TO_TABLE","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":846.5,"y":120.0},{"groups":["model"],"h":10.0,"id":"score","label":"SCORE_HOTSPOTS","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":941.5,"y":120.0},{"groups":["model"],"h":10.0,"id":"train","label":"training.tsv","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":1036.5,"y":120.0},{"groups":["model"],"h":10.0,"id":"recall","label":"RECALL_VS_VAF","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":1131.5,"y":120.0},{"groups":["model","wgs"],"h":14.0,"id":"rec","label":"RECONCILE_OFFTARGET_REPORT","patterns":[],"r":5.0,"region":"rep","rx":5.0,"w":10.0,"x":891.5,"y":276.0},{"groups":["wgs"],"h":10.0,"id":"out","label":"offtarget_report.csv","patterns":[],"r":5.0,"region":"rep","rx":5.0,"w":10.0,"x":986.5,"y":274.0}],"regions":[{"id":"in","label":"Samplesheet"},{"id":"ecsarm","label":"ECS arm: error-corrected truth"},{"id":"wgsarm","label":"WGS arm: genome-wide homology-free"},{"id":"modelarm","label":"Paired: WGS-only model"},{"id":"rep","label":"Report"}],"title":"Unified CRISPR Off-Target Workflow","version":"1.0","width":1254} + + +Unified CRISPR Off-Target Workflow + + +1 + + + +2 + + + +3 + + + +4 + + + +5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ECS_INDELS + +WGS_WORKLIST + +RECONCILE_OFFTARGET_REPORT + +HOTSPOT_TO_TABLE + +sample datatype guide crams vcf + +ECS truth VAF + +PON_OFFTARGET_FILTER + +offtarget_report.csv + +SCORE_HOTSPOTS + +PoN worklist + +training.tsv + +RECALL_VS_VAF +created with nf-metro v1.1.0 + +
+ +
+
+ +
+
+ +

Embed snippets

+

Interactive HTML (inline). Self-contained snippet - + paste into any HTML host (MkDocs, Confluence, Notion, blog templates) + and it keeps full pan / zoom / line-filter. No iframe, no hosting.

+
+ + +
+

+    

Interactive (iframe). Host this HTML file and embed + the iframe. GitHub READMEs strip iframes - link to a hosted page + from the README instead.

+
+ + +
+

+    

Static SVG. Inline this anywhere that accepts raw HTML + (or save it as .svg). No interactivity but it renders even where + scripts are stripped.

+
+ + +
+

+  
+
+ + + + diff --git a/docs/images/offtarget_metro.svg b/docs/images/offtarget_metro.svg new file mode 100644 index 0000000..c44041f --- /dev/null +++ b/docs/images/offtarget_metro.svg @@ -0,0 +1,137 @@ + + + + +{"groups":[{"color":"#E6194B","id":"ecs","label":"ECS truth (hotspots)"},{"color":"#4363D8","id":"wgs","label":"WGS genome-wide discovery"},{"color":"#3CB44B","id":"model","label":"WGS-only model (ECS-trained)"}],"height":470,"match":{"flags":"i","target":"fqProcessName","type":"regex"},"nodes":[{"groups":["ecs","wgs"],"h":14.0,"id":"ss","label":"sample datatype guide crams vcf","patterns":[],"r":5.0,"region":"in","rx":5.0,"w":10.0,"x":221.0,"y":122.0},{"groups":["ecs"],"h":10.0,"id":"ecs","label":"ECS_INDELS","patterns":[],"r":5.0,"region":"ecsarm","rx":5.0,"w":10.0,"x":464.5,"y":120.0},{"groups":["ecs","model"],"h":14.0,"id":"truth","label":"ECS truth VAF","patterns":[],"r":5.0,"region":"ecsarm","rx":5.0,"w":10.0,"x":559.5,"y":122.0},{"groups":["wgs"],"h":10.0,"id":"wl","label":"WGS_WORKLIST","patterns":[],"r":5.0,"region":"wgsarm","rx":5.0,"w":10.0,"x":472.5,"y":274.0},{"groups":["wgs"],"h":10.0,"id":"pon","label":"PON_OFFTARGET_FILTER","patterns":[],"r":5.0,"region":"wgsarm","rx":5.0,"w":10.0,"x":567.5,"y":274.0},{"groups":["wgs"],"h":10.0,"id":"worklist","label":"PoN worklist","patterns":[],"r":5.0,"region":"wgsarm","rx":5.0,"w":10.0,"x":662.5,"y":274.0},{"groups":["model"],"h":10.0,"id":"h2t","label":"HOTSPOT_TO_TABLE","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":846.5,"y":120.0},{"groups":["model"],"h":10.0,"id":"score","label":"SCORE_HOTSPOTS","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":941.5,"y":120.0},{"groups":["model"],"h":10.0,"id":"train","label":"training.tsv","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":1036.5,"y":120.0},{"groups":["model"],"h":10.0,"id":"recall","label":"RECALL_VS_VAF","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":1131.5,"y":120.0},{"groups":["model","wgs"],"h":14.0,"id":"rec","label":"RECONCILE_OFFTARGET_REPORT","patterns":[],"r":5.0,"region":"rep","rx":5.0,"w":10.0,"x":891.5,"y":276.0},{"groups":["wgs"],"h":10.0,"id":"out","label":"offtarget_report.csv","patterns":[],"r":5.0,"region":"rep","rx":5.0,"w":10.0,"x":986.5,"y":274.0}],"regions":[{"id":"in","label":"Samplesheet"},{"id":"ecsarm","label":"ECS arm: error-corrected truth"},{"id":"wgsarm","label":"WGS arm: genome-wide homology-free"},{"id":"modelarm","label":"Paired: WGS-only model"},{"id":"rep","label":"Report"}],"title":"Unified CRISPR Off-Target Workflow","version":"1.0","width":1254} + + +Unified CRISPR Off-Target Workflow + + +1 + + + +2 + + + +3 + + + +4 + + + +5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ECS_INDELS + +WGS_WORKLIST + +RECONCILE_OFFTARGET_REPORT + +HOTSPOT_TO_TABLE + +sample datatype guide crams vcf + +ECS truth VAF + +PON_OFFTARGET_FILTER + +offtarget_report.csv + +SCORE_HOTSPOTS + +PoN worklist + +training.tsv + +RECALL_VS_VAF + + +ECS truth (hotspots) + +WGS genome-wide discovery + +WGS-only model (ECS-trained) +created with nf-metro v1.1.0 + diff --git a/docs/images/offtarget_metro_dark.svg b/docs/images/offtarget_metro_dark.svg new file mode 100644 index 0000000..8784eaa --- /dev/null +++ b/docs/images/offtarget_metro_dark.svg @@ -0,0 +1,137 @@ + + + + +{"groups":[{"color":"#E6194B","id":"ecs","label":"ECS truth (hotspots)"},{"color":"#4363D8","id":"wgs","label":"WGS genome-wide discovery"},{"color":"#3CB44B","id":"model","label":"WGS-only model (ECS-trained)"}],"height":470,"match":{"flags":"i","target":"fqProcessName","type":"regex"},"nodes":[{"groups":["ecs","wgs"],"h":14.0,"id":"ss","label":"sample datatype guide crams vcf","patterns":[],"r":5.0,"region":"in","rx":5.0,"w":10.0,"x":221.0,"y":122.0},{"groups":["ecs"],"h":10.0,"id":"ecs","label":"ECS_INDELS","patterns":[],"r":5.0,"region":"ecsarm","rx":5.0,"w":10.0,"x":464.5,"y":120.0},{"groups":["ecs","model"],"h":14.0,"id":"truth","label":"ECS truth VAF","patterns":[],"r":5.0,"region":"ecsarm","rx":5.0,"w":10.0,"x":559.5,"y":122.0},{"groups":["wgs"],"h":10.0,"id":"wl","label":"WGS_WORKLIST","patterns":[],"r":5.0,"region":"wgsarm","rx":5.0,"w":10.0,"x":472.5,"y":274.0},{"groups":["wgs"],"h":10.0,"id":"pon","label":"PON_OFFTARGET_FILTER","patterns":[],"r":5.0,"region":"wgsarm","rx":5.0,"w":10.0,"x":567.5,"y":274.0},{"groups":["wgs"],"h":10.0,"id":"worklist","label":"PoN worklist","patterns":[],"r":5.0,"region":"wgsarm","rx":5.0,"w":10.0,"x":662.5,"y":274.0},{"groups":["model"],"h":10.0,"id":"h2t","label":"HOTSPOT_TO_TABLE","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":846.5,"y":120.0},{"groups":["model"],"h":10.0,"id":"score","label":"SCORE_HOTSPOTS","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":941.5,"y":120.0},{"groups":["model"],"h":10.0,"id":"train","label":"training.tsv","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":1036.5,"y":120.0},{"groups":["model"],"h":10.0,"id":"recall","label":"RECALL_VS_VAF","patterns":[],"r":5.0,"region":"modelarm","rx":5.0,"w":10.0,"x":1131.5,"y":120.0},{"groups":["model","wgs"],"h":14.0,"id":"rec","label":"RECONCILE_OFFTARGET_REPORT","patterns":[],"r":5.0,"region":"rep","rx":5.0,"w":10.0,"x":891.5,"y":276.0},{"groups":["wgs"],"h":10.0,"id":"out","label":"offtarget_report.csv","patterns":[],"r":5.0,"region":"rep","rx":5.0,"w":10.0,"x":986.5,"y":274.0}],"regions":[{"id":"in","label":"Samplesheet"},{"id":"ecsarm","label":"ECS arm: error-corrected truth"},{"id":"wgsarm","label":"WGS arm: genome-wide homology-free"},{"id":"modelarm","label":"Paired: WGS-only model"},{"id":"rep","label":"Report"}],"title":"Unified CRISPR Off-Target Workflow","version":"1.0","width":1254} + + +Unified CRISPR Off-Target Workflow + + +1 + + + +2 + + + +3 + + + +4 + + + +5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ECS_INDELS + +WGS_WORKLIST + +RECONCILE_OFFTARGET_REPORT + +HOTSPOT_TO_TABLE + +sample datatype guide crams vcf + +ECS truth VAF + +PON_OFFTARGET_FILTER + +offtarget_report.csv + +SCORE_HOTSPOTS + +PoN worklist + +training.tsv + +RECALL_VS_VAF + + +ECS truth (hotspots) + +WGS genome-wide discovery + +WGS-only model (ECS-trained) +created with nf-metro v1.1.0 + diff --git a/docs/images/offtarget_snapshot_example.png b/docs/images/offtarget_snapshot_example.png new file mode 100644 index 0000000..36bf359 Binary files /dev/null and b/docs/images/offtarget_snapshot_example.png differ diff --git a/docs/images/scge_analysis_DAG.jpg b/docs/images/scge_analysis_DAG.jpg new file mode 100644 index 0000000..f5ad0ab Binary files /dev/null and b/docs/images/scge_analysis_DAG.jpg differ diff --git a/docs/offtarget_metro.mmd b/docs/offtarget_metro.mmd new file mode 100644 index 0000000..72d93de --- /dev/null +++ b/docs/offtarget_metro.mmd @@ -0,0 +1,45 @@ +%%metro title: Unified CRISPR Off-Target Workflow +%%metro line: ecs | ECS truth (hotspots) | #E6194B +%%metro line: wgs | WGS genome-wide discovery | #4363D8 +%%metro line: model | WGS-only model (ECS-trained) | #3CB44B + +graph LR + subgraph in [Samplesheet] + ss[sample datatype guide crams vcf] + end + + subgraph ecsarm [ECS arm: error-corrected truth] + ecs[ECS_INDELS] + truth[ECS truth VAF] + end + + subgraph wgsarm [WGS arm: genome-wide homology-free] + wl[WGS_WORKLIST] + pon[PON_OFFTARGET_FILTER] + worklist[PoN worklist] + end + + subgraph modelarm [Paired: WGS-only model] + h2t[HOTSPOT_TO_TABLE] + score[SCORE_HOTSPOTS] + train[training.tsv] + recall[RECALL_VS_VAF] + end + + subgraph rep [Report] + rec[RECONCILE_OFFTARGET_REPORT] + out[offtarget_report.csv] + end + + ss -->|ecs| ecs + ecs -->|ecs| truth + ss -->|wgs| wl + wl -->|wgs| pon + pon -->|wgs| worklist + truth -->|model| h2t + h2t -->|model| score + score -->|model| train + train -->|model| recall + worklist -->|wgs| rec + truth -->|model| rec + rec -->|wgs| out diff --git a/docs/usage.md b/docs/usage.md index 9762418..cdd90cc 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,9 +1,5 @@ # nf-core/scge: Usage -## :warning: Please read this documentation on the nf-core website: [https://nf-co.re/scge/usage](https://nf-co.re/scge/usage) - -> _Documentation of pipeline parameters is generated automatically from the pipeline schema and can no longer be found in markdown files._ - ## Introduction @@ -75,7 +71,7 @@ If you wish to repeatedly use the same parameters for multiple runs, rather than Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. -:::warning +:::***warning*** Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such as output directories), or module arguments (args). ::: @@ -96,28 +92,6 @@ genome: 'GRCh37' You can also generate such `YAML`/`JSON` files via [nf-core/launch](https://nf-co.re/launch). -### Updating the pipeline - -When you run the above command, Nextflow automatically pulls the pipeline code from GitHub and stores it as a cached version. When running the pipeline after this, it will always use the cached version if available - even if the pipeline has been updated since. To make sure that you're running the latest version of the pipeline, make sure that you regularly update the cached version of the pipeline: - -```bash -nextflow pull nf-core/scge -``` - -### Reproducibility - -It is a good idea to specify a pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. - -First, go to the [nf-core/scge releases page](https://github.com/nf-core/scge/releases) and find the latest pipeline version - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. Of course, you can switch to another version by changing the number after the `-r` flag. - -This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. - -To further assist in reproducbility, you can use share and re-use [parameter files](#running-the-pipeline) to repeat pipeline runs with the same settings without having to write out a command with every single parameter. - -:::tip -If you wish to share such profile (such as upload as supplementary material for academic publications), make sure to NOT include cluster specific paths to files, nor institutional specific profiles. -::: - ## Core Nextflow arguments :::note @@ -152,8 +126,6 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - A generic configuration profile to be used with [Podman](https://podman.io/) - `shifter` - A generic configuration profile to be used with [Shifter](https://nersc.gitlab.io/development/shifter/how-to-use/) -- `charliecloud` - - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) - `apptainer` - A generic configuration profile to be used with [Apptainer](https://apptainer.org/) - `conda` @@ -167,58 +139,4 @@ You can also supply a run name to resume a specific run: `-resume [run-name]`. U ### `-c` -Specify the path to a specific config file (this is a core Nextflow command). See the [nf-core website documentation](https://nf-co.re/usage/configuration) for more information. - -## Custom configuration - -### Resource requests - -Whilst the default requirements set within the pipeline will hopefully work for most people and with most input data, you may find that you want to customise the compute resources that the pipeline requests. Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the steps in the pipeline, if the job exits with any of the error codes specified [here](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L18) it will automatically be resubmitted with higher requests (2 x original, then 3 x original). If it still fails after the third attempt then the pipeline execution is stopped. - -To change the resource requests, please see the [max resources](https://nf-co.re/docs/usage/configuration#max-resources) and [tuning workflow resources](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources) section of the nf-core website. - -### Custom Containers - -In some cases you may wish to change which container or conda environment a step of the pipeline uses for a particular tool. By default nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However in some cases the pipeline specified version maybe out of date. - -To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/usage/configuration#updating-tool-versions) section of the nf-core website. - -### Custom Tool Arguments - -A pipeline might not always support every possible argument or option of a particular tool used in pipeline. Fortunately, nf-core pipelines provide some freedom to users to insert additional parameters that the pipeline does not include by default. - -To learn how to provide additional arguments to a particular tool of the pipeline, please see the [customising tool arguments](https://nf-co.re/docs/usage/configuration#customising-tool-arguments) section of the nf-core website. - -### nf-core/configs - -In most cases, you will only need to create a custom config as a one-off but if you and others within your organisation are likely to be running nf-core pipelines regularly and need to use the same settings regularly it may be a good idea to request that your custom config file is uploaded to the `nf-core/configs` git repository. Before you do this please can you test that the config file works with your pipeline of choice using the `-c` parameter. You can then create a pull request to the `nf-core/configs` repository with the addition of your config file, associated documentation file (see examples in [`nf-core/configs/docs`](https://github.com/nf-core/configs/tree/master/docs)), and amending [`nfcore_custom.config`](https://github.com/nf-core/configs/blob/master/nfcore_custom.config) to include your custom profile. - -See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config.html) for more information about creating your own configuration files. - -If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack) on the [`#configs` channel](https://nfcore.slack.com/channels/configs). - -## Azure Resource Requests - -To be used with the `azurebatch` profile by specifying the `-profile azurebatch`. -We recommend providing a compute `params.vm_type` of `Standard_D16_v3` VMs by default but these options can be changed if required. - -Note that the choice of VM size depends on your quota and the overall workload during the analysis. -For a thorough list, please refer the [Azure Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/sizes). - -## Running in the background - -Nextflow handles job submissions and supervises the running jobs. The Nextflow process must run until the pipeline is finished. - -The Nextflow `-bg` flag launches Nextflow in the background, detached from your terminal so that the workflow does not stop if you log out of your session. The logs are saved to a file. - -Alternatively, you can use `screen` / `tmux` or similar tool to create a detached session which you can log back into at a later time. -Some HPC setups also allow you to run nextflow within a cluster job submitted your job scheduler (from where it submits more jobs). - -## Nextflow memory requirements - -In some cases, the Nextflow Java virtual machines can start to request a large amount of memory. -We recommend adding the following line to your environment to limit this (typically in `~/.bashrc` or `~./bash_profile`): - -```bash -NXF_OPTS='-Xms1g -Xmx4g' -``` +Specify the path to a specific config file (this is a core Nextflow command). See the [nf-core website documentation](https://nf-co.re/usage/configuration) for more information \ No newline at end of file diff --git a/main.nf b/main.nf index a258ad3..bfb4f2d 100644 --- a/main.nf +++ b/main.nf @@ -18,7 +18,10 @@ nextflow.enable.dsl = 2 include { SCGE } from './workflows/scge' include { PIPELINE_INITIALISATION } from './subworkflows/local/utils_nfcore_scge_pipeline' include { PIPELINE_COMPLETION } from './subworkflows/local/utils_nfcore_scge_pipeline' -include { INPUT_CHECK } from './subworkflows/local/input_check' +include { VALIDATE_PARAMS } from './subworkflows/local/utils_nfcore_scge_pipeline' +include { OFFTARGET_WORKFLOW } from './workflows/offtarget' +include { TRAIN_WORKFLOW } from './workflows/train' +include { GENERATE_HOTSPOTS } from './subworkflows/local/generate_hotspots' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -34,13 +37,25 @@ workflow { main: ch_versions = Channel.empty() - INPUT_CHECK(params.input) - .set { ch_input } + // + // SUBWORKFLOW: Validate params against nextflow_schema.json, print the run summary, + // and build the input channel. This is what makes --help and parameter validation + // work; INPUT_CHECK is invoked inside it, so it must not also be called here. + // + PIPELINE_INITIALISATION ( + params.version, + params.help, + params.validate_params, + params.monochrome_logs, + args, + params.outdir, + params.input + ) - ch_versions = ch_versions.mix(ch_input.versions) + ch_versions = ch_versions.mix(PIPELINE_INITIALISATION.out.versions) SCGE ( - ch_input.input + PIPELINE_INITIALISATION.out.input ) ch_versions = ch_versions.mix(SCGE.out.versions) @@ -58,6 +73,78 @@ workflow { ) } +// +// WORKFLOW: Unified CRISPR Off-Target Workflow. +// Run with: nextflow run . -entry OFFTARGET -profile ris --input offtarget_samplesheet.csv --outdir ./results +// When -entry OFFTARGET is given, the default SCGE workflow above does not run. +// +workflow OFFTARGET { + VALIDATE_PARAMS ( + params.version, + params.help, + params.validate_params, + params.monochrome_logs, + args, + params.outdir, + "nextflow run ${workflow.manifest.name} -entry OFFTARGET -profile ris2,apptainer --input offtarget_samplesheet.csv --outdir " + ) + OFFTARGET_WORKFLOW() +} + +// +// WORKFLOW: Off-Target Model Trainer (offline retrain loop). +// Run with: nextflow run . -entry TRAIN -profile ris2,apptainer --input training.tsv --outdir ./results +// Fits a new wgs_shape_model.pkl from a BUILD_TRAINING_TABLE output; deploy it via +// -entry OFFTARGET --offtarget_shape_model . +// +workflow TRAIN { + VALIDATE_PARAMS ( + params.version, + params.help, + params.validate_params, + params.monochrome_logs, + args, + params.outdir, + "nextflow run ${workflow.manifest.name} -entry TRAIN -profile ris2,apptainer --input training.tsv --outdir " + ) + TRAIN_WORKFLOW() +} + +// +// WORKFLOW: Auto-Hotspot Finder — gRNA -> predicted off-target sites (target_file). +// Run with: nextflow run . -entry HOTSPOTS -profile ris2,apptainer --input grna_samplesheet.csv --outdir ./results +// Emits, per guide, .targets.csv (readable) and .targets.vcf (feed as the +// OFFTARGET arm's per-row target_file). Cas-OFFinder by default; add --run_crisprme with a +// prebuilt --crisprme_index_dir to also include CRISPRme. +// +workflow HOTSPOTS { + VALIDATE_PARAMS ( + params.version, + params.help, + params.validate_params, + params.monochrome_logs, + args, + params.outdir, + "nextflow run ${workflow.manifest.name} -entry HOTSPOTS -profile ris2,apptainer --input grna_samplesheet.csv --outdir " + ) + + if (!params.input) { error "HOTSPOTS: provide --input grna_samplesheet.csv (columns: guide_id,spacer[,pam,idt])" } + + ch_guides = Channel.fromPath(params.input, checkIfExists: true) + | splitCsv(header: true) + | map { row -> + if (!row.guide_id?.trim() || !row.spacer?.trim()) { + error "HOTSPOTS: every --input row needs non-empty 'guide_id' and 'spacer' (got: ${row})" + } + def pam = (row.pam?.trim()) ?: params.offtarget_pam + def idt = (row.idt?.trim()) ? file(row.idt.trim(), checkIfExists: true) + : file("${projectDir}/assets/NO_IDT") + tuple([id: row.guide_id.trim()], row.spacer.trim().toUpperCase(), pam, idt) + } + + GENERATE_HOTSPOTS(ch_guides) +} + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ THE END diff --git a/modules/local/annotate_offtargets.nf b/modules/local/annotate_offtargets.nf index 89b5da2..dc210f8 100644 --- a/modules/local/annotate_offtargets.nf +++ b/modules/local/annotate_offtargets.nf @@ -5,93 +5,26 @@ process ANNOTATE_OFFTARGETS { input: tuple val(meta), path(targetfile) - path(vep_cache) - path(fasta) + path(vepcache) + path(reference) output: - tuple val(meta), path("${meta.id}.indels.annotated.tsv"), emit: targetfile + tuple val(meta), path("${meta.id}.targets.annotated.vcf"), emit: targetfile path "versions.yml", emit: versions script: - // Use params directly for vep_cache to ensure absolute path is used - // Handle both params.vepcache (absolute path) and staged vep_cache (relative path) - def vep_cache_dir = params.vepcache - ? params.vepcache.toString().replaceAll(/\/$/, '') // Remove trailing slash if present - : (vep_cache ? vep_cache.toString() : "") - - // Find fasta file from the collection - def fasta_file = fasta.find{ it ==~ /.*\.(fasta|fa)$/ }?.toString() ?: "" - def vep_args = [ targetfile ? "-i ${targetfile}" : "", - vep_cache_dir ? "--dir ${vep_cache_dir}" : "", - fasta_file ? "--fasta ${fasta_file}" : "" - ].findAll{ it }.join(' ') - + vepcache ? "--dir ${vepcache}" : "", + reference.find{ it ==~ /.*\.(fasta|fa)$/ }?.with{ "--fasta $it" } ?: "", + ].join(' ').trim() + """ - # Extract the ENTIRE header from the target file (used as keys for the Info column) - # This header should be comma-separated and will be parsed by extract_variant_reads_ML.py - LAST_COL_HEADER=\$(head -n 1 ${targetfile} | tr -d '\\r') - - # Detect delimiter (comma or tab) - if head -n 1 ${targetfile} | grep -q ','; then - DELIM="," - else - DELIM="\\t" - fi - - # Convert target CSV to VEP's ensembl input format with proper allele representation - # VEP ensembl format: chromosome start end allele strand [identifier] - # For target site annotation, we use N/N as a dummy SNP (any nucleotide) - # CSV format: Source,DNA_Sequence,PAM,Chromosome,Strand,Start,... - awk -F"\$DELIM" 'NR==1 { - for (i=1; i<=NF; i++) { - gsub(/^[ \\t]+|[ \\t]+\$/, "", \$i) # trim whitespace - if (\$i ~ /^[Cc]hromosome\$|^[Cc]hrom\$/) chr_col=i - if (\$i ~ /^[Ss]tart\$/) start_col=i - if (\$i ~ /^[Ss]trand( [Dd]irection)?\$/) strand_col=i - if (\$i ~ /^[Oo]n.?[Tt]arget\$/) ontarget_col=i - } - next - } - chr_col && start_col { - chr=\$chr_col - start=\$start_col - end=start # For point annotation, end = start - strand = strand_col ? \$strand_col : "+" - if (strand == "") strand = "+" - ontarget = ontarget_col ? \$ontarget_col : "0" - # Build identifier from all columns (comma-separated to match header) - # This will be parsed by extract_variant_reads_ML.py as key-value pairs - id="" - for (i=1; i<=NF; i++) { - if (i>1) id=id"," - id=id\$i - } - # VEP ensembl format: chr start end allele strand identifier - # Use A/T as dummy SNP allele - VEP will accept this and annotate the position - print chr, start, end, "A/T", strand, id - }' ${targetfile} > vep_input_unsorted.txt - - # Sort by chromosome and position (VEP requires sorted input) - sort -k1,1V -k2,2n vep_input_unsorted.txt > vep_input.txt - - # Check if vep_input.txt has data - if [ ! -s vep_input.txt ]; then - echo "Warning: No valid records found in target file for VEP annotation" - # Create empty output with header - echo -e "#chromosome\\tstart\\tend\\tLocation\\tAllele\\tGene\\tFeature\\tFeature_type\\tConsequence\\tcDNA_position\\tCDS_position\\tProtein_position\\tAmino_acids\\tCodons\\tExisting_variation\\tExtra\\t\$LAST_COL_HEADER" > "${meta.id}.indels.annotated.tsv" - else - # Run VEP on converted input /opt/vep/src/ensembl-vep/vep \\ --offline \\ --cache \\ - -i vep_input.txt \\ - --dir ${vep_cache_dir} \\ - --fasta ${fasta_file} \\ - --force --symbol --term SO --per_gene --fields "Location,SYMBOL,DISTANCE,INTRON,EXON" --numbers -o stdout \\ - | add_vep2targetfile.pl "\$LAST_COL_HEADER" > "${meta.id}.indels.annotated.tsv" - fi + ${vep_args} \\ + --force --symbol --numbers --per_gene --format vcf --vcf --term SO --fields "SYMBOL,Gene,Consequence,DISTANCE,INTRON,EXON" -o "${meta.id}.targets.annotated.vcf" cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/annotate_transgene_junctions.nf b/modules/local/annotate_transgene_junctions.nf new file mode 100644 index 0000000..d279e40 --- /dev/null +++ b/modules/local/annotate_transgene_junctions.nf @@ -0,0 +1,42 @@ +process ANNOTATE_TRANSGENE_JUNCTIONS { + tag "$meta.id" + label 'process_low' + container "ghcr.io/dhslab/docker-vep_release113:250810" + + input: + tuple val(meta), path(transgene_vcf) + path(reference) + path(vepcache) + path(cytobands) + + output: + tuple val(meta), path("${meta.id}.transgene_junctions.annotated.tsv"), emit: annotated_junctions + path "versions.yml", emit: versions + + script: + def annotate_args = [ + vepcache ? "--dir ${vepcache}" : "", + reference.find{ it ==~ /.*\.(fasta|fa)$/ }?.with{ "--fasta ${it}" } ?: "", + cytobands.find{ it ==~ /.*\.bed\.gz$/ }?.with{ "--plugin StructuralVariantOverlap,file=${it}" } ?: "", + transgene_vcf ? "-i ${transgene_vcf}" : "" + ].join(' ').trim() + + """ + /opt/vep/src/ensembl-vep/vep \\ + --offline \\ + --cache \\ + --symbol \\ + --term SO \\ + --flag_pick \\ + --format vcf \\ + --tab \\ + --fields Location,Consequence,SYMBOL,BIOTYPE,EXON,INTRON,STRAND,Canonical,Pick,Feature \\ + ${annotate_args} \\ + -o ${meta.id}.transgene_junctions.annotated.tsv + + cat <<-END_VERSIONS > versions.yml + ${task.process}: + vep: \$(/opt/vep/src/ensembl-vep/vep 2>&1 | grep ensembl-vep | cut -d ':' -f 2 | sed 's/\\s*//g') + END_VERSIONS + """ +} \ No newline at end of file diff --git a/modules/local/annotate_variants.nf b/modules/local/annotate_variants.nf index c04cc6b..c2632fd 100644 --- a/modules/local/annotate_variants.nf +++ b/modules/local/annotate_variants.nf @@ -14,13 +14,8 @@ process ANNOTATE_VARIANTS { path("versions.yml") , emit: versions script: - // Use params directly for vep_cache to ensure absolute path is used - def vep_cache_dir = params.vepcache - ? params.vepcache.toString().replaceAll(/\/$/, '') - : (vep_cache ? vep_cache.toString() : "") - def annotate_args = [ - vep_cache_dir ? "--dir ${vep_cache_dir}" : "", + vep_cache ? "--dir ${vep_cache}" : "", reference.find{ it ==~ /.*\.(fasta|fa)$/ }?.with{ "--fasta $it" } ?: "", dragen_files.find{ it ==~ /.*\.hard-filtered.vcf.gz$/ }?.with{ "-i $it" } ?: "" ].join(' ').trim() diff --git a/modules/local/bnd_from_indels_to_vcf.nf b/modules/local/bnd_from_indels_to_vcf.nf index 08fd6d4..df0f4b6 100644 --- a/modules/local/bnd_from_indels_to_vcf.nf +++ b/modules/local/bnd_from_indels_to_vcf.nf @@ -5,17 +5,28 @@ process BND_FROM_INDELS_TO_VCF { container "ghcr.io/dhslab/docker-baseimage:latest" input: - tuple val(meta), path(indels_txt) + tuple val(meta), path(indelfile) output: - tuple val(meta), path("${meta.id}.indels.bnd.vcf"), emit: bnd_vcf + tuple val(meta), path("${meta.id}.offtarget_svs.vcf"), emit: vcf path "versions.yml", emit: versions script: """ bnd_from_indels_to_vcf.py \\ --meta_id ${meta.id} \\ - --indels_path ${indels_txt} + --indels_path ${indelfile} \\ + --outfile ${meta.id}.offtarget_svs.vcf + + cat <<-END_VERSIONS > versions.yml + ${task.process}: + python: \$(python3 --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + """ + touch ${meta.id}.offtarget_svs.vcf cat <<-END_VERSIONS > versions.yml ${task.process}: diff --git a/modules/local/build_training_table.nf b/modules/local/build_training_table.nf new file mode 100644 index 0000000..282834a --- /dev/null +++ b/modules/local/build_training_table.nf @@ -0,0 +1,41 @@ +// BUILD_TRAINING_TABLE — join WGS hotspot features ⋈ ECS truth on (guide, chrom, start). +// Emits training.tsv (WGS features + ECS VAF + label) for the offline model trainer. +// Training is deliberately NOT in this DAG; the deployed model stays a fixed asset. +// Retrain it with the separate `-entry TRAIN` workflow (workflows/train.nf): +// -entry TRAIN --input -> a new wgs_shape_model.pkl. +process BUILD_TRAINING_TABLE { + tag "cohort" + label 'process_low' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path wgs_scores + path truth + path samplesheet + + output: + path "training.tsv", emit: training + path "versions.yml", emit: versions + + script: + // Invoke the repo script by explicit path, NOT bare name: the container bakes an older + // copy at /opt/scge-offtarget/bin that would otherwise shadow the repo's bin/ (Nextflow + // only *appends* the pipeline bin/ to PATH). Explicit `python ${projectDir}/bin/...` is + // immune to both PATH ordering and the script's executable bit. + """ + python ${projectDir}/bin/join_training_table.py \\ + --wgs-scores ${wgs_scores} \\ + --truth ${truth} \\ + --samplesheet ${samplesheet} \\ + --germline-max-ctrl-if ${params.offtarget_germline_max_ctrl_if} \\ + --out training.tsv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + "touch training.tsv versions.yml" +} diff --git a/modules/local/casoffinder.nf b/modules/local/casoffinder.nf new file mode 100644 index 0000000..ff18f1c --- /dev/null +++ b/modules/local/casoffinder.nf @@ -0,0 +1,52 @@ +// CASOFFINDER — enumerate a guide's genome-wide off-target sites with Cas-OFFinder v3 +// (mismatches + DNA/RNA bulges, done natively — no separate wrapper). Emits the v3 table +// (Id, Bulge Type, crRNA, DNA, Chromosome, Location, Direction, Mismatches, Bulge Size) that +// bin/combine_offtarget_results.py parses. CPU device ('C'), so no GPU is required. +process CASOFFINDER { + tag "${meta.id}" + label 'process_medium' + container "ghcr.io/dhslab/docker-casoffinder-bulge:latest" + + input: + tuple val(meta), val(spacer), val(pam) + path twobit + + output: + tuple val(meta), path("${meta.id}.casoffinder.txt"), emit: hits + path "versions.yml", emit: versions + + script: + def mm = params.offtarget_mismatches + def bul = params.offtarget_bulges + """ + # pocl (the CPU OpenCL driver) caches compiled kernels under \$HOME/.cache; under Apptainer's + # --no-home the host HOME is absent/unwritable, which makes pocl report "No OpenCL devices + # found". Point its cache at the (writable) task work dir so the 'C' device is available. + export POCL_CACHE_DIR="\${PWD}/.pocl_cache" + mkdir -p "\$POCL_CACHE_DIR" + + # Cas-OFFinder v3 native bulge input: genome, then " ", then + # " ". Pattern masks the protospacer with N and appends the PAM; + # the query is the spacer with N placeholders for the PAM bases (equal length to the pattern). + SPACER=${spacer} + PAM=${pam} + PATTERN=\$(printf 'N%.0s' \$(seq 1 \${#SPACER}))\${PAM} + QUERY=\${SPACER}\$(printf 'N%.0s' \$(seq 1 \${#PAM})) + + printf '%s\\n%s %s %s\\n%s %s\\n' \\ + "\$(readlink -f ${twobit})" "\$PATTERN" "${bul}" "${bul}" "\$QUERY" "${mm}" > casoffinder_input.txt + + cas-offinder casoffinder_input.txt C ${meta.id}.casoffinder.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cas-offinder: \$(cas-offinder 2>&1 | grep -oE 'Cas-OFFinder [0-9][0-9.a-z]*' | head -1 || echo NA) + END_VERSIONS + """ + + stub: + """ + printf '##Generated by Cas-OFFinder (stub)\\n#Id\\tBulge Type\\tcrRNA\\tDNA\\tChromosome\\tLocation\\tDirection\\tMismatches\\tBulge Size\\n' > ${meta.id}.casoffinder.txt + touch versions.yml + """ +} diff --git a/modules/local/combine_offtarget_sites.nf b/modules/local/combine_offtarget_sites.nf new file mode 100644 index 0000000..6ff3c35 --- /dev/null +++ b/modules/local/combine_offtarget_sites.nf @@ -0,0 +1,40 @@ +// COMBINE_OFFTARGET_SITES — merge one guide's per-tool off-target predictions +// (Cas-OFFinder bulge output, CRISPRme, optionally IDT) into the canonical +// `.targets.csv` schema the OFFTARGET arm consumes as a target_file. +// Any source may be omitted by passing assets/NO_FILE; at least one must be real. +process COMBINE_OFFTARGET_SITES { + tag "${meta.id}" + label 'process_low' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + tuple val(meta), path(casoffinder), path(crisprme), path(idt) + + output: + tuple val(meta), path("${meta.id}.targets.csv"), emit: sites + path "versions.yml", emit: versions + + script: + // Optional slots are passed as distinct NO_* sentinel files (distinct names avoid a + // staging collision); a real tool output never starts with 'NO_'. + def real = { f -> f && !f.name.startsWith('NO_') } + def cas_arg = real(casoffinder) ? "--casoffinder ${casoffinder}" : '' + def cme_arg = real(crisprme) ? "--crisprme ${crisprme}" : '' + def idt_arg = real(idt) ? "--idt ${idt}" : '' + """ + python ${projectDir}/bin/combine_offtarget_results.py \\ + ${cas_arg} \\ + ${cme_arg} \\ + ${idt_arg} \\ + --pam ${params.offtarget_pam} \\ + -o ${meta.id}.targets.csv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + "touch ${meta.id}.targets.csv versions.yml" +} diff --git a/modules/local/compile_report_json.nf b/modules/local/compile_report_json.nf index 0c43c05..03b1452 100644 --- a/modules/local/compile_report_json.nf +++ b/modules/local/compile_report_json.nf @@ -5,57 +5,57 @@ process COMPILE_REPORT_JSON { container 'ghcr.io/dhslab/docker-baseimage:latest' input: - tuple val(meta), - path(cna_plot), - path(baf_plot), - val(circos_plot), - path(on_target_sv_transgene), - path(vcf_tsv), - path(off_target_indels), - path(bnd_vcf), - path(tumor_cov), - path(normal_cov), - val(timestamp) + tuple val(meta), path(files) + val(timestamp) output: - tuple val(meta), path("report_input.json"), emit: json - path "versions.yml" , emit: versions + tuple val(meta), path("${meta.id}.scge_report.json"), emit: json + path "versions.yml" , emit: versions - when: - task.ext.when == null || task.ext.when script: def args = task.ext.args ?: '' - def transgene_str = params.transgene ?: (meta.transgene ?: "N/A") - def control_sample = params.control_sample ?: (meta.normal ?: "N/A") - def grnas_str = params.grnas ?: meta.id - def hotspot_file_arg = meta.hotspot_file ? "--hotspot_file ${meta.hotspot_file}" : "" - def circos_arg = (circos_plot && circos_plot.toString().endsWith(".png") && file(circos_plot).exists()) ? "--circos_plot ${circos_plot}" : "" - def tumor_coverage_arg = tumor_cov ? "--tumor_coverage ${tumor_cov}" : "" - def normal_coverage_arg = normal_cov ? "--normal_coverage ${normal_cov}" : "" + def input = [ + files.find{ it ==~ /.*\.wgs_overall_mean_cov_tumor\.csv$/ }?.with{ "--tumor_coverage $it" } ?: "", + files.find{ it ==~ /.*\.wgs_overall_mean_cov_normal\.csv$/ }?.with{ "--normal_coverage $it" } ?: "", + files.find{ it ==~ /.*\.cna_plot\.png$/ }?.with{ "--cna_plot $it" } ?: "", + files.find{ it ==~ /.*\.baf_plot\.png$/ }?.with{ "--baf_plot $it" } ?: "", + files.find{ it ==~ /.*\.annotated_transgene_insertions\.tsv$/ }?.with{ "--transgene_insertions $it" } ?: "", + files.find{ it ==~ /.*\.transgene_insertions_circos\.png$/ }?.with{ "--circos_plot $it" } ?: "", + files.find{ it ==~ /.*\.hard-filtered\.annotated\.tsv$/ }?.with{ "--somatic_variants $it" } ?: "", + files.find{ it ==~ /.*\.offtarget_analysis\.tsv$/ }?.with{ "--offtarget_indels $it" } ?: "", + files.find{ it ==~ /.*\.offtarget_svs\.vcf$/ }?.with{ "--offtarget_svs $it" } ?: "", + ].join(' ').trim() + """ - export PATH=/usr/local/bin:\$PATH - python3 ${projectDir}/bin/compile_report_data.py \\ + compile_report_data.py \\ --sample_id ${meta.id} \\ - --transgene "${transgene_str}" \\ - --control_sample "${control_sample}" \\ - --grnas "${grnas_str}" \\ - ${hotspot_file_arg} \\ - --cna_plot ${cna_plot} \\ - --baf_plot ${baf_plot} \\ - ${circos_arg} \\ - --on_target_sv_transgene ${on_target_sv_transgene} \\ - --vcf_tsv ${vcf_tsv} \\ - --off_target_indels ${off_target_indels} \\ - --bnd_vcf ${bnd_vcf} \\ - ${tumor_coverage_arg} \\ - ${normal_coverage_arg} \\ - --output report_input.json + --control_id "${meta.normal_id}" \\ + ${input} \\ + --output ${meta.id}.scge_report.json + + cat <<-END_VERSIONS > versions.yml + ${task.process}: + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + // Without this, `-stub-run` executes the REAL script above against stub-generated + // (empty) inputs, compile_report_data.py exits on its required arguments, and the + // whole stub run dies here -- before it ever reaches the review arm downstream. That + // is why no stub run has ever exercised REVIEW_FILTER / REVIEW_FILTER_BND and their + // snapshot renderers. + // + // versions.yml must carry real content even in a stub: nf-core's + // processVersionsFromYAML does yaml.load(f).collectEntries{...}, and an empty file + // loads as null -> NPE at pipeline completion. + """ + echo '{}' > ${meta.id}.scge_report.json cat <<-END_VERSIONS > versions.yml ${task.process}: python: \$(python --version | sed 's/Python //g') - pandas: \$(python -c "import pandas; print(pandas.__version__)") END_VERSIONS """ -} \ No newline at end of file +} \ No newline at end of file diff --git a/modules/local/crisprme.nf b/modules/local/crisprme.nf new file mode 100644 index 0000000..de674a2 --- /dev/null +++ b/modules/local/crisprme.nf @@ -0,0 +1,73 @@ +// CRISPRME — enumerate a guide's off-target sites (mismatches + DNA/RNA bulges) against a +// PREBUILT CRISPRme/CRISPRitz index. Emits the CRISPRme integrated-results TSV that +// bin/combine_offtarget_results.py parses. Off by default (params.run_crisprme); the index is a +// heavy one-time offline asset built by bin/build_crisprme_index.sh — this module only consumes it. +// +// The index dir (params.crisprme_index_dir) must contain, as built by build_crisprme_index.sh: +// Genome/ per-chromosome unzipped FASTAs +// genome_library/__Genome/ the TST index (bMax must equal bDNA+bRNA of the search) +// bp--.txt the PAM file (its name encodes the nuclease) +// CRISPRme looks for genome_library relative to the CWD, so we symlink the staged index into the +// task work dir before running complete-search — that reuses the prebuilt index instead of +// rebuilding it (verified: prebuilt .bin files are left untouched). +process CRISPRME { + tag "${meta.id}" + label 'process_high' + // Lab wrapper over pinellolab/crisprme that adds procps (`ps`) — Nextflow's task wrapper needs + // it under -euo pipefail. See containers/docker-crisprme/Dockerfile. Build/push before enabling. + container "ghcr.io/dhslab/docker-crisprme:latest" + // CRISPRme writes scratch files (e.g. vuoto.txt) into its own read-only install dir under + // Apptainer; an ephemeral writable overlay lets those succeed without persisting anything. + containerOptions '--writable-tmpfs' + + input: + tuple val(meta), val(spacer), val(pam) + path index_dir + + output: + tuple val(meta), path("${meta.id}.crisprme.tsv"), emit: hits + path "versions.yml", emit: versions + + script: + def mm = params.offtarget_mismatches + def bul = params.offtarget_bulges + """ + # CRISPRme ships in a conda env its entrypoint activates; Nextflow bypasses the entrypoint, + # so put its tools on PATH. + export PATH=/opt/conda/bin:\$PATH + + # Expose the prebuilt index in the CWD so complete-search reuses it (it resolves + # genome_library relative to the working directory) instead of rebuilding. + ln -s ${index_dir}/Genome Genome + ln -s ${index_dir}/genome_library genome_library + PAMFILE=\$(basename \$(ls ${index_dir}/*bp-*-*.txt | head -1)) + cp ${index_dir}/\$PAMFILE . + + # guide file: spacer padded with N over the PAM positions (CRISPRme's crRNA format) + printf '%s%s\\n' "${spacer}" "\$(printf 'N%.0s' \$(seq 1 ${pam.length()}))" > guide.txt + + crisprme.py complete-search \\ + --genome Genome \\ + --pam \$PAMFILE \\ + --guide guide.txt \\ + --mm ${mm} \\ + --bDNA ${bul} \\ + --bRNA ${bul} \\ + --output ${meta.id}_crisprme \\ + --thread ${task.cpus} + + # the parseable target table is the integrated-results TSV (schema consumed by the combiner) + cp Results/${meta.id}_crisprme/*_integrated_results.tsv ${meta.id}.crisprme.tsv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + crisprme: \$(crisprme.py --version 2>&1 | tail -1 || echo NA) + END_VERSIONS + """ + + stub: + """ + printf 'Spacer+PAM\\tChromosome\\tStart\\tStrand\\tx\\tDNA\\tx\\tPAM\\tMismatches\\tBulges\\tx\\tx\\tx\\tx\\tx\\tBulge_type\\n' > ${meta.id}.crisprme.tsv + touch versions.yml + """ +} diff --git a/modules/local/ecs_indels.nf b/modules/local/ecs_indels.nf new file mode 100644 index 0000000..e8aa716 --- /dev/null +++ b/modules/local/ecs_indels.nf @@ -0,0 +1,48 @@ +// ECS_INDELS — deep, error-corrected edit calls at the hotspot panel (the TRUTH arm). +// Wraps bin/find_edited_reads.py directly (explicit --edited-bam/--control-bam, no length +// heuristic), producing .offtarget_analysis.tsv whose indel_fraction is the ECS VAF. +process ECS_INDELS { + tag "$meta.id" + label 'process_highmem' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + tuple val(meta), val(edited_cram), val(control_cram), val(target_file) + val reference + + output: + tuple val(meta), path("${meta.id}.offtarget_analysis.tsv"), emit: indels_file + tuple val(meta), path("${meta.id}.offtarget_edits.vcf"), emit: indels_vcf + tuple val(meta), path("${meta.id}.tagged.bam*"), optional: true, emit: tagged_bam + path "versions.yml", emit: versions + + script: + // The per-read "unevaluable reads" log is a debug artifact that is NOT an emitted + // output and is not consumed downstream, yet it grows to ~0.1-1 TB per sample and + // was the sole cause of multi-TB work-dir bloat / ENOSPC. Off unless explicitly asked. + def unevaluable = params.offtarget_ecs_unevaluable_log ? "-u ${meta.id}.unevaluable_reads.txt" : "" + // Review aid, not a pipeline input: a BAM of the target windows in which every read + // carries an XC tag naming the per-read call, for colouring the pileup in IGV. Window- + // restricted, but it still scales with target count -- off unless explicitly asked. + def tagged_bam = params.offtarget_tagged_bam ? "--tagged-bam-out ${meta.id}.tagged.bam" : "" + """ + python ${projectDir}/bin/find_edited_reads.py \\ + --fasta ${reference} \\ + --edited-bam ${edited_cram} \\ + --control-bam ${control_cram} \\ + --target-file ${target_file} \\ + ${unevaluable} \\ + ${tagged_bam} \\ + --vcf-out ${meta.id}.offtarget_edits.vcf \\ + -o ${meta.id}.offtarget_analysis.tsv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + def tagged_bam = params.offtarget_tagged_bam ? "${meta.id}.tagged.bam ${meta.id}.tagged.bam.bai" : "" + "touch ${meta.id}.offtarget_analysis.tsv ${meta.id}.offtarget_edits.vcf ${tagged_bam} versions.yml" +} diff --git a/modules/local/ecs_indels.nf.test b/modules/local/ecs_indels.nf.test new file mode 100644 index 0000000..3294e27 --- /dev/null +++ b/modules/local/ecs_indels.nf.test @@ -0,0 +1,140 @@ +nextflow_process { + + name "ECS_INDELS" + script "modules/local/ecs_indels.nf" + process "ECS_INDELS" + tag "ecs" + tag "tagged_bam" + tag "offtarget" + + /* + * Runs the REAL edit caller (bin/find_edited_reads.py) on real CRAMs. + * + * Fixture: tests/fixtures/ecs/ — 5.5 KB total, built by make_ecs_fixture.py from the + * same read model tests/conftest.py uses. A 3 kb contig with two targets 200 bp apart: + * + * target A @ chr1:1001 edited — 12 of 20 evaluable pairs carry a 5 bp deletion + * target B @ chr1:1201 quiet — no edit + * + * edited.cram holds 35 pairs / 70 records: 12 edited, 8 clean, and — the useful part — + * 2 duplicate-flagged, 2 at MAPQ 3, 2 at NM 6, plus 9 pairs sitting in the region where + * the two +/-150 bp fetch windows overlap. Those last ones are visited by BOTH targets, + * which is exactly where a per-read writer is tempted to emit a read twice. + * + * Division of labour: the pytest suite owns the tag VOCABULARY and per-read precedence + * (it can open the BAM with pysam). This file owns what pytest cannot see — that + * params.offtarget_tagged_bam actually becomes a --tagged-bam-out flag, that the BAM + * *and its index* both land on the declared output channel, and that the caller's + * numbers survive the trip through Nextflow staging. + */ + + test("calls the edit and reports the right VAF — tagged BAM off by default") { + + when { + params { + offtarget_tagged_bam = false + } + process { + """ + def fx = "\${projectDir}/tests/fixtures/ecs" + input[0] = [ + [ id: 'DEMO' ], + file("\${fx}/edited.cram"), + file("\${fx}/control.cram"), + file("\${fx}/targets.vcf") + ] + input[1] = file("\${fx}/ref.fa") + """ + } + } + + then { + assert process.success + + // --- the caller's actual numbers ----------------------------------------- + def tsv = file(process.out.indels_file[0][1]).readLines() + def hdr = tsv[0].split('\t') as List + def rows = tsv[1..-1].collect { line -> + [hdr, line.split('\t', -1) as List].transpose().collectEntries() + } + + assert rows.size() == 2 // one row per target + + def a = rows.find { it.start == '1000' } // target A, the edited site + def b = rows.find { it.start == '1200' } // target B, the quiet site + assert a != null && b != null + + // 12 edited pairs out of 20 evaluable. The 2 duplicate / 2 low-MAPQ / + // 2 high-mismatch pairs must NOT be in that denominator — if a filter + // regresses, total_reads climbs above 20 and this VAF drops. + assert a.total_reads == '20' + assert a.indel_reads == '12' + assert Math.abs(Double.parseDouble(a.indel_fraction) - 0.6) < 1e-9 + assert a.indel_count == '1' + assert a.indel_info.contains('|1000|') // the 5 bp deletion, left-anchored + + // the matched control carries no edit at all: this is what makes the call somatic + assert a.control_reads == '20' + assert a.control_indel_reads == '0' + + // the quiet target must stay quiet — a caller that leaks reads between the two + // overlapping windows shows up here first + assert b.indel_reads == '0' + assert Math.abs(Double.parseDouble(b.indel_fraction)) < 1e-9 + + // --- the review BAM is opt-in ------------------------------------------- + // it costs ~800 MB on a real sample, so silence here is the correct default + assert process.out.tagged_bam.size() == 0 + + assert process.out.indels_vcf.size() == 1 + assert process.out.versions.size() == 1 + } + } + + test("offtarget_tagged_bam=true emits a per-read tagged BAM and its index") { + + when { + params { + offtarget_tagged_bam = true + } + process { + """ + def fx = "\${projectDir}/tests/fixtures/ecs" + input[0] = [ + [ id: 'DEMO' ], + file("\${fx}/edited.cram"), + file("\${fx}/control.cram"), + file("\${fx}/targets.vcf") + ] + input[1] = file("\${fx}/ref.fa") + """ + } + } + + then { + assert process.success + + // The param really reached the command line. With the flag absent the caller + // writes nothing and this channel stays empty, so an empty channel here means + // the params.offtarget_tagged_bam -> --tagged-bam-out wiring is broken. + assert process.out.tagged_bam.size() == 1 + + def emitted = process.out.tagged_bam[0][1] + def names = (emitted instanceof List ? emitted : [emitted]) + .collect { file(it).name }.sort() + + // the `${meta.id}.tagged.bam*` glob must capture the INDEX too — a BAM without + // its .bai cannot be loaded in IGV, which is the entire purpose of this output + assert names == ['DEMO.tagged.bam', 'DEMO.tagged.bam.bai'] + + def bam = (emitted instanceof List ? emitted : [emitted]) + .find { file(it).name.endsWith('.bam') } + assert file(bam).size() > 0 + + // the TSV is unchanged by tagging — the review aid must not perturb the calls + def tsv = file(process.out.indels_file[0][1]).readLines() + assert tsv.size() == 3 + assert tsv[1].contains('\t12\t0.6\t') + } + } +} diff --git a/modules/local/generate_cna_baf_plots.nf b/modules/local/generate_cna_baf_plots.nf index a7c70df..1ce5c86 100644 --- a/modules/local/generate_cna_baf_plots.nf +++ b/modules/local/generate_cna_baf_plots.nf @@ -1,63 +1,39 @@ process GENERATE_CNA_BAF_PLOTS { tag "${meta.id}" label 'process_low' - - container 'ghcr.io/dhslab/docker-clerbase:250719' - - publishDir "${params.outdir}/pipeline_info/cna_baf_plots/${meta.id}", mode: 'copy', pattern: '*.png' + container 'ghcr.io/dhslab/docker-rbase4.4.0:251223' input: tuple val(meta), path(dragen_files, stageAs: "dragen_files/*") output: - tuple val(meta), path("*cna_plot.png"), emit: cna_plot - tuple val(meta), path("*baf_plot.png"), emit: baf_plot - path "versions.yml", emit: versions + tuple val(meta), path("${meta.id}.cna_plot.png"), path("${meta.id}.baf_plot.png"), emit: plots + path "versions.yml" , emit: versions script: - def inputs = [ - meta.id, - dragen_files.find{ it ==~ /.*\.(baf.bedgraph.gz)$/ } ?: "", - dragen_files.find{ it ==~ /.*\.(tn.tsv.gz)$/ } ?: "" + def args = task.ext.args ?: '' + def input = [ + "--id ${meta.id}", + dragen_files.find{ it ==~ /.*\.baf\.bedgraph\.gz$/ }?.with{ "--baf $it" } ?: "", + dragen_files.find{ it ==~ /.*\.tn\.tsv\.gz$/ }?.with{ "--cn $it" } ?: "" ].join(' ').trim() - """ - export PATH=\$PATH:/usr/local/bin - echo "DEBUG: PATH is \$PATH" - echo "DEBUG: Rscript location: \$(which Rscript || echo 'not found')" - - generate_cna_baf_plots.R ${inputs} + generate_cna_baf_plots.R ${input} - cat <<-'END_VERSIONS' > versions.yml + cat <<-END_VERSIONS > versions.yml "${task.process}": - r-base: \$(R --version | sed 's/.*version \\([0-9.]*\\).*/\\1/') - ggplot2: \$(R --vanilla --quiet -e "cat(as.character(packageVersion('ggplot2')))") - dplyr: \$(R --vanilla --quiet -e "cat(as.character(packageVersion('dplyr')))") - cowplot: \$(R --vanilla --quiet -e "cat(as.character(packageVersion('cowplot')))") - genomicranges: \$(R --vanilla --quiet -e "cat(as.character(packageVersion('GenomicRanges')))") + generate_cna_baf_plots: \$(generate_cna_baf_plots.R --version) END_VERSIONS """ stub: - def inputs = [ - ${meta.id}, - dragen_files.find{ it ==~ /.*\.(baf.bedgraph.gz)$/ } ?: "", - dragen_files.find{ it ==~ /.*\.(tn.tsv.gz)$/ } ?: "" - ].join(' ').trim() - """ - touch ${meta.id}.cna_plot.png touch ${meta.id}.baf_plot.png - - cat <<-'END_VERSIONS' > versions.yml + cat <<-END_VERSIONS > versions.yml "${task.process}": - r-base: \$(R --version | sed 's/.*version \\([0-9.]*\\).*/\\1/') - ggplot2: \$(R --vanilla --quiet -e "cat(as.character(packageVersion('ggplot2')))") - dplyr: \$(R --vanilla --quiet -e "cat(as.character(packageVersion('dplyr')))") - cowplot: \$(R --vanilla --quiet -e "cat(as.character(packageVersion('cowplot')))") - genomicranges: \$(R --vanilla --quiet -e "cat(as.character(packageVersion('GenomicRanges')))") + generate_cna_baf_plots: \$(generate_cna_baf_plots.R --version) END_VERSIONS """ -} \ No newline at end of file +} \ No newline at end of file diff --git a/modules/local/generate_excel_report.nf b/modules/local/generate_excel_report.nf new file mode 100644 index 0000000..2a53f18 --- /dev/null +++ b/modules/local/generate_excel_report.nf @@ -0,0 +1,54 @@ +process GENERATE_EXCEL_REPORT { + tag "${meta.id}" + label "process_low" + label "final_output" + container "ghcr.io/dhslab/docker-baseimage:latest" + + input: + tuple val(meta), path(report_json), path(cna_plot), path(baf_plot), path(circos_plot), path(indel_plot), path(off_target_plot) + + output: + path("${meta.id}.scge_report.xlsx"), emit: excel_report + path("versions.yml") , emit: versions + + script: + """ + # No runtime pip install: the container already ships pandas + openpyxl, and installing at + # task time needs network on every compute node and silently changes the versions the run + # computed with. (It also just fails here -- user site-packages are disabled in this Python.) + + # Defensive copy/dereference logic for Circos + CIRCOS_FILENAME="" + if [ -s "${circos_plot}" ]; then + CIRCOS_FILENAME=\$(basename "${circos_plot}") + if [ -L "\${CIRCOS_FILENAME}" ]; then + cp -L "\${CIRCOS_FILENAME}" "dereferenced_circos.png" + mv "dereferenced_circos.png" "\${CIRCOS_FILENAME}" + fi + fi + + make_scge_excel.py \\ + --report_json "${report_json}" \\ + --circos_plot "\${CIRCOS_FILENAME}" \\ + --cna_plot "${cna_plot}" \\ + --baf_plot "${baf_plot}" \\ + --indel_freq_plot "${indel_plot}" \\ + --off_targets_plot "${off_target_plot}" \\ + --output "${meta.id}.scge_report.xlsx" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + """ + touch ${meta.id}.scge_report.xlsx + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ +} \ No newline at end of file diff --git a/modules/local/get_indels.nf b/modules/local/get_indels.nf index 0aa3eb3..693c65a 100644 --- a/modules/local/get_indels.nf +++ b/modules/local/get_indels.nf @@ -1,45 +1,42 @@ process GET_INDELS { tag "$meta.id" label 'process_highmem' + label 'final_output' container "ghcr.io/dhslab/docker-scge:latest" input: tuple val(meta), path(dragen_files, stageAs: "dragen_files/*"), path(hotspot_file) path(crispr_model) - path(fasta_files) + path(reference) output: - tuple val(meta), path("${meta.id}.indels.txt"), emit: indels_file - tuple val(meta), path("${meta.id}.ml_results.txt"), emit: ml_results - tuple val(meta), path("${meta.id}.fp_filtered.txt"), emit: fp_log + tuple val(meta), path("${meta.id}.offtarget_analysis.tsv"), emit: indels_file + tuple val(meta), path("${meta.id}.offtarget_edits.vcf"), emit: indels_vcf + tuple val(meta), path("${meta.id}.tagged.bam*"), optional: true, emit: tagged_bam + //tuple val(meta), path("${meta.id}.ml_results.txt"), emit: ml_results + //tuple val(meta), path("${meta.id}.fp_filtered.txt"), emit: fp_log path "versions.yml", emit: versions script: def inputs = [ - crispr_model ? "--enable-crispr-prediction --crispr-model ${crispr_model} --crispr-threshold 0.7" : "", + reference.find{ it ==~ /.*\.(fasta|fa)$/ }?.with{ "--fasta $it" } ?: "", +// crispr_model ? "--enable-crispr-prediction --crispr-model ${crispr_model} --crispr-threshold 0.7" : "", dragen_files.findAll{ it ==~ /.*\.(cram)$/ }.max{ it.toString().length() }?.with{ "--edited-bam $it" } ?: "", dragen_files.findAll{ it ==~ /.*\.(cram)$/ }.min{ it.toString().length() }?.with{ "--control-bam $it" } ?: "", hotspot_file ? "--target-file ${hotspot_file}" : "" ].join(' ').trim() - // Find the main fasta file (not .fai) - handle empty channel case - def fasta_file = null - if (fasta_files) { - if (fasta_files instanceof List) { - fasta_file = fasta_files.find { it.name.endsWith('.fa') || it.name.endsWith('.fasta') } - } else if (fasta_files.name?.endsWith('.fa') || fasta_files.name?.endsWith('.fasta')) { - fasta_file = fasta_files - } - } - def ref_arg = fasta_file ? "--fasta ${fasta_file}" : "" - """ - export PATH=/usr/local/bin:\$PATH - - extract_variant_reads_ML.py ${inputs} ${ref_arg} --filter-off-target-fp \\ - --fp-log ${meta.id}.fp_filtered.txt -v -o ${meta.id}.indels.txt + // Optional review aid: a window-restricted BAM whose reads carry an XC tag naming + // the per-read call, for colouring the pileup in IGV. Off unless explicitly asked. + def tagged_bam = params.offtarget_tagged_bam ? "--tagged-bam-out ${meta.id}.tagged.bam" : "" - # Extract ML results into a separate file, preserving the header - cut -f 17-19 ${meta.id}.indels.txt > ${meta.id}.ml_results.txt + // The per-read "unevaluable reads" log is a debug artifact, not an emitted output, and it + // runs ~0.1-1 TB per sample. Passed unconditionally it filled the shared scratch2 group + // quota and killed three CAR-T runs before anyone traced it. Gated behind the same param + // ecs_indels.nf already uses; off by default. + def unevaluable = params.offtarget_ecs_unevaluable_log ? "-u ${meta.id}.unevaluable_reads.txt" : "" + """ + find_edited_reads.py ${inputs} ${tagged_bam} ${unevaluable} --vcf-out ${meta.id}.offtarget_edits.vcf -o ${meta.id}.offtarget_analysis.tsv cat <<-END_VERSIONS > versions.yml ${task.process}: @@ -48,17 +45,11 @@ process GET_INDELS { """ stub: - def inputs = [ - crispr_model ? "--enable-crispr-prediction --crispr-model ${crispr_model} --crispr-threshold 0.7" : "", - dragen_files.findAll{ it ==~ /.*\.(cram)$/ }.max{ it.toString().length() }?.with{ "--edited-bam $it" } ?: "", - dragen_files.findAll{ it ==~ /.*\.(cram)$/ }.min{ it.toString().length() }?.with{ "--control-bam $it" } ?: "", - hotspot_file ? "--target-file ${hotspot_file}" : "" - ].join(' ').trim() - + def tagged_bam = params.offtarget_tagged_bam ? "touch ${meta.id}.tagged.bam ${meta.id}.tagged.bam.bai" : "" """ - touch ${meta.id}.fp_filtered.txt - touch ${meta.id}.indels.txt - touch ${meta.id}.ml_results.txt + touch ${meta.id}.offtarget_analysis.tsv + touch ${meta.id}.offtarget_edits.vcf + ${tagged_bam} cat <<-END_VERSIONS > versions.yml ${task.process}: diff --git a/modules/local/get_transgene_junctions.nf b/modules/local/get_transgene_junctions.nf index ad1e2e8..9beb175 100644 --- a/modules/local/get_transgene_junctions.nf +++ b/modules/local/get_transgene_junctions.nf @@ -6,6 +6,7 @@ process GET_TRANSGENE_JUNCTIONS { input: tuple val(meta), path(dragen_files) path(fasta) + val(transgene_name) output: tuple val(meta), path("${meta.id}.transgene_out.tsv"), emit: transgene_file @@ -14,15 +15,13 @@ process GET_TRANSGENE_JUNCTIONS { script: def input = [ fasta.find{ it ==~ /.*\.(fasta|fa)$/ }?.with{ "--reference $it" } ?: "", + transgene_name ? "--name ${transgene_name}" : "", params.transgene_match_coordinates ? "-x ${params.transgene_match_coordinates}" : "", - params.transgene_name ? "${params.transgene_name}" : "", dragen_files.findAll{ it ==~ /.*\.(cram)$/ }.max{ it.toString().length() }?.with{ "$it" } ?: "", ].join(' ').trim() """ - export PATH=\$PATH:/usr/local/bin - - getTransgeneJunctions.py ${input} > ${meta.id}.transgene_out.tsv + getTransgeneJunctions.py ${input} -o ${meta.id}.transgene_out.tsv cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -32,9 +31,9 @@ process GET_TRANSGENE_JUNCTIONS { stub: def input = [ - fasta ? "--reference ${fasta}" : "", + fasta.find{ it ==~ /.*\.(fasta|fa)$/ }?.with{ "--reference $it" } ?: "", + transgene_name ? "--name ${transgene_name}" : "", params.transgene_match_coordinates ? "-x ${params.transgene_match_coordinates}" : "", - transgene_name ? "${transgene_name}" : "", dragen_files.findAll{ it ==~ /.*\.(cram)$/ }.max{ it.toString().length() }?.with{ "$it" } ?: "", ].join(' ').trim() diff --git a/modules/local/hotspot_to_table.nf b/modules/local/hotspot_to_table.nf new file mode 100644 index 0000000..68716fa --- /dev/null +++ b/modules/local/hotspot_to_table.nf @@ -0,0 +1,35 @@ +// HOTSPOT_TO_TABLE — turn the ECS hotspot panel (+ ECS truth VAF) into a score.py input +// table keyed to the WGS samples of the same guide. Emits the scoring table and the ECS +// truth table for the downstream training-table / recall joins. +process HOTSPOT_TO_TABLE { + tag "cohort" + label 'process_low' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path ecs_tables // all ECS *.offtarget_analysis.tsv + path samplesheet + + output: + path "wgs_hotspot_input_table.csv", emit: table + path "ecs_hotspot_truth.csv", emit: truth + path "versions.yml", emit: versions + + script: + """ + python ${projectDir}/bin/hotspot_to_table.py \\ + --ecs-tables ${ecs_tables} \\ + --samplesheet ${samplesheet} \\ + --edit-threshold ${params.offtarget_ecs_edit_threshold} \\ + --out-table wgs_hotspot_input_table.csv \\ + --out-truth ecs_hotspot_truth.csv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + "touch wgs_hotspot_input_table.csv ecs_hotspot_truth.csv versions.yml" +} diff --git a/modules/local/make_circos_plot.nf b/modules/local/make_circos_plot.nf index 93434f0..4e56c0c 100644 --- a/modules/local/make_circos_plot.nf +++ b/modules/local/make_circos_plot.nf @@ -7,16 +7,20 @@ process MAKE_CIRCOS_PLOT { tuple val(meta), path(circos_input) output: - tuple val(meta), path("*png"), emit: circos_plot + tuple val(meta), path("${meta.id}.transgene_insertions_circos.png"), emit: plot + // Invoke circos from PATH, not an absolute versioned path. The container tag above floats, + // so a hardcoded /circos-/bin/circos breaks silently the first time upstream + // publishes a new release -- 0.69-9 -> 0.69-10 did exactly that (exit 127). script: """ if [ -s "$circos_input" ]; then cp ${projectDir}/bin/circos.conf . && \\ sed -i "s|__FILE_PLACEHOLDER__|$circos_input|" circos.conf && \\ - /circos-0.69-9/bin/circos -conf circos.conf + circos -conf circos.conf + mv *.png ${meta.id}.transgene_insertions_circos.png else - touch "${meta.id}_circos.png" + touch "${meta.id}.transgene_insertions_circos.png" fi cat <<-END_VERSIONS > versions.yml @@ -27,7 +31,7 @@ process MAKE_CIRCOS_PLOT { stub: """ - touch "${meta.id}_circos.png" + touch "${meta.id}.transgene_insertions_circos.png" cat <<-END_VERSIONS > versions.yml ${task.process}: diff --git a/modules/local/make_hotspot_vcf.nf b/modules/local/make_hotspot_vcf.nf index 5b6efde..5c85bc9 100644 --- a/modules/local/make_hotspot_vcf.nf +++ b/modules/local/make_hotspot_vcf.nf @@ -1,4 +1,5 @@ process MAKE_HOTSPOT_VCF { + tag "${id}" label 'process_low' container "ghcr.io/dhslab/docker-cleutils" @@ -14,7 +15,7 @@ process MAKE_HOTSPOT_VCF { script: def args = [ bed_file.find{ it ==~ /.*\.(bed)$/ }?.with{ "--bed $it" } ?: "", - editing_targets.find{ it ==~ /.*\.(csv)$/ }?.with{ "--targets $it" } ?: "", + editing_targets.find{ it ==~ /.*\.(vcf|vcf.gz)$/ }?.with{ "--targets $it" } ?: "", params.hotspot_window_size ? "--window ${params.hotspot_window_size}" : "", reference.find{ it ==~ /.*\.(fasta|fa)$/ }?.with{ "--fasta $it" } ?: "" ].join(' ').trim() diff --git a/modules/local/offtarget_metrics.nf b/modules/local/offtarget_metrics.nf new file mode 100644 index 0000000..8f524b3 --- /dev/null +++ b/modules/local/offtarget_metrics.nf @@ -0,0 +1,43 @@ +// OFFTARGET_METRICS — the metrics a recall-first diagnostic is judged on: PR-AUC and +// recall-weighted F-beta (F2, F5), plus precision/recall/F1 at the reported operating +// point. Computed against the ECS label in training.tsv, which has a genuine two-class +// label — NEVER against the manual review, which has no confirmed negatives (its NaNs +// mean "unreviewed", not "rejected"). Recall vs manual review stays with +// bin/validate_recall.py and stays recall-only. Both denominators are stamped into the +// outputs so the two can never be confused. +process OFFTARGET_METRICS { + tag "cohort" + label 'process_low' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path training + + output: + path "offtarget_metrics.json", emit: metrics + path "offtarget_metrics.txt", emit: report + path "offtarget_pr_curve.png", optional: true, emit: curve + path "versions.yml", emit: versions + + script: + """ + python ${projectDir}/bin/offtarget_metrics.py \\ + --training ${training} \\ + --hi ${params.offtarget_hi_score} \\ + --min-ecs-vaf ${params.offtarget_min_ecs_vaf} \\ + --min-ecs-reads ${params.offtarget_min_ecs_reads} \\ + --betas ${params.offtarget_metrics_betas} \\ + --negatives ${params.offtarget_metrics_negatives} \\ + --out-json offtarget_metrics.json \\ + --out-txt offtarget_metrics.txt \\ + --out-curve offtarget_pr_curve.png + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + "touch offtarget_metrics.json offtarget_metrics.txt offtarget_pr_curve.png versions.yml" +} diff --git a/modules/local/offtarget_metrics.nf.test b/modules/local/offtarget_metrics.nf.test new file mode 100644 index 0000000..040b633 --- /dev/null +++ b/modules/local/offtarget_metrics.nf.test @@ -0,0 +1,167 @@ +nextflow_process { + + name "OFFTARGET_METRICS" + script "modules/local/offtarget_metrics.nf" + process "OFFTARGET_METRICS" + tag "metrics" + tag "offtarget" + + /* + * What this covers that nothing else does. + * + * bin/offtarget_metrics.py is already tested hard by tests/test_offtarget_glue.py — + * that suite owns the MATH. This file owns the WIRING: that the process script block + * hands the script flags it actually accepts, that params.offtarget_metrics_* reach + * the command line, and that the declared output channels match the filenames the + * script really writes. The stub for this process is `touch`, so a stub run would + * stay green if every one of those were wrong. + * + * Fixture: tests/fixtures/training_mini.tsv — 11 rows, hand-built so that every + * number asserted below can be checked on paper: + * + * 6 credible positives (label=1, ecs_is_edit=1, ecs_if=0.20, 50 indel reads) + * scores .95 .90 .85 .70 — called LIKELY EDIT -> 4 TP + * score .30 — called LIKELY EDIT -> 1 TP (see below) + * score .25 — called ARTIFACT -> 1 FN + * 1 credible positive with NO score (INSUFFICIENT COVERAGE) -> excluded from ranking + * 4 ECS negatives (label=0, ecs_is_edit=0) + * scores .80 .75 — called LIKELY EDIT -> 2 FP + * scores .20 .10 — called ARTIFACT -> 2 TN + * + * The score=0.30 positive is deliberate. Calls come from the VERDICT column, not from + * `score >= hi` — a high-evidence rescue is reported as a LIKELY EDIT at a model score + * below the threshold. A test that assumed `score >= 0.60` would compute 4 TP here and + * be wrong; that same confusion was a real mislabelled axis on the recall figure. + */ + + test("computes the real metrics and emits every declared channel") { + + when { + process { + """ + input[0] = file("\${projectDir}/tests/fixtures/training_mini.tsv") + """ + } + } + + then { + assert process.success + + def out = new groovy.json.JsonSlurper() + .parseText(file(process.out.metrics[0]).text) + def m = out.metrics + def op = m.operating_point + def eps = 1e-6 + + // --- the declared output channels are all really produced ----------------- + assert process.out.metrics.size() == 1 + assert process.out.report.size() == 1 + assert process.out.versions.size() == 1 + assert file(process.out.metrics[0]).name == "offtarget_metrics.json" + assert file(process.out.report[0]).name == "offtarget_metrics.txt" + + // --- denominator composition --------------------------------------------- + // the no-score positive is excluded from the ranking, NOT silently counted + // as a miss and NOT folded into the negatives. + assert m.n_pos == 6 + assert m.n_neg == 4 + assert m.n_excluded_no_score == 1 + assert m.n_excluded_no_score_pos == 1 + assert out.counts.n_positives_credible == 7 + + // --- confusion matrix at the reported operating point -------------------- + assert op.tp == 5 + assert op.fp == 2 + assert op.fn == 1 + assert op.tn == 2 + assert Math.abs(op.precision - 5.0 / 7.0) < eps // 0.7143 + assert Math.abs(op.recall - 5.0 / 6.0) < eps // 0.8333 + + // recall over ALL credible positives including the uncovered one — the honest + // number, and strictly lower than `recall`. If these two are ever equal, the + // depth floor has gone missing from the report. + assert Math.abs(op.recall_incl_unevaluable - 5.0 / 7.0) < eps + assert op.recall_incl_unevaluable < op.recall + + // --- F-beta really is recall-weighted ------------------------------------ + // The whole point of shipping F2/F5: here recall (0.833) > precision (0.714), + // so F_beta must RISE with beta. F_beta is monotone in beta, so F1 is always + // an endpoint of the set — F1 in the middle means --betas was applied + // backwards. + assert op.f1 < op.f2 + assert op.f2 < op.f5 + assert Math.abs(op.f1 - 0.769231) < 1e-5 + assert Math.abs(op.f2 - 0.806452) < 1e-5 + assert Math.abs(op.f5 - 0.828025) < 1e-5 + + // --- ranking quality ------------------------------------------------------ + // imperfect on purpose: two negatives outrank two positives. + assert Math.abs(m.pr_auc - 0.855159) < 1e-5 + assert Math.abs(m.roc_auc - 0.75) < 1e-5 + + // --- the human-readable report names BOTH denominators -------------------- + // This report gets pasted into slides. It must say out loud that it scores + // against the ECS label and not against manual review, because manual review + // has no confirmed negatives (NaN there means unreviewed, not rejected). + def txt = file(process.out.report[0]).text + assert txt.contains("NOT vs human review") + assert txt.toLowerCase().contains("manual review") + } + } + + test("--betas reaches the script: a custom beta set changes the reported columns") { + + when { + params { + offtarget_metrics_betas = '3' + } + process { + """ + input[0] = file("\${projectDir}/tests/fixtures/training_mini.tsv") + """ + } + } + + then { + assert process.success + + def op = new groovy.json.JsonSlurper() + .parseText(file(process.out.metrics[0]).text) + .metrics.operating_point + + // proves params.offtarget_metrics_betas is actually interpolated into the + // command, not merely declared in nextflow_schema.json and ignored. + assert op.containsKey('f3') + assert !op.containsKey('f2') + assert !op.containsKey('f5') + // recall > precision, so F3 must sit above F1 + assert op.f3 > op.f1 + } + } + + test("--negatives all_label0 is honoured as a distinct negative set") { + + when { + params { + offtarget_metrics_negatives = 'all_label0' + } + process { + """ + input[0] = file("\${projectDir}/tests/fixtures/training_mini.tsv") + """ + } + } + + then { + assert process.success + + // The fixture has no germline-demoted rows, so both negative sets are the same + // size here. What this asserts is that the switch is PLUMBED: an unrecognised + // value makes argparse exit non-zero and fails the process — precisely the + // wiring bug a stub run cannot see. + def m = new groovy.json.JsonSlurper() + .parseText(file(process.out.metrics[0]).text).metrics + assert m.n_neg == 4 + } + } +} diff --git a/modules/local/pon_offtarget_filter.nf b/modules/local/pon_offtarget_filter.nf new file mode 100644 index 0000000..8f67cac --- /dev/null +++ b/modules/local/pon_offtarget_filter.nf @@ -0,0 +1,36 @@ +// PON_OFFTARGET_FILTER — Panel-of-Normals post-filter (the shallow-normal fix). +// Wraps bin/pon_filter.py. Pools ALL unedited normals in the cram map and demotes any +// LIKELY-EDIT candidate that shows the same indel in ANY donor's normal (germline/mosaic +// leak the single matched normal was too shallow to catch). Genuine gather step. +process PON_OFFTARGET_FILTER { + tag "cohort" + label 'process_medium' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path worklist + path cram_map + val reference + + output: + path "wgs_offtarget_worklist_pon.csv", emit: worklist + path "versions.yml", emit: versions + + script: + """ + python ${projectDir}/bin/pon_filter.py \\ + --worklist ${worklist} \\ + --cram-list ${cram_map} \\ + --ref ${reference} \\ + --top ${params.offtarget_top} \\ + --out wgs_offtarget_worklist_pon.csv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + "touch wgs_offtarget_worklist_pon.csv versions.yml" +} diff --git a/modules/local/prep_casoffinder_ref.nf b/modules/local/prep_casoffinder_ref.nf new file mode 100644 index 0000000..7c024cc --- /dev/null +++ b/modules/local/prep_casoffinder_ref.nf @@ -0,0 +1,28 @@ +// PREP_CASOFFINDER_REF — build the .2bit Cas-OFFinder searches against, from the +// pipeline reference FASTA. Runs once per pipeline (faToTwoBit is cheap/deterministic); +// skip it entirely by setting params.casoffinder_2bit to a prebuilt .2bit. +process PREP_CASOFFINDER_REF { + tag "${fasta.baseName}" + label 'process_low' + container "ghcr.io/dhslab/docker-casoffinder-bulge:latest" + + input: + path fasta + + output: + path "${fasta.baseName}.2bit", emit: twobit + path "versions.yml", emit: versions + + script: + """ + faToTwoBit ${fasta} ${fasta.baseName}.2bit + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + faToTwoBit: \$(faToTwoBit 2>&1 | grep -oE 'faToTwoBit v[0-9.]+' | head -1 || echo NA) + END_VERSIONS + """ + + stub: + "touch ${fasta.baseName}.2bit versions.yml" +} diff --git a/modules/local/recall_vs_vaf.nf b/modules/local/recall_vs_vaf.nf new file mode 100644 index 0000000..7d2546a --- /dev/null +++ b/modules/local/recall_vs_vaf.nf @@ -0,0 +1,36 @@ +// RECALL_VS_VAF — the honest limit, measured. From the training table, compute WGS +// recall of ECS-confirmed edits as a function of ECS VAF, and the VAF floor above which +// WGS-only detection is trustworthy. Curve + metrics CSV. +process RECALL_VS_VAF { + tag "cohort" + label 'process_low' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path training + + output: + path "recall_vs_vaf.csv", emit: metrics + path "recall_vs_vaf.png", optional: true, emit: curve + path "versions.yml", emit: versions + + script: + """ + python ${projectDir}/bin/recall_vs_vaf.py \\ + --training ${training} \\ + --hi ${params.offtarget_hi_score} \\ + --target-recall ${params.offtarget_target_recall} \\ + --min-ecs-vaf ${params.offtarget_min_ecs_vaf} \\ + --min-ecs-reads ${params.offtarget_min_ecs_reads} \\ + --out-metrics recall_vs_vaf.csv \\ + --out-curve recall_vs_vaf.png + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + "touch recall_vs_vaf.csv recall_vs_vaf.png versions.yml" +} diff --git a/modules/local/reconcile_offtarget_report.nf b/modules/local/reconcile_offtarget_report.nf new file mode 100644 index 0000000..0606ce1 --- /dev/null +++ b/modules/local/reconcile_offtarget_report.nf @@ -0,0 +1,34 @@ +// RECONCILE_OFFTARGET_REPORT — annotate the genome-wide PoN worklist with is_hotspot / +// ecs_confirmed / ecs_if, so a reviewer sees whether a homology-free WGS hit is a known +// predicted (ECS-backed) site or a novel candidate. Truth is optional (wgs_only mode). +process RECONCILE_OFFTARGET_REPORT { + tag "cohort" + label 'process_low' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path worklist + path truth // ecs_hotspot_truth.csv, or the NO_FILE placeholder + + output: + path "offtarget_report.csv", emit: report + path "versions.yml", emit: versions + + script: + def truth_arg = truth.name != 'NO_FILE' ? "--truth ${truth}" : "" + """ + python ${projectDir}/bin/reconcile_offtarget_report.py \\ + --worklist ${worklist} \\ + ${truth_arg} \\ + --pad ${params.offtarget_hotspot_pad} \\ + --out offtarget_report.csv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + "touch offtarget_report.csv versions.yml" +} diff --git a/modules/local/render_scge_report.nf b/modules/local/render_scge_report.nf index 36d1cd9..b729490 100644 --- a/modules/local/render_scge_report.nf +++ b/modules/local/render_scge_report.nf @@ -5,11 +5,13 @@ process RENDER_SCGE_REPORT { container "ghcr.io/dhslab/docker-quarto-chromoseq:latest" input: - tuple val(meta), path(report_json), path(cna_plot), path(baf_plot) + tuple val(meta), path(report_json), path(cna_plot), path(baf_plot), path(circos_plot) path(scge_report_qmd) output: - path("${meta.id}.scge_report.html") , emit: scge_report + tuple val(meta), path("${meta.id}.scge_report.html") , emit: scge_report + tuple val(meta), path("indel_freq.png"), emit: indel_plot + tuple val(meta), path("off_targets.png"), emit: off_targets_plot path("versions.yml") , emit: versions when: @@ -24,10 +26,81 @@ process RENDER_SCGE_REPORT { # Add quarto to PATH export PATH="/opt/quarto/bin:\$PATH" + # Quarto writes a cache under \$HOME on startup. \$HOME is not writable inside the container + # on the cluster, so it aborts with "Read-only file system ... mkdir '\$HOME/.cache/quarto'" + # before rendering anything. Point HOME and the XDG cache at the task work dir, which always + # is writable. + export HOME="\$PWD" + export XDG_CACHE_HOME="\$PWD/.cache" + export XDG_DATA_HOME="\$PWD/.local/share" + mkdir -p "\$XDG_CACHE_HOME" "\$XDG_DATA_HOME" + # Debug: verify tools are available - which quarto && which Rscript || { echo "ERROR: Required tools not found"; exit 1; } + which quarto && which Rscript || { echo "ERROR: quarto or Rscript not on PATH"; exit 1; } + + # Create params file for Quarto to avoid shell quoting issues + # Ensure circos_plot is just the filename if it exists + CIRCOS_FILENAME="" + if [ -s "${circos_plot}" ]; then + CIRCOS_FILENAME=\$(basename "${circos_plot}") + # Resolve symlink to physical file to prevent container mount issues + if [ -L "\${CIRCOS_FILENAME}" ]; then + cp -L "\${CIRCOS_FILENAME}" "dereferenced_circos.png" + mv "dereferenced_circos.png" "\${CIRCOS_FILENAME}" + fi + fi + + # Copy QMD to current directory to ensure relative paths work correctly + # (Quarto can sometimes resolve symlinked QMDs to their original dir) + cp "${scge_report_qmd}" "report.qmd" + + # Copy all input images to current directory if not already there + # This ensures they are in the same directory as the .qmd file being rendered + if [ -s "${cna_plot}" ]; then + CNA_BASENAME=\$(basename "${cna_plot}") + if [ ! -f "\${CNA_BASENAME}" ]; then + cp -L "${cna_plot}" "\${CNA_BASENAME}" + fi + fi + if [ -s "${baf_plot}" ]; then + BAF_BASENAME=\$(basename "${baf_plot}") + if [ ! -f "\${BAF_BASENAME}" ]; then + cp -L "${baf_plot}" "\${BAF_BASENAME}" + fi + fi + # Also copy off-target plots if they exist + if [ -f "indel_freq.png" ]; then + cp -L "indel_freq.png" "indel_freq_copy.png" + mv "indel_freq_copy.png" "indel_freq.png" + fi + if [ -f "off_targets.png" ]; then + cp -L "off_targets.png" "off_targets_copy.png" + mv "off_targets_copy.png" "off_targets.png" + fi - quarto render ${scge_report_qmd} -P report_json:"${report_json}" -P off_target_threshold:${params.off_target_threshold} --output "${meta.id}.scge_report.html" + cat < params.yml + report_json: "${report_json}" + off_target_threshold: ${params.off_target_threshold} + cna_plot_file: "${cna_plot}" + baf_plot_file: "${baf_plot}" + circos_plot_file: "\${CIRCOS_FILENAME}" + transgene_name: "${params.transgene_name ?: ''}" + EOF + + # Explicitly set execution dir to current dir + quarto render "report.qmd" --execute-dir . --execute-params params.yml --output "${meta.id}.scge_report.html" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + quarto: \$(quarto --version) + END_VERSIONS + """ + + stub: + """ + touch ${meta.id}.scge_report.html + touch indel_freq.png + touch off_targets.png cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/review_bnd_snapshots.nf b/modules/local/review_bnd_snapshots.nf new file mode 100644 index 0000000..e464254 --- /dev/null +++ b/modules/local/review_bnd_snapshots.nf @@ -0,0 +1,55 @@ +// REVIEW_BND_SNAPSHOTS — the breakend half of the review packet. +// +// One PNG per JUNCTION, not per queue row: bnd_review_queue.tsv reports each event from +// both ends and at a few bp of jitter, so the rows outnumber the junctions several-fold +// (25 rows / 8 junctions on the CAR-T cohort). Each figure is a to-scale schematic of +// the rearrangement over a 2x2 read grid — left and right breakpoint, each with the edited +// sample above its matched unedited control — with reads whose SA tag lands at the +// partner locus drawn green. The schematic branches on orientation: an inverted junction is +// drawn with the segment retained and reversed, not excised. +// +// Same CRAM-map-by-absolute-path convention as REVIEW_SNAPSHOTS, and the same reason: +// the queue names arbitrary samples, and staging every cohort CRAM to draw a handful of +// pictures would copy terabytes. +process REVIEW_BND_SNAPSHOTS { + tag "cohort" + label 'process_medium' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path bnd_queue + path cram_map + val reference + + output: + path "bnd_snapshots/*.png", optional: true, emit: snapshots + path "versions.yml", emit: versions + + script: + """ + python ${projectDir}/bin/bnd_snapshots.py \\ + --queue ${bnd_queue} \\ + --cram-map ${cram_map} \\ + --fasta ${reference} \\ + --window ${params.review_bnd_snapshot_window} \\ + --max-junctions ${params.review_bnd_max_junctions} \\ + --outdir bnd_snapshots + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + // versions.yml must carry real content even in a stub: nf-core's processVersionsFromYAML + // does yaml.load(f).collectEntries{...}, and an empty file loads as null -> NPE. + """ + mkdir -p bnd_snapshots && touch bnd_snapshots/stub_bnd_junction.png + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ +} diff --git a/modules/local/review_bnd_snapshots.nf.test b/modules/local/review_bnd_snapshots.nf.test new file mode 100644 index 0000000..8ecc9b0 --- /dev/null +++ b/modules/local/review_bnd_snapshots.nf.test @@ -0,0 +1,159 @@ +nextflow_process { + + name "REVIEW_BND_SNAPSHOTS" + script "modules/local/review_bnd_snapshots.nf" + process "REVIEW_BND_SNAPSHOTS" + tag "bnd" + tag "review" + tag "offtarget" + + /* + * Runs the REAL junction renderer (bin/bnd_snapshots.py) on real CRAMs. + * + * Fixture: tests/fixtures/bnd/ -- 48 KB, built by make_bnd_fixture.py. An 8 kb contig + * with two breakpoints 4,000 bp apart, i.e. the multi-cut deletion that accounts for + * 23 of the 25 breakend rows in the CAR-T cohort: + * + * edited.cram 40 clean reads tiled across the two breakpoints, plus 14 SPLIT + * reads whose primary is clipped at one breakpoint and whose + * supplementary segment sits at the partner, carrying an SA tag + * control.cram the same 40 clean reads, no split reads, no SA tags + * + * The split reads are the reason this file cannot be a stub test. Until this change + * bin/pileup_snapshot.py dropped `is_supplementary` unconditionally, which hid + * precisely the alignments that constitute a junction -- the figure rendered, looked + * plausible, and showed nothing. `keep_supplementary=True` plus the SA-derived + * highlight set is what has to be proven actually wired, and only a real run can. + * + * Division of labour, per nf-test.config: + * tests/test_bnd_snapshots.py owns the row-to-junction ARITHMETIC (against the + * real 25-row cohort queue). + * this file owns the WIRING -- that the module's flags are ones + * the script accepts, that params.review_bnd_* reach + * the command line, and that the declared output + * channel matches the path the script really writes. + * + * The queue here is 5 rows describing ONE junction, reported from both ends with a + * few bp of jitter and both strand orientations -- the cohort's own pattern. If the + * collapse regressed, this would emit 5 PNGs, not 1. + */ + + test("renders one figure per junction, not one per queue row") { + + when { + process { + """ + def fx = "\${projectDir}/tests/fixtures/bnd" + + // CRAM paths travel as a MAP of absolute paths, not as staged inputs -- + // the queue names arbitrary samples, and staging every cohort CRAM to draw + // a few pictures would copy TBs. Nextflow stages this small map file + // itself, so it only has to be readable from the launch side. + def m = new File(System.getProperty("java.io.tmpdir"), + "bnd_cram_map_\${System.nanoTime()}.tsv") + m.text = "BNDDEMO\\t\${fx}/edited.cram\\t\${fx}/control.cram\\n" + + input[0] = file("\${fx}/bnd_review_queue.tsv") + input[1] = file(m.getAbsolutePath()) + input[2] = "\${fx}/ref.fa" + """ + } + } + + then { + assert process.success + + // --- 5 queue rows, 1 junction, 1 figure -------------------------------- + assert process.out.snapshots.size() == 1 + def png = file(process.out.snapshots[0]) + + // filename encodes BOTH ends, canonically ordered: this is how a reviewer + // finds the figure for a junction they read about in the queue. + assert png.name == "001_BNDDEMO_chr1_2000_chr1_6000.png" + + // a real rendering, not an empty canvas + assert png.size() > 20000 + + // --- versions.yml must have real content ------------------------------- + // nf-core's processVersionsFromYAML does yaml.load(f).collectEntries{...}; + // an empty file loads as null and NPEs the whole pipeline at completion. + assert process.out.versions.size() == 1 + def versions = file(process.out.versions[0]).text + assert versions.contains("REVIEW_BND_SNAPSHOTS") + assert versions.contains("python:") + assert versions.trim().length() > 0 + } + } + + test("params.review_bnd_max_junctions reaches the command line") { + + when { + params { + review_bnd_max_junctions = 0 + } + process { + """ + def fx = "\${projectDir}/tests/fixtures/bnd" + + // CRAM paths travel as a MAP of absolute paths, not as staged inputs -- + // the queue names arbitrary samples, and staging every cohort CRAM to draw + // a few pictures would copy TBs. Nextflow stages this small map file + // itself, so it only has to be readable from the launch side. + def m = new File(System.getProperty("java.io.tmpdir"), + "bnd_cram_map_\${System.nanoTime()}.tsv") + m.text = "BNDDEMO\\t\${fx}/edited.cram\\t\${fx}/control.cram\\n" + + input[0] = file("\${fx}/bnd_review_queue.tsv") + input[1] = file(m.getAbsolutePath()) + input[2] = "\${fx}/ref.fa" + """ + } + } + + then { + // A cap of 0 renders nothing, and the script still exits 0 -- the output is + // declared `optional: true` precisely so an empty cohort is not a failure. + // If --max-junctions were not interpolated, the default of 200 would apply + // and this would emit the figure anyway. That is the assertion. + assert process.success + assert process.out.snapshots.size() == 0 + assert process.out.versions.size() == 1 + } + } + + test("params.review_bnd_snapshot_window is a flag the script accepts") { + + when { + params { + review_bnd_snapshot_window = 600 + } + process { + """ + def fx = "\${projectDir}/tests/fixtures/bnd" + + // CRAM paths travel as a MAP of absolute paths, not as staged inputs -- + // the queue names arbitrary samples, and staging every cohort CRAM to draw + // a few pictures would copy TBs. Nextflow stages this small map file + // itself, so it only has to be readable from the launch side. + def m = new File(System.getProperty("java.io.tmpdir"), + "bnd_cram_map_\${System.nanoTime()}.tsv") + m.text = "BNDDEMO\\t\${fx}/edited.cram\\t\${fx}/control.cram\\n" + + input[0] = file("\${fx}/bnd_review_queue.tsv") + input[1] = file(m.getAbsolutePath()) + input[2] = "\${fx}/ref.fa" + """ + } + } + + then { + // argparse exits non-zero on an unrecognised flag, so a renamed or + // misspelled --window in the module fails the process here. That is the + // arity class of bug a stub run cannot see: `-stub-run` never executes a + // single line of bin/*.py. + assert process.success + assert process.out.snapshots.size() == 1 + assert file(process.out.snapshots[0]).size() > 20000 + } + } +} diff --git a/modules/local/review_filter.nf b/modules/local/review_filter.nf new file mode 100644 index 0000000..381843a --- /dev/null +++ b/modules/local/review_filter.nf @@ -0,0 +1,81 @@ +// REVIEW_FILTER — turn the raw off-target call table into the short list a human reviews. +// +// Wraps bin/review_filter.py. Six rules, first match wins: matched control clean, indel within +// 10 bp of a PAM position, >=3 distinct indel lengths, not a known-bad site (panel of normals), +// not inside a repeat, and not on a recurrent indel-noise locus in the external DRAGEN panel. +// On the 32-sample CAR-T WGS cohort this takes 1,498 gated rows to an 88-site queue (87 with +// rule 6 enabled) while retaining all 81 on-target edits. +// +// Rule 4 is params.review_noise_model: a beta-binomial test against the sample's OWN unedited +// control, which needs no cohort and so works for a SINGLE-GUIDE submission. The panel of normals +// it replaced has been removed. With the model off the process falls back to cross-guide +// recurrence, which needs several differently-guided samples in the same invocation and cannot +// fire at all for one guide -- which is why all samples are still staged into a single call. +// +// Rule 6 (--snv-noise) is off unless params.review_snv_noise is set. It streams a ~1 GB unindexed +// BED, and this process invokes the script twice, so enabling it costs roughly 6 minutes. +process REVIEW_FILTER { + tag "cohort" + label 'process_single' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path analysis_tsvs + path repeat_beds + path snv_noise + + output: + path "review_queue.tsv", emit: queue + path "review_queue_all.tsv", emit: audit + path "versions.yml", emit: versions + + script: + def rep_arg = repeat_beds ? "--repeats ${repeat_beds.join(' ')}" : '' + def snv_arg = snv_noise.name != 'NO_FILE' + ? "--snv-noise ${snv_noise} --snv-noise-min-donors ${params.review_snv_noise_min_donors}" + : '' + def nm_arg = params.review_noise_model != 'off' + ? "--noise-model ${params.review_noise_model} --aq-min ${params.review_aq_min}" + + (params.review_depth_floor ? '' : ' --no-depth-floor') + : '' + def strict_arg = params.review_strict_fallback ? '--strict-fallback' : '' + """ + python ${projectDir}/bin/review_filter.py ${analysis_tsvs} \\ + ${rep_arg} ${snv_arg} ${nm_arg} ${strict_arg} \\ + --min-reads ${params.review_min_reads} \\ + --min-vaf ${params.review_min_vaf} \\ + --max-cut-dist ${params.review_max_cut_dist} \\ + --min-distinct-len ${params.review_min_distinct_len} \\ + --max-control-vaf ${params.review_max_control_vaf} \\ + -o review_queue.tsv + + # Same thresholds, nothing filtered: every gated row with a why_dropped column, so a + # reviewer can audit what was removed and why without re-running anything. + python ${projectDir}/bin/review_filter.py ${analysis_tsvs} \\ + ${rep_arg} ${snv_arg} ${nm_arg} ${strict_arg} \\ + --min-reads ${params.review_min_reads} \\ + --min-vaf ${params.review_min_vaf} \\ + --max-cut-dist ${params.review_max_cut_dist} \\ + --min-distinct-len ${params.review_min_distinct_len} \\ + --max-control-vaf ${params.review_max_control_vaf} \\ + --keep-all \\ + -o review_queue_all.tsv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + // versions.yml must carry real content even in a stub: nf-core's processVersionsFromYAML + // does yaml.load(f).collectEntries{...}, and an empty file loads as null -> NPE. + """ + touch review_queue.tsv review_queue_all.tsv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ +} diff --git a/modules/local/review_filter_bnd.nf b/modules/local/review_filter_bnd.nf new file mode 100644 index 0000000..08d236e --- /dev/null +++ b/modules/local/review_filter_bnd.nf @@ -0,0 +1,79 @@ +// REVIEW_FILTER_BND — the breakend counterpart of REVIEW_FILTER. +// +// Wraps bin/review_filter_bnd.py. Reads the same *.offtarget_analysis.tsv tables as REVIEW_FILTER +// and triages the BND calls rather than the indels. On the 32-sample CAR-T WGS cohort (the +// 2026-08-17 run): 1,022 breakends -> 25 pass the evidence gate -> 25 reach the queue, i.e. rules +// 2-4 drop nothing and the >= 3 read gate is the only filter that acts. Those 25 rows are 8 +// junctions (23 multi-cut INVERSION rows across 7 samples, segment 413 bp to 126 kb, 2 inversion +// rows at a cut site, 0 translocations, 0 off-target junctions). See docs/OFFTARGET.md. +// +// These were labelled "multi-cut deletion" until 2026-08-20. The classifier ignored `strands`, and +// every same-chromosome row in this queue is +-/-+ — an inversion. Orientation is now part of the +// call. +// +// The earlier "2,404 -> 36 -> 25" in this header described the 2026-08-10 run, before the caller +// changed; do not quote it against current output. +// +// The rules differ from the indel side because a junction has two ends. Length diversity is +// meaningless here, so it is replaced by breakpoint promiscuity: a bin joining many distinct +// partners is a mapping hub rather than biology, with the real cut sites exempt. +// +// The SV noise panel (--sv-noise) is off unless params.review_sv_noise is set, and only the WGS +// v3.1.0 panel is safe -- the IDPF and FF_Heme panels flag 25/25 and 24/25 of the real junctions +// respectively. See the warning in nextflow.config next to review_sv_noise. +process REVIEW_FILTER_BND { + tag "cohort" + label 'process_single' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path analysis_tsvs + path sv_noise + + output: + path "bnd_review_queue.tsv", emit: queue + path "bnd_review_queue_all.tsv", emit: audit + path "versions.yml", emit: versions + + script: + def sv_arg = sv_noise.name != 'NO_FILE' + ? "--sv-noise ${sv_noise} --sv-noise-slop ${params.review_sv_noise_slop}" + : '' + """ + python ${projectDir}/bin/review_filter_bnd.py ${analysis_tsvs} \\ + ${sv_arg} \\ + --min-reads ${params.review_bnd_min_reads} \\ + --max-cut-dist ${params.review_bnd_max_cut_dist} \\ + --max-partners ${params.review_bnd_max_partners} \\ + --bin-size ${params.review_bnd_bin_size} \\ + -o bnd_review_queue.tsv + + # Same thresholds, nothing filtered: every gated row with a why_dropped column, so a + # reviewer can audit what was removed and why without re-running anything. + python ${projectDir}/bin/review_filter_bnd.py ${analysis_tsvs} \\ + ${sv_arg} \\ + --min-reads ${params.review_bnd_min_reads} \\ + --max-cut-dist ${params.review_bnd_max_cut_dist} \\ + --max-partners ${params.review_bnd_max_partners} \\ + --bin-size ${params.review_bnd_bin_size} \\ + --keep-all \\ + -o bnd_review_queue_all.tsv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + // versions.yml must carry real content even in a stub: nf-core's processVersionsFromYAML + // does yaml.load(f).collectEntries{...}, and an empty file loads as null -> NPE. + """ + touch bnd_review_queue.tsv bnd_review_queue_all.tsv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ +} diff --git a/modules/local/review_snapshots.nf b/modules/local/review_snapshots.nf new file mode 100644 index 0000000..9846590 --- /dev/null +++ b/modules/local/review_snapshots.nf @@ -0,0 +1,50 @@ +// REVIEW_SNAPSHOTS — turn the review queue into a packet of IGV-style pileup images. +// +// One PNG per surviving site, edited sample on top and its matched unedited control below. +// That pairing is what makes the packet self-adjudicating: germline and shared alignment +// artifacts appear in both panels, a real edit appears in only one. +// +// CRAMs are read from an absolute-path map rather than staged, matching the convention +// SCORE_HOTSPOTS already uses for its cram list: the queue names arbitrary samples, so staging +// every cohort CRAM into this one task would copy terabytes to render a few dozen pictures. +process REVIEW_SNAPSHOTS { + tag "cohort" + label 'process_medium' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path review_queue + path cram_map + val reference + + output: + path "snapshots/*.png", optional: true, emit: snapshots + path "versions.yml", emit: versions + + script: + """ + python ${projectDir}/bin/review_snapshots.py \\ + --queue ${review_queue} \\ + --cram-map ${cram_map} \\ + --fasta ${reference} \\ + --window ${params.review_snapshot_window} \\ + --outdir snapshots + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + // versions.yml must carry real content even in a stub: nf-core's processVersionsFromYAML + // does yaml.load(f).collectEntries{...}, and an empty file loads as null -> NPE. + """ + mkdir -p snapshots && touch snapshots/stub_review_site.png + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ +} diff --git a/modules/local/score_hotspots.nf b/modules/local/score_hotspots.nf new file mode 100644 index 0000000..765c63d --- /dev/null +++ b/modules/local/score_hotspots.nf @@ -0,0 +1,56 @@ +// SCORE_HOTSPOTS — score the WGS CRAMs at the ECS hotspot panel with the shape model. +// Wraps bin/score.py with the homology gate OFF and the stage-1 if/control gates opened +// (the table's indel_fraction is a gate-passer; real signal is recomputed from the WGS +// CRAM). Output is the per-hotspot WGS feature+score table. +process SCORE_HOTSPOTS { + tag "cohort" + label 'process_medium' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path table + path cram_map + path model + val reference + + output: + path "wgs_hotspot_scores.csv", emit: scores + // Per-read XC-tagged BAMs for IGV, one per WGS sample, covering the called sites only. + // Optional because --offtarget_wgs_tagged_bam is off by default. + path "wgs_tagged/*.bam*", optional: true, emit: tagged_bam + path "versions.yml", emit: versions + + script: + """ + python ${projectDir}/bin/score.py \\ + --table ${table} \\ + --cram-list ${cram_map} \\ + --ref ${reference} \\ + --model ${model} \\ + --no-homology-gate \\ + --include-ontarget \\ + --min-ifrac -1 \\ + --max-control 2 \\ + --min-span ${params.offtarget_min_span} \\ + ${params.offtarget_max_cut_dist != null ? "--max-cut-dist ${params.offtarget_max_cut_dist}" : ''} \\ + ${params.offtarget_wgs_tagged_bam ? "--tagged-bam-dir wgs_tagged" : ''} \\ + ${params.offtarget_rescue ? "--rescue-min-ifrac ${params.offtarget_rescue_min_ifrac} --rescue-min-conc ${params.offtarget_rescue_min_conc} --rescue-min-span ${params.offtarget_rescue_min_span}" : '--no-rescue'} \\ + --out wgs_hotspot_scores.csv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + // the tagged BAMs are an `optional:` output, but the stub must still create them when the + // param is on, or a stub run silently exercises a different DAG than the real one + def tagged = params.offtarget_wgs_tagged_bam + ? "mkdir -p wgs_tagged && touch wgs_tagged/stub.wgs_tagged.bam wgs_tagged/stub.wgs_tagged.bam.bai" + : "true" + """ + touch wgs_hotspot_scores.csv versions.yml + ${tagged} + """ +} diff --git a/modules/local/targets_csv_to_vcf.nf b/modules/local/targets_csv_to_vcf.nf new file mode 100644 index 0000000..ad03336 --- /dev/null +++ b/modules/local/targets_csv_to_vcf.nf @@ -0,0 +1,33 @@ +// TARGETS_CSV_TO_VCF — expand a combined off-target sites CSV into the per-base hotspot +// VCF the OFFTARGET arm consumes as a target_file (windowed, merged, reference-ordered). +process TARGETS_CSV_TO_VCF { + tag "${meta.id}" + label 'process_low' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + tuple val(meta), path(sites_csv) + path fasta + path fai + + output: + tuple val(meta), path("${meta.id}.targets.vcf"), emit: vcf + path "versions.yml", emit: versions + + script: + """ + python ${projectDir}/bin/targets_csv_to_vcf.py \\ + --csv ${sites_csv} \\ + --fasta ${fasta} \\ + --window ${params.hotspot_window_size} \\ + -o ${meta.id}.targets.vcf + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + "touch ${meta.id}.targets.vcf versions.yml" +} diff --git a/modules/local/train_shape_model.nf b/modules/local/train_shape_model.nf new file mode 100644 index 0000000..60796c5 --- /dev/null +++ b/modules/local/train_shape_model.nf @@ -0,0 +1,40 @@ +// TRAIN_SHAPE_MODEL — offline trainer for the off-target WGS shape model. +// Reads a training.tsv (BUILD_TRAINING_TABLE output) and fits the Stage-2 shape +// ranker consumed by score.py / worklist_from_vcf.py. Runs only under -entry TRAIN; +// the deployed OFFTARGET pipeline keeps the model as a fixed asset by design. +process TRAIN_SHAPE_MODEL { + tag "train" + label 'process_low' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path training + + output: + path "wgs_shape_model.pkl", emit: model + path "train_metrics.json", emit: metrics + path "versions.yml", emit: versions + + script: + // Explicit python ${projectDir}/bin path: immune to PATH ordering and the exec bit, + // and to any stale copy the container may bake in. + """ + python ${projectDir}/bin/train_shape_model.py \\ + --training ${training} \\ + --learning-rate ${params.offtarget_train_learning_rate} \\ + --max-iter ${params.offtarget_train_max_iter} \\ + --max-depth ${params.offtarget_train_max_depth} \\ + --holdout-frac ${params.offtarget_train_holdout_frac} \\ + --seed ${params.offtarget_train_seed} \\ + --out wgs_shape_model.pkl \\ + --metrics train_metrics.json + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + "touch wgs_shape_model.pkl train_metrics.json versions.yml" +} diff --git a/modules/local/vep_to_tsv.nf b/modules/local/vep_to_tsv.nf index 83aeca5..03eeb30 100644 --- a/modules/local/vep_to_tsv.nf +++ b/modules/local/vep_to_tsv.nf @@ -9,7 +9,7 @@ process VEP_TO_TSV { val(type) output: - tuple val(meta), path("*.tsv"), emit: vep_tsv + tuple val(meta), path("*.tsv"), emit: tsv path "versions.yml", emit: versions script: @@ -22,7 +22,6 @@ process VEP_TO_TSV { def output = vcf.getName().replaceFirst('\\.vcf\\.gz\$', '.tsv') """ - export PATH=/usr/local/bin:\$PATH vep2table.py $args $vcf -o $output cat <<-END_VERSIONS > versions.yml diff --git a/modules/local/wgs_worklist.nf b/modules/local/wgs_worklist.nf new file mode 100644 index 0000000..76ed0d3 --- /dev/null +++ b/modules/local/wgs_worklist.nf @@ -0,0 +1,46 @@ +// WGS_WORKLIST — genome-wide, homology-free off-target discovery + shape ranking. +// Wraps bin/worklist_from_vcf.py: reads each DRAGEN somatic VCF + tumor CRAM listed in +// the cram map, applies the depth-augmented shape model, cross-checks the matched normal. +// Cohort-level (the script loops all samples in the map). CRAMs/VCFs are read by absolute +// path from bind-mounted storage (as elsewhere in this pipeline), so they are not staged. +process WGS_WORKLIST { + tag "cohort" + label 'process_medium' + container "ghcr.io/dhslab/docker-scge-offtarget:260710" + + input: + path cram_map + path model + val reference // absolute FASTA path on mounted storage + + output: + path "wgs_offtarget_worklist_genomewide.csv", emit: worklist + path "snapshots/*.png", optional: true, emit: snapshots + path "versions.yml", emit: versions + + script: + def homology = params.offtarget_homology_table ? "--homology-table '${params.offtarget_homology_table}'" : "" + def snaps = params.offtarget_snapshots ? "--snapshot-dir snapshots" : "" + def rescue = params.offtarget_rescue + ? "--rescue-min-ifrac ${params.offtarget_rescue_min_ifrac} --rescue-min-conc ${params.offtarget_rescue_min_conc} --rescue-min-span ${params.offtarget_rescue_min_span}" + : "--no-rescue" + """ + python ${projectDir}/bin/worklist_from_vcf.py \\ + --cram-list ${cram_map} \\ + --ref ${reference} \\ + --model ${model} \\ + --min-af ${params.offtarget_min_af} \\ + --min-span ${params.offtarget_min_span} \\ + --top ${params.offtarget_top} \\ + ${homology} ${snaps} ${rescue} \\ + --out wgs_offtarget_worklist_genomewide.csv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ + + stub: + "mkdir -p snapshots; touch wgs_offtarget_worklist_genomewide.csv versions.yml" +} diff --git a/nextflow.config b/nextflow.config index b93f2ed..32aa7bb 100644 --- a/nextflow.config +++ b/nextflow.config @@ -9,11 +9,13 @@ // Global default params, used in configs params { + + input = null outdir = null target_file = null - hotspot_bed = null + hotspot_bed = "${projectDir}/assets/accessory_files/hematopoietic_gene_hotspots.bed" transgene_name = "PLVM_CD19_CARv4_cd34" transgene_match_coordinates = "3130,5930" @@ -32,20 +34,178 @@ params { queue = "dspencer" user_group = "compute-dspencer" job_group_name = "/dspencer/adhoc" - slurm_partition = "general-cpu" + // Lab defaults for RIS Compute2, so a lab member needs no extra flags. Override + // per-run with --slurm_partition/--slurm_account (run_offtarget.sh also inherits + // them from the submitting job). Set either to "" to pass nothing and let the + // cluster's own default apply — that is the path for a non-RIS site. + // NB: was "general-cpu", which this group is NOT permitted to use. + slurm_partition = "condo-dspencer" + slurm_account = "compute2-dspencer" // References fasta = "/storage2/fs1/dspencer/Active/clinseq/projects/scge/data/refdata/singh/hg38_PLVM_CD19_CARv4_cd34.fa" cram_reference = "/storage2/fs1/dspencer/Active/clinseq/projects/scge/data/refdata/singh/hg38_PLVM_CD19_CARv4_cd34.fa" vepcache = "/storage2/fs1/dspencer/Active/spencerlab/refdata/hg38/VEP113_cache/" - nirvana_path = "/storage2/fs1/dspencer/Active/spencerlab/refdata/hg38/dragenfiles/nirvana_annotation_data_323" - nirvana_assembly = "GRCh38" + nirvana_path = null // "/storage2/fs1/dspencer/Active/spencerlab/refdata/hg38/dragenfiles/nirvana_annotation_data_323" + nirvana_assembly = null // "GRCh38" cytobands = "${projectDir}/assets/accessory_files/hg38.cytoBandIdeo.bed.gz" crispr_model = "${projectDir}/assets/models/site14_site5_combined_model.pkl" - + + // Unified CRISPR Off-Target Workflow (entry: -entry OFFTARGET) + offtarget_shape_model = "${projectDir}/assets/models/wgs_shape_model.pkl" // genome-wide/hotspot shape ranker + offtarget_homology_table = null // optional Cas-OFFinder table for min_mm/is_target ANNOTATION only + offtarget_min_af = 0.05 // DRAGEN tumor AF floor for candidate indels + offtarget_min_span = 8 // spanning-read coverage gate + offtarget_top = 60 // top-N to print / snapshot + offtarget_snapshots = false // render IGV-style pileup PNGs for LIKELY EDITs + offtarget_ecs_unevaluable_log = false // write per-read unevaluable-reads debug log (very large: ~0.1-1 TB/sample); off by default + offtarget_tagged_bam = false // emit a target-window BAM whose reads carry an XC tag with the per-read call, for IGV review; off by default + offtarget_ecs_edit_threshold = 0.0 // ECS indel_fraction strictly above this = an ECS edit (ecs_is_edit) + offtarget_germline_max_ctrl_if = 0.05 // matched-normal (WGS) indel frac above this = germline/artifact, not a somatic edit (label 0) + offtarget_hi_score = 0.60 // WGS shape score >= this = detected (recall curve) + offtarget_rescue = true // high-evidence rescue: call LIKELY EDIT on unambiguous somatic indel evidence even if the shape model under-scores it + offtarget_rescue_min_ifrac = 0.15 // rescue: minimum indel fraction in the edited sample + offtarget_rescue_min_conc = 0.5 // rescue: minimum positional concordance (clonality) + offtarget_rescue_min_span = 20 // rescue: minimum spanning reads + offtarget_target_recall = 0.80 // report VAF floor where binned recall first reaches this + offtarget_min_ecs_vaf = 0.005 // recall denominator: ECS VAF floor below which a call is assay noise, not an edit + offtarget_min_ecs_reads = 5 // recall denominator: ECS indel reads required to believe a site is a real edit + offtarget_metrics_betas = '2,5' // F-beta weights for the clinical metrics report (recall weighted beta^2 x) + offtarget_metrics_negatives = 'ecs_negative' // PR-AUC negatives: 'ecs_negative' (label==0 & ecs_is_edit==0) or 'all_label0' (also counts germline-demoted ECS edits) + offtarget_hotspot_pad = 25 // bp window to match a worklist candidate to a hotspot + offtarget_max_cut_dist = null // demote LIKELY EDIT calls whose observed indel sits further than this many bp from the predicted cut site (null = off, report only) + offtarget_wgs_tagged_bam = false // emit per-read XC-tagged BAMs for the WGS arm at called sites (IGV review); off by default + + // Automated review filter — turns the raw call table into the short list a human reviews. + // Six rules, first match wins. Measured on the 32-sample CAR-T WGS cohort at the current + // gate (reads>=2, VAF>=0.005) with the current config (no PoN, beta-binomial rule 4, the + // caller's own cut distance): 1,498 gated rows -> 96 queue, precision 0.889 against the + // curated review label. All 81 on-target edits are retained, as are all 70 ECS-confirmed + // edits including the 12 below 5% VAF. + review_filter = true // run REVIEW_FILTER after GET_INDELS + review_min_reads = 2 // gate: supporting indel reads (the manual-review entry criterion) + review_min_vaf = 0.005 // gate: indel fraction + // NOTE: rule 3 (review_min_distinct_len) cannot be satisfied by a site + // with fewer than 3 indel reads -- 2 reads carry at most 2 distinct + // lengths. Below reads>=3 this gate admits rows that rule 3 then drops + // by arithmetic rather than by evidence. See docs/THRESHOLD_CHANGE_IMPACT.md + review_max_control_vaf = 0.05 // rule 1: drop sites the matched unedited control also carries + review_max_cut_dist = 10 // rule 2: indel must be within this many bp of a PAM position + review_min_distinct_len = 3 // rule 3: distinct indel lengths required (do NOT use below the gate — it is depth-sensitive) + // Rule 4, statistical form. Replaces the PoN blacklist with a beta-binomial test: + // AQ = -10log10 P(X >= k | n, background), background from an empirical-Bayes Beta posterior + // over the control's own reads. Measured on the 32-sample CAR-T cohort, 'matched' equals the + // PoN exactly -- 91 rows, 64 confirmed, 9 human-rejected, precision 0.877 vs the PoN's + // 88/64/9/0.877 -- while needing NO cohort, only the sample's own unedited control. That is + // the whole point: a single-sample submission gets PoN-grade rule 4. + // off no statistical rule 4; falls back to cross-guide recurrence, which needs >=2 + // guides in ONE invocation and so cannot fire for a single-guide submission + // matched the sample's own control <- the default, and the reason the PoN is gone + // loo the other samples' controls (cohort recurrence as a rate) + // both pooled + review_noise_model = 'matched' + review_aq_min = 5 // AQ below this is called background. With the depth + // floor on, 3-8 all reproduce the PoN result exactly; + // 10 starts costing confirmed edits. + // A control with no alt reads at depth d shows the background is below ~1/d -- NOT that it is + // zero. Without this floor the posterior mean collapses to 3.5e-5 against a 170x control, + // ~100x beyond what 170 reads can support, and every call at a locus the control never + // sampled deeply looks significant. Harmless at the current VAF>=0.005 gate (only 2 gated rows + // sit below a 170x control's 0.59% resolution) and NOT harmless the moment that gate is + // lowered for a high-sensitivity run. Leave this on. + review_depth_floor = true + // Rule 4 can silently have no source at all: no PoN, no noise model, and one guide in the + // invocation means cross-guide recurrence cannot fire, and the unfiltered queue looks clean. + // true = exit non-zero in that state instead of warning. + review_strict_fallback = false + // Rule 5: repeat context. Comma-separated BEDs; a site inside one is dropped. Measured on + // the CAR-T cohort: RepeatMasker flags 100 of 177 artifacts and 0 of 61 real edits. + // Unlike the PoN this needs no controls, cohort or guide context, so it is the fallback + // that works on day one for a guide never run before. + review_repeat_beds = null + // Rule 6: DRAGEN systematic noise panel — an external PoN built from hundreds of donors, so + // unlike rule 4 it needs no controls of our own. Point this at the systematic_noise.snv.bed.gz + // in the dragenfiles refdata directory. + // + // Do NOT use a bare interval hit as the rule. Measured against the 1,498 gated rows of the + // 32-sample cohort, a plain overlap flags 33.1% of artifacts but also 1.2% of REAL on-target + // edits -- 27x enrichment, but it would delete true positives. The panel's own fields separate + // the two cases, so the rule additionally requires both: + // * the locus recurs in >= review_snv_noise_min_donors panel donors (drops n=1 coincidences) + // * the noise involves an insertion or deletion (a 'D' or 'I' allele code) -- an SNV-only + // locus says nothing about an indel call at the same coordinate + // Despite "snv" in the filename the panel carries 1,299,670 D and 892,925 I records. + // IKZF2 chr2:213,147,790 on-target, n_donors=1, alleles 'G' -> coincidence, kept + // B2M chr1:28,580,333 off-target, n_donors=17, alleles 'C,D' -> real warning, dropped + // COST: the file is ~1 GB and ships without a tabix index, so it is streamed. REVIEW_FILTER + // runs the script twice (queue + audit), so enabling this adds roughly 6 minutes to the run. + review_snv_noise = null // path to systematic_noise.snv.bed.gz (null = rule off) + review_snv_noise_min_donors = 3 // distinct panel donors required before a locus counts as noise + review_snapshots = true // render an IGV-style pileup per surviving review site + review_snapshot_window = 80 // bp either side of the site in each snapshot + + // Breakend review filter — the same idea applied to the BND calls rather than the indels. + // Runs off the same *.offtarget_analysis.tsv tables. On the 32-sample cohort: 2,404 BNDs -> + // 36 gated -> 25 queue (23 multi-cut deletions across 7 samples spanning 413 bp to 125 kb, + // 2 deletions at a cut site, 0 off-target junctions). + review_filter_bnd = true // run REVIEW_FILTER_BND after GET_INDELS + review_bnd_min_reads = 3 // gate: reads supporting the junction + review_bnd_max_cut_dist = 10 // junction must sit within this many bp of a PAM position + review_bnd_max_partners = 5 // promiscuity: a breakpoint bin joining >= this many distinct + // partners is a mapping hub, not biology. The real cut sites are + // exempt. NOTE this rule is currently non-binding -- fixing the BND + // off-by-one in find_edited_reads.py dropped the worst hub from 25 + // partners to 3. It is kept as insurance for future cohorts. + review_bnd_bin_size = 1000 // bp bin used to group breakpoints when counting partners + // WARNING: only the WGS v3.1.0 SV panel is safe here. Re-measured 2026-08-20 against the 25 + // real junctions of the 32-sample cohort, with the on-target exemption disabled: + // WGS_hg38_v3.1.0 flags 0/25 real at slop 0 and 50, 3/25 at 200 <- use this one + // IDPF_WGS_hg38_v3.0.0 flags 25/25 real at every slop <- erases the entire result + // WGS_FF_Heme_hg38_v3.1.0 flags 22/25 at slop 0, 25/25 at 50 and 200 <- same + // The cause is COVERAGE, not a profile mismatch: IDPF's intervals blanket 62.7% of hg38 and + // FF_Heme's 50.1%, so with two endpoints per junction they flag ~86% and ~75% of ANYTHING by + // chance -- and both flag on-target junctions MORE often than off-target ones (odds ratio 0.45 + // and 0.33, CIs excluding 1). WGS v3.1.0 covers 1.1%. See docs/PANEL_AS_FILTER.md. + // NB this is NOT params.sv_noisefile, which is IDPF by deliberate choice and goes to DRAGEN + // only (see the note there). Wiring IDPF into THIS parameter would delete the BND findings. + // If the BND queue collapses toward zero, the wrong BEDPE is wired here. + review_sv_noise = null // path to WGS_hg38_v3.1.0_systematic_noise.sv.bedpe.gz (null = off) + review_sv_noise_slop = 50 // bp tolerance when matching a junction to a panel record + + // Breakend review packet. One figure per JUNCTION, not per queue row -- the queue reports + // each event from both ends and at a few bp of jitter, so on the 32-sample cohort 25 rows + // collapse to 8 junctions. Each figure is a to-scale schematic of the excision over a 2x2 + // read grid (left/right breakpoint x edited/matched control), with reads whose SA tag lands + // at the partner locus drawn green. + review_bnd_snapshots = true // render a pileup figure per surviving junction + review_bnd_snapshot_window = 150 // bp either side of each breakpoint. Wider than the indel + // window (80) on purpose: the evidence is a stack of soft + // clips, and it needs flank to be legible as a stack. + review_bnd_max_junctions = 200 // safety cap; a runaway queue should not render thousands + + pon_min_vaf = 0.02 // AND this indel fraction. A read count alone is not depth-robust: + // 3 reads is ~5% VAF at WGS depth but ~0.15% at ECS depth, which + // would blacklist half an ECS panel as noise. + + // Auto-hotspot finder (entry: -entry HOTSPOTS) — gRNA -> predicted off-target sites + casoffinder_2bit = null // prebuilt .2bit for Cas-OFFinder; null = build from params.fasta with faToTwoBit + run_crisprme = false // also run CRISPRme (needs crisprme_index_dir); off = Cas-OFFinder only + crisprme_index_dir = "/storage2/fs1/dspencer/Active/clinseq/projects/scge/data/refdata/crisprme_hg38" // prebuilt CRISPRme index dir (Genome/, genome_library/NGG_2_Genome/, .txt) built offline by bin/build_crisprme_index.sh + offtarget_pam = 'NGG' // SpCas9 PAM used for off-target search + offtarget_mismatches = 3 // max mismatches to enumerate + offtarget_bulges = 1 // max DNA/RNA bulge size to enumerate + run_idt = false // include IDT off-target export (per-guide .xlsx) in the combine + + // Off-target model trainer (entry: -entry TRAIN) — offline retrain of the shape model + offtarget_train_learning_rate = 0.05 // HistGradientBoostingClassifier learning rate + offtarget_train_max_iter = 200 // boosting iterations + offtarget_train_max_depth = 3 // tree depth + offtarget_train_holdout_frac = 0.25 // stratified holdout for reported AUC/AP (0 = train on all) + offtarget_train_seed = 1 // RNG seed (reproducible) + // Dragen inputs intermediate_dir = "/staging/intermediate-results-dir" - refdir = "/storage2/fs1/dspencer/Active/spencerlab/refdata/hg38/dragen_hg38v4.3.6" + refdir = "/storage2/fs1/dspencer/Active/clinseq/projects/scge/data/refdata/singh_v4.3.6" dbsnp = "/storage2/fs1/dspencer/Active/spencerlab/refdata/hg38/dragenfiles/dbsnp.vcf.gz" adapter1 = "/storage2/fs1/dspencer/Active/spencerlab/refdata/hg38/dragenfiles/dragen_adapter1.fa" adapter2 = "/storage2/fs1/dspencer/Active/spencerlab/refdata/hg38/dragenfiles/dragen_adapter2.fa" @@ -116,6 +276,7 @@ def lsf_user_group = params.user_group ? "-G ${params.user_group}" : "" def lsf_group_name = params.job_group_name ? "-g ${params.job_group_name}" : "" def slurm_partition = params.slurm_partition ? "${params.slurm_partition}" : "" +def slurm_account = params.slurm_account ? "--account=${params.slurm_account}" : "" // Load base.config by default for all pipelines includeConfig 'conf/base.config' @@ -136,28 +297,27 @@ try { // } plugins { + // Both must stay pinned: an unpinned id resolves to whatever the running Nextflow + // prefers, which silently changes behaviour between machines. Use nf-validation + // everywhere -- mixing in a `plugin/nf-schema` import makes Nextflow pull a second, + // unpinned schema plugin at runtime (nf-schema is the eventual migration target, + // but it renames the validation* params, so that is a deliberate separate change). id 'nf-validation@1.1.3' // Validation of pipeline parameters and creation of an input channel from a sample sheet - id 'nf-amazon' + id 'nf-amazon@3.4.4' } profiles { stub { includeConfig 'conf/stub.config' } // local executor for testing + test { includeConfig 'conf/test.config' } // local executor for testing // RIS Compute1 ris { - executor.queueSize = 10 - executor.submitRateLimit = '1/1sec' + executor.queueSize = 50 + executor.submitRateLimit = '12/1min' process { - maxForks = 10 - executor = "lsf" - clusterOptions = { "-a 'docker(${task.container})' ${lsf_host} ${lsf_queue} ${lsf_user_group} ${lsf_group_name} -env \"LSF_DOCKER_VOLUMES='/storage1/fs1/dspencer/Active:/storage1/fs1/dspencer/Active /storage2/fs1/dspencer/Active:/storage2/fs1/dspencer/Active /scratch1/fs1/dspencer:/scratch1/fs1/dspencer $HOME:$HOME'\"" } - - withName: '.*RENDER_SCGE_REPORT' { - clusterOptions = { "-a 'docker(${task.container})' ${lsf_host} ${lsf_queue} ${lsf_user_group} ${lsf_group_name} -env \"LSF_DOCKER_ENTRYPOINT=/bin/bash, LSF_DOCKER_VOLUMES='/storage1/fs1/dspencer/Active:/storage1/fs1/dspencer/Active /storage2/fs1/dspencer/Active:/storage2/fs1/dspencer/Active /scratch1/fs1/dspencer:/scratch1/fs1/dspencer $HOME:$HOME'\"" } - memory = '64.GB' - time = '1.h' - } + executor = "lsf" + clusterOptions = { "-a 'docker(${task.container})' ${lsf_host} ${lsf_queue} ${lsf_user_group} ${lsf_group_name}" } } } @@ -165,13 +325,37 @@ profiles { ris2 { executor.queueSize = 100 executor.submitRateLimit = '12/1min' + // Ride out SLURM controller blips instead of dying on them. A 32-sample run makes + // hundreds of sbatch calls over many hours, so a controller restart mid-run is a + // question of when, not if -- and a failed *submission* kills the whole run, not just + // one task. This is not hypothetical: the 2026-08-11 cohort run lost 160 pending tasks + // to a single `sbatch: error: Batch job submission failed: Connection reset by peer` + // after 104 tasks had already succeeded. + // The default retry.reason matches ONLY 'Socket timed out on send/recv operation', + // which is why that error was fatal rather than retried. Widen it to the connection + // failures the RIS controller actually emits. + executor.retry.maxAttempt = 5 + executor.retry.delay = '30s' + executor.retry.maxDelay = '10m' + executor.retry.reason = '(?i).*(Socket timed out on send/recv operation|Connection reset by peer|Unable to contact slurm controller|Connection refused|Connection timed out).*' process { executor = "slurm" - queue = "${slurm_partition}" + // null (not "") when unset, so nextflow omits -p / -A entirely and the + // site default applies instead of an empty flag being submitted. + queue = slurm_partition ?: null + clusterOptions = slurm_account ?: null } + // Container engine is added separately, e.g. -profile ris2,apptainer (preferred) + // or -profile ris2,singularity. These blocks only take effect once that engine + // is enabled; they cache the image and bind the shared filesystems the jobs read. singularity { cacheDir = '/scratch2/fs1/dspencer/singularity_cache' } + apptainer { + cacheDir = '/scratch2/fs1/dspencer/apptainer_cache' + autoMounts = true + runOptions = '--bind /storage2 --bind /scratch2' // Compute2 has /scratch2, not /scratch1 + } } dragen4 { @@ -190,7 +374,7 @@ profiles { dragenaws { bucketDir = "s3://dhslab-dragen-data" - params.refdir = "/storage2/fs1/dspencer/Active/spencerlab/refdata/hg38/dragen_hg38_cg_v4.4.6" + params.refdir = "/storage2/fs1/dspencer/Active/clinseq/projects/scge/data/refdata/singh_v4.4.6" process { withName: 'DRAGEN_SCGE' { ext.dragen_container = "${params.aws_dragen_container}" diff --git a/nextflow_schema.json b/nextflow_schema.json index 38679eb..62527dc 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-07/schema", + "$schema": "https://json-schema.org/draft-07/schema", "$id": "https://raw.githubusercontent.com/nf-core/scge/master/nextflow_schema.json", "title": "nf-core/scge pipeline parameters", "description": "Nextflow implementation of scge workflow", @@ -12,71 +12,390 @@ "properties": { "transgene_name": { "type": "string", - "description": "Name of the transgene contig" + "default": "PLVM_CD19_CARv4_cd34", + "description": "Name of the transgene contig in the reference FASTA" }, - "editing_targets": { + "transgene_match_coordinates": { "type": "string", - "description": "Editing targets file" + "default": "3130,5930", + "description": "Comma-separated start,end coordinates of the transgene match region" + }, + "target_file": { + "type": "string", + "format": "file-path", + "description": "Nominated editing-target VCF used for on/off-target indel calling" }, "off_target_threshold": { "type": "number", - "description": "Off-target threshold" + "default": 1.0, + "description": "ML score threshold for calling an off-target edit" + }, + "hotspot_window_size": { + "type": "integer", + "default": 200, + "description": "Window (bp) around a hotspot used when building the hotspot VCF" }, - "window": { + "max_filter_sv_length": { "type": "integer", - "description": "Window size" + "default": 150000000, + "description": "Structural variants longer than this are filtered out" + }, + "sv_annotation_distance": { + "type": "integer", + "default": 20000, + "description": "Distance (bp) within which to annotate genes against an SV breakend" + }, + "run_alignment": { + "type": "boolean", + "default": true, + "description": "Run the DRAGEN alignment/calling half of the pipeline", + "help_text": "Set to false to run analysis only from existing DRAGEN output directories. This is the low-barrier path: no DRAGEN licence or FPGA hardware required." + }, + "run_analysis": { + "type": "boolean", + "default": true, + "description": "Run the annotation/report half of the pipeline" + }, + "transgene_analysis": { + "type": "boolean", + "default": true, + "description": "Run transgene integration-junction analysis" + }, + "hotspot_bed": { + "type": "string", + "format": "file-path", + "description": "Hotspot BED file used for hotspot annotation" + }, + "alignment_file_format": { + "type": "string", + "default": "CRAM", + "enum": [ + "CRAM", + "BAM" + ], + "description": "Alignment file format emitted by DRAGEN" }, "user_group": { "type": "string", - "description": "User group for cluster submission" + "default": "compute-dspencer", + "description": "LSF user group for cluster submission (RIS Compute1)", + "hidden": true }, "queue": { "type": "string", - "description": "Queue for cluster submission" + "default": "dspencer", + "description": "LSF queue for cluster submission (RIS Compute1)", + "hidden": true }, "job_group_name": { "type": "string", - "description": "Job group name for cluster submission" + "default": "/dspencer/adhoc", + "description": "LSF job group name for cluster submission (RIS Compute1)", + "hidden": true + }, + "host": { + "type": "string", + "description": "Restrict LSF submission to a specific host (RIS Compute1)", + "hidden": true }, - "run_dragen": { + "slurm_partition": { + "type": "string", + "default": "general-cpu", + "description": "SLURM partition for cluster submission (RIS Compute2)", + "hidden": true + }, + "slurm_account": { + "type": "string", + "default": "compute2-dspencer", + "description": "SLURM account for cluster submission (RIS Compute2)", + "hidden": true + }, + "scge_report_qmd": { + "type": "string", + "format": "file-path", + "description": "Quarto document used to render the per-sample HTML report" + }, + "crispr_model": { + "type": "string", + "format": "file-path", + "description": "CRISPR_ML edit-classification model consumed by GET_INDELS" + } + } + }, + "offtarget_options": { + "title": "Off-target workflow options", + "type": "object", + "fa_icon": "fas fa-crosshairs", + "description": "Unified CRISPR Off-Target Workflow (-entry OFFTARGET).", + "help_text": "These options only take effect under `-entry OFFTARGET`. See docs/OFFTARGET.md for the full description of the two arms (ECS truth and WGS discovery) and the validated VAF floor.", + "properties": { + "offtarget_shape_model": { + "type": "string", + "format": "file-path", + "description": "Pileup shape-ranker model applied to WGS candidates", + "help_text": "A fixed asset by design. Retrain with `-entry TRAIN` and deploy the result by pointing this parameter at the new .pkl." + }, + "offtarget_homology_table": { + "type": "string", + "format": "file-path", + "description": "Optional Cas-OFFinder table used for min_mm/is_target annotation only" + }, + "offtarget_min_af": { + "type": "number", + "default": 0.05, + "description": "DRAGEN tumour allele-fraction floor for candidate indels" + }, + "offtarget_min_span": { + "type": "integer", + "default": 8, + "description": "Minimum spanning-read coverage for a locus to be evaluated" + }, + "offtarget_top": { + "type": "integer", + "default": 60, + "description": "Number of top-ranked candidates to print and snapshot" + }, + "offtarget_snapshots": { "type": "boolean", - "description": "Whether to run DRAGEN" + "description": "Render IGV-style edited-vs-normal pileup PNGs for every LIKELY EDIT", + "help_text": "Off by default because it writes one image per hit." }, - "run_analysis": { + "offtarget_ecs_unevaluable_log": { "type": "boolean", - "description": "Whether to run analysis" + "description": "Write the per-read unevaluable-reads debug log from ECS_INDELS", + "help_text": "Off by default. This log reaches roughly 0.1-1 TB per sample and was the sole cause of work-directory ENOSPC failures; enable only when debugging read evaluation.", + "hidden": true }, - "transgene_analysis": { + "offtarget_tagged_bam": { + "type": "boolean", + "description": "Emit a per-read tagged BAM from the ECS caller for review in IGV", + "help_text": "Off by default. Writes .tagged.bam(.bai) in which every read carries an XC string tag naming how the caller classified it (Edited_Deletion_5bp, Unedited_WT, Skipped_LowMapQ, ...), so a reviewer can load it in IGV and use Color alignments by -> tag -> XC. Output is restricted to the target windows (target +/- 150 bp), not the whole genome, but it still scales with target count and depth: one AAVS1 site14 ECS sample (1149 targets, ~11000x) produced a 800 MB BAM of 21.8 M reads and pushed ECS_INDELS from 1.4 GB to 6.3 GB peak RSS, so the process is given 24 GB instead of 8 GB while this is set. Check the size on one sample before enabling it across a cohort. See docs/OFFTARGET.md." + }, + "offtarget_ecs_edit_threshold": { + "type": "number", + "default": 0.0, + "description": "ECS indel_fraction strictly above this counts as an ECS edit" + }, + "offtarget_germline_max_ctrl_if": { + "type": "number", + "default": 0.05, + "description": "Matched-normal indel fraction above this marks a site germline, not a somatic edit", + "help_text": "Sites exceeding this are demoted to label 0 in training.tsv even when ECS shows an indel." + }, + "offtarget_hi_score": { + "type": "number", + "default": 0.6, + "description": "Shape score at or above which a locus counts as detected in the recall curve" + }, + "offtarget_target_recall": { + "type": "number", + "default": 0.8, + "description": "Recall level whose VAF floor is reported by the recall curve" + }, + "offtarget_hotspot_pad": { + "type": "integer", + "default": 25, + "description": "Window (bp) for matching a worklist candidate to a predicted hotspot" + }, + "offtarget_rescue": { "type": "boolean", - "description": "Whether to run transgene analysis" + "default": true, + "description": "Call LIKELY EDIT on unambiguous somatic indel evidence even when the shape model under-scores it", + "help_text": "The shape model is a ranker, not a detector, and demotes some clear edits. The rescue runs AFTER the low-MAPQ and matched-normal vetoes, so it can only override the model score, never the evidence. Set false to call on the model score alone. See docs/OFFTARGET.md." + }, + "offtarget_rescue_min_ifrac": { + "type": "number", + "default": 0.15, + "description": "Rescue: minimum indel fraction in the edited sample" + }, + "offtarget_rescue_min_conc": { + "type": "number", + "default": 0.5, + "description": "Rescue: minimum positional concordance (clonality) of the indel reads" + }, + "offtarget_rescue_min_span": { + "type": "integer", + "default": 20, + "description": "Rescue: minimum spanning reads required before the evidence counts" + }, + "offtarget_min_ecs_vaf": { + "type": "number", + "default": 0.005, + "description": "Recall denominator: ECS VAF floor below which a call is assay noise rather than a real edit", + "help_text": "The raw ECS label counts any nonzero indel fraction as an edit, which at ECS depth is overwhelmingly noise and makes the recall curve meaningless. Set 0 to keep every ECS call." + }, + "offtarget_min_ecs_reads": { + "type": "integer", + "default": 5, + "description": "Recall denominator: ECS indel reads required to believe a site is a real edit", + "help_text": "VAF alone cannot separate a genuine low-VAF edit at high depth from a few stray reads; read support can. Set 0 to disable." }, - "targetfile": { + "offtarget_metrics_betas": { "type": "string", - "description": "Target file" + "default": "2,5", + "description": "Comma-separated F-beta weights for the clinical metrics report", + "help_text": "F_beta weights recall beta^2 times more than precision (beta=2 -> 4x, beta=5 -> 25x). F_beta is monotone in beta, so F1 is always an endpoint of the reported set, never the middle value." }, - "hotspot_bed": { + "offtarget_metrics_negatives": { "type": "string", - "description": "Hotspot BED file" + "default": "ecs_negative", + "enum": [ + "ecs_negative", + "all_label0" + ], + "description": "Negative set for PR-AUC: ECS-negative hotspots only, or all label==0 rows", + "help_text": "label==0 is two populations: genuine ECS-negatives (ecs_is_edit==0) and ECS edits demoted because the indel is in the matched normal. The germline-demoted rows carry a real indel, so the shape ranker correctly scores them high and germline rejection is a separate downstream gate; including them charges the ranker with a job it does not do. Either way the alternative is reported as a labelled sensitivity block." }, - "hotspot_csv": { + "offtarget_max_cut_dist": { + "type": "number", + "description": "Demote LIKELY EDIT calls whose indel sits further than this many bp from the predicted cut site", + "help_text": "Off by default (report only): cut_dist is always emitted as a column, but nothing is demoted unless this is set. Cas9 cuts ~3 bp from the PAM, so a genuine edit sits within a few bp of the predicted site. Measured on the AAVS1 cohort: the two curated on-target edits are 2 bp and 4 bp away, while sites called LIKELY EDIT that curation marked negative run to a median of 24 bp (max 94). Setting 10 dropped 23 of 28 false positives without losing either edit. Demotion, not deletion - the row and its score stay in the table." + }, + "offtarget_wgs_tagged_bam": { + "type": "boolean", + "description": "Emit per-read XC-tagged BAMs for the WGS arm at called sites, for IGV review", + "help_text": "Off by default. The WGS analogue of --offtarget_tagged_bam, using the same XC tag names so one IGV colour scheme (Color alignments by -> tag -> XC) serves both arms. Windows cover only the LIKELY EDIT sites, so unlike the ECS tagged BAMs these stay small. Reads excluded by the caller's own filters are written and labelled Skipped_Duplicate / Skipped_LowMapQ / Skipped_Mismatches / Skipped_NoSpan, so a reviewer can audit the denominator rather than trust it." + } + } + }, + "hotspot_finder_options": { + "title": "Auto-hotspot finder options", + "type": "object", + "fa_icon": "fas fa-crosshairs", + "description": "gRNA -> predicted off-target sites (-entry HOTSPOTS).", + "properties": { + "offtarget_pam": { "type": "string", - "description": "Hotspot CSV file" + "default": "NGG", + "description": "SpCas9 PAM used for off-target search" }, - "alignment_file_format": { + "offtarget_mismatches": { + "type": "integer", + "default": 3, + "description": "Max mismatches to enumerate" + }, + "offtarget_bulges": { + "type": "integer", + "default": 1, + "description": "Max DNA/RNA bulge size to enumerate" + }, + "casoffinder_2bit": { + "type": "string", + "format": "file-path", + "description": "Prebuilt .2bit for Cas-OFFinder; null builds it from --fasta with faToTwoBit" + }, + "run_crisprme": { + "type": "boolean", + "description": "Also run CRISPRme (needs --crisprme_index_dir); default is Cas-OFFinder only" + }, + "run_idt": { + "type": "boolean", + "description": "Include a per-guide IDT off-target export (.xlsx via the samplesheet 'idt' column) in the combine" + }, + "crisprme_index_dir": { + "type": "string", + "format": "directory-path", + "description": "Prebuilt CRISPRme index directory (built offline by bin/build_crisprme_index.sh)" + } + } + }, + "offtarget_train_options": { + "title": "Off-target model trainer options", + "type": "object", + "fa_icon": "fas fa-brain", + "description": "Offline shape-model trainer (-entry TRAIN).", + "help_text": "These options only take effect under `-entry TRAIN`, which fits a new wgs_shape_model.pkl from a training.tsv produced by `-entry OFFTARGET`. Training is deliberately kept out of the OFFTARGET DAG.", + "properties": { + "offtarget_train_learning_rate": { + "type": "number", + "default": 0.05, + "description": "HistGradientBoostingClassifier learning rate" + }, + "offtarget_train_max_iter": { + "type": "integer", + "default": 200, + "description": "Number of boosting iterations" + }, + "offtarget_train_max_depth": { + "type": "integer", + "default": 3, + "description": "Maximum tree depth" + }, + "offtarget_train_holdout_frac": { + "type": "number", + "default": 0.25, + "description": "Stratified holdout fraction used for the reported AUC/AP (0 trains on all rows)" + }, + "offtarget_train_seed": { + "type": "integer", + "default": 1, + "description": "Random seed, for reproducible fits" + } + } + }, + "dragen_options": { + "title": "DRAGEN options", + "type": "object", + "fa_icon": "fas fa-microchip", + "description": "Inputs and containers for the DRAGEN alignment/calling half.", + "help_text": "Only used when `--run_alignment true` together with the `dragen4` or `dragenaws` profile.", + "properties": { + "intermediate_dir": { + "type": "string", + "default": "/staging/intermediate-results-dir", + "description": "DRAGEN intermediate results directory", + "hidden": true + }, + "refdir": { + "type": "string", + "format": "directory-path", + "description": "DRAGEN reference hash table directory" + }, + "dbsnp": { + "type": "string", + "format": "file-path", + "description": "dbSNP VCF passed to DRAGEN" + }, + "adapter1": { + "type": "string", + "format": "file-path", + "description": "Read 1 adapter FASTA", + "hidden": true + }, + "adapter2": { + "type": "string", + "format": "file-path", + "description": "Read 2 adapter FASTA", + "hidden": true + }, + "snv_noisefile": { + "type": "string", + "format": "file-path", + "description": "Systematic-noise BED for SNV calling", + "hidden": true + }, + "sv_noisefile": { "type": "string", - "description": "Alignment file format" + "format": "file-path", + "description": "Systematic-noise BEDPE for SV calling", + "hidden": true }, "mark_duplicates": { "type": "boolean", - "description": "Whether to mark duplicates" + "default": true, + "description": "Mark duplicate reads during DRAGEN alignment" }, - "scge_report_qmd": { + "aws_dragen_container": { "type": "string", - "description": "Path to SCGE report QMD file" + "default": "job-definition://dragen_v4-4-6", + "description": "AWS Batch job definition used by the dragenaws profile", + "hidden": true }, - "crispr_model": { + "local_dragen_container": { "type": "string", - "description": "Path to CRISPR model file" + "default": "apldx/oracle8-dragen-4.3.6", + "description": "Container image used by the local dragen4 profile", + "hidden": true } } }, @@ -94,10 +413,9 @@ "type": "string", "format": "file-path", "exists": true, - "mimetype": "text/csv", - "pattern": "^\\S+\\.csv$", - "description": "Path to comma-separated file containing information about the samples in the experiment.", - "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re/scge/usage#samplesheet-input).", + "pattern": "^\\S+\\.(csv|tsv|xlsx)$", + "description": "Path to the samplesheet describing the samples in the experiment.", + "help_text": "Accepts .csv, .tsv or .xlsx. The expected columns depend on the entry point: the default SCGE workflow takes a mastersheet (`id,uid,sample_type,fastq_list,hotspot_file`, or `id,dragen_path,target_file` when running with `--run_alignment false`); `-entry OFFTARGET` takes `sample,datatype,guide,edited_cram,control_cram,target_file,vcf` (template at assets/offtarget_samplesheet_template.csv); `-entry TRAIN` takes a training.tsv emitted by BUILD_TRAINING_TABLE.", "fa_icon": "fas fa-file-csv" }, "outdir": { @@ -124,7 +442,58 @@ "title": "Reference genome options", "type": "object", "fa_icon": "fas fa-dna", - "description": "Reference genome related files and options required for the workflow." + "description": "Reference genome related files and options required for the workflow.", + "properties": { + "fasta": { + "type": "string", + "format": "file-path", + "mimetype": "text/plain", + "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", + "description": "Reference genome FASTA, including the CAR/transgene contig", + "fa_icon": "far fa-file-code" + }, + "cram_reference": { + "type": "string", + "format": "file-path", + "description": "Reference FASTA used to decode input CRAMs", + "help_text": "Normally the same file as --fasta. Set it separately only when existing CRAMs were written against a different reference." + }, + "vepcache": { + "type": "string", + "format": "directory-path", + "description": "VEP annotation cache directory" + }, + "nirvana_path": { + "type": "string", + "format": "directory-path", + "description": "Optional Nirvana annotation data directory", + "hidden": true + }, + "nirvana_assembly": { + "type": "string", + "description": "Genome assembly name passed to Nirvana, e.g. GRCh38", + "hidden": true + }, + "cytobands": { + "type": "string", + "format": "file-path", + "description": "Cytoband BED used for the Circos and CNA/BAF plots", + "hidden": true + }, + "genome": { + "type": "string", + "description": "iGenomes reference key", + "help_text": "This pipeline normally uses an explicit --fasta rather than iGenomes; leave unset unless you know you need it.", + "fa_icon": "fas fa-book", + "hidden": true + }, + "igenomes_ignore": { + "type": "boolean", + "description": "Do not load the iGenomes reference config", + "fa_icon": "fas fa-ban", + "hidden": true + } + } }, "institutional_config_options": { "title": "Institutional config options", @@ -292,6 +661,12 @@ "fa_icon": "fas fa-image", "hidden": true }, + "ch_multiqc_logo": { + "type": "string", + "description": "Internal placeholder for the resolved MultiQC logo. Not intended to be set by users.", + "fa_icon": "fas fa-image", + "hidden": true + }, "multiqc_methods_description": { "type": "string", "description": "Custom MultiQC yaml file containing HTML including a methods description.", @@ -326,6 +701,184 @@ "help_text": "Allows string values that are parseable as numbers or booleans. For further information see [JSONSchema docs](https://github.com/everit-org/json-schema#lenient-mode)." } } + }, + "review_filter_options": { + "title": "Automated review filter options", + "type": "object", + "description": "Turn the raw off-target call table into the short list a human reviews.", + "help_text": "Six rules, first match wins, applied to sites clearing the review gate: the matched control must be clean, the indel must sit near a PAM position, it must show several distinct indel lengths, the site must not already be known bad, it must not lie in a repeat, and it must not sit on a recurrent indel-noise locus in the external DRAGEN panel. On the 32-sample CAR-T WGS cohort this takes 1,498 gated rows to an 88-site queue (87 with rule 6 enabled) while retaining all 81 on-target edits. A companion process, REVIEW_FILTER_BND, applies the same idea to breakends.", + "properties": { + "review_filter": { + "type": "boolean", + "default": true, + "description": "Run REVIEW_FILTER after GET_INDELS." + }, + "review_min_reads": { + "type": "integer", + "default": 2, + "minimum": 1, + "description": "Gate: supporting indel reads required to enter the review queue." + }, + "review_min_vaf": { + "type": "number", + "default": 0.005, + "minimum": 0, + "maximum": 1, + "description": "Gate: indel fraction required to enter the review queue." + }, + "review_max_control_vaf": { + "type": "number", + "default": 0.05, + "minimum": 0, + "maximum": 1, + "description": "Rule 1: drop sites whose matched unedited control carries indels at or above this fraction." + }, + "review_max_cut_dist": { + "type": "integer", + "default": 10, + "minimum": 0, + "description": "Rule 2: the indel must lie within this many bp of a PAM position." + }, + "review_min_distinct_len": { + "type": "integer", + "default": 3, + "minimum": 1, + "description": "Rule 3: distinct indel lengths required. Depth-sensitive - do not apply below the gate.", + "help_text": "Resampling real edits to 3 supporting reads leaves only ~49% passing this rule, so it silently reimposes a read-count floor if used at low VAF." + }, + "pon_min_vaf": { + "type": "number", + "default": 0.02, + "minimum": 0, + "maximum": 1, + "description": "PoN: indel fraction required as well as the read count.", + "help_text": "A read count alone is not depth-robust: 3 reads is ~5% VAF at WGS depth but ~0.15% at ECS depth, which would blacklist over half an ECS panel as noise." + }, + "review_repeat_beds": { + "type": "string", + "default": null, + "description": "Comma-separated repeat-annotation BEDs; off-target sites inside one are dropped (rule 5).", + "help_text": "Measured on the CAR-T cohort: RepeatMasker flags 100 of 177 artifacts and 0 of 61 real edits. Needs no controls, cohort or guide context, so it is the only rule that works on day one for a guide never run before." + }, + "review_snv_noise": { + "type": "string", + "format": "file-path", + "default": null, + "description": "Rule 6: DRAGEN systematic-noise BED (systematic_noise.snv.bed.gz). Unset disables the rule.", + "help_text": "An external panel of normals built from hundreds of donors, so unlike rule 4 it needs no controls of our own. A bare interval hit is not usable as the rule: it flags 33.1% of artifacts but also 1.2% of real on-target edits. The rule therefore also requires the locus to recur in several panel donors and to involve an insertion or deletion. Despite the filename the panel carries 1,299,670 D and 892,925 I records. The file is ~1 GB and unindexed, and REVIEW_FILTER runs the script twice, so enabling this adds roughly 6 minutes." + }, + "review_snv_noise_min_donors": { + "type": "integer", + "default": 3, + "minimum": 1, + "description": "Rule 6: distinct panel donors required before a locus counts as systematic noise." + }, + "review_snapshots": { + "type": "boolean", + "default": true, + "description": "Render an IGV-style pileup image for each surviving review site.", + "help_text": "Each figure pairs the edited sample over its matched unedited control at the same locus, which is what lets a reviewer settle most calls without opening IGV." + }, + "review_snapshot_window": { + "type": "integer", + "default": 80, + "minimum": 10, + "description": "bp either side of the site to show in each snapshot." + }, + "review_filter_bnd": { + "type": "boolean", + "default": true, + "description": "Run REVIEW_FILTER_BND, the breakend counterpart of the review filter.", + "help_text": "Reads the same *.offtarget_analysis.tsv tables and triages BND calls. On the 32-sample cohort: 2,404 breakends to 36 gated to a 25-site queue." + }, + "review_bnd_min_reads": { + "type": "integer", + "default": 3, + "minimum": 1, + "description": "Breakend gate: reads supporting the junction." + }, + "review_bnd_max_cut_dist": { + "type": "integer", + "default": 10, + "minimum": 0, + "description": "Breakend rule: the junction must lie within this many bp of a PAM position." + }, + "review_bnd_max_partners": { + "type": "integer", + "default": 5, + "minimum": 2, + "description": "Breakend rule: drop bins joining this many or more distinct partners as mapping hubs.", + "help_text": "The real cut sites are exempt. Currently non-binding: fixing the BND off-by-one in find_edited_reads.py dropped the worst hub from 25 partners to 3. Kept as insurance for future cohorts." + }, + "review_bnd_bin_size": { + "type": "integer", + "default": 1000, + "minimum": 1, + "description": "bp bin used to group breakpoints when counting partners." + }, + "review_sv_noise": { + "type": "string", + "format": "file-path", + "default": null, + "description": "Breakend rule: DRAGEN systematic-noise BEDPE. Use ONLY the WGS v3.1.0 panel.", + "help_text": "Measured against the 25 real junctions of the 32-sample cohort: WGS_hg38_v3.1.0 flags 0 of 25 real junctions and 11 of 11 artifacts. IDPF_WGS_hg38_v3.0.0 flags 25 of 25 real, and WGS_FF_Heme_hg38_v3.1.0 flags 24 of 25 - either would erase the entire result. If the breakend queue collapses toward zero, the wrong BEDPE is wired here." + }, + "review_sv_noise_slop": { + "type": "integer", + "default": 50, + "minimum": 0, + "description": "bp tolerance when matching a junction to an SV noise panel record." + }, + "review_bnd_snapshots": { + "type": "boolean", + "default": true, + "description": "Render a pileup figure for each junction in the breakend review queue.", + "help_text": "One figure per JUNCTION, not per queue row: the queue reports each event from both ends and at a few bp of jitter, so on the 32-sample CAR-T cohort 25 rows collapse to 8 junctions. Each figure pairs a to-scale schematic of the excision with a 2x2 read grid (left/right breakpoint x edited/matched control); reads whose SA tag lands at the partner locus are drawn green." + }, + "review_bnd_snapshot_window": { + "type": "integer", + "default": 150, + "minimum": 10, + "description": "bp either side of each breakpoint to show in a breakend figure.", + "help_text": "Wider than review_snapshot_window on purpose: breakend evidence is a stack of soft clips terminating on one base, which needs flank to read as a stack." + }, + "review_bnd_max_junctions": { + "type": "integer", + "default": 200, + "minimum": 1, + "description": "Safety cap on the number of breakend figures rendered." + }, + "review_noise_model": { + "type": "string", + "default": "matched", + "enum": [ + "off", + "matched", + "loo", + "both" + ], + "description": "Rule 4: beta-binomial test against a control-derived background, replacing the boolean panel of normals.", + "help_text": "'matched' uses only the sample's own unedited control and needs no cohort, yet matches the PoN's measured performance on the 32-sample CAR-T cohort (64/64 confirmed retained, 9 human-rejected, precision 0.877). 'loo' uses the other samples' controls, 'both' pools them. Default 'off' keeps the PoN so existing runs are unchanged." + }, + "review_aq_min": { + "type": "number", + "default": 5, + "description": "AQ below which a site is called background under review_noise_model.", + "help_text": "AQ = -10log10 P(X >= k | n, background). With review_depth_floor on, 3-8 all reproduce the panel-of-normals result exactly; 10 begins costing confirmed edits." + }, + "review_depth_floor": { + "type": "boolean", + "default": true, + "description": "Floor the posterior background at 1/control_depth so the model cannot claim more resolution than the control has.", + "help_text": "A control with zero alt reads at depth d shows background is below ~1/d, not that it is zero. Without the floor the posterior collapses to 3.5e-5 against a 170x control. Harmless at the current VAF>=0.005 gate, unsafe if that gate is lowered." + }, + "review_strict_fallback": { + "type": "boolean", + "default": false, + "description": "Fail instead of warning when rule 4 has no usable source.", + "help_text": "With no PoN, no noise model and a single guide in one invocation, cross-guide recurrence cannot fire and the unfiltered queue looks deceptively clean." + } + } } }, "allOf": [ @@ -338,6 +891,18 @@ { "$ref": "#/definitions/scge_options" }, + { + "$ref": "#/definitions/offtarget_options" + }, + { + "$ref": "#/definitions/hotspot_finder_options" + }, + { + "$ref": "#/definitions/offtarget_train_options" + }, + { + "$ref": "#/definitions/dragen_options" + }, { "$ref": "#/definitions/institutional_config_options" }, @@ -346,6 +911,9 @@ }, { "$ref": "#/definitions/generic_options" + }, + { + "$ref": "#/definitions/review_filter_options" } ] -} \ No newline at end of file +} diff --git a/nf-test.config b/nf-test.config new file mode 100644 index 0000000..3d0a132 --- /dev/null +++ b/nf-test.config @@ -0,0 +1,38 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + nf-test — REAL execution tests for the off-target CRISPR edit finder +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Why this exists, and how it differs from everything else in run_offtarget_tests.sh: + + pytest (tests/*.py) — runs bin/*.py directly. Proves the SCIENCE is right. + nextflow -stub-run — only `touch`es outputs. Proves the DAG WIRES UP. + nf-test (this) — runs the real process bodies in the real container. + Proves the two halves are actually connected. + + That middle gap is not hypothetical: `-stub-run` never executes a single line of + bin/*.py, so a module can pass a flag the script does not accept and stay green + through every stub test in the repo. That exact class of bug (an arity mismatch) + once survived CI and died three hours into a cluster run. + + Run: nf-test test # everything + nf-test test --tag metrics # one feature +*/ + +config { + testsDir "." + workDir ".nf-test" + configFile "tests/nextflow.config" + + // load the pipeline's own params so tests see production defaults, not nf-test's + profile "stub" + + // Discovery scope. Without this, a bare `nf-test test` finds 98 tests instead of 5: + // - modules/nf-core/** and subworkflows/nf-core/** ship template tests (FASTQC, + // MULTIQC, UTILS_*) that need the nf-core test-datasets this pipeline does not + // vendor. They have never been run here and 42 of them fail on missing fixtures. + // That is a separate piece of work; it must not drown out the off-target signal. + // - .claude/ holds agent worktrees, i.e. whole second checkouts of this repo, so + // every test in the tree would otherwise be discovered two or three times over. + ignore 'modules/nf-core/**', 'subworkflows/nf-core/**', '.claude/**' +} diff --git a/run_offtarget.sh b/run_offtarget.sh new file mode 100755 index 0000000..0d6b3b2 --- /dev/null +++ b/run_offtarget.sh @@ -0,0 +1,169 @@ +#!/bin/bash +#SBATCH --job-name=offtarget +# Lab defaults (RIS Compute2) so `sbatch run_offtarget.sh ...` needs no extra flags. +# An #SBATCH line cannot read a variable, so these are literal — override them the +# normal SLURM way, which takes precedence: `sbatch --partition=X --account=Y ...` +# (or export SBATCH_PARTITION / SBATCH_ACCOUNT). +#SBATCH --partition=condo-dspencer +#SBATCH --account=compute2-dspencer +#SBATCH --cpus-per-task=2 +#SBATCH --mem=10G +#SBATCH --time=48:00:00 +#SBATCH --output=offtarget.%j.log +#SBATCH --error=offtarget.%j.err +# --------------------------------------------------------------------------- +# Unified CRISPR Off-Target Workflow (-entry OFFTARGET), SLURM + a container +# engine. ONE wrapper for every cohort: pass the samplesheet and an output dir; +# everything else has a sane default and can be overridden. +# +# sbatch run_offtarget.sh --input --outdir [options] +# +# Defaults are the lab's working RIS Compute2 setup, so lab members need no flags: +# sbatch run_offtarget.sh --input s.csv --outdir out +# Nothing is locked to that cluster, though — every site setting resolves as: +# command-line flag > environment variable > inherited from SLURM > lab default +# and passing an EMPTY value ("") means "pass nothing, use the cluster's own default". +# On a non-RIS cluster you will typically want --partition/--account/--profile +# (see the last example). +# +# Options (all optional except --input): +# --input FILE samplesheet (required) +# --outdir DIR results dir (default: ./results_offtarget) +# --partition NAME SLURM partition for the PIPELINE'S OWN jobs [$OFFTARGET_PARTITION] +# --account NAME SLURM account for those jobs [$OFFTARGET_ACCOUNT] +# --profile NAME nextflow profile(s) (default: ris2,apptainer) [$OFFTARGET_PROFILE] +# --work-dir DIR nextflow work dir (default: /work) [$OFFTARGET_WORKDIR] +# --cache DIR container image cache [$OFFTARGET_CACHE] +# --bind PATHS comma-separated container bind paths [$OFFTARGET_BIND] +# --modules LIST modules to `module load` ("" = none) [$OFFTARGET_MODULES] +# --snapshots render IGV-style tumor|normal pileup PNGs for LIKELY EDITs +# --no-resume start fresh instead of -resume +# -- everything after is passed straight through to `nextflow run` +# +# PARTITION — read this once, it is the usual stumbling block. There are TWO +# levels of job, set in different places: +# 1. this wrapper job -> the #SBATCH line above, or `sbatch --partition=NAME ...` +# 2. the pipeline's jobs -> `--partition NAME` here, forwarded to nextflow as +# --slurm_partition, which the SLURM profile maps to process.queue +# You rarely set (2): it is INHERITED from (1) via $SLURM_JOB_PARTITION. So moving a +# run to another partition takes ONE flag and both levels follow: +# sbatch --partition=mypart run_offtarget.sh --input s.csv --outdir out +# Account behaves identically (inherits $SLURM_JOB_ACCOUNT). +# +# Examples: +# # lab default — RIS Compute2, no site flags needed +# sbatch run_offtarget.sh --input offtarget_samplesheet_aavs1.csv \ +# --outdir results_offtarget_aavs1 +# +# # another partition; the pipeline's jobs follow automatically +# sbatch --partition=general-cpu run_offtarget.sh --input s.csv --outdir out +# +# # a completely different SLURM cluster: singularity, its own cache, no RIS binds, +# # no Lmod, and the site's default account +# sbatch --partition=batch run_offtarget.sh --input s.csv --outdir out \ +# --profile singularity --account "" \ +# --cache "$HOME/.singularity_cache" --bind "" --modules "" +# +# Launch from a node that can sbatch (login/compute) — NOT an interactive exec +# node, which cannot dispatch. If nested submission is blocked on your partition, +# run the body under nohup on a compute node instead. +# +# Per-process resources are right-sized in conf/modules.config; the ECS +# unevaluable-reads debug log is off by default (offtarget_ecs_unevaluable_log), +# so the whole run stays a few GB and lives comfortably in the repo-local ./work. +# +# For the RIS Compute1 (LSF) path instead, use: nextflow run . -entry OFFTARGET +# -profile ris (see docs/OFFTARGET.md). +# --------------------------------------------------------------------------- +set -euo pipefail + +INPUT="" +OUTDIR="./results_offtarget" +SNAP="" +RESUME="-resume" +EXTRA=() + +# Defaults are the lab's working RIS Compute2 values, so a lab member runs this with +# no extra flags. Resolution order is +# --flag > $OFFTARGET_* > inherited from this job > lab default +# Inheriting from $SLURM_JOB_* before the lab default is what makes +# `sbatch --partition=X run_offtarget.sh ...` place the pipeline's own jobs in X too, +# from that one flag. Use ${VAR-default} (no colon) throughout so that setting a +# variable to EMPTY means "pass nothing, use the cluster default" — the non-RIS path. +PARTITION="${OFFTARGET_PARTITION-${SLURM_JOB_PARTITION-condo-dspencer}}" +ACCOUNT="${OFFTARGET_ACCOUNT-${SLURM_JOB_ACCOUNT-compute2-dspencer}}" +PROFILE="${OFFTARGET_PROFILE-ris2,apptainer}" +WORKDIR="${OFFTARGET_WORKDIR-}" +CACHE="${OFFTARGET_CACHE-/scratch2/fs1/dspencer/apptainer_cache}" +BIND="${OFFTARGET_BIND-/storage2,/scratch2}" +MODULES="${OFFTARGET_MODULES-nextflow/25.10.4 apptainer/1.4.5}" +NXF_MEM="${OFFTARGET_NXF_OPTS--Xmx8g}" + +while [[ $# -gt 0 ]]; do + case "$1" in + --input) INPUT="${2:?--input needs a value}"; shift 2 ;; + --outdir) OUTDIR="${2:?--outdir needs a value}"; shift 2 ;; + --partition) PARTITION="${2-}"; shift 2 ;; + --account) ACCOUNT="${2-}"; shift 2 ;; + --profile) PROFILE="${2:?--profile needs a value}"; shift 2 ;; + --work-dir) WORKDIR="${2:?--work-dir needs a value}"; shift 2 ;; + --cache) CACHE="${2-}"; shift 2 ;; + --bind) BIND="${2-}"; shift 2 ;; + --modules) MODULES="${2-}"; shift 2 ;; + --snapshots) SNAP="--offtarget_snapshots true"; shift ;; + --no-resume) RESUME=""; shift ;; + --) shift; EXTRA=("$@"); break ;; + # print the banner block between the two '# ---' rules (no brittle line numbers) + -h|--help) awk '/^# -{10,}/{n++; next} n==1' "$0"; exit 0 ;; + *) echo "run_offtarget.sh: unknown option '$1' (see --help)" >&2; exit 2 ;; + esac +done +[[ -n "$INPUT" ]] || { echo "ERROR: --input is required (see --help)" >&2; exit 2; } + +# Environment modules are a site convention, not a given: load them only if this +# cluster has Lmod AND the caller has not opted out with --modules "". +if [[ -n "$MODULES" ]]; then + source /etc/profile.d/lmod.sh 2>/dev/null || true + if command -v module >/dev/null 2>&1; then + # shellcheck disable=SC2086 + module load $MODULES || echo "WARN: 'module load $MODULES' failed; " \ + "continuing with whatever is already on PATH" >&2 + else + echo "WARN: no 'module' command here; skipping --modules '$MODULES'" >&2 + fi +fi +command -v nextflow >/dev/null 2>&1 || { + echo "ERROR: nextflow is not on PATH. Load it yourself, or pass --modules ''." >&2 + exit 127; } + +# Container cache + bind paths. Both are site-specific, so an empty value means +# "leave the engine's own default alone" rather than exporting an empty setting. +if [[ -n "$CACHE" ]]; then + export NXF_APPTAINER_CACHEDIR="$CACHE" APPTAINER_CACHEDIR="$CACHE" + export NXF_SINGULARITY_CACHEDIR="$CACHE" SINGULARITY_CACHEDIR="$CACHE" + mkdir -p "$CACHE" +fi +[[ -n "$BIND" ]] && export APPTAINER_BINDPATH="$BIND" SINGULARITY_BIND="$BIND" +[[ -n "$NXF_MEM" ]] && export NXF_OPTS="$NXF_MEM" + +# Under sbatch, $0 is a spool copy — use the submission dir; fall back to the script dir (nohup). +RUNDIR="${SLURM_SUBMIT_DIR:-$(dirname "$(readlink -f "$0")")}" +cd "$RUNDIR" +export NXF_WORK="${WORKDIR:-${RUNDIR}/work}" + +# Forward the SLURM placement to the pipeline's own jobs. Only pass what we +# actually know: an unset partition/account must stay unset so the site default +# (or the profile's) applies instead of an empty -p/-A being submitted. +NF_SITE=() +[[ -n "$PARTITION" ]] && NF_SITE+=(--slurm_partition "$PARTITION") +[[ -n "$ACCOUNT" ]] && NF_SITE+=(--slurm_account "$ACCOUNT") + +echo "run_offtarget.sh: profile=${PROFILE} partition=${PARTITION:-} " \ + "account=${ACCOUNT:-} work=${NXF_WORK}" + +nextflow run . -entry OFFTARGET -profile "$PROFILE" \ + --input "$INPUT" \ + --outdir "$OUTDIR" \ + -work-dir "$NXF_WORK" \ + ${NF_SITE[@]+"${NF_SITE[@]}"} \ + $SNAP $RESUME "${EXTRA[@]+"${EXTRA[@]}"}" diff --git a/run_offtarget_tests.sh b/run_offtarget_tests.sh new file mode 100755 index 0000000..eaeb3c9 --- /dev/null +++ b/run_offtarget_tests.sh @@ -0,0 +1,303 @@ +#!/usr/bin/env bash +# --------------------------------------------------------------------------- +# run_offtarget_tests.sh — one-shot test harness for the Unified CRISPR +# Off-Target Workflow (-entry OFFTARGET). +# +# Runs the cheap-to-medium tiers that DON'T need a real cohort / scheduler: +# Tier 0 static parse python ast on bin/*.py + nextflow -preview +# Tier 1 glue unit tests pytest tests/test_offtarget_glue.py (the ECS<->WGS join) +# Tier 2 model contract wgs_shape_model.pkl loads + sklearn version guard +# Tier 3 stub end-to-end nextflow -profile stub -stub-run (DAG wiring, no CRAMs) +# Tier 4 nf-test real process bodies in the real container, KB fixtures +# +# Tiers 1 & 2 run INSIDE the pipeline's own container (Apptainer), so they use +# the exact pinned deps the pipeline runs — python 3.11, scikit-learn 1.8.0 +# (the version wgs_shape_model.pkl was pickled under), pandas, pysam. That makes +# Tier 2 a true mirror of production and sidesteps the repo-root vendored +# numpy/pandas dirs that otherwise shadow a bare interpreter. +# +# Best run on a normal compute node (module + apptainer available). It auto-loads +# the `apptainer` and `nextflow` Lmod modules; you can also pre-load them yourself: +# module load apptainer nextflow +# Anything genuinely missing (no apptainer, no java) is reported SKIP, not FAIL. +# The real AAVS1 acceptance run needs a cohort and stays separate: +# sbatch run_offtarget.sh --input offtarget_samplesheet_aavs1.csv --outdir results_offtarget_aavs1 +# +# Usage: bash run_offtarget_tests.sh +# OFFTARGET_CONTAINER=ghcr.io/dhslab/docker-scge-offtarget:TAG bash run_offtarget_tests.sh +# OFFTARGET_TEST_CACHE=/path/to/cache bash run_offtarget_tests.sh # where the SIF is cached +# INSTALL_DEPS=1 bash run_offtarget_tests.sh # allow the venv fallback +# Exit code is nonzero only if a tier FAILED (SKIP never fails the run). +# --------------------------------------------------------------------------- +set -u + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$REPO" +SS="assets/offtarget_samplesheet_template.csv" +SYS_PY="${PYTHON:-python3}" # dependency-free; used only for the ast parse tier + +# Pin the container straight from the pipeline modules so the harness can't drift +# from what actually runs. Override with OFFTARGET_CONTAINER. +CONTAINER="$(grep -rhoE 'ghcr\.io/dhslab/docker-scge-offtarget:[0-9A-Za-z._-]+' modules/local/*.nf 2>/dev/null | sort -u | head -1)" +CONTAINER="${OFFTARGET_CONTAINER:-${CONTAINER:-ghcr.io/dhslab/docker-scge-offtarget:260710}}" +CACHE="${OFFTARGET_TEST_CACHE:-$REPO/.offtarget_testcache}" +SIF="$CACHE/$(printf '%s' "$CONTAINER" | tr '/:' '__').sif" +PYX="$CACHE/pyextra" # pure-python pytest overlay (pytest isn't in the prod image) + +pass=0; fail=0; skip=0; FAILED_NAMES=() +c_g=$'\033[32m'; c_r=$'\033[31m'; c_y=$'\033[33m'; c_b=$'\033[1m'; c_0=$'\033[0m' +hdr(){ printf '\n%s========== %s ==========%s\n' "$c_b" "$1" "$c_0"; } +ok(){ printf ' %sPASS%s %s\n' "$c_g" "$c_0" "$1"; pass=$((pass+1)); } +no(){ printf ' %sFAIL%s %s\n' "$c_r" "$c_0" "$1"; fail=$((fail+1)); FAILED_NAMES+=("$1"); } +sk(){ printf ' %sSKIP%s %s (%s)\n' "$c_y" "$c_0" "$1" "$2"; skip=$((skip+1)); } +# a nextflow run failing on the JVM (missing / <17) is an env issue, not a pipeline defect -> SKIP +nf_env_broke(){ grep -qiE 'Cannot find Java|wrong version|java: command not found|needs a Java|Java .* (or later|is required)' "$1"; } + +# --- Lmod plumbing --------------------------------------------------------- +# `module` is a shell function that a non-login `bash script.sh` doesn't inherit; +# re-source the init if it's gone. MODULEPATH is an env var and *is* inherited, so +# the lab's own modulefiles stay visible either way. +init_modules(){ + command -v module >/dev/null 2>&1 && return 0 + local i + for i in /etc/profile.d/lmod.sh /etc/profile.d/z00_lmod.sh \ + "${LMOD_PKG:-/usr/share/lmod/lmod}/init/bash" /usr/share/lmod/lmod/init/bash; do + [ -f "$i" ] && . "$i" 2>/dev/null && command -v module >/dev/null 2>&1 && return 0 + done + command -v module >/dev/null 2>&1 +} +newest_module(){ module -t avail 2>&1 | grep -iE "^$1/[0-9]" | sort -V | tail -1; } +# load_tool : make resolvable, loading the newest module if needed +load_tool(){ + command -v "$1" >/dev/null 2>&1 && return 0 + init_modules || return 1 + local m; m="$(newest_module "$2")" || return 1 + [ -n "$m" ] && module load "$m" >/dev/null 2>&1 + command -v "$1" >/dev/null 2>&1 +} + +# --- python backend: container (preferred) or venv (fallback) -------------- +MODE_PY=none; CTR=""; VENVPY=""; SKLEARN_OK=0 +# run python with the pipeline deps, always from a neutral cwd (/): the repo root +# has broken vendored numpy/pandas/... dirs that would otherwise shadow real packages +# (same reason the glue-test conftest invokes bin scripts with cwd=tmp). +run_py(){ + case "$MODE_PY" in + container) ( cd / && $CTR env ${PYX:+PYTHONPATH="$PYX"} REPO="$REPO" python "$@" );; + venv) ( cd / && REPO="$REPO" "$VENVPY" "$@" );; + *) return 127;; + esac +} + +setup_container(){ + local rt="" + load_tool apptainer apptainer && rt=apptainer + [ -z "$rt" ] && load_tool singularity singularity && rt=singularity + [ -z "$rt" ] && return 1 + mkdir -p "$CACHE" + if [ ! -s "$SIF" ]; then + echo " pulling $CONTAINER (one-time, ~300MB)..." + APPTAINER_CACHEDIR="$CACHE/.pull" SINGULARITY_CACHEDIR="$CACHE/.pull" \ + "$rt" pull --force "$SIF" "docker://$CONTAINER" >"$CACHE/pull.log" 2>&1 \ + || { echo " container pull failed (see $CACHE/pull.log)"; return 1; } + fi + CTR="$rt exec --bind $REPO:$REPO --bind $CACHE:$CACHE $SIF" + MODE_PY=container + SKLEARN_OK=1 # image carries scikit-learn at the pickling version -> Tier 2 is a true mirror + # pytest is test-only and not in the prod image; drop a pure-python overlay beside the SIF + if ( cd / && $CTR python -c "import pytest" ) >/dev/null 2>&1; then + PYX="" + elif [ ! -d "$PYX/_pytest" ]; then + $CTR pip install --quiet --target="$PYX" pytest >"$CACHE/pytest_install.log" 2>&1 \ + || echo " note: could not add pytest overlay (Tier 1 will SKIP; see $CACHE/pytest_install.log)" + fi + return 0 +} + +# Fallback for hosts with no container runtime. Opt-in (INSTALL_DEPS=1) because it +# builds a venv. A venv on shared storage hard-references a per-node interpreter, so +# we rebuild (--clear) whenever the recorded python no longer executes here. +setup_venv(){ + [ "${INSTALL_DEPS:-0}" = "1" ] || return 1 + mkdir -p "$CACHE" + local py="${PYTHON:-python3}" pyver + pyver="$("$py" -c 'import sys;print("%d.%d"%sys.version_info[:2])' 2>/dev/null || echo x)" + local venv="$REPO/.offtarget_testenv-$pyver" + VENVPY="$venv/bin/python" + if [ ! -x "$VENVPY" ] || ! ( cd / && "$VENVPY" -c "import pandas,pytest,joblib,matplotlib" ) 2>/dev/null; then + "$py" -m venv --clear "$venv" >"$CACHE/venv.log" 2>&1 || return 1 + "$VENVPY" -m pip install --quiet --upgrade pip >>"$CACHE/venv.log" 2>&1 + "$VENVPY" -m pip install --quiet pytest pandas joblib matplotlib >>"$CACHE/venv.log" 2>&1 || return 1 + "$VENVPY" -m pip install --quiet "scikit-learn==1.8.0" >>"$CACHE/venv.log" 2>&1 && SKLEARN_OK=1 + else + ( cd / && "$VENVPY" -c "import sklearn" ) 2>/dev/null && SKLEARN_OK=1 + fi + MODE_PY=venv + return 0 +} + +NF="" +setup_nextflow(){ + if load_tool nextflow nextflow; then NF="$(command -v nextflow)"; return 0; fi + if [ -x "$REPO/nextflow" ] && command -v java >/dev/null 2>&1; then NF="$REPO/nextflow"; return 0; fi + return 1 +} + +printf '%sOFF-TARGET PIPELINE TESTS%s repo=%s\n' "$c_b" "$c_0" "$REPO" +printf 'container=%s\n' "$CONTAINER" + +# --- environment setup ----------------------------------------------------- +hdr "environment setup" +init_modules >/dev/null 2>&1 || true +if setup_container; then echo " python deps: container ($CONTAINER)" +elif setup_venv; then echo " python deps: venv ($VENVPY)" +else echo " python deps: unavailable (load the apptainer module, or re-run with INSTALL_DEPS=1)"; fi +if setup_nextflow; then echo " nextflow: $NF | $(java -version 2>&1 | head -1)" +else echo " nextflow/java: unavailable (nextflow tiers will SKIP)"; fi + +# =========================================================================== +hdr "Tier 0 — static parse (fast, no container)" + +# 0a. python syntax of every bin/ script (ast only, no third-party deps) +BAD="" +for s in "$REPO"/bin/*.py; do + "$SYS_PY" -c "import ast,sys; ast.parse(open(sys.argv[1]).read())" "$s" 2>/dev/null \ + || BAD="$BAD $(basename "$s")" +done +[ -z "$BAD" ] && ok "all bin/*.py parse" || no "python syntax errors in:$BAD" + +# 0b. nextflow can compile the OFFTARGET entry + resolve the ris profile +if [ -z "$NF" ]; then + sk "nextflow -preview" "no nextflow / java" +else + # --outdir is a REQUIRED param: without it schema validation fails and this tier + # reported a red herring rather than a genuine compile error. + if "$NF" run . -entry OFFTARGET -profile ris --input "$SS" --outdir /tmp/off_preview_out \ + -preview >/tmp/off_preview.log 2>&1; then + ok "nextflow compiles OFFTARGET entry (-preview, ris profile)" + elif nf_env_broke /tmp/off_preview.log; then + sk "nextflow -preview" "Java 17+ not available in this env" + else + no "nextflow -preview (see /tmp/off_preview.log)"; tail -n 15 /tmp/off_preview.log | sed 's/^/ /' + fi +fi + +# =========================================================================== +hdr "Tier 1 — glue-logic unit tests (ECS<->WGS join + off-target combiner)" +if [ "$MODE_PY" = none ]; then + sk "pytest tests/test_offtarget_glue.py tests/test_combine_offtarget.py" "no python backend (load apptainer, or INSTALL_DEPS=1)" +elif ! run_py -c "import pytest, pandas" >/dev/null 2>&1; then + sk "pytest tests/test_offtarget_glue.py tests/test_combine_offtarget.py" "pytest/pandas unavailable" +else + if run_py -m pytest -q "$REPO/tests/test_offtarget_glue.py" "$REPO/tests/test_combine_offtarget.py" >/tmp/off_pytest.log 2>&1; then + ok "$(grep -Eo '[0-9]+ passed' /tmp/off_pytest.log | tail -1) — glue + combiner tests" + else + no "pytest glue/combiner tests (see /tmp/off_pytest.log)"; tail -n 20 /tmp/off_pytest.log | sed 's/^/ /' + fi +fi + +# =========================================================================== +hdr "Tier 2 — model contract (sklearn pin / version guard)" +if [ "$MODE_PY" = none ]; then + sk "model load + version guard" "no python backend" +elif [ "$SKLEARN_OK" != 1 ] || ! run_py -c "import joblib, sklearn, pandas" >/dev/null 2>&1; then + sk "model load + version guard" "scikit-learn 1.8.0 unavailable (use the container)" +else + run_py - >/tmp/off_model.log 2>&1 <<'PY' +import os, sys +repo = os.environ["REPO"] +sys.path.insert(0, os.path.join(repo, "bin")) # for features.py (absolute; cwd is neutral) +import joblib +from features import check_sklearn_version +b = joblib.load(os.path.join(repo, "assets/models/wgs_shape_model.pkl")) +model = b["model"] if isinstance(b, dict) else b +check_sklearn_version(model, name="wgs_shape_model.pkl") # raises if runtime older than pickle +print("features:", b.get("features") if isinstance(b, dict) else None) +print("OK") +PY + if grep -q '^OK' /tmp/off_model.log; then + ok "wgs_shape_model.pkl loads + version guard passes" + grep -i 'features:' /tmp/off_model.log | sed 's/^/ /' + else + no "model load / version guard (see /tmp/off_model.log)"; tail -n 15 /tmp/off_model.log | sed 's/^/ /' + fi +fi + +# =========================================================================== +hdr "Tier 3 — stub end-to-end (DAG wiring, no CRAMs)" +if [ -z "$NF" ]; then + sk "nextflow -stub-run" "no nextflow / java" +else + rm -rf "$REPO/results_stub" + if "$NF" run . -entry OFFTARGET -profile stub -stub-run \ + --input "$SS" --outdir "$REPO/results_stub" >/tmp/off_stub.log 2>&1; then + ok "stub run completed (both arms + paired join scheduled)" + elif nf_env_broke /tmp/off_stub.log; then + sk "nextflow -stub-run" "Java 17+ not available in this env" + else + no "stub run (see /tmp/off_stub.log)"; tail -n 20 /tmp/off_stub.log | sed 's/^/ /' + fi + + # HOTSPOTS entry (gRNA -> targets) — pure-shell stubs, tiny committed fixture FASTA. + rm -rf "$REPO/results_hotspots_stub" + if "$NF" run . -entry HOTSPOTS -profile stub -stub-run \ + --input assets/grna_samplesheet_template.csv --fasta assets/stub/tiny.fa \ + --outdir "$REPO/results_hotspots_stub" >/tmp/hotspots_stub.log 2>&1; then + ok "HOTSPOTS stub run completed (Cas-OFFinder -> combine -> targets.vcf)" + elif nf_env_broke /tmp/hotspots_stub.log; then + sk "HOTSPOTS -stub-run" "Java 17+ not available in this env" + else + no "HOTSPOTS stub run (see /tmp/hotspots_stub.log)"; tail -n 20 /tmp/hotspots_stub.log | sed 's/^/ /' + fi +fi + +# =========================================================================== +hdr "Tier 4 — nf-test (REAL process bodies in the real container)" +# The gap this closes: every Nextflow tier above runs with -stub-run, whose process +# bodies only `touch` their outputs. A module can therefore pass a flag that +# bin/*.py does not accept and stay green through all of Tier 3. nf-test runs the +# actual command on the KB-sized fixtures in tests/fixtures/, so the module <-> script +# contract is executed for real. Costs ~1 min; no cohort data required. +NFTEST="${NFTEST:-}" +[ -z "$NFTEST" ] && NFTEST="$(command -v nf-test 2>/dev/null || true)" +[ -z "$NFTEST" ] && [ -x "$REPO/nf-test" ] && NFTEST="$REPO/nf-test" +if [ -z "$NF" ]; then + sk "nf-test" "no nextflow / java" +elif [ -z "$NFTEST" ]; then + sk "nf-test" "nf-test not installed (curl -fsSL https://code.askimed.com/install/nf-test | bash, or set NFTEST=/path/to/nf-test)" +elif [ "$MODE_PY" != "container" ]; then + # nf-test executes the process bodies, which declare a container. Without a runtime + # there is nothing to execute them in, and a venv cannot stand in. + sk "nf-test" "needs a container runtime (apptainer/singularity)" +else + # Point Nextflow's image cache at the SIF this harness already pulled, so Tier 4 + # never re-downloads 300 MB, and bind /storage2 so projectDir is visible inside. + if PATH="$(dirname "$NF"):$PATH" \ + NXF_APPTAINER_CACHEDIR="$CACHE" NXF_SINGULARITY_CACHEDIR="$CACHE" \ + APPTAINER_BIND=/storage2 SINGULARITY_BIND=/storage2 NXF_ANSI_LOG=false \ + "$NFTEST" test --profile stub,apptainer >/tmp/off_nftest.log 2>&1; then + NT_N="$(grep -c 'PASSED' /tmp/off_nftest.log 2>/dev/null || echo '?')" + ok "nf-test: $NT_N tests passed (metrics module + ECS caller, real execution)" + elif nf_env_broke /tmp/off_nftest.log; then + sk "nf-test" "Java 17+ not available in this env" + else + no "nf-test (see /tmp/off_nftest.log)"; tail -n 25 /tmp/off_nftest.log | sed 's/^/ /' + fi +fi + +# =========================================================================== +hdr "SUMMARY" +printf ' %sPASS %d%s %sFAIL %d%s %sSKIP %d%s\n' \ + "$c_g" "$pass" "$c_0" "$c_r" "$fail" "$c_0" "$c_y" "$skip" "$c_0" +if [ "$fail" -gt 0 ]; then printf ' failed: %s\n' "${FAILED_NAMES[*]}"; fi +cat < join broke) + offtarget_report.csv AAVS1 on-target: is_hotspot=1 & ecs_confirmed=1 + recall_vs_vaf.{csv,png} ~1.0 in high-VAF bins + Known blind spots (no data yet): sub-5% VAF floor; de-novo off-target positive control. +EOF +[ "$fail" -eq 0 ] diff --git a/subworkflows/local/gather_alignment_samples.nf b/subworkflows/local/gather_alignment_samples.nf index e0236bf..811b9ff 100644 --- a/subworkflows/local/gather_alignment_samples.nf +++ b/subworkflows/local/gather_alignment_samples.nf @@ -64,8 +64,6 @@ workflow GATHER_ALIGNMENT_SAMPLES { .filter{ it != [] } ) - ch_crams_to_convert.dump(tag:'crams_to_convert', pretty:true) - // // // SUBWORKFLOW: Partition BAM/CRAM files that need to be converted to fastq and realigned. @@ -152,7 +150,9 @@ workflow GATHER_ALIGNMENT_SAMPLES { } .filter{ it!= [] } ) - + .unique() + + // // // MODULE: Create fastq_list with local/staged fastq paths and appropriate metadata // @@ -206,9 +206,6 @@ workflow GATHER_ALIGNMENT_SAMPLES { .map{ meta, reads, fastq_list -> [ meta, reads.flatten(), fastq_list ] } ) - ch_gathered_samples.dump(tag:'gathered_samples', pretty:true) - - // emit: samples = ch_gathered_samples // channel: [ val(meta), path(reads), path(fastq_list) ] versions = ch_versions // channel: [ path(file) ] @@ -233,14 +230,14 @@ workflow PREPARE_SOMATIC_FASTQS { .map { meta, reads, fastqlist -> [ meta.individual_id, meta, reads, fastqlist ] } - .cross( // and join with normal samples + .combine( // and join with normal samples ch_prepare_somatic_fastqs_samples.normal .map { meta, reads, fastqlist -> [ meta.individual_id, meta, reads, fastqlist ] - } - ).map { tumor, normal -> [ tumor[1], tumor[2], tumor[3], normal[1], normal[2], normal[3] ] } - // on joined samples, set tumor and normal id to meta and combine reads. - .map { tumor_meta, tumor_reads, tumor_fastqlist, normal_meta, normal_reads, normal_fastqlist -> + }, + by: 0 + ) + .map { id, tumor_meta, tumor_reads, tumor_fastqlist, normal_meta, normal_reads, normal_fastqlist -> def new_meta = [:] new_meta['id'] = tumor_meta['id'] new_meta['sex'] = tumor_meta['sex'] @@ -254,7 +251,7 @@ workflow PREPARE_SOMATIC_FASTQS { reads: [ meta, reads ] fastqlist: [ meta.id, meta, fastqlists ] } - + ch_prepare_somatic_fastqs_output = ch_prepare_somatic_fastqs.reads .join( ch_prepare_somatic_fastqs.fastqlist diff --git a/subworkflows/local/generate_hotspots.nf b/subworkflows/local/generate_hotspots.nf new file mode 100644 index 0000000..ee1cd90 --- /dev/null +++ b/subworkflows/local/generate_hotspots.nf @@ -0,0 +1,72 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + GENERATE_HOTSPOTS — gRNA -> predicted off-target sites (target_file) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Per guide: enumerate off-target sites with Cas-OFFinder (and, when enabled, CRISPRme), + combine them into .targets.csv, then expand to .targets.vcf — the VCF the + OFFTARGET arm consumes as a per-row target_file. + + (meta, spacer, pam, idt) + ├─ CASOFFINDER (2bit) ──► .casoffinder.txt + └─ CRISPRME (opt) ──► .crisprme.tsv + └─ COMBINE_OFFTARGET_SITES ──► .targets.csv + └─ TARGETS_CSV_TO_VCF ──► .targets.vcf +*/ + +include { PREP_CASOFFINDER_REF } from '../../modules/local/prep_casoffinder_ref.nf' +include { CASOFFINDER } from '../../modules/local/casoffinder.nf' +include { CRISPRME } from '../../modules/local/crisprme.nf' +include { COMBINE_OFFTARGET_SITES } from '../../modules/local/combine_offtarget_sites.nf' +include { TARGETS_CSV_TO_VCF } from '../../modules/local/targets_csv_to_vcf.nf' + +workflow GENERATE_HOTSPOTS { + take: + ch_guides // tuple(meta[id], spacer, pam, idt_path_or_NO_FILE) + + main: + ch_versions = Channel.empty() + // Distinct sentinels for the two optional COMBINE slots — same filename in both slots + // would collide when staged into one task. + def no_crisprme = file("${projectDir}/assets/NO_FILE") + + // Reference the search runs against: a prebuilt .2bit, or built once with faToTwoBit. + if (params.casoffinder_2bit) { + ch_2bit = Channel.value(file(params.casoffinder_2bit, checkIfExists: true)) + } else { + PREP_CASOFFINDER_REF(file(params.fasta, checkIfExists: true)) + ch_2bit = PREP_CASOFFINDER_REF.out.twobit.first() + ch_versions = ch_versions.mix(PREP_CASOFFINDER_REF.out.versions) + } + + ch_guide_only = ch_guides.map { meta, spacer, pam, idt -> tuple(meta, spacer, pam) } + + // ---- Cas-OFFinder (always) ---- + CASOFFINDER(ch_guide_only, ch_2bit) + ch_versions = ch_versions.mix(CASOFFINDER.out.versions) + + // ---- CRISPRme (optional; Cas-OFFinder-only by default) ---- + if (params.run_crisprme) { + ch_index = Channel.value(file(params.crisprme_index_dir, checkIfExists: true)) + CRISPRME(ch_guide_only, ch_index) + ch_versions = ch_versions.mix(CRISPRME.out.versions) + ch_cme = CRISPRME.out.hits + } else { + ch_cme = ch_guide_only.map { meta, s, p -> tuple(meta, no_crisprme) } + } + + // ---- combine per guide, then expand to the target VCF ---- + ch_idt = ch_guides.map { meta, spacer, pam, idt -> tuple(meta, idt) } + ch_combine = CASOFFINDER.out.hits.join(ch_cme).join(ch_idt) + + COMBINE_OFFTARGET_SITES(ch_combine) + ch_versions = ch_versions.mix(COMBINE_OFFTARGET_SITES.out.versions) + + TARGETS_CSV_TO_VCF(COMBINE_OFFTARGET_SITES.out.sites, + file(params.fasta), file("${params.fasta}.fai")) + ch_versions = ch_versions.mix(TARGETS_CSV_TO_VCF.out.versions) + + emit: + sites = COMBINE_OFFTARGET_SITES.out.sites // (meta, .targets.csv) + vcf = TARGETS_CSV_TO_VCF.out.vcf // (meta, .targets.vcf) + versions = ch_versions +} diff --git a/subworkflows/local/make_scge_report.nf b/subworkflows/local/make_scge_report.nf index b80f502..5292ac7 100644 --- a/subworkflows/local/make_scge_report.nf +++ b/subworkflows/local/make_scge_report.nf @@ -1,6 +1,7 @@ // make scge report include { RENDER_SCGE_REPORT } from '../../modules/local/render_scge_report.nf' +include { GENERATE_EXCEL_REPORT } from '../../modules/local/generate_excel_report.nf' workflow MAKE_SCGE_REPORT { take: @@ -8,5 +9,20 @@ workflow MAKE_SCGE_REPORT { main: RENDER_SCGE_REPORT(ch_report_input, params.scge_report_qmd) + + // Join inputs: + // ch_report_input: [meta, json, cna, baf, circos] + // RENDER.out.indel_plot: [meta, indel_png] + // RENDER.out.off_targets_plot: [meta, off_target_png] + ch_excel_input = ch_report_input + .join(RENDER_SCGE_REPORT.out.indel_plot) + .join(RENDER_SCGE_REPORT.out.off_targets_plot) + // Result: [meta, json, cna, baf, circos, indel, off_target] + + GENERATE_EXCEL_REPORT(ch_excel_input) + + emit: + scge_report = RENDER_SCGE_REPORT.out.scge_report + excel_report = GENERATE_EXCEL_REPORT.out.excel_report } \ No newline at end of file diff --git a/subworkflows/local/scge_analysis.nf b/subworkflows/local/scge_analysis.nf index 4980adf..fe5e1c0 100644 --- a/subworkflows/local/scge_analysis.nf +++ b/subworkflows/local/scge_analysis.nf @@ -10,11 +10,15 @@ include { ANNOTATE_SV_VARIANTS } from '../../modules/local/annotate_sv_ include { VEP_TO_TSV as SV_TO_TSV } from '../../modules/local/vep_to_tsv.nf' include { ANNOTATE_CNV_VARIANTS } from '../../modules/local/annotate_cnv_variants.nf' include { VEP_TO_TSV as CNV_TO_TSV } from '../../modules/local/vep_to_tsv' -include { ANNOTATE_OFFTARGETS } from '../../modules/local/annotate_offtargets.nf' -include { GET_INDELS } from '../../modules/local/get_indels.nf' -include { GET_TRANSGENE_JUNCTIONS } from '../../modules/local/get_transgene_junctions.nf' -include { TRANSGENE_TO_VCF } from '../../modules/local/transgene_to_vcf' -include { ANNOTATE_TRANSGENE_VARIANTS } from '../../modules/local/annotate_transgene.nf' +include { ANNOTATE_OFFTARGETS } from '../../modules/local/annotate_offtargets.nf' +include { GET_INDELS } from '../../modules/local/get_indels.nf' +include { REVIEW_FILTER } from '../../modules/local/review_filter.nf' +include { REVIEW_FILTER_BND } from '../../modules/local/review_filter_bnd.nf' +include { REVIEW_SNAPSHOTS } from '../../modules/local/review_snapshots.nf' +include { REVIEW_BND_SNAPSHOTS } from '../../modules/local/review_bnd_snapshots.nf' +include { GET_TRANSGENE_JUNCTIONS } from '../../modules/local/get_transgene_junctions.nf' +include { TRANSGENE_TO_VCF } from '../../modules/local/transgene_to_vcf' +include { ANNOTATE_TRANSGENE_JUNCTIONS } from '../../modules/local/annotate_transgene_junctions.nf' include { TRANSFORM_TRANSGENE } from '../../modules/local/transform_transgene.nf' include { MAKE_CIRCOS_PLOT } from '../../modules/local/make_circos_plot.nf' include { REFORMAT_CNV_DATA } from '../../modules/local/reformat_cnv_data.nf' @@ -33,7 +37,7 @@ include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../../modules/nf-core/custom/dumps // Vep cache ch_vepcache = params.vepcache - ? Channel.fromPath(params.vepcache, type: 'dir', checkIfExists: true) + ? Channel.fromPath(params.vepcache, type: 'dir', checkIfExists: true).collect() : Channel.empty() ch_cytobands = params.cytobands @@ -41,9 +45,13 @@ ch_cytobands = params.cytobands : [] ch_crispr_model = params.crispr_model ? - Channel.fromPath("${params.crispr_model}", checkIfExists: true) + Channel.fromPath("${params.crispr_model}", checkIfExists: true).collect() : [] +ch_transgene_name = params.transgene_name && params.transgene_name != false && params.transgene_name != null + ? Channel.value(params.transgene_name) : Channel.empty() + + /* ======================================================================================== SUBWORKFLOW TO ANALYZE DATA @@ -58,6 +66,7 @@ workflow SCGE_ANALYSIS { main: ch_versions = Channel.empty() + ch_report_inputs = Channel.empty() // channel: meta, [ file1, file2, etc ] // // Main analysis @@ -67,6 +76,16 @@ workflow SCGE_ANALYSIS { ch_dragen_files = ch_analysis_samples .map { meta, dragenfiles, targetfile -> [ meta, dragenfiles ]} + // Get coverage files for report + ch_report_inputs = ch_report_inputs.mix( + ch_dragen_files.map { meta, dragen_path -> + def tumor_cov = dragen_path.find { it.name.endsWith('.wgs_overall_mean_cov_tumor.csv') } + def normal_cov = dragen_path.find { it.name.endsWith('.wgs_overall_mean_cov_normal.csv') } + return [ meta, [ file(tumor_cov,checkIfExists: true), file(normal_cov,checkIfExists: true) ] ] + } + ) + + // Annotate small variants ANNOTATE_VARIANTS ( ch_dragen_files, ch_fasta_reference, @@ -75,8 +94,10 @@ workflow SCGE_ANALYSIS { ch_versions = ch_versions.mix(ANNOTATE_VARIANTS.out.versions) VARIANTS_TO_TSV (ANNOTATE_VARIANTS.out.vcf,Channel.value('vcf')) + ch_report_inputs = ch_report_inputs.mix(VARIANTS_TO_TSV.out.tsv) ch_versions = ch_versions.mix(VARIANTS_TO_TSV.out.versions) + // Annotate structural variants ANNOTATE_SV_VARIANTS ( ch_dragen_files, ch_fasta_reference, @@ -86,8 +107,10 @@ workflow SCGE_ANALYSIS { ch_versions = ch_versions.mix(ANNOTATE_VARIANTS.out.versions) SV_TO_TSV (ANNOTATE_SV_VARIANTS.out.vcf,Channel.value('sv')) + ch_report_inputs = ch_report_inputs.mix(SV_TO_TSV.out.tsv) ch_versions = ch_versions.mix(SV_TO_TSV.out.versions) + // Annotate copy number variants ANNOTATE_CNV_VARIANTS ( ch_dragen_files, ch_fasta_reference, @@ -97,8 +120,10 @@ workflow SCGE_ANALYSIS { ch_versions = ch_versions.mix(ANNOTATE_CNV_VARIANTS.out.versions) CNV_TO_TSV (ANNOTATE_CNV_VARIANTS.out.vcf,Channel.value('cnv')) + ch_report_inputs = ch_report_inputs.mix(CNV_TO_TSV.out.tsv) ch_versions = ch_versions.mix(CNV_TO_TSV.out.versions) + // Annotate and analyze off-target sites ANNOTATE_OFFTARGETS( ch_analysis_samples.map{ meta, dragenfiles, targetfile -> [meta, targetfile] }, ch_vepcache, @@ -106,112 +131,164 @@ workflow SCGE_ANALYSIS { ) ch_versions = ch_versions.mix(ANNOTATE_OFFTARGETS.out.versions) - GET_INDELS(ch_dragen_files.join(ANNOTATE_OFFTARGETS.out.targetfile), - ch_crispr_model, - ch_fasta_reference) + GET_INDELS( + ch_dragen_files.join(ANNOTATE_OFFTARGETS.out.targetfile), + ch_crispr_model, + ch_fasta_reference + ) + + ch_report_inputs = ch_report_inputs.mix(GET_INDELS.out.indels_file) ch_versions = ch_versions.mix(GET_INDELS.out.versions) + // Collapse the per-sample call tables into one short review queue. Every sample is staged + // into a SINGLE call on purpose: the cross-guide fallback for rule 4 can only see recurrence + // across whatever is passed together, so a per-sample invocation would silently disable it. + // With review_noise_model set that fallback is not used at all -- the beta-binomial scores + // each sample against its OWN control, which is what makes a single-sample submission work. + if (params.review_filter) { + ch_no_file = Channel.fromPath("${projectDir}/assets/NO_FILE") + + // Rule 5, repeat context. Needs no controls, no cohort and no guide information, so it + // is the one rule that works on day one for a guide never run before. + ch_repeats = params.review_repeat_beds + ? Channel.fromPath(params.review_repeat_beds.tokenize(','), checkIfExists: true).collect() + : Channel.value([]) + + // Rule 6, external DRAGEN noise panel. Like rule 5 it needs nothing from this run, but it + // is a single optional file, so it uses the NO_FILE sentinel rather than an empty list. + ch_snv_noise = params.review_snv_noise + ? Channel.fromPath(params.review_snv_noise, checkIfExists: true) + : ch_no_file + + // .collect() yields a value channel, so the same staged list feeds both review processes. + ch_analysis_tsvs = GET_INDELS.out.indels_file.map{ meta, tsv -> tsv }.collect() + + REVIEW_FILTER( + ch_analysis_tsvs, + ch_repeats, + ch_snv_noise + ) + ch_versions = ch_versions.mix(REVIEW_FILTER.out.versions) + + // Review packet inputs, shared by the indel and breakend renderers. CRAM paths are + // passed as a map rather than staged -- the queue names arbitrary samples, and staging + // every cohort CRAM to draw a few dozen pictures would copy TBs. + def want_bnd_snaps = params.review_filter_bnd && params.review_bnd_snapshots + if (params.review_snapshots || want_bnd_snaps) { + ch_review_cram_map = ch_dragen_files + .map{ meta, dragenfiles -> + def crams = dragenfiles.findAll{ it ==~ /.*\.(cram)$/ } + def ed = crams.max{ it.toString().length() } + def ct = crams.min{ it.toString().length() } + "${meta.id}\t${ed}\t${ct}\n" + } + .collectFile(name: 'review_cram_map.tsv', sort: true) + .first() + + // No .first() here: ch_fasta_reference is built with .collect(), so it is + // already a value channel and .first() would only earn a warning. + ch_review_fasta = ch_fasta_reference + .map{ it.find{ f -> f ==~ /.*\.(fasta|fa)$/ } } + } + // .first() on the cram map: collectFile() yields a QUEUE channel, and it now feeds + // two processes. A value channel is re-readable; a queue channel would let whichever + // renderer ran first consume the only item and leave the other waiting forever. + + // The same triage applied to breakends rather than indels. Separate process because the + // rules differ: a junction has two ends, so promiscuity replaces length diversity and the + // noise panel is a BEDPE rather than a BED. + if (params.review_filter_bnd) { + ch_sv_noise = params.review_sv_noise + ? Channel.fromPath(params.review_sv_noise, checkIfExists: true) + : ch_no_file + + REVIEW_FILTER_BND( + ch_analysis_tsvs, + ch_sv_noise + ) + ch_versions = ch_versions.mix(REVIEW_FILTER_BND.out.versions) + + // One figure per junction, not per queue row -- see the module header. + if (params.review_bnd_snapshots) { + REVIEW_BND_SNAPSHOTS( + REVIEW_FILTER_BND.out.queue, + ch_review_cram_map, + ch_review_fasta + ) + ch_versions = ch_versions.mix(REVIEW_BND_SNAPSHOTS.out.versions) + } + } + + // Review packet: an IGV-style pileup per surviving site, edited over matched control. + if (params.review_snapshots) { + REVIEW_SNAPSHOTS( + REVIEW_FILTER.out.queue, + ch_review_cram_map, + ch_review_fasta + ) + ch_versions = ch_versions.mix(REVIEW_SNAPSHOTS.out.versions) + } + } + + BND_FROM_INDELS_TO_VCF ( + GET_INDELS.out.indels_file + ) + ch_report_inputs = ch_report_inputs.mix(BND_FROM_INDELS_TO_VCF.out.vcf) + ch_versions = ch_versions.mix(BND_FROM_INDELS_TO_VCF.out.versions) + + // Get transgene junctions GET_TRANSGENE_JUNCTIONS(ch_dragen_files, - ch_fasta_reference) + ch_fasta_reference, + ch_transgene_name + ) ch_versions = ch_versions.mix(GET_TRANSGENE_JUNCTIONS.out.versions) TRANSGENE_TO_VCF(GET_TRANSGENE_JUNCTIONS.out.transgene_file) ch_versions = ch_versions.mix(TRANSGENE_TO_VCF.out.versions) - ANNOTATE_TRANSGENE_VARIANTS( + ANNOTATE_TRANSGENE_JUNCTIONS( TRANSGENE_TO_VCF.out.transgene_vcf, ch_fasta_reference, ch_vepcache, ch_cytobands ) - ch_versions = ch_versions.mix(ANNOTATE_TRANSGENE_VARIANTS.out.versions) + ch_report_inputs = ch_report_inputs.mix(ANNOTATE_TRANSGENE_JUNCTIONS.out.annotated_junctions) + ch_versions = ch_versions.mix(ANNOTATE_TRANSGENE_JUNCTIONS.out.versions) + // Make Circos plot TRANSFORM_TRANSGENE(GET_TRANSGENE_JUNCTIONS.out.transgene_file) ch_versions = ch_versions.mix(TRANSFORM_TRANSGENE.out.versions) MAKE_CIRCOS_PLOT(TRANSFORM_TRANSGENE.out.circos_input) - - BND_FROM_INDELS_TO_VCF ( - GET_INDELS.out.indels_file - .join(VARIANTS_TO_TSV.out.vep_tsv) - .map { meta, indels_file, vep_tsv -> [meta, indels_file] } - ) + // Add to report inputs + ch_report_inputs = ch_report_inputs.mix(MAKE_CIRCOS_PLOT.out.plot) // - // Generate plots + // Generate CNA plots // GENERATE_CNA_BAF_PLOTS(ch_dragen_files) + ch_report_inputs = ch_report_inputs.mix(GENERATE_CNA_BAF_PLOTS.out.plots) ch_versions = ch_versions.mix(GENERATE_CNA_BAF_PLOTS.out.versions) - // - // Collate outputs - // - - ch_coverage_files = ch_dragen_files.map { meta, dragen_path -> - // dragen_path is a List of files, not a directory path object - def tumor_cov_file = dragen_path.find { it.name.endsWith('.wgs_overall_mean_cov_tumor.csv') } ?: file("${baseDir}/assets/empty_tumor_coverage.txt") - def normal_cov_file = dragen_path.find { it.name.endsWith('.wgs_overall_mean_cov_normal.csv') } ?: file("${baseDir}/assets/empty_normal_coverage.txt") - return [meta.id, tumor_cov_file, normal_cov_file] - } - - def ch_plots = GENERATE_CNA_BAF_PLOTS.out.cna_plot - .join(GENERATE_CNA_BAF_PLOTS.out.baf_plot) - .map { meta, cna, baf -> [meta.id, meta, cna, baf] } - - def ch_circos = MAKE_CIRCOS_PLOT.out.circos_plot - .map { meta, circos -> [meta.id, circos] } - ch_circos.view { "Circos: $it" } - - def ch_annotated_transgene = ANNOTATE_TRANSGENE_VARIANTS.out.annotated_transgene_variants - .map { meta, transgene -> [meta.id, transgene] } - ch_annotated_transgene.view { "Annotated Transgene: $it" } - - def ch_vep_tsv = VARIANTS_TO_TSV.out.vep_tsv - .map { meta, tsv -> [meta.id, tsv] } - ch_vep_tsv.view { "VEP TSV: $it" } - - // Use actual indels output from GET_INDELS (not the VEP-annotated target file) - def ch_indels = GET_INDELS.out.indels_file - .map { meta, indels -> [meta.id, indels] } - ch_indels.view { "Indels: $it" } - - def ch_bnd_vcf = BND_FROM_INDELS_TO_VCF.out.bnd_vcf - .map { meta, vcf -> [meta.id, vcf] } - - ch_plots - .join(ch_circos, by: 0) - .join(ch_annotated_transgene, by: 0) - .join(ch_vep_tsv, by: 0) - .join(ch_indels, by: 0) - .join(ch_bnd_vcf, by: 0) - .join(ch_coverage_files, by: 0) - .map { id, meta, cna, baf, circos, transgene, tsv, indels, bnd_vcf, tumor_cov, normal_cov -> - def timestamp = new Date().getTime() - [meta, cna, baf, circos, transgene, tsv, indels, bnd_vcf, tumor_cov, normal_cov, timestamp] - } - .set { ch_compile_report_input } - - - COMPILE_REPORT_JSON(ch_compile_report_input) + // Make report JSON + COMPILE_REPORT_JSON( + ch_report_inputs + .groupTuple() + .map{ it -> [ it[0], it[1].flatten() ] }.view(), + Channel.value("${new Date().getTime()}")) ch_versions = ch_versions.mix(COMPILE_REPORT_JSON.out.versions) - def ch_plots_for_report = GENERATE_CNA_BAF_PLOTS.out.cna_plot - .join(GENERATE_CNA_BAF_PLOTS.out.baf_plot) - .map { meta, cna, baf -> [meta.id, cna, baf] } - - def ch_report_input = COMPILE_REPORT_JSON.out.json - .map { meta, json -> [meta.id, meta, json] } - .join(ch_plots_for_report) - .map { id, meta, json, cna, baf -> [meta, json, cna, baf] } - MAKE_SCGE_REPORT(ch_report_input) - - CUSTOM_DUMPSOFTWAREVERSIONS ( - ch_versions.unique().collectFile(name: 'collated_versions.yml') + // Render report + MAKE_SCGE_REPORT( + COMPILE_REPORT_JSON.out.json + .join(GENERATE_CNA_BAF_PLOTS.out.plots) + .join(MAKE_CIRCOS_PLOT.out.plot) ) emit: versions = ch_versions // channel: [ path(file) ] + scge_report = MAKE_SCGE_REPORT.out.scge_report } diff --git a/subworkflows/local/utils_nfcore_scge_pipeline/main.nf b/subworkflows/local/utils_nfcore_scge_pipeline/main.nf index 51b7ae8..37d4816 100644 --- a/subworkflows/local/utils_nfcore_scge_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_scge_pipeline/main.nf @@ -90,6 +90,57 @@ workflow PIPELINE_INITIALISATION { } +/* +======================================================================================== + SUBWORKFLOW TO VALIDATE PARAMETERS ONLY +======================================================================================== +*/ + +// +// The validation half of PIPELINE_INITIALISATION, without INPUT_CHECK. +// +// The named entries (-entry OFFTARGET, -entry TRAIN) take their own samplesheet shapes +// (an ecs/wgs sheet and a training.tsv respectively), neither of which is the MGI +// mastersheet INPUT_CHECK parses. They still need --help, version reporting and +// schema validation, so they call this instead of PIPELINE_INITIALISATION. +// +workflow VALIDATE_PARAMS { + + take: + version // boolean: Display version and exit + help // boolean: Display help text + validate_params // boolean: Validate parameters against the schema at runtime + monochrome_logs // boolean: Do not use coloured log outputs + nextflow_cli_args // array: List of positional nextflow CLI args + outdir // string: The output directory where the results will be saved + workflow_command // string: Example command shown in the help text + + main: + + UTILS_NEXTFLOW_PIPELINE ( + version, + true, + outdir, + workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1 + ) + + pre_help_text = nfCoreLogo(monochrome_logs) + post_help_text = '\n' + workflowCitation() + '\n' + dashedLine(monochrome_logs) + + UTILS_NFVALIDATION_PLUGIN ( + help, + workflow_command, + pre_help_text, + post_help_text, + validate_params, + "nextflow_schema.json" + ) + + UTILS_NFCORE_PIPELINE ( + nextflow_cli_args + ) +} + /* ======================================================================================== SUBWORKFLOW FOR PIPELINE COMPLETION diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..f5c7c92 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,253 @@ +"""Shared fixtures for the off-target glue-script tests. + +These exercise the pure-pandas glue scripts (no pysam / CRAM / model needed): + hotspot_to_table.py, join_training_table.py, recall_vs_vaf.py, reconcile_offtarget_report.py + +Run with an interpreter that has pandas (the docker-scge container, or any env with +pandas). Scripts are invoked as subprocesses with cwd=tmp so the repo-root vendored +packages never shadow the interpreter's own. +""" +import subprocess +import sys +from pathlib import Path + +import pandas as pd +import pytest + +BIN = Path(__file__).resolve().parent.parent / "bin" + +# 3 hotspots for one guide (PLCB2_KO): +# chr12:32679408 real off-target, strong ECS edit (VAF 0.15) -> WGS should detect +# chr1:1000000 ECS-negative (VAF 0) -> true negative +# chr7:5000000 ECS low VAF (0.008), below the WGS depth floor -> WGS misses (by design) +HOTSPOTS = [ + ("chr12", 32679408, 32679409, 0.15, 1, "MISMATCHES=1;PAM=AGG"), + ("chr1", 1000000, 1000001, 0.00, 0, "MISMATCHES=3;PAM=TGG"), + ("chr7", 5000000, 5000001, 0.008, 0, "MISMATCHES=2;PAM=GGG"), +] +ECS_COLS = ["chrom", "start", "end", "pam_positions", "total_reads", "indel_reads", + "indel_fraction", "control_reads", "control_indel_reads", + "control_indel_fraction", "indel_count", "indel_info", "bnd_count", + "bnd_info", "target_info", "is_target"] + + +def run(script, *args, cwd): + """Run a bin/ script as a subprocess; return the CompletedProcess (asserts rc==0).""" + proc = subprocess.run([sys.executable, str(BIN / script), *map(str, args)], + cwd=cwd, capture_output=True, text=True) + assert proc.returncode == 0, f"{script} failed:\n{proc.stdout}\n{proc.stderr}" + return proc + + +def _ecs_table(scale): + rows = [] + for chrom, start, end, base_vaf, is_tgt, tinfo in HOTSPOTS: + vaf = round(base_vaf * scale, 4) + total = 3000 + rows.append([chrom, start, end, str(end), total, int(total * vaf), vaf, + 2500, 0, 0.0, int(total * vaf), ".", 0, ".", tinfo, is_tgt]) + return pd.DataFrame(rows, columns=ECS_COLS) + + +@pytest.fixture +def workspace(tmp_path): + """A tmp dir populated with realistic ECS tables, samplesheet, simulated WGS score + output and a PoN worklist. Returns the Path.""" + d = tmp_path + _ecs_table(1.0).to_csv(d / "PLCB2_ecs_1.offtarget_analysis.tsv", sep="\t", index=False) + _ecs_table(0.8).to_csv(d / "PLCB2_ecs_2.offtarget_analysis.tsv", sep="\t", index=False) + + pd.DataFrame([ + ["PLCB2_ecs_1", "ecs", "PLCB2_KO", "/abs/ed1.cram", "/abs/ctl.cram", "/abs/t.vcf", ""], + ["PLCB2_ecs_2", "ecs", "PLCB2_KO", "/abs/ed2.cram", "/abs/ctl.cram", "/abs/t.vcf", ""], + ["PLCB2_wgs_1", "wgs", "PLCB2_KO", "/abs/w1_tumor.cram", "/abs/w1.cram", "", "/abs/w1.hard-filtered.vcf.gz"], + ], columns=["sample", "datatype", "guide", "edited_cram", "control_cram", "target_file", "vcf"] + ).to_csv(d / "samplesheet.csv", index=False) + + # simulated SCORE_HOTSPOTS output: chr12 detected, chr7 below HI, chr1 nothing + pd.DataFrame([ + ["PLCB2_wgs_1", "chr12", 32679408, 1, 0.16, 0.0, 1, 0.85, 0.90, "LIKELY EDIT", 42, 32679408], + ["PLCB2_wgs_1", "chr1", 1000000, 3, 0.00, 0.0, 0, 0.00, 0.00, "ARTIFACT (shape)", 40, 1000000], + ["PLCB2_wgs_1", "chr7", 5000000, 2, 0.03, 0.0, 1, 0.30, 0.12, "POSSIBLE — review", 38, 5000000], + ], columns=["sample", "chrom", "start", "min_mm", "indel_frac", "ctrl_if", "modal_len", + "conc_ratio", "score", "verdict", "spanning", "modal_pos"] + ).to_csv(d / "wgs_hotspot_scores.csv", index=False) + + # simulated PoN worklist: chr12 hit 1bp off a known hotspot, chr3 novel + pd.DataFrame([ + [1, "PLCB2_wgs_1", "chr12", 32679409, "A", 0.16, 0.90, "LIKELY EDIT"], + [2, "PLCB2_wgs_1", "chr3", 9999999, "AT", 0.20, 0.88, "LIKELY EDIT"], + ], columns=["rank", "sample", "chrom", "start", "alt", "dragen_af", "score", "verdict_pon"] + ).to_csv(d / "worklist_pon.csv", index=False) + return d + + +# --------------------------------------------------------------------------- +# Synthetic aligned-read workspace for find_edited_reads.py +# +# The glue fixtures above are pure tables; the read-level tagging path needs +# real alignments. This builds the smallest workspace that reproduces the two +# things that make tagging non-trivial: +# +# * two targets 200 bp apart -- far enough that pyranges clusters them +# separately (slack = --target-window = 150), close enough that their +# +/-150 fetch windows overlap, so some reads are visited twice; +# * a read pair sitting in that overlap which one target calls Unedited_WT +# and the other cannot evaluate, i.e. the tag-conflict case. +# --------------------------------------------------------------------------- + +ECS_CHROM = "chr1" +ECS_CONTIG_LEN = 3000 +ECS_TARGET_A = 1001 # 1-based; the edited site +ECS_TARGET_B = 1201 # 1-based; a quiet site +ECS_DEL_LEN = 5 +ECS_N_EDIT = 12 # read pairs carrying the deletion +ECS_N_WT = 8 # read pairs spanning target A cleanly +ECS_N_DUP = 2 # duplicate-flagged pairs +ECS_N_LOWMAPQ = 2 # MAPQ below the default floor of 20 +ECS_N_MISMATCH = 2 # NM above the default ceiling of 4 +ECS_N_OVERLAP = 6 # pairs inside the window overlap, spanning neither target +ECS_N_SPAN_B = 3 # pairs in the overlap that DO span target B (conflict case) + + +def _write_ecs_fasta(path): + import random + random.seed(7) + seq = "".join(random.choice("ACGT") for _ in range(ECS_CONTIG_LEN)) + with open(path, "w") as fh: + fh.write(f">{ECS_CHROM}\n") + for i in range(0, ECS_CONTIG_LEN, 60): + fh.write(seq[i:i + 60] + "\n") + import pysam + pysam.faidx(str(path)) + return pysam.FastaFile(str(path)) + + +def _ecs_pair(fasta, name, r1_start, r1_cigar, r2_start, mapq=60, dup=False, + r1_nm=0, r2_nm=0): + """One properly-paired FR pair (R1 forward, R2 reverse) with real sequence.""" + import pysam + + def qseq(start, cigar): + out, ref = [], start + for op, ln in cigar: + if op == 0: # M + out.append(fasta.fetch(ECS_CHROM, ref, ref + ln)); ref += ln + elif op == 2: # D + ref += ln + elif op == 1: # I + out.append("A" * ln) + elif op == 4: # S + out.append("T" * ln) + return "".join(out) + + span = r2_start + 100 - r1_start + reads = [] + for is_read1, start, cigar, mate_start, nm in ( + (True, r1_start, r1_cigar, r2_start, r1_nm), + (False, r2_start, [(0, 100)], r1_start, r2_nm)): + a = pysam.AlignedSegment() + a.query_name = name + a.query_sequence = qseq(start, cigar) + a.reference_id = 0 + a.reference_start = start + a.mapping_quality = mapq + a.cigar = cigar + a.next_reference_id = 0 + a.next_reference_start = mate_start + a.template_length = span if is_read1 else -span + a.query_qualities = pysam.qualitystring_to_array("I" * len(a.query_sequence)) + a.is_paired = True + a.is_proper_pair = True + a.is_read1 = is_read1 + a.is_read2 = not is_read1 + a.is_reverse = not is_read1 + a.mate_is_reverse = is_read1 + a.is_duplicate = dup + a.set_tag("NM", nm, value_type="i") + a.set_tag("MC", "100M", value_type="Z") + reads.append(a) + return reads + + +def _build_ecs_cram(fasta, fasta_path, out_bam, reads): + import pysam + header = {"HD": {"VN": "1.6", "SO": "coordinate"}, + "SQ": [{"SN": ECS_CHROM, "LN": ECS_CONTIG_LEN}]} + reads.sort(key=lambda r: r.reference_start) + tmp = str(out_bam) + ".tmp.bam" + with pysam.AlignmentFile(tmp, "wb", header=header) as out: + for r in reads: + out.write(r) + pysam.sort("-o", str(out_bam), tmp) + Path(tmp).unlink() + pysam.index(str(out_bam)) + # production opens its inputs as CRAM, so hand the caller a CRAM + cram = str(out_bam)[:-4] + ".cram" + with pysam.AlignmentFile(str(out_bam)) as src, \ + pysam.AlignmentFile(cram, "wc", template=src, + reference_filename=str(fasta_path)) as out: + for r in src: + out.write(r) + pysam.index(cram) + return cram + + +@pytest.fixture +def ecs_reads_workspace(tmp_path): + """Synthetic reference + targets VCF + edited/control CRAMs for the ECS caller. + + Returns a dict of paths plus the read counts the tags should reconcile with. + """ + pysam = pytest.importorskip("pysam") + d = tmp_path + fasta_path = d / "ref.fa" + fasta = _write_ecs_fasta(fasta_path) + + header = pysam.VariantHeader() + header.contigs.add(ECS_CHROM, length=ECS_CONTIG_LEN) + targets = d / "targets.vcf" + with pysam.VariantFile(str(targets), "w", header=header) as vout: + for pos in (ECS_TARGET_A, ECS_TARGET_B): + rec = vout.new_record() + rec.chrom = ECS_CHROM + rec.pos = pos + rec.id = "." + rec.ref = fasta.fetch(ECS_CHROM, pos - 1, pos) + rec.alts = ("N",) + rec.filter.add("PASS") + vout.write(rec) + + del_cigar = [(0, 60), (2, ECS_DEL_LEN), (0, 40)] + edited = [] + for i in range(ECS_N_EDIT): + edited += _ecs_pair(fasta, f"edit{i}", 940, del_cigar, 1180, r1_nm=ECS_DEL_LEN) + for i in range(ECS_N_WT): + edited += _ecs_pair(fasta, f"wt{i}", 940, [(0, 100)], 1180) + for i in range(ECS_N_DUP): + edited += _ecs_pair(fasta, f"dup{i}", 940, [(0, 100)], 1180, dup=True) + for i in range(ECS_N_LOWMAPQ): + edited += _ecs_pair(fasta, f"lowq{i}", 940, [(0, 100)], 1180, mapq=3) + for i in range(ECS_N_MISMATCH): + edited += _ecs_pair(fasta, f"mm{i}", 940, [(0, 100)], 1180, r1_nm=6, r2_nm=6) + for i in range(ECS_N_OVERLAP): + edited += _ecs_pair(fasta, f"both{i}", 1080, [(0, 100)], 1220) + # R1 lands in both padded windows: target A cannot evaluate it, target B + # calls it reference. Unedited_WT must win, and it must be written once. + for i in range(ECS_N_SPAN_B): + edited += _ecs_pair(fasta, f"spanb{i}", 1150, [(0, 100)], 1220) + + control = [] + for i in range(ECS_N_EDIT + ECS_N_WT): + control += _ecs_pair(fasta, f"ctl{i}", 940, [(0, 100)], 1180) + + return { + "dir": d, + "fasta": fasta_path, + "targets": targets, + "edited": _build_ecs_cram(fasta, fasta_path, d / "edited.bam", edited), + "control": _build_ecs_cram(fasta, fasta_path, d / "control.bam", control), + "n_edit_reads": ECS_N_EDIT, + "del_len": ECS_DEL_LEN, + "total_records": len(edited), + } diff --git a/tests/fixtures/bnd/bnd_review_queue.tsv b/tests/fixtures/bnd/bnd_review_queue.tsv new file mode 100644 index 0000000..8778eb3 --- /dev/null +++ b/tests/fixtures/bnd/bnd_review_queue.tsv @@ -0,0 +1,6 @@ +sample_name chrom pos chrom2 pos2 strands cut_dist reads control_reads_at_event site_start site_end is_target site_total_reads bin partner_bin n_partners span interchromosomal far_end_on_target why_dropped call +BNDDEMO chr1 2000 chr1 6000 -+ 2 3 0 1980 2020 1 40 chr1:2 chr1:6 1 4000 False 1 multi-cut inversion +BNDDEMO chr1 2002 chr1 5999 +- 2 4 0 1982 2022 1 40 chr1:2 chr1:6 1 3997 False 1 multi-cut inversion +BNDDEMO chr1 5998 chr1 2001 -+ 2 3 0 5978 6018 1 40 chr1:6 chr1:2 1 3997 False 1 multi-cut inversion +BNDDEMO chr1 6000 chr1 2000 -+ 2 4 0 5980 6020 1 40 chr1:6 chr1:2 1 4000 False 1 multi-cut inversion +BNDDEMO chr1 6000 chr1 2001 +- 2 4 0 5980 6020 1 40 chr1:6 chr1:2 1 3999 False 1 multi-cut inversion diff --git a/tests/fixtures/bnd/control.cram b/tests/fixtures/bnd/control.cram new file mode 100644 index 0000000..58b0aeb Binary files /dev/null and b/tests/fixtures/bnd/control.cram differ diff --git a/tests/fixtures/bnd/control.cram.crai b/tests/fixtures/bnd/control.cram.crai new file mode 100644 index 0000000..de05249 Binary files /dev/null and b/tests/fixtures/bnd/control.cram.crai differ diff --git a/tests/fixtures/bnd/cram_map.tsv b/tests/fixtures/bnd/cram_map.tsv new file mode 100644 index 0000000..204ffb2 --- /dev/null +++ b/tests/fixtures/bnd/cram_map.tsv @@ -0,0 +1 @@ +BNDDEMO edited.cram control.cram diff --git a/tests/fixtures/bnd/edited.cram b/tests/fixtures/bnd/edited.cram new file mode 100644 index 0000000..d5d20a9 Binary files /dev/null and b/tests/fixtures/bnd/edited.cram differ diff --git a/tests/fixtures/bnd/edited.cram.crai b/tests/fixtures/bnd/edited.cram.crai new file mode 100644 index 0000000..0c66421 Binary files /dev/null and b/tests/fixtures/bnd/edited.cram.crai differ diff --git a/tests/fixtures/bnd/ref.fa b/tests/fixtures/bnd/ref.fa new file mode 100644 index 0000000..6bcea65 --- /dev/null +++ b/tests/fixtures/bnd/ref.fa @@ -0,0 +1,135 @@ +>chr1 +TTTCCTCATGCAATTCAAAACCATGTCCGTAATGTAGGCGAAATAGTAAACCATTTTACG +GAGGATACCAAATTCCTCCTTATTCAGGACCTAACCTGAGGTAAACCAGGTCTCTCCGCC +CCCTTATAAAAGCTGTTGCACCTAGCCAAGTTCAACGGCAGCTGCAATGGAAATAGGCAA +TGACGGATATATATTAAAAAGTGTTTTAAGATACATTGAGGCCCGTTCGTGCTCCTCGCC +CTGAAGCATTGCTTTGTGAAGAGGGACTTCAGCCAATAGACCTGCATACCGGCTCATTCT +TCATGTGCAACCTAGGGAGAATGTGTACATACGCTCTTACTGCGGTCGCGTCTAATAATA +TACATTTGCTTCGTTGACTAGCAACCCAGGGCTATAGCTATTCCCCCCGCGGCCCACCCA +GTATTCCTAACGGAGCATAAATCCCACCCGAACTAAGTTTGTCGAACCTTGGTCCAAGAT +CGGGACTCGGTCTCCAGGTAAGACGGGCTCATTCATAAACGTTACTAAGGGGTATAATCT +TCTATTTGTGGGTGGGAACACTTAGTAGACTTGCAATCCAATTACAGCAGTCTTGTGCGC +CTAGGGGCGCCCCAAAGGTAAACGAACCGTTGCGGTCAATCTTGTCGCGGCTGATGAATT +TGAAGCAGTGGCCGGGAGTGTGTGCTCAGGAGTTCGTCCCATGACACGATAGAGAGAGAA +CATCCTGTTGGGCTTAATGATATAGAATTCCCTCGCTTGGATGAGCCATATAGACCGCCT +CTCGTCGTGTTGATCTACCTGACATGTCTCTCGCGCGACCACCCAGGATTAGACTCATCA +TTCGGGTAGTAGACATTATATTCGATACCGTGGTAGCCTAGGGTGTTAACACCCCTATAA +CACATTAGTCCCTTGTATGCAGGCGGTATCGGACGGCGCCCACACCTTGGAGGTATCCAG +CGCAAGGCGCCATATCCGTACCTTACTATCGCGCGAACTTATGTTGTTTTAAGTTAGAGT +TGGACATCTATACGTCAGTCCTAAACATAGCGAGCATTTCGCAGATGGGTCTCCGACGGT +ACCCCAAGGGTCGTTACCGACGCCGGGACGCCGCATATAAAGGTACGCCCGACCATTATA +CAGGTAGCCATCTGCGTCTGACATCGCATTTGAAACCCAGTAGGTACTGCCTTAGTTGCA +CTCCTAACTCATGTTAACGGACTTACGGGCACTAGCTTCTTACTGCCCTCTCTGTTTCTC +TTAAGGGACGTCGAGACGCCAAGTTATGGAGTCTACCCACGTTTCGGTTCCGTTCTGCAG +GGCCAATAGACGAGCGATATTATTGGTGCCTCTCGCAGTCTGGATAGATGATTGTGGAAA +GGGGGCTTGGACAATTAGATTTTACGGTGTACCGCGCCATACTAGGGAAGCTCCCCGTGG +TGGTCCGGCCAAAGATTACTTAGGTTGGGGCGCCTCGCCCTGCCATCGGTGTTCACAACG +GATGATCGAGTGCTTCTCGCTCAGTTACGAGCGTGGCATCGGACAAGAACGTCCTTATGT +ACGGCGCTACACAAGGAGATACAGAGCTTGATTTGAACCGTGGGTGGGAGAGGCCCACGC +CGACCGGCTAATATAGCACGAAGTTCTTCGATGCGACTACGTTAATTTTTCTAATTGAAG +CTGGGCTTACTACCCAAGGACAGGGTCATCTGCAATTCATAACGCAGAGCGATCTATTAA +CGCTTAGGGCCCCCTACGAGGGGCAACGGTCCAGTGTGTCAAGTCTAGAGATCTTCTCTA +GTGGTGGACATGCGTTGGAAATCAGAGAGACTAGCTGTACATTCAAATTCCTGCTAAACG +TATTCAGGAAGTAAGAACCAGGGCCTTACTCATCACCCTATACCATCGATATGATTGACG +ATGTCCATGGGCGATTTGTGTAAGACTGTCAGAGGTCTAGTAAGCGGGCAGCTAGAACGG +TGTAGAATCGGAGCCGGATATACGACATTGACATCTTTATGAAGAATGACATGCACGTTA +TTCTTTTTACGCAGCGTTTTGCTTGATCGGTAGAGTCCTACTTTTACCAGCAGCTGTCTG +GACCCCGACCCGGGAGGACGACGGGGCGTAGAGGCTCCACGGATGCTTGGCGGCAAAGAA +ACGGGCAACATCATCAGTCATCTCATAACGGGCGCCTATGCACAAAGGATACCAAGACTC +TGGCGTACGAGGGTCTCCCCGTTCGCCGGACGCAGGCACAACTCATCGGAATCTCGCTGA +TAATATATCCACCTCGGCCCGACCCCTGGAGCACGAAGGCAGTGAACAAGCCGAGTTGTT +ACCTATTAGCACTCAACTTATACGACGAGGGTGGCGCTTTGGTCCTGCGCTCGGAAGTAT +TATTGTTAAGTTACAGTAAGACTAGCATGAATTCGGGCCTGCCGGCATGCAAGTTACAGG +TGGCGCATTTAGTTCTGAACTCCACTGTGCAGAGGAAGGTAGAGCTAAAATCGCGCTGTA +GAGGTCTCTAATTTTGTAACCACCGGGAATATATCGAAAGTTCTTCTCTAACCATTATAT +TACCTGAGGACTTCGAAGTCGTCTTGCATGATTTTTACGCTTCGCAGTATGTGATCTGCT +ATACTAGGTGGTCACGAGGTGCTTGTCAATTTAGGTAAAGCGCTGCGAGTTCGCCCAAAA +CGATAAGGCGGGCTGATGGCCGCGTTCCCTGGCGCTGACTAAAAGAGTTAATACGACGAT +GCAGCGACGGGAAGGTCGCACATCGTCTTGGTTCGAGGTAATGCGTGTATCCAACGTGAG +GAAACTATTACATCTCTGAACCACGGCACGCCCAGACCACTGGCGAAAGTGTCTTACGGC +AAGCCTGATGTAATTTAGAAAGGGTCCCATCTCTAAACCTTCTTCGAGACGCAACTCAAC +GAACGCCTATCACACTTCTATATGAACGATTGGCCTGAAGGGGCACTGGAATGGCTGCGT +TACATGCGTCGTAGCGCGCTGAAAAGGTAATCTCTTTGGTCGTCCCCATTCCGAGAACTG +GTGAAATCAACACGCAGAGGTCAGGTGTTCATTGTCGACGGAGATTGTTTTGAAATACTC +TACCTGGGTCAACTCCCCAACCGTCAGAGCTAAAGTTCACTTGGTCATCTCGATACCGCC +GCGCGTCTAAACCCTTTGCGACCCCATTCGTGAGGTGGCGTAGTGACGTACAGTCAAGTC +GTGGTACGTCAATAAACTTTGGATTGGCGACGACAACTCGGGGATATCGACTTACACGAT +CTCGGAGTATTACAGGCTGCTTAGATACCTACTCTTCTCAGCTCAATCGACGGTTATGTG +CCATGAATCGAAGCGAGCATGCCAGATCCACCTGTAGATTGATAGAGGACGCCATGTAGC +ATAAGGGTTATATCTGTCTAAGTGGTGGATAGTTAGAAGGCACATAAGATCATATTAGTG +TCGTAATCTACGCTAGTAGCTGATTAAATTCGCATTATCGACGTTTTCGACCCTTGGGAC +ACACACAAGATGTCGGGCCGCCCAATGAAATATATCGTGAATTTCCTTACATCCCCTCAC +GCGAGAGAATTATTACGGAAGTTCACTTAGGATGGAAGTAATGAGCGCGAGTGGTGGATG +GCGTAGCCACATTCTGGATTAAGACCGTTGCGGAATACCACATTTATGAATAGCTGCTGG +GGATGCCAAATATCAGTGGCACACACTTTGGGCTATAGACCCGCCGCTACTAGCACGAAG +AGACTCCAGGACTAGTACTGATCTCTCCATGCAGTAAATTCCATCACCTAGTTAACGCAG +CGTCTTACTCTCGGCATTTTCGGTGCGGACAGTATTCATTTAATCTACAATACAAATCGA +ACGTACAGCACGTCTCCATAATCAGGCCCGGGCGCGCAGAGAACCAACCTGCGACCCGAT +GCTCCACGATCGACCGATGAGATTTCACGCACACCTTCGTCGAGGCGGGTTCGCTGCTTA +AAGCTTGGAATTTCTGGCACCCCCGATACTATCGGTGATATGCGGACTGGTCTCCTCTGG +TTCCGGGTTTGGTTTTTCTCCCAGAAAGACTATACGAATGTTCAACTGGTATTTCCCTTG +CAACACGTACAGAGCTTCCGAAAAAAACGTGCTCTCTCAACACCGGAGTTGATTGATGTG +AGTCGATGCTGTACGTTGATTGGTTAGCATCCACGGATCATATCACTACCCACGTTTTTT +GCACAAGCCTGTCCGACGTGTATATTTGGCGTCTGGAGTCAAGACAGGCATCTGGCTGAT +TTACGAGTAGTCCCGGTCTAGTCGCATATTCGGGGCCTTCAACGTGTCGGGCCCTAGGGC +TCATGTTTCTAAGGTGATATATAACGCCTTCGGGGGCAAGTAACTGCCTGAGACATACTC +GTGGGAATCATCATGTCGCTACTTAAGATTGGCGGGTTAGAATGAATTAGTCTTTCACCT +GTTTTATCGCATAATGATCGCTATCTACCTCCTGTCCGAACGTTCATGAGAAACGCACAG +AATTACGATCTTACGACTCTGCATAGAATTATTTCGTCGTTGAGTCCTCGGGAGACAGTA +GTCAGTTACAATTAGCCCTGGTGCTGGCTGGGAGGCCCATTGGGACATGGATGTCTAGTA +GAGAAAATCGAGAACTCCATTTGATAAAATTCCCTCGCGATAATGATCTTCAGAGCTCTG +TATTCCTGAATCTATCCTCGCCACCACGCGGCTCTAGAGTACGCTATTTGCGACTAATTG +CTCTTGGAGCCGCTTAGAGTTAAGTATTGGCCAGCGTAGCCTTTGATGATCGTGTACACT +CTCCAAAGCATGGGCCAGGGGACGGGGCAATTCAAGGAAAGCTAACCTACGACAGAAAGC +TGCAAACGCCCCTCACAGATCAGCTAAATCAAAGTTTGGCCGACACGTTTCTCGTTGATC +GAGAGACGTACCGCCACACAGTCAAAAGCTGAGGCACTGACGAGTGCCACGGACATATGC +CAAAACGAGGTTAATCCGGATATTCAGGATTCTGTTGAGCGCCTGTTTGGGCACGCCAAG +GGTAATTTGATCCTAGTCGTATATACGACAACGGACTCTAAGTCCTGACTGGATGAGAGC +GACGCTTATGCCAAATGGTATGGAGACGGAACACGCTCGCGCGAAGATGATGTGGGCGAT +ATCTCAAAATAAGTACAAAACCCACACTTGAGAATTAACTGTTTCATATAAAAGGCCCAA +GTTATAGCACCCGCCGCTCTAATTATTCAGAAAGAGTTATTGATCACACAGATTATACCG +TTAATTTGTGTTATCTCAGCTTTGCTCCTCGAGTGTGCCGCTGTATTATTTGACGCTTTG +AACTGCTGCATCTTAGAAGTTGCTTAGGCGATATGCATGGCGTGCTGGTTTGGTTTAAAG +TACGGCGTGACTTTACAAACCTGGCAGCTTTGGATAATAACGTTCCGGGCGTCTGACGAA +ACGCTACTTGCAGGCGTCGATTACGACATACATGTTCCGACATCCTATAGGTTGTATCAT +GCTCAGTACCAGTGTTATCGGCTCGTGAGGGTAATTCTTCGGAAACGAGGCACGGTCTGA +GGGGCCAACACGTGTTGGAGACTATGAGTCGTGTAGTTAGTGAGGATAGGGGGAGTACAC +CGGAGGCAGACATTATTAGATACAGCATCCTACCGTATAAAAGCACACATGTCGCGGTCT +ATACAGAGCCGCTTTCCCCTTGTGTTGAACTATTAATAAGGCCGGACAGTTGGTGCTGTG +GTCTCTAGTTACTTCAGTGAATCTAAGGGGCTAACTCCCCATCAATTCGAAGTGTCACGT +CTGGACATCGAGAGCTTAAGGAGACCCGGCACCGGTACTGGCCGGATTTGGCCTAAAGGG +GTAATGGTGACCAGCTTGGTACCCCAAGATACACATTCTGCCGCGCAAAACCACGGCCTG +GTACCATTGGTCTCCCCGATAGCCGCAGGTGGTCCGCCCTCTATCGCTTAGTATCACACG +GGGTCCTGGCAGATTCAGGACACAACCAAATAAATGGCAAAGGCCTCATACGGAATATCG +TCTCGGTAGTTATCCAGCAGCGTTCGTTCATCATCCAAAGGACCGCACGGACATTTACCA +GCAGCTCAATGCGATGGGCGTCTGTTGTCACGGGACAAACGGTCCCCTGTAGATCAAGAG +GACGTCACGATAAAGCTCCACAGGGAGCCCATAAGAGCTTAAACGCGTCCTAGGCCTTGT +CCTACCATGCTGCGACGGTCCGATGGTTTCACGTCAACGGTACCCTATAATTCCGCTTCC +CTGAGGACAATCTACTATGAGGTTGTAGAGCGTCTATCAATGCTTGGTTGGTACTCATCG +CGAGATAAATGATGGACTCAAACGCATATCGCTCTAGTGCATAGTTGCACCCGCGGGGGA +GAGTGTGATAAAAAGACTGCTCCGCGGTTGCCGCGGCTAACACACCTACGACAAGCGCAC +GGACTAATGCGTTCGGTGGTTTACTGAATCCGGCTTAGGCTTAGTTGCTTAATGATTTAT +CAGGCATGTCCATGATATGTTCAGCTCTGGACAAAACGATTCTCTGTTGTCACGGAGCGC +TATGCCAATCATTGTGATGTCACTAACACCCGGACTGTCTGGAACGAACCTAGAGGCAAC +AGTGCCCGAGAATGTGCCCTCAAAGTGTGCCAAAATTTTTCTCAACTGTGAACCGGGGAA +GGCTGACGAACCAACCGTATGTAGTCTCCCCGTTATCGTAAAATGGGACCATGTCATCCC +AATAATCTGTTTAACAATCCTACTGGTCTGGTTTTAGAATTGATGCTTTCGTTGCAAGTG +AGCTATTCTACTGAACTGGATCCGGCCCGTAGGTAGATGACGCGATCAAGGATTATACAC +TGGCGTACAATTACGTCCTGGTAGGCAGGGGCCTTCAACTGCAGACTCAACGGCGTGCCG +TTGGCACGAGCAAACTTAACGACATACTTAGCAGGTTAAACTTGCCCATCTGGGTTTATA +ATCACAGGGGGCAGATTAGTTGCCTCACGCTTGTATGCCTTCTAAAGGGGCACCTAGGTT +AAAATCCCTCCTAGGGAGTCGTGAGCTTCTAGAACGGTTCAGCGCAATTGCTGCGGGTCG +CGTTGGATGATGACGGGAGTCGAAGACTAACAGGATAAGCCCTTTCCAGTTGCCGGCCGT +ACCTGTGCCGTTGACGTTTGAGCACGGGGCGCATCCAGACTATGCGGCCCACAACTAAGC +AGCGCACCCCCAAGGCTCCACCGGCAGGTTTTAGGTATGCCTCGGGCGCGCTTGGCTCCC +GCCCTCGACAGGCGGCTGTGCAGGCGACGGGGATTGAAGGGCGAAATTCCCTGGCGAGAT +AAGGGTCTCAACCTGGTCGCGTTTCGCACCCCATGCGCCTTCGATCCGAATGCGGCCTCG +CCCCATCGGCTCATCAGATATTCCTTACCAACTTGTTGTCTAGTTAACGGACATGTTCGG +CTCACCCGTGGATCAATTAGCCGCTGTATCAAGTCACCACACAACAGAATCCTTATGCGA +CTCAGATTTGGTTACAATTTGCCCGCACAAGCGTGGGCAGTGCAAGCACCTGCCTACAAG +CTGTCATTTGCAGCTTTAGAAATGTCCGAGTGGCGAAACCCTCCGCCATCTGCGCAATAG +CCTGCCGGTGGAACAGGCTGAGCTTATTAATATTGCCGGCCTCATCCGGGATCAATGGTA +AATGAGTACCCGTCTGGGATTAGTGTACCTCCTGTGACTCTCGTACTAGTTCCAATCCTC +TTCTTATCCTTCGTATAGCGTAATGCGATTTGTATTGCTGACCCATGGATAAATATAGAT +TTAAGTCCATGGCTTGCGCCAGCAGTGAGGCTTCAGGCGTGAGTTTTGCATGAGACTGCT +GGGCGCCAAAGCTTGCATAC diff --git a/tests/fixtures/bnd/ref.fa.fai b/tests/fixtures/bnd/ref.fa.fai new file mode 100644 index 0000000..156b290 --- /dev/null +++ b/tests/fixtures/bnd/ref.fa.fai @@ -0,0 +1 @@ +chr1 8000 6 60 61 diff --git a/tests/fixtures/bnd_review_queue_cart.tsv b/tests/fixtures/bnd_review_queue_cart.tsv new file mode 100644 index 0000000..25b794e --- /dev/null +++ b/tests/fixtures/bnd_review_queue_cart.tsv @@ -0,0 +1,26 @@ +sample_name chrom pos chrom2 pos2 strands cut_dist reads control_reads_at_event site_start site_end is_target site_total_reads bin partner_bin n_partners span interchromosomal far_end_on_target why_dropped orientation call +ARID4A-KO-DNA chr14 58301619 chr14 58330081 -+ 1 3 0 58301616 58301617 1 123 chr14:58301 chr14:58330 4 28462 0 1 inverted multi-cut inversion +ARID4A-KO-DNA chr14 58301623 chr14 58330079 +- 5 4 0 58301616 58301617 1 123 chr14:58301 chr14:58330 4 28456 0 1 inverted multi-cut inversion +ARID4A-KO-DNA chr14 58330078 chr14 58301622 -+ 2 3 0 58330078 58330079 1 129 chr14:58330 chr14:58301 1 28456 0 1 inverted multi-cut inversion +ARID4A-KO-DNA chr14 58330082 chr14 58301619 -+ 2 4 0 58330078 58330079 1 129 chr14:58330 chr14:58301 1 28463 0 1 inverted multi-cut inversion +ARID4A-KO-DNA chr14 58330082 chr14 58301620 +- 2 4 0 58330078 58330079 1 129 chr14:58330 chr14:58301 1 28462 0 1 inverted multi-cut inversion +BRAF-KO-CART-DNA chr7 140801459 chr7 140834644 -+ 3 3 0 140801460 140801463 1 165 chr7:140801 chr7:140834 1 33185 0 0 inverted inversion at cut site +BRAF-KO-CART-DNA chr7 140801460 chr7 140834645 +- 2 7 0 140801460 140801463 1 165 chr7:140801 chr7:140834 1 33185 0 0 inverted inversion at cut site +IKZF2-KO-DNA chr2 213147792 chr2 213022045 -+ 1 5 0 213147788 213147790 1 176 chr2:213147 chr2:213022 1 125747 0 1 inverted multi-cut inversion +IKZF2-KO-DNA chr2 213147793 chr2 213022046 +- 2 7 0 213147788 213147790 1 176 chr2:213147 chr2:213022 1 125747 0 1 inverted multi-cut inversion +KLF12-KO-DNA chr13 73845933 chr13 73846348 -+ 3 6 0 73845934 73845937 1 206 chr13:73845 chr13:73846 1 415 0 1 inverted multi-cut inversion +KLF12-KO-DNA chr13 73846347 chr13 73845934 -+ 0 7 0 73846345 73846346 1 186 chr13:73846 chr13:73845 2 413 0 1 inverted multi-cut inversion +KLF12-KO-DNA chr13 73846349 chr13 73845933 +- 2 4 0 73846345 73846346 1 186 chr13:73846 chr13:73845 2 416 0 1 inverted multi-cut inversion +KLF12-KO-DNA chr13 73846349 chr13 73845934 +- 2 3 0 73846345 73846346 1 186 chr13:73846 chr13:73845 2 415 0 1 inverted multi-cut inversion +PDCD4-KO-CART chr10 110887715 chr10 110890582 -+ 1 15 0 110887712 110887713 1 176 chr10:110887 chr10:110890 3 2867 0 1 inverted multi-cut inversion +PDCD4-KO-CART chr10 110887716 chr10 110890582 +- 2 13 0 110887712 110887713 1 176 chr10:110887 chr10:110890 3 2866 0 1 inverted multi-cut inversion +PDCD4-KO-CART chr10 110890582 chr10 110887716 +- 2 7 0 110890578 110890579 1 145 chr10:110890 chr10:110887 1 2866 0 1 inverted multi-cut inversion +PDE7A-KO-DNA chr8 65782787 chr8 65779781 -+ 1 3 0 65782784 65782785 1 171 chr8:65782 chr8:65779 1 3006 0 1 inverted multi-cut inversion +PDE7A-KO-DNA chr8 65782788 chr8 65779781 -+ 2 3 0 65782784 65782785 1 171 chr8:65782 chr8:65779 1 3007 0 1 inverted multi-cut inversion +PDE7A-KO-DNA chr8 65782789 chr8 65779781 +- 3 4 0 65782784 65782785 1 171 chr8:65782 chr8:65779 1 3008 0 1 inverted multi-cut inversion +RXRB-KO-DNA chr6 33197861 chr6 33198326 -+ 1 8 0 33197857 33197859 1 203 chr6:33197 chr6:33198 3 465 0 1 inverted multi-cut inversion +RXRB-KO-DNA chr6 33197862 chr6 33198327 +- 2 9 0 33197857 33197859 1 203 chr6:33197 chr6:33198 3 465 0 1 inverted multi-cut inversion +RXRB-KO-DNA chr6 33198327 chr6 33197862 +- 1 6 0 33198322 33198325 1 218 chr6:33198 chr6:33197 1 465 0 1 inverted multi-cut inversion +ZEB2-KO-DNA chr2 144399459 chr2 144429936 -+ 4 9 0 144399461 144399463 1 272 chr2:144399 chr2:144429 2 30477 0 1 inverted multi-cut inversion +ZEB2-KO-DNA chr2 144399460 chr2 144429937 +- 3 7 0 144399461 144399463 1 272 chr2:144399 chr2:144429 2 30477 0 1 inverted multi-cut inversion +ZEB2-KO-DNA chr2 144429936 chr2 144399459 -+ 1 6 0 144429933 144429934 1 197 chr2:144429 chr2:144399 3 30477 0 1 inverted multi-cut inversion diff --git a/tests/fixtures/ecs/control.cram b/tests/fixtures/ecs/control.cram new file mode 100644 index 0000000..40c5dad Binary files /dev/null and b/tests/fixtures/ecs/control.cram differ diff --git a/tests/fixtures/ecs/control.cram.crai b/tests/fixtures/ecs/control.cram.crai new file mode 100644 index 0000000..6eacdfe Binary files /dev/null and b/tests/fixtures/ecs/control.cram.crai differ diff --git a/tests/fixtures/ecs/edited.cram b/tests/fixtures/ecs/edited.cram new file mode 100644 index 0000000..a13a251 Binary files /dev/null and b/tests/fixtures/ecs/edited.cram differ diff --git a/tests/fixtures/ecs/edited.cram.crai b/tests/fixtures/ecs/edited.cram.crai new file mode 100644 index 0000000..3490010 Binary files /dev/null and b/tests/fixtures/ecs/edited.cram.crai differ diff --git a/tests/fixtures/ecs/ref.fa b/tests/fixtures/ecs/ref.fa new file mode 100644 index 0000000..a264198 --- /dev/null +++ b/tests/fixtures/ecs/ref.fa @@ -0,0 +1,51 @@ +>chr1 +GCTAAAGACAATTACATAACATACACGTCAGCACGAAACTTGTTGGCCCAGTGTGAATCG +CTTAAGGGTTAAGTAAGTGTGATGCATACGCCTTTACTTGCTGTGTCCACCCCATCGGAC +TGGCATTTTTATTACACTCAGAAACAGAACTCGGGTAATTTTGACAGGTCACGCAGAGGC +GCGCCCTCCTGAAGTGCGTGGACACTCGCTATGAATCTCTGATTTACCCACTCTGCCAAA +CTCCAGCGCGGTCAGTTCCATCACCCTAAGTAACCGAATAATGCGTTCGCTCTATTGACT +ACGACGCGCTCATTCCCTTGTCGGAGAGTTATGGAACAAGGACGCTGTCTGAGACTAGAA +GACAGATAGTGCACACGACCGGCGTCGGAGAAACTCTATTTGCCGCCTGACAAGTCAATG +CGATCCGTAGGGGCAGCGCAGTATGCCAAGACTATAGGCACTGTCGCATCACAAACGATT +AACTGATAAATGAGCCCTTTATGACACGGGCATATGACTGGTTTACGATAGTATGTCCAA +CGGCGAGCTTTACATTTGCTGTGAGAGGTACAGGGATTAGTGAGAAGCCGTGCGTATCAA +TTCGTACCTTGGGGGTCGTTACCACTCTGTTCCCACGAGCGGCATTTCTGGATGGCCAGC +TTTTGACATTTAATTTCACCCATAAACCAGCGTAAAGCTGCAAGTGGCTCCATGAACTTA +GCTGCTAGTGTCAGACTCGCCTCGGATCCTTACTACACTAACTTGAACGCCTAGTGGTCA +AAGAGTACTGGTAATCGTCGGTATCTATATAAGCAGGGGAGGGGAAACATTTGTTCTCAG +CCGGTGACTCCTAATGCTAAGACATTTCCCTTCAGGGGGGGCTCCCCCGCGATGCCATAA +ATCTGAGCAACCAGCTGAAGCAGGCACGACAGTGCGACATTATATCACTGTGGTAGGTTA +GCTTCATCTAATGTCCAACTAGCCGGCCAATTCGCATGATACCTCTCCATCTGACCCAAG +ATTGTGCTTGTTCAATTCTTCTTAACGTGATAACAGAATCAAACCTGCCAGGCGGTCGTC +GCGGACCTCGGTCGAAGTAGTGGTGCGGATCCAGGGGAACCGTTGACTCAAAAGGAGCTG +CCGTCCACCTAACGTGAAGTTCCAAAATCCCAAACCTCTCGAGATATTTATCCAGCAAGG +AGTGGCAACGCCCGCTGCTTTAATCGCTACCAAAACGCAAACAAAAGCATACCCAAAAGT +ACACGGGTGAGGGAGGTGATATAGTACAGCTACGAAGTATCTGGCGCCTCAATAGGATTA +TAGCGGTCTCTCAGGCTGCTTGCCGTCCGGCCCGGCCGCGACACTCCGGTGCAAGCTTAA +TTCGTACGTACTTCCCATTGGATCTCGTTTATCGATTAAGCCCGATCTAGGTTCCTAGAG +GTTAAATTGGACGTCTTCCCACTCCGTTGCTGCGTGTCTAGGCGGTTTAGCGTAAGCGAA +CAGGACCCTGCCTCAGCTCATAAGTCCTTATTCTCTCACGTTGTGTTACGAAAGATTCAC +TCGAGGTCGTGTGAGGGTTGGGCTAGCGGCAATTATGAAACTATCACATCACATAAGCGG +GCTAGATATAATTTAATCTTAATCCATAAAACACTAGCTCAGCAGTTGAAAAAATGGCTA +GGTTCCAGCTTTTGGGGAGACGTCTTTCTGAGGGTCAGCCGTGATTCCGATTCGATTAGA +CTGGTCCCCACGGGTCCATGAGTACGAGGAAACTCGGTATCGAGCCTAAAAGTTATAAGG +CATCTCGCCCAGGAAAGTAACGACGTATGGGTAGTTCTCCATCACCAGCTATAATGGCTA +GCGCACTCTCGTTCCAGGGCGTAGTTACACTGAGCGTGCCATGTCAGCATGCTAGCGTAT +CGCCCCCCAATGCCCCGCAATAGGGTAATTCGCCGACGAGTAAGCGTAGATTACACACCC +AGGAAACGATCTAGACAGATTGAAATCCCCTTCATTATAGGTCGTGTAGCGCTAGACAGT +CACCTTTAAAGGAAGAATCAGAGGCAAGATCTACGTGGCAGTCTCGTGTTGACGCCTTAG +CCGGTGGCGAACAGTATTGACCTGGCCGATGCTAATATTCTGATTTGGGGTTGATTTGCG +CTTCAGGCGCTAAAGTGGTTTTGAGTAACATGTCCTTTTGACGGGAGCAGGTCGCCTCAA +GATAAGAGTAAACCTGCCTACCAAAACTTTAAGCCGGCAGAAGCTTAACTATACCCACCG +ATGTGTACTCTGTTACACCGTCAGTGAGTGTAATGCTCTGGCTAGAGCCCACGCTTCCGG +CTTCGTCCTCGTGCTCCAAGTACGATACCGCAAGGCAGACGCTGGTTCGCAGGTATCTGA +CGAGCATACTCGCTAGCCTGTGAAGAACAAGCGATTCGAGTTGTACTCTCAGCCCGCACG +GTACGCCTTCCATCGGCCCGATCCTTCAGAGTCAAGGCAGTACGTTGGCAAATTAGGATT +TCGAGAGGCACAATCGGCCAGGTCGGCGCGGCAAATACTTTCGACCCCTTAATTCCGAAT +CGAATGATACCTGATGCTAGTTCTAAGGTGTCGGACCTACGTGCTTGACCCACGACGTCT +CAATATCAATTCCTACGATCAGAACTGACTACAGCGGAGACGGTAGAGGAACGGCTATAA +TAAGCCGTCGGTAAGCTTAAACTTCTTCAGGCGCACCGTGTTGGAGTGCACTACCGTGAG +GCAACTAGGCCAGGGCGTGAGGTGCCGCCCATTTTGCACGGGGACACGGTGTATGCGGAC +GCACATTCGACCACAAAGCACGAGACGGATTGCATAAGTTGTAAGGATGCAACCCAGGTG +CGCGTAGTGGGCGATAGCCTAACAACCGGCCCAGCTTCGTTCGAAAATGACTTTCAGAGT +CCGCGTGGTCCTGCGGAGATCCGTCACGATCTCGAACACGCGACTTATGTGACCAACCTA diff --git a/tests/fixtures/ecs/ref.fa.fai b/tests/fixtures/ecs/ref.fa.fai new file mode 100644 index 0000000..81232b6 --- /dev/null +++ b/tests/fixtures/ecs/ref.fa.fai @@ -0,0 +1 @@ +chr1 3000 6 60 61 diff --git a/tests/fixtures/ecs/targets.vcf b/tests/fixtures/ecs/targets.vcf new file mode 100644 index 0000000..ed9b414 --- /dev/null +++ b/tests/fixtures/ecs/targets.vcf @@ -0,0 +1,7 @@ +##fileformat=VCFv4.2 +##FILTER= +##contig= +##INFO= +#CHROM POS ID REF ALT QUAL FILTER INFO +chr1 1001 . A N . PASS . +chr1 1201 . A N . PASS . diff --git a/tests/fixtures/make_bnd_fixture.py b/tests/fixtures/make_bnd_fixture.py new file mode 100644 index 0000000..49ddb69 --- /dev/null +++ b/tests/fixtures/make_bnd_fixture.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python +"""Regenerate the committed breakend fixture in tests/fixtures/bnd/. + +modules/local/review_bnd_snapshots.nf.test runs the REAL junction renderer in the real +container, so it needs real CRAMs -- but a cohort CRAM is tens of GB and cannot live in +git. This builds the smallest synthetic pair that still exercises the thing the figure +exists to show. + + chr1, 8 kb + left breakpoint @ 2000 (1-based) + right breakpoint @ 6000 -- a 4,000 bp INVERSION, the multi-cut case seen 8 + times in the CAR-T cohort. The rows carry +-/-+, + the inverted adjacency, so the label must be + "multi-cut inversion" -- this fixture said + "deletion" until 2026-08-20, mirroring the bug in + review_filter_bnd.py's classifier. + + edited.cram + 20 clean pairs spanning each breakpoint -> the background + 14 SPLIT reads: primary clipped at one breakpoint, plus a + supplementary segment at the partner, carrying an SA tag <- the signal + control.cram + 20 clean pairs at each breakpoint, no split reads, no SA tags <- the contrast + +The split reads are the whole point. bin/pileup_snapshot.py used to drop +`is_supplementary` unconditionally, which hid exactly the alignments that constitute a +junction; `snapshot(..., keep_supplementary=True, highlight=...)` is what this fixture +proves is wired up. A fixture without SA tags would render two empty pileups and pass. + +The queue is real, not synthetic: tests/fixtures/bnd_review_queue_cart.tsv is the actual +25-row cohort queue. This script writes a 5-row queue in the same schema pointing at the +synthetic contig, because the nf-test needs coordinates that exist in these CRAMs. The +row-to-junction collapse is covered against the real queue in tests/test_bnd_snapshots.py. + +Run (from the repo root, in an env with pysam): + + python tests/fixtures/make_bnd_fixture.py +""" +import random +from pathlib import Path + +import pysam + +OUT = Path(__file__).resolve().parent / "bnd" +CHROM = "chr1" +CONTIG_LEN = 8000 +LEFT = 2000 # 1-based breakpoint +RIGHT = 6000 +READ_LEN = 100 +N_CLEAN = 20 # clean pairs per breakpoint +N_SPLIT = 14 # split reads carrying the junction +SAMPLE = "BNDDEMO" + +# 1-based -> 0-based +L0, R0 = LEFT - 1, RIGHT - 1 + + +def write_fasta(path): + random.seed(11) + seq = "".join(random.choice("ACGT") for _ in range(CONTIG_LEN)) + with open(path, "w") as fh: + fh.write(f">{CHROM}\n") + for i in range(0, CONTIG_LEN, 60): + fh.write(seq[i:i + 60] + "\n") + pysam.faidx(str(path)) + return pysam.FastaFile(str(path)) + + +def seg(fasta, name, start, cigar, *, supplementary=False, reverse=False, sa=None, + mapq=60): + """One alignment record. `cigar` is a list of (op, len); S is filled with the + reference base so the clip is not a run of a single letter.""" + out, ref = [], start + for op, ln in cigar: + if op in (0, 7, 8): + out.append(fasta.fetch(CHROM, ref, ref + ln)); ref += ln + elif op in (2, 3): + ref += ln + elif op == 1: + out.append("A" * ln) + elif op == 4: + # soft clip: sequence that belongs at the OTHER side of the junction + out.append(fasta.fetch(CHROM, max(0, ref), max(0, ref) + ln)) + a = pysam.AlignedSegment() + a.query_name = name + a.query_sequence = "".join(out) + a.reference_id = 0 + a.reference_start = start + a.mapping_quality = mapq + a.cigar = cigar + a.is_paired = False + a.is_reverse = reverse + a.is_supplementary = supplementary + a.query_qualities = pysam.qualitystring_to_array("I" * len(a.query_sequence)) + a.set_tag("NM", 0, value_type="i") + if sa: + a.set_tag("SA", sa, value_type="Z") + return a + + +def clean_pile(fasta, prefix, centre, n): + """Reads tiled across a breakpoint with no junction evidence.""" + reads = [] + for i in range(n): + start = centre - READ_LEN // 2 - 25 + (i % 10) * 5 + reads.append(seg(fasta, f"{prefix}{i}", start, [(0, READ_LEN)], + reverse=bool(i % 2))) + return reads + + +def split_pair(fasta, name, i): + """One read spanning the junction: primary clipped at LEFT, supplementary at RIGHT. + + Both segments carry an SA tag naming the other, which is what + bnd_snapshots.sa_supporters() keys on. The clip lengths sum to the read length, as a + real split alignment's do. + """ + keep = 55 + (i % 8) # aligned on the left side of the cut + clip = READ_LEN - keep + lstart = L0 - keep + 1 # so the alignment ends exactly at the breakpoint + rstart = R0 # partner picks up at the far breakpoint + + sa_right = f"{CHROM},{rstart + 1},+,{keep}S{clip}M,60,0;" + sa_left = f"{CHROM},{lstart + 1},+,{keep}M{clip}S,60,0;" + return [ + seg(fasta, name, lstart, [(0, keep), (4, clip)], sa=sa_right), + seg(fasta, name, rstart, [(4, keep), (0, clip)], supplementary=True, sa=sa_left), + ] + + +def build(fasta, fasta_path, out_cram, reads): + header = {"HD": {"VN": "1.6", "SO": "coordinate"}, + "SQ": [{"SN": CHROM, "LN": CONTIG_LEN}]} + reads.sort(key=lambda r: r.reference_start) + tmp = str(out_cram) + ".tmp.bam" + with pysam.AlignmentFile(tmp, "wb", header=header) as out: + for r in reads: + out.write(r) + sorted_bam = str(out_cram) + ".sorted.bam" + pysam.sort("-o", sorted_bam, tmp) + with pysam.AlignmentFile(sorted_bam) as src, \ + pysam.AlignmentFile(str(out_cram), "wc", template=src, + reference_filename=str(fasta_path)) as out: + for r in src: + out.write(r) + pysam.index(str(out_cram)) + Path(tmp).unlink() + Path(sorted_bam).unlink() + + +QUEUE_COLS = ["sample_name", "chrom", "pos", "chrom2", "pos2", "strands", "cut_dist", + "reads", "control_reads_at_event", "site_start", "site_end", "is_target", + "site_total_reads", "bin", "partner_bin", "n_partners", "span", + "interchromosomal", "far_end_on_target", "why_dropped", "call"] + + +def write_queue(path): + """5 rows describing ONE junction, in the cohort's own reporting pattern: + both directions, a few bp of jitter, both strand orientations.""" + lbin, rbin = f"{CHROM}:{LEFT // 1000}", f"{CHROM}:{RIGHT // 1000}" + rows = [ + (LEFT, RIGHT, "-+", 3, lbin, rbin), + (LEFT + 2, RIGHT - 1, "+-", 4, lbin, rbin), + (RIGHT - 2, LEFT + 1, "-+", 3, rbin, lbin), + (RIGHT, LEFT, "-+", 4, rbin, lbin), + (RIGHT, LEFT + 1, "+-", 4, rbin, lbin), + ] + with open(path, "w") as fh: + fh.write("\t".join(QUEUE_COLS) + "\n") + for pos, pos2, strands, reads, b, pb in rows: + fh.write("\t".join(str(x) for x in [ + SAMPLE, CHROM, pos, CHROM, pos2, strands, 2, reads, 0, + pos - 20, pos + 20, 1, 40, b, pb, 1, abs(pos2 - pos), + "False", 1, "", "multi-cut inversion"]) + "\n") + + +def main(): + OUT.mkdir(parents=True, exist_ok=True) + fasta_path = OUT / "ref.fa" + fasta = write_fasta(fasta_path) + + edited = clean_pile(fasta, "clnL", L0, N_CLEAN) + clean_pile(fasta, "clnR", R0, N_CLEAN) + for i in range(N_SPLIT): + edited += split_pair(fasta, f"split{i}", i) + + control = clean_pile(fasta, "ctlL", L0, N_CLEAN) + clean_pile(fasta, "ctlR", R0, N_CLEAN) + + build(fasta, fasta_path, OUT / "edited.cram", edited) + build(fasta, fasta_path, OUT / "control.cram", control) + write_queue(OUT / "bnd_review_queue.tsv") + + # The renderer takes CRAM paths from a map rather than staged files -- same reason + # production does: the queue names arbitrary samples and staging every cohort CRAM + # would copy TBs. Paths are filled in by the test at run time; this is the template. + (OUT / "cram_map.tsv").write_text(f"{SAMPLE}\tedited.cram\tcontrol.cram\n") + + print(f"wrote {OUT}: {len(edited)} edited records ({N_SPLIT} split), " + f"{len(control)} control records") + + +if __name__ == "__main__": + main() diff --git a/tests/fixtures/make_ecs_fixture.py b/tests/fixtures/make_ecs_fixture.py new file mode 100644 index 0000000..6b004b0 --- /dev/null +++ b/tests/fixtures/make_ecs_fixture.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +"""Regenerate the committed ECS fixture in tests/fixtures/ecs/. + +The nf-test suite runs the REAL ECS caller in the real container, so it needs real +CRAMs — but a cohort CRAM is tens of GB and cannot live in git. This builds a +deliberately tiny synthetic one instead: a 3 kb contig, two targets, 35 read pairs. +The whole fixture is a few KB, so CI can check it out and run the caller on it. + +The read construction is NOT duplicated here. It is imported from tests/conftest.py, +which is the single definition of what a synthetic ECS pileup looks like, so the +pytest suite and the nf-test suite can never drift apart on the fixture's meaning. + +What the fixture contains (see conftest for the constants): + + chr1, 3000 bp + target A @ 1001 -- the edited site: 12 read pairs carry a 5 bp deletion + target B @ 1201 -- a quiet site 200 bp away, close enough that the +/-150 bp + fetch windows overlap, so some reads are visited twice + + edited.cram 12 edited + 8 clean + 2 duplicate + 2 low-MAPQ + 2 high-mismatch + + 6 in-the-overlap + 3 spanning-B-only = 35 pairs / 70 records + control.cram 20 clean pairs at the same site (no edit) + +The awkward cases are the point: a duplicate, a MAPQ-3 pair and an NM-6 pair must be +classed as skipped rather than counted, and the pairs in the window overlap must be +written to the tagged BAM exactly once even though two targets both visit them. + +Run (from the repo root, inside the off-target container): + + python tests/fixtures/make_ecs_fixture.py + +Regenerate only when the read model changes; the outputs are committed. +""" +import importlib +import importlib.util +import sys +import types +from pathlib import Path + +HERE = Path(__file__).resolve().parent +REPO = HERE.parent.parent +OUT = HERE / "ecs" + + +class _PytestShim(types.ModuleType): + """Just enough `pytest` to import conftest.py outside a test run. + + The off-target container ships pandas and pysam but not pytest, and this generator + has to run there because that is where the pinned pysam lives. conftest only touches + pytest at import time for the @pytest.fixture decorators, so an identity decorator is + a faithful stand-in. We only ever call the plain builder functions, never a fixture. + """ + + def __init__(self): + super().__init__("pytest") + + @staticmethod + def fixture(func=None, **_kw): + return func if func is not None else (lambda f: f) + + @staticmethod + def importorskip(name, *_a, **_kw): + return importlib.import_module(name) + + class approx: # noqa: N801 - mirrors pytest's name + def __init__(self, *_a, **_kw): + pass + + +def _load_conftest(): + """Import tests/conftest.py as a module without needing pytest to collect it.""" + sys.modules.setdefault("pytest", _PytestShim()) + spec = importlib.util.spec_from_file_location( + "ecs_conftest", REPO / "tests" / "conftest.py") + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + + +def main(): + import pysam + + c = _load_conftest() + OUT.mkdir(parents=True, exist_ok=True) + + fasta_path = OUT / "ref.fa" + fasta = c._write_ecs_fasta(fasta_path) + + # targets VCF — the --target-file the caller takes + header = pysam.VariantHeader() + header.contigs.add(c.ECS_CHROM, length=c.ECS_CONTIG_LEN) + targets = OUT / "targets.vcf" + with pysam.VariantFile(str(targets), "w", header=header) as vout: + for pos in (c.ECS_TARGET_A, c.ECS_TARGET_B): + rec = vout.new_record() + rec.chrom = c.ECS_CHROM + rec.pos = pos + rec.id = "." + rec.ref = fasta.fetch(c.ECS_CHROM, pos - 1, pos) + rec.alts = ("N",) + rec.filter.add("PASS") + vout.write(rec) + + del_cigar = [(0, 60), (2, c.ECS_DEL_LEN), (0, 40)] + edited = [] + for i in range(c.ECS_N_EDIT): + edited += c._ecs_pair(fasta, f"edit{i}", 940, del_cigar, 1180, r1_nm=c.ECS_DEL_LEN) + for i in range(c.ECS_N_WT): + edited += c._ecs_pair(fasta, f"wt{i}", 940, [(0, 100)], 1180) + for i in range(c.ECS_N_DUP): + edited += c._ecs_pair(fasta, f"dup{i}", 940, [(0, 100)], 1180, dup=True) + for i in range(c.ECS_N_LOWMAPQ): + edited += c._ecs_pair(fasta, f"lowq{i}", 940, [(0, 100)], 1180, mapq=3) + for i in range(c.ECS_N_MISMATCH): + edited += c._ecs_pair(fasta, f"mm{i}", 940, [(0, 100)], 1180, r1_nm=6, r2_nm=6) + for i in range(c.ECS_N_OVERLAP): + edited += c._ecs_pair(fasta, f"both{i}", 1080, [(0, 100)], 1220) + for i in range(c.ECS_N_SPAN_B): + edited += c._ecs_pair(fasta, f"spanb{i}", 1150, [(0, 100)], 1220) + + control = [] + for i in range(c.ECS_N_EDIT + c.ECS_N_WT): + control += c._ecs_pair(fasta, f"ctl{i}", 940, [(0, 100)], 1180) + + c._build_ecs_cram(fasta, fasta_path, OUT / "edited.bam", edited) + c._build_ecs_cram(fasta, fasta_path, OUT / "control.bam", control) + + # the intermediate BAMs are a build artifact of the CRAM writer; only ship CRAMs + for stem in ("edited", "control"): + for ext in (".bam", ".bam.bai"): + p = OUT / f"{stem}{ext}" + if p.exists(): + p.unlink() + + print(f"wrote fixture to {OUT}") + for p in sorted(OUT.iterdir()): + print(f" {p.name:20s} {p.stat().st_size:>8,d} bytes") + print(f"\ntotal {sum(p.stat().st_size for p in OUT.iterdir()):,d} bytes") + print(f"edited records: {len(edited)} control records: {len(control)}") + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tests/fixtures/training_mini.tsv b/tests/fixtures/training_mini.tsv new file mode 100644 index 0000000..2d94ba9 --- /dev/null +++ b/tests/fixtures/training_mini.tsv @@ -0,0 +1,12 @@ +sample guide chrom start score verdict ecs_if ecs_is_edit ecs_indel_reads label +DEMO AAVS1 chr1 1000 0.95 LIKELY EDIT 0.20 1 50 1 +DEMO AAVS1 chr2 1010 0.90 LIKELY EDIT 0.20 1 50 1 +DEMO AAVS1 chr3 1020 0.85 LIKELY EDIT 0.20 1 50 1 +DEMO AAVS1 chr4 1030 0.70 LIKELY EDIT 0.20 1 50 1 +DEMO AAVS1 chr5 1040 0.30 LIKELY EDIT 0.20 1 50 1 +DEMO AAVS1 chr6 1050 0.25 ARTIFACT (shape) 0.20 1 50 1 +DEMO AAVS1 chr7 1060 INSUFFICIENT COVERAGE 0.20 1 50 1 +DEMO AAVS1 chrN0 2000 0.80 LIKELY EDIT 0.0 0 0 0 +DEMO AAVS1 chrN1 2010 0.75 LIKELY EDIT 0.0 0 0 0 +DEMO AAVS1 chrN2 2020 0.20 ARTIFACT (shape) 0.0 0 0 0 +DEMO AAVS1 chrN3 2030 0.10 ARTIFACT (shape) 0.0 0 0 0 diff --git a/tests/nextflow.config b/tests/nextflow.config new file mode 100644 index 0000000..579d76d --- /dev/null +++ b/tests/nextflow.config @@ -0,0 +1,36 @@ +/* + * Config applied to every nf-test run. + * + * These tests execute REAL process bodies (not stubs), so they need a container engine. + * The engine itself is chosen by the profile on the command line: + * CI / laptop : nf-test test --profile docker + * RIS cluster : nf-test test --profile apptainer + * + * Everything below is about keeping a real run small enough for a 2-CPU CI runner. + */ + +params { + // conf/stub.config nulls the /storage2 DRAGEN reference paths that workflows/scge.nf + // validates at PARSE time on every entry. Without that these tests cannot even be + // compiled off-cluster. We inherit it via the `stub` profile in nf-test.config, but + // re-state the sizing here so a test never inherits a cluster-sized request. + max_cpus = 2 + max_memory = '6.GB' + max_time = '1.h' +} + +process { + executor = 'local' + cpus = 1 + memory = '2.GB' + // Fixtures are a few KB; nothing here should ever take a minute. A hang is a bug, + // and a fast failure is more useful in CI than a 6-hour queue timeout. + time = '10.m' + errorStrategy = 'terminate' +} + +// nf-test asserts on file contents; a timestamped/versioned trace adds churn without value. +timeline.enabled = false +report.enabled = false +trace.enabled = false +dag.enabled = false diff --git a/tests/test_bnd_snapshots.py b/tests/test_bnd_snapshots.py new file mode 100644 index 0000000..e1d8aa9 --- /dev/null +++ b/tests/test_bnd_snapshots.py @@ -0,0 +1,195 @@ +"""bin/bnd_snapshots.py -- the row-to-junction collapse, which is the whole design. + +The breakend queue reports one physical event several times: once from each end, at a +few bp of position jitter, and under both strand orientations. On the 32-sample CAR-T +cohort that is 25 rows describing 8 junctions. Rendering per row would produce 25 +figures, three of which are the same inversion drawn from opposite directions, and the +per-row read counts (3, 4, 3, 4, 4) would understate an event carrying 18 reads. + +So `collapse()` is not a convenience -- it is the difference between a figure that says +what happened and a stack of figures that say it five times, quieter each time. This +file pins that behaviour against the REAL queue, checked in at +tests/fixtures/bnd_review_queue_cart.tsv (3.5 KB), rather than a synthetic one: the +jitter pattern and the both-directions reporting are precisely the properties a +hand-written fixture would smooth away. + +No CRAM, no pysam, no plotting -- this is the arithmetic only. The rendering path is +covered by modules/local/review_bnd_snapshots.nf.test, which runs the real script. +""" +import importlib.util +from pathlib import Path + +import pytest + +pd = pytest.importorskip("pandas") + +FIXTURE = Path(__file__).resolve().parent / "fixtures" / "bnd_review_queue_cart.tsv" +BIN = Path(__file__).resolve().parent.parent / "bin" + + +def _load(): + """Import bin/bnd_snapshots.py by path -- bin/ is not a package.""" + spec = importlib.util.spec_from_file_location("bnd_snapshots", BIN / "bnd_snapshots.py") + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + + +bs = _load() + + +@pytest.fixture(scope="module") +def queue(): + return pd.read_csv(FIXTURE, sep="\t", dtype=str) + + +@pytest.fixture(scope="module") +def junctions(queue): + return bs.collapse(queue) + + +def by_sample(junctions): + return {j["sample"]: j for j in junctions} + + +# -------------------------------------------------------------------------------- +# The collapse itself +# -------------------------------------------------------------------------------- + +def test_the_real_queue_is_25_rows(queue): + """Guards the fixture: if this changes, every count below is measuring something else.""" + assert len(queue) == 25 + assert queue["sample_name"].nunique() == 8 + + +def test_25_rows_collapse_to_8_junctions(junctions): + assert len(junctions) == 8 + assert {j["sample"] for j in junctions} == { + "ARID4A-KO-DNA", "BRAF-KO-CART-DNA", "PDCD4-KO-CART", "KLF12-KO-DNA", + "PDE7A-KO-DNA", "IKZF2-KO-DNA", "RXRB-KO-DNA", "ZEB2-KO-DNA", + } + + +def test_rows_reported_from_opposite_ends_land_in_one_junction(junctions): + """ARID4A is the clean case: 2 rows call it chr14:58301->58330, 3 call it the reverse. + + A key that did not sort its two bins would produce two junctions here, and the figure + would draw the same inversion twice, mirrored. + """ + j = by_sample(junctions)["ARID4A-KO-DNA"] + assert j["n_rows"] == 5 + assert j["left"][0] == j["right"][0] == "chr14" + assert j["left"][1] < j["right"][1] + + +def test_every_row_is_accounted_for(queue, junctions): + assert sum(j["n_rows"] for j in junctions) == len(queue) + assert sum(j["reads"] for j in junctions) == queue["reads"].astype(int).sum() == 150 + + +# -------------------------------------------------------------------------------- +# Aggregation -- the numbers the figure prints +# -------------------------------------------------------------------------------- + +def test_aggregate_support_exceeds_any_single_row(queue, junctions): + """The reason per-row counts must not be quoted: ARID4A's largest row says 4 reads. + + 18 is the sum over the rows describing that junction. It is support counted from both + ends of the same event, so it is an aggregate of the caller's row-level evidence -- + not an independent read count, and deliberately more conservative than the SA-tag + evidence the figure highlights (48 of 60 SA reads at this locus point at the partner). + """ + j = by_sample(junctions)["ARID4A-KO-DNA"] + rows = queue[queue["sample_name"] == "ARID4A-KO-DNA"]["reads"].astype(int) + + assert j["reads"] == 18 == rows.sum() + assert j["reads"] > rows.max() * 4 + + +@pytest.mark.parametrize("sample,left,right,span,reads", [ + # positions are the highest-support end, not the first seen + ("ARID4A-KO-DNA", 58301619, 58330082, 28463, 18), + ("PDCD4-KO-CART", 110887716, 110890582, 2866, 35), + ("IKZF2-KO-DNA", 213022046, 213147793, 125747, 12), + ("BRAF-KO-CART-DNA", 140801460, 140834645, 33185, 10), +]) +def test_representative_ends_and_span(junctions, sample, left, right, span, reads): + j = by_sample(junctions)[sample] + assert j["left"][1] == left + assert j["right"][1] == right + assert j["span"] == span + assert j["reads"] == reads + + +def test_depth_and_control_are_carried(junctions): + """site_total_reads is the denominator a reviewer needs; control must stay visible.""" + j = by_sample(junctions)["ARID4A-KO-DNA"] + assert j["depth"] == 129 + assert j["control"] == 0 + assert all(x["control"] == 0 for x in junctions), "cohort has no control support" + + +def test_jittered_positions_are_kept_as_marks(junctions): + """Every distinct end position survives, so the figure can show the jitter.""" + j = by_sample(junctions)["ARID4A-KO-DNA"] + assert sorted(j["left"][2]) == [58301619, 58301620, 58301622, 58301623] + assert j["left"][1] in j["left"][2] + assert j["right"][1] in j["right"][2] + + +# -------------------------------------------------------------------------------- +# Canonical ordering -- so a figure is reproducible +# -------------------------------------------------------------------------------- + +def test_left_is_always_before_right(junctions): + for j in junctions: + assert (j["left"][0], j["left"][1]) < (j["right"][0], j["right"][1]) + + +def test_ordering_is_independent_of_row_order(queue): + """Reversing the input must not mirror any figure.""" + forward = {j["sample"]: (j["left"], j["right"]) for j in bs.collapse(queue)} + reverse = {j["sample"]: (j["left"], j["right"]) + for j in bs.collapse(queue.iloc[::-1].reset_index(drop=True))} + assert forward == reverse + + +def test_metadata_passthrough(junctions): + j = by_sample(junctions)["BRAF-KO-CART-DNA"] + assert j["call"] == "inversion at cut site" + assert j["interchrom"] is False + assert set(j["strands"].split(",")) == {"-+", "+-"} + + assert by_sample(junctions)["ARID4A-KO-DNA"]["call"] == "multi-cut inversion" + + +def test_opposite_strands_are_flagged_inverted(junctions): + """collapse() must carry orientation, because the schematic branches on it. + + +-/-+ means the two joined segments run in opposite directions: the segment between the + cuts was flipped, not removed. Drawing the excision cartoon for one of those is worse + than drawing nothing, since a reader trusts the picture over the caption -- which is + exactly what shipped until 2026-08-20. + """ + for j in junctions: + assert j["inverted"] is True, f"{j['sample']} lost its orientation" + + +# -------------------------------------------------------------------------------- +# Helpers, directly +# -------------------------------------------------------------------------------- + +def test_junction_bins_is_order_insensitive(): + a = bs.junction_bins({"bin": "chr14:58301", "partner_bin": "chr14:58330"}) + b = bs.junction_bins({"bin": "chr14:58330", "partner_bin": "chr14:58301"}) + assert a == b == ("chr14:58301", "chr14:58330") + + +def test_end_of_rejects_an_unknown_bin(queue): + g = queue[queue["sample_name"] == "ARID4A-KO-DNA"] + with pytest.raises(ValueError): + bs.end_of(g, "chr1:999999") + + +def test_empty_queue_collapses_to_nothing(queue): + assert bs.collapse(queue.iloc[0:0]) == [] diff --git a/tests/test_bnd_vcf.py b/tests/test_bnd_vcf.py new file mode 100644 index 0000000..f230134 --- /dev/null +++ b/tests/test_bnd_vcf.py @@ -0,0 +1,218 @@ +"""bin/bnd_from_indels_to_vcf.py -- the breakend VCF behind the report's SV section. + +Why this file exists, in one sentence: for every run ever done before this suite, that +script emitted a VCF containing zero records and nobody noticed. + +The cause was `'\\t'` and `'\\n'` written into the source with doubled backslashes -- so +the header was split on the two-character string backslash-t, never matched, and every +row took the `continue` branch. The output was one line of literal backslash-n text, +`wc -l` = 0. It is downstream of nothing that checks it: compile_report_json.nf feeds it +to the per-sample HTML report as --offtarget_svs, and a blank SV section looks exactly +like a sample with no SVs. + +So the first test here is deliberately dumb -- it asserts the file contains real tab and +newline bytes -- because that is the assertion whose absence cost 32 samples' worth of +reports. The rest cover what the rewrite added: mate linking and the SR/CTRL evidence +fields that the old `parts[:5]` slice threw away. + +Fixtures are REAL bnd_info payloads lifted from +results_cart_nopon/ARID4A-KO-DNA/ARID4A-KO-DNA.offtarget_analysis.tsv, including the one +genuinely reciprocal pair in that sample (the 28 kb chr14 deletion, reported from both +ends). Synthetic strings would not have caught the bracket-orientation question, which +is why they are copied rather than invented. +""" +import csv +from pathlib import Path + +import pytest + +from conftest import run + +BIN = Path(__file__).resolve().parent.parent / "bin" + +# The 19 columns find_edited_reads.py writes. Only bnd_info is read by the script under +# test, but the header must be complete or the DictReader lookup is not being exercised +# the way production exercises it. +COLS = ["chrom", "start", "end", "pam_positions", "total_reads", "indel_reads", + "indel_fraction", "control_reads", "control_indel_reads", + "control_indel_fraction", "indel_count", "indel_info", "bnd_count", + "bnd_info", "control_bnd_reads", "n_control_filtered", "min_cut_distance", + "target_info", "is_target"] + +# chrom|pos|chrom2|pos2|strands|ref|alt|distance|distance2|counts|control_alt_counts +# 0 1 2 3 4 5 6 7 8 9 10 +MATE_A = "chr14|58301619|chr14|58330081|-+|G|G]chr14:58330081]|1|1|3|0" +MATE_B = "chr14|58330081|chr14|58301619|+-|A|A]chr14:58301619]|1|1|1|0" +# no reciprocal partner in the file -- the common case +LONE = "chr2|71504476|chr2|32916560|-+|C|CCAC]chr2:32916560]|8|118233|1|0" +# a second lone junction whose ALT uses the opposite bracket form +LONE2 = "chr3|75672394|chr2|32916405|++|C|]chr2:32916405]GCC|2|118078|7|2" + + +def write_tsv(path, bnd_infos): + """One analysis row per bnd_info payload; every other column is filler.""" + with open(path, "w", newline="") as fh: + w = csv.writer(fh, delimiter="\t", lineterminator="\n") + w.writerow(COLS) + for i, bi in enumerate(bnd_infos): + row = ["chr14", 1000 + i, 1001 + i, str(1001 + i), 100, 0, 0.0, + 100, 0, 0.0, 0, ".", bi.count(";") + 1, bi, 0, 0, 1, ".", 0] + w.writerow(row) + + +def convert(tmp_path, bnd_infos, sample="TEST"): + """Run the script the way modules/local/*.nf runs it; return the VCF text.""" + tsv = tmp_path / "in.offtarget_analysis.tsv" + out = tmp_path / "out.vcf" + write_tsv(tsv, bnd_infos) + run("bnd_from_indels_to_vcf.py", "--meta_id", sample, + "--indels_path", tsv, "--outfile", out, cwd=tmp_path) + return out.read_text() + + +def records(text): + """The data lines, as dicts keyed by VCF column.""" + keys = ["CHROM", "POS", "ID", "REF", "ALT", "QUAL", "FILTER", "INFO"] + return [dict(zip(keys, ln.split("\t"))) + for ln in text.splitlines() if ln and not ln.startswith("#")] + + +def info_of(rec): + return dict(kv.split("=", 1) for kv in rec["INFO"].split(";") if "=" in kv) + + +# -------------------------------------------------------------------------------- +# The regression that was missing +# -------------------------------------------------------------------------------- + +def test_output_uses_real_tabs_and_newlines(tmp_path): + """The exact bug: escapes written doubled, so nothing was ever a delimiter.""" + text = convert(tmp_path, [LONE]) + + assert "\\t" not in text, "literal backslash-t in output -- the escape bug is back" + assert "\\n" not in text, "literal backslash-n in output -- the escape bug is back" + assert text.count("\n") > 1, "single-line output -- newlines are not newlines" + + header = [ln for ln in text.splitlines() if ln.startswith("#CHROM")] + assert len(header) == 1 + assert header[0].split("\t") == ["#CHROM", "POS", "ID", "REF", "ALT", + "QUAL", "FILTER", "INFO"] + + +def test_emits_records_at_all(tmp_path): + """Before the fix this was 0 for every sample in every run.""" + assert len(records(convert(tmp_path, [LONE, LONE2]))) == 2 + + +# -------------------------------------------------------------------------------- +# Content +# -------------------------------------------------------------------------------- + +def test_ref_and_alt_come_from_the_caller_verbatim(tmp_path): + """Fields 5 and 6 are already a valid VCF REF/ALT -- they must not be re-derived. + + Both bracket forms appear here on purpose: `t]p]` (a piece to the right joins after + this base) and `]p]t` (a piece to the left joins before it). Re-deriving orientation + from `strands` is what the old code attempted, and it only handled '++'. + """ + recs = {r["CHROM"]: r for r in records(convert(tmp_path, [LONE, LONE2]))} + + assert recs["chr2"]["REF"] == "C" + assert recs["chr2"]["ALT"] == "CCAC]chr2:32916560]" + assert recs["chr3"]["REF"] == "C" + assert recs["chr3"]["ALT"] == "]chr2:32916405]GCC" + + +def test_support_counts_survive_into_info(tmp_path): + """SR/CTRL are bnd_info fields 9 and 10, which the old `parts[:5]` slice discarded. + + Without them the report's SV table can only show coordinates, so a 1-read junction + and a 7-read junction look identical to a reviewer. + """ + recs = {r["CHROM"]: r for r in records(convert(tmp_path, [LONE, LONE2]))} + + assert info_of(recs["chr2"])["SR"] == "1" + assert info_of(recs["chr2"])["CTRL"] == "0" + assert info_of(recs["chr3"])["SR"] == "7" # field 9 of LONE2 + assert info_of(recs["chr3"])["CTRL"] == "2" # field 10 of LONE2 + + text = convert(tmp_path, [LONE]) + assert "##INFO==2.1, one header line): Spacer+PAM[0], Chromosome[1], +# Start[2], Strand[3], Aligned_protospacer+PAM_REF[5], PAM[7], Mismatches[8], Bulges[9], +# Bulge_type[15]. '+' strand: adjusted Start = Start + (len(DNA) - 4) = 101 + 19 = 120. +def _crisprme_row(chrom, start, strand, mm, bulge, btype): + cols = [""] * 16 + cols[0] = "crRNA"; cols[1] = chrom; cols[2] = str(start); cols[3] = strand + cols[5] = DNA; cols[7] = "TGG"; cols[8] = str(mm); cols[9] = str(bulge); cols[15] = btype + return "\t".join(cols) + +CRISPRME = "crisprme_header\n" + "\n".join([ + _crisprme_row("chr1", 101, "+", 2, 0, "mismatch"), # shared site @ chr1:120 + _crisprme_row("chr3", 300, "+", 3, 1, "RNA"), # crisprme-only @ chr3:319 +]) + "\n" + + +def _write(tmp_path, casoff=True, crisprme=True): + if casoff: + (tmp_path / "g.casoffinder.txt").write_text(CASOFFINDER) + if crisprme: + (tmp_path / "g.crisprme.tsv").write_text(CRISPRME) + + +def test_combine_merges_shared_site(tmp_path): + _write(tmp_path) + run("combine_offtarget_results.py", + "--casoffinder", "g.casoffinder.txt", "--crisprme", "g.crisprme.tsv", + "-o", "out.csv", cwd=tmp_path) + df = pd.read_csv(tmp_path / "out.csv") + + assert list(df.columns) == CANONICAL_HEADER + # 3 distinct physical sites: shared chr1, cas-only chr2, crisprme-only chr3 + assert len(df) == 3 + + shared = df[(df["Chromosome"] == "chr1") & (df["Start"] == 120)].iloc[0] + assert shared["Source"] == "CasOffFinder|CrisprME" # both tools, join order preserved + assert shared["Mismatch"] == 2 # min across the two + assert shared["Bulge_Size"] == 0 + assert shared["On_target"] == 0 + assert shared["PAM"] == "TGG" + + cas_only = df[df["Chromosome"] == "chr2"].iloc[0] + assert cas_only["Source"] == "CasOffFinder" + assert cas_only["Start"] == 220 + assert cas_only["On_target"] == 1 # X / 0 MM / 0 bulge + + cme_only = df[df["Chromosome"] == "chr3"].iloc[0] + assert cme_only["Source"] == "CrisprME" + assert cme_only["Start"] == 319 + + +def test_single_source_ok(tmp_path): + """IDT-dropped reality: one source is enough; no crash on the missing others.""" + _write(tmp_path, casoff=True, crisprme=False) + run("combine_offtarget_results.py", + "--casoffinder", "g.casoffinder.txt", "-o", "out.csv", cwd=tmp_path) + df = pd.read_csv(tmp_path / "out.csv") + assert list(df.columns) == CANONICAL_HEADER + assert set(df["Source"]) == {"CasOffFinder"} + assert len(df) == 2 + + +def test_requires_a_source(tmp_path): + """No source at all is a usage error (rc != 0).""" + proc = subprocess.run([sys.executable, str(BIN / "combine_offtarget_results.py"), + "-o", "out.csv"], cwd=tmp_path, capture_output=True, text=True) + assert proc.returncode != 0 + + +def test_schema_matches_committed_targetfile(): + """The output header must match the committed target_file schema exactly. + + Despite the name, assets/stub/AAVS1_site14.targets.csv is gitignored (.gitignore), + so it exists only in a working checkout that has generated it — never in a fresh + clone or on CI. Skip rather than fail there: a red job that can never go green on CI + trains people to ignore the whole run. + """ + target = REPO / "assets/stub/AAVS1_site14.targets.csv" + if not target.exists(): + pytest.skip(f"{target.name} is gitignored and absent from this checkout") + committed = pd.read_csv(target, nrows=0) + assert list(committed.columns) == CANONICAL_HEADER diff --git a/tests/test_control_counts.py b/tests/test_control_counts.py new file mode 100644 index 0000000..29e24cb --- /dev/null +++ b/tests/test_control_counts.py @@ -0,0 +1,141 @@ +"""add_normal_counts must count control alt support in FRAGMENTS, not reads. + +Depth has always been fragment-level -- `len(total_reads)` where `total_reads` is a set of +query_name -- so R1 and R2 of one physical molecule contribute one unit of depth. Alt support was +counted per read, so an overlapping mate pair that both showed the variant contributed TWO to the +numerator and ONE to the denominator. That biases the background rate upward wherever mates +overlap, which on real CAR-T control CRAMs is ~49% of fragments, and it is one route to the +`control_alt_counts > control_total_counts` rows that make the (k, n) pair invalid for betabinom. + +These tests pin the invariant: one fragment, one vote, however many of its reads are visible. + +Requires the caller's own imports (pysam, edlib, pyranges) -- run inside +ghcr.io/dhslab/docker-scge-offtarget if the host interpreter lacks them. +""" +import importlib.util +import random +from pathlib import Path + +import pandas as pd +import pytest + +pysam = pytest.importorskip("pysam") +pytest.importorskip("edlib") + +# find_edited_reads imports pyranges at module scope for target-window merging, which +# add_normal_counts never touches. Stub it if absent so this test runs on any interpreter that +# has pysam and edlib, rather than silently skipping and leaving the fix unverified. +try: # pragma: no cover + import pyranges # noqa: F401 +except ImportError: # pragma: no cover + import sys, types + sys.modules["pyranges"] = types.ModuleType("pyranges") + +BIN = Path(__file__).resolve().parents[1] / "bin" +CHROM, CONTIG_LEN = "chr1", 2000 +DEL_POS, DEL_LEN = 1001, 4 # 1-based deletion start, length + + +def _load_caller(): + spec = importlib.util.spec_from_file_location("find_edited_reads", + BIN / "find_edited_reads.py") + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + + +@pytest.fixture +def workspace(tmp_path): + """A reference plus a control BAM whose alt-supporting pairs OVERLAP each other.""" + random.seed(11) + seq = "".join(random.choice("ACGT") for _ in range(CONTIG_LEN)) + fa = tmp_path / "ref.fa" + with open(fa, "w") as fh: + fh.write(f">{CHROM}\n") + for i in range(0, CONTIG_LEN, 60): + fh.write(seq[i:i + 60] + "\n") + pysam.faidx(str(fa)) + fasta = pysam.FastaFile(str(fa)) + + hdr = {"HD": {"VN": "1.6"}, "SQ": [{"SN": CHROM, "LN": CONTIG_LEN}]} + bam = tmp_path / "control.bam" + + def deleted_seq(start, length): + """Read sequence carrying the deletion, as ref-minus-the-deleted-bases.""" + left = fasta.fetch(CHROM, start, DEL_POS - 1) + right = fasta.fetch(CHROM, DEL_POS - 1 + DEL_LEN, + start + length + DEL_LEN) + return left + right + + with pysam.AlignmentFile(str(bam), "wb", header=hdr) as out: + # 3 pairs where BOTH mates span the deletion -- the double-counting case. + for i in range(3): + start = DEL_POS - 41 + left_len = DEL_POS - 1 - start + right_len = 60 - left_len + cig = [(0, left_len), (2, DEL_LEN), (0, right_len)] + s = deleted_seq(start, 60) + for is_r1 in (True, False): + a = pysam.AlignedSegment() + a.query_name = f"overlapping_pair_{i}" # SAME name for both mates + a.query_sequence = s + a.flag = 99 if is_r1 else 147 + a.reference_id = 0 + a.reference_start = start + a.mapping_quality = 60 + a.cigartuples = cig + a.next_reference_id = 0 + a.next_reference_start = start + a.template_length = 60 if is_r1 else -60 + a.query_qualities = pysam.qualitystring_to_array("I" * len(s)) + out.write(a) + # 2 pairs where only R1 spans it -- one read, one fragment, unambiguous. + for i in range(2): + start = DEL_POS - 41 + left_len = DEL_POS - 1 - start + right_len = 60 - left_len + a = pysam.AlignedSegment() + a.query_name = f"single_end_pair_{i}" + a.query_sequence = deleted_seq(start, 60) + a.flag = 99 + a.reference_id = 0 + a.reference_start = start + a.mapping_quality = 60 + a.cigartuples = [(0, left_len), (2, DEL_LEN), (0, right_len)] + a.next_reference_id = 0 + a.next_reference_start = 1500 + a.template_length = 600 + a.query_qualities = pysam.qualitystring_to_array("I" * 60) + out.write(a) + pysam.index(str(bam)) + return {"fasta": fasta, "bam": bam} + + +def _run(workspace): + mod = _load_caller() + ref = workspace["fasta"].fetch(CHROM, DEL_POS - 2, DEL_POS - 1 + DEL_LEN) + alt = ref[0] + # alttype drives generate_contig's BND-vs-linear branch; a plain deletion is linear. + df = pd.DataFrame([{"chrom": CHROM, "pos": DEL_POS - 1, "ref": ref, "alt": alt, + "alttype": "DEL"}]) + with pysam.AlignmentFile(str(workspace["bam"]), "rb") as bam: + reads = list(bam.fetch(CHROM, DEL_POS - 400, DEL_POS + 400)) + return mod.add_normal_counts(df, reads, workspace["fasta"]) + + +def test_overlapping_mates_count_once(workspace): + """5 supporting FRAGMENTS (3 overlapping pairs + 2 single) -- not 8 supporting reads.""" + out = _run(workspace) + assert int(out["control_alt_counts"].iloc[0]) == 5 + + +def test_alt_never_exceeds_depth(workspace): + """The (k, n) pair must be valid: betabinom is undefined for k > n.""" + out = _run(workspace) + assert int(out["control_alt_counts"].iloc[0]) <= int(out["control_total_counts"].iloc[0]) + + +def test_depth_is_fragment_level(workspace): + """5 fragments were written; both mates of three of them are present.""" + out = _run(workspace) + assert int(out["control_total_counts"].iloc[0]) == 5 diff --git a/tests/test_offtarget_glue.py b/tests/test_offtarget_glue.py new file mode 100644 index 0000000..dd4b0f0 --- /dev/null +++ b/tests/test_offtarget_glue.py @@ -0,0 +1,544 @@ +"""Logic tests for the Unified CRISPR Off-Target Workflow glue scripts. + +Scenario (see conftest): one guide, two ECS replicates + one WGS sample, three hotspots +(a real edit, a true negative, and a below-floor low-VAF edit). These lock in the +ECS⋈WGS join and the recall-vs-VAF behaviour that the Nextflow layer depends on. +""" +import subprocess +import sys + +import pandas as pd +import pytest +from conftest import BIN, run + + +def test_hotspot_to_table(workspace): + run("hotspot_to_table.py", + "--ecs-tables", "PLCB2_ecs_1.offtarget_analysis.tsv", "PLCB2_ecs_2.offtarget_analysis.tsv", + "--samplesheet", "samplesheet.csv", "--edit-threshold", "0.0", cwd=workspace) + + truth = pd.read_csv(workspace / "ecs_hotspot_truth.csv").set_index("chrom") + # ECS truth takes the strongest evidence across replicates (max VAF) + assert truth.loc["chr12", "ecs_if"] == 0.15 + assert truth.loc["chr12", "ecs_is_edit"] == 1 + assert truth.loc["chr1", "ecs_is_edit"] == 0 + assert truth.loc["chr7", "ecs_is_edit"] == 1 # 0.008 > threshold 0.0 + assert int(truth["ecs_is_edit"].sum()) == 2 + + table = pd.read_csv(workspace / "wgs_hotspot_input_table.csv") + assert len(table) == 3 # 1 WGS sample x 3 hotspots + assert (table["sample_name"] == "PLCB2_wgs_1").all() + assert (table["indel_fraction"] == 1.0).all() # gate-passer, not real signal + + +def test_join_training_table(workspace): + run("hotspot_to_table.py", + "--ecs-tables", "PLCB2_ecs_1.offtarget_analysis.tsv", "PLCB2_ecs_2.offtarget_analysis.tsv", + "--samplesheet", "samplesheet.csv", cwd=workspace) + run("join_training_table.py", "--wgs-scores", "wgs_hotspot_scores.csv", + "--truth", "ecs_hotspot_truth.csv", "--samplesheet", "samplesheet.csv", cwd=workspace) + + tr = pd.read_csv(workspace / "training.tsv", sep="\t").set_index("chrom") + assert len(tr) == 3 + assert set(tr["label"]) == {0, 1} + # WGS features and ECS truth land on the same row, keyed on (guide, chrom, start) + assert tr.loc["chr12", "label"] == 1 + assert tr.loc["chr12", "ecs_if"] == 0.15 + assert tr.loc["chr12", "score"] == 0.90 + assert tr.loc["chr7", "label"] == 1 and tr.loc["chr7", "score"] == 0.12 + + +def test_recall_vs_vaf(workspace): + run("hotspot_to_table.py", + "--ecs-tables", "PLCB2_ecs_1.offtarget_analysis.tsv", "PLCB2_ecs_2.offtarget_analysis.tsv", + "--samplesheet", "samplesheet.csv", cwd=workspace) + run("join_training_table.py", "--wgs-scores", "wgs_hotspot_scores.csv", + "--truth", "ecs_hotspot_truth.csv", "--samplesheet", "samplesheet.csv", cwd=workspace) + proc = run("recall_vs_vaf.py", "--training", "training.tsv", "--hi", "0.60", + "--target-recall", "0.80", cwd=workspace) + + # overall: 1 of 2 credible ECS edits recovered (chr12 yes @0.15, chr7 no @0.008). + # Both clear the denominator gates (3000x depth -> 450 and 24 indel reads). + assert "overall WGS recall of credible ECS edits: 0.50" in proc.stdout + assert "2 EVALUABLE sites" in proc.stdout + m = pd.read_csv(workspace / "recall_vs_vaf.csv") + recalls = dict(zip(m["vaf_bin"], m["recall"])) + assert recalls["[0.005, 0.01)"] == 0.0 # below the depth floor + assert recalls["[0.1, 0.2)"] == 1.0 # above it + assert (workspace / "recall_vs_vaf.png").exists() + + # the denominator must be stamped into the file so it can't be read out of context + for col in ("n_unevaluable", "n_evaluable", "recall_incl_unevaluable", + "denom_min_ecs_vaf", "denom_min_ecs_reads", "denom_excluded_as_noise"): + assert col in m.columns, f"{col} missing from recall_vs_vaf.csv" + assert (m["denom_min_ecs_vaf"] == 0.005).all() + assert (m["denom_min_ecs_reads"] == 5).all() + # chr1 (VAF 0, no read support) must be excluded as noise, never counted as a miss + assert (m["denom_excluded_as_noise"] >= 0).all() + assert "[0.0, 0.005)" not in recalls + + +def test_recall_denominator_excludes_ecs_noise(workspace): + """A high-VAF ECS call with almost no read support is assay noise, not a missed edit: + raising --min-ecs-reads above its support must DROP it from the denominator rather + than scoring it as a recall failure.""" + run("hotspot_to_table.py", + "--ecs-tables", "PLCB2_ecs_1.offtarget_analysis.tsv", "PLCB2_ecs_2.offtarget_analysis.tsv", + "--samplesheet", "samplesheet.csv", cwd=workspace) + run("join_training_table.py", "--wgs-scores", "wgs_hotspot_scores.csv", + "--truth", "ecs_hotspot_truth.csv", "--samplesheet", "samplesheet.csv", cwd=workspace) + + # chr7 has 24 indel reads; require 100 and it must leave the denominator entirely + proc = run("recall_vs_vaf.py", "--training", "training.tsv", "--min-ecs-reads", "100", + cwd=workspace) + m = pd.read_csv(workspace / "recall_vs_vaf.csv") + assert "[0.005, 0.01)" not in set(m["vaf_bin"]) # chr7 gone, not scored as a miss + assert "overall WGS recall of credible ECS edits: 1.00" in proc.stdout + + +def test_reconcile_report(workspace): + run("hotspot_to_table.py", + "--ecs-tables", "PLCB2_ecs_1.offtarget_analysis.tsv", "PLCB2_ecs_2.offtarget_analysis.tsv", + "--samplesheet", "samplesheet.csv", cwd=workspace) + run("reconcile_offtarget_report.py", "--worklist", "worklist_pon.csv", + "--truth", "ecs_hotspot_truth.csv", "--pad", "25", "--verdict-col", "verdict_pon", + cwd=workspace) + + rep = pd.read_csv(workspace / "offtarget_report.csv").set_index("chrom") + # chr12 candidate is 1bp off the known hotspot -> matched within pad, ECS-confirmed + assert rep.loc["chr12", "is_hotspot"] == 1 + assert rep.loc["chr12", "ecs_confirmed"] == 1 + assert rep.loc["chr12", "ecs_if"] == 0.15 + # chr3 has no predicted hotspot nearby -> novel candidate + assert rep.loc["chr3", "is_hotspot"] == 0 + + +def test_join_empty_on_coord_mismatch(workspace): + """Guardrail: when both arms have rows but coords drift, the join is empty and the + script must FAIL — a silent empty training.tsv would otherwise pass as a clean run.""" + run("hotspot_to_table.py", + "--ecs-tables", "PLCB2_ecs_1.offtarget_analysis.tsv", "PLCB2_ecs_2.offtarget_analysis.tsv", + "--samplesheet", "samplesheet.csv", cwd=workspace) + w = pd.read_csv(workspace / "wgs_hotspot_scores.csv") + w["start"] += 5 # simulate a 5bp drift + w.to_csv(workspace / "wgs_shifted.csv", index=False) + + # invoke directly (not the rc==0 run() helper) because we expect a non-zero exit + proc = subprocess.run( + [sys.executable, str(BIN / "join_training_table.py"), + "--wgs-scores", "wgs_shifted.csv", "--truth", "ecs_hotspot_truth.csv", + "--samplesheet", "samplesheet.csv"], + cwd=workspace, capture_output=True, text=True) + + assert proc.returncode != 0 # both arms had rows -> hard fail + assert "ERROR" in proc.stderr and "empty join" in proc.stderr + + +# ── verdict() call-arity contract ────────────────────────────────────────────── +# score.verdict() returns a 3-tuple (verdict, score, call_basis). worklist_from_vcf.py +# imports it as S.verdict and unpacks it too, so changing the arity in one file silently +# breaks the other — it did, and only surfaced mid-run on the cluster because the failing +# branch needs a real CRAM. This walks the AST of every caller so a future arity change +# fails here instead of an hour into a cohort run. +def test_verdict_callers_unpack_three_values(): + import ast + + offenders = [] + for path in sorted(BIN.glob("*.py")): + tree = ast.parse(path.read_text()) + for node in ast.walk(tree): + if not isinstance(node, ast.Assign): + continue + call = node.value + if not isinstance(call, ast.Call): + continue + fn = call.func + name = (fn.attr if isinstance(fn, ast.Attribute) + else fn.id if isinstance(fn, ast.Name) else None) + if name != "verdict": + continue + for tgt in node.targets: + if not isinstance(tgt, ast.Tuple): + offenders.append(f"{path.name}:{node.lineno} not a tuple unpack") + elif len(tgt.elts) != 3: + offenders.append(f"{path.name}:{node.lineno} unpacks {len(tgt.elts)}, want 3") + + assert not offenders, "verdict() arity mismatch: " + "; ".join(offenders) + + +# -------------------------------------------------------------------------- +# find_edited_reads.py --tagged-bam-out (read-level tags for IGV review) +# +# The caller visits the same alignment record once per overlapping target, so +# the risk here is a BAM with duplicate records, which IGV silently renders as +# doubled depth. These run the real caller on the synthetic CRAM workspace. +# -------------------------------------------------------------------------- +import collections + +import conftest as C + + +def _load_find_edited_reads(): + """Import bin/find_edited_reads.py as a module (it is a script, not a package).""" + import importlib.util + spec = importlib.util.spec_from_file_location("find_edited_reads", + BIN / "find_edited_reads.py") + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def _run_caller(ws, *extra): + run("find_edited_reads.py", + "--fasta", ws["fasta"], "--edited-bam", ws["edited"], + "--control-bam", ws["control"], "--target-file", ws["targets"], + "-o", ws["dir"] / "out.tsv", *extra, cwd=ws["dir"]) + return pd.read_csv(ws["dir"] / "out.tsv", sep="\t") + + +def test_tagged_bam_off_by_default(ecs_reads_workspace): + ws = ecs_reads_workspace + tsv = _run_caller(ws) + assert tsv["indel_reads"].sum() == ws["n_edit_reads"] + # the feature is opt-in: nothing extra on disk unless asked for + assert not list(ws["dir"].glob("*.tagged.bam*")) + + +def test_tagged_bam_tags_every_read_exactly_once(ecs_reads_workspace): + pysam = pytest.importorskip("pysam") + ws = ecs_reads_workspace + out = ws["dir"] / "tagged.bam" + tsv = _run_caller(ws, "--tagged-bam-out", out) + + assert out.exists() and (ws["dir"] / "tagged.bam.bai").exists() + + keys, tags, positions = [], collections.Counter(), [] + spanb_read1 = [] + with pysam.AlignmentFile(str(out)) as bam: + assert bam.header.to_dict()["HD"]["SO"] == "coordinate" + for read in bam: + assert read.has_tag("XC"), f"{read.query_name} has no XC tag" + keys.append((read.query_name, read.flag, read.reference_start)) + tags[read.get_tag("XC")] += 1 + positions.append(read.reference_start) + if read.query_name.startswith("spanb") and read.is_read1: + spanb_read1.append(read.get_tag("XC")) + + # (a) one record per alignment: the whole point of the second pass + duplicated = [k for k, n in collections.Counter(keys).items() if n > 1] + assert not duplicated, f"duplicate records in tagged BAM: {duplicated[:5]}" + assert len(keys) == ws["total_records"] + + # (b) coordinate-sorted, so IGV will load it + assert positions == sorted(positions) + + # (c) tag counts reconcile with the TSV. Tags are per alignment record while + # indel_reads is per fragment (the caller collapses mates by read name), so + # these are only equal because just R1 carries the deletion in this fixture. + # On real data the record count runs ~2x the TSV number. + edit_tag = f"Edited_Deletion_{ws['del_len']}bp" + assert tags[edit_tag] == ws["n_edit_reads"] == tsv["indel_reads"].sum() + + # (d) skipped reads are visibly skipped, not silently absent + assert tags["Skipped_Duplicate"] == 2 * C.ECS_N_DUP + assert tags["Skipped_LowMapQ"] == 2 * C.ECS_N_LOWMAPQ + assert tags["Skipped_Mismatches"] == 2 * C.ECS_N_MISMATCH + # reads sitting in the +/-150 bp pad that span neither target: the implicit + # default, never stored in the tag map (see DEFAULT_TAG) + assert tags["Skipped_NoSpan"] == 2 * C.ECS_N_OVERLAP + C.ECS_N_SPAN_B + + # (e) conflict resolution: these reads fall in both padded windows, where one + # target cannot evaluate them and the other calls them reference + assert spanb_read1 == ["Unedited_WT"] * C.ECS_N_SPAN_B + + +def test_tagged_bam_honours_custom_tag_name(ecs_reads_workspace): + pysam = pytest.importorskip("pysam") + ws = ecs_reads_workspace + out = ws["dir"] / "tagged.bam" + _run_caller(ws, "--tagged-bam-out", out, "--tagged-bam-tag", "YC") + with pysam.AlignmentFile(str(out)) as bam: + read = next(iter(bam)) + assert read.has_tag("YC") and not read.has_tag("XC") + + +def test_read_tag_precedence_is_order_independent(): + """A read seen at two overlapping targets keeps the most specific call.""" + m = _load_find_edited_reads() + + ordered = ["Edited_BND_chr19", "Edited_Deletion_5bp", "Edited_SoftClip", + "Unedited_WT", "Skipped_NoSpan", "Skipped_LowMapQ"] + ranks = [m.read_tag_rank(t) for t in ordered] + assert ranks == sorted(ranks) and len(set(ranks)) == len(ranks) + + class FakeRead: + query_name, flag, reference_start = "r1", 99, 100 + + for first, second in ((("Unedited_WT"), "Edited_Deletion_5bp"), + ("Edited_Deletion_5bp", "Unedited_WT"), + ("Skipped_NoSpan", "Unedited_WT")): + tags = {} + m.record_read_tag(tags, FakeRead(), first) + m.record_read_tag(tags, FakeRead(), second) + winner = min([first, second], key=m.read_tag_rank) + assert tags[("r1", 99, 100)] == winner + + +def test_classify_read_tag_vocabulary(): + m = _load_find_edited_reads() + assert m.classify_read_tag(None, "CIGAR") == "Skipped_Unevaluable" + assert m.classify_read_tag({"alttype": "REF"}, "REF") == "Unedited_WT" + assert m.classify_read_tag( + {"alttype": "BND", "chrom2": "PLVM_CD19_CARv4_cd34"}, "SA" + ) == "Edited_BND_PLVM_CD19_CARv4_cd34" + assert m.classify_read_tag( + {"alttype": "DEL", "ref": "ATTTTT", "alt": "A"}, "CIGAR") == "Edited_Deletion_5bp" + assert m.classify_read_tag( + {"alttype": "INS", "ref": "A", "alt": "ACCC"}, "CIGAR") == "Edited_Insertion_3bp" + # symbolic alleles carry no length, so fall back to the breakpoint span + assert m.classify_read_tag( + {"alttype": "DUP", "ref": "A", "alt": "", "pos": 100, "pos2": 112}, + "SA") == "Edited_Duplication_12bp" + # soft-clip calls are realignments, reported by mechanism not implied size + assert m.classify_read_tag( + {"alttype": "DEL", "ref": "ATTTTT", "alt": "A"}, "SOFTCLIP") == "Edited_SoftClip" + + +def test_merge_windows_collapses_overlapping_targets(): + m = _load_find_edited_reads() + merged = m.merge_windows([("chr1", 850, 1151), ("chr1", 1050, 1351), + ("chr1", 5000, 5300), ("chr2", 10, 300)]) + assert merged == [("chr1", 850, 1351), ("chr1", 5000, 5300), ("chr2", 10, 300)] +# ── offtarget_metrics.py: PR-AUC / F-beta on a hand-built frame ──────────────── +# Every expected value below is computable with a calculator, so a regression shows up +# as a wrong number rather than a plausible-looking one. +# +# 11 credible positives (ecs_if >= 0.005, ecs_indel_reads >= 5), one of which has NO +# score (INSUFFICIENT COVERAGE) and is excluded from the ranking metrics +# 5 ECS-negatives (label 0, ecs_is_edit 0) +# 2 germline-demoted rows (label 0, ecs_is_edit 1) -> excluded from the DEFAULT +# negative set; the shape ranker is not the germline filter +# 3 sub-credibility label==1 rows -> AMBIGUOUS, excluded, never counted as negatives +# +# Of the 10 scored positives, 4 are called LIKELY EDIT; 1 of the 5 negatives is. +# precision = 4/5 = 0.8 recall = 4/10 = 0.4 +# F1 = 2(.8)(.4)/(.8+.4) = 0.5333... +# F2 = 5(.8)(.4)/(4(.8)+.4) = 1.6/3.6 = 0.4444... +# F5 = 26(.8)(.4)/(25(.8)+.4) = 8.32/20.4 = 0.40784... +# recall_incl_unevaluable = 4/11 = 0.36363... +# Scores separate the two classes perfectly, so PR-AUC and ROC-AUC are exactly 1.0. +METRIC_COLS = ["sample", "guide", "chrom", "start", "score", "verdict", + "ecs_if", "ecs_is_edit", "ecs_indel_reads", "label"] + +_EDIT = "LIKELY EDIT" +_ART = "ARTIFACT (shape)" + + +def _metrics_frame(): + rows = [] + pos_scores = [0.90, 0.85, 0.80, 0.75, 0.70, 0.65, 0.60, 0.55, 0.50, 0.45] + for i, sc in enumerate(pos_scores): + rows.append(("s1", "G", f"chr{i + 1}", 1000 + i, sc, + _EDIT if i < 4 else _ART, 0.20, 1, 50, 1)) + # 11th credible positive: no WGS coverage -> no score, out of the ranking metrics + rows.append(("s1", "G", "chrU", 9000, float("nan"), "INSUFFICIENT COVERAGE", + 0.20, 1, 50, 1)) + neg_scores = [0.40, 0.30, 0.20, 0.10, 0.05] + for i, sc in enumerate(neg_scores): + rows.append(("s1", "G", f"chrN{i}", 2000 + i, sc, + _EDIT if i == 0 else _ART, 0.0, 0, 0, 0)) + for i in range(2): # germline-demoted: real indel, in normal + rows.append(("s1", "G", f"chrG{i}", 3000 + i, 0.95, + "GERMLINE/ARTIFACT (in normal)", 0.30, 1, 90, 0)) + for i in range(3): # sub-credibility ECS signal -> ambiguous + rows.append(("s1", "G", f"chrA{i}", 4000 + i, 0.10, _ART, 0.001, 1, 2, 1)) + return pd.DataFrame(rows, columns=METRIC_COLS) + + +def _run_metrics(tmp_path, df, *extra): + df.to_csv(tmp_path / "training.tsv", sep="\t", index=False) + proc = run("offtarget_metrics.py", "--training", "training.tsv", + "--out-json", "m.json", "--out-txt", "m.txt", *extra, cwd=tmp_path) + import json + return json.loads((tmp_path / "m.json").read_text()), (tmp_path / "m.txt").read_text(), proc + + +def test_offtarget_metrics_exact_values(tmp_path): + out, txt, _ = _run_metrics(tmp_path, _metrics_frame()) + m, op = out["metrics"], out["metrics"]["operating_point"] + + # denominator composition + assert (m["n_pos"], m["n_neg"]) == (10, 5) # NaN-score positive not ranked + assert m["n_excluded_no_score"] == 1 + assert m["n_excluded_no_score_pos"] == 1 + assert out["counts"]["n_positives_credible"] == 11 + assert out["counts"]["n_ambiguous"] == 3 # excluded, NOT negatives + assert out["counts"]["n_germline_demoted_excluded"] == 2 + + # perfect ranking -> PR-AUC and ROC-AUC are exactly 1 + assert m["pr_auc"] == pytest.approx(1.0) + assert m["roc_auc"] == pytest.approx(1.0) + assert m["prevalence"] == pytest.approx(10 / 15) + + # operating point, hand-computed + assert (op["tp"], op["fp"], op["fn"], op["tn"]) == (4, 1, 6, 4) + assert op["precision"] == pytest.approx(0.8) + assert op["recall"] == pytest.approx(0.4) + assert op["f1"] == pytest.approx(2 * 0.8 * 0.4 / (0.8 + 0.4)) + assert op["f2"] == pytest.approx(1.6 / 3.6) + assert op["f5"] == pytest.approx(8.32 / 20.4) + assert op["recall_incl_unevaluable"] == pytest.approx(4 / 11) + + # F_beta is monotone in beta: with precision > recall it DECREASES as beta rises, so + # F1 is an endpoint. F1 sitting in the middle means the beta wiring is inverted. + assert op["f1"] > op["f2"] > op["f5"] + + # both denominators must be named in the human-readable report + assert "manual review" in txt.lower() + assert "UNREVIEWED" in txt + assert "NOT vs human review" in txt + + +def test_offtarget_metrics_fbeta_favours_recall(tmp_path): + """Mirror image: when recall > precision, F_beta RISES with beta.""" + df = _metrics_frame() + # call every scored positive plus all 5 negatives -> P = 10/15, R = 10/10 + df["verdict"] = df["verdict"].where(df["verdict"] == "INSUFFICIENT COVERAGE", _EDIT) + # drop the 3 sub-credibility rows only (the ECS-negatives also have a low ecs_if, + # so filtering on ecs_if alone would silently take the negatives with them) + df = df[~((df["label"] == 1) & (df["ecs_indel_reads"] < 5))] + out, _txt, _ = _run_metrics(tmp_path, df, "--negatives", "all_label0") + op = out["metrics"]["operating_point"] + assert op["recall"] == pytest.approx(1.0) + assert op["precision"] == pytest.approx(10 / 17) # 5 ECS-neg + 2 germline as FP + assert op["f1"] < op["f2"] < op["f5"] + + +def test_offtarget_metrics_negative_set_switch(tmp_path): + """The germline-demoted rows are excluded by default and included on request; the + alternative is always reported as a labelled sensitivity block either way.""" + default, _t, _ = _run_metrics(tmp_path, _metrics_frame()) + strict, _t2, _ = _run_metrics(tmp_path, _metrics_frame(), "--negatives", "all_label0") + assert default["metrics"]["n_neg"] == 5 + assert strict["metrics"]["n_neg"] == 7 + assert any("all label==0" in s["definition"] for s in default["sensitivity"]) + + +def test_offtarget_metrics_ambiguous_never_silently_negative(tmp_path): + """Sub-credibility label==1 rows are the training-table analogue of the unreviewed + manual-review rows: excluded by default, counted as negatives only on request.""" + default, _t, _ = _run_metrics(tmp_path, _metrics_frame()) + forced, _t2, _ = _run_metrics(tmp_path, _metrics_frame(), "--ambiguous-as-negative") + assert default["metrics"]["n_neg"] == 5 + assert forced["metrics"]["n_neg"] == 8 # + the 3 ambiguous rows + assert forced["counts"]["n_ambiguous"] == 0 + + +@pytest.mark.parametrize("mutate,expect", [ + (lambda d: d[d["label"] == 1], "single-class"), # no negatives at all + (lambda d: d.assign(ecs_if=0.0, ecs_indel_reads=0), "single-class"), # no credible pos +]) +def test_offtarget_metrics_degenerate_exits_zero(tmp_path, mutate, expect): + """A run with no credible positives is a legitimate result, not an error: the file + still has to be published, with nulls and an explanatory note.""" + out, txt, proc = _run_metrics(tmp_path, mutate(_metrics_frame())) + assert proc.returncode == 0 + assert out["metrics"] is None + assert expect in out["note"] + assert "manual review" in txt.lower() # denominators still documented + + +def test_offtarget_metrics_all_nan_scores_exits_zero(tmp_path): + """All-NaN scores must not be filled with 0 — that would fabricate confident + negatives. Ranking metrics go null, the exclusion count is reported.""" + df = _metrics_frame() + df["score"] = float("nan") + out, _txt, proc = _run_metrics(tmp_path, df) + assert proc.returncode == 0 + assert out["metrics"]["pr_auc"] is None + assert out["metrics"]["n_excluded_no_score"] == 16 # 11 pos + 5 neg + + +# -------------------------------------------------------------------------- +# Reference-context + cut-site features (added after auditing the model against +# the manual-review rules). These are pure functions over a sequence / record +# list, so they are unit-testable without CRAMs. +# -------------------------------------------------------------------------- +sys.path.insert(0, str(BIN)) + + +class _FakeFasta: + """Minimal pysam.FastaFile stand-in: fetch(chrom, start, end) -> str.""" + + def __init__(self, seq): + self.seq = seq + + def fetch(self, chrom, start, end): + return self.seq[max(0, start):end] + + +def test_homopolymer_run_only_counts_runs_touching_the_site(): + from features import homopolymer_run + # a run AT the site is reported + assert homopolymer_run("CGAAAAAGC", 4) == 5 + # the same run far from the site is NOT: a homopolymer 8bp away does not + # explain an indel here, and counting it would flag every read near any repeat + assert homopolymer_run("AAAAACGCGCG", 9) == 1 + # adjacency counts (a run ending one base before the site still explains a slip) + assert homopolymer_run("AAAAACG", 5) == 5 + assert homopolymer_run("ACGTACGT", 4) == 1 + assert homopolymer_run("", 0) == 0 + + +def test_repeat_context_flags_homopolymer_and_tandem_repeat(): + from features import repeat_context + hp = repeat_context(_FakeFasta("ACGT" * 10 + "A" * 10 + "ACGT" * 10), "c", 45) + assert hp["homopolymer_len"] >= 10 + # a pure trinucleotide repeat is fully covered but has no homopolymer + cag = repeat_context(_FakeFasta("CAG" * 30), "c", 45) + assert cag["repeat_frac"] == 1.0 + assert cag["homopolymer_len"] == 1 + + +def test_repeat_context_returns_zeros_off_contig(): + """A missing/unreadable reference must yield zeros, never fabricated signal.""" + from features import repeat_context + + class Boom: + def fetch(self, *a): + raise KeyError("no such contig") + + assert repeat_context(Boom(), "chrZ", 100) == {"homopolymer_len": 0, "repeat_frac": 0.0} + + +def _rec(spans=True, indel=None, mapq=60, softclip=()): + return {"spans": spans, "indel": indel, "mapq": mapq, "softclip": list(softclip)} + + +def test_cut_dist_is_distance_from_observed_indel_to_predicted_cut(): + from features import features_from_records + # 12 reads carrying a 5bp deletion at ref position 1000, plus 8 clean reads + recs = [_rec(indel=(1000, 5)) for _ in range(12)] + [_rec() for _ in range(8)] + f = features_from_records(recs, min_span=8, cut_pos=1002) + assert f["modal_pos"] == 1000 + assert f["cut_dist"] == 2 # |1000 - 1002| + f_far = features_from_records(recs, min_span=8, cut_pos=1071) + assert f_far["cut_dist"] == 71 + + +def test_cut_dist_is_nan_not_zero_when_no_indel_is_observed(): + """0 would assert the indel sits exactly on the cut. There is no indel at all.""" + import math + from features import features_from_records + f = features_from_records([_rec() for _ in range(20)], min_span=8, cut_pos=1000) + assert f["modal_pos"] is None + assert math.isnan(f["cut_dist"]) + # and NaN when no cut site was supplied, rather than a silent 0 + f2 = features_from_records([_rec(indel=(1000, 5)) for _ in range(20)], min_span=8) + assert math.isnan(f2["cut_dist"]) + + +def test_new_features_are_declared_model_inputs(): + from features import MODEL_FEATURES + for f in ("cut_dist", "homopolymer_len", "repeat_frac"): + assert f in MODEL_FEATURES, f"{f} must be a model input, not just a report column" diff --git a/workflows/offtarget.nf b/workflows/offtarget.nf new file mode 100644 index 0000000..920c85b --- /dev/null +++ b/workflows/offtarget.nf @@ -0,0 +1,194 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Unified CRISPR Off-Target Workflow (entry: -entry OFFTARGET) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Self-contained. Leaves the default SCGE workflow untouched. + + samplesheet (sample,datatype{ecs|wgs},guide,edited_cram,control_cram,target_file,vcf) + ├─ ecs rows ─► ECS_INDELS @ hotspots ─────────────► ECS truth (indel_fraction = VAF) + └─ wgs rows ─► WGS_WORKLIST ─► PON_OFFTARGET_FILTER ─► genome-wide homology-free worklist + │ + paired: HOTSPOT_TO_TABLE ─► SCORE_HOTSPOTS ─► BUILD_TRAINING_TABLE ─► training.tsv + ├► RECALL_VS_VAF ─► recall_vs_vaf.{csv,png} + └► OFFTARGET_METRICS ─► offtarget_metrics.{json,txt} + all : RECONCILE_OFFTARGET_REPORT ─► offtarget_report.csv (is_hotspot / ecs_confirmed) + + Notes for the first real run: + * WGS edited_cram must be the DRAGEN '_tumor.cram'; the matched normal + '.cram' and '.hard-filtered.vcf.gz' must sit beside it (the scripts + derive them by naming convention). CRAMs/VCFs are read by absolute path from + bind-mounted storage, so paths in the samplesheet must be absolute. + * The paired training/recall arm is new code — validate its join on the first run + (coordinate off-by-one between ECS and WGS is the usual culprit for an empty join). +*/ + +include { WGS_WORKLIST } from '../modules/local/wgs_worklist.nf' +include { PON_OFFTARGET_FILTER } from '../modules/local/pon_offtarget_filter.nf' +include { ECS_INDELS } from '../modules/local/ecs_indels.nf' +include { HOTSPOT_TO_TABLE } from '../modules/local/hotspot_to_table.nf' +include { SCORE_HOTSPOTS } from '../modules/local/score_hotspots.nf' +include { BUILD_TRAINING_TABLE } from '../modules/local/build_training_table.nf' +include { RECALL_VS_VAF } from '../modules/local/recall_vs_vaf.nf' +include { OFFTARGET_METRICS } from '../modules/local/offtarget_metrics.nf' +include { RECONCILE_OFFTARGET_REPORT } from '../modules/local/reconcile_offtarget_report.nf' +include { GENERATE_HOTSPOTS } from '../subworkflows/local/generate_hotspots.nf' + +workflow OFFTARGET_WORKFLOW { + + if (!params.input) { error "OFFTARGET: provide --input samplesheet.csv" } + ch_ss = file(params.input, checkIfExists: true) + + // ---- preflight: detect run mode from the sheet and validate datatypes up front, so a + // mistyped or single-arm sheet fails with a clear message (or runs the right arms) instead + // of silently sending empty inputs downstream. Read synchronously — it's a small local file. + def rows = ch_ss.readLines().findAll { it.trim() } + def hdr = rows[0].split(',', -1).collect { it.trim().toLowerCase() } + def dti = hdr.indexOf('datatype') + if (dti < 0) { error "OFFTARGET: --input has no 'datatype' column" } + def dts = rows.drop(1).collect { (it.split(',', -1)[dti] ?: '').trim().toLowerCase() } + def bad = dts.findAll { it && it != 'ecs' && it != 'wgs' }.unique() + if (bad) { error "OFFTARGET: unknown datatype(s) ${bad} in --input (expected ecs|wgs)" } + def n_ecs = dts.count { it == 'ecs' } + def n_wgs = dts.count { it == 'wgs' } + if (n_ecs + n_wgs == 0) { error "OFFTARGET: no ecs/wgs rows in --input" } + def mode = (n_ecs && n_wgs) ? 'paired' : (n_wgs ? 'wgs_only' : 'ecs_only') + log.info "OFFTARGET mode: ${mode} (${n_ecs} ecs, ${n_wgs} wgs rows)" + + // ---- preflight: every ecs row needs a target_file OR a spacer (to auto-generate one via + // GENERATE_HOTSPOTS). Count the auto-generate rows synchronously here so the hotspot + // subworkflow — whose PREP_CASOFFINDER_REF runs once regardless of guide count — is only + // invoked when a row actually needs it (never on a fully target_file-provided sheet). + def n_ecs_auto = 0 + if (n_ecs > 0) { + def sfi = hdr.indexOf('spacer') + def tfi = hdr.indexOf('target_file') + def si2 = hdr.indexOf('sample') + def eprob = [] + rows.drop(1).each { line -> + def cols = line.split(',', -1) + if ((cols[dti] ?: '').trim().toLowerCase() != 'ecs') return + def sample = si2 >= 0 ? (cols[si2] ?: '').trim() : '?' + def tf = tfi >= 0 ? (cols[tfi] ?: '').trim() : '' + def sp = sfi >= 0 ? (cols[sfi] ?: '').trim() : '' + if (!tf && !sp) { + eprob << "row '${sample}': ecs row needs a 'target_file' or a 'spacer' (to auto-generate one)" + } else if (!tf && sp) { + n_ecs_auto++ + } + } + if (eprob) { error "OFFTARGET: ecs preflight failed:\n " + eprob.join('\n ') } + if (n_ecs_auto > 0) { log.info "OFFTARGET: auto-generating hotspots for ${n_ecs_auto} ecs row(s) from their spacer" } + } + + // ---- preflight: WGS rows depend on DRAGEN sidecar files derived from the tumor CRAM name + // by convention (bin/worklist_from_vcf.py, bin/score.py): the matched normal '.cram' + // and the somatic VCF '.hard-filtered.vcf.gz' must sit beside '_tumor.cram'. + // Validate them up front with a named-file error, so a misnamed or missing sidecar fails + // clearly here instead of surfacing as a confusing empty worklist or a mid-run task crash. + // Skipped under -stub-run and -preview, where inputs are placeholder paths that need not exist. + if (n_wgs > 0 && !workflow.stubRun && !workflow.preview) { + def eci = hdr.indexOf('edited_cram') + def si = hdr.indexOf('sample') + if (eci < 0) { error "OFFTARGET: --input has no 'edited_cram' column" } + def problems = [] + rows.drop(1).each { line -> + def cols = line.split(',', -1) + if ((cols[dti] ?: '').trim().toLowerCase() != 'wgs') return + def sample = si >= 0 ? (cols[si] ?: '').trim() : '?' + def tumor = (cols[eci] ?: '').trim() + if (!tumor.endsWith('_tumor.cram')) { + problems << "row '${sample}': WGS edited_cram must be a DRAGEN '_tumor.cram' (got '${tumor}')" + return + } + def base = tumor - ~/_tumor\.cram$/ + [ (tumor) : 'tumor CRAM', + ("${base}.cram".toString()) : 'matched-normal CRAM', + ("${base}.hard-filtered.vcf.gz".toString()): 'DRAGEN somatic VCF' ].each { p, what -> + if (!file(p).exists()) problems << "row '${sample}': missing ${what}: ${p}" + } + } + if (problems) { + error "OFFTARGET: DRAGEN sidecar preflight failed. The WGS arm derives the matched\n" + + "normal and somatic VCF from the tumor CRAM name; each must exist beside it:\n " + + problems.join('\n ') + } + } + + ch_rows = Channel.fromPath(ch_ss) + | splitCsv(header: true) + | branch { row -> + ecs: (row.datatype ?: '').toLowerCase() == 'ecs' + wgs: (row.datatype ?: '').toLowerCase() == 'wgs' + } + + // ---- ECS arm: truth at hotspots ---- + ch_ecs_truth_files = Channel.empty() + if (n_ecs > 0) { + // Rows that already point at a target_file VCF use it directly. + ch_ecs_provided = ch_rows.ecs + .filter { row -> row.target_file?.trim() } + .map { row -> tuple([id: row.sample, guide: row.guide], + row.edited_cram, row.control_cram, row.target_file) } + + if (n_ecs_auto > 0) { + // Rows with a spacer but no target_file: auto-generate the hotspot VCF once per + // guide, then broadcast it to every ecs replicate of that guide. + ch_ecs_auto = ch_rows.ecs.filter { row -> !row.target_file?.trim() && row.spacer?.trim() } + + ch_guides = ch_ecs_auto + .map { row -> tuple(row.guide, row.spacer.trim().toUpperCase(), + (row.pam?.trim() ?: params.offtarget_pam)) } + .unique() + .map { guide, spacer, pam -> tuple([id: guide], spacer, pam, + file("${projectDir}/assets/NO_IDT")) } + + GENERATE_HOTSPOTS(ch_guides) + + ch_ecs_auto_in = ch_ecs_auto + .map { row -> tuple(row.guide, [id: row.sample, guide: row.guide], + row.edited_cram, row.control_cram) } + .combine(GENERATE_HOTSPOTS.out.vcf.map { meta, vcf -> tuple(meta.id, vcf) }, by: 0) + .map { guide, meta, ed, ctl, vcf -> tuple(meta, ed, ctl, vcf) } + + ch_ecs_in = ch_ecs_provided.mix(ch_ecs_auto_in) + } else { + ch_ecs_in = ch_ecs_provided + } + + ECS_INDELS(ch_ecs_in, params.fasta) + ch_ecs_truth_files = ECS_INDELS.out.indels_file.map { meta, tsv -> tsv } + } + + // ---- WGS arm: genome-wide homology-free discovery + PoN ---- + if (n_wgs > 0) { + // build the sampletumor_cram map the scripts consume (single source of truth) + ch_cram_map = ch_rows.wgs + .map { row -> "${row.sample}\t${row.edited_cram}" } + .collectFile(name: 'wgs_cram_map.tsv', newLine: true, sort: true) + + WGS_WORKLIST(ch_cram_map, file(params.offtarget_shape_model), params.fasta) + PON_OFFTARGET_FILTER(WGS_WORKLIST.out.worklist, ch_cram_map, params.fasta) + } + + // ---- paired arm: ECS-truth ⋈ WGS-features → training table + recall-vs-VAF ---- + // Only meaningful when BOTH arms are present. + ch_truth = Channel.empty() + if (n_ecs > 0 && n_wgs > 0) { + HOTSPOT_TO_TABLE(ch_ecs_truth_files.collect(), ch_ss) + SCORE_HOTSPOTS(HOTSPOT_TO_TABLE.out.table, ch_cram_map, + file(params.offtarget_shape_model), params.fasta) + BUILD_TRAINING_TABLE(SCORE_HOTSPOTS.out.scores, HOTSPOT_TO_TABLE.out.truth, ch_ss) + RECALL_VS_VAF(BUILD_TRAINING_TABLE.out.training) + // PR-AUC / F2 / F5 against the ECS label (training.tsv has a real two-class + // label). Recall vs the human review stays with validate_recall.py and stays + // recall-only — that table has no confirmed negatives to divide by. + OFFTARGET_METRICS(BUILD_TRAINING_TABLE.out.training) + ch_truth = HOTSPOT_TO_TABLE.out.truth + } + + // ---- reconciled report: whenever there's a WGS worklist to annotate (truth optional) ---- + if (n_wgs > 0) { + ch_truth_opt = ch_truth.ifEmpty(file("${projectDir}/assets/NO_FILE")) + RECONCILE_OFFTARGET_REPORT(PON_OFFTARGET_FILTER.out.worklist, ch_truth_opt) + } +} diff --git a/workflows/scge.nf b/workflows/scge.nf index 3e02fca..8d88653 100644 --- a/workflows/scge.nf +++ b/workflows/scge.nf @@ -6,7 +6,7 @@ */ include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' -include { paramsSummaryMap } from 'plugin/nf-schema' +include { paramsSummaryMap } from 'plugin/nf-validation' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_scge_pipeline' include { MULTIQC } from '../modules/nf-core/multiqc/main' @@ -20,7 +20,8 @@ include { PREPARE_SOMATIC_FASTQS } from '../subworkflows/local/gather_align include { MAKE_HOTSPOT_VCF } from '../modules/local/make_hotspot_vcf.nf' include { DRAGEN_SCGE } from '../modules/local/dragen_scge.nf' include { SCGE_ANALYSIS } from '../subworkflows/local/scge_analysis.nf' -//include { TRANSGENE_TO_VCF } from '../modules/local/transgene_to_vcf' +// Note: TRANSGENE_TO_VCF is included and invoked inside the SCGE_ANALYSIS subworkflow +// (subworkflows/local/scge_analysis.nf), not here. def generateMetaFromCsv(csv_string) { def lines = csv_string.readLines() @@ -31,6 +32,49 @@ def generateMetaFromCsv(csv_string) { }.findAll { it } } +def check_reference_contig(fasta, contig) { + if (!contig || contig == null || contig == false){ + return true + } + def fai_file = new File("${fasta}.fai") + if (!fai_file.exists()) { + error "ERROR: FASTA index file not found: ${fai_file}" + } + def found = false + fai_file.eachLine { line -> + def current_contig = line.split('\t')[0] + if (current_contig == contig) { + found = true + } + } + if (!found) { + error "ERROR: Contig '${contig}' not found in reference index: ${fai_file}" + } + return true +} + +def check_dragen_hash_contig(dragen_ref, contig) { + // if no contig is passed, then continue + if (!contig || contig == null || contig == false){ + return true + } + def cfg_file = new File("${dragen_ref}/hash_table.cfg") + if (!cfg_file.exists()) { + error "ERROR: DRAGEN hash table config not found: ${cfg_file}" + } + def found = false + def target_string = "'${contig}'" + cfg_file.eachLine { line -> + if (line.contains(target_string)) { + found = true + } + } + if (!found) { + error "ERROR: Contig '${contig}' not found in DRAGEN reference config: ${cfg_file}" + } + return true +} + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CREATE CHANNELS FOR INPUT PARAMETERS @@ -43,10 +87,15 @@ ch_mastersheet = params.input ? Channel.empty() // DRAGEN reference directory -ch_reference_dir = params.refdir +ch_reference_dir = params.refdir && check_dragen_hash_contig(params.refdir, params.transgene_name) ? Channel.fromPath(params.refdir, type: 'dir', checkIfExists: true).collect() : Channel.empty() +// FastA reference +ch_fasta_reference = params.fasta && check_reference_contig(params.fasta, params.transgene_name) + ? Channel.fromPath("${params.fasta}*", checkIfExists: true).collect() + : Channel.empty() + // DRAGEN adapter sequences for read 1 ch_adapter1_file = params.adapter1 ? Channel.fromPath(params.adapter1, checkIfExists: true).collect() @@ -71,11 +120,6 @@ ch_hotspot_bed = params.hotspot_bed ? Channel.fromPath("${params.hotspot_bed}", checkIfExists: true).collect() : [] -// FastA reference -ch_fasta_reference = params.fasta - ? Channel.fromPath("${params.fasta}*", checkIfExists: true).collect() - : Channel.empty() - // SNV systematic noise BED file ch_snv_noisefile = params.snv_noisefile ? Channel.fromPath(params.snv_noisefile, checkIfExists: true).collect() @@ -94,12 +138,12 @@ ch_cram_reference = params.cram_reference // Gene regions / target file for analysis ch_param_target_file = params.target_file ? Channel.fromPath("${params.target_file}", checkIfExists: true).first() - : Channel.value([]) + : [] // Nirvana path ch_nirvana_path = params.nirvana_path - ? Channel.fromPath("${params.nirvana_path}", checkIfExists: true) - : Channel.empty() + ? Channel.fromPath("${params.nirvana_path}", checkIfExists: true).collect() + : [] /* ~~~~~~~~~~~~~~~~~~ @@ -141,10 +185,6 @@ workflow SCGE { ch_dragen_output = Channel.empty() ch_dragen_usage = Channel.empty() - // - // dump samplesheet channel - ch_input_samplesheet.dump(tag:'mastersheet') - // // MODULE: Parse input samplesheet to format samples for processing. // Output of this process are csv files for samples that need to be aligned @@ -155,9 +195,6 @@ workflow SCGE { ) ch_versions = ch_versions.mix(PARSE_INPUT_SAMPLESHEET.out.versions) - PARSE_INPUT_SAMPLESHEET.out.samples_to_align.dump(tag:'alignmentsamples') - PARSE_INPUT_SAMPLESHEET.out.samples_to_analyze.dump(tag:'analysissamples') - // Get dragen outputs and add target files to analyze ch_dragen_output = ch_dragen_output.mix( PARSE_INPUT_SAMPLESHEET.out.samples_to_analyze @@ -182,13 +219,16 @@ workflow SCGE { // get editing target file as separate channel ch_target_files = ch_target_files.mix( ch_sample_meta - .combine(ch_param_target_file) - .map { meta, targetfile -> - if (targetfile){ + .filter{ it.sample_type == "tumor" } + .map { meta -> + def targetfile = params.target_file ? + file(params.target_file, checkIfExists: true) : + (meta.target_file ? file(meta.target_file, checkIfExists: true) : []) + if (targetfile!=[]){ [ meta.id, targetfile ] } else { - [ meta.id, meta.target_file ? file(meta.target_file, checkIfExists: true) : [] ] - } + error "NO Target file provided." + } } ) @@ -238,7 +278,7 @@ workflow SCGE { ch_dragen_output = ch_dragen_output.mix( DRAGEN_SCGE.out.dragen_output .map { meta, dragenfiles -> [ meta.id, meta, dragenfiles ] } - .join(ch_param_target_file) + .join(ch_target_files) .map { id, meta, dragenfiles, targetfile -> [ meta, dragenfiles, targetfile ] } ) } @@ -254,7 +294,7 @@ workflow SCGE { ch_versions = ch_versions.mix(SCGE_ANALYSIS.out.versions) } - + // // // Collate and save software versions @@ -288,7 +328,7 @@ workflow SCGE { ch_multiqc_custom_config.toList(), ch_multiqc_logo.toList() ) - + emit: multiqc_report = MULTIQC.out.report.toList() // channel: [ path(file) ] versions = ch_versions // channel: [ path(file) ] diff --git a/workflows/train.nf b/workflows/train.nf new file mode 100644 index 0000000..9968c51 --- /dev/null +++ b/workflows/train.nf @@ -0,0 +1,25 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Off-Target Model Trainer (entry: -entry TRAIN) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Offline trainer for the WGS shape model. Deliberately kept OUT of the OFFTARGET + DAG (the deployed model stays a fixed asset); this is the explicit retrain loop: + + 1. run -entry OFFTARGET (paired ECS+WGS) on a labeled cohort -> training.tsv + 2. run -entry TRAIN --input training.tsv -> wgs_shape_model.pkl + 3. deploy the new model: -entry OFFTARGET --offtarget_shape_model + + --input is the training.tsv from step 1 (a BUILD_TRAINING_TABLE output). +*/ + +include { TRAIN_SHAPE_MODEL } from '../modules/local/train_shape_model.nf' + +workflow TRAIN_WORKFLOW { + + if (!params.input) { + error "TRAIN: provide --input training.tsv (a BUILD_TRAINING_TABLE output from -entry OFFTARGET)" + } + ch_training = file(params.input, checkIfExists: true) + + TRAIN_SHAPE_MODEL(ch_training) +}