pylocuszoom 0.3.0__py3-none-any.whl → 0.6.0__py3-none-any.whl

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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pylocuszoom
3
- Version: 0.3.0
4
- Summary: Regional association plots for GWAS results with LD coloring, gene tracks, and recombination rate overlays
3
+ Version: 0.6.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
@@ -26,51 +26,63 @@ 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.0.0
29
+ Requires-Dist: plotly>=5.15.0
30
+ Requires-Dist: pydantic>=2.0.0
30
31
  Requires-Dist: pyliftover>=0.4
32
+ Requires-Dist: requests>=2.25.0
33
+ Requires-Dist: tqdm>=4.60.0
31
34
  Provides-Extra: all
32
35
  Requires-Dist: pyspark>=3.0.0; extra == 'all'
33
36
  Provides-Extra: dev
34
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'
35
40
  Requires-Dist: pytest>=7.0.0; extra == 'dev'
36
41
  Requires-Dist: ruff>=0.1.0; extra == 'dev'
37
42
  Provides-Extra: spark
38
43
  Requires-Dist: pyspark>=3.0.0; extra == 'spark'
39
44
  Description-Content-Type: text/markdown
40
45
 
41
- # pyLocusZoom
42
-
43
46
  [![CI](https://github.com/michael-denyer/pyLocusZoom/actions/workflows/ci.yml/badge.svg)](https://github.com/michael-denyer/pyLocusZoom/actions/workflows/ci.yml)
44
- [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
47
+ [![codecov](https://codecov.io/gh/michael-denyer/pyLocusZoom/graph/badge.svg)](https://codecov.io/gh/michael-denyer/pyLocusZoom)
48
+ [![PyPI](https://img.shields.io/pypi/v/pylocuszoom)](https://pypi.org/project/pylocuszoom/)
49
+ [![Bioconda](https://img.shields.io/conda/vn/bioconda/pylocuszoom)](https://anaconda.org/bioconda/pylocuszoom)
50
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-red.svg)](https://www.gnu.org/licenses/gpl-3.0)
45
51
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
46
52
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
47
-
48
53
  [![Matplotlib](https://img.shields.io/badge/Matplotlib-3.5+-11557c.svg)](https://matplotlib.org/)
49
54
  [![Plotly](https://img.shields.io/badge/Plotly-5.0+-3F4F75.svg)](https://plotly.com/python/)
50
55
  [![Bokeh](https://img.shields.io/badge/Bokeh-3.8+-E6526F.svg)](https://bokeh.org/)
51
56
  [![Pandas](https://img.shields.io/badge/Pandas-1.4+-150458.svg)](https://pandas.pydata.org/)
52
-
53
57
  <img src="logo.svg" alt="pyLocusZoom logo" width="120" align="right">
58
+ # pyLocusZoom
54
59
 
55
- Regional association plots for GWAS results with LD coloring, gene tracks, and recombination rate overlays.
60
+ Publication-ready regional association plots with LD coloring, gene tracks, and recombination overlays.
56
61
 
57
62
  Inspired by [LocusZoom](http://locuszoom.org/) and [locuszoomr](https://github.com/myles-lewis/locuszoomr).
58
63
 
59
64
  ## Features
60
65
 
61
- - **LD coloring**: SNPs colored by linkage disequilibrium (R²) with lead variant
62
- - **Gene track**: Annotated gene/exon positions below the association plot
63
- - **Recombination rate**: Overlay showing recombination rate across region (*Canis lupus familiaris* only)
64
- - **SNP labels**: Automatic labeling of top SNPs with RS ID or nearest gene
65
- - **Species support**: Built-in *Canis lupus familiaris* (CanFam3.1/CanFam4), *Felis catus* (FelCat9), or custom species
66
- - **CanFam4 support**: Automatic coordinate liftover for recombination maps
67
- - **Multiple backends**: matplotlib (static), plotly (interactive), bokeh (dashboards)
68
- - **Stacked plots**: Compare multiple GWAS/phenotypes vertically
69
- - **eQTL overlay**: Expression QTL data as separate panel
70
- - **PySpark support**: Handles large-scale genomics DataFrames
66
+ 1. **Regional association plot**:
67
+
68
+ - **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
69
+ - **LD coloring**: SNPs colored by linkage disequilibrium (R²) with lead variant
70
+ - **Gene tracks**: Annotated gene/exon positions below the association plot
71
+ - **Recombination rate**: Overlay showing recombination rate across region (*Canis lupus familiaris* only)
72
+ - **SNP labels (matplotlib)**: Automatic labeling of lead SNPs with RS ID
73
+ - **Tooltips (Bokeh and Plotly)**: Mouseover for detailed SNP data
71
74
 
72
75
  ![Example regional association plot](examples/regional_plot.png)
73
76
 
77
+ 2. **Stacked plots**: Compare multiple GWAS/phenotypes vertically
78
+ 3. **eQTL plot**: Expression QTL data aligned with association plots and gene tracks
79
+ 4. **Fine-mapping plots**: Visualize SuSiE credible sets with posterior inclusion probabilities
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
85
+
74
86
  ## Installation
75
87
 
76
88
  ```bash
@@ -186,13 +198,13 @@ fig.write_html("plot.html")
186
198
  fig = plotter.plot(gwas_df, chrom=1, start=1000000, end=2000000, backend="bokeh")
187
199
  ```
188
200
 
189
- | Backend | Output | Best For |
190
- |---------|--------|----------|
191
- | `matplotlib` | Static PNG/PDF/SVG | Publications, presentations |
192
- | `plotly` | Interactive HTML | Web reports, data exploration |
193
- | `bokeh` | Interactive HTML | Dashboards, web apps |
201
+ | Backend | Output | Best For | Features |
202
+ |---------|--------|----------|----------|
203
+ | `matplotlib` | Static PNG/PDF/SVG | Publications, presentations | Full feature set with SNP labels |
204
+ | `plotly` | Interactive HTML | Web reports, data exploration | Hover tooltips, pan/zoom |
205
+ | `bokeh` | Interactive HTML | Dashboards, web apps | Hover tooltips, pan/zoom |
194
206
 
195
- > **Note:** All backends support gene track, recombination overlay, and LD legend. SNP labels (auto-positioned with adjustText) are matplotlib-only.
207
+ > **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.
196
208
 
197
209
  ## Stacked Plots
198
210
 
@@ -209,6 +221,8 @@ fig = plotter.plot_stacked(
209
221
  )
210
222
  ```
211
223
 
224
+ ![Example stacked plot](examples/stacked_plot.png)
225
+
212
226
  ## eQTL Overlay
213
227
 
214
228
  Add expression QTL data as a separate panel:
@@ -229,6 +243,72 @@ fig = plotter.plot_stacked(
229
243
  )
230
244
  ```
231
245
 
246
+ ![Example eQTL overlay plot](examples/eqtl_overlay.png)
247
+
248
+ ## Fine-mapping Visualization
249
+
250
+ Visualize SuSiE or other fine-mapping results with credible set coloring:
251
+
252
+ ```python
253
+ finemapping_df = pd.DataFrame({
254
+ "pos": [1000500, 1001200, 1002000, 1003500],
255
+ "pip": [0.85, 0.12, 0.02, 0.45], # Posterior inclusion probability
256
+ "cs": [1, 1, 0, 2], # Credible set assignment (0 = not in CS)
257
+ })
258
+
259
+ fig = plotter.plot_stacked(
260
+ [gwas_df],
261
+ chrom=1, start=1000000, end=2000000,
262
+ finemapping_df=finemapping_df,
263
+ finemapping_cs_col="cs",
264
+ genes_df=genes_df,
265
+ )
266
+ ```
267
+
268
+ ![Example fine-mapping plot](examples/finemapping_plot.png)
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
+ ![Example PheWAS plot](examples/phewas_plot.png)
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
+ ![Example forest plot](examples/forest_plot.png)
311
+
232
312
  ## PySpark Support
233
313
 
234
314
  For large-scale genomics data, pass PySpark DataFrames directly:
@@ -245,6 +325,47 @@ pandas_df = to_pandas(spark_gwas_df, sample_size=100000)
245
325
 
246
326
  Install PySpark support: `uv add pylocuszoom[spark]`
247
327
 
328
+ ## Loading Data from Files
329
+
330
+ pyLocusZoom includes loaders for common GWAS, eQTL, and fine-mapping file formats:
331
+
332
+ ```python
333
+ from pylocuszoom import (
334
+ # GWAS loaders
335
+ load_gwas, # Auto-detect format
336
+ load_plink_assoc, # PLINK .assoc, .assoc.linear, .qassoc
337
+ load_regenie, # REGENIE .regenie
338
+ load_bolt_lmm, # BOLT-LMM .stats
339
+ load_gemma, # GEMMA .assoc.txt
340
+ load_saige, # SAIGE output
341
+ # eQTL loaders
342
+ load_gtex_eqtl, # GTEx significant pairs
343
+ load_eqtl_catalogue, # eQTL Catalogue format
344
+ # Fine-mapping loaders
345
+ load_susie, # SuSiE output
346
+ load_finemap, # FINEMAP .snp output
347
+ # Gene annotations
348
+ load_gtf, # GTF/GFF3 files
349
+ load_bed, # BED files
350
+ )
351
+
352
+ # Auto-detect GWAS format from filename
353
+ gwas_df = load_gwas("results.assoc.linear")
354
+
355
+ # Or use specific loader
356
+ gwas_df = load_regenie("ukb_results.regenie")
357
+
358
+ # Load gene annotations
359
+ genes_df = load_gtf("genes.gtf", feature_type="gene")
360
+ exons_df = load_gtf("genes.gtf", feature_type="exon")
361
+
362
+ # Load eQTL data
363
+ eqtl_df = load_gtex_eqtl("GTEx.signif_pairs.txt.gz", gene="BRCA1")
364
+
365
+ # Load fine-mapping results
366
+ fm_df = load_susie("susie_output.tsv")
367
+ ```
368
+
248
369
  ## Data Formats
249
370
 
250
371
  ### GWAS Results DataFrame
@@ -371,6 +492,13 @@ plotter = LocusZoomPlotter(log_level="DEBUG")
371
492
  Optional:
372
493
  - pyspark >= 3.0.0 (for PySpark DataFrame support) - `uv add pylocuszoom[spark]`
373
494
 
495
+ ## Documentation
496
+
497
+ - [User Guide](docs/USER_GUIDE.md) - Comprehensive documentation with API reference
498
+ - [Architecture](docs/ARCHITECTURE.md) - Design decisions and component overview
499
+ - [Example Notebook](examples/getting_started.ipynb) - Interactive tutorial
500
+ - [CHANGELOG](CHANGELOG.md) - Version history
501
+
374
502
  ## License
375
503
 
376
504
  GPL-3.0-or-later
@@ -0,0 +1,26 @@
1
+ pylocuszoom/__init__.py,sha256=yb7NMehYOWYPPSBkO4EWwMY4NT-fj8oniNvI3h4oLL0,5219
2
+ pylocuszoom/colors.py,sha256=B28rfhWwGZ-e6Q-F43iXxC6NZpjUo0yWk4S_-vp9ZvU,7686
3
+ pylocuszoom/eqtl.py,sha256=9lZJ8jT1WEj3won6D9B54xdqUvbRvxpOitf97NCUR28,6167
4
+ pylocuszoom/finemapping.py,sha256=PJ4HJYeCaHZecUmADCEGQxKd9HhhjrdIA1H5LQsUmLI,6332
5
+ pylocuszoom/forest.py,sha256=WFX29gEcH-xS5G4kbb9J2WPcbRw7OdMegFuLqN4VfIE,1147
6
+ pylocuszoom/gene_track.py,sha256=VWvPY0SrVFGJprTdttJ72r3JD-r3bdRDr0HDBai0oJw,18692
7
+ pylocuszoom/labels.py,sha256=Ams5WVZFNVT692BRiQ5wZcdbdNEAm5xtgRwmF5u0s_A,3492
8
+ pylocuszoom/ld.py,sha256=64xIulpDVvbMSryWUPoCQ99Odcjwf1wejpwVr_30MLU,6412
9
+ pylocuszoom/loaders.py,sha256=28PqlUhbq1Y6Xzv9NFucWSAqRTqGj8h-pR7wOOmIHxI,25132
10
+ pylocuszoom/logging.py,sha256=nZHEkbnjp8zoyWj_S-Hy9UQvUYLoMoxyiOWRozBT2dg,4987
11
+ pylocuszoom/phewas.py,sha256=jrVDQvUu4rEH3YCE00LX-6STY96vMcK9xZ7AhiN9Jjo,984
12
+ pylocuszoom/plotter.py,sha256=ywqlLMDalzWJaeIfkK_qYh9HRWbypJf9Pgd0II8jAss,53368
13
+ pylocuszoom/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ pylocuszoom/recombination.py,sha256=_KU9zwlhjk0MfyG4_i3rS0JPj5SIWcyTxglVlF-KMP8,13826
15
+ pylocuszoom/schemas.py,sha256=vABBBlAR1vUP6BIewZ8E-TYpacccrcxavrdIDVCrQB4,11916
16
+ pylocuszoom/utils.py,sha256=fKNX9WSTbfHR1EpPYijt6ycNjXEjwzunQMHXAvHaK3s,5211
17
+ pylocuszoom/backends/__init__.py,sha256=7dlGvDoqMVK3fCtoMcI9zOP9qO0odQGPwfXhxnLfXfI,1196
18
+ pylocuszoom/backends/base.py,sha256=ll6pKxVuzMNBDGowOYcPHpFkh4vIRoD_XomXQS8pPOk,11960
19
+ pylocuszoom/backends/bokeh_backend.py,sha256=MQ-UJyGW46Rm6Cj6za9mPn9z8yUVnHibLrAfyNzYp-c,23851
20
+ pylocuszoom/backends/matplotlib_backend.py,sha256=dK3n1KSGSTg4jgnwpa_5A5UvQhbN9hdyEtuDy-uUY1I,13178
21
+ pylocuszoom/backends/plotly_backend.py,sha256=l6H4xabuxZPIGn4bqMb1BGRGylehklvxomun7nL8wIY,29174
22
+ pylocuszoom/reference_data/__init__.py,sha256=qqHqAUt1jebGlCN3CjqW3Z-_coHVNo5K3a3bb9o83hA,109
23
+ pylocuszoom-0.6.0.dist-info/METADATA,sha256=rSgBh890ygYNyPwv6oEBpsIU23BSevMw1Nyfhzv90Bs,16543
24
+ pylocuszoom-0.6.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
25
+ pylocuszoom-0.6.0.dist-info/licenses/LICENSE.md,sha256=U2y_hv8RcN5lECA3uK88irU3ODUE1TDAPictcmnP0Q4,698
26
+ pylocuszoom-0.6.0.dist-info/RECORD,,
@@ -1,21 +0,0 @@
1
- pylocuszoom/__init__.py,sha256=f8h22YYL3JkDP5P_dJftu98qlJkXvaAeyto5kVc8bzU,3785
2
- pylocuszoom/colors.py,sha256=XXTCmCFfHrOrSiP6b0V8Kis7Z1tyvGEKJpdv59QDVQ8,6610
3
- pylocuszoom/eqtl.py,sha256=9lZJ8jT1WEj3won6D9B54xdqUvbRvxpOitf97NCUR28,6167
4
- pylocuszoom/finemapping.py,sha256=PJ4HJYeCaHZecUmADCEGQxKd9HhhjrdIA1H5LQsUmLI,6332
5
- pylocuszoom/gene_track.py,sha256=CbKqIIl-3VpqIS0NWQ7p-VazhrgbF0-XDkkvoWx_2jI,18665
6
- pylocuszoom/labels.py,sha256=Ams5WVZFNVT692BRiQ5wZcdbdNEAm5xtgRwmF5u0s_A,3492
7
- pylocuszoom/ld.py,sha256=64xIulpDVvbMSryWUPoCQ99Odcjwf1wejpwVr_30MLU,6412
8
- pylocuszoom/logging.py,sha256=nZHEkbnjp8zoyWj_S-Hy9UQvUYLoMoxyiOWRozBT2dg,4987
9
- pylocuszoom/plotter.py,sha256=7wEN0b3emb0SM7gYn8bSjXBGNt7npw3y3y5AEC-Ha2k,43660
10
- pylocuszoom/recombination.py,sha256=Q2tAft54nJWHlZt-vZje1r_5RP7D8_VUy5ab_deYXVw,13749
11
- pylocuszoom/utils.py,sha256=fKNX9WSTbfHR1EpPYijt6ycNjXEjwzunQMHXAvHaK3s,5211
12
- pylocuszoom/backends/__init__.py,sha256=7dlGvDoqMVK3fCtoMcI9zOP9qO0odQGPwfXhxnLfXfI,1196
13
- pylocuszoom/backends/base.py,sha256=YEYMtaqPRTJQI-TPqK62-XPN6WvjVwqP6e6ydULK6H0,8523
14
- pylocuszoom/backends/bokeh_backend.py,sha256=oOXTOhSx-tNgBzgtYfYvGUgNmuUP2vhCbtEBOZ5YZ18,18496
15
- pylocuszoom/backends/matplotlib_backend.py,sha256=TIKaT7x0X3QKYUB5076XlG6RC0zbi0hcm3LSU7LGnmw,8521
16
- pylocuszoom/backends/plotly_backend.py,sha256=ucQLmcz6WAdEvII5n3_rdHffZv5-a8FOp8nBGBng-hk,22222
17
- pylocuszoom/reference_data/__init__.py,sha256=qqHqAUt1jebGlCN3CjqW3Z-_coHVNo5K3a3bb9o83hA,109
18
- pylocuszoom-0.3.0.dist-info/METADATA,sha256=P-JbXF9KxFzixMAYKQalKO4F4TwOqxDZD0B0uciyy_c,12068
19
- pylocuszoom-0.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
20
- pylocuszoom-0.3.0.dist-info/licenses/LICENSE.md,sha256=U2y_hv8RcN5lECA3uK88irU3ODUE1TDAPictcmnP0Q4,698
21
- pylocuszoom-0.3.0.dist-info/RECORD,,