afquery 0.2.2__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. {afquery-0.2.2 → afquery-0.3.0}/.github/workflows/ci.yml +1 -0
  2. afquery-0.3.0/.github/workflows/docs.yml +52 -0
  3. {afquery-0.2.2 → afquery-0.3.0}/.github/workflows/release.yml +29 -56
  4. {afquery-0.2.2 → afquery-0.3.0}/.gitignore +1 -0
  5. afquery-0.3.0/CONTRIBUTING.md +35 -0
  6. {afquery-0.2.2 → afquery-0.3.0}/PKG-INFO +1 -1
  7. afquery-0.3.0/benchmarks/.gitignore +20 -0
  8. afquery-0.3.0/benchmarks/INSTALL.md +141 -0
  9. afquery-0.3.0/benchmarks/README.md +172 -0
  10. afquery-0.3.0/benchmarks/Snakefile +103 -0
  11. afquery-0.3.0/benchmarks/capture_kit/.gitignore +15 -0
  12. afquery-0.3.0/benchmarks/capture_kit/01a_assign_samples.py +130 -0
  13. afquery-0.3.0/benchmarks/capture_kit/01b_write_manifests.py +86 -0
  14. afquery-0.3.0/benchmarks/capture_kit/02_build_databases.py +115 -0
  15. afquery-0.3.0/benchmarks/capture_kit/03_compute_metrics.py +312 -0
  16. afquery-0.3.0/benchmarks/capture_kit/04_classify_acmg.py +199 -0
  17. afquery-0.3.0/benchmarks/capture_kit/05_plot_figures.py +401 -0
  18. afquery-0.3.0/benchmarks/capture_kit/README.md +190 -0
  19. afquery-0.3.0/benchmarks/capture_kit/Snakefile +225 -0
  20. afquery-0.3.0/benchmarks/capture_kit/__init__.py +0 -0
  21. afquery-0.3.0/benchmarks/capture_kit/beds/SureSelect_v5.bed +5060 -0
  22. afquery-0.3.0/benchmarks/capture_kit/beds/SureSelect_v6.bed +5479 -0
  23. afquery-0.3.0/benchmarks/capture_kit/beds/SureSelect_v7.bed +4598 -0
  24. afquery-0.3.0/benchmarks/capture_kit/config.py +84 -0
  25. afquery-0.3.0/benchmarks/config.yaml +21 -0
  26. afquery-0.3.0/benchmarks/envs/benchmark.yaml +31 -0
  27. afquery-0.3.0/benchmarks/performance/.gitignore +17 -0
  28. afquery-0.3.0/benchmarks/performance/01_prepare_data.py +248 -0
  29. afquery-0.3.0/benchmarks/performance/02_query_scaling.py +188 -0
  30. afquery-0.3.0/benchmarks/performance/03_build.py +236 -0
  31. afquery-0.3.0/benchmarks/performance/04_annotate.py +190 -0
  32. afquery-0.3.0/benchmarks/performance/05_vs_bcftools.py +500 -0
  33. afquery-0.3.0/benchmarks/performance/06_plot.py +379 -0
  34. afquery-0.3.0/benchmarks/performance/README.md +162 -0
  35. afquery-0.3.0/benchmarks/performance/Snakefile +464 -0
  36. afquery-0.3.0/benchmarks/performance/collect_annotate.py +82 -0
  37. afquery-0.3.0/benchmarks/performance/collect_bcftools.py +33 -0
  38. afquery-0.3.0/benchmarks/performance/collect_build_perf.py +83 -0
  39. afquery-0.3.0/benchmarks/performance/collect_prepare.py +39 -0
  40. afquery-0.3.0/benchmarks/performance/collect_query_scaling.py +30 -0
  41. afquery-0.3.0/benchmarks/performance/config.py +90 -0
  42. afquery-0.3.0/benchmarks/performance/config_smoke.py +12 -0
  43. afquery-0.3.0/benchmarks/shared/__init__.py +1 -0
  44. afquery-0.3.0/benchmarks/shared/config.py +53 -0
  45. afquery-0.3.0/benchmarks/shared/rules/download_1kg.smk +138 -0
  46. afquery-0.3.0/benchmarks/shared/utils.py +104 -0
  47. afquery-0.3.0/docs/advanced/coverage-evidence.md +192 -0
  48. {afquery-0.2.2 → afquery-0.3.0}/docs/faq.md +13 -0
  49. {afquery-0.2.2 → afquery-0.3.0}/docs/getting-started/preprocessing.md +1 -0
  50. {afquery-0.2.2 → afquery-0.3.0}/docs/getting-started/understanding-output.md +7 -4
  51. {afquery-0.2.2 → afquery-0.3.0}/docs/guides/annotate-vcf.md +1 -0
  52. {afquery-0.2.2 → afquery-0.3.0}/docs/guides/create-database.md +39 -0
  53. {afquery-0.2.2 → afquery-0.3.0}/docs/guides/dump-export.md +7 -4
  54. {afquery-0.2.2 → afquery-0.3.0}/docs/guides/query.md +38 -4
  55. {afquery-0.2.2 → afquery-0.3.0}/docs/guides/update-database.md +22 -0
  56. {afquery-0.2.2 → afquery-0.3.0}/docs/guides/variant-info.md +1 -0
  57. {afquery-0.2.2 → afquery-0.3.0}/docs/reference/cli.md +24 -1
  58. {afquery-0.2.2 → afquery-0.3.0}/docs/reference/glossary.md +4 -0
  59. {afquery-0.2.2 → afquery-0.3.0}/docs/reference/python-api.md +24 -7
  60. {afquery-0.2.2 → afquery-0.3.0}/mkdocs.yml +4 -1
  61. {afquery-0.2.2 → afquery-0.3.0}/recipes/afquery/meta.yaml +5 -11
  62. {afquery-0.2.2 → afquery-0.3.0}/resources/normalize_vcf.sh +1 -1
  63. afquery-0.3.0/src/afquery/_version.py +24 -0
  64. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/annotate.py +46 -22
  65. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/cli.py +57 -8
  66. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/database.py +39 -9
  67. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/dump.py +32 -14
  68. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/models.py +12 -2
  69. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/preprocess/__init__.py +34 -3
  70. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/preprocess/build.py +159 -21
  71. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/preprocess/compact.py +28 -8
  72. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/preprocess/ingest.py +47 -0
  73. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/preprocess/synth.py +1 -1
  74. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/preprocess/update.py +150 -26
  75. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/query.py +205 -32
  76. {afquery-0.2.2 → afquery-0.3.0}/tests/conftest.py +17 -12
  77. {afquery-0.2.2 → afquery-0.3.0}/tests/test_haploid_stats.py +5 -2
  78. afquery-0.3.0/tests/test_no_coverage.py +299 -0
  79. {afquery-0.2.2 → afquery-0.3.0}/tests/test_preprocess.py +5 -1
  80. {afquery-0.2.2 → afquery-0.3.0}/tests/test_variant_info.py +78 -1
  81. afquery-0.2.2/.github/workflows/docs.yml +0 -38
  82. afquery-0.2.2/src/afquery/_version.py +0 -34
  83. {afquery-0.2.2 → afquery-0.3.0}/.dockerignore +0 -0
  84. {afquery-0.2.2 → afquery-0.3.0}/Dockerfile +0 -0
  85. {afquery-0.2.2 → afquery-0.3.0}/LICENSE +0 -0
  86. {afquery-0.2.2 → afquery-0.3.0}/README.md +0 -0
  87. {afquery-0.2.2 → afquery-0.3.0}/docs/advanced/benchmarking.md +0 -0
  88. {afquery-0.2.2 → afquery-0.3.0}/docs/advanced/debugging-results.md +0 -0
  89. {afquery-0.2.2 → afquery-0.3.0}/docs/advanced/filter-pass-tracking.md +0 -0
  90. {afquery-0.2.2 → afquery-0.3.0}/docs/advanced/multi-cohort-strategies.md +0 -0
  91. {afquery-0.2.2 → afquery-0.3.0}/docs/advanced/performance.md +0 -0
  92. {afquery-0.2.2 → afquery-0.3.0}/docs/advanced/pipeline-integration.md +0 -0
  93. {afquery-0.2.2 → afquery-0.3.0}/docs/advanced/ploidy-and-sex-chroms.md +0 -0
  94. {afquery-0.2.2 → afquery-0.3.0}/docs/assets/img/gap2_mixed_technologies.png +0 -0
  95. {afquery-0.2.2 → afquery-0.3.0}/docs/getting-started/concepts.md +0 -0
  96. {afquery-0.2.2 → afquery-0.3.0}/docs/getting-started/installation.md +0 -0
  97. {afquery-0.2.2 → afquery-0.3.0}/docs/getting-started/motivation.md +0 -0
  98. {afquery-0.2.2 → afquery-0.3.0}/docs/getting-started/quickstart.md +0 -0
  99. {afquery-0.2.2 → afquery-0.3.0}/docs/getting-started/tutorial.md +0 -0
  100. {afquery-0.2.2 → afquery-0.3.0}/docs/guides/manifest-format.md +0 -0
  101. {afquery-0.2.2 → afquery-0.3.0}/docs/guides/sample-filtering.md +0 -0
  102. {afquery-0.2.2 → afquery-0.3.0}/docs/index.md +0 -0
  103. {afquery-0.2.2 → afquery-0.3.0}/docs/reference/data-model.md +0 -0
  104. {afquery-0.2.2 → afquery-0.3.0}/docs/scripts/gen_gap2_figure.py +0 -0
  105. {afquery-0.2.2 → afquery-0.3.0}/docs/stylesheets/extra.css +0 -0
  106. {afquery-0.2.2 → afquery-0.3.0}/docs/troubleshooting.md +0 -0
  107. {afquery-0.2.2 → afquery-0.3.0}/docs/use-cases/acmg-use-cases.md +0 -0
  108. {afquery-0.2.2 → afquery-0.3.0}/docs/use-cases/clinical-prioritization.md +0 -0
  109. {afquery-0.2.2 → afquery-0.3.0}/docs/use-cases/cohort-stratification.md +0 -0
  110. {afquery-0.2.2 → afquery-0.3.0}/docs/use-cases/population-specific-af.md +0 -0
  111. {afquery-0.2.2 → afquery-0.3.0}/docs/use-cases/pseudo-controls.md +0 -0
  112. {afquery-0.2.2 → afquery-0.3.0}/docs/use-cases/sex-specific-af.md +0 -0
  113. {afquery-0.2.2 → afquery-0.3.0}/docs/use-cases/technology-integration.md +0 -0
  114. {afquery-0.2.2 → afquery-0.3.0}/examples/demo/README.md +0 -0
  115. {afquery-0.2.2 → afquery-0.3.0}/examples/demo/create_demo_data.py +0 -0
  116. {afquery-0.2.2 → afquery-0.3.0}/pyproject.toml +0 -0
  117. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/__init__.py +0 -0
  118. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/benchmark.py +0 -0
  119. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/bitmaps.py +0 -0
  120. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/capture.py +0 -0
  121. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/cli.pyr +0 -0
  122. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/constants.py +0 -0
  123. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/ploidy.py +0 -0
  124. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/preprocess/manifest.py +0 -0
  125. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/preprocess/regions.py +0 -0
  126. {afquery-0.2.2 → afquery-0.3.0}/src/afquery/variant_info.py +0 -0
  127. {afquery-0.2.2 → afquery-0.3.0}/tests/data/annotate_input.vcf +0 -0
  128. {afquery-0.2.2 → afquery-0.3.0}/tests/data/annotate_multi_bucket.vcf +0 -0
  129. {afquery-0.2.2 → afquery-0.3.0}/tests/data/annotate_multi_chrom.vcf +0 -0
  130. {afquery-0.2.2 → afquery-0.3.0}/tests/data/beds/wes_kit_a.bed +0 -0
  131. {afquery-0.2.2 → afquery-0.3.0}/tests/data/beds/wes_kit_b.bed +0 -0
  132. {afquery-0.2.2 → afquery-0.3.0}/tests/data/expected_results.json +0 -0
  133. {afquery-0.2.2 → afquery-0.3.0}/tests/data/manifest.tsv +0 -0
  134. {afquery-0.2.2 → afquery-0.3.0}/tests/data/vcfs/S00.vcf +0 -0
  135. {afquery-0.2.2 → afquery-0.3.0}/tests/data/vcfs/S01.vcf +0 -0
  136. {afquery-0.2.2 → afquery-0.3.0}/tests/data/vcfs/S02.vcf +0 -0
  137. {afquery-0.2.2 → afquery-0.3.0}/tests/data/vcfs/S03.vcf +0 -0
  138. {afquery-0.2.2 → afquery-0.3.0}/tests/data/vcfs/S04.vcf +0 -0
  139. {afquery-0.2.2 → afquery-0.3.0}/tests/data/vcfs/S05.vcf +0 -0
  140. {afquery-0.2.2 → afquery-0.3.0}/tests/data/vcfs/S06.vcf +0 -0
  141. {afquery-0.2.2 → afquery-0.3.0}/tests/data/vcfs/S07.vcf +0 -0
  142. {afquery-0.2.2 → afquery-0.3.0}/tests/data/vcfs/S08.vcf +0 -0
  143. {afquery-0.2.2 → afquery-0.3.0}/tests/data/vcfs/S09.vcf +0 -0
  144. {afquery-0.2.2 → afquery-0.3.0}/tests/test_annotate.py +0 -0
  145. {afquery-0.2.2 → afquery-0.3.0}/tests/test_batch.py +0 -0
  146. {afquery-0.2.2 → afquery-0.3.0}/tests/test_benchmark.py +0 -0
  147. {afquery-0.2.2 → afquery-0.3.0}/tests/test_bitmaps.py +0 -0
  148. {afquery-0.2.2 → afquery-0.3.0}/tests/test_capture.py +0 -0
  149. {afquery-0.2.2 → afquery-0.3.0}/tests/test_cli.py +0 -0
  150. {afquery-0.2.2 → afquery-0.3.0}/tests/test_cli_docs_consistency.py +0 -0
  151. {afquery-0.2.2 → afquery-0.3.0}/tests/test_compact.py +0 -0
  152. {afquery-0.2.2 → afquery-0.3.0}/tests/test_constants.py +0 -0
  153. {afquery-0.2.2 → afquery-0.3.0}/tests/test_dump.py +0 -0
  154. {afquery-0.2.2 → afquery-0.3.0}/tests/test_info.py +0 -0
  155. {afquery-0.2.2 → afquery-0.3.0}/tests/test_pass_filter.py +0 -0
  156. {afquery-0.2.2 → afquery-0.3.0}/tests/test_ploidy.py +0 -0
  157. {afquery-0.2.2 → afquery-0.3.0}/tests/test_query.py +0 -0
  158. {afquery-0.2.2 → afquery-0.3.0}/tests/test_sample_filter.py +0 -0
  159. {afquery-0.2.2 → afquery-0.3.0}/tests/test_synth.py +0 -0
  160. {afquery-0.2.2 → afquery-0.3.0}/tests/test_synthetic_stats.py +0 -0
  161. {afquery-0.2.2 → afquery-0.3.0}/tests/test_update.py +0 -0
  162. {afquery-0.2.2 → afquery-0.3.0}/tests/test_update_metadata.py +0 -0
  163. {afquery-0.2.2 → afquery-0.3.0}/tests/test_warnings.py +0 -0
@@ -34,3 +34,4 @@ jobs:
34
34
  token: ${{ secrets.CODECOV_TOKEN }}
35
35
  files: ./coverage.xml
36
36
  fail_ci_if_error: true
37
+ disable-safe: true
@@ -0,0 +1,52 @@
1
+ name: Deploy Documentation
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ paths:
7
+ - 'docs/**'
8
+ - 'mkdocs.yml'
9
+ - 'src/**'
10
+ workflow_dispatch:
11
+ inputs:
12
+ bootstrap:
13
+ description: 'Wipe gh-pages before deploying (one-time when migrating from mkdocs gh-deploy to mike)'
14
+ type: boolean
15
+ default: false
16
+
17
+ permissions:
18
+ contents: write
19
+
20
+ concurrency:
21
+ group: pages
22
+ cancel-in-progress: false
23
+
24
+ jobs:
25
+ deploy:
26
+ runs-on: ubuntu-latest
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+ with:
30
+ fetch-depth: 0
31
+
32
+ - uses: actions/setup-python@v5
33
+ with:
34
+ python-version: '3.11'
35
+
36
+ - name: Install docs dependencies
37
+ run: pip install -e ".[docs]"
38
+
39
+ - name: Configure git for mike
40
+ run: |
41
+ git config --global user.name "github-actions[bot]"
42
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
43
+
44
+ - name: Fetch gh-pages
45
+ run: git fetch origin gh-pages --depth=1 || true
46
+
47
+ - name: Bootstrap gh-pages (wipe old flat-deploy content)
48
+ if: ${{ inputs.bootstrap == true }}
49
+ run: mike delete --all --push --allow-empty
50
+
51
+ - name: Deploy dev docs with mike
52
+ run: mike deploy --push --update-aliases dev
@@ -127,66 +127,39 @@ jobs:
127
127
  ghcr.io/${{ github.repository }}:${{ steps.version.outputs.version }}
128
128
  ghcr.io/${{ github.repository }}:latest
129
129
 
130
- # ── 6. Bioconda PR (final releases only — no "rc" in tag) ────────────
131
- bioconda-pr:
132
- needs: publish-pypi
130
+ # ── 6. Versioned docs → gh-pages via mike (final releases only) ──────
131
+ docs:
132
+ needs: test
133
+ if: ${{ !contains(github.ref_name, 'rc') }}
133
134
  runs-on: ubuntu-latest
134
- if: ${{ !contains(github.ref_name, 'rc') }} # skip RC tags
135
+ permissions:
136
+ contents: write
135
137
  steps:
136
- - name: Get version from tag
137
- run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
138
-
139
- - name: Fetch SHA256 from PyPI
140
- run: |
141
- SHA256=$(curl -s https://pypi.org/pypi/afquery/${VERSION}/json \
142
- | jq -r '.urls[] | select(.packagetype=="sdist") | .digests.sha256')
143
- echo "SHA256=${SHA256}" >> $GITHUB_ENV
144
-
145
- - name: Get fork owner
146
- env:
147
- GH_TOKEN: ${{ secrets.GH_PAT }}
148
- run: echo "FORK_USER=$(gh api user --jq .login)" >> $GITHUB_ENV
149
-
150
- - name: Sync fork with upstream
151
- env:
152
- GH_TOKEN: ${{ secrets.GH_PAT }}
153
- run: gh repo sync ${FORK_USER}/bioconda-recipes --source bioconda/bioconda-recipes --branch master
154
-
155
- - name: Checkout afquery repo
156
- uses: actions/checkout@v4
138
+ - uses: actions/checkout@v4
157
139
  with:
158
- path: afquery-repo
140
+ fetch-depth: 0
159
141
 
160
- - name: Checkout fork of bioconda-recipes
161
- uses: actions/checkout@v4
142
+ - uses: actions/setup-python@v5
162
143
  with:
163
- repository: ${{ env.FORK_USER }}/bioconda-recipes
164
- token: ${{ secrets.GH_PAT }}
165
- path: bioconda-recipes
144
+ python-version: "3.11"
166
145
 
167
- - name: Update recipe
168
- working-directory: bioconda-recipes
169
- run: |
170
- mkdir -p recipes/afquery
171
- cp ../afquery-repo/recipes/afquery/meta.yaml recipes/afquery/meta.yaml
172
- sed -i "s/^{% set version = .* %}/{% set version = \"${VERSION}\" %}/" recipes/afquery/meta.yaml
173
- sed -i "s/sha256: .*/sha256: ${SHA256}/" recipes/afquery/meta.yaml
174
- sed -i "s/^ number: .*/ number: 0/" recipes/afquery/meta.yaml
175
-
176
- - name: Create pull request
177
- working-directory: bioconda-recipes
178
- env:
179
- GH_TOKEN: ${{ secrets.GH_PAT }}
146
+ - name: Install docs dependencies
147
+ run: pip install -e ".[docs]"
148
+
149
+ - name: Configure git for mike
180
150
  run: |
181
- git config user.name "github-actions[bot]"
182
- git config user.email "github-actions[bot]@users.noreply.github.com"
183
- git checkout -b afquery-${VERSION}
184
- git add recipes/afquery/meta.yaml
185
- git commit -m "Update afquery to ${VERSION}"
186
- git push origin afquery-${VERSION}
187
- gh pr create \
188
- --repo bioconda/bioconda-recipes \
189
- --title "Update afquery to ${VERSION}" \
190
- --body "Automated version bump from https://github.com/dlopez-bioinfo/afquery/releases/tag/v${VERSION}" \
191
- --head "${FORK_USER}:afquery-${VERSION}" \
192
- --base master
151
+ git config --global user.name "github-actions[bot]"
152
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
153
+
154
+ - name: Fetch gh-pages
155
+ run: git fetch origin gh-pages --depth=1 || true
156
+
157
+ - name: Extract version
158
+ id: version
159
+ run: echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
160
+
161
+ - name: Deploy versioned docs and update latest alias
162
+ run: mike deploy --push --update-aliases ${{ steps.version.outputs.version }} latest
163
+
164
+ - name: Set default to latest
165
+ run: mike set-default --push latest
@@ -60,3 +60,4 @@ src/afquery/_version.py
60
60
  *.parquet
61
61
  db/*
62
62
  site
63
+ CONTEXT.md
@@ -0,0 +1,35 @@
1
+ # Contributing
2
+
3
+ ## Documentation deployment
4
+
5
+ The published site at <https://dlopez-bioinfo.github.io/afquery/> is built with [MkDocs](https://www.mkdocs.org/) (Material theme) and versioned with [mike](https://github.com/jimporter/mike). Source content lives under `docs/` and is configured by `mkdocs.yml`.
6
+
7
+ ### CI workflows
8
+
9
+ | Workflow | Trigger | What it does |
10
+ |---|---|---|
11
+ | `.github/workflows/docs.yml` | push to `master` (paths: `docs/**`, `mkdocs.yml`, `src/**`) and manual dispatch | `mike deploy --push --update-aliases dev` — publishes the working master under the `dev` alias |
12
+ | `.github/workflows/release.yml` (job `docs`) | push of a `v*` tag (non-`rc`) | `mike deploy --push --update-aliases <version> latest` followed by `mike set-default --push latest` — publishes the tagged version, points `latest` at it, and makes `latest` the site root |
13
+
14
+ ### Cutting a release
15
+
16
+ Tag the commit with a [PEP 440](https://peps.python.org/pep-0440/)-compatible version prefixed with `v` (e.g. `v0.3.0`) and push the tag. The `release.yml` workflow handles PyPI, the GitHub release, the Docker image, and the versioned docs deploy. Pre-release tags (anything containing `rc`) skip Docker and docs publishing.
17
+
18
+ ### Local preview
19
+
20
+ ```bash
21
+ pip install -e ".[docs]"
22
+
23
+ # Plain build — no versioning, fastest iteration on content
24
+ mkdocs serve
25
+
26
+ # Versioned layout — only after running mike deploy locally at least once
27
+ mike deploy 0.0.0-test dev # writes to local gh-pages branch (no push)
28
+ mike serve # serves the gh-pages branch with version selector
29
+ ```
30
+
31
+ To discard local mike state: `git branch -D gh-pages`.
32
+
33
+ ### Migrating from a flat `mkdocs gh-deploy` (one-time)
34
+
35
+ When `gh-pages` still contains content from the previous flat deploy, the first `mike deploy` will leave the old root-level files in place. To wipe `gh-pages` clean before deploying, manually trigger the *Deploy Documentation* workflow with `bootstrap: true`. This runs `mike delete --all --push --allow-empty` before deploying, leaving only the versioned layout (`versions.json` + version subdirectories + redirector at root).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: afquery
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: Genomic allele frequency query engine with bitmap-encoded genotypes
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -0,0 +1,20 @@
1
+ # Benchmark data directories (large, external)
2
+ # Users create these as needed via config.py
3
+
4
+ # pycache
5
+ __pycache__/
6
+ *.pyc
7
+ .pytest_cache/
8
+
9
+ # benchmarking results
10
+ results
11
+ .snakemake
12
+
13
+ # Snakemake log directory
14
+ logs/
15
+
16
+ # Default data directory
17
+ .results/
18
+
19
+ # Local test run logs
20
+ smoke_test.log
@@ -0,0 +1,141 @@
1
+ # Installation Guide for AFQuery Benchmarks
2
+
3
+ This guide covers installing benchmark dependencies in your existing `afquery_bench` micromamba environment.
4
+ See [README.md](./README.md) for the recommended setup using `envs/benchmark.yaml`.
5
+
6
+ ## Option 1: Using conda environment file (Recommended)
7
+
8
+ The easiest way is to create the pre-configured environment:
9
+
10
+ ```bash
11
+ cd benchmarks/
12
+ micromamba env create -f envs/benchmark.yaml
13
+ micromamba activate afquery_bench
14
+ ```
15
+
16
+ Then skip to [Running Benchmarks](#running-benchmarks).
17
+
18
+ ## Option 2: Manual installation
19
+
20
+ If you prefer to install into an existing environment, install dependencies into your `snakemake` micromamba environment:
21
+
22
+ ### Prerequisites
23
+
24
+ You must have:
25
+ - Snakemake ≥ 8 installed in a micromamba environment named `snakemake`
26
+
27
+ If not, install it:
28
+ ```bash
29
+ micromamba install -n snakemake snakemake
30
+ ```
31
+
32
+ ### Install all dependencies at once
33
+
34
+ ```bash
35
+ micromamba run -n snakemake mamba install \
36
+ -c bioconda -c conda-forge \
37
+ bcftools bedtools matplotlib numpy pandas scipy wget \
38
+ && micromamba run -n snakemake pip install afquery
39
+ ```
40
+
41
+ ### Or step-by-step installation
42
+
43
+ #### 1. Bioinformatics tools
44
+
45
+ ```bash
46
+ micromamba run -n snakemake mamba install \
47
+ -c bioconda -c conda-forge \
48
+ bcftools bedtools wget
49
+ ```
50
+
51
+ #### 2. Python scientific libraries
52
+
53
+ ```bash
54
+ micromamba run -n snakemake mamba install \
55
+ -c conda-forge \
56
+ numpy pandas scipy matplotlib
57
+ ```
58
+
59
+ #### 3. AFQuery
60
+
61
+ ```bash
62
+ micromamba run -n snakemake pip install afquery
63
+ ```
64
+
65
+ ## Verification
66
+
67
+ Test that everything is installed:
68
+
69
+ ```bash
70
+ # Test bcftools
71
+ micromamba run -n afquery_bench bcftools --version
72
+
73
+ # Test Python imports
74
+ micromamba run -n afquery_bench python -c "
75
+ import afquery
76
+ import numpy
77
+ import pandas
78
+ import scipy
79
+ import matplotlib
80
+ print('All dependencies OK!')
81
+ "
82
+ ```
83
+
84
+ Expected output:
85
+ ```
86
+ bcftools >=1.17
87
+ All dependencies OK!
88
+ ```
89
+
90
+ ## Running Benchmarks
91
+
92
+ Once dependencies are installed and the environment is active:
93
+
94
+ ```bash
95
+ cd benchmarks/
96
+ micromamba activate afquery_bench
97
+ snakemake --cores 52 all
98
+ ```
99
+
100
+ Or run with conda activation:
101
+
102
+ ```bash
103
+ micromamba run -n afquery_bench snakemake --cores 52 all
104
+ ```
105
+
106
+ See [README.md](./README.md) for more options (smoke test, dry-run, etc.).
107
+
108
+ ## Troubleshooting
109
+
110
+ ### `afquery` import fails
111
+
112
+ Verify the installation:
113
+ ```bash
114
+ micromamba run -n afquery_bench pip show afquery
115
+ ```
116
+
117
+ If not found, reinstall:
118
+ ```bash
119
+ micromamba run -n afquery_bench pip install --upgrade afquery
120
+ ```
121
+
122
+ ### Missing Python packages
123
+
124
+ Check installed packages:
125
+ ```bash
126
+ micromamba run -n afquery_bench pip list | grep -E "numpy|pandas|scipy|matplotlib"
127
+ ```
128
+
129
+ If any are missing, re-run the mamba install commands above.
130
+
131
+ ### `bcftools` not found
132
+
133
+ Verify bcftools is installed:
134
+ ```bash
135
+ micromamba run -n afquery_bench which bcftools
136
+ ```
137
+
138
+ If not found, install it:
139
+ ```bash
140
+ micromamba run -n afquery_bench mamba install -c bioconda bcftools
141
+ ```
@@ -0,0 +1,172 @@
1
+ # AFQuery Benchmarking Suite
2
+
3
+ This directory contains benchmarking experiments for AFQuery.
4
+
5
+ ## Benchmark Categories
6
+
7
+ ### 1. [Performance Benchmarks](./performance/README.md)
8
+
9
+ Core performance characterization across 4 experiments:
10
+
11
+ - **Experiment 1:** Query latency scaling with sample count
12
+ - **Experiment 2:** Build time scaling with parallelism
13
+ - **Experiment 3:** VCF annotation throughput
14
+ - **Experiment 4:** AFQuery vs. bcftools comparison
15
+
16
+ Uses real 1000 Genomes data (chr22) and synthetic datasets (1K-50K samples).
17
+
18
+ ### 2. [Capture Kit Benchmark](./capture_kit/README.md)
19
+
20
+ Capture kit mixing impact on allele frequency classification:
21
+
22
+ - Sample generation with three Agilent SureSelect kits (v5, v6, v7)
23
+ - Three mixing scenarios (balanced, skewed, extreme)
24
+ - ACMG classification discordance analysis with directional error decomposition (toward-pathogenic vs. toward-benign)
25
+ - Coverage overlap metrics
26
+
27
+ ## Prerequisites
28
+
29
+ - micromamba with `snakemake` environment already set up (with Snakemake >= 8 and SLURM executor plugin)
30
+ - Benchmark dependencies installed in the `snakemake` environment (see Environment Setup section)
31
+ - `/usr/bin/time` (GNU time) for memory profiling -- should be available on most Linux systems
32
+ - ~200 GB disk space for all 1KG data and databases
33
+
34
+ ## Environment Setup
35
+
36
+ All benchmark dependencies are installed in the `snakemake` micromamba environment.
37
+
38
+ ### Install dependencies
39
+
40
+ The benchmark requires:
41
+ - External bioinformatics tools: bcftools >= 1.18, bedtools, bgzip/tabix
42
+ - Python packages: pandas, numpy, scipy, matplotlib
43
+ - AFQuery and its dependencies: pyroaring, pyarrow, duckdb, cyvcf2, pyranges, click, tqdm
44
+
45
+ Install them in your `snakemake` environment:
46
+
47
+ ```bash
48
+ micromamba run -n snakemake mamba install \
49
+ -c bioconda -c conda-forge \
50
+ bcftools bedtools matplotlib numpy pandas scipy wget \
51
+ && micromamba run -n snakemake \
52
+ pip install -e <path_to_afquery_repo>
53
+ ```
54
+
55
+ ### Verify
56
+
57
+ ```bash
58
+ micromamba run -n snakemake bcftools --version
59
+ micromamba run -n snakemake python -c "import afquery; print('OK')"
60
+ ```
61
+
62
+ ## Running the Benchmarks
63
+
64
+ All commands below are run from the `benchmarks/` directory. Activate the `snakemake` environment first:
65
+
66
+ ```bash
67
+ micromamba activate snakemake
68
+ ```
69
+
70
+ Then use Snakemake with `--cores 52` to utilize all local CPU cores:
71
+
72
+ ```bash
73
+ # Run everything (both benchmarks)
74
+ snakemake --cores 52 all
75
+
76
+ # Run individual benchmarks
77
+ snakemake --cores 52 performance_all
78
+ snakemake --cores 52 capture_kit_all
79
+
80
+ # Download 1KG data only (prerequisite for both)
81
+ snakemake --cores 52 download_1kg
82
+
83
+ # Dry run (preview what will execute)
84
+ snakemake --cores 52 --dry-run all
85
+
86
+ # Smoke test (fast validation with small parameter scales)
87
+ snakemake --cores 52 --config smoke_test=true all
88
+ ```
89
+
90
+ ### Smoke Test
91
+
92
+ The `smoke_test=true` flag reduces both pipelines to minimal scales for fast validation:
93
+
94
+ - **Performance:** 1 synthetic scale (1K), 1 1KG subset (500), 2 thread counts (1, 4), 1 rep
95
+ - **Capture kit:** 50 samples, balanced scenario only
96
+
97
+ This is useful for verifying pipeline logic without waiting for full-scale runs.
98
+
99
+ ### Resuming after a failure
100
+
101
+ Snakemake uses output files to track completed steps. Re-running any command above will automatically skip steps whose outputs already exist and resume from the first incomplete step.
102
+
103
+ ## Directory Structure
104
+
105
+ ```
106
+ benchmarks/
107
+ ├── Snakefile # Root pipeline (includes both benchmarks)
108
+ ├── config.yaml # Global parameters (data_dir, threads, etc.)
109
+ ├── envs/
110
+ │ └── benchmark.yaml # conda/micromamba environment spec
111
+ ├── shared/
112
+ │ ├── __init__.py
113
+ │ ├── config.py # Common constants: DATA_DIR, 1KG paths, SEED
114
+ │ ├── utils.py # Common helpers: stats, time_ms, save_figure, WONG_COLORS
115
+ │ └── rules/
116
+ │ └── download_1kg.smk # Shared Snakemake rules: download + split 1KG
117
+ ├── performance/
118
+ │ ├── Snakefile # Performance-specific rules
119
+ │ ├── config.py # Performance parameters (scales, reps, thread counts)
120
+ │ ├── config_smoke.py # Minimal config for quick smoke testing
121
+ │ ├── 01_prepare_data.py
122
+ │ ├── 02_query_scaling.py
123
+ │ ├── 03_build.py
124
+ │ ├── 04_annotate.py
125
+ │ ├── 05_vs_bcftools.py
126
+ │ ├── 06_plot.py
127
+ │ ├── collect_prepare.py # Aggregation scripts
128
+ │ ├── collect_query_scaling.py
129
+ │ ├── collect_build_perf.py
130
+ │ ├── collect_annotate.py
131
+ │ └── collect_bcftools.py
132
+ └── capture_kit/
133
+ ├── Snakefile # Capture kit-specific rules
134
+ ├── config.py # Capture kit parameters (scenarios, ACMG thresholds)
135
+ ├── beds/ # Agilent SureSelect BED files (chr22, committed)
136
+ │ ├── SureSelect_v5.bed
137
+ │ ├── SureSelect_v6.bed
138
+ │ └── SureSelect_v7.bed
139
+ ├── 01a_assign_samples.py # Subsample & assign technologies
140
+ ├── 01b_write_manifests.py # Write AFQuery manifest TSVs
141
+ ├── 02_build_databases.py
142
+ ├── 03_compute_metrics.py
143
+ ├── 04_classify_acmg.py
144
+ └── 05_plot_figures.py
145
+ ```
146
+
147
+ ## Configuration
148
+
149
+ Edit `config.yaml` to set the data directory and global parameters:
150
+
151
+ ```yaml
152
+ data_dir: "/path/to/bench_data" # needs ~200 GB free
153
+ build_memory: "8GB" # DuckDB memory per worker
154
+ ```
155
+
156
+ The data directory can also be set via the `AFQUERY_BENCH_DATA` environment variable.
157
+
158
+ ## Known Limitations
159
+
160
+ - **Chromosome scope:** All benchmarks use only chromosome 22 (1000 Genomes Phase 3). Chr22 is one of the smallest autosomes (~51 Mb) and coverage patterns may not be representative of genome-wide behavior. The paper's methods section should discuss generalizability.
161
+ - **Synthetic data for scaling:** Query scaling experiments (1K-50K samples) use synthetic data. Allele frequency spectra and LD patterns differ from real population data.
162
+ - **Capture kits:** The capture kit benchmark uses only Agilent SureSelect kits (v5, v6, v7). Other vendors (Illumina, Roche) and custom panels are not evaluated.
163
+
164
+ ## Reproducibility
165
+
166
+ All random seeds are fixed in `shared/config.py` (SEED = 42).
167
+ Re-running with the same configuration produces identical results within timing noise.
168
+
169
+ ## References
170
+
171
+ - Weber LM et al. (2019). Essential guidelines for computational method benchmarking. *Genome Biology* 20:125. DOI: 10.1186/s13059-019-1738-8
172
+ - Auton A et al. (2015). A global reference for human genetic variation. *Nature* 526:68-74. DOI: 10.1038/nature15393
@@ -0,0 +1,103 @@
1
+ """Unified benchmark pipeline for AFQuery.
2
+
3
+ Usage (run from benchmarks/ directory):
4
+ # All benchmarks
5
+ snakemake --cores 52 all
6
+
7
+ # Only performance benchmark
8
+ snakemake --cores 52 performance_all
9
+
10
+ # Only capture kit benchmark
11
+ snakemake --cores 52 capture_kit_all
12
+
13
+ # Only download 1KG data
14
+ snakemake --cores 52 download_1kg
15
+
16
+ # Dry run (preview rules to execute)
17
+ snakemake --cores 52 --dry-run all
18
+
19
+ # Smoke test (fast validation with small scales)
20
+ snakemake --cores 52 --config smoke_test=true all
21
+ """
22
+
23
+ import sys
24
+ from pathlib import Path
25
+
26
+ # Make shared/ importable from within Snakemake rules
27
+ _bench = Path(workflow.basedir)
28
+ sys.path.insert(0, str(_bench))
29
+
30
+ from shared.config import ( # noqa: E402
31
+ DATA_DIR,
32
+ ONEKG_DIR,
33
+ ONEKG_MANIFEST,
34
+ SEED,
35
+ )
36
+
37
+ # ---------------------------------------------------------------------------
38
+ # Global settings
39
+ # ---------------------------------------------------------------------------
40
+ configfile: "config.yaml"
41
+
42
+ # NOTE: conda env management is DISABLED. Dependencies are installed manually
43
+ # in the snakemake environment. Conda path normalization is no longer needed.
44
+ # if config.get("conda_env_file"):
45
+ # _conda_env = Path(config["conda_env_file"])
46
+ # if not _conda_env.is_absolute():
47
+ # config["conda_env_file"] = str((_bench / _conda_env).resolve())
48
+
49
+
50
+
51
+ # Guard: data_dir must be set
52
+ if not config.get("data_dir", "").strip():
53
+ raise WorkflowError(
54
+ "config.yaml: 'data_dir' is not set. "
55
+ "Edit config.yaml or pass --config data_dir=/path/to/data"
56
+ )
57
+
58
+ # Override DATA_DIR from config if provided
59
+ if config.get("data_dir"):
60
+ import shared.config as _sc
61
+ _sc._set_data_dir(Path(config["data_dir"]))
62
+ DATA_DIR = _sc.DATA_DIR
63
+ ONEKG_DIR = _sc.ONEKG_DIR
64
+ ONEKG_MANIFEST = _sc.ONEKG_MANIFEST
65
+
66
+ # Propagate the resolved DATA_DIR to all child processes via environment.
67
+ # Python scripts import shared.config fresh in each subprocess; without this
68
+ # they fall back to the default Path(".results") and cannot find pipeline outputs.
69
+ import os as _os
70
+ _os.environ["AFQUERY_BENCH_DATA"] = str(DATA_DIR.resolve())
71
+ if config.get("smoke_test"):
72
+ _os.environ["AFQUERY_BENCH_SMOKE"] = "1"
73
+
74
+ # Export constants to sub-Snakefiles via globals
75
+ workflow._globals = {} # not needed; sub-files access via import
76
+
77
+ # ---------------------------------------------------------------------------
78
+ # Create log directories before any rule runs (Snakemake does not auto-create
79
+ # log dirs, unlike output dirs).
80
+ # ---------------------------------------------------------------------------
81
+ onstart:
82
+ import os
83
+ for subdir in ["performance", "capture_kit"]:
84
+ os.makedirs(f"logs/{subdir}", exist_ok=True)
85
+
86
+
87
+ # ---------------------------------------------------------------------------
88
+ # Include sub-pipelines
89
+ # ---------------------------------------------------------------------------
90
+ include: "shared/rules/download_1kg.smk"
91
+ include: "performance/Snakefile"
92
+ include: "capture_kit/Snakefile"
93
+
94
+ # ---------------------------------------------------------------------------
95
+ # Top-level targets
96
+ # ---------------------------------------------------------------------------
97
+
98
+
99
+ rule all:
100
+ """Run both benchmarks end-to-end."""
101
+ input:
102
+ rules.performance_all.output,
103
+ rules.capture_kit_all.output,
@@ -0,0 +1,15 @@
1
+ # Benchmark data and results
2
+ /results/
3
+ /figures/
4
+ *.csv
5
+ *.pdf
6
+ *.png
7
+
8
+ # Cache
9
+ __pycache__/
10
+ *.pyc
11
+ .pytest_cache/
12
+
13
+ # Temporary
14
+ *.tmp
15
+