gfviewer 2.0.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 (63) hide show
  1. gfviewer-2.0.0/LICENSE +21 -0
  2. gfviewer-2.0.0/MANIFEST.in +28 -0
  3. gfviewer-2.0.0/PKG-INFO +197 -0
  4. gfviewer-2.0.0/README.md +148 -0
  5. gfviewer-2.0.0/docs/BIOCONDA.md +197 -0
  6. gfviewer-2.0.0/docs/INSTALL.md +438 -0
  7. gfviewer-2.0.0/environment.yml +19 -0
  8. gfviewer-2.0.0/flaskapp.py +20 -0
  9. gfviewer-2.0.0/gfviewer/__init__.py +18 -0
  10. gfviewer-2.0.0/gfviewer/analytics.py +1348 -0
  11. gfviewer-2.0.0/gfviewer/charts.py +254 -0
  12. gfviewer-2.0.0/gfviewer/cli.py +284 -0
  13. gfviewer-2.0.0/gfviewer/errors.py +33 -0
  14. gfviewer-2.0.0/gfviewer/genome.py +251 -0
  15. gfviewer-2.0.0/gfviewer/io.py +709 -0
  16. gfviewer-2.0.0/gfviewer/legacy.py +459 -0
  17. gfviewer-2.0.0/gfviewer/palette.py +236 -0
  18. gfviewer-2.0.0/gfviewer/pipeline.py +115 -0
  19. gfviewer-2.0.0/gfviewer/render.py +709 -0
  20. gfviewer-2.0.0/gfviewer/style.py +210 -0
  21. gfviewer-2.0.0/gfviewer.egg-info/PKG-INFO +197 -0
  22. gfviewer-2.0.0/gfviewer.egg-info/SOURCES.txt +61 -0
  23. gfviewer-2.0.0/gfviewer.egg-info/dependency_links.txt +1 -0
  24. gfviewer-2.0.0/gfviewer.egg-info/entry_points.txt +2 -0
  25. gfviewer-2.0.0/gfviewer.egg-info/requires.txt +21 -0
  26. gfviewer-2.0.0/gfviewer.egg-info/top_level.txt +2 -0
  27. gfviewer-2.0.0/gfviewer.py +14 -0
  28. gfviewer-2.0.0/gfviewer_web/__init__.py +73 -0
  29. gfviewer-2.0.0/gfviewer_web/api.py +171 -0
  30. gfviewer-2.0.0/gfviewer_web/config.py +46 -0
  31. gfviewer-2.0.0/gfviewer_web/datasets.py +201 -0
  32. gfviewer-2.0.0/gfviewer_web/errors.py +49 -0
  33. gfviewer-2.0.0/gfviewer_web/jobs.py +585 -0
  34. gfviewer-2.0.0/gfviewer_web/routes.py +127 -0
  35. gfviewer-2.0.0/gfviewer_web/usage.py +181 -0
  36. gfviewer-2.0.0/pyproject.toml +75 -0
  37. gfviewer-2.0.0/requirements.txt +18 -0
  38. gfviewer-2.0.0/setup.cfg +4 -0
  39. gfviewer-2.0.0/static/images/NIH-logo.png +0 -0
  40. gfviewer-2.0.0/static/images/UCR_Icon_WhtBG.png +0 -0
  41. gfviewer-2.0.0/static/images/color_guide_sample.png +0 -0
  42. gfviewer-2.0.0/static/images/logo.png +0 -0
  43. gfviewer-2.0.0/static/js/editor.js +673 -0
  44. gfviewer-2.0.0/static/js/submit.js +36 -0
  45. gfviewer-2.0.0/static/styles.css +341 -0
  46. gfviewer-2.0.0/templates/about_us.html +119 -0
  47. gfviewer-2.0.0/templates/base.html +48 -0
  48. gfviewer-2.0.0/templates/error.html +15 -0
  49. gfviewer-2.0.0/templates/help.html +277 -0
  50. gfviewer-2.0.0/templates/index.html +202 -0
  51. gfviewer-2.0.0/templates/install.html +231 -0
  52. gfviewer-2.0.0/templates/result.html +243 -0
  53. gfviewer-2.0.0/templates/stats.html +64 -0
  54. gfviewer-2.0.0/tests/conftest.py +88 -0
  55. gfviewer-2.0.0/tests/make_fixtures.py +238 -0
  56. gfviewer-2.0.0/tests/test_analytics.py +311 -0
  57. gfviewer-2.0.0/tests/test_genome.py +80 -0
  58. gfviewer-2.0.0/tests/test_io.py +198 -0
  59. gfviewer-2.0.0/tests/test_packaging.py +68 -0
  60. gfviewer-2.0.0/tests/test_palette.py +82 -0
  61. gfviewer-2.0.0/tests/test_render_pipeline.py +241 -0
  62. gfviewer-2.0.0/tests/test_style_cli.py +107 -0
  63. gfviewer-2.0.0/tests/test_webapp.py +314 -0
gfviewer-2.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sakshar Chakravarty and Stefano Lonardi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,28 @@
1
+ # Files to ship in the source distribution (sdist) built by `python -m build`.
2
+ # The wheel contents are controlled by [tool.setuptools] in pyproject.toml.
3
+
4
+ include README.md
5
+ include LICENSE
6
+ include requirements.txt
7
+ include environment.yml
8
+ include pyproject.toml
9
+
10
+ recursive-include docs *.md
11
+ recursive-include gfviewer *.py
12
+ recursive-include gfviewer_web *.py
13
+
14
+ # Web portal assets (only used when running the portal from a source checkout).
15
+ recursive-include templates *.html
16
+ recursive-include static *.css *.js *.png *.svg
17
+
18
+ # Tests and the fixture builder.
19
+ include flaskapp.py gfviewer.py
20
+ recursive-include tests *.py
21
+ include tests/*.csv tests/*.txt
22
+
23
+ # Never ship generated output or large bundled datasets.
24
+ prune static/output
25
+ prune static/tests
26
+ prune uploads
27
+ prune instance
28
+ global-exclude __pycache__ *.py[cod] .DS_Store
@@ -0,0 +1,197 @@
1
+ Metadata-Version: 2.1
2
+ Name: gfviewer
3
+ Version: 2.0.0
4
+ Summary: Visualize and quantify the localization of multigene families across chromosomes
5
+ Author: Sakshar Chakravarty, Stefano Lonardi
6
+ Maintainer-email: Stefano Lonardi <stelo@ucr.edu>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/sakshar/GFViewer
9
+ Project-URL: Repository, https://github.com/sakshar/GFViewer
10
+ Project-URL: Documentation, https://github.com/sakshar/GFViewer/blob/main/docs/INSTALL.md
11
+ Project-URL: Issues, https://github.com/sakshar/GFViewer/issues
12
+ Keywords: bioinformatics,genomics,multigene family,gene family,chromosome,ideogram,karyotype,visualization,comparative genomics,localization,Ripley K
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Environment :: Console
15
+ Classifier: Environment :: Web Environment
16
+ Classifier: Framework :: Flask
17
+ Classifier: Intended Audience :: Science/Research
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.8
22
+ Classifier: Programming Language :: Python :: 3.9
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
27
+ Classifier: Topic :: Scientific/Engineering :: Visualization
28
+ Requires-Python: >=3.8
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: biopython>=1.80
32
+ Requires-Dist: matplotlib>=3.6
33
+ Requires-Dist: pandas>=1.5
34
+ Requires-Dist: numpy>=1.22
35
+ Requires-Dist: openpyxl>=3.0
36
+ Requires-Dist: Pillow>=9.0
37
+ Requires-Dist: reportlab>=3.6
38
+ Requires-Dist: PyPDF2>=3.0
39
+ Requires-Dist: PyYAML>=6.0
40
+ Provides-Extra: web
41
+ Requires-Dist: Flask>=2.2; extra == "web"
42
+ Requires-Dist: Werkzeug>=2.2; extra == "web"
43
+ Requires-Dist: gunicorn>=21.0; extra == "web"
44
+ Provides-Extra: dev
45
+ Requires-Dist: pytest>=7.0; extra == "dev"
46
+ Provides-Extra: build
47
+ Requires-Dist: build>=1.0; extra == "build"
48
+ Requires-Dist: twine>=4.0; extra == "build"
49
+
50
+ # GFViewer
51
+
52
+ Visualize the localization of **multigene families** across the chromosomes of a
53
+ genome, and quantify how those families are distributed.
54
+
55
+ GFViewer draws round-capped chromosome ideograms with each family in its own
56
+ colour (``+`` strand above the axis, ``-`` below), optionally marks centromeres,
57
+ and can compute localization statistics. Output is fully vector and can be saved
58
+ as **PDF, SVG, PNG, JPG, TIFF or EPS**.
59
+
60
+ Version 2 rewrites the rendering engine on top of matplotlib (the old
61
+ BioPython/`BasicChromosome` engine is kept at `gfviewer.legacy` for one
62
+ release), removes the 19-family ceiling, adds BED / GFF3 / GTF input, a style
63
+ system, an analytics module, and an interactive web portal.
64
+
65
+ ## Install
66
+
67
+ ```bash
68
+ pip install gfviewer # the `gfviewer` command-line tool
69
+ ```
70
+
71
+ From a source checkout (development, tests, or the web portal):
72
+
73
+ ```bash
74
+ conda env create -f environment.yml # or: python -m venv .venv && source .venv/bin/activate
75
+ conda activate gfviewer
76
+ pip install -e ".[web,dev]" # editable, with Flask + pytest
77
+ ```
78
+
79
+ A full pip-installation and command-line walkthrough — isolated environments,
80
+ every flag with worked examples, troubleshooting — is in
81
+ [`docs/INSTALL.md`](docs/INSTALL.md), and is mirrored on the web portal's
82
+ **Install** page. Build distributable artifacts with `scripts/build_wheel.sh`.
83
+
84
+ ## Command line
85
+
86
+ ```bash
87
+ gfviewer -d genes.tsv -g genome.fasta -o out/ \
88
+ -f pdf svg png --analytics -cen \
89
+ --tick-style lollipop --title "My organism"
90
+ ```
91
+
92
+ Key options (`gfviewer --help` for the full list):
93
+
94
+ | Flag | Meaning |
95
+ |------|---------|
96
+ | `-d/--data` | one or more annotation files (`.xlsx/.csv/.tsv/.bed/.gff3/.gtf`) |
97
+ | `-g/--genome` | FASTA, `.fai`, `chrom.sizes`, or `chrom,length` table |
98
+ | `-c/--colors` | colour-map file (`family,index` / `family,#hex` / `family,r,g,b`) |
99
+ | `-m/--mapping` | `gene_id,gene_family` map (single BED/GFF input) |
100
+ | `--family-attr` | GFF3/GTF attribute that holds the family |
101
+ | `-f/--format` | export formats |
102
+ | `--collapse-rare` | fold infrequent families into "Other" above the 40-family cap |
103
+ | `--style` / `--save-style` | load / write a YAML/JSON style file |
104
+ | `--analytics` | also write per-family statistics as CSV/JSON |
105
+ | `--no-titles` | omit titles from the exported figure and analytics-chart images |
106
+ | `-cen` | draw centromeres |
107
+
108
+ ### Input formats
109
+
110
+ * **Table** — columns `gene_id, gene_family, chromosome, start, end, strand`
111
+ (1-based, inclusive; header synonyms accepted). A `centromere` value in
112
+ `gene_family` (strand `0`) marks a centromere.
113
+ * **BED** — 0-based half-open, converted automatically. One file → column 4 is
114
+ the family; several files → each file's base name is the family; one file plus
115
+ a mapping file → family from the map.
116
+ * **GFF3 / GTF** — 1-based; gene-like feature types kept; family taken from
117
+ `--family-attr` (default search: `gene_family`, `Family`, `gene_biotype`,
118
+ `Name`, …).
119
+
120
+ ### Analytics
121
+
122
+ `--analytics` writes `analytics_*.csv` / `.bed`, `analytics_summary.json` and
123
+ four figures (`analytics_genes_per_family`, `analytics_positional_profile`,
124
+ `analytics_ripley`, `analytics_family_proximity` — one per requested figure
125
+ format). It computes:
126
+
127
+ * per-family counts split into genes on chromosomes vs. unplaced/stray contigs,
128
+ linear density, gene length, strand fraction;
129
+ * permutation tests for **telomere-** and (with a centromere track)
130
+ **centromere-proximal** bias, plus **p-arm / q-arm** occupancy;
131
+ * **tandem-array** detection and a **tandem / proximal / dispersed** duplication
132
+ mode per family;
133
+ * **multi-scale clustering** — edge-corrected 1-D **Ripley's K/L** with a
134
+ permutation envelope (`--ripley-scales`);
135
+ * **chromosome-enrichment** (binomial, per family × chromosome), **strand bias**,
136
+ and per-chromosome **family diversity** (Shannon / evenness);
137
+ * a binned **positional density profile** ("metachromosome" plot);
138
+ * a **family × family proximity matrix** with average-linkage clustering;
139
+ * **multigene-family hotspots** — a Poisson window scan, merged and written as a
140
+ table and a **BED** file (`--hotspot-window`);
141
+ * optional pairwise **co-localization** (`--colocalization`).
142
+
143
+ Every per-family / per-pair / per-window test carries a Benjamini–Hochberg
144
+ `q_value`. See `templates/help.html` (the *Downloadable outputs* section) for the
145
+ column-by-column layout of each file.
146
+
147
+ ## Web portal
148
+
149
+ ```bash
150
+ # development
151
+ python flaskapp.py # http://localhost:5001
152
+
153
+ # production
154
+ gunicorn -w 1 --threads 4 -b 0.0.0.0:5001 "gfviewer_web:create_app()"
155
+ ```
156
+
157
+ Uploads are rendered on a background thread pool behind an async job API
158
+ (`POST /api/jobs` → `GET /api/jobs/<id>/status` → results page). The results page
159
+ embeds the SVG with an editor for choosing which families and chromosomes to
160
+ draw, recolouring, moving the legend and labels, changing fonts and mark style,
161
+ toggling whether titles are baked into the image files, then re-rendering and
162
+ exporting. Analytics figures are shown inline, and two buttons download
163
+ **everything as a ZIP** — either as produced, or re-rendered in every figure
164
+ format. `GET /api/health` is a readiness probe.
165
+
166
+ **Usage monitor.** A privacy-respecting counter (`/stats`, or JSON at
167
+ `/api/stats`) tracks page views, unique visitors per day (a salted daily hash —
168
+ no IPs, cookies or other personal data are stored), jobs submitted / completed /
169
+ failed, example-dataset runs and downloads, with a rolling ~120-day daily
170
+ series. Counters persist to `instance/usage.json`.
171
+
172
+ Configuration (environment variables): `GFVIEWER_DATA_DIR`,
173
+ `GFVIEWER_MAX_UPLOAD_MB` (25), `GFVIEWER_WORKERS` (2), `GFVIEWER_JOB_TTL_HOURS`
174
+ (24), `GFVIEWER_USAGE_FILE`, `GFVIEWER_STATS_TOKEN` (require `?token=` on
175
+ `/stats`), `SECRET_KEY`, `PORT`.
176
+
177
+ ## Example datasets
178
+
179
+ `python tests/make_fixtures.py` builds every bundled dataset into
180
+ `static/tests/`: the three *Babesia* sets, the 6-family set re-expressed in
181
+ every input format (`formats/` — BED, per-family BED, BED + mapping, GFF3, GTF),
182
+ and two synthetic sets — 10 random gene families on the *Arabidopsis* (TAIR10)
183
+ chromosomes and 20 on *C. elegans* (WBcel235). The web home page lists them all
184
+ with **Run** (submits the job) and **Download** buttons, plus *Download every
185
+ dataset (ZIP)*.
186
+
187
+ ## Tests
188
+
189
+ ```bash
190
+ python tests/make_fixtures.py # once, to build the example datasets
191
+ pytest -q
192
+ ```
193
+
194
+ ## Citation
195
+
196
+ Chakravarty S. & Lonardi S. *Visualizing the localization of multigene families
197
+ with GFViewer.* Development supported by NIH grant 1-R01-AI169543-01.
@@ -0,0 +1,148 @@
1
+ # GFViewer
2
+
3
+ Visualize the localization of **multigene families** across the chromosomes of a
4
+ genome, and quantify how those families are distributed.
5
+
6
+ GFViewer draws round-capped chromosome ideograms with each family in its own
7
+ colour (``+`` strand above the axis, ``-`` below), optionally marks centromeres,
8
+ and can compute localization statistics. Output is fully vector and can be saved
9
+ as **PDF, SVG, PNG, JPG, TIFF or EPS**.
10
+
11
+ Version 2 rewrites the rendering engine on top of matplotlib (the old
12
+ BioPython/`BasicChromosome` engine is kept at `gfviewer.legacy` for one
13
+ release), removes the 19-family ceiling, adds BED / GFF3 / GTF input, a style
14
+ system, an analytics module, and an interactive web portal.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pip install gfviewer # the `gfviewer` command-line tool
20
+ ```
21
+
22
+ From a source checkout (development, tests, or the web portal):
23
+
24
+ ```bash
25
+ conda env create -f environment.yml # or: python -m venv .venv && source .venv/bin/activate
26
+ conda activate gfviewer
27
+ pip install -e ".[web,dev]" # editable, with Flask + pytest
28
+ ```
29
+
30
+ A full pip-installation and command-line walkthrough — isolated environments,
31
+ every flag with worked examples, troubleshooting — is in
32
+ [`docs/INSTALL.md`](docs/INSTALL.md), and is mirrored on the web portal's
33
+ **Install** page. Build distributable artifacts with `scripts/build_wheel.sh`.
34
+
35
+ ## Command line
36
+
37
+ ```bash
38
+ gfviewer -d genes.tsv -g genome.fasta -o out/ \
39
+ -f pdf svg png --analytics -cen \
40
+ --tick-style lollipop --title "My organism"
41
+ ```
42
+
43
+ Key options (`gfviewer --help` for the full list):
44
+
45
+ | Flag | Meaning |
46
+ |------|---------|
47
+ | `-d/--data` | one or more annotation files (`.xlsx/.csv/.tsv/.bed/.gff3/.gtf`) |
48
+ | `-g/--genome` | FASTA, `.fai`, `chrom.sizes`, or `chrom,length` table |
49
+ | `-c/--colors` | colour-map file (`family,index` / `family,#hex` / `family,r,g,b`) |
50
+ | `-m/--mapping` | `gene_id,gene_family` map (single BED/GFF input) |
51
+ | `--family-attr` | GFF3/GTF attribute that holds the family |
52
+ | `-f/--format` | export formats |
53
+ | `--collapse-rare` | fold infrequent families into "Other" above the 40-family cap |
54
+ | `--style` / `--save-style` | load / write a YAML/JSON style file |
55
+ | `--analytics` | also write per-family statistics as CSV/JSON |
56
+ | `--no-titles` | omit titles from the exported figure and analytics-chart images |
57
+ | `-cen` | draw centromeres |
58
+
59
+ ### Input formats
60
+
61
+ * **Table** — columns `gene_id, gene_family, chromosome, start, end, strand`
62
+ (1-based, inclusive; header synonyms accepted). A `centromere` value in
63
+ `gene_family` (strand `0`) marks a centromere.
64
+ * **BED** — 0-based half-open, converted automatically. One file → column 4 is
65
+ the family; several files → each file's base name is the family; one file plus
66
+ a mapping file → family from the map.
67
+ * **GFF3 / GTF** — 1-based; gene-like feature types kept; family taken from
68
+ `--family-attr` (default search: `gene_family`, `Family`, `gene_biotype`,
69
+ `Name`, …).
70
+
71
+ ### Analytics
72
+
73
+ `--analytics` writes `analytics_*.csv` / `.bed`, `analytics_summary.json` and
74
+ four figures (`analytics_genes_per_family`, `analytics_positional_profile`,
75
+ `analytics_ripley`, `analytics_family_proximity` — one per requested figure
76
+ format). It computes:
77
+
78
+ * per-family counts split into genes on chromosomes vs. unplaced/stray contigs,
79
+ linear density, gene length, strand fraction;
80
+ * permutation tests for **telomere-** and (with a centromere track)
81
+ **centromere-proximal** bias, plus **p-arm / q-arm** occupancy;
82
+ * **tandem-array** detection and a **tandem / proximal / dispersed** duplication
83
+ mode per family;
84
+ * **multi-scale clustering** — edge-corrected 1-D **Ripley's K/L** with a
85
+ permutation envelope (`--ripley-scales`);
86
+ * **chromosome-enrichment** (binomial, per family × chromosome), **strand bias**,
87
+ and per-chromosome **family diversity** (Shannon / evenness);
88
+ * a binned **positional density profile** ("metachromosome" plot);
89
+ * a **family × family proximity matrix** with average-linkage clustering;
90
+ * **multigene-family hotspots** — a Poisson window scan, merged and written as a
91
+ table and a **BED** file (`--hotspot-window`);
92
+ * optional pairwise **co-localization** (`--colocalization`).
93
+
94
+ Every per-family / per-pair / per-window test carries a Benjamini–Hochberg
95
+ `q_value`. See `templates/help.html` (the *Downloadable outputs* section) for the
96
+ column-by-column layout of each file.
97
+
98
+ ## Web portal
99
+
100
+ ```bash
101
+ # development
102
+ python flaskapp.py # http://localhost:5001
103
+
104
+ # production
105
+ gunicorn -w 1 --threads 4 -b 0.0.0.0:5001 "gfviewer_web:create_app()"
106
+ ```
107
+
108
+ Uploads are rendered on a background thread pool behind an async job API
109
+ (`POST /api/jobs` → `GET /api/jobs/<id>/status` → results page). The results page
110
+ embeds the SVG with an editor for choosing which families and chromosomes to
111
+ draw, recolouring, moving the legend and labels, changing fonts and mark style,
112
+ toggling whether titles are baked into the image files, then re-rendering and
113
+ exporting. Analytics figures are shown inline, and two buttons download
114
+ **everything as a ZIP** — either as produced, or re-rendered in every figure
115
+ format. `GET /api/health` is a readiness probe.
116
+
117
+ **Usage monitor.** A privacy-respecting counter (`/stats`, or JSON at
118
+ `/api/stats`) tracks page views, unique visitors per day (a salted daily hash —
119
+ no IPs, cookies or other personal data are stored), jobs submitted / completed /
120
+ failed, example-dataset runs and downloads, with a rolling ~120-day daily
121
+ series. Counters persist to `instance/usage.json`.
122
+
123
+ Configuration (environment variables): `GFVIEWER_DATA_DIR`,
124
+ `GFVIEWER_MAX_UPLOAD_MB` (25), `GFVIEWER_WORKERS` (2), `GFVIEWER_JOB_TTL_HOURS`
125
+ (24), `GFVIEWER_USAGE_FILE`, `GFVIEWER_STATS_TOKEN` (require `?token=` on
126
+ `/stats`), `SECRET_KEY`, `PORT`.
127
+
128
+ ## Example datasets
129
+
130
+ `python tests/make_fixtures.py` builds every bundled dataset into
131
+ `static/tests/`: the three *Babesia* sets, the 6-family set re-expressed in
132
+ every input format (`formats/` — BED, per-family BED, BED + mapping, GFF3, GTF),
133
+ and two synthetic sets — 10 random gene families on the *Arabidopsis* (TAIR10)
134
+ chromosomes and 20 on *C. elegans* (WBcel235). The web home page lists them all
135
+ with **Run** (submits the job) and **Download** buttons, plus *Download every
136
+ dataset (ZIP)*.
137
+
138
+ ## Tests
139
+
140
+ ```bash
141
+ python tests/make_fixtures.py # once, to build the example datasets
142
+ pytest -q
143
+ ```
144
+
145
+ ## Citation
146
+
147
+ Chakravarty S. & Lonardi S. *Visualizing the localization of multigene families
148
+ with GFViewer.* Development supported by NIH grant 1-R01-AI169543-01.
@@ -0,0 +1,197 @@
1
+ # Releasing GFViewer on Bioconda
2
+
3
+ GFViewer is packaged on **Bioconda** (channel `bioconda`), recipe at
4
+ `bioconda/bioconda-recipes` → `recipes/gfviewer/meta.yaml`. Recipe maintainer:
5
+ `sakshar`. The package is `noarch: python` and ships the **CLI only**
6
+ (`gfviewer` command); the Flask web portal (`pip install "gfviewer[web]"`) is
7
+ not part of the conda package.
8
+
9
+ Install (Bioconda requires conda-forge in the channel list):
10
+
11
+ ```bash
12
+ conda install -c conda-forge -c bioconda gfviewer
13
+ # or
14
+ mamba install -c conda-forge -c bioconda gfviewer
15
+ ```
16
+
17
+ ---
18
+
19
+ ## How a release reaches Bioconda
20
+
21
+ 1. You push a new tag `vX.Y.Z` to `github.com/sakshar/GFViewer` and cut a GitHub
22
+ Release.
23
+ 2. **BiocondaBot** notices the new tag within a few hours and opens an
24
+ auto-bump PR against `bioconda-recipes` titled *"Update gfviewer to X.Y.Z"*.
25
+ It changes only `version`, `source.url`, `source.sha256` and resets
26
+ `build.number` to `0`.
27
+ 3. Bioconda CI builds the recipe on Linux / OSX / ARM. When green **and a
28
+ maintainer approves**, it is merged and the build bot uploads the package to
29
+ `anaconda.org/bioconda/gfviewer` (usually 30–60 min after merge).
30
+
31
+ The auto-bump PR does **not** update dependencies or metadata — do that in a
32
+ separate follow-up PR (see below) whenever `pyproject.toml` deps change.
33
+
34
+ ---
35
+
36
+ ## Step 1 — Merge the auto-bump PR
37
+
38
+ On the BiocondaBot PR page (e.g. `bioconda/bioconda-recipes#68787` for 2.0.0):
39
+
40
+ 1. Check that all CI checks are green (Linux Tests, OSX-64 Tests,
41
+ build and test (ARM), Lint).
42
+ 2. Verify the `sha256` matches the tag tarball:
43
+
44
+ ```bash
45
+ curl -sL https://github.com/sakshar/GFViewer/archive/refs/tags/vX.Y.Z.tar.gz | shasum -a 256
46
+ ```
47
+
48
+ > GitHub's auto-generated tag tarballs are **not guaranteed byte-stable**,
49
+ > and force-moving a tag changes the hash. If the hashes differ, comment
50
+ > `@BiocondaBot please update` on the PR (or fix `sha256` by hand). Long
51
+ > term, once GFViewer is on PyPI, switch `source.url` to the immutable PyPI
52
+ > sdist: `https://pypi.io/packages/source/g/gfviewer/gfviewer-{{ version }}.tar.gz`.
53
+
54
+ 3. As the recipe maintainer, comment to merge:
55
+
56
+ ```
57
+ @BiocondaBot please merge
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Step 2 — Follow-up PR to update `meta.yaml` (deps / metadata)
63
+
64
+ Do this **after** the auto-bump PR is merged, so you branch off an up-to-date
65
+ `master`. `bioconda-recipes` is huge — edit the single file in the browser
66
+ rather than cloning.
67
+
68
+ ### Web UI (recommended)
69
+
70
+ 1. Open
71
+ `https://github.com/bioconda/bioconda-recipes/blob/master/recipes/gfviewer/meta.yaml`
72
+ and confirm `version:` is the new one.
73
+ 2. Click the **pencil** ("Edit this file"). GitHub prompts to **fork the
74
+ repository** (one-time) — accept.
75
+ 3. Apply your changes (see the reference `meta.yaml` below).
76
+ 4. **Bump `build.number`** by 1 (a recipe change without a version change needs
77
+ a new build number; the auto-bump already set it to `0` for the version
78
+ change, so a same-version follow-up becomes `1`).
79
+ 5. Commit message e.g. `gfviewer: add numpy, pillow, pyyaml to run deps (build 1)`
80
+ → **"Create a new branch and start a pull request"** → branch
81
+ `gfviewer-deps` → **Propose changes**.
82
+ 6. Base must be `bioconda:master`. Complete the PR template checklist
83
+ (one recipe changed; build number bumped).
84
+ 7. When CI is green and approved: `@BiocondaBot please merge`.
85
+
86
+ ### Local git (alternative)
87
+
88
+ ```bash
89
+ # Fork bioconda/bioconda-recipes on GitHub first, then:
90
+ git clone --depth 1 https://github.com/<your-username>/bioconda-recipes.git
91
+ cd bioconda-recipes
92
+ git remote add upstream https://github.com/bioconda/bioconda-recipes.git
93
+ git checkout -b gfviewer-deps
94
+
95
+ $EDITOR recipes/gfviewer/meta.yaml # apply the changes
96
+
97
+ git add recipes/gfviewer/meta.yaml
98
+ git commit -m "gfviewer: add numpy, pillow, pyyaml to run deps (build 1)"
99
+ git push -u origin gfviewer-deps
100
+ # open the PR: <you>:gfviewer-deps -> bioconda:master
101
+ ```
102
+
103
+ No local build needed — Bioconda CI builds it. (A local `conda build` of a
104
+ Bioconda recipe needs `bioconda-utils` and is heavy.)
105
+
106
+ ---
107
+
108
+ ## Reference `meta.yaml` for GFViewer v2.x
109
+
110
+ Keep `requirements.run` in sync with `[project.dependencies]` in
111
+ `pyproject.toml`. As of v2.0.0 that is: biopython, matplotlib, pandas, numpy,
112
+ openpyxl, Pillow, reportlab, PyPDF2, PyYAML. On conda: `matplotlib` →
113
+ `matplotlib-base` (headless), `PyPDF2` → `pypdf2`, `Pillow` → `pillow`,
114
+ `PyYAML` → `pyyaml`.
115
+
116
+ ```yaml
117
+ package:
118
+ name: gfviewer
119
+ version: "2.0.0"
120
+
121
+ source:
122
+ url: https://github.com/sakshar/GFViewer/archive/refs/tags/v2.0.0.tar.gz
123
+ sha256: 30aec61635d669ac86f9596b254646bf1cff3544bc033fe87d0d376510e94c5f
124
+
125
+ build:
126
+ noarch: python
127
+ number: 1 # bump on any recipe change without a version change
128
+ script: "{{ PYTHON }} -m pip install . --no-deps --ignore-installed -vv"
129
+ run_exports:
130
+ - {{ pin_subpackage("gfviewer", max_pin="x") }}
131
+
132
+ requirements:
133
+ host:
134
+ - python >=3.8,<3.13
135
+ - pip
136
+ - setuptools >=64
137
+ - wheel
138
+ run:
139
+ - python >=3.8,<3.13
140
+ - biopython
141
+ - pandas
142
+ - numpy # imported directly by gfviewer.analytics
143
+ - matplotlib-base
144
+ - pillow # matplotlib-base excludes it; needed for -f jpg / tiff
145
+ - reportlab
146
+ - pypdf2
147
+ - openpyxl
148
+ - pyyaml # --style / --save-style *.yaml
149
+
150
+ test:
151
+ imports:
152
+ - gfviewer # do NOT test `import gfviewer_web` (needs Flask, not a dep)
153
+ commands:
154
+ - gfviewer --help
155
+ - gfviewer --version
156
+
157
+ about:
158
+ home: https://github.com/sakshar/GFViewer
159
+ license: MIT
160
+ license_file: LICENSE
161
+ summary: "Visualize and quantify the localization of multigene families across chromosomes."
162
+ description: |
163
+ GFViewer draws round-capped chromosome ideograms with each gene family in
164
+ its own colour and computes localization statistics (sub-telomeric bias,
165
+ tandem arrays, 1-D Ripley's K/L, chromosome enrichment, multigene-family
166
+ hotspots, family-proximity clustering, ...). Reads annotation tables, BED,
167
+ GFF3 and GTF. Provides the `gfviewer` command-line tool.
168
+ dev_url: https://github.com/sakshar/GFViewer
169
+
170
+ extra:
171
+ recipe-maintainers:
172
+ - sakshar
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Checklist for the next version bump (vX.Y.Z)
178
+
179
+ - [ ] `gfviewer/__init__.py::__version__` and `pyproject.toml::version` bumped
180
+ together (`tests/test_packaging.py` fails if they drift).
181
+ - [ ] Tag `vX.Y.Z` pushed; GitHub Release published.
182
+ - [ ] Wait for the BiocondaBot *"Update gfviewer to X.Y.Z"* PR.
183
+ - [ ] Confirm `sha256` matches `curl -sL <tag tarball> | shasum -a 256`.
184
+ - [ ] If `pyproject.toml` deps changed, prepare the `meta.yaml` `run:` update.
185
+ - [ ] `@BiocondaBot please merge` once green + approved.
186
+ - [ ] Follow-up PR for deps/metadata if needed (`build.number` +1).
187
+ - [ ] After the channel updates: `conda install -c conda-forge -c bioconda gfviewer`
188
+ and check `gfviewer --version`.
189
+
190
+ ## Useful BiocondaBot / PR commands
191
+
192
+ | Comment | Effect |
193
+ |---|---|
194
+ | `@BiocondaBot please merge` | maintainer merges a green, approved PR |
195
+ | `@BiocondaBot please update` | regenerate the bump PR (re-fetch source, recompute hash) |
196
+ | `@BiocondaBot please add label` | add the `please review & merge` label |
197
+ | `@bioconda-bot please fetch artifacts` | link to the built packages from CI for local testing |