bindmc 0.1.0__tar.gz → 0.1.2__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.
- bindmc-0.1.2/PKG-INFO +63 -0
- bindmc-0.1.2/README.md +25 -0
- {bindmc-0.1.0 → bindmc-0.1.2}/pyproject.toml +39 -1
- bindmc-0.1.2/src/bindmc/main.py +72 -0
- bindmc-0.1.2/src/bindmc/webgui/Class model.md +27 -0
- bindmc-0.1.2/src/bindmc/webgui/TODO.md +232 -0
- bindmc-0.1.2/src/bindmc/webgui/TODO_old.md +89 -0
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/app.py +13 -17
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/BindingConstant.py +3 -10
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/ChemicalShiftParam.py +9 -15
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/Component.py +9 -25
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/ExptData.py +76 -72
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/ExptDataType.py +18 -25
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/FitResult.py +31 -44
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/MCMCSim.py +22 -37
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/Model.py +10 -26
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/RawData.py +4 -16
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/Simulation.py +13 -34
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/UIBindings.py +3 -8
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/classes/__init__.py +2 -3
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/__init__.py +2 -2
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/base.py +1 -0
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/bayes.py +194 -195
- bindmc-0.1.2/src/bindmc/webgui/components/bayes_priors.py +368 -0
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/binding_model.py +86 -89
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/body.py +31 -54
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/data_gen.py +59 -78
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/data_import.py +159 -150
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/data_model.py +171 -163
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/fitting.py +152 -157
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/graph.py +133 -137
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/header.py +22 -22
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/components/simulation.py +42 -69
- bindmc-0.1.2/src/bindmc/webgui/default_models.json +1 -0
- bindmc-0.1.2/src/bindmc/webgui/export/__init__.py +0 -0
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/export/notebook_exporter.py +230 -213
- bindmc-0.1.2/src/bindmc/webgui/state/__init__.py +1 -0
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/state/statemanager.py +293 -375
- {bindmc-0.1.0 → bindmc-0.1.2}/src/bindmc/webgui/utils.py +64 -58
- bindmc-0.1.0/PKG-INFO +0 -22
- bindmc-0.1.0/setup.cfg +0 -4
- bindmc-0.1.0/src/bindmc/main.py +0 -67
- bindmc-0.1.0/src/bindmc/webgui/components/bayes_priors.py +0 -351
- bindmc-0.1.0/src/bindmc/webgui/state/__init__.py +0 -1
- bindmc-0.1.0/src/bindmc.egg-info/PKG-INFO +0 -22
- bindmc-0.1.0/src/bindmc.egg-info/SOURCES.txt +0 -56
- bindmc-0.1.0/src/bindmc.egg-info/dependency_links.txt +0 -1
- bindmc-0.1.0/src/bindmc.egg-info/requires.txt +0 -18
- bindmc-0.1.0/src/bindmc.egg-info/top_level.txt +0 -1
- bindmc-0.1.0/tests/test_active_context_state_manager.py +0 -245
- bindmc-0.1.0/tests/test_analytical_fast_exchange_backend.py +0 -203
- bindmc-0.1.0/tests/test_bayes_plot_sizing.py +0 -31
- bindmc-0.1.0/tests/test_body_tab_guidance.py +0 -101
- bindmc-0.1.0/tests/test_component_concentration.py +0 -87
- bindmc-0.1.0/tests/test_data_model_analytical_defaults.py +0 -19
- bindmc-0.1.0/tests/test_exptdata_shift_param_naming.py +0 -104
- bindmc-0.1.0/tests/test_fit_analytical_fast_exchange_screen.py +0 -167
- bindmc-0.1.0/tests/test_fit_graph_subset_dep_vars.py +0 -137
- bindmc-0.1.0/tests/test_model_setups.py +0 -165
- bindmc-0.1.0/tests/test_model_to_python.py +0 -22
- bindmc-0.1.0/tests/test_notebook_export.py +0 -548
- bindmc-0.1.0/tests/test_sim_flow.py +0 -59
- bindmc-0.1.0/tests/test_simulation_workflow_screen.py +0 -144
- bindmc-0.1.0/tests/test_startup.py +0 -17
- bindmc-0.1.0/tests/test_uvvis_fluorescence.py +0 -520
- bindmc-0.1.0/tests/testutils.py +0 -15
- {bindmc-0.1.0/src/bindmc/webgui → bindmc-0.1.2/src/bindmc}/__init__.py +0 -0
- {bindmc-0.1.0/src/bindmc/webgui/export → bindmc-0.1.2/src/bindmc/webgui}/__init__.py +0 -0
bindmc-0.1.2/PKG-INFO
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: bindmc
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Keywords: chemistry,analytical chemistry,binding constants,supramolecular
|
|
5
|
+
Author: Martin Peeks
|
|
6
|
+
Author-email: Martin Peeks <martinp23@googlemail.com>, m.peeks@unsw.edu.au
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Science/Research
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
14
|
+
Requires-Dist: arviz==0.21.0
|
|
15
|
+
Requires-Dist: bindtools>=0.1.0
|
|
16
|
+
Requires-Dist: corner==2.2.3
|
|
17
|
+
Requires-Dist: emcee==3.1.6
|
|
18
|
+
Requires-Dist: h5py==3.13.0
|
|
19
|
+
Requires-Dist: latex2mathml>=3.0.0
|
|
20
|
+
Requires-Dist: lmfit==1.3.3
|
|
21
|
+
Requires-Dist: matplotlib==3.10.7
|
|
22
|
+
Requires-Dist: nicegui[plotly]==3.3.1
|
|
23
|
+
Requires-Dist: numba>=0.65.1
|
|
24
|
+
Requires-Dist: numpy>=2.3.5
|
|
25
|
+
Requires-Dist: openpyxl==3.1.2
|
|
26
|
+
Requires-Dist: pandas>=2.3.3
|
|
27
|
+
Requires-Dist: platformdirs>=3.0.0
|
|
28
|
+
Requires-Dist: pywebview>=5
|
|
29
|
+
Requires-Dist: scipy==1.16.3
|
|
30
|
+
Requires-Dist: tqdm==4.66.3
|
|
31
|
+
Requires-Dist: uncertainties==3.2.3
|
|
32
|
+
Requires-Python: >=3.12
|
|
33
|
+
Project-URL: Homepage, https://github.com/martinp23/bindmc
|
|
34
|
+
Project-URL: Documentation, https://readthedocs.org
|
|
35
|
+
Project-URL: Repository, https://github.com/martinp23/bindmc.git
|
|
36
|
+
Project-URL: Issues, https://github.com/martinp23/bindmc/issues
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# bindmc
|
|
40
|
+
|
|
41
|
+
[](https://badge.fury.io/py/bindtools)
|
|
42
|
+
[](https://pypi.org/project/bindtools/)
|
|
43
|
+
|
|
44
|
+
`bindmc` is a tool for calculating binding constants, built on top of [bindtools](https://github.com/martinp23/bindtools).
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
### Pre-built Binary
|
|
49
|
+
Download the latest executable for your platform from the [Releases](https://github.com/martinp23/bindmc/releases) page.
|
|
50
|
+
|
|
51
|
+
### Pip
|
|
52
|
+
```bash
|
|
53
|
+
pip install bindmc
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
If using the pre-built binary, run the downloaded executable.
|
|
59
|
+
|
|
60
|
+
If installed via pip, run:
|
|
61
|
+
```bash
|
|
62
|
+
python -m bindmc
|
|
63
|
+
```
|
bindmc-0.1.2/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# bindmc
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/bindtools)
|
|
4
|
+
[](https://pypi.org/project/bindtools/)
|
|
5
|
+
|
|
6
|
+
`bindmc` is a tool for calculating binding constants, built on top of [bindtools](https://github.com/martinp23/bindtools).
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
### Pre-built Binary
|
|
11
|
+
Download the latest executable for your platform from the [Releases](https://github.com/martinp23/bindmc/releases) page.
|
|
12
|
+
|
|
13
|
+
### Pip
|
|
14
|
+
```bash
|
|
15
|
+
pip install bindmc
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
If using the pre-built binary, run the downloaded executable.
|
|
21
|
+
|
|
22
|
+
If installed via pip, run:
|
|
23
|
+
```bash
|
|
24
|
+
python -m bindmc
|
|
25
|
+
```
|
|
@@ -1,6 +1,30 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
1
5
|
[project]
|
|
2
6
|
name = "bindmc"
|
|
3
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
keywords = ["chemistry", "analytical chemistry", "binding constants", "supramolecular"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
# How mature is this project? Common values are
|
|
12
|
+
# 3 - Alpha
|
|
13
|
+
# 4 - Beta
|
|
14
|
+
# 5 - Production/Stable
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
|
|
17
|
+
# Indicate who your project is intended for
|
|
18
|
+
"Intended Audience :: Science/Research",
|
|
19
|
+
|
|
20
|
+
# Specify the Python versions you support here.
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
24
|
+
|
|
25
|
+
"Topic :: Scientific/Engineering :: Chemistry",
|
|
26
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
27
|
+
]
|
|
4
28
|
requires-python = ">=3.12"
|
|
5
29
|
dependencies = [
|
|
6
30
|
"arviz==0.21.0",
|
|
@@ -23,6 +47,17 @@ dependencies = [
|
|
|
23
47
|
"uncertainties==3.2.3",
|
|
24
48
|
]
|
|
25
49
|
|
|
50
|
+
authors = [
|
|
51
|
+
{name = "Martin Peeks", email = "martinp23@googlemail.com"},
|
|
52
|
+
{email = "m.peeks@unsw.edu.au"},
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[project.urls]
|
|
56
|
+
Homepage = "https://github.com/martinp23/bindmc"
|
|
57
|
+
Documentation = "https://readthedocs.org"
|
|
58
|
+
Repository = "https://github.com/martinp23/bindmc.git"
|
|
59
|
+
Issues = "https://github.com/martinp23/bindmc/issues"
|
|
60
|
+
|
|
26
61
|
[tool.uv.sources]
|
|
27
62
|
bindtools = { path = "./bindtools", editable = true }
|
|
28
63
|
|
|
@@ -107,4 +142,7 @@ docstring-code-line-length = "dynamic"
|
|
|
107
142
|
dev = [
|
|
108
143
|
"pyinstaller>=6.21.0",
|
|
109
144
|
"pytest>=9.1.0",
|
|
145
|
+
"pytest-asyncio>=1.4.0",
|
|
146
|
+
"ruff>=0.15.17",
|
|
147
|
+
"selenium>=4.44.0",
|
|
110
148
|
]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# to build: rm -fr build && rm -fr dist && nicegui-pack --onefile --add-data "C:\Users\mpeeks\miniforge3\envs\binding-nicegui\Lib\site-packages\arviz\static;arviz/static" --add-data "C:\Users\mpeeks\miniforge3\envs\binding-nicegui\Lib\site-packages\arviz\data;arviz/data" --add-data "C:\Users\mpeeks\miniforge3\envs\binding-nicegui\Lib\site-packages\latex2mathml\unimathsymbols.txt;latex2mathml" main.py
|
|
2
|
+
|
|
3
|
+
# on windows:
|
|
4
|
+
# nicegui-pack main.py --no-build
|
|
5
|
+
|
|
6
|
+
# macOS packaging support
|
|
7
|
+
from multiprocessing import freeze_support # noqa
|
|
8
|
+
|
|
9
|
+
freeze_support() # noqa
|
|
10
|
+
|
|
11
|
+
# hidden import for pyinstaller
|
|
12
|
+
import matplotlib
|
|
13
|
+
|
|
14
|
+
matplotlib.use("module://matplotlib.backends.backend_svg")
|
|
15
|
+
import sys
|
|
16
|
+
from nicegui import native, ui, app
|
|
17
|
+
from bindmc.webgui.app import BindMCServer
|
|
18
|
+
import logging
|
|
19
|
+
import nicegui
|
|
20
|
+
from packaging.version import InvalidVersion, Version
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from platformdirs import user_data_dir
|
|
23
|
+
from importlib.metadata import version
|
|
24
|
+
|
|
25
|
+
__version__ = version("bindmc")
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
nicegui_version = Version(nicegui.__version__)
|
|
31
|
+
except InvalidVersion:
|
|
32
|
+
logger.warning(
|
|
33
|
+
"Could not parse NiceGUI version '%s'; continuing, but NiceGUI >= 3 is required.",
|
|
34
|
+
nicegui.__version__,
|
|
35
|
+
)
|
|
36
|
+
else:
|
|
37
|
+
if nicegui_version.is_prerelease or nicegui_version.is_devrelease:
|
|
38
|
+
logger.warning(
|
|
39
|
+
"NiceGUI %s is a pre-release/dev build; recommended to install the latest stable 3.x.",
|
|
40
|
+
nicegui.__version__,
|
|
41
|
+
)
|
|
42
|
+
elif nicegui_version.major < 3:
|
|
43
|
+
raise RuntimeError(f"NiceGUI >= 3 is required; found {nicegui.__version__}")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
app.native.settings["ALLOW_DOWNLOADS"] = True
|
|
47
|
+
|
|
48
|
+
# logging.basicConfig(level=logging.INFO, filename='BindMC.log')
|
|
49
|
+
logging.basicConfig(level=logging.INFO, format="%(levelname)s:%(message)s")
|
|
50
|
+
|
|
51
|
+
logger.info(f"Starting BindMC {__version__} NiceGUI server...")
|
|
52
|
+
BindMCServer()
|
|
53
|
+
|
|
54
|
+
# Set DEV based on whether running from PyInstaller bundle
|
|
55
|
+
DEV = not getattr(sys, "frozen", False)
|
|
56
|
+
|
|
57
|
+
if DEV:
|
|
58
|
+
native_mode = False
|
|
59
|
+
reload = True
|
|
60
|
+
else:
|
|
61
|
+
native_mode = True
|
|
62
|
+
reload = False
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# make a sensible storage path for native mode
|
|
66
|
+
storage_path = Path(user_data_dir(appname="BindMC", appauthor=False))
|
|
67
|
+
storage_path.mkdir(parents=True, exist_ok=True)
|
|
68
|
+
|
|
69
|
+
# Redirect native window persistence data away from default paths
|
|
70
|
+
app.native.start_args["storage_path"] = str(storage_path)
|
|
71
|
+
|
|
72
|
+
ui.run(title="BindMC", reload=reload, native=native_mode, port=native.find_open_port(), storage_secret="bindmc_secret")
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Class model
|
|
2
|
+
|
|
3
|
+
- UIState
|
|
4
|
+
- This class contains the current state of the user interface, so includes:
|
|
5
|
+
- list of Models and index of active Model
|
|
6
|
+
- List of simulations and field values from latest/active simulation
|
|
7
|
+
- Graph state
|
|
8
|
+
- component details
|
|
9
|
+
|
|
10
|
+
- Simulation
|
|
11
|
+
- A simulation comprises:
|
|
12
|
+
- A Model
|
|
13
|
+
- A set of parameters
|
|
14
|
+
- Input data (i.e. components)
|
|
15
|
+
- Output data (i.e. species concentrations)
|
|
16
|
+
- A name or timestamp or other unique(?) slug
|
|
17
|
+
- An optional comment
|
|
18
|
+
|
|
19
|
+
- Model
|
|
20
|
+
- Comprises
|
|
21
|
+
- A name (unique among all models in the UIState)
|
|
22
|
+
- An optional comment
|
|
23
|
+
- The string entered into the eqStr input box
|
|
24
|
+
- The parsed equation matrix as a list of lists (np.array)
|
|
25
|
+
- (A function that returns a list of BindingConstant parameters?)
|
|
26
|
+
- A list of species
|
|
27
|
+
- A list of components
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# BindMC WebGUI Release Checklist
|
|
2
|
+
|
|
3
|
+
Use this as the source of truth for shipping readiness.
|
|
4
|
+
|
|
5
|
+
Legend:
|
|
6
|
+
- `Priority`: `P0` (must ship), `P1` (should ship), `P2` (hardening)
|
|
7
|
+
- `Effort`: `S`, `M`, `L`
|
|
8
|
+
- `Owner`: set to initials or role (`@unassigned` until assigned)
|
|
9
|
+
|
|
10
|
+
## P0 - Must Ship
|
|
11
|
+
|
|
12
|
+
- [ ] Streamline analytical methods in bindtools package binding.py
|
|
13
|
+
|
|
14
|
+
- Check obs_list is right in tests/elsewhere, and/or check "uvvis" vs "absorbance" dtype
|
|
15
|
+
- Add timing trial done/starting real run popups
|
|
16
|
+
- Dark species do not appear in fit and mcmc any mroe - check obslist change!
|
|
17
|
+
- [ ] Fix fit graph mismatch when only subset of dependent variables are fitted.
|
|
18
|
+
- Owner: `@unassigned`
|
|
19
|
+
- Effort: `M`
|
|
20
|
+
- Files: `webgui/components/fitting.py`, `webgui/components/graph.py`
|
|
21
|
+
|
|
22
|
+
- [X] Make active object handling robust after delete/change (model, data, fit, sim).
|
|
23
|
+
- Owner: `@unassigned`
|
|
24
|
+
- Effort: `M`
|
|
25
|
+
- Files: `webgui/state/statemanager.py`
|
|
26
|
+
|
|
27
|
+
- [ ] Implement explicit expt data load/select/delete workflow in UI.
|
|
28
|
+
- Owner: `@unassigned`
|
|
29
|
+
- Effort: `M`
|
|
30
|
+
- Files: `webgui/components/data_import.py`, `webgui/components/body.py`, `webgui/state/statemanager.py`
|
|
31
|
+
|
|
32
|
+
- [ ] Add strict validation + actionable inline errors for data-model mapping (col->comp, integ->spec, fast-exchange).
|
|
33
|
+
- Owner: `@unassigned`
|
|
34
|
+
- Effort: `L`
|
|
35
|
+
- Files: `webgui/components/data_model.py`, `webgui/classes/ExptData.py`
|
|
36
|
+
|
|
37
|
+
- [X] Sanitize chemical-shift parameter names (spaces/special chars) before lmfit parameter creation.
|
|
38
|
+
- Owner: `@unassigned`
|
|
39
|
+
- Effort: `S`
|
|
40
|
+
- Files: `webgui/classes/ExptData.py`
|
|
41
|
+
|
|
42
|
+
- [ ] Apply consistent long-task UI state handling (disable/re-enable buttons + spinner + no double-submit).
|
|
43
|
+
- Owner: `@unassigned`
|
|
44
|
+
- Effort: `M`
|
|
45
|
+
- Files: `webgui/components/simulation.py`, `webgui/components/fitting.py`, `webgui/components/data_import.py`
|
|
46
|
+
|
|
47
|
+
- [ ] Add destructive action confirmations and unsaved-change protection.
|
|
48
|
+
- Owner: `@unassigned`
|
|
49
|
+
- Effort: `M`
|
|
50
|
+
- Files: `webgui/components/header.py`, `webgui/state/statemanager.py`, relevant panel files
|
|
51
|
+
|
|
52
|
+
- [X] Fix disabled-tab guidance so reason is always visible and correct.
|
|
53
|
+
- Owner: `@unassigned`
|
|
54
|
+
- Effort: `S`
|
|
55
|
+
- Files: `webgui/components/body.py`
|
|
56
|
+
|
|
57
|
+
## P1 - Should Ship
|
|
58
|
+
|
|
59
|
+
- [ ] UI polish pass (spacing, naming consistency, remove placeholder text, responsive fit/focus).
|
|
60
|
+
- Owner: `@unassigned`
|
|
61
|
+
- Effort: `M`
|
|
62
|
+
- Files: `webgui/components/*.py`
|
|
63
|
+
|
|
64
|
+
- [ ] Add raw-data quick plot/preview during import to validate selected columns.
|
|
65
|
+
- Owner: `@unassigned`
|
|
66
|
+
- Effort: `M`
|
|
67
|
+
- Files: `webgui/components/data_import.py`, `webgui/components/graph.py`
|
|
68
|
+
|
|
69
|
+
- [ ] Complete graph export UX (PNG options/resolution, fit/sim parity, clear labels).
|
|
70
|
+
- Owner: `@unassigned`
|
|
71
|
+
- Effort: `S`
|
|
72
|
+
- Files: `webgui/components/fitting.py`, `webgui/components/simulation.py`
|
|
73
|
+
|
|
74
|
+
- [ ] Persist graph view preferences (x-axis, ratio, legend visibility) across reload.
|
|
75
|
+
- Owner: `@unassigned`
|
|
76
|
+
- Effort: `M`
|
|
77
|
+
- Files: `webgui/components/graph.py`, `webgui/state/statemanager.py`
|
|
78
|
+
|
|
79
|
+
- [ ] Replace broad `except Exception` with specific exceptions + targeted user notifications.
|
|
80
|
+
- Owner: `@unassigned`
|
|
81
|
+
- Effort: `M`
|
|
82
|
+
- Files: multiple `webgui/components/*.py`, `webgui/state/statemanager.py`
|
|
83
|
+
|
|
84
|
+
- [ ] Replace remaining `print` calls with structured logging.
|
|
85
|
+
- Owner: `@unassigned`
|
|
86
|
+
- Effort: `S`
|
|
87
|
+
- Files: multiple `webgui/**/*.py`
|
|
88
|
+
|
|
89
|
+
- [ ] Improve first-run empty states and inline guidance for main workflows.
|
|
90
|
+
- Owner: `@unassigned`
|
|
91
|
+
- Effort: `M`
|
|
92
|
+
- Files: `webgui/components/body.py`, panel files
|
|
93
|
+
|
|
94
|
+
## P2 - Hardening
|
|
95
|
+
|
|
96
|
+
- [ ] Add end-to-end test for fit workflow including CSV/PNG export.
|
|
97
|
+
- Owner: `@unassigned`
|
|
98
|
+
- Effort: `L`
|
|
99
|
+
- Files: `tests/`
|
|
100
|
+
|
|
101
|
+
- [ ] Add regression tests for cascade deletion and active-ID reassignment.
|
|
102
|
+
- Owner: `@unassigned`
|
|
103
|
+
- Effort: `M`
|
|
104
|
+
- Files: `tests/`, `webgui/state/statemanager.py`
|
|
105
|
+
|
|
106
|
+
- [ ] Add serialization round-trip tests for fast-exchange (`delta_to_spec`, `limiting_shifts`).
|
|
107
|
+
- Owner: `@unassigned`
|
|
108
|
+
- Effort: `M`
|
|
109
|
+
- Files: `tests/`, `webgui/classes/ExptData.py`
|
|
110
|
+
|
|
111
|
+
- [ ] Create packaging smoke-test checklist (platform launch, downloads, save/open, project import/export).
|
|
112
|
+
- Owner: `@unassigned`
|
|
113
|
+
- Effort: `S`
|
|
114
|
+
- Files: `docs/` (new release checklist doc)
|
|
115
|
+
|
|
116
|
+
- [ ] Add release process doc (version bump, changelog, sign-off criteria).
|
|
117
|
+
- Owner: `@unassigned`
|
|
118
|
+
- Effort: `S`
|
|
119
|
+
- Files: `docs/` (new release process doc)
|
|
120
|
+
|
|
121
|
+
## Post-Ship Backlog
|
|
122
|
+
|
|
123
|
+
- [ ] Complete MCMC analysis workflow.
|
|
124
|
+
- Owner: `@unassigned`
|
|
125
|
+
- Effort: `L`
|
|
126
|
+
|
|
127
|
+
- [X] Add analytical-mode simulation support for simple 1:1/1:2/2:1 fast-exchange systems.
|
|
128
|
+
- Owner: `@unassigned`
|
|
129
|
+
- Effort: `M`
|
|
130
|
+
- Note: Until this ships, point users to supramolecular.org for these simulations.
|
|
131
|
+
|
|
132
|
+
- [ ] Add graph log-scale options and richer plot controls.
|
|
133
|
+
- Owner: `@unassigned`
|
|
134
|
+
- Effort: `M`
|
|
135
|
+
|
|
136
|
+
- [ ] Improve model comments/metadata editing UX.
|
|
137
|
+
- Owner: `@unassigned`
|
|
138
|
+
- Effort: `S`
|
|
139
|
+
|
|
140
|
+
## Legacy Notes (Untriaged)
|
|
141
|
+
|
|
142
|
+
Carried forward from the previous TODO for reference:
|
|
143
|
+
|
|
144
|
+
- Enable choosing of graph elements:
|
|
145
|
+
- What should be y-axis? Plot all species ideally
|
|
146
|
+
- allow comments alongside equilibria
|
|
147
|
+
- graphs - y/x log options
|
|
148
|
+
- fast exchange work
|
|
149
|
+
- add refresh-bindings as in model tab to other tabs
|
|
150
|
+
- precompile numba (part done)
|
|
151
|
+
|
|
152
|
+
## Sprint-Ready Breakdown (Top 3 P0)
|
|
153
|
+
|
|
154
|
+
### A) Fix fit graph mismatch for partially fitted dependent variables
|
|
155
|
+
|
|
156
|
+
- [ ] A1. Reproduce and lock down failing scenario with test data containing multiple dependent columns where only a subset is fitted.
|
|
157
|
+
- Owner: `@unassigned`
|
|
158
|
+
- Effort: `S`
|
|
159
|
+
|
|
160
|
+
- [ ] A2. Ensure graph plotting uses only columns present in `fit.calc_obs` and aligned index lengths.
|
|
161
|
+
- Owner: `@unassigned`
|
|
162
|
+
- Effort: `S`
|
|
163
|
+
- Files: `webgui/components/fitting.py`, `webgui/components/graph.py`
|
|
164
|
+
|
|
165
|
+
- [ ] A3. Add guardrail notifications when expected columns are missing, without crashing render.
|
|
166
|
+
- Owner: `@unassigned`
|
|
167
|
+
- Effort: `S`
|
|
168
|
+
- Files: `webgui/components/fitting.py`
|
|
169
|
+
|
|
170
|
+
- [ ] A4. Add regression test for fit graph rendering with partial dependent-variable fitting.
|
|
171
|
+
- Owner: `@unassigned`
|
|
172
|
+
- Effort: `M`
|
|
173
|
+
- Files: `tests/`
|
|
174
|
+
|
|
175
|
+
Acceptance criteria:
|
|
176
|
+
- Fit results tab renders both experimental markers and calculated lines with no exceptions when only subset of dependent variables is fitted.
|
|
177
|
+
- No mismatch warnings/errors appear for valid partial-fit cases.
|
|
178
|
+
- Regression test fails on old behavior and passes on fix.
|
|
179
|
+
|
|
180
|
+
### B) Make active-object handling robust after delete/change (model/data/fit/sim)
|
|
181
|
+
|
|
182
|
+
- [ ] B1. Audit all delete/change paths to identify where active IDs may become stale.
|
|
183
|
+
- Owner: `@unassigned`
|
|
184
|
+
- Effort: `S`
|
|
185
|
+
- Files: `webgui/state/statemanager.py`, `webgui/components/*.py`
|
|
186
|
+
|
|
187
|
+
- [ ] B2. Implement centralized helper(s) in `StateManager` to set safe fallback active IDs after deletion.
|
|
188
|
+
- Owner: `@unassigned`
|
|
189
|
+
- Effort: `M`
|
|
190
|
+
- Files: `webgui/state/statemanager.py`
|
|
191
|
+
|
|
192
|
+
- [ ] B3. Replace scattered manual active-ID patching in components with calls to the centralized helper.
|
|
193
|
+
- Owner: `@unassigned`
|
|
194
|
+
- Effort: `M`
|
|
195
|
+
- Files: `webgui/components/simulation.py`, `webgui/components/fitting.py`, others as needed
|
|
196
|
+
|
|
197
|
+
- [ ] B4. Add tests for cascade delete and active object reassignment across model/data/fit/sim.
|
|
198
|
+
- Owner: `@unassigned`
|
|
199
|
+
- Effort: `M`
|
|
200
|
+
- Files: `tests/`, `webgui/state/statemanager.py`
|
|
201
|
+
|
|
202
|
+
Acceptance criteria:
|
|
203
|
+
- After any delete/change action, all active IDs are either valid existing IDs or `None`.
|
|
204
|
+
- UI header and relevant panels refresh without exceptions after deletions.
|
|
205
|
+
- Cascade deletion behavior is deterministic and covered by tests.
|
|
206
|
+
|
|
207
|
+
### C) Implement explicit expt data load/select/delete workflow
|
|
208
|
+
|
|
209
|
+
- [ ] C1. Add expt-data selector UI with active-item indicator and load action.
|
|
210
|
+
- Owner: `@unassigned`
|
|
211
|
+
- Effort: `M`
|
|
212
|
+
- Files: `webgui/components/data_import.py`
|
|
213
|
+
|
|
214
|
+
- [ ] C2. Add expt-data delete action with confirmation dialog and post-delete fallback selection logic.
|
|
215
|
+
- Owner: `@unassigned`
|
|
216
|
+
- Effort: `M`
|
|
217
|
+
- Files: `webgui/components/data_import.py`, `webgui/state/statemanager.py`
|
|
218
|
+
|
|
219
|
+
- [ ] C3. Emit and consume consistent `expt_data_changed` notifications so dependent panels refresh correctly.
|
|
220
|
+
- Owner: `@unassigned`
|
|
221
|
+
- Effort: `S`
|
|
222
|
+
- Files: `webgui/state/statemanager.py`, `webgui/components/body.py`, `webgui/components/header.py`, `webgui/components/data_model.py`, `webgui/components/fitting.py`
|
|
223
|
+
|
|
224
|
+
- [ ] C4. Add tests for selecting, loading, deleting multiple expt datasets and preserving app stability.
|
|
225
|
+
- Owner: `@unassigned`
|
|
226
|
+
- Effort: `M`
|
|
227
|
+
- Files: `tests/`
|
|
228
|
+
|
|
229
|
+
Acceptance criteria:
|
|
230
|
+
- User can select among multiple expt datasets, and active dataset is clearly shown.
|
|
231
|
+
- Deleting active expt dataset selects a valid fallback (or `None`) without stale references.
|
|
232
|
+
- Data Model and Fit panels always reflect the currently active expt dataset.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
TODO
|
|
2
|
+
|
|
3
|
+
- Enable choosing of graph elements:
|
|
4
|
+
- What should be y-axis? Plot all species ideally
|
|
5
|
+
----- see also https://community.plotly.com/t/possible-to-have-nested-or-hierarchical-legends/2376/8 for potential way to toggle species vs group
|
|
6
|
+
- Fix GUI grossness
|
|
7
|
+
|
|
8
|
+
model.py:
|
|
9
|
+
overwrite model should delete all fits and simulations associated with it, and then clean up all orphaned expt_data.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
- if chemical shift column has spaces in it then parameters are given invalid names. need to sanitize or just call them delta1, delta2, etc.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
allow comments alongside equilibria
|
|
18
|
+
graphs - y/x log options
|
|
19
|
+
|
|
20
|
+
cannot have tooltip on a disabled element; would need to wrap it in a ui.element() and set tooltip on that. body.py:164
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
- if there are many dep variables but we do not fit them all, the fit graph does not work because m1.obslist (len(dep vars)) != fit.calc_obs (which ignores unfitted dep vars e.g. chemical shifts)
|
|
24
|
+
|
|
25
|
+
- multiple expdatas -- need to implement load_data, delete_data
|
|
26
|
+
- check effect of changing a model on exptdata - it should be fine. but maybe we need to work in dict/uuids rather than indices. we should 'invalidate' expt_data when model changed but not necessarily delete it.
|
|
27
|
+
- fast exchange :'(
|
|
28
|
+
|
|
29
|
+
- statemanager, sim/fit deletions
|
|
30
|
+
--- make sure that they always adjust the active_sim properly
|
|
31
|
+
--- in the fit box, bind the inputs like in simulations (easy)
|
|
32
|
+
|
|
33
|
+
- quick data plotting for raw data
|
|
34
|
+
- saving calc data?
|
|
35
|
+
- saving graphs?
|
|
36
|
+
- save plots/data to png/pdf and csv
|
|
37
|
+
|
|
38
|
+
- mcmc
|
|
39
|
+
- allow expt_data selection on data page
|
|
40
|
+
- auto-title for fits
|
|
41
|
+
- check whether hasattr(..., "active_...") works as expected/is a good idea. probably not, because attr exists since it is a getter... we really want to be checking whether the value is None (or whatever the default is).
|
|
42
|
+
- add refresh-bindings as in model tab to other tabs.
|
|
43
|
+
|
|
44
|
+
- precompile numba (part done; do better)
|
|
45
|
+
- plot fit vs expt observables (not just speciation)
|
|
46
|
+
|
|
47
|
+
- chemical shifts/fast exchange
|
|
48
|
+
- fit graph seems to show lines from sim graph?
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
DONE:
|
|
54
|
+
component concs for simulation - also allow edits maybe to a preformed table (or upload csv!)
|
|
55
|
+
- automatically plot sim/fit results against a concentration that changes, not against H
|
|
56
|
+
- overall it might be better to not have a default model.... -- actually how about a selection of fixed default models, e.g. 1:1, 2:1, 1:2.
|
|
57
|
+
- add packaging code, make it easily distributable
|
|
58
|
+
- annoying problem that components on LHS of equation is different to order of components in a species on RHS
|
|
59
|
+
- indicator to header
|
|
60
|
+
- make data dep/indep into radio buttons
|
|
61
|
+
- overwrite model should prompt to save as.
|
|
62
|
+
- show fit results (and parameters), somehow
|
|
63
|
+
- remove "s" from delete dropdowns
|
|
64
|
+
- Read binding constants from controls
|
|
65
|
+
- Add a spinning wheel to indicate processing
|
|
66
|
+
- Replace graph e.g. with a plotly graph
|
|
67
|
+
- Ability to overlay multiple different models?
|
|
68
|
+
- Model name should give a clue as to its use in the plot (e.g. encourage user to give a descriptive name).
|
|
69
|
+
- Model name should be used as legend title.
|
|
70
|
+
- Enable selection of graph elements:
|
|
71
|
+
- What should be x-axis? Any component, species, or ratio thereof.
|
|
72
|
+
- What should be y-axis? Plot all species ideally
|
|
73
|
+
----- maybe give an option to disable plotting of [comp]_free.
|
|
74
|
+
----- use grouped legend <--- sadly, for now, this seems to make it impossible to toggle off single traces. :(
|
|
75
|
+
- Do we remember line visibility? NO. we should.
|
|
76
|
+
- default x-axis should be first varying component, notjust first component
|
|
77
|
+
- When a simulation is run with one conc range, then more steps in the same conc range are added, the graph currently seems to show the original data (first simulation) on an incorrect x-axis.
|
|
78
|
+
- Download and upload project
|
|
79
|
+
- if model name is blah, then ask if we should overwrite results
|
|
80
|
+
- Model persistence: on simulation, save model params results to session state.
|
|
81
|
+
- Load and edit models (dropdown? + button).
|
|
82
|
+
- so we should begin by instantiating a model with empty parameters and bind to/edit that.
|
|
83
|
+
- needs some architecture changes:
|
|
84
|
+
- model class
|
|
85
|
+
- sd.currmodel (property? or int index?)
|
|
86
|
+
- sd.models (list of models)
|
|
87
|
+
- Delete models.
|
|
88
|
+
- fix a bug where it seems like we cannot change the x-axis if "do not plot [comp]_free" is selected.
|
|
89
|
+
- plot loaded fit data (need to deal with compconcs sensibly -- re-calc via an expt_data_to_comp_concs function?)
|
|
@@ -1,54 +1,50 @@
|
|
|
1
1
|
from nicegui import ui
|
|
2
2
|
|
|
3
|
-
from .components import
|
|
4
|
-
BindToolsHeader,
|
|
5
|
-
Body
|
|
6
|
-
)
|
|
3
|
+
from .components import BindMCHeader, Body
|
|
7
4
|
from .state.statemanager import StateManager
|
|
8
5
|
|
|
9
|
-
class BindToolsServer:
|
|
10
6
|
|
|
7
|
+
class BindMCServer:
|
|
11
8
|
def __init__(self):
|
|
12
9
|
|
|
13
10
|
self.state_manager: StateManager = StateManager(load_prior_state=False) # Initialize state_manager attribute
|
|
14
|
-
self.sm: StateManager =self.state_manager
|
|
11
|
+
self.sm: StateManager = self.state_manager
|
|
15
12
|
self.components = {}
|
|
16
|
-
self.body_components={}
|
|
13
|
+
self.body_components = {}
|
|
17
14
|
self.tabs = {}
|
|
18
15
|
self.setup_routes()
|
|
19
16
|
|
|
20
|
-
|
|
21
17
|
def setup_routes(self):
|
|
22
18
|
"""Set up the application routes and UI components."""
|
|
23
19
|
|
|
24
20
|
@ui.page("/")
|
|
25
|
-
|
|
26
|
-
def index():
|
|
21
|
+
def index():
|
|
27
22
|
self.state_manager = StateManager()
|
|
28
23
|
self.sm = self.state_manager # alias
|
|
29
24
|
self._generate_header()
|
|
30
25
|
self._generate_body()
|
|
31
26
|
self.body_components = self.components["body"].components
|
|
32
27
|
self._load_prior_state()
|
|
33
|
-
|
|
34
|
-
|
|
35
28
|
|
|
36
29
|
def _load_prior_state(self):
|
|
37
30
|
# if simulations have been run already, populate the graph
|
|
38
31
|
if len(self.sm.simulations) > 0:
|
|
39
32
|
self.body_components["simulation"].graph.load_simulations_data()
|
|
40
|
-
if
|
|
33
|
+
if (
|
|
34
|
+
self.sm.active_expt_data_id is not None
|
|
35
|
+
and self.sm.active_expt_data.data is not None
|
|
36
|
+
and not self.sm.active_expt_data.data.empty
|
|
37
|
+
):
|
|
41
38
|
self.sm.notify_listeners("data_imported")
|
|
42
39
|
if len(self.sm.fits) > 0:
|
|
43
40
|
self.sm.notify_listeners("fits_loaded")
|
|
44
41
|
# self.components["fit_results"].sync_graphs()
|
|
45
42
|
# self.components["fit_results"].generate_delete_fit_dropdown()
|
|
46
43
|
|
|
47
|
-
|
|
48
44
|
def _generate_header(self):
|
|
49
|
-
ui.colors(primary=
|
|
45
|
+
ui.colors(primary="#000000", secondary="grey-5", accent="blue-grey-5")
|
|
50
46
|
|
|
51
|
-
self.components["header"] =
|
|
47
|
+
self.components["header"] = BindMCHeader(state_manager=self.state_manager)
|
|
52
48
|
|
|
53
49
|
def _generate_body(self):
|
|
54
|
-
self.components["body"]= Body(self.state_manager)
|
|
50
|
+
self.components["body"] = Body(self.state_manager)
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
from
|
|
3
|
-
|
|
4
|
-
import unicodedata
|
|
5
|
-
from nicegui import binding
|
|
6
|
-
import numpy as np
|
|
7
|
-
import pandas as pd
|
|
8
|
-
from lmfit import Parameter as LMFitParameter
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
9
4
|
|
|
10
5
|
@dataclass
|
|
11
6
|
class BindingConstant:
|
|
@@ -19,5 +14,3 @@ class BindingConstant:
|
|
|
19
14
|
@property
|
|
20
15
|
def name(self) -> str:
|
|
21
16
|
return self.species
|
|
22
|
-
|
|
23
|
-
|