pylocuszoom 0.2.0__tar.gz → 0.5.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.5.0/.gitattributes +3 -0
- pylocuszoom-0.5.0/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
- pylocuszoom-0.5.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- pylocuszoom-0.5.0/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/.github/workflows/ci.yml +1 -1
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/.gitignore +3 -0
- pylocuszoom-0.5.0/.pre-commit-config.yaml +7 -0
- pylocuszoom-0.5.0/CHANGELOG.md +126 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/PKG-INFO +125 -31
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/README.md +121 -26
- pylocuszoom-0.5.0/bioconda/meta.yaml +54 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/docs/ARCHITECTURE.md +30 -8
- pylocuszoom-0.5.0/docs/USER_GUIDE.md +740 -0
- pylocuszoom-0.5.0/examples/eqtl_bokeh.html +61 -0
- pylocuszoom-0.5.0/examples/eqtl_overlay.png +0 -0
- pylocuszoom-0.5.0/examples/eqtl_plotly.html +3888 -0
- pylocuszoom-0.5.0/examples/finemapping_bokeh.html +61 -0
- pylocuszoom-0.5.0/examples/finemapping_plot.png +0 -0
- pylocuszoom-0.5.0/examples/finemapping_plotly.html +3888 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/examples/generate_readme_plots.py +78 -2
- pylocuszoom-0.5.0/examples/getting_started.ipynb +931 -0
- pylocuszoom-0.5.0/examples/regional_plot.png +0 -0
- pylocuszoom-0.5.0/examples/stacked_plot.png +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/pyproject.toml +9 -6
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/__init__.py +52 -1
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/backends/base.py +47 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/backends/bokeh_backend.py +323 -61
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/backends/matplotlib_backend.py +133 -7
- pylocuszoom-0.5.0/src/pylocuszoom/backends/plotly_backend.py +863 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/colors.py +3 -1
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/finemapping.py +0 -1
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/gene_track.py +232 -23
- pylocuszoom-0.5.0/src/pylocuszoom/loaders.py +862 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/plotter.py +354 -245
- pylocuszoom-0.5.0/src/pylocuszoom/py.typed +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/recombination.py +4 -4
- pylocuszoom-0.5.0/src/pylocuszoom/schemas.py +395 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/tests/test_finemapping.py +6 -3
- pylocuszoom-0.5.0/tests/test_loaders.py +466 -0
- pylocuszoom-0.5.0/tests/test_notebook_backends.py +798 -0
- pylocuszoom-0.5.0/tests/test_plotter.py +765 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/uv.lock +395 -8
- pylocuszoom-0.2.0/CHANGELOG.md +0 -59
- pylocuszoom-0.2.0/examples/eqtl_overlay.png +0 -0
- pylocuszoom-0.2.0/examples/finemapping_plot.png +0 -0
- pylocuszoom-0.2.0/examples/getting_started.ipynb +0 -240
- pylocuszoom-0.2.0/examples/regional_plot.png +0 -0
- pylocuszoom-0.2.0/examples/stacked_plot.png +0 -0
- pylocuszoom-0.2.0/src/pylocuszoom/backends/plotly_backend.py +0 -473
- pylocuszoom-0.2.0/tests/test_plotter.py +0 -385
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/.github/workflows/publish.yml +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/CONTRIBUTING.md +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/LICENSE.md +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/logo.svg +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/backends/__init__.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/eqtl.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/labels.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/ld.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/logging.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/reference_data/__init__.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/src/pylocuszoom/utils.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/tests/conftest.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/tests/test_colors.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/tests/test_gene_track.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/tests/test_labels.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/tests/test_ld.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/tests/test_logging.py +0 -0
- {pylocuszoom-0.2.0 → pylocuszoom-0.5.0}/tests/test_recombination.py +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug Report
|
|
3
|
+
about: Report a bug or unexpected behavior
|
|
4
|
+
title: ''
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Description
|
|
10
|
+
|
|
11
|
+
A clear description of the bug.
|
|
12
|
+
|
|
13
|
+
## Minimal Reproducible Example
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from pylocuszoom import LocusZoomPlotter
|
|
17
|
+
import pandas as pd
|
|
18
|
+
|
|
19
|
+
# Minimal code to reproduce the issue
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Expected Behavior
|
|
23
|
+
|
|
24
|
+
What you expected to happen.
|
|
25
|
+
|
|
26
|
+
## Actual Behavior
|
|
27
|
+
|
|
28
|
+
What actually happened. Include error messages if applicable.
|
|
29
|
+
|
|
30
|
+
## Environment
|
|
31
|
+
|
|
32
|
+
- pylocuszoom version:
|
|
33
|
+
- Python version:
|
|
34
|
+
- OS:
|
|
35
|
+
- Installation method: pip / conda / uv
|
|
36
|
+
|
|
37
|
+
## Additional Context
|
|
38
|
+
|
|
39
|
+
Any other relevant information (screenshots, data samples, etc.)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature Request
|
|
3
|
+
about: Suggest a new feature or enhancement
|
|
4
|
+
title: ''
|
|
5
|
+
labels: enhancement
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
|
|
11
|
+
What problem does this feature solve?
|
|
12
|
+
|
|
13
|
+
## Proposed Solution
|
|
14
|
+
|
|
15
|
+
Describe the feature you'd like.
|
|
16
|
+
|
|
17
|
+
## Alternatives Considered
|
|
18
|
+
|
|
19
|
+
Any alternative solutions or workarounds you've tried.
|
|
20
|
+
|
|
21
|
+
## Additional Context
|
|
22
|
+
|
|
23
|
+
Any other relevant information (mockups, examples from other tools, etc.)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.5.0] - 2026-01-27
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Hover tooltips for fine-mapping scatter plots (Plotly/Bokeh backends)
|
|
14
|
+
- Hover tooltips for eQTL scatter plots (Plotly/Bokeh backends)
|
|
15
|
+
- Interactive HTML example plots for eQTL and fine-mapping (Plotly/Bokeh)
|
|
16
|
+
- Comprehensive marker and hover data tests for interactive backends
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- Plotly/Bokeh backends now hide grid lines for cleaner LocusZoom appearance
|
|
20
|
+
- Plotly/Bokeh backends now show black axis lines (matching matplotlib style)
|
|
21
|
+
- Plotly/Bokeh gene track panels now hide y-axis (ticks, labels, line, grid)
|
|
22
|
+
- Plotly/Bokeh backends now hide minor ticks and zero lines
|
|
23
|
+
|
|
24
|
+
## [0.4.0] - 2026-01-26
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
- **File format loaders** for common GWAS, eQTL, and fine-mapping formats:
|
|
28
|
+
- GWAS: `load_gwas`, `load_plink_assoc`, `load_regenie`, `load_bolt_lmm`, `load_gemma`, `load_saige`, `load_gwas_catalog`
|
|
29
|
+
- eQTL: `load_gtex_eqtl`, `load_eqtl_catalogue`, `load_matrixeqtl`
|
|
30
|
+
- Fine-mapping: `load_susie`, `load_finemap`, `load_caviar`, `load_polyfun`
|
|
31
|
+
- Gene annotations: `load_gtf`, `load_bed`, `load_ensembl_genes`
|
|
32
|
+
- Pydantic validation for file loaders with detailed error messages
|
|
33
|
+
- `py.typed` marker for PEP 561 type checking support
|
|
34
|
+
- Pre-commit configuration for automated linting
|
|
35
|
+
- GitHub issue templates for bug reports and feature requests
|
|
36
|
+
- Codecov badge in README
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
- eQTL and fine-mapping legends now route through backend protocol (works with all backends)
|
|
40
|
+
- Simplified backend code with reduced duplication
|
|
41
|
+
- Backend protocol class diagram added to ARCHITECTURE.md
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
- Additional robustness improvements for edge cases
|
|
45
|
+
|
|
46
|
+
## [0.3.0] - 2026-01-26
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
- Bioconda recipe for conda installation
|
|
50
|
+
- `adjustText` moved to default dependencies (was optional)
|
|
51
|
+
- **Interactive plotly backend** - use `backend="plotly"` for hover tooltips and pan/zoom
|
|
52
|
+
- **Interactive bokeh backend** - use `backend="bokeh"` for dashboard-ready plots
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
- `plot()` and `plot_stacked()` now use backend protocol for all rendering (scatter, line, axes, layout)
|
|
56
|
+
- **Gene track now works with all backends** (plotly, bokeh, matplotlib)
|
|
57
|
+
- **Recombination overlay now works with all backends** - secondary y-axis with rate line and fill
|
|
58
|
+
- **LD legend now works with all backends** - r² color scale (lead SNP highlighted in plot, not legend)
|
|
59
|
+
- SNP labels remain matplotlib-only (interactive backends use hover tooltips instead)
|
|
60
|
+
- Default `genomewide_threshold` changed from 5e-7 to 5e-8 (standard GWAS significance)
|
|
61
|
+
- Gene track strand colors: forward strand now goldenrod (#DAA520), reverse strand light blue (#6BB3FF)
|
|
62
|
+
- Gene track directional arrows: black for forward, dark grey for reverse
|
|
63
|
+
- Added panel spacing (hspace=0.1) between stacked/fine-mapping panels for visual separation
|
|
64
|
+
- Tightened gene track internal spacing for more compact layout
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
- Bokeh backend `x_range=None` error when creating figures with shared x-axis
|
|
68
|
+
- Bokeh backend `legend_label=None` error in scatter plots
|
|
69
|
+
- Bokeh backend LD legend not rendering (empty scatter plots don't create legend glyphs)
|
|
70
|
+
- Bokeh backend deprecated `FuncTickFormatter` replaced with `CustomJSTickFormatter`
|
|
71
|
+
- Bokeh backend deprecated `circle()` method replaced with `scatter(marker=...)`
|
|
72
|
+
- Bokeh backend `FIXED_SIZING_MODE` validation warning in column layouts
|
|
73
|
+
|
|
74
|
+
## [0.2.0] - 2026-01-26
|
|
75
|
+
|
|
76
|
+
### Added
|
|
77
|
+
- Fine-mapping/SuSiE visualization with credible set coloring
|
|
78
|
+
- Example plots in `examples/` directory
|
|
79
|
+
- Plot generation script for documentation
|
|
80
|
+
|
|
81
|
+
### Fixed
|
|
82
|
+
- Ruff linting and formatting errors
|
|
83
|
+
- Bokeh security vulnerability (bumped to >= 3.8.2)
|
|
84
|
+
- `plot()` KeyError when `rs_col` column missing with `ld_reference_file` provided
|
|
85
|
+
- `plot_stacked()` now validates eQTL DataFrame columns before use
|
|
86
|
+
- `plot_stacked()` now validates list lengths for `lead_positions`, `panel_labels`, and `ld_reference_files`
|
|
87
|
+
- `calculate_ld()` docstring now documents `ValidationError` for missing PLINK files
|
|
88
|
+
|
|
89
|
+
### Changed
|
|
90
|
+
- Minimum Python version bumped to 3.10 (required by bokeh 3.8.2)
|
|
91
|
+
- Renamed species terminology: "dog" → "canine", "cat" → "feline"
|
|
92
|
+
- Clarified interactive backend status in README (coming soon)
|
|
93
|
+
|
|
94
|
+
## [0.1.0] - 2026-01-26
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
- Initial release of pyLocusZoom
|
|
98
|
+
- Regional association plots with LD coloring
|
|
99
|
+
- Gene and exon track visualization
|
|
100
|
+
- Recombination rate overlay (canine only)
|
|
101
|
+
- Automatic SNP labeling with adjustText
|
|
102
|
+
- Species support: Canine (CanFam3.1/CanFam4), Feline (FelCat9), custom
|
|
103
|
+
- CanFam4 coordinate liftover via pyliftover
|
|
104
|
+
- Stacked plots for multi-GWAS comparison
|
|
105
|
+
- eQTL overlay panel support
|
|
106
|
+
- PySpark DataFrame support
|
|
107
|
+
- Backend infrastructure for matplotlib, plotly, bokeh (matplotlib only active)
|
|
108
|
+
- Logging via loguru
|
|
109
|
+
- Comprehensive test suite
|
|
110
|
+
|
|
111
|
+
### Dependencies
|
|
112
|
+
- matplotlib >= 3.5.0
|
|
113
|
+
- pandas >= 1.4.0
|
|
114
|
+
- numpy >= 1.21.0
|
|
115
|
+
- loguru >= 0.7.0
|
|
116
|
+
- pyliftover >= 0.4
|
|
117
|
+
- plotly >= 5.0.0
|
|
118
|
+
- bokeh >= 3.8.2
|
|
119
|
+
- kaleido >= 0.2.0
|
|
120
|
+
|
|
121
|
+
[Unreleased]: https://github.com/michael-denyer/pyLocusZoom/compare/v0.5.0...HEAD
|
|
122
|
+
[0.5.0]: https://github.com/michael-denyer/pyLocusZoom/compare/v0.4.0...v0.5.0
|
|
123
|
+
[0.4.0]: https://github.com/michael-denyer/pyLocusZoom/compare/v0.3.0...v0.4.0
|
|
124
|
+
[0.3.0]: https://github.com/michael-denyer/pyLocusZoom/compare/v0.2.0...v0.3.0
|
|
125
|
+
[0.2.0]: https://github.com/michael-denyer/pyLocusZoom/compare/v0.1.0...v0.2.0
|
|
126
|
+
[0.1.0]: https://github.com/michael-denyer/pyLocusZoom/releases/tag/v0.1.0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pylocuszoom
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.5.0
|
|
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
|
|
7
7
|
Project-URL: Repository, https://github.com/michael-denyer/pylocuszoom
|
|
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
20
20
|
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
21
21
|
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: adjusttext>=0.8
|
|
22
23
|
Requires-Dist: bokeh>=3.8.2
|
|
23
24
|
Requires-Dist: kaleido>=0.2.0
|
|
24
25
|
Requires-Dist: loguru>=0.7.0
|
|
@@ -26,63 +27,72 @@ Requires-Dist: matplotlib>=3.5.0
|
|
|
26
27
|
Requires-Dist: numpy>=1.21.0
|
|
27
28
|
Requires-Dist: pandas>=1.4.0
|
|
28
29
|
Requires-Dist: plotly>=5.0.0
|
|
30
|
+
Requires-Dist: pydantic>=2.0.0
|
|
29
31
|
Requires-Dist: pyliftover>=0.4
|
|
30
32
|
Provides-Extra: all
|
|
31
|
-
Requires-Dist: adjusttext>=0.8; extra == 'all'
|
|
32
33
|
Requires-Dist: pyspark>=3.0.0; extra == 'all'
|
|
33
34
|
Provides-Extra: dev
|
|
34
35
|
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
35
36
|
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
36
37
|
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
37
|
-
Provides-Extra: labels
|
|
38
|
-
Requires-Dist: adjusttext>=0.8; extra == 'labels'
|
|
39
38
|
Provides-Extra: spark
|
|
40
39
|
Requires-Dist: pyspark>=3.0.0; extra == 'spark'
|
|
41
40
|
Description-Content-Type: text/markdown
|
|
42
41
|
|
|
43
|
-
# pyLocusZoom
|
|
44
|
-
|
|
45
42
|
[](https://github.com/michael-denyer/pyLocusZoom/actions/workflows/ci.yml)
|
|
46
|
-
[](https://codecov.io/gh/michael-denyer/pyLocusZoom)
|
|
44
|
+
[](https://pypi.org/project/pylocuszoom/)
|
|
45
|
+
[](https://anaconda.org/bioconda/pylocuszoom)
|
|
46
|
+
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
47
47
|
[](https://www.python.org/downloads/)
|
|
48
48
|
[](https://github.com/astral-sh/ruff)
|
|
49
|
-
|
|
50
49
|
[](https://matplotlib.org/)
|
|
51
50
|
[](https://plotly.com/python/)
|
|
52
51
|
[](https://bokeh.org/)
|
|
53
52
|
[](https://pandas.pydata.org/)
|
|
54
|
-
|
|
55
53
|
<img src="logo.svg" alt="pyLocusZoom logo" width="120" align="right">
|
|
54
|
+
# pyLocusZoom
|
|
56
55
|
|
|
57
|
-
|
|
56
|
+
Publication-ready regional association plots with LD coloring, gene tracks, and recombination overlays.
|
|
58
57
|
|
|
59
58
|
Inspired by [LocusZoom](http://locuszoom.org/) and [locuszoomr](https://github.com/myles-lewis/locuszoomr).
|
|
60
59
|
|
|
61
60
|
## Features
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
- **
|
|
66
|
-
- **
|
|
67
|
-
- **
|
|
68
|
-
- **
|
|
69
|
-
- **
|
|
70
|
-
- **
|
|
71
|
-
- **eQTL overlay**: Expression QTL data as separate panel
|
|
72
|
-
- **PySpark support**: Handles large-scale genomics DataFrames
|
|
62
|
+
1. **Regional association plot**:
|
|
63
|
+
|
|
64
|
+
- **Multi-species support**: Built-in reference data for *Canis lupus familiaris* (CanFam3.1/CanFam4) and *Felis catus* (FelCat9), or optionally provide your own for any species
|
|
65
|
+
- **LD coloring**: SNPs colored by linkage disequilibrium (R²) with lead variant
|
|
66
|
+
- **Gene tracks**: Annotated gene/exon positions below the association plot
|
|
67
|
+
- **Recombination rate**: Overlay showing recombination rate across region (*Canis lupus familiaris* only)
|
|
68
|
+
- **SNP labels (matplotlib)**: Automatic labeling of lead SNPs with RS ID
|
|
69
|
+
- **Tooltips (Bokeh and Plotly)**: Mouseover for detailed SNP data
|
|
73
70
|
|
|
74
71
|

|
|
75
72
|
|
|
73
|
+
2. **Stacked plots**: Compare multiple GWAS/phenotypes vertically
|
|
74
|
+
3. **eQTL plot**: Expression QTL data aligned with association plots and gene tracks
|
|
75
|
+
4. **Fine-mapping plots**: Visualize SuSiE credible sets with posterior inclusion probabilities
|
|
76
|
+
5. **Multiple charting libraries**: matplotlib (static), plotly (interactive), bokeh (dashboards)
|
|
77
|
+
6. **Pandas and PySpark support**: Works with both Pandas and PySpark DataFrames for large-scale genomics data
|
|
78
|
+
7. **Convenience data file loaders**: Load and validate common GWAS, eQTL and fine-mapping file formats
|
|
79
|
+
|
|
76
80
|
## Installation
|
|
77
81
|
|
|
82
|
+
```bash
|
|
83
|
+
pip install pylocuszoom
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Or with uv:
|
|
87
|
+
|
|
78
88
|
```bash
|
|
79
89
|
uv add pylocuszoom
|
|
80
90
|
```
|
|
81
91
|
|
|
82
|
-
Or with
|
|
92
|
+
Or with conda (Bioconda):
|
|
83
93
|
|
|
84
94
|
```bash
|
|
85
|
-
|
|
95
|
+
conda install -c bioconda pylocuszoom
|
|
86
96
|
```
|
|
87
97
|
|
|
88
98
|
## Quick Start
|
|
@@ -165,20 +175,30 @@ fig = plotter.plot(
|
|
|
165
175
|
)
|
|
166
176
|
```
|
|
167
177
|
|
|
168
|
-
##
|
|
178
|
+
## Backends
|
|
169
179
|
|
|
170
|
-
|
|
180
|
+
pyLocusZoom supports multiple rendering backends:
|
|
171
181
|
|
|
172
182
|
```python
|
|
173
|
-
# Static publication-quality plot (default
|
|
174
|
-
|
|
175
|
-
fig = plotter.plot(gwas_df, chrom=1, start=1000000, end=2000000)
|
|
183
|
+
# Static publication-quality plot (default)
|
|
184
|
+
fig = plotter.plot(gwas_df, chrom=1, start=1000000, end=2000000, backend="matplotlib")
|
|
176
185
|
fig.savefig("plot.png", dpi=150)
|
|
186
|
+
|
|
187
|
+
# Interactive Plotly (hover tooltips, pan/zoom)
|
|
188
|
+
fig = plotter.plot(gwas_df, chrom=1, start=1000000, end=2000000, backend="plotly")
|
|
189
|
+
fig.write_html("plot.html")
|
|
190
|
+
|
|
191
|
+
# Interactive Bokeh (dashboard-ready)
|
|
192
|
+
fig = plotter.plot(gwas_df, chrom=1, start=1000000, end=2000000, backend="bokeh")
|
|
177
193
|
```
|
|
178
194
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
195
|
+
| Backend | Output | Best For | Features |
|
|
196
|
+
|---------|--------|----------|----------|
|
|
197
|
+
| `matplotlib` | Static PNG/PDF/SVG | Publications, presentations | Full feature set with SNP labels |
|
|
198
|
+
| `plotly` | Interactive HTML | Web reports, data exploration | Hover tooltips, pan/zoom |
|
|
199
|
+
| `bokeh` | Interactive HTML | Dashboards, web apps | Hover tooltips, pan/zoom |
|
|
200
|
+
|
|
201
|
+
> **Note:** All backends support scatter plots, gene tracks, recombination overlay, and LD legend. SNP labels (auto-positioned with adjustText) are matplotlib-only; interactive backends use hover tooltips instead.
|
|
182
202
|
|
|
183
203
|
## Stacked Plots
|
|
184
204
|
|
|
@@ -195,6 +215,8 @@ fig = plotter.plot_stacked(
|
|
|
195
215
|
)
|
|
196
216
|
```
|
|
197
217
|
|
|
218
|
+

|
|
219
|
+
|
|
198
220
|
## eQTL Overlay
|
|
199
221
|
|
|
200
222
|
Add expression QTL data as a separate panel:
|
|
@@ -215,6 +237,30 @@ fig = plotter.plot_stacked(
|
|
|
215
237
|
)
|
|
216
238
|
```
|
|
217
239
|
|
|
240
|
+

|
|
241
|
+
|
|
242
|
+
## Fine-mapping Visualization
|
|
243
|
+
|
|
244
|
+
Visualize SuSiE or other fine-mapping results with credible set coloring:
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
finemapping_df = pd.DataFrame({
|
|
248
|
+
"pos": [1000500, 1001200, 1002000, 1003500],
|
|
249
|
+
"pip": [0.85, 0.12, 0.02, 0.45], # Posterior inclusion probability
|
|
250
|
+
"cs": [1, 1, 0, 2], # Credible set assignment (0 = not in CS)
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
fig = plotter.plot_stacked(
|
|
254
|
+
[gwas_df],
|
|
255
|
+
chrom=1, start=1000000, end=2000000,
|
|
256
|
+
finemapping_df=finemapping_df,
|
|
257
|
+
finemapping_cs_col="cs",
|
|
258
|
+
genes_df=genes_df,
|
|
259
|
+
)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+

|
|
263
|
+
|
|
218
264
|
## PySpark Support
|
|
219
265
|
|
|
220
266
|
For large-scale genomics data, pass PySpark DataFrames directly:
|
|
@@ -231,6 +277,47 @@ pandas_df = to_pandas(spark_gwas_df, sample_size=100000)
|
|
|
231
277
|
|
|
232
278
|
Install PySpark support: `uv add pylocuszoom[spark]`
|
|
233
279
|
|
|
280
|
+
## Loading Data from Files
|
|
281
|
+
|
|
282
|
+
pyLocusZoom includes loaders for common GWAS, eQTL, and fine-mapping file formats:
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
from pylocuszoom import (
|
|
286
|
+
# GWAS loaders
|
|
287
|
+
load_gwas, # Auto-detect format
|
|
288
|
+
load_plink_assoc, # PLINK .assoc, .assoc.linear, .qassoc
|
|
289
|
+
load_regenie, # REGENIE .regenie
|
|
290
|
+
load_bolt_lmm, # BOLT-LMM .stats
|
|
291
|
+
load_gemma, # GEMMA .assoc.txt
|
|
292
|
+
load_saige, # SAIGE output
|
|
293
|
+
# eQTL loaders
|
|
294
|
+
load_gtex_eqtl, # GTEx significant pairs
|
|
295
|
+
load_eqtl_catalogue, # eQTL Catalogue format
|
|
296
|
+
# Fine-mapping loaders
|
|
297
|
+
load_susie, # SuSiE output
|
|
298
|
+
load_finemap, # FINEMAP .snp output
|
|
299
|
+
# Gene annotations
|
|
300
|
+
load_gtf, # GTF/GFF3 files
|
|
301
|
+
load_bed, # BED files
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
# Auto-detect GWAS format from filename
|
|
305
|
+
gwas_df = load_gwas("results.assoc.linear")
|
|
306
|
+
|
|
307
|
+
# Or use specific loader
|
|
308
|
+
gwas_df = load_regenie("ukb_results.regenie")
|
|
309
|
+
|
|
310
|
+
# Load gene annotations
|
|
311
|
+
genes_df = load_gtf("genes.gtf", feature_type="gene")
|
|
312
|
+
exons_df = load_gtf("genes.gtf", feature_type="exon")
|
|
313
|
+
|
|
314
|
+
# Load eQTL data
|
|
315
|
+
eqtl_df = load_gtex_eqtl("GTEx.signif_pairs.txt.gz", gene="BRCA1")
|
|
316
|
+
|
|
317
|
+
# Load fine-mapping results
|
|
318
|
+
fm_df = load_susie("susie_output.tsv")
|
|
319
|
+
```
|
|
320
|
+
|
|
234
321
|
## Data Formats
|
|
235
322
|
|
|
236
323
|
### GWAS Results DataFrame
|
|
@@ -357,6 +444,13 @@ plotter = LocusZoomPlotter(log_level="DEBUG")
|
|
|
357
444
|
Optional:
|
|
358
445
|
- pyspark >= 3.0.0 (for PySpark DataFrame support) - `uv add pylocuszoom[spark]`
|
|
359
446
|
|
|
447
|
+
## Documentation
|
|
448
|
+
|
|
449
|
+
- [User Guide](docs/USER_GUIDE.md) - Comprehensive documentation with API reference
|
|
450
|
+
- [Architecture](docs/ARCHITECTURE.md) - Design decisions and component overview
|
|
451
|
+
- [Example Notebook](examples/getting_started.ipynb) - Interactive tutorial
|
|
452
|
+
- [CHANGELOG](CHANGELOG.md) - Version history
|
|
453
|
+
|
|
360
454
|
## License
|
|
361
455
|
|
|
362
456
|
GPL-3.0-or-later
|