bioelectrics 0.3.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 (40) hide show
  1. bioelectrics-0.3.0/LICENSE +24 -0
  2. bioelectrics-0.3.0/PKG-INFO +245 -0
  3. bioelectrics-0.3.0/README.md +206 -0
  4. bioelectrics-0.3.0/THIRD_PARTY_NOTICES.md +42 -0
  5. bioelectrics-0.3.0/pyproject.toml +53 -0
  6. bioelectrics-0.3.0/setup.cfg +4 -0
  7. bioelectrics-0.3.0/src/bioelectrics/__init__.py +34 -0
  8. bioelectrics-0.3.0/src/bioelectrics/attractors.py +463 -0
  9. bioelectrics-0.3.0/src/bioelectrics/channels.py +154 -0
  10. bioelectrics-0.3.0/src/bioelectrics/constants.py +51 -0
  11. bioelectrics-0.3.0/src/bioelectrics/control.py +183 -0
  12. bioelectrics-0.3.0/src/bioelectrics/gap_junctions.py +92 -0
  13. bioelectrics-0.3.0/src/bioelectrics/integrators.py +247 -0
  14. bioelectrics-0.3.0/src/bioelectrics/interventions.py +461 -0
  15. bioelectrics-0.3.0/src/bioelectrics/io/__init__.py +5 -0
  16. bioelectrics-0.3.0/src/bioelectrics/io/betse.py +334 -0
  17. bioelectrics-0.3.0/src/bioelectrics/ionic/__init__.py +14 -0
  18. bioelectrics-0.3.0/src/bioelectrics/ionic/channel_library.py +152 -0
  19. bioelectrics-0.3.0/src/bioelectrics/ionic/model.py +385 -0
  20. bioelectrics-0.3.0/src/bioelectrics/ionic/profiles.py +95 -0
  21. bioelectrics-0.3.0/src/bioelectrics/ionic/transport.py +95 -0
  22. bioelectrics-0.3.0/src/bioelectrics/pharmacology.py +370 -0
  23. bioelectrics-0.3.0/src/bioelectrics/tissue.py +119 -0
  24. bioelectrics-0.3.0/src/bioelectrics/viz.py +402 -0
  25. bioelectrics-0.3.0/src/bioelectrics/zoo/__init__.py +11 -0
  26. bioelectrics-0.3.0/src/bioelectrics/zoo/cam2016.py +77 -0
  27. bioelectrics-0.3.0/src/bioelectrics.egg-info/PKG-INFO +245 -0
  28. bioelectrics-0.3.0/src/bioelectrics.egg-info/SOURCES.txt +38 -0
  29. bioelectrics-0.3.0/src/bioelectrics.egg-info/dependency_links.txt +1 -0
  30. bioelectrics-0.3.0/src/bioelectrics.egg-info/requires.txt +14 -0
  31. bioelectrics-0.3.0/src/bioelectrics.egg-info/top_level.txt +1 -0
  32. bioelectrics-0.3.0/tests/test_attractors.py +158 -0
  33. bioelectrics-0.3.0/tests/test_betse_io.py +179 -0
  34. bioelectrics-0.3.0/tests/test_interventions.py +115 -0
  35. bioelectrics-0.3.0/tests/test_inverse_control.py +83 -0
  36. bioelectrics-0.3.0/tests/test_ionic_physics.py +199 -0
  37. bioelectrics-0.3.0/tests/test_pharmacology.py +181 -0
  38. bioelectrics-0.3.0/tests/test_single_cell.py +106 -0
  39. bioelectrics-0.3.0/tests/test_tissue_domains.py +98 -0
  40. bioelectrics-0.3.0/tests/test_viz.py +72 -0
@@ -0,0 +1,24 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 The bioelectrics contributors
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.
22
+
23
+ Portions of src/bioelectrics/ionic/ are derived from BETSE (BSD-2-Clause).
24
+ See THIRD_PARTY_NOTICES.md.
@@ -0,0 +1,245 @@
1
+ Metadata-Version: 2.4
2
+ Name: bioelectrics
3
+ Version: 0.3.0
4
+ Summary: Differentiable somatic bioelectricity: ion-level tissue physics, published model zoo, and inverse design of lab interventions in PyTorch
5
+ Author: The bioelectrics contributors
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://tlcdv.github.io/bioelectrics/
8
+ Project-URL: Documentation, https://tlcdv.github.io/bioelectrics/
9
+ Project-URL: Repository, https://github.com/tlcdv/bioelectrics
10
+ Project-URL: Issues, https://github.com/tlcdv/bioelectrics/issues
11
+ Project-URL: Validation, https://tlcdv.github.io/bioelectrics/validation/
12
+ Keywords: bioelectricity,membrane potential,gap junctions,ion channels,morphogenesis,developmental biology,differentiable simulation,pytorch
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
20
+ Classifier: Topic :: Scientific/Engineering :: Physics
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ License-File: THIRD_PARTY_NOTICES.md
26
+ Requires-Dist: torch>=2.0
27
+ Requires-Dist: numpy>=1.24
28
+ Requires-Dist: scipy>=1.10
29
+ Requires-Dist: matplotlib>=3.7
30
+ Requires-Dist: networkx>=3.0
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7; extra == "dev"
33
+ Requires-Dist: pytest-cov>=4; extra == "dev"
34
+ Requires-Dist: pyyaml>=6; extra == "dev"
35
+ Provides-Extra: notebooks
36
+ Requires-Dist: nbmake>=1.5; extra == "notebooks"
37
+ Requires-Dist: matplotlib; extra == "notebooks"
38
+ Dynamic: license-file
39
+
40
+ # bioelectrics
41
+
42
+ **A differentiable engine for somatic bioelectricity, in PyTorch.**
43
+
44
+ Documentation: <https://tlcdv.github.io/bioelectrics/> — with
45
+ [four runnable tutorials](https://tlcdv.github.io/bioelectrics/tutorials/) that open in
46
+ Colab with no installation — including a
47
+ [validation page](https://tlcdv.github.io/bioelectrics/validation/) whose every number is
48
+ recomputed from this code, and a
49
+ [limitations page](https://tlcdv.github.io/bioelectrics/limitations/).
50
+
51
+ `bioelectrics` simulates the membrane potential (V_mem) of non-neural tissues at the
52
+ level of ions, channels, pumps and gap junctions, and computes exact gradients of any
53
+ outcome with respect to any parameter. It uses these gradients for the **bioelectric
54
+ inverse problem**: which experimentally realizable intervention (a channel mRNA, a
55
+ drug dose, a gap junction blocker, a light pattern), applied for a short time, moves a
56
+ tissue into a target V_mem pattern that then persists on its own?
57
+
58
+ The library builds on the work of Michael Levin's lab, Alexis Pietak (BETSE), and
59
+ Javier Cervera and Salvador Mafe. See [Related tools](#related-tools) for what it
60
+ takes from them and what it adds.
61
+
62
+ <picture>
63
+ <source media="(prefers-color-scheme: dark)" srcset="assets/ionic_tumor_normalization_dark.png">
64
+ <img alt="Inverse design of interventions on an ion-level tissue" src="assets/ionic_tumor_normalization.png">
65
+ </picture>
66
+
67
+ *(A) An ion-level cell (GHK fluxes, pumps, a K⁺ inward rectifier and a depolarizing cation
68
+ channel) has two attractors. (B) A depolarized "tumor" domain is isolated by closed
69
+ voltage-gated gap junctions. (C) An optimized bath drug, given for 0.1 s and then washed
70
+ out, flips the tumor cells into the healthy attractor. (D) An optimized light pattern for
71
+ an anion channelrhodopsin concentrates the light on the tumor. (E) The tissue after the
72
+ light is off. (F) Optimization by backpropagation through the simulation.*
73
+
74
+ Results of this demo (16×16 cells, 31 tumor cells):
75
+
76
+ | Protocol | Optimized intervention | RMS error at 0.5 s |
77
+ |---|---|---|
78
+ | Drug | block 67 % of the depolarizing channel in the bath for 0.1 s, then wash out | 26.1 → 0.41 mV (98.4 % lower) |
79
+ | Light | light on 32 cells (mean opsin open probability 0.22 on the tumor, 0.003 elsewhere) for 0.1 s | 26.1 → 0.41 mV (98.4 % lower) |
80
+
81
+ The full protocol tables are in [`assets/ionic_protocols.md`](assets/ionic_protocols.md).
82
+
83
+ ## What you can do with it
84
+
85
+ | Task | API |
86
+ |---|---|
87
+ | Simulate V_mem, Na⁺/K⁺/Cl⁻/Ca²⁺ concentrations and channel gates in a tissue (grid or any graph) | `bioelectrics.ionic.IonicTissue` |
88
+ | Use BETSE-compatible physics: GHK electrodiffusion, Na/K- and Ca-ATPase, voltage-gated electrodiffusive gap junctions | `bioelectrics.ionic` |
89
+ | Express gated channels from a library (Kv1.5, Kir2.1, HCN2, Cav1.2, leaks, CAM-type channels) | `bioelectrics.ionic.LIBRARY` |
90
+ | Get gradients of any V_mem outcome with respect to channel expression, pump rates, gap junction density | `torch.autograd` through the solvers |
91
+ | Design interventions and print them as a lab protocol | `bioelectrics.interventions.InterventionOptimizer` |
92
+ | Find steady states (pattern memories), their stability and slowest time scale, without long simulations | `bioelectrics.attractors.find_steady_state` |
93
+ | Differentiate a steady state with respect to any parameter (implicit function theorem, one sparse solve) | `bioelectrics.attractors.steady_state_implicit` |
94
+ | Map the attractor landscape: all patterns from many start states, basins, dose ramps with hysteresis | `enumerate_attractors`, `basin_map`, `dose_response` |
95
+ | Design chronic interventions (constant dose, stable misexpression) whose steady state is the target | `bioelectrics.interventions.ChronicInterventionOptimizer` |
96
+ | Screen drugs with published potency values, each carrying its assay, species and citation | `bioelectrics.pharmacology` |
97
+ | Run published models and their reproduction tests | `bioelectrics.zoo` |
98
+ | Use the fast voltage-level (CAM) model for large tissues | `bioelectrics.Tissue`, `PatternOptimizer` |
99
+
100
+ ## Installation
101
+
102
+ ```bash
103
+ git clone https://github.com/tlcdv/bioelectrics.git
104
+ cd bioelectrics
105
+ python -m venv .venv
106
+ .venv/bin/pip install -e ".[dev]" # Windows: .venv\Scripts\pip
107
+ .venv/bin/python -m pytest # about 3 minutes on a laptop CPU
108
+ ```
109
+
110
+ Requires Python ≥ 3.10 and PyTorch ≥ 2.0. A GPU is not required.
111
+
112
+ ## Quickstart: design a drug protocol
113
+
114
+ ```python
115
+ import torch
116
+ from bioelectrics.ionic import IonicTissue, ChannelExpression, K_IR_CAM, CAT_DEP_CAM
117
+ from bioelectrics.interventions import ChannelBlocker, InterventionOptimizer
118
+
119
+ # Hardware: each cell expresses a K+ inward rectifier and a depolarizing cation channel.
120
+ tissue = IonicTissue(channels=[ChannelExpression(K_IR_CAM, 1e-16),
121
+ ChannelExpression(CAT_DEP_CAM, 1e-16)])
122
+
123
+ # Software: an 8x8 tissue at -78 mV with a 2x2 depolarized domain at -3 mV.
124
+ v0 = torch.full((1, 8, 8), -0.078, dtype=torch.float64)
125
+ v0[:, 3:5, 3:5] = -0.003
126
+ state = tissue.simulate(tissue.with_vmem(tissue.initial_state((8, 8)), v0), 0.5)
127
+
128
+ # Which dose of a bath-applied blocker of the depolarizing channel, given for 0.1 s and
129
+ # then washed out, puts every cell into the healthy attractor by t = 0.5 s?
130
+ opt = InterventionOptimizer(tissue, state, torch.full_like(v0, -0.078),
131
+ [ChannelBlocker("Cat_dep(CAM)", cost=1.0)], t_stim=0.1, t_relax=0.5)
132
+ print(opt.optimize(n_iters=30, tol_mV=1.0).protocol.to_markdown())
133
+ ```
134
+
135
+ ### Examples
136
+
137
+ | Script | What it shows | Output |
138
+ |---|---|---|
139
+ | [`examples/ionic_tumor_normalization.py`](examples/ionic_tumor_normalization.py) | Ion-level tissue: optimized drug dose and optimized optogenetic light pattern | `assets/ionic_tumor_normalization.png`, `assets/ionic_protocols.md` |
140
+ | [`examples/drug_repurposing.py`](examples/drug_repurposing.py) | In-silico screen of the drug library against a depolarized domain, with the direction and size of each effect | `assets/drug_screen.png` (+ `_dark`), `assets/drug_screen.md` |
141
+ | [`examples/attractor_landscape.py`](examples/attractor_landscape.py) | Hysteresis of a dose ramp, basins of two coupled cells, chronic drug design on a 16×16 tissue by implicit differentiation | `assets/attractor_landscape.png` (+ `_dark`) |
142
+ | [`examples/tumor_reprogramming_demo.py`](examples/tumor_reprogramming_demo.py) | Voltage-level (CAM-type) tissue: optimized current stimulus I_ext(t, x, y) | `assets/inverse_reprogramming_result.png` (+ `_dark`) |
143
+
144
+ ## Concepts
145
+
146
+ The API uses the terms of [`DOMAIN_CONCEPTS.md`](DOMAIN_CONCEPTS.md), after Levin &
147
+ Martyniuk (2018) and Levin (2019):
148
+
149
+ - **Hardware and software.** Channel and gap junction expression (`ChannelExpression`,
150
+ `IonicTissue` parameters) is the hardware. The V_mem pattern (`IonicState`,
151
+ `BioelectricState`) is the software, which stores pattern memory.
152
+ - **Target morphology as an attractor.** The optimizers are error-minimizing controllers
153
+ that move a tissue from one basin of attraction into a target attractor.
154
+ - **Triggers, not clamps.** Every inverse design has an intervention phase `[0, T_stim]`
155
+ and an intervention-free phase `[T_stim, T_relax]`. The error is measured at `T_relax`,
156
+ so a solution must be a permanent attractor switch.
157
+ - **Computational boundary of the self.** A large transjunctional voltage closes gap
158
+ junctions and isolates a depolarized domain; re-polarization re-opens them.
159
+
160
+ ## Physics and validation
161
+
162
+ Equations, parameters and their sources are in [`MATH_REFERENCE.md`](MATH_REFERENCE.md).
163
+ All internal math is in SI units. The tests check the physics against analytic results
164
+ and published results:
165
+
166
+ | Test file | What it checks |
167
+ |---|---|
168
+ | `test_ionic_physics.py` | Nernst and GHK voltage limits, pump stoichiometry and sign, mass and charge conservation in gap junctions, BETSE gap junction gating formula, grid = graph, gradients |
169
+ | `zoo/test_cam2016.py` | Cervera et al. (2016): fixed points (−58.6, −15.5, −7.5 mV), Fig. 4 (normalization depends on coupling), Fig. 5 (channel over-expression blocks normalization) |
170
+ | `test_pharmacology.py` | Every entry has a source, assay and species; each stored concentration matches the figure its source prints; every target exists; the Hill equation gives exactly 50 % at the published value; a pump or junction dose writes its own modifier field |
171
+ | `test_attractors.py` | Exact sparse Jacobian (= dense autograd), two stable states and a saddle, fixed points of the simulation, implicit gradient = finite difference, hysteresis, mixed two-cell patterns, chronic drug design |
172
+ | `test_interventions.py` | The tumor is a stable attractor; an optimized drug dose normalizes it permanently; an optimized light pattern targets the tumor |
173
+ | `test_single_cell.py`, `test_tissue_domains.py`, `test_inverse_control.py` | Voltage-level model: bistability, domain walls, current-stimulus inverse control |
174
+
175
+ ## Related tools
176
+
177
+ | Tool | What it is | Relation to this library |
178
+ |---|---|---|
179
+ | [BETSE](https://gitlab.com/betse/betse) (Pietak & Levin) | Full bioelectric tissue simulator: electrodiffusion, extracellular space, gene and metabolic networks, GUI (BETSEE) | The ion-level physics here is ported from BETSE (BSD-2-Clause, see [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)). BETSE is far more complete; this library adds gradients and inverse design, and has no extracellular space model yet. |
180
+ | [BioElectricNetwork](https://github.com/santamanicka/BioElectricNetwork) (Manicka & Levin 2019) | Minimal bioelectric networks trained with backpropagation and genetic algorithms (logic gates, pattern detection) | Pioneered gradient training of bioelectric networks. This library is a general, tested package with BETSE-level physics and lab-realizable interventions. BEN is not yet in the zoo (see below). |
181
+ | [ElectricMorphogenesis](https://github.com/santamanicka/ElectricMorphogenesis) (Manicka & Levin 2025) | Bioelectric field models of tissue-level voltage patterning, trained with backpropagation | Complementary: it models endogenous electric fields, which this library does not yet include. |
182
+ | Cervera, Alcaraz & Mafe models | Bistable cell model and multicellular patterns (Sci. Rep. 2016 and later) | Implemented in `bioelectrics.zoo.cam2016` with reproduction tests; CAM-type gating is also available at ion level. |
183
+
184
+ ## Limitations and roadmap
185
+
186
+ Present limitations, stated so that results are not over-read:
187
+
188
+ - The extracellular space is a fixed bath (as BETSE without `is_ecm`). There are no
189
+ extracellular electric fields or extracellular diffusion.
190
+ - The CAM-type channels used for bistability are phenomenological, not models of one
191
+ specific protein. The BETSE Kir2.1 model alone does not give bistability with the
192
+ default profile.
193
+ - The model has no cell volume or osmotic regulation, and the bath is fixed. A depolarized
194
+ steady state is reached within seconds, but over hours (slowest time scale about 3 h) its
195
+ cells gain Na⁺ (up to about 200 mM in the default cell). Steady states of depolarized
196
+ cells are therefore not physiological at long times; see `MATH_REFERENCE.md` §7.
197
+ - `bioelectrics.pharmacology` contains 10 potency values read from 4 primary sources. Each
198
+ carries its assay, species, regulatory status and citation. **None of them was estimated.**
199
+ Compounds considered and left out are listed in `pharmacology.EXCLUDED` with the reason;
200
+ dihydropyridines are excluded because their block is state-dependent, so one IC50 is wrong
201
+ in a tissue whose cells sit at different voltages.
202
+ - The screen in `examples/drug_repurposing.py` finds that **no drug in that set normalizes a
203
+ depolarized domain.** Every compound with a verified value acts on a polarizing element
204
+ (the inward rectifier, the Na/K-ATPase), so blocking it depolarizes. This is a statement
205
+ about which potency data are published, not about bioelectric medicine. The depolarizing
206
+ channel in the model is also phenomenological rather than a named protein, so no real drug
207
+ targets it by construction.
208
+ - Potency values are in-silico inputs, not predictions of a clinical effect. Off-target
209
+ actions are recorded but not modelled.
210
+ - BPTT cost grows with simulated time; long rollouts on large ion-level grids are slow on
211
+ a CPU (an 8×8 tissue: about 4 s per optimization iteration for a 0.5 s rollout).
212
+
213
+ Planned:
214
+
215
+ - BEN (Manicka & Levin 2019) in the zoo. The equations in its Fig. 8 have inconsistent
216
+ units and signs, so an exact reproduction needs confirmation from the authors.
217
+ - Higher-order stiff solvers, GPU benchmarks, Voronoi cell meshes from segmented images.
218
+ - Gene regulatory network coupling (V_mem → expression → channels).
219
+ - Fitting model parameters to voltage-dye (DiBAC, CC2-DMPE) images.
220
+
221
+ ## Contributing and citation
222
+
223
+ See [`CONTRIBUTING.md`](CONTRIBUTING.md). If you use the library, cite it with
224
+ [`CITATION.cff`](CITATION.cff), and cite the papers of the models you use.
225
+
226
+ ## References
227
+
228
+ - Levin, M. & Martyniuk, C. J. (2018). The bioelectric code: An ancient computational
229
+ medium for dynamic control of growth and form. *BioSystems* 164, 76–93.
230
+ - Levin, M. (2019). The computational boundary of a "self": Developmental bioelectricity
231
+ drives multicellularity and scale-free cognition. *Frontiers in Psychology* 10, 2688.
232
+ - Pietak, A. & Levin, M. (2016). Exploring instructive physiological signaling with the
233
+ bioelectric tissue simulation engine. *Frontiers in Bioengineering and Biotechnology* 4, 55.
234
+ - Cervera, J., Alcaraz, A. & Mafe, S. (2016). Bioelectrical signals and ion channels in the
235
+ modeling of multicellular patterns and cancer biophysics. *Scientific Reports* 6, 20403.
236
+ - Manicka, S. & Levin, M. (2019). Modeling somatic computation with non-neural bioelectric
237
+ networks. *Scientific Reports* 9, 18612.
238
+ - Verwer, J. G., Spee, E. J., Blom, J. G. & Hundsdorfer, W. (1999). A second-order
239
+ Rosenbrock method applied to photochemical dispersion problems. *SIAM J. Sci. Comput.* 20,
240
+ 1456–1480.
241
+
242
+ ## License
243
+
244
+ MIT. Parts of `src/bioelectrics/ionic/` are derived from BETSE (BSD-2-Clause); see
245
+ [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md).
@@ -0,0 +1,206 @@
1
+ # bioelectrics
2
+
3
+ **A differentiable engine for somatic bioelectricity, in PyTorch.**
4
+
5
+ Documentation: <https://tlcdv.github.io/bioelectrics/> — with
6
+ [four runnable tutorials](https://tlcdv.github.io/bioelectrics/tutorials/) that open in
7
+ Colab with no installation — including a
8
+ [validation page](https://tlcdv.github.io/bioelectrics/validation/) whose every number is
9
+ recomputed from this code, and a
10
+ [limitations page](https://tlcdv.github.io/bioelectrics/limitations/).
11
+
12
+ `bioelectrics` simulates the membrane potential (V_mem) of non-neural tissues at the
13
+ level of ions, channels, pumps and gap junctions, and computes exact gradients of any
14
+ outcome with respect to any parameter. It uses these gradients for the **bioelectric
15
+ inverse problem**: which experimentally realizable intervention (a channel mRNA, a
16
+ drug dose, a gap junction blocker, a light pattern), applied for a short time, moves a
17
+ tissue into a target V_mem pattern that then persists on its own?
18
+
19
+ The library builds on the work of Michael Levin's lab, Alexis Pietak (BETSE), and
20
+ Javier Cervera and Salvador Mafe. See [Related tools](#related-tools) for what it
21
+ takes from them and what it adds.
22
+
23
+ <picture>
24
+ <source media="(prefers-color-scheme: dark)" srcset="assets/ionic_tumor_normalization_dark.png">
25
+ <img alt="Inverse design of interventions on an ion-level tissue" src="assets/ionic_tumor_normalization.png">
26
+ </picture>
27
+
28
+ *(A) An ion-level cell (GHK fluxes, pumps, a K⁺ inward rectifier and a depolarizing cation
29
+ channel) has two attractors. (B) A depolarized "tumor" domain is isolated by closed
30
+ voltage-gated gap junctions. (C) An optimized bath drug, given for 0.1 s and then washed
31
+ out, flips the tumor cells into the healthy attractor. (D) An optimized light pattern for
32
+ an anion channelrhodopsin concentrates the light on the tumor. (E) The tissue after the
33
+ light is off. (F) Optimization by backpropagation through the simulation.*
34
+
35
+ Results of this demo (16×16 cells, 31 tumor cells):
36
+
37
+ | Protocol | Optimized intervention | RMS error at 0.5 s |
38
+ |---|---|---|
39
+ | Drug | block 67 % of the depolarizing channel in the bath for 0.1 s, then wash out | 26.1 → 0.41 mV (98.4 % lower) |
40
+ | Light | light on 32 cells (mean opsin open probability 0.22 on the tumor, 0.003 elsewhere) for 0.1 s | 26.1 → 0.41 mV (98.4 % lower) |
41
+
42
+ The full protocol tables are in [`assets/ionic_protocols.md`](assets/ionic_protocols.md).
43
+
44
+ ## What you can do with it
45
+
46
+ | Task | API |
47
+ |---|---|
48
+ | Simulate V_mem, Na⁺/K⁺/Cl⁻/Ca²⁺ concentrations and channel gates in a tissue (grid or any graph) | `bioelectrics.ionic.IonicTissue` |
49
+ | Use BETSE-compatible physics: GHK electrodiffusion, Na/K- and Ca-ATPase, voltage-gated electrodiffusive gap junctions | `bioelectrics.ionic` |
50
+ | Express gated channels from a library (Kv1.5, Kir2.1, HCN2, Cav1.2, leaks, CAM-type channels) | `bioelectrics.ionic.LIBRARY` |
51
+ | Get gradients of any V_mem outcome with respect to channel expression, pump rates, gap junction density | `torch.autograd` through the solvers |
52
+ | Design interventions and print them as a lab protocol | `bioelectrics.interventions.InterventionOptimizer` |
53
+ | Find steady states (pattern memories), their stability and slowest time scale, without long simulations | `bioelectrics.attractors.find_steady_state` |
54
+ | Differentiate a steady state with respect to any parameter (implicit function theorem, one sparse solve) | `bioelectrics.attractors.steady_state_implicit` |
55
+ | Map the attractor landscape: all patterns from many start states, basins, dose ramps with hysteresis | `enumerate_attractors`, `basin_map`, `dose_response` |
56
+ | Design chronic interventions (constant dose, stable misexpression) whose steady state is the target | `bioelectrics.interventions.ChronicInterventionOptimizer` |
57
+ | Screen drugs with published potency values, each carrying its assay, species and citation | `bioelectrics.pharmacology` |
58
+ | Run published models and their reproduction tests | `bioelectrics.zoo` |
59
+ | Use the fast voltage-level (CAM) model for large tissues | `bioelectrics.Tissue`, `PatternOptimizer` |
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ git clone https://github.com/tlcdv/bioelectrics.git
65
+ cd bioelectrics
66
+ python -m venv .venv
67
+ .venv/bin/pip install -e ".[dev]" # Windows: .venv\Scripts\pip
68
+ .venv/bin/python -m pytest # about 3 minutes on a laptop CPU
69
+ ```
70
+
71
+ Requires Python ≥ 3.10 and PyTorch ≥ 2.0. A GPU is not required.
72
+
73
+ ## Quickstart: design a drug protocol
74
+
75
+ ```python
76
+ import torch
77
+ from bioelectrics.ionic import IonicTissue, ChannelExpression, K_IR_CAM, CAT_DEP_CAM
78
+ from bioelectrics.interventions import ChannelBlocker, InterventionOptimizer
79
+
80
+ # Hardware: each cell expresses a K+ inward rectifier and a depolarizing cation channel.
81
+ tissue = IonicTissue(channels=[ChannelExpression(K_IR_CAM, 1e-16),
82
+ ChannelExpression(CAT_DEP_CAM, 1e-16)])
83
+
84
+ # Software: an 8x8 tissue at -78 mV with a 2x2 depolarized domain at -3 mV.
85
+ v0 = torch.full((1, 8, 8), -0.078, dtype=torch.float64)
86
+ v0[:, 3:5, 3:5] = -0.003
87
+ state = tissue.simulate(tissue.with_vmem(tissue.initial_state((8, 8)), v0), 0.5)
88
+
89
+ # Which dose of a bath-applied blocker of the depolarizing channel, given for 0.1 s and
90
+ # then washed out, puts every cell into the healthy attractor by t = 0.5 s?
91
+ opt = InterventionOptimizer(tissue, state, torch.full_like(v0, -0.078),
92
+ [ChannelBlocker("Cat_dep(CAM)", cost=1.0)], t_stim=0.1, t_relax=0.5)
93
+ print(opt.optimize(n_iters=30, tol_mV=1.0).protocol.to_markdown())
94
+ ```
95
+
96
+ ### Examples
97
+
98
+ | Script | What it shows | Output |
99
+ |---|---|---|
100
+ | [`examples/ionic_tumor_normalization.py`](examples/ionic_tumor_normalization.py) | Ion-level tissue: optimized drug dose and optimized optogenetic light pattern | `assets/ionic_tumor_normalization.png`, `assets/ionic_protocols.md` |
101
+ | [`examples/drug_repurposing.py`](examples/drug_repurposing.py) | In-silico screen of the drug library against a depolarized domain, with the direction and size of each effect | `assets/drug_screen.png` (+ `_dark`), `assets/drug_screen.md` |
102
+ | [`examples/attractor_landscape.py`](examples/attractor_landscape.py) | Hysteresis of a dose ramp, basins of two coupled cells, chronic drug design on a 16×16 tissue by implicit differentiation | `assets/attractor_landscape.png` (+ `_dark`) |
103
+ | [`examples/tumor_reprogramming_demo.py`](examples/tumor_reprogramming_demo.py) | Voltage-level (CAM-type) tissue: optimized current stimulus I_ext(t, x, y) | `assets/inverse_reprogramming_result.png` (+ `_dark`) |
104
+
105
+ ## Concepts
106
+
107
+ The API uses the terms of [`DOMAIN_CONCEPTS.md`](DOMAIN_CONCEPTS.md), after Levin &
108
+ Martyniuk (2018) and Levin (2019):
109
+
110
+ - **Hardware and software.** Channel and gap junction expression (`ChannelExpression`,
111
+ `IonicTissue` parameters) is the hardware. The V_mem pattern (`IonicState`,
112
+ `BioelectricState`) is the software, which stores pattern memory.
113
+ - **Target morphology as an attractor.** The optimizers are error-minimizing controllers
114
+ that move a tissue from one basin of attraction into a target attractor.
115
+ - **Triggers, not clamps.** Every inverse design has an intervention phase `[0, T_stim]`
116
+ and an intervention-free phase `[T_stim, T_relax]`. The error is measured at `T_relax`,
117
+ so a solution must be a permanent attractor switch.
118
+ - **Computational boundary of the self.** A large transjunctional voltage closes gap
119
+ junctions and isolates a depolarized domain; re-polarization re-opens them.
120
+
121
+ ## Physics and validation
122
+
123
+ Equations, parameters and their sources are in [`MATH_REFERENCE.md`](MATH_REFERENCE.md).
124
+ All internal math is in SI units. The tests check the physics against analytic results
125
+ and published results:
126
+
127
+ | Test file | What it checks |
128
+ |---|---|
129
+ | `test_ionic_physics.py` | Nernst and GHK voltage limits, pump stoichiometry and sign, mass and charge conservation in gap junctions, BETSE gap junction gating formula, grid = graph, gradients |
130
+ | `zoo/test_cam2016.py` | Cervera et al. (2016): fixed points (−58.6, −15.5, −7.5 mV), Fig. 4 (normalization depends on coupling), Fig. 5 (channel over-expression blocks normalization) |
131
+ | `test_pharmacology.py` | Every entry has a source, assay and species; each stored concentration matches the figure its source prints; every target exists; the Hill equation gives exactly 50 % at the published value; a pump or junction dose writes its own modifier field |
132
+ | `test_attractors.py` | Exact sparse Jacobian (= dense autograd), two stable states and a saddle, fixed points of the simulation, implicit gradient = finite difference, hysteresis, mixed two-cell patterns, chronic drug design |
133
+ | `test_interventions.py` | The tumor is a stable attractor; an optimized drug dose normalizes it permanently; an optimized light pattern targets the tumor |
134
+ | `test_single_cell.py`, `test_tissue_domains.py`, `test_inverse_control.py` | Voltage-level model: bistability, domain walls, current-stimulus inverse control |
135
+
136
+ ## Related tools
137
+
138
+ | Tool | What it is | Relation to this library |
139
+ |---|---|---|
140
+ | [BETSE](https://gitlab.com/betse/betse) (Pietak & Levin) | Full bioelectric tissue simulator: electrodiffusion, extracellular space, gene and metabolic networks, GUI (BETSEE) | The ion-level physics here is ported from BETSE (BSD-2-Clause, see [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)). BETSE is far more complete; this library adds gradients and inverse design, and has no extracellular space model yet. |
141
+ | [BioElectricNetwork](https://github.com/santamanicka/BioElectricNetwork) (Manicka & Levin 2019) | Minimal bioelectric networks trained with backpropagation and genetic algorithms (logic gates, pattern detection) | Pioneered gradient training of bioelectric networks. This library is a general, tested package with BETSE-level physics and lab-realizable interventions. BEN is not yet in the zoo (see below). |
142
+ | [ElectricMorphogenesis](https://github.com/santamanicka/ElectricMorphogenesis) (Manicka & Levin 2025) | Bioelectric field models of tissue-level voltage patterning, trained with backpropagation | Complementary: it models endogenous electric fields, which this library does not yet include. |
143
+ | Cervera, Alcaraz & Mafe models | Bistable cell model and multicellular patterns (Sci. Rep. 2016 and later) | Implemented in `bioelectrics.zoo.cam2016` with reproduction tests; CAM-type gating is also available at ion level. |
144
+
145
+ ## Limitations and roadmap
146
+
147
+ Present limitations, stated so that results are not over-read:
148
+
149
+ - The extracellular space is a fixed bath (as BETSE without `is_ecm`). There are no
150
+ extracellular electric fields or extracellular diffusion.
151
+ - The CAM-type channels used for bistability are phenomenological, not models of one
152
+ specific protein. The BETSE Kir2.1 model alone does not give bistability with the
153
+ default profile.
154
+ - The model has no cell volume or osmotic regulation, and the bath is fixed. A depolarized
155
+ steady state is reached within seconds, but over hours (slowest time scale about 3 h) its
156
+ cells gain Na⁺ (up to about 200 mM in the default cell). Steady states of depolarized
157
+ cells are therefore not physiological at long times; see `MATH_REFERENCE.md` §7.
158
+ - `bioelectrics.pharmacology` contains 10 potency values read from 4 primary sources. Each
159
+ carries its assay, species, regulatory status and citation. **None of them was estimated.**
160
+ Compounds considered and left out are listed in `pharmacology.EXCLUDED` with the reason;
161
+ dihydropyridines are excluded because their block is state-dependent, so one IC50 is wrong
162
+ in a tissue whose cells sit at different voltages.
163
+ - The screen in `examples/drug_repurposing.py` finds that **no drug in that set normalizes a
164
+ depolarized domain.** Every compound with a verified value acts on a polarizing element
165
+ (the inward rectifier, the Na/K-ATPase), so blocking it depolarizes. This is a statement
166
+ about which potency data are published, not about bioelectric medicine. The depolarizing
167
+ channel in the model is also phenomenological rather than a named protein, so no real drug
168
+ targets it by construction.
169
+ - Potency values are in-silico inputs, not predictions of a clinical effect. Off-target
170
+ actions are recorded but not modelled.
171
+ - BPTT cost grows with simulated time; long rollouts on large ion-level grids are slow on
172
+ a CPU (an 8×8 tissue: about 4 s per optimization iteration for a 0.5 s rollout).
173
+
174
+ Planned:
175
+
176
+ - BEN (Manicka & Levin 2019) in the zoo. The equations in its Fig. 8 have inconsistent
177
+ units and signs, so an exact reproduction needs confirmation from the authors.
178
+ - Higher-order stiff solvers, GPU benchmarks, Voronoi cell meshes from segmented images.
179
+ - Gene regulatory network coupling (V_mem → expression → channels).
180
+ - Fitting model parameters to voltage-dye (DiBAC, CC2-DMPE) images.
181
+
182
+ ## Contributing and citation
183
+
184
+ See [`CONTRIBUTING.md`](CONTRIBUTING.md). If you use the library, cite it with
185
+ [`CITATION.cff`](CITATION.cff), and cite the papers of the models you use.
186
+
187
+ ## References
188
+
189
+ - Levin, M. & Martyniuk, C. J. (2018). The bioelectric code: An ancient computational
190
+ medium for dynamic control of growth and form. *BioSystems* 164, 76–93.
191
+ - Levin, M. (2019). The computational boundary of a "self": Developmental bioelectricity
192
+ drives multicellularity and scale-free cognition. *Frontiers in Psychology* 10, 2688.
193
+ - Pietak, A. & Levin, M. (2016). Exploring instructive physiological signaling with the
194
+ bioelectric tissue simulation engine. *Frontiers in Bioengineering and Biotechnology* 4, 55.
195
+ - Cervera, J., Alcaraz, A. & Mafe, S. (2016). Bioelectrical signals and ion channels in the
196
+ modeling of multicellular patterns and cancer biophysics. *Scientific Reports* 6, 20403.
197
+ - Manicka, S. & Levin, M. (2019). Modeling somatic computation with non-neural bioelectric
198
+ networks. *Scientific Reports* 9, 18612.
199
+ - Verwer, J. G., Spee, E. J., Blom, J. G. & Hundsdorfer, W. (1999). A second-order
200
+ Rosenbrock method applied to photochemical dispersion problems. *SIAM J. Sci. Comput.* 20,
201
+ 1456–1480.
202
+
203
+ ## License
204
+
205
+ MIT. Parts of `src/bioelectrics/ionic/` are derived from BETSE (BSD-2-Clause); see
206
+ [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md).
@@ -0,0 +1,42 @@
1
+ # Third-party notices
2
+
3
+ ## BETSE
4
+
5
+ The following parts of `bioelectrics` are derived from BETSE, the BioElectric
6
+ Tissue Simulation Engine (https://gitlab.com/betse/betse):
7
+
8
+ - `src/bioelectrics/ionic/transport.py`: GHK electroflux, Na/K-ATPase and Ca-ATPase
9
+ rate laws, voltage-sensitive gap junction gating (`betse/science/sim_toolbox.py`,
10
+ `betse/science/channels/gap_junction.py`).
11
+ - `src/bioelectrics/ionic/channel_library.py`: Hodgkin-Huxley gating functions of
12
+ Kv1.5, Kir2.1, HCN2 and Cav1.2 (`betse/science/channels/vg_*.py`).
13
+ - `src/bioelectrics/ionic/profiles.py` and `model.py`: ion profiles, diffusion
14
+ constants and default parameters (`betse/science/parameters.py`,
15
+ `betse/data/yaml/sim_config.yaml`).
16
+
17
+ The equations were re-implemented as vectorized PyTorch code. BETSE license:
18
+
19
+ ```text
20
+ Copyright 2014-2025 by Alexis Pietak & Cecil Curry.
21
+ All rights reserved.
22
+
23
+ Redistribution and use in source and binary forms, with or without
24
+ modification, are permitted provided that the following conditions are met:
25
+
26
+ 1. Redistributions of source code must retain the above copyright notice, this
27
+ list of conditions and the following disclaimer.
28
+ 2. Redistributions in binary form must reproduce the above copyright notice,
29
+ this list of conditions and the following disclaimer in the documentation
30
+ and/or other materials provided with the distribution.
31
+
32
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
36
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42
+ ```
@@ -0,0 +1,53 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "bioelectrics"
7
+ version = "0.3.0"
8
+ description = "Differentiable somatic bioelectricity: ion-level tissue physics, published model zoo, and inverse design of lab interventions in PyTorch"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE", "THIRD_PARTY_NOTICES.md"]
13
+ authors = [{ name = "The bioelectrics contributors" }]
14
+ keywords = [
15
+ "bioelectricity", "membrane potential", "gap junctions", "ion channels",
16
+ "morphogenesis", "developmental biology", "differentiable simulation", "pytorch",
17
+ ]
18
+ classifiers = [
19
+ "Development Status :: 4 - Beta",
20
+ "Intended Audience :: Science/Research",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
26
+ "Topic :: Scientific/Engineering :: Physics",
27
+ "Typing :: Typed",
28
+ ]
29
+
30
+ dependencies = [
31
+ "torch>=2.0",
32
+ "numpy>=1.24",
33
+ "scipy>=1.10",
34
+ "matplotlib>=3.7",
35
+ "networkx>=3.0",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://tlcdv.github.io/bioelectrics/"
40
+ Documentation = "https://tlcdv.github.io/bioelectrics/"
41
+ Repository = "https://github.com/tlcdv/bioelectrics"
42
+ Issues = "https://github.com/tlcdv/bioelectrics/issues"
43
+ Validation = "https://tlcdv.github.io/bioelectrics/validation/"
44
+
45
+ [project.optional-dependencies]
46
+ dev = ["pytest>=7", "pytest-cov>=4", "pyyaml>=6"]
47
+ notebooks = ["nbmake>=1.5", "matplotlib"]
48
+
49
+ [tool.setuptools.packages.find]
50
+ where = ["src"]
51
+
52
+ [tool.pytest.ini_options]
53
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,34 @@
1
+ """bioelectrics: a differentiable engine for somatic bioelectricity.
2
+
3
+ Subpackages and modules
4
+ -----------------------
5
+ * ``bioelectrics.ionic``: ion-level physics (Na+, K+, Cl-, Ca2+; GHK fluxes, pumps,
6
+ Hodgkin-Huxley channels, electrodiffusive gap junctions), BETSE-compatible.
7
+ * ``bioelectrics.interventions``: channel misexpression, drugs, gap junction blockers,
8
+ optogenetics, and their inverse design (``InterventionOptimizer``,
9
+ ``ChronicInterventionOptimizer``).
10
+ * ``bioelectrics.attractors``: steady states, stability, basins, dose ramps, and
11
+ implicit gradients of steady states.
12
+ * ``bioelectrics.pharmacology``: drugs with published potency values, each carrying its
13
+ assay, species and citation.
14
+ * ``bioelectrics.zoo``: published models with reproduction tests.
15
+ * Voltage-level (CAM-type) models: ``ChannelProfile``, ``Tissue``, ``PatternOptimizer``.
16
+ """
17
+
18
+ from . import attractors, constants, interventions, ionic, pharmacology, zoo
19
+ from .channels import (
20
+ ChannelProfile,
21
+ find_fixed_points,
22
+ ghk_current,
23
+ i_dep,
24
+ i_leak,
25
+ i_pol,
26
+ ionic_current,
27
+ membrane_rhs,
28
+ )
29
+ from .control import OptimizationResult, PatternOptimizer
30
+ from .gap_junctions import GapJunctionProfile, gj_conductance, grid_conductances
31
+ from .integrators import euler_step, integrate, integrate_adaptive, integrate_rosenbrock, rk4_step
32
+ from .tissue import BioelectricState, Tissue, tumor_prepattern
33
+
34
+ __version__ = "0.3.0"