pylocuszoom 0.5.0__tar.gz → 0.6.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.
- pylocuszoom-0.6.0/.github/workflows/publish.yml +108 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/CHANGELOG.md +25 -2
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/PKG-INFO +53 -5
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/README.md +47 -3
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/bioconda/meta.yaml +2 -2
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/docs/USER_GUIDE.md +159 -1
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/examples/eqtl_bokeh.html +5 -5
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/examples/eqtl_plotly.html +1 -1
- pylocuszoom-0.6.0/examples/finemapping_bokeh.html +61 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/examples/finemapping_plotly.html +1 -1
- pylocuszoom-0.6.0/examples/forest_plot.png +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/examples/generate_readme_plots.py +50 -0
- pylocuszoom-0.6.0/examples/phewas_plot.png +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/pyproject.toml +6 -2
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/__init__.py +23 -2
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/backends/base.py +86 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/backends/bokeh_backend.py +116 -20
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/backends/matplotlib_backend.py +69 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/backends/plotly_backend.py +115 -23
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/colors.py +41 -0
- pylocuszoom-0.6.0/src/pylocuszoom/forest.py +37 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/loaders.py +35 -17
- pylocuszoom-0.6.0/src/pylocuszoom/phewas.py +35 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/plotter.py +258 -4
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/recombination.py +45 -31
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/schemas.py +37 -26
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/tests/test_colors.py +25 -0
- pylocuszoom-0.6.0/tests/test_forest.py +54 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/tests/test_loaders.py +134 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/tests/test_notebook_backends.py +133 -0
- pylocuszoom-0.6.0/tests/test_phewas.py +51 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/tests/test_plotter.py +156 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/uv.lock +187 -2
- pylocuszoom-0.5.0/.github/workflows/publish.yml +0 -23
- pylocuszoom-0.5.0/examples/finemapping_bokeh.html +0 -61
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/.gitattributes +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/.github/workflows/ci.yml +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/.gitignore +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/.pre-commit-config.yaml +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/CONTRIBUTING.md +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/LICENSE.md +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/docs/ARCHITECTURE.md +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/examples/eqtl_overlay.png +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/examples/finemapping_plot.png +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/examples/getting_started.ipynb +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/examples/regional_plot.png +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/examples/stacked_plot.png +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/logo.svg +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/backends/__init__.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/eqtl.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/finemapping.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/gene_track.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/labels.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/ld.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/logging.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/py.typed +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/reference_data/__init__.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/src/pylocuszoom/utils.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/tests/conftest.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/tests/test_finemapping.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/tests/test_gene_track.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/tests/test_labels.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/tests/test_ld.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/tests/test_logging.py +0 -0
- {pylocuszoom-0.5.0 → pylocuszoom-0.6.0}/tests/test_recombination.py +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
environment: pypi
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
outputs:
|
|
14
|
+
version: ${{ steps.version.outputs.version }}
|
|
15
|
+
sha256: ${{ steps.sha256.outputs.sha256 }}
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v5
|
|
21
|
+
|
|
22
|
+
- name: Get version
|
|
23
|
+
id: version
|
|
24
|
+
run: |
|
|
25
|
+
VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
|
|
26
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
27
|
+
|
|
28
|
+
- name: Build package
|
|
29
|
+
run: uv build
|
|
30
|
+
|
|
31
|
+
- name: Publish to PyPI
|
|
32
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
33
|
+
|
|
34
|
+
- name: Wait for PyPI availability
|
|
35
|
+
env:
|
|
36
|
+
PKG_VERSION: ${{ steps.version.outputs.version }}
|
|
37
|
+
run: |
|
|
38
|
+
echo "Waiting for pylocuszoom $PKG_VERSION to be available on PyPI..."
|
|
39
|
+
for i in {1..30}; do
|
|
40
|
+
if curl -s "https://pypi.org/pypi/pylocuszoom/$PKG_VERSION/json" | grep -q '"version"'; then
|
|
41
|
+
echo "Package available on PyPI"
|
|
42
|
+
break
|
|
43
|
+
fi
|
|
44
|
+
echo "Attempt $i: Package not yet available, waiting 10s..."
|
|
45
|
+
sleep 10
|
|
46
|
+
done
|
|
47
|
+
|
|
48
|
+
- name: Get SHA256
|
|
49
|
+
id: sha256
|
|
50
|
+
env:
|
|
51
|
+
PKG_VERSION: ${{ steps.version.outputs.version }}
|
|
52
|
+
run: |
|
|
53
|
+
URL="https://pypi.io/packages/source/p/pylocuszoom/pylocuszoom-$PKG_VERSION.tar.gz"
|
|
54
|
+
SHA256=$(curl -sL "$URL" | sha256sum | cut -d' ' -f1)
|
|
55
|
+
echo "sha256=$SHA256" >> "$GITHUB_OUTPUT"
|
|
56
|
+
echo "SHA256: $SHA256"
|
|
57
|
+
|
|
58
|
+
update-bioconda:
|
|
59
|
+
needs: publish
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
steps:
|
|
62
|
+
- uses: actions/checkout@v4
|
|
63
|
+
|
|
64
|
+
- name: Update bioconda/meta.yaml
|
|
65
|
+
env:
|
|
66
|
+
PKG_VERSION: ${{ needs.publish.outputs.version }}
|
|
67
|
+
PKG_SHA256: ${{ needs.publish.outputs.sha256 }}
|
|
68
|
+
run: |
|
|
69
|
+
# Update version
|
|
70
|
+
sed -i "s/{% set version = \".*\" %}/{% set version = \"$PKG_VERSION\" %}/" bioconda/meta.yaml
|
|
71
|
+
|
|
72
|
+
# Update sha256
|
|
73
|
+
sed -i "s/sha256: .*/sha256: $PKG_SHA256/" bioconda/meta.yaml
|
|
74
|
+
|
|
75
|
+
# Update plotly version requirement
|
|
76
|
+
sed -i "s/plotly >=5.0.0/plotly >=5.15.0/" bioconda/meta.yaml
|
|
77
|
+
|
|
78
|
+
# Add new dependencies if missing
|
|
79
|
+
if ! grep -q "pydantic" bioconda/meta.yaml; then
|
|
80
|
+
sed -i '/adjusttext/a\ - pydantic >=2.0.0' bioconda/meta.yaml
|
|
81
|
+
fi
|
|
82
|
+
if ! grep -q "requests" bioconda/meta.yaml; then
|
|
83
|
+
sed -i '/pydantic/a\ - requests >=2.25.0' bioconda/meta.yaml
|
|
84
|
+
fi
|
|
85
|
+
if ! grep -q "tqdm" bioconda/meta.yaml; then
|
|
86
|
+
sed -i '/requests/a\ - tqdm >=4.60.0' bioconda/meta.yaml
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
cat bioconda/meta.yaml
|
|
90
|
+
|
|
91
|
+
- name: Create Pull Request
|
|
92
|
+
uses: peter-evans/create-pull-request@v6
|
|
93
|
+
with:
|
|
94
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
95
|
+
commit-message: "chore: update bioconda recipe for new release"
|
|
96
|
+
branch: bioconda-update
|
|
97
|
+
title: "Update bioconda recipe"
|
|
98
|
+
body: |
|
|
99
|
+
Automated update of bioconda/meta.yaml after PyPI release.
|
|
100
|
+
|
|
101
|
+
**Next steps:**
|
|
102
|
+
1. Review this PR
|
|
103
|
+
2. Merge to main
|
|
104
|
+
3. Copy `bioconda/meta.yaml` to your fork of bioconda-recipes
|
|
105
|
+
4. Submit PR to bioconda-recipes
|
|
106
|
+
labels: |
|
|
107
|
+
bioconda
|
|
108
|
+
automated
|
|
@@ -5,7 +5,29 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [0.6.0] - 2026-01-27
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `plot_phewas()` method for phenome-wide association study plots
|
|
12
|
+
- `plot_forest()` method for forest plots (meta-analysis visualization)
|
|
13
|
+
- PheWAS category color palette with 12 distinct colors
|
|
14
|
+
- Forest plot and PheWAS validation utilities
|
|
15
|
+
- Backend methods: `axvline()`, `hbar()`, `errorbar_h()` for new plot types
|
|
16
|
+
- Example plots for PheWAS and forest plots
|
|
17
|
+
- Progress bars (tqdm) for recombination map and liftover chain downloads
|
|
18
|
+
- `requests` and `tqdm` as core dependencies for reliable downloads with progress
|
|
19
|
+
- `pytest-randomly` and `pytest-xdist` as dev dependencies for test randomization and parallel execution
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- Bumped minimum Plotly version to 5.15.0 (required for multiple legends feature)
|
|
23
|
+
- eQTL loaders now output `effect_size` column instead of `effect` for plotter compatibility
|
|
24
|
+
- Download functions now use `requests` with streaming and progress bars instead of `urllib`
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- SAIGE loader now prefers SPA-adjusted p-values (`p.value.NA`) over raw p-values when both present
|
|
28
|
+
- BED loader now handles BED12 format and files with more than 6 columns
|
|
29
|
+
- eQTL panel in `plot_stacked()` now filters by chromosome in addition to position
|
|
30
|
+
- Validation errors for non-numeric p-values or positions now show clear "must be numeric" message instead of runtime errors
|
|
9
31
|
|
|
10
32
|
## [0.5.0] - 2026-01-27
|
|
11
33
|
|
|
@@ -118,7 +140,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
118
140
|
- bokeh >= 3.8.2
|
|
119
141
|
- kaleido >= 0.2.0
|
|
120
142
|
|
|
121
|
-
[Unreleased]: https://github.com/michael-denyer/pyLocusZoom/compare/v0.
|
|
143
|
+
[Unreleased]: https://github.com/michael-denyer/pyLocusZoom/compare/v0.6.0...HEAD
|
|
144
|
+
[0.6.0]: https://github.com/michael-denyer/pyLocusZoom/compare/v0.5.0...v0.6.0
|
|
122
145
|
[0.5.0]: https://github.com/michael-denyer/pyLocusZoom/compare/v0.4.0...v0.5.0
|
|
123
146
|
[0.4.0]: https://github.com/michael-denyer/pyLocusZoom/compare/v0.3.0...v0.4.0
|
|
124
147
|
[0.3.0]: https://github.com/michael-denyer/pyLocusZoom/compare/v0.2.0...v0.3.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pylocuszoom
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Publication-ready regional association plots with LD coloring, gene tracks, and recombination overlays
|
|
5
5
|
Project-URL: Homepage, https://github.com/michael-denyer/pylocuszoom
|
|
6
6
|
Project-URL: Documentation, https://github.com/michael-denyer/pylocuszoom#readme
|
|
@@ -26,13 +26,17 @@ Requires-Dist: loguru>=0.7.0
|
|
|
26
26
|
Requires-Dist: matplotlib>=3.5.0
|
|
27
27
|
Requires-Dist: numpy>=1.21.0
|
|
28
28
|
Requires-Dist: pandas>=1.4.0
|
|
29
|
-
Requires-Dist: plotly>=5.
|
|
29
|
+
Requires-Dist: plotly>=5.15.0
|
|
30
30
|
Requires-Dist: pydantic>=2.0.0
|
|
31
31
|
Requires-Dist: pyliftover>=0.4
|
|
32
|
+
Requires-Dist: requests>=2.25.0
|
|
33
|
+
Requires-Dist: tqdm>=4.60.0
|
|
32
34
|
Provides-Extra: all
|
|
33
35
|
Requires-Dist: pyspark>=3.0.0; extra == 'all'
|
|
34
36
|
Provides-Extra: dev
|
|
35
37
|
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest-randomly>=3.0.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: pytest-xdist>=3.0.0; extra == 'dev'
|
|
36
40
|
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
37
41
|
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
38
42
|
Provides-Extra: spark
|
|
@@ -73,9 +77,11 @@ Inspired by [LocusZoom](http://locuszoom.org/) and [locuszoomr](https://github.c
|
|
|
73
77
|
2. **Stacked plots**: Compare multiple GWAS/phenotypes vertically
|
|
74
78
|
3. **eQTL plot**: Expression QTL data aligned with association plots and gene tracks
|
|
75
79
|
4. **Fine-mapping plots**: Visualize SuSiE credible sets with posterior inclusion probabilities
|
|
76
|
-
5. **
|
|
77
|
-
6. **
|
|
78
|
-
7. **
|
|
80
|
+
5. **PheWAS plots**: Phenome-wide association study visualization across multiple phenotypes
|
|
81
|
+
6. **Forest plots**: Meta-analysis effect size visualization with confidence intervals
|
|
82
|
+
7. **Multiple charting libraries**: matplotlib (static), plotly (interactive), bokeh (dashboards)
|
|
83
|
+
8. **Pandas and PySpark support**: Works with both Pandas and PySpark DataFrames for large-scale genomics data
|
|
84
|
+
9. **Convenience data file loaders**: Load and validate common GWAS, eQTL and fine-mapping file formats
|
|
79
85
|
|
|
80
86
|
## Installation
|
|
81
87
|
|
|
@@ -261,6 +267,48 @@ fig = plotter.plot_stacked(
|
|
|
261
267
|
|
|
262
268
|

|
|
263
269
|
|
|
270
|
+
## PheWAS Plots
|
|
271
|
+
|
|
272
|
+
Visualize associations of a single variant across multiple phenotypes:
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
phewas_df = pd.DataFrame({
|
|
276
|
+
"phenotype": ["Height", "BMI", "T2D", "CAD", "HDL"],
|
|
277
|
+
"p_value": [1e-15, 0.05, 1e-8, 1e-3, 1e-10],
|
|
278
|
+
"category": ["Anthropometric", "Anthropometric", "Metabolic", "Cardiovascular", "Lipids"],
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
fig = plotter.plot_phewas(
|
|
282
|
+
phewas_df,
|
|
283
|
+
variant_id="rs12345",
|
|
284
|
+
category_col="category",
|
|
285
|
+
)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+

|
|
289
|
+
|
|
290
|
+
## Forest Plots
|
|
291
|
+
|
|
292
|
+
Create forest plots for meta-analysis visualization:
|
|
293
|
+
|
|
294
|
+
```python
|
|
295
|
+
forest_df = pd.DataFrame({
|
|
296
|
+
"study": ["Study A", "Study B", "Study C", "Meta-analysis"],
|
|
297
|
+
"effect": [0.45, 0.52, 0.38, 0.46],
|
|
298
|
+
"ci_lower": [0.30, 0.35, 0.20, 0.40],
|
|
299
|
+
"ci_upper": [0.60, 0.69, 0.56, 0.52],
|
|
300
|
+
"weight": [25, 35, 20, 100],
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
fig = plotter.plot_forest(
|
|
304
|
+
forest_df,
|
|
305
|
+
variant_id="rs12345",
|
|
306
|
+
weight_col="weight",
|
|
307
|
+
)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+

|
|
311
|
+
|
|
264
312
|
## PySpark Support
|
|
265
313
|
|
|
266
314
|
For large-scale genomics data, pass PySpark DataFrames directly:
|
|
@@ -32,9 +32,11 @@ Inspired by [LocusZoom](http://locuszoom.org/) and [locuszoomr](https://github.c
|
|
|
32
32
|
2. **Stacked plots**: Compare multiple GWAS/phenotypes vertically
|
|
33
33
|
3. **eQTL plot**: Expression QTL data aligned with association plots and gene tracks
|
|
34
34
|
4. **Fine-mapping plots**: Visualize SuSiE credible sets with posterior inclusion probabilities
|
|
35
|
-
5. **
|
|
36
|
-
6. **
|
|
37
|
-
7. **
|
|
35
|
+
5. **PheWAS plots**: Phenome-wide association study visualization across multiple phenotypes
|
|
36
|
+
6. **Forest plots**: Meta-analysis effect size visualization with confidence intervals
|
|
37
|
+
7. **Multiple charting libraries**: matplotlib (static), plotly (interactive), bokeh (dashboards)
|
|
38
|
+
8. **Pandas and PySpark support**: Works with both Pandas and PySpark DataFrames for large-scale genomics data
|
|
39
|
+
9. **Convenience data file loaders**: Load and validate common GWAS, eQTL and fine-mapping file formats
|
|
38
40
|
|
|
39
41
|
## Installation
|
|
40
42
|
|
|
@@ -220,6 +222,48 @@ fig = plotter.plot_stacked(
|
|
|
220
222
|
|
|
221
223
|

|
|
222
224
|
|
|
225
|
+
## PheWAS Plots
|
|
226
|
+
|
|
227
|
+
Visualize associations of a single variant across multiple phenotypes:
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
phewas_df = pd.DataFrame({
|
|
231
|
+
"phenotype": ["Height", "BMI", "T2D", "CAD", "HDL"],
|
|
232
|
+
"p_value": [1e-15, 0.05, 1e-8, 1e-3, 1e-10],
|
|
233
|
+
"category": ["Anthropometric", "Anthropometric", "Metabolic", "Cardiovascular", "Lipids"],
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
fig = plotter.plot_phewas(
|
|
237
|
+
phewas_df,
|
|
238
|
+
variant_id="rs12345",
|
|
239
|
+
category_col="category",
|
|
240
|
+
)
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+

|
|
244
|
+
|
|
245
|
+
## Forest Plots
|
|
246
|
+
|
|
247
|
+
Create forest plots for meta-analysis visualization:
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
forest_df = pd.DataFrame({
|
|
251
|
+
"study": ["Study A", "Study B", "Study C", "Meta-analysis"],
|
|
252
|
+
"effect": [0.45, 0.52, 0.38, 0.46],
|
|
253
|
+
"ci_lower": [0.30, 0.35, 0.20, 0.40],
|
|
254
|
+
"ci_upper": [0.60, 0.69, 0.56, 0.52],
|
|
255
|
+
"weight": [25, 35, 20, 100],
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
fig = plotter.plot_forest(
|
|
259
|
+
forest_df,
|
|
260
|
+
variant_id="rs12345",
|
|
261
|
+
weight_col="weight",
|
|
262
|
+
)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+

|
|
266
|
+
|
|
223
267
|
## PySpark Support
|
|
224
268
|
|
|
225
269
|
For large-scale genomics data, pass PySpark DataFrames directly:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{% set name = "pylocuszoom" %}
|
|
2
|
-
{% set version = "0.
|
|
2
|
+
{% set version = "0.5.0" %}
|
|
3
3
|
|
|
4
4
|
package:
|
|
5
5
|
name: {{ name|lower }}
|
|
@@ -7,7 +7,7 @@ package:
|
|
|
7
7
|
|
|
8
8
|
source:
|
|
9
9
|
url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.tar.gz
|
|
10
|
-
sha256:
|
|
10
|
+
sha256: 5aa46c51631e2c736867b85144f390da94f813146eeef5f943038a772820022e
|
|
11
11
|
|
|
12
12
|
build:
|
|
13
13
|
noarch: python
|
|
@@ -11,6 +11,8 @@ Comprehensive documentation for pyLocusZoom - regional association plots for GWA
|
|
|
11
11
|
- [Stacked Plots](#stacked-plots)
|
|
12
12
|
- [eQTL Overlay](#eqtl-overlay)
|
|
13
13
|
- [Fine-mapping Visualization](#fine-mapping-visualization)
|
|
14
|
+
- [PheWAS Plots](#phewas-plots)
|
|
15
|
+
- [Forest Plots](#forest-plots)
|
|
14
16
|
- [Backends](#backends)
|
|
15
17
|
- [Matplotlib (Static)](#matplotlib-static)
|
|
16
18
|
- [Plotly (Interactive)](#plotly-interactive)
|
|
@@ -19,6 +21,8 @@ Comprehensive documentation for pyLocusZoom - regional association plots for GWA
|
|
|
19
21
|
- [LocusZoomPlotter](#locuszoomplotter)
|
|
20
22
|
- [plot() Method](#plot-method)
|
|
21
23
|
- [plot_stacked() Method](#plot_stacked-method)
|
|
24
|
+
- [plot_phewas() Method](#plot_phewas-method)
|
|
25
|
+
- [plot_forest() Method](#plot_forest-method)
|
|
22
26
|
- [File Loaders](#file-loaders)
|
|
23
27
|
- [GWAS Loaders](#gwas-loaders)
|
|
24
28
|
- [eQTL Loaders](#eqtl-loaders)
|
|
@@ -209,6 +213,63 @@ fig = plotter.plot_stacked(
|
|
|
209
213
|
- Credible sets colored distinctly (CS1 = red, CS2 = blue, etc.)
|
|
210
214
|
- Variants not in credible sets shown in gray
|
|
211
215
|
|
|
216
|
+
### PheWAS Plots
|
|
217
|
+
|
|
218
|
+
Visualize associations of a single variant across multiple phenotypes in a phenome-wide association study.
|
|
219
|
+
|
|
220
|
+

|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
phewas_df = pd.DataFrame({
|
|
224
|
+
"phenotype": ["Height", "BMI", "T2D", "CAD", "HDL"],
|
|
225
|
+
"p_value": [1e-15, 0.05, 1e-8, 1e-3, 1e-10],
|
|
226
|
+
"category": ["Anthropometric", "Anthropometric", "Metabolic", "Cardiovascular", "Lipids"],
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
fig = plotter.plot_phewas(
|
|
230
|
+
phewas_df,
|
|
231
|
+
variant_id="rs12345",
|
|
232
|
+
category_col="category",
|
|
233
|
+
significance_threshold=5e-8,
|
|
234
|
+
)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Features:**
|
|
238
|
+
- Phenotypes grouped and colored by category
|
|
239
|
+
- Genome-wide significance line (red dashed)
|
|
240
|
+
- Optional effect direction markers (triangles for +/-)
|
|
241
|
+
- 12-color palette for distinct categories
|
|
242
|
+
|
|
243
|
+
### Forest Plots
|
|
244
|
+
|
|
245
|
+
Create forest plots for meta-analysis visualization showing effect sizes with confidence intervals.
|
|
246
|
+
|
|
247
|
+

|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
forest_df = pd.DataFrame({
|
|
251
|
+
"study": ["Study A", "Study B", "Study C", "Meta-analysis"],
|
|
252
|
+
"effect": [0.45, 0.52, 0.38, 0.46],
|
|
253
|
+
"ci_lower": [0.30, 0.35, 0.20, 0.40],
|
|
254
|
+
"ci_upper": [0.60, 0.69, 0.56, 0.52],
|
|
255
|
+
"weight": [25, 35, 20, 100], # Optional: affects marker size
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
fig = plotter.plot_forest(
|
|
259
|
+
forest_df,
|
|
260
|
+
variant_id="rs12345",
|
|
261
|
+
weight_col="weight",
|
|
262
|
+
null_value=0.0, # Reference line (0 for beta, 1 for OR)
|
|
263
|
+
effect_label="Effect Size",
|
|
264
|
+
)
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Features:**
|
|
268
|
+
- Effect sizes as squares with confidence interval whiskers
|
|
269
|
+
- Marker size scaled by study weight (optional)
|
|
270
|
+
- Null effect reference line
|
|
271
|
+
- Study names as y-axis labels
|
|
272
|
+
|
|
212
273
|
---
|
|
213
274
|
|
|
214
275
|
## Backends
|
|
@@ -391,6 +452,66 @@ fig = plotter.plot_stacked(
|
|
|
391
452
|
| `finemapping_df` | DataFrame | None | Fine-mapping results with `pos` and `pip`. |
|
|
392
453
|
| `finemapping_cs_col` | str | `"cs"` | Column for credible set assignment. |
|
|
393
454
|
|
|
455
|
+
### plot_phewas() Method
|
|
456
|
+
|
|
457
|
+
Create a PheWAS (Phenome-Wide Association Study) plot.
|
|
458
|
+
|
|
459
|
+
```python
|
|
460
|
+
fig = plotter.plot_phewas(
|
|
461
|
+
phewas_df, # Required: PheWAS results
|
|
462
|
+
variant_id="rs12345", # Required: variant ID for title
|
|
463
|
+
phenotype_col="phenotype", # Phenotype name column
|
|
464
|
+
p_col="p_value", # P-value column
|
|
465
|
+
category_col="category", # Category for grouping/coloring
|
|
466
|
+
effect_col=None, # Effect column for direction markers
|
|
467
|
+
significance_threshold=5e-8, # Significance line threshold
|
|
468
|
+
figsize=(10, 8), # Figure dimensions
|
|
469
|
+
)
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
| Parameter | Type | Default | Description |
|
|
473
|
+
|-----------|------|---------|-------------|
|
|
474
|
+
| `phewas_df` | DataFrame | Required | PheWAS results with phenotype and p-value. |
|
|
475
|
+
| `variant_id` | str | Required | Variant ID for plot title. |
|
|
476
|
+
| `phenotype_col` | str | `"phenotype"` | Column with phenotype names. |
|
|
477
|
+
| `p_col` | str | `"p_value"` | Column with p-values. |
|
|
478
|
+
| `category_col` | str | `"category"` | Column for phenotype categories. |
|
|
479
|
+
| `effect_col` | str | None | Column with effect sizes for direction markers. |
|
|
480
|
+
| `significance_threshold` | float | `5e-8` | P-value for significance line. |
|
|
481
|
+
| `figsize` | tuple | `(10, 8)` | Figure dimensions (width, height). |
|
|
482
|
+
|
|
483
|
+
### plot_forest() Method
|
|
484
|
+
|
|
485
|
+
Create a forest plot for meta-analysis visualization.
|
|
486
|
+
|
|
487
|
+
```python
|
|
488
|
+
fig = plotter.plot_forest(
|
|
489
|
+
forest_df, # Required: meta-analysis data
|
|
490
|
+
variant_id="rs12345", # Required: variant ID for title
|
|
491
|
+
study_col="study", # Study/phenotype name column
|
|
492
|
+
effect_col="effect", # Effect size column
|
|
493
|
+
ci_lower_col="ci_lower", # Lower CI column
|
|
494
|
+
ci_upper_col="ci_upper", # Upper CI column
|
|
495
|
+
weight_col=None, # Optional weight column for marker sizes
|
|
496
|
+
null_value=0.0, # Null effect value (0 for beta, 1 for OR)
|
|
497
|
+
effect_label="Effect Size", # X-axis label
|
|
498
|
+
figsize=(8, 6), # Figure dimensions
|
|
499
|
+
)
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
| Parameter | Type | Default | Description |
|
|
503
|
+
|-----------|------|---------|-------------|
|
|
504
|
+
| `forest_df` | DataFrame | Required | Forest plot data with effects and CIs. |
|
|
505
|
+
| `variant_id` | str | Required | Variant ID for plot title. |
|
|
506
|
+
| `study_col` | str | `"study"` | Column with study/phenotype names. |
|
|
507
|
+
| `effect_col` | str | `"effect"` | Column with effect sizes. |
|
|
508
|
+
| `ci_lower_col` | str | `"ci_lower"` | Column with lower confidence interval. |
|
|
509
|
+
| `ci_upper_col` | str | `"ci_upper"` | Column with upper confidence interval. |
|
|
510
|
+
| `weight_col` | str | None | Column with study weights (affects marker size). |
|
|
511
|
+
| `null_value` | float | `0.0` | Reference value for null effect line. |
|
|
512
|
+
| `effect_label` | str | `"Effect Size"` | X-axis label. |
|
|
513
|
+
| `figsize` | tuple | `(8, 6)` | Figure dimensions (width, height). |
|
|
514
|
+
|
|
394
515
|
---
|
|
395
516
|
|
|
396
517
|
## File Loaders
|
|
@@ -568,7 +689,44 @@ gwas_df = pd.DataFrame({
|
|
|
568
689
|
| `pos` | int | Yes | Variant position. |
|
|
569
690
|
| `p_value` | float | Yes | Association p-value. |
|
|
570
691
|
| `gene` | str | Yes | Target gene symbol. |
|
|
571
|
-
| `
|
|
692
|
+
| `effect_size` | float | No | Effect size for color coding. |
|
|
693
|
+
|
|
694
|
+
### PheWAS DataFrame
|
|
695
|
+
|
|
696
|
+
| Column | Type | Required | Description |
|
|
697
|
+
|--------|------|----------|-------------|
|
|
698
|
+
| `phenotype` | str | Yes | Phenotype name. |
|
|
699
|
+
| `p_value` | float | Yes | Association p-value. |
|
|
700
|
+
| `category` | str | No | Phenotype category for grouping/coloring. |
|
|
701
|
+
| `effect_size` | float | No | Effect size for direction markers. |
|
|
702
|
+
|
|
703
|
+
```python
|
|
704
|
+
phewas_df = pd.DataFrame({
|
|
705
|
+
"phenotype": ["Height", "BMI", "T2D"],
|
|
706
|
+
"p_value": [1e-15, 0.05, 1e-8],
|
|
707
|
+
"category": ["Anthropometric", "Anthropometric", "Metabolic"],
|
|
708
|
+
})
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
### Forest Plot DataFrame
|
|
712
|
+
|
|
713
|
+
| Column | Type | Required | Description |
|
|
714
|
+
|--------|------|----------|-------------|
|
|
715
|
+
| `study` | str | Yes | Study or phenotype name. |
|
|
716
|
+
| `effect` | float | Yes | Effect size (beta, OR, HR). |
|
|
717
|
+
| `ci_lower` | float | Yes | Lower confidence interval bound. |
|
|
718
|
+
| `ci_upper` | float | Yes | Upper confidence interval bound. |
|
|
719
|
+
| `weight` | float | No | Study weight (affects marker size). |
|
|
720
|
+
|
|
721
|
+
```python
|
|
722
|
+
forest_df = pd.DataFrame({
|
|
723
|
+
"study": ["Study A", "Study B", "Meta-analysis"],
|
|
724
|
+
"effect": [0.45, 0.52, 0.46],
|
|
725
|
+
"ci_lower": [0.30, 0.35, 0.40],
|
|
726
|
+
"ci_upper": [0.60, 0.69, 0.52],
|
|
727
|
+
"weight": [25, 35, 100],
|
|
728
|
+
})
|
|
729
|
+
```
|
|
572
730
|
|
|
573
731
|
---
|
|
574
732
|
|