bindtools 0.2.3__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bindtools-0.2.3 → bindtools-0.3.1}/PKG-INFO +57 -4
- {bindtools-0.2.3 → bindtools-0.3.1}/README.md +56 -3
- bindtools-0.3.1/pyproject.toml +111 -0
- bindtools-0.2.3/pyproject.toml → bindtools-0.3.1/pyproject.toml.orig +1 -1
- bindtools-0.3.1/src/bindtools/__init__.py +49 -0
- bindtools-0.3.1/src/bindtools/binding.py +95 -0
- bindtools-0.3.1/src/bindtools/exceptions.py +6 -0
- bindtools-0.3.1/src/bindtools/io/__init__.py +4 -0
- bindtools-0.3.1/src/bindtools/io/export.py +29 -0
- bindtools-0.3.1/src/bindtools/mcmc/__init__.py +19 -0
- bindtools-0.3.1/src/bindtools/mcmc/helpers.py +71 -0
- bindtools-0.3.1/src/bindtools/mcmc/likelihood.py +49 -0
- bindtools-0.3.1/src/bindtools/mcmc/sampler.py +226 -0
- bindtools-0.3.1/src/bindtools/models/__init__.py +11 -0
- bindtools-0.3.1/src/bindtools/models/binding_model.py +293 -0
- bindtools-0.3.1/src/bindtools/models/objective.py +95 -0
- bindtools-0.3.1/src/bindtools/models/simulation.py +39 -0
- bindtools-0.3.1/src/bindtools/observables/__init__.py +17 -0
- bindtools-0.3.1/src/bindtools/observables/transforms.py +87 -0
- bindtools-0.3.1/src/bindtools/observables/types.py +78 -0
- bindtools-0.3.1/src/bindtools/plotting/__init__.py +8 -0
- bindtools-0.3.1/src/bindtools/plotting/fit_plots.py +66 -0
- bindtools-0.3.1/src/bindtools/plotting/mcmc_plots.py +38 -0
- bindtools-0.3.1/src/bindtools/speciation/__init__.py +34 -0
- bindtools-0.3.1/src/bindtools/speciation/analytical.py +250 -0
- bindtools-0.3.1/src/bindtools/speciation/numerical.py +139 -0
- bindtools-0.3.1/src/bindtools/speciation/scipy_solver.py +45 -0
- bindtools-0.2.3/src/bindtools/__init__.py +0 -0
- bindtools-0.2.3/src/bindtools/binding.py +0 -1605
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: bindtools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Keywords: chemistry,analytical chemistry,binding constants,supramolecular
|
|
5
5
|
Author: Martin Peeks
|
|
6
6
|
Author-email: Martin Peeks <martinp23@googlemail.com>, m.peeks@unsw.edu.au
|
|
@@ -51,11 +51,26 @@ Description-Content-Type: text/markdown
|
|
|
51
51
|
- Handles various experimental data including NMR integrations, chemical shifts (NMR `deltaH`/`deltaF`), and linear concentration-weighted observables (UV-vis / fluorescence).
|
|
52
52
|
- **Bayesian Inference & Uncertainty Quantification**:
|
|
53
53
|
- Uses `emcee` for Markov Chain Monte Carlo (MCMC) sampling.
|
|
54
|
-
- Generates trace/chain convergence plots and corner plots using `corner` and `
|
|
54
|
+
- Generates trace/chain convergence plots and corner plots using `corner` and `matplotlib`.
|
|
55
55
|
- MCMC runs can be serialized and stored as HDF5 files for future analysis.
|
|
56
56
|
|
|
57
57
|
---
|
|
58
58
|
|
|
59
|
+
## Package Architecture
|
|
60
|
+
|
|
61
|
+
`bindtools` is organized into modular scientific domain subpackages:
|
|
62
|
+
|
|
63
|
+
- **`bindtools.speciation`**: Chemical equilibrium solvers (Numba JIT Newton-Raphson and vectorized cubic analytical solutions for 1:1, 1:2, and 2:1 systems).
|
|
64
|
+
- **`bindtools.observables`**: Physical measurement transforms (`ObsType`, NMR chemical shifts, integrals, and UV-vis / fluorescence linear absorption).
|
|
65
|
+
- **`bindtools.models`**: Model definition (`bindingModel`), simulation helpers, and optimization engine.
|
|
66
|
+
- **`bindtools.mcmc`**: Bayesian parameter estimation (`MCMC`), priors, likelihoods, and HDF5 serialization.
|
|
67
|
+
- **`bindtools.plotting`**: Visualizations for speciation, fit residuals, and MCMC trace/corner diagnostics.
|
|
68
|
+
- **`bindtools.io`**: Data export utilities (`saveFitCSV`).
|
|
69
|
+
|
|
70
|
+
Core symbols can be imported directly from the top level (`import bindtools as bt`), while legacy imports (`from bindtools import binding as bd`) remain fully supported for backwards compatibility.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
59
74
|
## Installation
|
|
60
75
|
|
|
61
76
|
`bindtools` is available on PyPI. You can install it directly using `pip`:
|
|
@@ -90,7 +105,7 @@ You can compute the equilibrium concentration of free species (components and co
|
|
|
90
105
|
|
|
91
106
|
```python
|
|
92
107
|
import numpy as np
|
|
93
|
-
|
|
108
|
+
import bindtools as bt
|
|
94
109
|
|
|
95
110
|
# Define total concentrations: 50 data points of Host (1e-3 M) and Guest (0 to 1e-2 M)
|
|
96
111
|
component_concs = np.zeros((50, 2))
|
|
@@ -113,13 +128,51 @@ logK = np.array([0, 0, 4])
|
|
|
113
128
|
# Solve for concentrations at each point
|
|
114
129
|
results = []
|
|
115
130
|
for total_concs in component_concs:
|
|
116
|
-
spec_concs =
|
|
131
|
+
spec_concs = bt.getConcs(eq_mat, total_concs, logK)
|
|
117
132
|
results.append(spec_concs)
|
|
118
133
|
|
|
119
134
|
results = np.array(results)
|
|
120
135
|
print("First point [H, G, HG]:", results[0])
|
|
121
136
|
```
|
|
122
137
|
|
|
138
|
+
### 2. Model Fitting (`bindingModel`)
|
|
139
|
+
|
|
140
|
+
Fit binding models to experimental observables (integrals, chemical shifts, or absorbance):
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
import bindtools as bt
|
|
144
|
+
|
|
145
|
+
# Initialize model with stoichiometry, component names, and data
|
|
146
|
+
model = bt.bindingModel(
|
|
147
|
+
eqMat=eq_mat,
|
|
148
|
+
compNames=["H", "G"],
|
|
149
|
+
speciesList=["H", "G", "HG"],
|
|
150
|
+
colToComp=col_to_comp,
|
|
151
|
+
rawData=raw_data,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Prepare parameters and fit
|
|
155
|
+
model.prepModel()
|
|
156
|
+
model.runModel(skip_col=2, method="least_squares")
|
|
157
|
+
|
|
158
|
+
print("Fitted logK:", model.miniResult.params["logHG"].value)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 3. Bayesian MCMC & Uncertainty Estimation
|
|
162
|
+
|
|
163
|
+
Quantify parameter uncertainties with MCMC sampling and generate corner plots:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
obs = [bt.ObsType("concMeas")]
|
|
167
|
+
mcmc = bt.MCMC(model, obs, walkers=25, samples=2000)
|
|
168
|
+
sampler, bm = mcmc.run(thin=10)
|
|
169
|
+
|
|
170
|
+
# Diagnostics & plots
|
|
171
|
+
mcmc.plot_chain()
|
|
172
|
+
mcmc.plot_corner()
|
|
173
|
+
mcmc.save("fit_results.hdf")
|
|
174
|
+
```
|
|
175
|
+
|
|
123
176
|
---
|
|
124
177
|
|
|
125
178
|
## License
|
|
@@ -18,11 +18,26 @@
|
|
|
18
18
|
- Handles various experimental data including NMR integrations, chemical shifts (NMR `deltaH`/`deltaF`), and linear concentration-weighted observables (UV-vis / fluorescence).
|
|
19
19
|
- **Bayesian Inference & Uncertainty Quantification**:
|
|
20
20
|
- Uses `emcee` for Markov Chain Monte Carlo (MCMC) sampling.
|
|
21
|
-
- Generates trace/chain convergence plots and corner plots using `corner` and `
|
|
21
|
+
- Generates trace/chain convergence plots and corner plots using `corner` and `matplotlib`.
|
|
22
22
|
- MCMC runs can be serialized and stored as HDF5 files for future analysis.
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
26
|
+
## Package Architecture
|
|
27
|
+
|
|
28
|
+
`bindtools` is organized into modular scientific domain subpackages:
|
|
29
|
+
|
|
30
|
+
- **`bindtools.speciation`**: Chemical equilibrium solvers (Numba JIT Newton-Raphson and vectorized cubic analytical solutions for 1:1, 1:2, and 2:1 systems).
|
|
31
|
+
- **`bindtools.observables`**: Physical measurement transforms (`ObsType`, NMR chemical shifts, integrals, and UV-vis / fluorescence linear absorption).
|
|
32
|
+
- **`bindtools.models`**: Model definition (`bindingModel`), simulation helpers, and optimization engine.
|
|
33
|
+
- **`bindtools.mcmc`**: Bayesian parameter estimation (`MCMC`), priors, likelihoods, and HDF5 serialization.
|
|
34
|
+
- **`bindtools.plotting`**: Visualizations for speciation, fit residuals, and MCMC trace/corner diagnostics.
|
|
35
|
+
- **`bindtools.io`**: Data export utilities (`saveFitCSV`).
|
|
36
|
+
|
|
37
|
+
Core symbols can be imported directly from the top level (`import bindtools as bt`), while legacy imports (`from bindtools import binding as bd`) remain fully supported for backwards compatibility.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
26
41
|
## Installation
|
|
27
42
|
|
|
28
43
|
`bindtools` is available on PyPI. You can install it directly using `pip`:
|
|
@@ -57,7 +72,7 @@ You can compute the equilibrium concentration of free species (components and co
|
|
|
57
72
|
|
|
58
73
|
```python
|
|
59
74
|
import numpy as np
|
|
60
|
-
|
|
75
|
+
import bindtools as bt
|
|
61
76
|
|
|
62
77
|
# Define total concentrations: 50 data points of Host (1e-3 M) and Guest (0 to 1e-2 M)
|
|
63
78
|
component_concs = np.zeros((50, 2))
|
|
@@ -80,13 +95,51 @@ logK = np.array([0, 0, 4])
|
|
|
80
95
|
# Solve for concentrations at each point
|
|
81
96
|
results = []
|
|
82
97
|
for total_concs in component_concs:
|
|
83
|
-
spec_concs =
|
|
98
|
+
spec_concs = bt.getConcs(eq_mat, total_concs, logK)
|
|
84
99
|
results.append(spec_concs)
|
|
85
100
|
|
|
86
101
|
results = np.array(results)
|
|
87
102
|
print("First point [H, G, HG]:", results[0])
|
|
88
103
|
```
|
|
89
104
|
|
|
105
|
+
### 2. Model Fitting (`bindingModel`)
|
|
106
|
+
|
|
107
|
+
Fit binding models to experimental observables (integrals, chemical shifts, or absorbance):
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
import bindtools as bt
|
|
111
|
+
|
|
112
|
+
# Initialize model with stoichiometry, component names, and data
|
|
113
|
+
model = bt.bindingModel(
|
|
114
|
+
eqMat=eq_mat,
|
|
115
|
+
compNames=["H", "G"],
|
|
116
|
+
speciesList=["H", "G", "HG"],
|
|
117
|
+
colToComp=col_to_comp,
|
|
118
|
+
rawData=raw_data,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Prepare parameters and fit
|
|
122
|
+
model.prepModel()
|
|
123
|
+
model.runModel(skip_col=2, method="least_squares")
|
|
124
|
+
|
|
125
|
+
print("Fitted logK:", model.miniResult.params["logHG"].value)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 3. Bayesian MCMC & Uncertainty Estimation
|
|
129
|
+
|
|
130
|
+
Quantify parameter uncertainties with MCMC sampling and generate corner plots:
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
obs = [bt.ObsType("concMeas")]
|
|
134
|
+
mcmc = bt.MCMC(model, obs, walkers=25, samples=2000)
|
|
135
|
+
sampler, bm = mcmc.run(thin=10)
|
|
136
|
+
|
|
137
|
+
# Diagnostics & plots
|
|
138
|
+
mcmc.plot_chain()
|
|
139
|
+
mcmc.plot_corner()
|
|
140
|
+
mcmc.save("fit_results.hdf")
|
|
141
|
+
```
|
|
142
|
+
|
|
90
143
|
---
|
|
91
144
|
|
|
92
145
|
## License
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "bindtools"
|
|
7
|
+
version = "0.3.1"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Development Status :: 3 - Alpha",
|
|
11
|
+
"Intended Audience :: Science/Research",
|
|
12
|
+
"Programming Language :: Python :: 3.12",
|
|
13
|
+
"Programming Language :: Python :: 3.13",
|
|
14
|
+
"Programming Language :: Python :: 3.14",
|
|
15
|
+
"Topic :: Scientific/Engineering :: Chemistry",
|
|
16
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
17
|
+
]
|
|
18
|
+
requires-python = ">=3.12"
|
|
19
|
+
keywords = [
|
|
20
|
+
"chemistry",
|
|
21
|
+
"analytical chemistry",
|
|
22
|
+
"binding constants",
|
|
23
|
+
"supramolecular",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"corner==2.2.3",
|
|
27
|
+
"emcee==3.1.6",
|
|
28
|
+
"h5py>=3.14.0",
|
|
29
|
+
"latex2mathml>=3.81.0",
|
|
30
|
+
"lmfit==1.3.4",
|
|
31
|
+
"matplotlib==3.11.0",
|
|
32
|
+
"numba>=0.66",
|
|
33
|
+
"numpy>=2.3.4",
|
|
34
|
+
"openpyxl>=3.1.5",
|
|
35
|
+
"pandas>=2.3.3",
|
|
36
|
+
"scipy==1.18.0",
|
|
37
|
+
"tqdm==4.68.3",
|
|
38
|
+
"uncertainties==3.2.3",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[[project.authors]]
|
|
42
|
+
name = "Martin Peeks"
|
|
43
|
+
email = "martinp23@googlemail.com"
|
|
44
|
+
|
|
45
|
+
[[project.authors]]
|
|
46
|
+
email = "m.peeks@unsw.edu.au"
|
|
47
|
+
|
|
48
|
+
[project.urls]
|
|
49
|
+
Homepage = "https://github.com/martinp23/bindtools"
|
|
50
|
+
Documentation = "https://readthedocs.org"
|
|
51
|
+
Repository = "https://github.com/martinp23/bindtools.git"
|
|
52
|
+
Issues = "https://github.com/martinp23/bindtools/issues"
|
|
53
|
+
|
|
54
|
+
[tool.ruff]
|
|
55
|
+
exclude = [
|
|
56
|
+
".bzr",
|
|
57
|
+
".direnv",
|
|
58
|
+
".eggs",
|
|
59
|
+
".git",
|
|
60
|
+
".git-rewrite",
|
|
61
|
+
".hg",
|
|
62
|
+
".ipynb_checkpoints",
|
|
63
|
+
".mypy_cache",
|
|
64
|
+
".nox",
|
|
65
|
+
".pants.d",
|
|
66
|
+
".pyenv",
|
|
67
|
+
".pytest_cache",
|
|
68
|
+
".pytype",
|
|
69
|
+
".ruff_cache",
|
|
70
|
+
".svn",
|
|
71
|
+
".tox",
|
|
72
|
+
".venv",
|
|
73
|
+
".vscode",
|
|
74
|
+
"__pypackages__",
|
|
75
|
+
"_build",
|
|
76
|
+
"buck-out",
|
|
77
|
+
"build",
|
|
78
|
+
"dist",
|
|
79
|
+
"node_modules",
|
|
80
|
+
"site-packages",
|
|
81
|
+
"venv",
|
|
82
|
+
]
|
|
83
|
+
line-length = 120
|
|
84
|
+
indent-width = 4
|
|
85
|
+
|
|
86
|
+
[tool.ruff.lint]
|
|
87
|
+
select = [
|
|
88
|
+
"E4",
|
|
89
|
+
"E7",
|
|
90
|
+
"E9",
|
|
91
|
+
"F",
|
|
92
|
+
]
|
|
93
|
+
ignore = []
|
|
94
|
+
fixable = ["ALL"]
|
|
95
|
+
unfixable = []
|
|
96
|
+
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
|
97
|
+
|
|
98
|
+
[tool.ruff.format]
|
|
99
|
+
quote-style = "double"
|
|
100
|
+
indent-style = "space"
|
|
101
|
+
skip-magic-trailing-comma = false
|
|
102
|
+
line-ending = "auto"
|
|
103
|
+
docstring-code-format = false
|
|
104
|
+
docstring-code-line-length = "dynamic"
|
|
105
|
+
|
|
106
|
+
[dependency-groups]
|
|
107
|
+
dev = [
|
|
108
|
+
"ipykernel>=7.3.0",
|
|
109
|
+
"pytest>=9.1.0",
|
|
110
|
+
"ruff>=0.15.18",
|
|
111
|
+
]
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""bindtools: Python library for supramolecular chemistry modeling, fitting, and speciation.
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
from bindtools.exceptions import EquilibriumError
|
|
5
|
+
from bindtools.speciation import (
|
|
6
|
+
getConcs,
|
|
7
|
+
getConcsScipy,
|
|
8
|
+
calc_analytical_speciation,
|
|
9
|
+
)
|
|
10
|
+
from bindtools.observables import (
|
|
11
|
+
ObsType,
|
|
12
|
+
concToObservable,
|
|
13
|
+
concToDelta,
|
|
14
|
+
concToLinearObs,
|
|
15
|
+
)
|
|
16
|
+
from bindtools.models import (
|
|
17
|
+
bindingModel,
|
|
18
|
+
simulateModel,
|
|
19
|
+
getCalcData,
|
|
20
|
+
)
|
|
21
|
+
from bindtools.mcmc import (
|
|
22
|
+
MCMC,
|
|
23
|
+
)
|
|
24
|
+
from bindtools.plotting import (
|
|
25
|
+
makeFitResidPlot,
|
|
26
|
+
)
|
|
27
|
+
from bindtools.io import (
|
|
28
|
+
saveFitCSV,
|
|
29
|
+
)
|
|
30
|
+
from bindtools import binding
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"binding",
|
|
34
|
+
"EquilibriumError",
|
|
35
|
+
"getConcs",
|
|
36
|
+
"getConcsScipy",
|
|
37
|
+
"calc_analytical_speciation",
|
|
38
|
+
"ObsType",
|
|
39
|
+
"concToObservable",
|
|
40
|
+
"concToDelta",
|
|
41
|
+
"concToLinearObs",
|
|
42
|
+
"bindingModel",
|
|
43
|
+
"simulateModel",
|
|
44
|
+
"getCalcData",
|
|
45
|
+
"MCMC",
|
|
46
|
+
"makeFitResidPlot",
|
|
47
|
+
"saveFitCSV",
|
|
48
|
+
]
|
|
49
|
+
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""Compatibility façade re-exporting all public and internal symbols from modular subpackages.
|
|
2
|
+
|
|
3
|
+
This module preserves 100% backwards compatibility with historical code and downstream packages
|
|
4
|
+
(e.g., `import bindtools.binding as bd` or `from bindtools.binding import bindingModel, getConcs`).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from bindtools.exceptions import EquilibriumError
|
|
8
|
+
from bindtools.speciation import (
|
|
9
|
+
apply_along_axis_0,
|
|
10
|
+
_apply_along_axis_0,
|
|
11
|
+
specCalc,
|
|
12
|
+
_specJac,
|
|
13
|
+
specJac,
|
|
14
|
+
specObj,
|
|
15
|
+
DoNR,
|
|
16
|
+
getConcs,
|
|
17
|
+
getConcsScipy,
|
|
18
|
+
_solve_cubic_vectorized,
|
|
19
|
+
calc_analytical_speciation,
|
|
20
|
+
_infer_simple_fast_exchange_topology,
|
|
21
|
+
)
|
|
22
|
+
from bindtools.observables import (
|
|
23
|
+
ObsType,
|
|
24
|
+
sigmaMapping,
|
|
25
|
+
deltaToConc,
|
|
26
|
+
concToDelta,
|
|
27
|
+
concToLinearObs,
|
|
28
|
+
concToObservable,
|
|
29
|
+
)
|
|
30
|
+
from bindtools.models import (
|
|
31
|
+
fitfun,
|
|
32
|
+
bindingModel,
|
|
33
|
+
simulateModel,
|
|
34
|
+
getCalcData,
|
|
35
|
+
)
|
|
36
|
+
from bindtools.mcmc import (
|
|
37
|
+
calclnprob,
|
|
38
|
+
log_prob,
|
|
39
|
+
log_prior,
|
|
40
|
+
MCMC,
|
|
41
|
+
doMCMC,
|
|
42
|
+
getTau,
|
|
43
|
+
makeMCMCLabels,
|
|
44
|
+
mcmchelper,
|
|
45
|
+
)
|
|
46
|
+
from bindtools.plotting import (
|
|
47
|
+
makeFitResidPlot,
|
|
48
|
+
plotMCMC,
|
|
49
|
+
plotCorner,
|
|
50
|
+
)
|
|
51
|
+
from bindtools.io import saveFitCSV
|
|
52
|
+
|
|
53
|
+
__all__ = [
|
|
54
|
+
# Exceptions
|
|
55
|
+
"EquilibriumError",
|
|
56
|
+
# Speciation
|
|
57
|
+
"apply_along_axis_0",
|
|
58
|
+
"_apply_along_axis_0",
|
|
59
|
+
"specCalc",
|
|
60
|
+
"_specJac",
|
|
61
|
+
"specJac",
|
|
62
|
+
"specObj",
|
|
63
|
+
"DoNR",
|
|
64
|
+
"getConcs",
|
|
65
|
+
"getConcsScipy",
|
|
66
|
+
"_solve_cubic_vectorized",
|
|
67
|
+
"calc_analytical_speciation",
|
|
68
|
+
"_infer_simple_fast_exchange_topology",
|
|
69
|
+
# Observables
|
|
70
|
+
"ObsType",
|
|
71
|
+
"sigmaMapping",
|
|
72
|
+
"deltaToConc",
|
|
73
|
+
"concToDelta",
|
|
74
|
+
"concToLinearObs",
|
|
75
|
+
"concToObservable",
|
|
76
|
+
# Models & Simulation
|
|
77
|
+
"fitfun",
|
|
78
|
+
"bindingModel",
|
|
79
|
+
"simulateModel",
|
|
80
|
+
"getCalcData",
|
|
81
|
+
# Visualization & IO
|
|
82
|
+
"makeFitResidPlot",
|
|
83
|
+
"plotMCMC",
|
|
84
|
+
"plotCorner",
|
|
85
|
+
"saveFitCSV",
|
|
86
|
+
# MCMC
|
|
87
|
+
"calclnprob",
|
|
88
|
+
"log_prob",
|
|
89
|
+
"log_prior",
|
|
90
|
+
"MCMC",
|
|
91
|
+
"doMCMC",
|
|
92
|
+
"getTau",
|
|
93
|
+
"makeMCMCLabels",
|
|
94
|
+
"mcmchelper",
|
|
95
|
+
]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from bindtools.models.simulation import getCalcData
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def saveFitCSV(m, mask, filename, xindex=1, xvals=None, xlabel="[G]_tot (M)", labels=None):
|
|
7
|
+
calcData = getCalcData(m)
|
|
8
|
+
compConcs = m.compConcs.copy()
|
|
9
|
+
exptData = m.fcn_opts["exptData"].copy()
|
|
10
|
+
|
|
11
|
+
if labels is None:
|
|
12
|
+
labels = [m.obsList[ii] for ii in mask]
|
|
13
|
+
|
|
14
|
+
if mask is not None:
|
|
15
|
+
calcData = calcData[:, mask]
|
|
16
|
+
exptData = exptData[:, mask]
|
|
17
|
+
|
|
18
|
+
if xvals is None:
|
|
19
|
+
xvals = compConcs[:, xindex]
|
|
20
|
+
|
|
21
|
+
ydata = np.concatenate((exptData, calcData), axis=1)
|
|
22
|
+
data = np.concatenate((xvals[:, np.newaxis], ydata), axis=1)
|
|
23
|
+
|
|
24
|
+
cols = [xlabel, *["expt " + x for x in labels], *["calc " + x for x in labels]]
|
|
25
|
+
print(cols)
|
|
26
|
+
dataExport = pd.DataFrame(data, columns=cols)
|
|
27
|
+
|
|
28
|
+
dataExport.to_csv(filename, index=False)
|
|
29
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from bindtools.mcmc.likelihood import calclnprob, log_prob, log_prior
|
|
2
|
+
from bindtools.mcmc.sampler import MCMC
|
|
3
|
+
from bindtools.mcmc.helpers import (
|
|
4
|
+
doMCMC,
|
|
5
|
+
getTau,
|
|
6
|
+
makeMCMCLabels,
|
|
7
|
+
mcmchelper,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"calclnprob",
|
|
12
|
+
"log_prob",
|
|
13
|
+
"log_prior",
|
|
14
|
+
"MCMC",
|
|
15
|
+
"doMCMC",
|
|
16
|
+
"getTau",
|
|
17
|
+
"makeMCMCLabels",
|
|
18
|
+
"mcmchelper",
|
|
19
|
+
]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from bindtools.mcmc.sampler import MCMC
|
|
2
|
+
from bindtools.observables.types import ObsType
|
|
3
|
+
import emcee
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def doMCMC(model, obs, samples=1000, variance=0.1, walkers=10):
|
|
7
|
+
print("Warning: doMCMC() is deprecated. Use the MCMC class and MCMC.run() in future.")
|
|
8
|
+
mcmcModel = MCMC(model, obs, walkers=walkers, samples=samples, variance=variance)
|
|
9
|
+
sampler, bm = mcmcModel.run(ret=True)
|
|
10
|
+
return sampler, bm
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def getTau(sampler):
|
|
14
|
+
print("Warning: getTau is deprecated. Use the MCMC class and MCMC.get_tau() in future.")
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
tau = sampler.get_autocorr_time()
|
|
18
|
+
print(tau)
|
|
19
|
+
except emcee.autocorr.AutocorrError as e:
|
|
20
|
+
print("Warning: Autocorrelation time is likely too short. Check the chain.")
|
|
21
|
+
print(e.tau)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def makeMCMCLabels(model, obs):
|
|
25
|
+
print("Warning: makeMCMCLabels is deprecated. Use the MCMC class and MCMC.labels in future.")
|
|
26
|
+
|
|
27
|
+
params = []
|
|
28
|
+
for pp in model.params:
|
|
29
|
+
if model.params[pp].vary:
|
|
30
|
+
params.append(model.params[pp].name)
|
|
31
|
+
|
|
32
|
+
ss = []
|
|
33
|
+
for pp in obs:
|
|
34
|
+
ss.append(pp.name)
|
|
35
|
+
|
|
36
|
+
ss = list(set(ss))
|
|
37
|
+
ss = ["lnsigma" + x for x in ss]
|
|
38
|
+
params += ss
|
|
39
|
+
|
|
40
|
+
return params
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def mcmchelper(
|
|
44
|
+
model, obsList=None, obs_types=None, walkers=25, samples=10000, variance=0.1, thin=500, figName="out.jpg"
|
|
45
|
+
):
|
|
46
|
+
"""
|
|
47
|
+
Helper function to run MCMC on a binding model and plot results.
|
|
48
|
+
|
|
49
|
+
Parameters:
|
|
50
|
+
- model: The binding model to run MCMC on.
|
|
51
|
+
- obsList: List of observable types.
|
|
52
|
+
- obs_types: Optional list of ObsType instances.
|
|
53
|
+
- walkers: Number of walkers for MCMC.
|
|
54
|
+
- samples: Number of samples to draw.
|
|
55
|
+
- variance: Variance for the MCMC sampling.
|
|
56
|
+
- thin: Thinning factor for the samples.
|
|
57
|
+
- figName: Name of the output figure file.
|
|
58
|
+
"""
|
|
59
|
+
if obs_types is None:
|
|
60
|
+
if obsList is None:
|
|
61
|
+
raise ValueError("Either obsList or obs_types must be provided.")
|
|
62
|
+
obs_types = [ObsType("deltaH")] * len(obsList)
|
|
63
|
+
|
|
64
|
+
mcmc = MCMC(model, obs_types, walkers=walkers, samples=samples, variance=variance)
|
|
65
|
+
mcmc.run(thin=thin)
|
|
66
|
+
|
|
67
|
+
mcmc.plot_chain()
|
|
68
|
+
mcmc.get_tau()
|
|
69
|
+
ff = mcmc.plot_corner()
|
|
70
|
+
ff.savefig(figName, dpi=150)
|
|
71
|
+
return mcmc
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import numpy as np
|
|
3
|
+
from numba import jit
|
|
4
|
+
|
|
5
|
+
from bindtools.models.objective import fitfun
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@jit(nopython=True, nogil=True, cache=True)
|
|
9
|
+
def calclnprob(r, lnsigma):
|
|
10
|
+
r = -0.5 * np.sum(np.divide(r, np.exp(lnsigma)) ** 2 + np.log(2 * np.pi) + 2 * lnsigma)
|
|
11
|
+
|
|
12
|
+
if math.isnan(r):
|
|
13
|
+
print("Probability function returned NaN, fudging to -inf.")
|
|
14
|
+
return -np.inf
|
|
15
|
+
return r
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@jit(nopython=True, nogil=True, cache=True)
|
|
19
|
+
def log_prior(val, bounds):
|
|
20
|
+
for ii in range(len(val)):
|
|
21
|
+
if not (bounds[ii][0] < val[ii] < bounds[ii][1]):
|
|
22
|
+
return -np.inf
|
|
23
|
+
return 0.0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def log_prob(params, fcn_opts, bounds):
|
|
27
|
+
lp = log_prior(params, bounds)
|
|
28
|
+
|
|
29
|
+
if not np.isfinite(lp):
|
|
30
|
+
return -np.inf
|
|
31
|
+
|
|
32
|
+
mapping = fcn_opts["sigmaMapping"]
|
|
33
|
+
lnsigmaVals = params[-(max(mapping) + 1) :]
|
|
34
|
+
lnsigma = np.array([lnsigmaVals[ii] for ii in mapping])
|
|
35
|
+
|
|
36
|
+
pp = np.zeros(
|
|
37
|
+
len(params) + np.shape(fcn_opts["compConcs"])[1]
|
|
38
|
+
) # need extra parameters - for logK=0 - for each component in the eqMat
|
|
39
|
+
|
|
40
|
+
pp[-len(params) :] = params
|
|
41
|
+
|
|
42
|
+
fcn_opts["ret"] = "residual"
|
|
43
|
+
r = np.array(fitfun(pp, fcn_opts))
|
|
44
|
+
if np.isnan(r).any():
|
|
45
|
+
return -np.inf
|
|
46
|
+
|
|
47
|
+
rout = calclnprob(r, lnsigma)
|
|
48
|
+
return rout
|
|
49
|
+
|