gpgraph-v2 1.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.
- gpgraph_v2-1.0.0/Cargo.lock +283 -0
- gpgraph_v2-1.0.0/Cargo.toml +10 -0
- gpgraph_v2-1.0.0/LICENSE +21 -0
- gpgraph_v2-1.0.0/PKG-INFO +218 -0
- gpgraph_v2-1.0.0/README.md +184 -0
- gpgraph_v2-1.0.0/crates/gpgraph-core/Cargo.toml +23 -0
- gpgraph_v2-1.0.0/crates/gpgraph-core/src/codon.rs +128 -0
- gpgraph_v2-1.0.0/crates/gpgraph-core/src/hamming.rs +221 -0
- gpgraph_v2-1.0.0/crates/gpgraph-core/src/lib.rs +89 -0
- gpgraph_v2-1.0.0/pyproject.toml +127 -0
- gpgraph_v2-1.0.0/python/gpgraph/__init__.py +33 -0
- gpgraph_v2-1.0.0/python/gpgraph/_rust.pyi +25 -0
- gpgraph_v2-1.0.0/python/gpgraph/_version.py +1 -0
- gpgraph_v2-1.0.0/python/gpgraph/base.py +231 -0
- gpgraph_v2-1.0.0/python/gpgraph/exceptions.py +11 -0
- gpgraph_v2-1.0.0/python/gpgraph/fixation.py +267 -0
- gpgraph_v2-1.0.0/python/gpgraph/layout.py +81 -0
- gpgraph_v2-1.0.0/python/gpgraph/neighbors.py +141 -0
- gpgraph_v2-1.0.0/python/gpgraph/paths.py +130 -0
- gpgraph_v2-1.0.0/python/gpgraph/pyplot/__init__.py +29 -0
- gpgraph_v2-1.0.0/python/gpgraph/pyplot/draw.py +118 -0
- gpgraph_v2-1.0.0/python/gpgraph/pyplot/paths.py +98 -0
- gpgraph_v2-1.0.0/python/gpgraph/pyplot/primitives.py +54 -0
- gpgraph_v2-1.0.0/python/gpgraph/pyplot/utils.py +60 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 3
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "autocfg"
|
|
7
|
+
version = "1.5.0"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "crossbeam-deque"
|
|
13
|
+
version = "0.8.6"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
|
16
|
+
dependencies = [
|
|
17
|
+
"crossbeam-epoch",
|
|
18
|
+
"crossbeam-utils",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[[package]]
|
|
22
|
+
name = "crossbeam-epoch"
|
|
23
|
+
version = "0.9.18"
|
|
24
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
25
|
+
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
|
26
|
+
dependencies = [
|
|
27
|
+
"crossbeam-utils",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[[package]]
|
|
31
|
+
name = "crossbeam-utils"
|
|
32
|
+
version = "0.8.21"
|
|
33
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
34
|
+
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
|
35
|
+
|
|
36
|
+
[[package]]
|
|
37
|
+
name = "either"
|
|
38
|
+
version = "1.15.0"
|
|
39
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
40
|
+
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
|
41
|
+
|
|
42
|
+
[[package]]
|
|
43
|
+
name = "gpgraph-core"
|
|
44
|
+
version = "1.0.0"
|
|
45
|
+
dependencies = [
|
|
46
|
+
"ndarray",
|
|
47
|
+
"numpy",
|
|
48
|
+
"pyo3",
|
|
49
|
+
"rayon",
|
|
50
|
+
"rustc-hash",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[[package]]
|
|
54
|
+
name = "heck"
|
|
55
|
+
version = "0.5.0"
|
|
56
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
57
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
58
|
+
|
|
59
|
+
[[package]]
|
|
60
|
+
name = "libc"
|
|
61
|
+
version = "0.2.185"
|
|
62
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
63
|
+
checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
|
|
64
|
+
|
|
65
|
+
[[package]]
|
|
66
|
+
name = "matrixmultiply"
|
|
67
|
+
version = "0.3.10"
|
|
68
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
69
|
+
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
|
|
70
|
+
dependencies = [
|
|
71
|
+
"autocfg",
|
|
72
|
+
"rawpointer",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
[[package]]
|
|
76
|
+
name = "ndarray"
|
|
77
|
+
version = "0.17.2"
|
|
78
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
79
|
+
checksum = "520080814a7a6b4a6e9070823bb24b4531daac8c4627e08ba5de8c5ef2f2752d"
|
|
80
|
+
dependencies = [
|
|
81
|
+
"matrixmultiply",
|
|
82
|
+
"num-complex",
|
|
83
|
+
"num-integer",
|
|
84
|
+
"num-traits",
|
|
85
|
+
"portable-atomic",
|
|
86
|
+
"portable-atomic-util",
|
|
87
|
+
"rawpointer",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
[[package]]
|
|
91
|
+
name = "num-complex"
|
|
92
|
+
version = "0.4.6"
|
|
93
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
94
|
+
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
|
95
|
+
dependencies = [
|
|
96
|
+
"num-traits",
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
[[package]]
|
|
100
|
+
name = "num-integer"
|
|
101
|
+
version = "0.1.46"
|
|
102
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
103
|
+
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
|
104
|
+
dependencies = [
|
|
105
|
+
"num-traits",
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
[[package]]
|
|
109
|
+
name = "num-traits"
|
|
110
|
+
version = "0.2.19"
|
|
111
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
112
|
+
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
|
113
|
+
dependencies = [
|
|
114
|
+
"autocfg",
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
[[package]]
|
|
118
|
+
name = "numpy"
|
|
119
|
+
version = "0.28.0"
|
|
120
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
121
|
+
checksum = "778da78c64ddc928ebf5ad9df5edf0789410ff3bdbf3619aed51cd789a6af1e2"
|
|
122
|
+
dependencies = [
|
|
123
|
+
"libc",
|
|
124
|
+
"ndarray",
|
|
125
|
+
"num-complex",
|
|
126
|
+
"num-integer",
|
|
127
|
+
"num-traits",
|
|
128
|
+
"pyo3",
|
|
129
|
+
"pyo3-build-config",
|
|
130
|
+
"rustc-hash",
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
[[package]]
|
|
134
|
+
name = "once_cell"
|
|
135
|
+
version = "1.21.4"
|
|
136
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
137
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
138
|
+
|
|
139
|
+
[[package]]
|
|
140
|
+
name = "portable-atomic"
|
|
141
|
+
version = "1.13.1"
|
|
142
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
143
|
+
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
|
144
|
+
|
|
145
|
+
[[package]]
|
|
146
|
+
name = "portable-atomic-util"
|
|
147
|
+
version = "0.2.7"
|
|
148
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
149
|
+
checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618"
|
|
150
|
+
dependencies = [
|
|
151
|
+
"portable-atomic",
|
|
152
|
+
]
|
|
153
|
+
|
|
154
|
+
[[package]]
|
|
155
|
+
name = "proc-macro2"
|
|
156
|
+
version = "1.0.106"
|
|
157
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
158
|
+
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
|
159
|
+
dependencies = [
|
|
160
|
+
"unicode-ident",
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
[[package]]
|
|
164
|
+
name = "pyo3"
|
|
165
|
+
version = "0.28.3"
|
|
166
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
167
|
+
checksum = "91fd8e38a3b50ed1167fb981cd6fd60147e091784c427b8f7183a7ee32c31c12"
|
|
168
|
+
dependencies = [
|
|
169
|
+
"libc",
|
|
170
|
+
"once_cell",
|
|
171
|
+
"portable-atomic",
|
|
172
|
+
"pyo3-build-config",
|
|
173
|
+
"pyo3-ffi",
|
|
174
|
+
"pyo3-macros",
|
|
175
|
+
]
|
|
176
|
+
|
|
177
|
+
[[package]]
|
|
178
|
+
name = "pyo3-build-config"
|
|
179
|
+
version = "0.28.3"
|
|
180
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
181
|
+
checksum = "e368e7ddfdeb98c9bca7f8383be1648fd84ab466bf2bc015e94008db6d35611e"
|
|
182
|
+
dependencies = [
|
|
183
|
+
"target-lexicon",
|
|
184
|
+
]
|
|
185
|
+
|
|
186
|
+
[[package]]
|
|
187
|
+
name = "pyo3-ffi"
|
|
188
|
+
version = "0.28.3"
|
|
189
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
190
|
+
checksum = "7f29e10af80b1f7ccaf7f69eace800a03ecd13e883acfacc1e5d0988605f651e"
|
|
191
|
+
dependencies = [
|
|
192
|
+
"libc",
|
|
193
|
+
"pyo3-build-config",
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
[[package]]
|
|
197
|
+
name = "pyo3-macros"
|
|
198
|
+
version = "0.28.3"
|
|
199
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
200
|
+
checksum = "df6e520eff47c45997d2fc7dd8214b25dd1310918bbb2642156ef66a67f29813"
|
|
201
|
+
dependencies = [
|
|
202
|
+
"proc-macro2",
|
|
203
|
+
"pyo3-macros-backend",
|
|
204
|
+
"quote",
|
|
205
|
+
"syn",
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
[[package]]
|
|
209
|
+
name = "pyo3-macros-backend"
|
|
210
|
+
version = "0.28.3"
|
|
211
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
212
|
+
checksum = "c4cdc218d835738f81c2338f822078af45b4afdf8b2e33cbb5916f108b813acb"
|
|
213
|
+
dependencies = [
|
|
214
|
+
"heck",
|
|
215
|
+
"proc-macro2",
|
|
216
|
+
"pyo3-build-config",
|
|
217
|
+
"quote",
|
|
218
|
+
"syn",
|
|
219
|
+
]
|
|
220
|
+
|
|
221
|
+
[[package]]
|
|
222
|
+
name = "quote"
|
|
223
|
+
version = "1.0.45"
|
|
224
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
225
|
+
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
|
226
|
+
dependencies = [
|
|
227
|
+
"proc-macro2",
|
|
228
|
+
]
|
|
229
|
+
|
|
230
|
+
[[package]]
|
|
231
|
+
name = "rawpointer"
|
|
232
|
+
version = "0.2.1"
|
|
233
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
234
|
+
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
|
235
|
+
|
|
236
|
+
[[package]]
|
|
237
|
+
name = "rayon"
|
|
238
|
+
version = "1.12.0"
|
|
239
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
240
|
+
checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
|
|
241
|
+
dependencies = [
|
|
242
|
+
"either",
|
|
243
|
+
"rayon-core",
|
|
244
|
+
]
|
|
245
|
+
|
|
246
|
+
[[package]]
|
|
247
|
+
name = "rayon-core"
|
|
248
|
+
version = "1.13.0"
|
|
249
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
250
|
+
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
|
251
|
+
dependencies = [
|
|
252
|
+
"crossbeam-deque",
|
|
253
|
+
"crossbeam-utils",
|
|
254
|
+
]
|
|
255
|
+
|
|
256
|
+
[[package]]
|
|
257
|
+
name = "rustc-hash"
|
|
258
|
+
version = "2.1.2"
|
|
259
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
260
|
+
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
|
|
261
|
+
|
|
262
|
+
[[package]]
|
|
263
|
+
name = "syn"
|
|
264
|
+
version = "2.0.117"
|
|
265
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
266
|
+
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
|
267
|
+
dependencies = [
|
|
268
|
+
"proc-macro2",
|
|
269
|
+
"quote",
|
|
270
|
+
"unicode-ident",
|
|
271
|
+
]
|
|
272
|
+
|
|
273
|
+
[[package]]
|
|
274
|
+
name = "target-lexicon"
|
|
275
|
+
version = "0.13.5"
|
|
276
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
277
|
+
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
278
|
+
|
|
279
|
+
[[package]]
|
|
280
|
+
name = "unicode-ident"
|
|
281
|
+
version = "1.0.24"
|
|
282
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
283
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
gpgraph_v2-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Luis Perez
|
|
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,218 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gpgraph-v2
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Intended Audience :: Science/Research
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Operating System :: OS Independent
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Programming Language :: Rust
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
14
|
+
Requires-Dist: numpy>=2.0
|
|
15
|
+
Requires-Dist: networkx>=3.6
|
|
16
|
+
Requires-Dist: gpmap-v2>=1.0
|
|
17
|
+
Requires-Dist: tqdm>=4.67
|
|
18
|
+
Requires-Dist: typing-extensions>=4.12
|
|
19
|
+
Requires-Dist: matplotlib>=3.10 ; extra == 'plot'
|
|
20
|
+
Requires-Dist: streamlit>=1.56 ; extra == 'streamlit'
|
|
21
|
+
Requires-Dist: matplotlib>=3.10 ; extra == 'streamlit'
|
|
22
|
+
Provides-Extra: plot
|
|
23
|
+
Provides-Extra: streamlit
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Summary: NetworkX-backed, Rust-accelerated graphs over genotype-phenotype maps.
|
|
26
|
+
Keywords: genotype,phenotype,epistasis,fitness-landscape,networkx,graph
|
|
27
|
+
Author-email: Luis Perez <lperezmo@users.noreply.github.com>
|
|
28
|
+
Requires-Python: >=3.11
|
|
29
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
30
|
+
Project-URL: Homepage, https://github.com/lperezmo/gpgraph-v2
|
|
31
|
+
Project-URL: Issues, https://github.com/lperezmo/gpgraph-v2/issues
|
|
32
|
+
Project-URL: Repository, https://github.com/lperezmo/gpgraph-v2
|
|
33
|
+
|
|
34
|
+
# gpgraph-v2
|
|
35
|
+
|
|
36
|
+
[](https://github.com/lperezmo/gpgraph-v2/actions/workflows/ci.yml)
|
|
37
|
+
[](https://pypi.org/project/gpgraph-v2/)
|
|
38
|
+
[](https://pypi.org/project/gpgraph-v2/)
|
|
39
|
+
[](LICENSE)
|
|
40
|
+
[](https://gpgraph-v2.streamlit.app)
|
|
41
|
+
|
|
42
|
+
NetworkX-backed, Rust-accelerated graphs over genotype-phenotype maps.
|
|
43
|
+
|
|
44
|
+
gpgraph-v2 lifts a [gpmap-v2](https://github.com/lperezmo/gpmap-v2) `GenotypePhenotypeMap` into a
|
|
45
|
+
NetworkX `DiGraph`. Nodes carry the row attributes from the map; edges connect neighbors under
|
|
46
|
+
a chosen distance metric (Hamming or codon). Fixation models (SSWM, ratio, Moran, McCandlish)
|
|
47
|
+
populate an edge `prob` attribute for evolutionary trajectory analysis.
|
|
48
|
+
|
|
49
|
+
This is a clean-break rewrite of [harmslab/gpgraph](https://github.com/harmslab/gpgraph).
|
|
50
|
+
Hot paths live in Rust via PyO3 + rayon; fixation models stay in vectorized numpy.
|
|
51
|
+
|
|
52
|
+
## Why v2
|
|
53
|
+
|
|
54
|
+
- **Fast.** Neighbor detection runs in Rust with rayon parallelism. Biallelic cutoff-1 and
|
|
55
|
+
cutoff-2 hit a bit-flip fast path: `O(N * L^cutoff)` instead of `O(N^2 * L)`.
|
|
56
|
+
- **Typed.** Full type hints, `mypy --strict` in CI.
|
|
57
|
+
- **Modern tooling.** `uv` + `maturin` + `pyproject.toml`. Releases via
|
|
58
|
+
`python-semantic-release`. OIDC-based PyPI publishing.
|
|
59
|
+
- **Consumes gpmap-v2.** Speaks the locked `SCHEMA.md` contract; reads `binary_packed`,
|
|
60
|
+
`n_mutations`, and `phenotypes` (not the removed v1 `fitnesses`).
|
|
61
|
+
- **No Cython, no `setup.py`, no `.c` blobs.**
|
|
62
|
+
|
|
63
|
+
## Install
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install gpgraph-v2
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Or with uv:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
uv add gpgraph-v2
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Plotting support is optional. For matplotlib:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install "gpgraph-v2[plot]"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Python 3.11+. Prebuilt wheels ship for Linux (x86_64, aarch64), macOS (x86_64, aarch64),
|
|
82
|
+
and Windows (x64).
|
|
83
|
+
|
|
84
|
+
## Quick start
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from gpmap import GenotypePhenotypeMap
|
|
88
|
+
from gpgraph import GenotypePhenotypeGraph
|
|
89
|
+
|
|
90
|
+
gpm = GenotypePhenotypeMap(
|
|
91
|
+
wildtype="AAA",
|
|
92
|
+
genotypes=["AAA", "AAT", "ATA", "TAA", "ATT", "TAT", "TTA", "TTT"],
|
|
93
|
+
phenotypes=[0.1, 0.2, 0.2, 0.6, 0.4, 0.6, 1.0, 1.1],
|
|
94
|
+
stdeviations=[0.05] * 8,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
G = GenotypePhenotypeGraph.from_gpm(gpm)
|
|
98
|
+
G.number_of_nodes() # 8
|
|
99
|
+
G.number_of_edges() # 24 directed (12 undirected pairs)
|
|
100
|
+
|
|
101
|
+
G.add_model(column="phenotypes", model="sswm")
|
|
102
|
+
G.edges[(0, 1)]["prob"] # SSWM fixation probability from AAA -> AAT
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Available fixation models: `"sswm"`, `"ratio"`, `"moran"`, `"mcclandish"`. Pass
|
|
106
|
+
`population_size=N` as a keyword for the last two. Pass any `f(fi, fj, **kw) -> float`
|
|
107
|
+
for a custom model.
|
|
108
|
+
|
|
109
|
+
## Forward paths and flux
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from gpgraph.paths import forward_paths_prob, paths_prob_to_edges_flux
|
|
113
|
+
|
|
114
|
+
G.add_model(column="phenotypes", model="sswm")
|
|
115
|
+
paths = forward_paths_prob(G, source=0, target=7)
|
|
116
|
+
flux = paths_prob_to_edges_flux(paths)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Plotting
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from gpgraph.pyplot import draw_gpgraph, draw_paths
|
|
123
|
+
|
|
124
|
+
fig, ax = draw_gpgraph(G) # Hamming-weight vertical layout
|
|
125
|
+
draw_paths(G, source=0, target=7) # paths flux overlay
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Benchmarks
|
|
129
|
+
|
|
130
|
+
Rust kernels vs a pure-Python pairwise reference. Windows 11, Ryzen, release build.
|
|
131
|
+
Run via `uv run pytest tests/benchmarks/ --benchmark-only`.
|
|
132
|
+
|
|
133
|
+
| problem | bit-flip (Rust) | pairwise (Rust) | pairwise (Python) |
|
|
134
|
+
|---|---|---|---|
|
|
135
|
+
| N=256, L=6, cutoff=1 | 77 us | 284 us | 29.3 ms |
|
|
136
|
+
| N=1024, L=8, cutoff=1| 167 us | 1.2 ms | (skipped, minutes)|
|
|
137
|
+
|
|
138
|
+
At L=6 the Rust bit-flip path is ~380x faster than a naive Python loop. Past
|
|
139
|
+
N = 1000 on biallelic data the bit-flip specialization pulls away from the
|
|
140
|
+
rayon-parallel pairwise version by another ~7x.
|
|
141
|
+
|
|
142
|
+
## Dispatch policy (neighbor kernels)
|
|
143
|
+
|
|
144
|
+
`gpgraph.neighbors.get_neighbors` chooses the fastest available implementation:
|
|
145
|
+
|
|
146
|
+
| problem shape | kernel |
|
|
147
|
+
|---|---|
|
|
148
|
+
| user-supplied `f(g1, g2, cutoff=...) -> bool` | pure Python `O(N^2)` |
|
|
149
|
+
| Hamming, biallelic `binary_packed`, cutoff <= 2 | Rust bit-flip (`O(N * C(L, cutoff))`) |
|
|
150
|
+
| Hamming, biallelic `binary_packed`, larger cutoff | Rust rayon-parallel packed pairwise |
|
|
151
|
+
| Hamming, non-binary alphabet | Rust rayon-parallel string pairwise |
|
|
152
|
+
| codon | Rust rayon-parallel codon pairwise |
|
|
153
|
+
|
|
154
|
+
See [SCHEMA.md](SCHEMA.md) for the full node/edge contract.
|
|
155
|
+
|
|
156
|
+
## Development
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
git clone https://github.com/lperezmo/gpgraph-v2
|
|
160
|
+
cd gpgraph-v2
|
|
161
|
+
uv sync
|
|
162
|
+
uv run maturin develop --release
|
|
163
|
+
uv run pytest
|
|
164
|
+
uv run ruff check python/gpgraph tests
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
After editing Rust:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
uv run maturin develop --release && uv run pytest
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Consuming from another local project
|
|
174
|
+
|
|
175
|
+
During co-development with gpmap-v2, point at the local source:
|
|
176
|
+
|
|
177
|
+
```toml
|
|
178
|
+
[tool.uv.sources]
|
|
179
|
+
gpgraph-v2 = { path = "/absolute/path/to/gpgraph-v2", editable = true }
|
|
180
|
+
|
|
181
|
+
[project]
|
|
182
|
+
dependencies = ["gpgraph-v2"]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Imports remain `from gpgraph import GenotypePhenotypeGraph`.
|
|
186
|
+
|
|
187
|
+
## Migration from v1 (`harmslab/gpgraph`)
|
|
188
|
+
|
|
189
|
+
gpgraph-v2 is not wire-compatible with v1. Key differences:
|
|
190
|
+
|
|
191
|
+
- Distribution name is `gpgraph-v2` on PyPI; import path is still `gpgraph`.
|
|
192
|
+
- Construction: use `GenotypePhenotypeGraph.from_gpm(gpm, ...)`. The v1 two-step
|
|
193
|
+
`G = GenotypePhenotypeGraph(); G.add_gpm(gpm)` is removed.
|
|
194
|
+
- Reads gpmap-v2 columns: node attribute is `phenotypes`, not `fitnesses`.
|
|
195
|
+
- `__repr__` no longer renders a matplotlib figure as a side effect.
|
|
196
|
+
- Matplotlib is an optional extra (`gpgraph-v2[plot]`); the core install is headless.
|
|
197
|
+
- The `_nx_wrapper` introspection shim in `pyplot/primitives.py` is gone. NetworkX is
|
|
198
|
+
version-pinned to `>=3.6`.
|
|
199
|
+
- `gpgraph.neighbor_functions` is renamed `gpgraph.neighbors` and the pairwise
|
|
200
|
+
`get_neighbors` returns a NumPy `(E, 2) int64` array instead of a list of tuples.
|
|
201
|
+
- Python 3.11+.
|
|
202
|
+
|
|
203
|
+
## Releases
|
|
204
|
+
|
|
205
|
+
Releases are driven by [`python-semantic-release`](https://python-semantic-release.readthedocs.io/)
|
|
206
|
+
on merge to `main`. Commits follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
207
|
+
|
|
208
|
+
- `fix: ...` -> patch
|
|
209
|
+
- `feat: ...` -> minor
|
|
210
|
+
- `feat!: ...` or a `BREAKING CHANGE:` footer -> major
|
|
211
|
+
|
|
212
|
+
`CHANGELOG.md`, version bumps, Git tags, GitHub Releases, wheel builds, and PyPI uploads
|
|
213
|
+
all happen automatically.
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
MIT. See [LICENSE](LICENSE).
|
|
218
|
+
|