pycmplot 0.3.1__tar.gz → 0.4.1__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 (52) hide show
  1. {pycmplot-0.3.1 → pycmplot-0.4.1}/PKG-INFO +64 -2
  2. {pycmplot-0.3.1 → pycmplot-0.4.1}/README.md +63 -1
  3. pycmplot-0.4.1/docs-bak/conf.py +90 -0
  4. pycmplot-0.4.1/pycmplot/__init__.py +50 -0
  5. pycmplot-0.4.1/pycmplot/__main__.py +6 -0
  6. pycmplot-0.4.1/pycmplot/_core.py +418 -0
  7. pycmplot-0.4.1/pycmplot/annotation.py +904 -0
  8. pycmplot-0.4.1/pycmplot/cache.py +832 -0
  9. pycmplot-0.4.1/pycmplot/cli.py +614 -0
  10. pycmplot-0.4.1/pycmplot/constants.py +91 -0
  11. pycmplot-0.4.1/pycmplot/io.py +1714 -0
  12. pycmplot-0.4.1/pycmplot/liftover.py +303 -0
  13. pycmplot-0.4.1/pycmplot/plotting/__init__.py +31 -0
  14. pycmplot-0.4.1/pycmplot/plotting/circular.py +831 -0
  15. pycmplot-0.4.1/pycmplot/plotting/linear.py +1756 -0
  16. pycmplot-0.4.1/pycmplot/plotting/qq.py +938 -0
  17. pycmplot-0.4.1/pycmplot/resources.py +199 -0
  18. pycmplot-0.4.1/pycmplot/stats.py +180 -0
  19. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/__init__.py +1 -1
  20. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/_core.py +30 -4
  21. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/annotation.py +298 -0
  22. pycmplot-0.4.1/pycmplot-bak/cache.py +832 -0
  23. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/cli.py +75 -1
  24. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/io.py +449 -82
  25. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/plotting/circular.py +104 -19
  26. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/plotting/linear.py +59 -7
  27. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/plotting/qq.py +248 -26
  28. {pycmplot-0.3.1 → pycmplot-0.4.1}/pycmplot.egg-info/PKG-INFO +64 -2
  29. {pycmplot-0.3.1 → pycmplot-0.4.1}/pycmplot.egg-info/SOURCES.txt +17 -0
  30. {pycmplot-0.3.1 → pycmplot-0.4.1}/pycmplot.egg-info/top_level.txt +2 -0
  31. {pycmplot-0.3.1 → pycmplot-0.4.1}/pyproject.toml +1 -1
  32. {pycmplot-0.3.1 → pycmplot-0.4.1}/setup.cfg +1 -1
  33. {pycmplot-0.3.1 → pycmplot-0.4.1}/LICENSE +0 -0
  34. {pycmplot-0.3.1 → pycmplot-0.4.1}/benchmark/bench_python.py +0 -0
  35. {pycmplot-0.3.1 → pycmplot-0.4.1}/benchmark/build_composite_figure.py +0 -0
  36. {pycmplot-0.3.1 → pycmplot-0.4.1}/benchmark/collect_results.py +0 -0
  37. {pycmplot-0.3.1 → pycmplot-0.4.1}/benchmark/generate_multi_sumstats.py +0 -0
  38. {pycmplot-0.3.1 → pycmplot-0.4.1}/benchmark/generate_sumstats.py +0 -0
  39. {pycmplot-0.3.1 → pycmplot-0.4.1}/pycmplot/data/Homo_sapiens.GRCh37.geneinfo.tsv.gz +0 -0
  40. {pycmplot-0.3.1 → pycmplot-0.4.1}/pycmplot/data/Homo_sapiens.GRCh38.geneinfo.tsv.gz +0 -0
  41. {pycmplot-0.3.1 → pycmplot-0.4.1}/pycmplot/data/hg18ToHg38.over.chain.gz +0 -0
  42. {pycmplot-0.3.1 → pycmplot-0.4.1}/pycmplot/data/hg19ToHg38.over.chain.gz +0 -0
  43. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/__main__.py +0 -0
  44. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/constants.py +0 -0
  45. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/liftover.py +0 -0
  46. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/plotting/__init__.py +0 -0
  47. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/resources.py +0 -0
  48. {pycmplot-0.3.1/pycmplot → pycmplot-0.4.1/pycmplot-bak}/stats.py +0 -0
  49. {pycmplot-0.3.1 → pycmplot-0.4.1}/pycmplot.egg-info/dependency_links.txt +0 -0
  50. {pycmplot-0.3.1 → pycmplot-0.4.1}/pycmplot.egg-info/entry_points.txt +0 -0
  51. {pycmplot-0.3.1 → pycmplot-0.4.1}/pycmplot.egg-info/requires.txt +0 -0
  52. {pycmplot-0.3.1 → pycmplot-0.4.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycmplot
3
- Version: 0.3.1
3
+ Version: 0.4.1
4
4
  Summary: Multi-track circular and linear Manhattan plot generation for GWAS summary statistics
5
5
  Author: Kevin Esoh
6
6
  Author-email: Kevin Esoh <kesohku1@jh.edu>
@@ -43,9 +43,11 @@ Dynamic: license-file
43
43
  <h1 align="center">Multi-track circular and linear Manhattan plotting in Python.</h1>
44
44
  </div>
45
45
 
46
+ <!--
46
47
  <p align="center">
47
- <img width="600" height="400" src="docs/pycmplot-logo-circular.png">
48
+ <img width="600" height="400" src="https://github.com/esohkevin/pycmplot/blob/main/docs/pycmplot-logo-circular.png">
48
49
  </p>
50
+ -->
49
51
 
50
52
 
51
53
  ```
@@ -67,6 +69,10 @@ Dynamic: license-file
67
69
  - [Trim insignificant variants for faster plotting](#trim-insignificant-variants-for-faster-plotting)
68
70
  - [Genome build conversion (liftover)](#genome-build-conversion-liftover)
69
71
  - [Nearest-gene annotation for GWAS lead SNPs](#nearest-gene-annotation-for-gwas-lead-snps)
72
+ - [Caching & warm resume](#caching--warm-resume)
73
+ - [User-editable hits overlay](#user-editable-hits-overlay)
74
+ - [Per-locus highlight colours & custom legend](#per-locus-highlight-colours--custom-legend)
75
+ - [Multi-panel canvas](#multi-panel-canvas)
70
76
  3. [Application](#application)
71
77
  4. [Tip](#tip)
72
78
  5. [Installation](#installation)
@@ -179,6 +185,46 @@ for gene annotation. Also included are UCSC chain files for coordinate conversio
179
185
  ``Homo_sapiens.GRCh37.geneinfo.tsv.gz``.
180
186
 
181
187
 
188
+ ### Caching & warm resume
189
+ Loading is the expensive step (I/O + trim + liftover + lead extraction), so
190
+ pycmplot ships a per-track cache keyed on `SHA-256(raw_file_sha256 + version + Stage-1 params)`.
191
+ Warm re-runs of the same `(files, parameters)` combination complete in
192
+ milliseconds; changing any parameter transparently invalidates only the
193
+ affected tracks and regenerates them. Enable with `--cache` (CLI) or
194
+ `cache=True` (Python API); use `--clear_cache` to wipe the tree.
195
+
196
+ ```bash
197
+ pycmplot --sum_stats hb.tsv,mcv.tsv --labels Hb,MCV \
198
+ --logp --highlight --cache --cache_dir ./.pycmplot
199
+ ```
200
+
201
+ ### User-editable hits overlay
202
+ When caching is on, the auto-generated hits table is written to a
203
+ group-scoped TSV at `<cache_dir>/annotations/hits.<group_key>.tsv`
204
+ that you're *expected to hand-edit*. Rows added or changed there feed
205
+ straight back into the next plot — no re-plumbing required. Each row
206
+ carries `source` (`auto` vs `user`), `highlight_color`, and `category`
207
+ columns; user edits are inherited across cache regenerations by
208
+ `(CHR, POS)` lookup, so re-running with a new parameter never loses
209
+ your annotations.
210
+
211
+ ### Per-locus highlight colours & custom legend
212
+ Set the `highlight_color` column on any row of the hits overlay to a
213
+ matplotlib-parseable colour (name, `#rrggbb`, or an RGB tuple) to give
214
+ that locus its own highlight colour; leave `auto` to fall back to the
215
+ plot-wide `--highlight_color`. Set the `category` column
216
+ (e.g. `novel`, `replicated`, `MHC`) to group loci in a
217
+ **"Highlighted Categories"** legend that both the linear and circular
218
+ plotters render automatically. If nothing is edited, no legend is
219
+ added — the pre-feature layout is preserved.
220
+
221
+ ### Multi-panel canvas
222
+ Place multiple *groups* of sumstats on the same figure by passing an
223
+ explicit matplotlib `Axes` or `SubFigure` via `ax=` to the plotter.
224
+ Cache files and hits overlays are group-scoped, so two panels with
225
+ different sumstats never clobber each other's artefacts.
226
+
227
+
182
228
  ## Application
183
229
  A potential useful application is **comparative visualization** of results from multiple imputation panels,
184
230
  multiple populations, or multiple traits to observe shared genetic architecture.
@@ -305,6 +351,16 @@ pycmplot \
305
351
  | `-st, --sort_track` | Sort tracks by `label` or `chrom_len` | input order |
306
352
  | `-od, --output_dir` | Output directory | `.` |
307
353
  | `-of, --output_format` | Output format (`png`, `pdf`, `svg`, `jpg`) | `png` |
354
+ | `--cache` | Enable per-track cache + user-editable hits overlay | off |
355
+ | `--cache_dir` | Where to store cache artefacts | `./.pycmplot` |
356
+ | `--no_resume` | Regenerate but still write fresh cache entries | resume on |
357
+ | `--clear_cache` | Delete the cache tree and exit | off |
358
+ | `-V, --version` | Print version and exit | — |
359
+
360
+ > **QQ note (0.4.0+):** the loader no longer materialises the full sorted
361
+ > p-value array by default. `-qq/--qq_plot` sets `compute_pvals=True`
362
+ > automatically on the CLI; Python-API callers must pass it explicitly
363
+ > to feed `bundle['pvals']` into a QQ plotter.
308
364
 
309
365
  Run `pycmplot -h` for the full option list.
310
366
 
@@ -314,6 +370,12 @@ Run `pycmplot -h` for the full option list.
314
370
 
315
371
  A demonstration of how to use the python API is provided in this notebook: https://github.com/esohkevin/pycmplot/blob/main/pycmplot_python_api.ipynb
316
372
 
373
+ For an end-to-end walkthrough of every feature (caching, hits overlay,
374
+ per-locus colours & categories, multi-panel canvas, mixed-build
375
+ liftover, QQ opt-in), see the
376
+ [Tutorial](https://pycmplot.readthedocs.io/en/latest/tutorial.html)
377
+ page in the docs.
378
+
317
379
 
318
380
  ---
319
381
 
@@ -4,9 +4,11 @@
4
4
  <h1 align="center">Multi-track circular and linear Manhattan plotting in Python.</h1>
5
5
  </div>
6
6
 
7
+ <!--
7
8
  <p align="center">
8
- <img width="600" height="400" src="docs/pycmplot-logo-circular.png">
9
+ <img width="600" height="400" src="https://github.com/esohkevin/pycmplot/blob/main/docs/pycmplot-logo-circular.png">
9
10
  </p>
11
+ -->
10
12
 
11
13
 
12
14
  ```
@@ -28,6 +30,10 @@
28
30
  - [Trim insignificant variants for faster plotting](#trim-insignificant-variants-for-faster-plotting)
29
31
  - [Genome build conversion (liftover)](#genome-build-conversion-liftover)
30
32
  - [Nearest-gene annotation for GWAS lead SNPs](#nearest-gene-annotation-for-gwas-lead-snps)
33
+ - [Caching & warm resume](#caching--warm-resume)
34
+ - [User-editable hits overlay](#user-editable-hits-overlay)
35
+ - [Per-locus highlight colours & custom legend](#per-locus-highlight-colours--custom-legend)
36
+ - [Multi-panel canvas](#multi-panel-canvas)
31
37
  3. [Application](#application)
32
38
  4. [Tip](#tip)
33
39
  5. [Installation](#installation)
@@ -140,6 +146,46 @@ for gene annotation. Also included are UCSC chain files for coordinate conversio
140
146
  ``Homo_sapiens.GRCh37.geneinfo.tsv.gz``.
141
147
 
142
148
 
149
+ ### Caching & warm resume
150
+ Loading is the expensive step (I/O + trim + liftover + lead extraction), so
151
+ pycmplot ships a per-track cache keyed on `SHA-256(raw_file_sha256 + version + Stage-1 params)`.
152
+ Warm re-runs of the same `(files, parameters)` combination complete in
153
+ milliseconds; changing any parameter transparently invalidates only the
154
+ affected tracks and regenerates them. Enable with `--cache` (CLI) or
155
+ `cache=True` (Python API); use `--clear_cache` to wipe the tree.
156
+
157
+ ```bash
158
+ pycmplot --sum_stats hb.tsv,mcv.tsv --labels Hb,MCV \
159
+ --logp --highlight --cache --cache_dir ./.pycmplot
160
+ ```
161
+
162
+ ### User-editable hits overlay
163
+ When caching is on, the auto-generated hits table is written to a
164
+ group-scoped TSV at `<cache_dir>/annotations/hits.<group_key>.tsv`
165
+ that you're *expected to hand-edit*. Rows added or changed there feed
166
+ straight back into the next plot — no re-plumbing required. Each row
167
+ carries `source` (`auto` vs `user`), `highlight_color`, and `category`
168
+ columns; user edits are inherited across cache regenerations by
169
+ `(CHR, POS)` lookup, so re-running with a new parameter never loses
170
+ your annotations.
171
+
172
+ ### Per-locus highlight colours & custom legend
173
+ Set the `highlight_color` column on any row of the hits overlay to a
174
+ matplotlib-parseable colour (name, `#rrggbb`, or an RGB tuple) to give
175
+ that locus its own highlight colour; leave `auto` to fall back to the
176
+ plot-wide `--highlight_color`. Set the `category` column
177
+ (e.g. `novel`, `replicated`, `MHC`) to group loci in a
178
+ **"Highlighted Categories"** legend that both the linear and circular
179
+ plotters render automatically. If nothing is edited, no legend is
180
+ added — the pre-feature layout is preserved.
181
+
182
+ ### Multi-panel canvas
183
+ Place multiple *groups* of sumstats on the same figure by passing an
184
+ explicit matplotlib `Axes` or `SubFigure` via `ax=` to the plotter.
185
+ Cache files and hits overlays are group-scoped, so two panels with
186
+ different sumstats never clobber each other's artefacts.
187
+
188
+
143
189
  ## Application
144
190
  A potential useful application is **comparative visualization** of results from multiple imputation panels,
145
191
  multiple populations, or multiple traits to observe shared genetic architecture.
@@ -266,6 +312,16 @@ pycmplot \
266
312
  | `-st, --sort_track` | Sort tracks by `label` or `chrom_len` | input order |
267
313
  | `-od, --output_dir` | Output directory | `.` |
268
314
  | `-of, --output_format` | Output format (`png`, `pdf`, `svg`, `jpg`) | `png` |
315
+ | `--cache` | Enable per-track cache + user-editable hits overlay | off |
316
+ | `--cache_dir` | Where to store cache artefacts | `./.pycmplot` |
317
+ | `--no_resume` | Regenerate but still write fresh cache entries | resume on |
318
+ | `--clear_cache` | Delete the cache tree and exit | off |
319
+ | `-V, --version` | Print version and exit | — |
320
+
321
+ > **QQ note (0.4.0+):** the loader no longer materialises the full sorted
322
+ > p-value array by default. `-qq/--qq_plot` sets `compute_pvals=True`
323
+ > automatically on the CLI; Python-API callers must pass it explicitly
324
+ > to feed `bundle['pvals']` into a QQ plotter.
269
325
 
270
326
  Run `pycmplot -h` for the full option list.
271
327
 
@@ -275,6 +331,12 @@ Run `pycmplot -h` for the full option list.
275
331
 
276
332
  A demonstration of how to use the python API is provided in this notebook: https://github.com/esohkevin/pycmplot/blob/main/pycmplot_python_api.ipynb
277
333
 
334
+ For an end-to-end walkthrough of every feature (caching, hits overlay,
335
+ per-locus colours & categories, multi-panel canvas, mixed-build
336
+ liftover, QQ opt-in), see the
337
+ [Tutorial](https://pycmplot.readthedocs.io/en/latest/tutorial.html)
338
+ page in the docs.
339
+
278
340
 
279
341
  ---
280
342
 
@@ -0,0 +1,90 @@
1
+ # Configuration file for the Sphinx documentation builder.
2
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html
3
+
4
+ import os
5
+ import sys
6
+
7
+ # -- Path setup ---------------------------------------------------------------
8
+ # Allow Sphinx to find the pycmplot package (needed for autodoc)
9
+ sys.path.insert(0, os.path.abspath(".."))
10
+
11
+ # -- Project information -------------------------------------------------------
12
+ project = "pycmplot"
13
+ copyright = "2026, Kevin Esoh"
14
+ author = "Kevin Esoh"
15
+ release = "0.3.1" # update to match PyPI version
16
+
17
+ # -- General configuration -----------------------------------------------------
18
+ extensions = [
19
+ "sphinx.ext.autodoc", # auto-generate docs from docstrings
20
+ "sphinx.ext.autosummary", # summary tables for modules/classes
21
+ "sphinx.ext.napoleon", # NumPy / Google docstring styles
22
+ "sphinx.ext.viewcode", # [source] links in API docs
23
+ "sphinx.ext.intersphinx", # cross-links to numpy, pandas, matplotlib docs
24
+ "numpydoc", # richer NumPy-style rendering
25
+ "nbsphinx", # embed Jupyter notebooks
26
+ "sphinx_copybutton", # copy-button on code blocks
27
+ "myst_parser", # allow Markdown (.md) pages alongside .rst
28
+ ]
29
+
30
+ # Napoleon settings (NumPy docstring style)
31
+ napoleon_google_docstring = False
32
+ napoleon_numpy_docstring = True
33
+ napoleon_include_init_with_doc = True
34
+ napoleon_include_private_with_doc = False
35
+ napoleon_use_param = True
36
+ napoleon_use_rtype = True
37
+
38
+ # numpydoc settings
39
+ numpydoc_show_class_members = False
40
+
41
+ # Autosummary: auto-generate stub files
42
+ autosummary_generate = True
43
+ autodoc_default_options = {
44
+ "members": True,
45
+ "undoc-members": False,
46
+ "show-inheritance": True,
47
+ }
48
+
49
+ # Intersphinx: link to external package docs
50
+ intersphinx_mapping = {
51
+ "python": ("https://docs.python.org/3", None),
52
+ "numpy": ("https://numpy.org/doc/stable", None),
53
+ "pandas": ("https://pandas.pydata.org/docs", None),
54
+ "matplotlib": ("https://matplotlib.org/stable", None),
55
+ }
56
+
57
+ # nbsphinx: do not re-execute notebooks during docs build
58
+ nbsphinx_execute = "never"
59
+
60
+ # Source file suffixes
61
+ source_suffix = {
62
+ ".rst": "restructuredtext",
63
+ ".md": "markdown",
64
+ }
65
+
66
+ templates_path = ["_templates"]
67
+ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "**.ipynb_checkpoints"]
68
+
69
+ # -- Options for HTML output ---------------------------------------------------
70
+ html_theme = "sphinx_rtd_theme"
71
+ html_theme_options = {
72
+ "logo_only": False,
73
+ "prev_next_buttons_location": "bottom",
74
+ "style_nav_header_background": "#2980B9",
75
+ "collapse_navigation": False,
76
+ "sticky_navigation": True,
77
+ "navigation_depth": 4,
78
+ "includehidden": True,
79
+ "titles_only": False,
80
+ }
81
+
82
+ html_static_path = ["_static"]
83
+ html_css_files = ["custom.css"]
84
+
85
+ # Optional: path to logo image (add docs/_static/logo.png if you have one)
86
+ # html_logo = "_static/logo.png"
87
+
88
+ html_show_sourcelink = True
89
+ html_show_sphinx = True
90
+ html_show_copyright = True
@@ -0,0 +1,50 @@
1
+ """
2
+ pycmplot
3
+ ========
4
+ Multi-track circular and linear Manhattan plot generation for GWAS summary statistics.
5
+
6
+ Quickstart
7
+ ----------
8
+ Command-line::
9
+
10
+ pycmplot -s file1.gz,file2.gz -l HbF,MCV --logp --mode lm
11
+
12
+ Python API::
13
+
14
+ from pycmplot.io import prep_pycmplot_input_info, get_sumstats_and_merged_sector_list
15
+ from pycmplot.plotting import plot_linear, plot_circular, plot_qq_single, plot_qq_separate, plot_qq_overlay, plot_qq_combined
16
+ from pycmplot.stats import get_lead_snps
17
+ from pycmplot.annotation import get_hits_summary_table
18
+
19
+ Public surface
20
+ --------------
21
+ """
22
+
23
+ from pycmplot.plotting.linear import plot_linear
24
+ from pycmplot.plotting.circular import plot_circular, compute_track_radii_dict
25
+ from pycmplot.plotting.qq import plot_qq_single, plot_qq_separate, plot_qq_overlay, plot_qq_combined
26
+ from pycmplot.stats import get_lead_snps, get_highlight_snps
27
+ from pycmplot.io import prep_pycmplot_input_info, get_sumstats_and_merged_sector_list
28
+ from pycmplot.annotation import get_hits_summary_table
29
+ from pycmplot.constants import hg38_chr_lengths, BIOTYPE_WEIGHTS
30
+ from pycmplot.resources import ResourceConfig
31
+
32
+ __all__ = [
33
+ "plot_linear",
34
+ "plot_circular",
35
+ "plot_qq_single",
36
+ "plot_qq_separate",
37
+ "plot_qq_overlay",
38
+ "plot_qq_combined",
39
+ "compute_track_radii_dict",
40
+ "get_lead_snps",
41
+ "get_highlight_snps",
42
+ "prep_pycmplot_input_info",
43
+ "get_sumstats_and_merged_sector_list",
44
+ "get_hits_summary_table",
45
+ "hg38_chr_lengths",
46
+ "BIOTYPE_WEIGHTS",
47
+ "ResourceConfig",
48
+ ]
49
+
50
+ __version__ = "0.4.1"
@@ -0,0 +1,6 @@
1
+ """Entry point for ``python -m pycmplot`` invocation."""
2
+
3
+ from pycmplot._core import main
4
+
5
+ if __name__ == "__main__":
6
+ main()