kbkit 1.0.15__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 (54) hide show
  1. kbkit-1.0.15/.gitignore +182 -0
  2. kbkit-1.0.15/LICENSE +21 -0
  3. kbkit-1.0.15/PKG-INFO +250 -0
  4. kbkit-1.0.15/README.md +189 -0
  5. kbkit-1.0.15/pyproject.toml +114 -0
  6. kbkit-1.0.15/src/kbkit/__init__.py +6 -0
  7. kbkit-1.0.15/src/kbkit/_version.py +1 -0
  8. kbkit-1.0.15/src/kbkit/analysis/__init__.py +7 -0
  9. kbkit-1.0.15/src/kbkit/analysis/calculator.py +303 -0
  10. kbkit-1.0.15/src/kbkit/analysis/integrator.py +464 -0
  11. kbkit-1.0.15/src/kbkit/analysis/thermo.py +959 -0
  12. kbkit-1.0.15/src/kbkit/config/__init__.py +6 -0
  13. kbkit-1.0.15/src/kbkit/config/mplstyle.py +18 -0
  14. kbkit-1.0.15/src/kbkit/config/presentation.mplstyle +48 -0
  15. kbkit-1.0.15/src/kbkit/config/unit_registry.py +82 -0
  16. kbkit-1.0.15/src/kbkit/data/__init__.py +5 -0
  17. kbkit-1.0.15/src/kbkit/data/gmx_units.json +13 -0
  18. kbkit-1.0.15/src/kbkit/data/property_resolver.py +102 -0
  19. kbkit-1.0.15/src/kbkit/parsers/__init__.py +8 -0
  20. kbkit-1.0.15/src/kbkit/parsers/edr_file.py +316 -0
  21. kbkit-1.0.15/src/kbkit/parsers/gro_file.py +96 -0
  22. kbkit-1.0.15/src/kbkit/parsers/rdf_file.py +255 -0
  23. kbkit-1.0.15/src/kbkit/parsers/top_file.py +138 -0
  24. kbkit-1.0.15/src/kbkit/schema/kbi_metadata.py +28 -0
  25. kbkit-1.0.15/src/kbkit/schema/plot_spec.py +40 -0
  26. kbkit-1.0.15/src/kbkit/schema/system_config.py +34 -0
  27. kbkit-1.0.15/src/kbkit/schema/system_metadata.py +51 -0
  28. kbkit-1.0.15/src/kbkit/schema/thermo_property.py +59 -0
  29. kbkit-1.0.15/src/kbkit/schema/thermo_state.py +46 -0
  30. kbkit-1.0.15/src/kbkit/systems/__init__.py +8 -0
  31. kbkit-1.0.15/src/kbkit/systems/loader.py +359 -0
  32. kbkit-1.0.15/src/kbkit/systems/properties.py +276 -0
  33. kbkit-1.0.15/src/kbkit/systems/registry.py +126 -0
  34. kbkit-1.0.15/src/kbkit/systems/state.py +544 -0
  35. kbkit-1.0.15/src/kbkit/utils/__init__.py +5 -0
  36. kbkit-1.0.15/src/kbkit/utils/chem.py +53 -0
  37. kbkit-1.0.15/src/kbkit/utils/file_resolver.py +125 -0
  38. kbkit-1.0.15/src/kbkit/utils/format.py +82 -0
  39. kbkit-1.0.15/src/kbkit/utils/io.py +54 -0
  40. kbkit-1.0.15/src/kbkit/utils/logging.py +35 -0
  41. kbkit-1.0.15/src/kbkit/utils/validation.py +61 -0
  42. kbkit-1.0.15/src/kbkit/workflow/__init__.py +6 -0
  43. kbkit-1.0.15/src/kbkit/workflow/pipeline.py +298 -0
  44. kbkit-1.0.15/src/kbkit/workflow/plotter.py +638 -0
  45. kbkit-1.0.15/tests/__init__.py +1 -0
  46. kbkit-1.0.15/tests/parsers/test_edrfile_parser.py +125 -0
  47. kbkit-1.0.15/tests/parsers/test_grofile_parser.py +121 -0
  48. kbkit-1.0.15/tests/parsers/test_rdf_parser.py +120 -0
  49. kbkit-1.0.15/tests/parsers/test_topfile_parser.py +83 -0
  50. kbkit-1.0.15/tests/systems/test_system_loader.py +197 -0
  51. kbkit-1.0.15/tests/systems/test_system_properties.py +204 -0
  52. kbkit-1.0.15/tests/systems/test_system_registry.py +136 -0
  53. kbkit-1.0.15/tests/test_smoke.py +21 -0
  54. kbkit-1.0.15/tests/utils/test_formatting_resolution.py +90 -0
@@ -0,0 +1,182 @@
1
+ # Created by https://www.toptal.com/developers/gitignore/api/python
2
+ # Edit at https://www.toptal.com/developers/gitignore?templates=python
3
+
4
+ ### Python ###
5
+ # Byte-compiled / optimized / DLL files
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+
10
+ # C extensions
11
+ *.so
12
+
13
+ # Distribution / packaging
14
+ .Python
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ .eggs/
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ sdist/
25
+ var/
26
+ wheels/
27
+ share/python-wheels/
28
+ *.egg-info/
29
+ .installed.cfg
30
+ *.egg
31
+ MANIFEST
32
+
33
+ # PyInstaller
34
+ # Usually these files are written by a python script from a template
35
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
36
+ *.manifest
37
+ *.spec
38
+
39
+ # Installer logs
40
+ pip-log.txt
41
+ pip-delete-this-directory.txt
42
+
43
+ # Unit test / coverage reports
44
+ htmlcov/
45
+ .tox/
46
+ .nox/
47
+ .coverage
48
+ .coverage.*
49
+ .cache
50
+ nosetests.xml
51
+ coverage.xml
52
+ *.cover
53
+ *.py,cover
54
+ .hypothesis/
55
+ .pytest_cache/
56
+ cover/
57
+ junit/
58
+ test-result*
59
+
60
+ # Translations
61
+ *.mo
62
+ *.pot
63
+
64
+ # Django stuff:
65
+ *.log
66
+ local_settings.py
67
+ db.sqlite3
68
+ db.sqlite3-journal
69
+
70
+ # Flask stuff:
71
+ instance/
72
+ .webassets-cache
73
+
74
+ # Scrapy stuff:
75
+ .scrapy
76
+
77
+ # Sphinx documentation
78
+ docs/_build/
79
+
80
+ # PyBuilder
81
+ .pybuilder/
82
+ target/
83
+
84
+ # Jupyter Notebook
85
+ .ipynb_checkpoints
86
+
87
+ # IPython
88
+ profile_default/
89
+ ipython_config.py
90
+
91
+ # pyenv
92
+ # For a library or package, you might want to ignore these files since the code is
93
+ # intended to run in multiple environments; otherwise, check them in:
94
+ # .python-version
95
+
96
+ # pipenv
97
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
98
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
99
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
100
+ # install all needed dependencies.
101
+ #Pipfile.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+
110
+ # pdm
111
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112
+ #pdm.lock
113
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114
+ # in version control.
115
+ # https://pdm.fming.dev/#use-with-ide
116
+ .pdm.toml
117
+
118
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
119
+ __pypackages__/
120
+
121
+ # Celery stuff
122
+ celerybeat-schedule
123
+ celerybeat.pid
124
+
125
+ # SageMath parsed files
126
+ *.sage.py
127
+
128
+ # Environments
129
+ .env
130
+ .venv
131
+ env/
132
+ venv/
133
+ ENV/
134
+ env.bak/
135
+ venv.bak/
136
+ .envrc
137
+
138
+ # Spyder project settings
139
+ .spyderproject
140
+ .spyproject
141
+
142
+ # Rope project settings
143
+ .ropeproject
144
+
145
+ # mkdocs documentation
146
+ /site
147
+
148
+ # mypy
149
+ .mypy_cache/
150
+ .dmypy.json
151
+ dmypy.json
152
+
153
+ # Pyre type checker
154
+ .pyre/
155
+
156
+ # pytype static type analyzer
157
+ .pytype/
158
+
159
+ # Cython debug symbols
160
+ cython_debug/
161
+
162
+ # PyCharm
163
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
164
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
165
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
166
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
167
+ #.idea/
168
+
169
+ ### Python Patch ###
170
+ # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
171
+ poetry.toml
172
+
173
+ # ruff
174
+ .ruff_cache/
175
+
176
+ # LSP config files
177
+ pyrightconfig.json
178
+
179
+ # End of https://www.toptal.com/developers/gitignore/api/python
180
+
181
+ # Pixi
182
+ .pixi
kbkit-1.0.15/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Allison Peroutka
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.
kbkit-1.0.15/PKG-INFO ADDED
@@ -0,0 +1,250 @@
1
+ Metadata-Version: 2.4
2
+ Name: kbkit
3
+ Version: 1.0.15
4
+ Summary: KBKit: Kirkwood-Buff Analysis Toolkit
5
+ Author: Allison Peroutka
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 Allison Peroutka
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ License-File: LICENSE
28
+ Requires-Python: >=3.10
29
+ Requires-Dist: babel<3,>=2.17.0
30
+ Requires-Dist: click<9,>=8.2.1
31
+ Requires-Dist: furo<2026,>=2025.7.19
32
+ Requires-Dist: gromacs<0.0.1,>=0.0.0
33
+ Requires-Dist: ipykernel<7,>=6.30.1
34
+ Requires-Dist: matplotlib<4,>=3.10.5
35
+ Requires-Dist: mdanalysis
36
+ Requires-Dist: mpltern<2,>=1.0.4
37
+ Requires-Dist: mypy
38
+ Requires-Dist: natsort<9,>=8.4.0
39
+ Requires-Dist: nbsphinx<0.10,>=0.9.6
40
+ Requires-Dist: numpy<3,>=2.3.2
41
+ Requires-Dist: pandas<3,>=2.3.1
42
+ Requires-Dist: pandoc<3,>=2.4
43
+ Requires-Dist: pathlib<2,>=1.0.1
44
+ Requires-Dist: pint<0.25
45
+ Requires-Dist: plotly<7,>=6.3.0
46
+ Requires-Dist: pytest-cov>=6.2.1
47
+ Requires-Dist: pytest>=8.4.1
48
+ Requires-Dist: rdkit<2026,>=2025.3.5
49
+ Requires-Dist: scipy<2,>=1.16.1
50
+ Requires-Dist: seaborn<0.14,>=0.13.2
51
+ Requires-Dist: sphinx
52
+ Requires-Dist: sphinx-copybutton<0.6,>=0.5.2
53
+ Requires-Dist: sphinx-gallery<0.20,>=0.19.0
54
+ Requires-Dist: sphinx-rtd-theme<4,>=3.0.2
55
+ Requires-Dist: stubs>=1.0.0
56
+ Requires-Dist: sympy<2,>=1.14.0
57
+ Requires-Dist: tree-format<0.2,>=0.1.2
58
+ Requires-Dist: types-requests
59
+ Requires-Dist: uncertainties<4,>=3.2.3
60
+ Description-Content-Type: text/markdown
61
+
62
+ # KBKit: Kirkwood-Buff Analysis Toolkit
63
+
64
+ [![License](https://img.shields.io/github/license/aperoutka/kbkit)](https://github.com/aperoutka/kbkit/blob/master/LICENSE)
65
+ [![PyPI version](https://img.shields.io/pypi/v/kbkit.svg)](https://pypi.org/project/kbkit/)
66
+ [![Powered by: Pixi](https://img.shields.io/badge/Powered_by-Pixi-facc15)](https://pixi.sh)
67
+ [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
68
+ [![Coverage Status](https://coveralls.io/repos/github/aperoutka/kbkit/badge.svg?branch=main)](https://coveralls.io/github/aperoutka/kbkit?branch=main)
69
+ [![docs](http://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat)](https://kbkit.readthedocs.io/)
70
+ ![python 3.12](https://img.shields.io/badge/Python-3.12%2B-blue)
71
+
72
+ **KBKit** is a Python package for automated Kirkwood-Buff (KB) analysis of molecular simulation data. It provides tools to parse simulation outputs, compute Kirkwood-Buff integrals, and extract thermodynamic properties for binary and multicomponent systems. **KBKit** supports flexible workflows, including:
73
+
74
+ * Parsing and processing of simulation data (e.g., RDFs, densities)
75
+ * Calculation of KB integrals and related thermodynamic quantities
76
+ * Integration of activity coefficient derivatives (numerical or polynomial)
77
+ * Automated pipelines for batch analysis
78
+ * Calculation of static structure factor and X-ray intensities in the limit of q &rarr; 0
79
+ * Visualization tools for KB integrals, thermodynamic properties, and static structure factors
80
+
81
+ **KBKit** is designed for researchers in computational chemistry, soft matter, and statistical mechanics who need robust, reproducible KB analysis from simulation data. The package is modular, extensible, and integrates easily with Jupyter notebooks and Python scripts.
82
+
83
+ ## Installation
84
+
85
+ ### Quick install via PyPI
86
+
87
+ ```python
88
+ pip install kbkit
89
+ ```
90
+
91
+ ### Developer install (recommended for contributors or conda users)
92
+
93
+ Clone the GitHub repository and use the provided Makefile to set up your development environment:
94
+
95
+ ```python
96
+ git clone https://github.com/aperoutka/kbkit.git
97
+ cd kbkit
98
+ make setup-dev
99
+ ```
100
+
101
+ This one-liner creates the `kbkit-dev` conda environment, installs `kbkit` in editable mode, and runs the test suite.
102
+
103
+ To install without running tests:
104
+
105
+ ```python
106
+ make dev-install
107
+ ```
108
+
109
+ To build and install the package into a clean user environment:
110
+
111
+ ```python
112
+ make setup-user
113
+ ```
114
+
115
+ For a full list of available commands:
116
+
117
+ ```python
118
+ make help
119
+ ```
120
+
121
+ ## File Organization
122
+
123
+ For running `kbkit.Pipeline` or its dependencies, the following file structure is required: a structured directory layout that separates mixed systems from pure components.
124
+ This organization enables automated parsing, reproducible KB integrals, and scalable analysis across chemical systems.
125
+
126
+ * NOTE: **KBKit** currently only supports parsing for *GROMACS* files.
127
+
128
+ An example of file structure:
129
+ ```python
130
+ kbi_dir/
131
+ ├── project/
132
+ │ └── system/
133
+ │ ├── rdf_dir/
134
+ │ │ ├── mol1_mol1.xvg
135
+ │ │ ├── mol1_mol2.xvg
136
+ │ │ └── mol1_mol2.xvg
137
+ │ ├── system_npt.edr
138
+ │ ├── system_npt.gro
139
+ │ └── system.top
140
+ └── pure_components/
141
+ └── molecule1/
142
+ ├── molecule1_npt.edr
143
+ └── molecule1.top
144
+ ```
145
+
146
+ **Requirements:**
147
+
148
+ * Each system to be analyzed must include:
149
+ * rdf_dir/ containing .xvg RDF files for all pairwise interactions
150
+ * Both molecule IDs in RDF calculation *MUST BE* in filename
151
+ * either .top topology file or .gro structure file (.gro is recommended)
152
+ * .edr energy file
153
+ * Each pure component must include:
154
+ * either .top topology file or .gro structure file (.gro is recommended)
155
+ * .edr energy file
156
+ * all other files (optional)
157
+
158
+ ## Examples
159
+
160
+ Below are several examples on various ways to implement **KBKit**.
161
+ See examples for a more complete example on the ethanol/water binary system.
162
+
163
+ ### Calculating Kirkwood-Buff integrals on a single RDF
164
+
165
+ ```python
166
+ import os
167
+ from kbkit.analysis import KBIntegrator
168
+ from kbkit.systems import SystemProperties
169
+
170
+ syspath = "./examples/test_data/ethanol_water_26C/sys_405"
171
+ rdf_path = os.path.join(sys_path, "kbi_rdf_files_gmx25", "rdf_ETHOL_SPCEW.xvg")
172
+
173
+ # create integrator object from single RDF file
174
+ integrator = KBIntegrator(
175
+ rdf_file=rdf_path,
176
+ system_properties=SystemProperties(sys_path),
177
+ use_fixed_rmin=False,
178
+ )
179
+
180
+ # calculate KBI in thermodynamic limit
181
+ kbi = integrator.kbi_limit(mol_j="SPCEW")
182
+ ```
183
+
184
+ ### Run an automated pipeline for batch analysis
185
+
186
+ ```python
187
+ from kbkit import Pipeline
188
+
189
+ # Set up and run the pipeline
190
+ pipe = Pipeline(
191
+ base_path="./examples/test_data/ethanol_water_26C", # directory with system data
192
+ pure_path="./examples/test_data/pure_components", # directory with pure component data
193
+ pure_systems=["ETHOL_300", "SPCEW_300"], # list of pure systems
194
+ ensemble="npt", # ensemble type: npt or nvt
195
+ gamma_integration_type="numerical", # integration method
196
+ verbose=False # logging verbosity
197
+ )
198
+
199
+ # run kbkit pipeline
200
+ pipe.run()
201
+
202
+ # Access the results properties
203
+ # stored in dataclass (ThermoProperty); attributes: name, value, units
204
+ # example for excess energy
205
+ ge_obj = pipe.get("ge")
206
+ print("GE summary: ", ge_array.shape)
207
+
208
+ # Convert units from kJ/mol -> kcal/mol
209
+ # default units will be those from GROMACS
210
+ pipe.convert_units("ge", "kcal/mol")
211
+
212
+ # make figures for select thermodynamic properties
213
+ pipe.plot(
214
+ molecule_map={"ETHOL": "ethanol", "SPCEW": "water"}, # dictionary mapping MD names to label names
215
+ x_mol="ETHOL" # MD name of molecule for x-axis
216
+ )
217
+ ```
218
+
219
+ ### Parse GROMACS files
220
+
221
+ ```python
222
+ import os
223
+ from kbkit.parsers import TopFileParser, EdrFileParser, GroFileParser
224
+
225
+ syspath = "./examples/test_data/ethanol_water_26C/sys_405"
226
+ top_file = os.path.join(syspath, "sys_405.top")
227
+ gro_file = os.path.join(syspath, "sys_405.gro")
228
+ edr_file = os.path.join(syspath, "sys_405_npt.edr")
229
+
230
+ # determines molecules present in simulation and their counts
231
+ top_parser = TopFileParser(top_file)
232
+ print("molecule dict: ", top_parser.molecule_counts)
233
+ print("molecule names: ", top_parser.molecules)
234
+ print("total molecule number: ", top_parser.total_molecules)
235
+
236
+ # determines electron count for each molecule type
237
+ gro_parser = GroFileParser(gro_file)
238
+ print("electron dict: ", gro_parser.electron_count)
239
+ print("box volume: ", gro_parser.compute_box_volume())
240
+
241
+ # computes energy properties by calling gmx energy
242
+ edr_parser = EdrFileParser(edr_file)
243
+ print("List of available properties: ", edr_parser.available_properties())
244
+ print("Density array over simulation time: ", edr_parser.extract_timeseries("density"))
245
+ print("Average density with std deviation: ", edr_parser.average_property("density", return_std=True))
246
+ ```
247
+
248
+ ## Credits
249
+
250
+ This package was created with [Cookiecutter](https://github.com/audreyr/cookiecutter) and the [jevandezande/pixi-cookiecutter](https://github.com/jevandezande/pixi-cookiecutter) project template.
kbkit-1.0.15/README.md ADDED
@@ -0,0 +1,189 @@
1
+ # KBKit: Kirkwood-Buff Analysis Toolkit
2
+
3
+ [![License](https://img.shields.io/github/license/aperoutka/kbkit)](https://github.com/aperoutka/kbkit/blob/master/LICENSE)
4
+ [![PyPI version](https://img.shields.io/pypi/v/kbkit.svg)](https://pypi.org/project/kbkit/)
5
+ [![Powered by: Pixi](https://img.shields.io/badge/Powered_by-Pixi-facc15)](https://pixi.sh)
6
+ [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
7
+ [![Coverage Status](https://coveralls.io/repos/github/aperoutka/kbkit/badge.svg?branch=main)](https://coveralls.io/github/aperoutka/kbkit?branch=main)
8
+ [![docs](http://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat)](https://kbkit.readthedocs.io/)
9
+ ![python 3.12](https://img.shields.io/badge/Python-3.12%2B-blue)
10
+
11
+ **KBKit** is a Python package for automated Kirkwood-Buff (KB) analysis of molecular simulation data. It provides tools to parse simulation outputs, compute Kirkwood-Buff integrals, and extract thermodynamic properties for binary and multicomponent systems. **KBKit** supports flexible workflows, including:
12
+
13
+ * Parsing and processing of simulation data (e.g., RDFs, densities)
14
+ * Calculation of KB integrals and related thermodynamic quantities
15
+ * Integration of activity coefficient derivatives (numerical or polynomial)
16
+ * Automated pipelines for batch analysis
17
+ * Calculation of static structure factor and X-ray intensities in the limit of q &rarr; 0
18
+ * Visualization tools for KB integrals, thermodynamic properties, and static structure factors
19
+
20
+ **KBKit** is designed for researchers in computational chemistry, soft matter, and statistical mechanics who need robust, reproducible KB analysis from simulation data. The package is modular, extensible, and integrates easily with Jupyter notebooks and Python scripts.
21
+
22
+ ## Installation
23
+
24
+ ### Quick install via PyPI
25
+
26
+ ```python
27
+ pip install kbkit
28
+ ```
29
+
30
+ ### Developer install (recommended for contributors or conda users)
31
+
32
+ Clone the GitHub repository and use the provided Makefile to set up your development environment:
33
+
34
+ ```python
35
+ git clone https://github.com/aperoutka/kbkit.git
36
+ cd kbkit
37
+ make setup-dev
38
+ ```
39
+
40
+ This one-liner creates the `kbkit-dev` conda environment, installs `kbkit` in editable mode, and runs the test suite.
41
+
42
+ To install without running tests:
43
+
44
+ ```python
45
+ make dev-install
46
+ ```
47
+
48
+ To build and install the package into a clean user environment:
49
+
50
+ ```python
51
+ make setup-user
52
+ ```
53
+
54
+ For a full list of available commands:
55
+
56
+ ```python
57
+ make help
58
+ ```
59
+
60
+ ## File Organization
61
+
62
+ For running `kbkit.Pipeline` or its dependencies, the following file structure is required: a structured directory layout that separates mixed systems from pure components.
63
+ This organization enables automated parsing, reproducible KB integrals, and scalable analysis across chemical systems.
64
+
65
+ * NOTE: **KBKit** currently only supports parsing for *GROMACS* files.
66
+
67
+ An example of file structure:
68
+ ```python
69
+ kbi_dir/
70
+ ├── project/
71
+ │ └── system/
72
+ │ ├── rdf_dir/
73
+ │ │ ├── mol1_mol1.xvg
74
+ │ │ ├── mol1_mol2.xvg
75
+ │ │ └── mol1_mol2.xvg
76
+ │ ├── system_npt.edr
77
+ │ ├── system_npt.gro
78
+ │ └── system.top
79
+ └── pure_components/
80
+ └── molecule1/
81
+ ├── molecule1_npt.edr
82
+ └── molecule1.top
83
+ ```
84
+
85
+ **Requirements:**
86
+
87
+ * Each system to be analyzed must include:
88
+ * rdf_dir/ containing .xvg RDF files for all pairwise interactions
89
+ * Both molecule IDs in RDF calculation *MUST BE* in filename
90
+ * either .top topology file or .gro structure file (.gro is recommended)
91
+ * .edr energy file
92
+ * Each pure component must include:
93
+ * either .top topology file or .gro structure file (.gro is recommended)
94
+ * .edr energy file
95
+ * all other files (optional)
96
+
97
+ ## Examples
98
+
99
+ Below are several examples on various ways to implement **KBKit**.
100
+ See examples for a more complete example on the ethanol/water binary system.
101
+
102
+ ### Calculating Kirkwood-Buff integrals on a single RDF
103
+
104
+ ```python
105
+ import os
106
+ from kbkit.analysis import KBIntegrator
107
+ from kbkit.systems import SystemProperties
108
+
109
+ syspath = "./examples/test_data/ethanol_water_26C/sys_405"
110
+ rdf_path = os.path.join(sys_path, "kbi_rdf_files_gmx25", "rdf_ETHOL_SPCEW.xvg")
111
+
112
+ # create integrator object from single RDF file
113
+ integrator = KBIntegrator(
114
+ rdf_file=rdf_path,
115
+ system_properties=SystemProperties(sys_path),
116
+ use_fixed_rmin=False,
117
+ )
118
+
119
+ # calculate KBI in thermodynamic limit
120
+ kbi = integrator.kbi_limit(mol_j="SPCEW")
121
+ ```
122
+
123
+ ### Run an automated pipeline for batch analysis
124
+
125
+ ```python
126
+ from kbkit import Pipeline
127
+
128
+ # Set up and run the pipeline
129
+ pipe = Pipeline(
130
+ base_path="./examples/test_data/ethanol_water_26C", # directory with system data
131
+ pure_path="./examples/test_data/pure_components", # directory with pure component data
132
+ pure_systems=["ETHOL_300", "SPCEW_300"], # list of pure systems
133
+ ensemble="npt", # ensemble type: npt or nvt
134
+ gamma_integration_type="numerical", # integration method
135
+ verbose=False # logging verbosity
136
+ )
137
+
138
+ # run kbkit pipeline
139
+ pipe.run()
140
+
141
+ # Access the results properties
142
+ # stored in dataclass (ThermoProperty); attributes: name, value, units
143
+ # example for excess energy
144
+ ge_obj = pipe.get("ge")
145
+ print("GE summary: ", ge_array.shape)
146
+
147
+ # Convert units from kJ/mol -> kcal/mol
148
+ # default units will be those from GROMACS
149
+ pipe.convert_units("ge", "kcal/mol")
150
+
151
+ # make figures for select thermodynamic properties
152
+ pipe.plot(
153
+ molecule_map={"ETHOL": "ethanol", "SPCEW": "water"}, # dictionary mapping MD names to label names
154
+ x_mol="ETHOL" # MD name of molecule for x-axis
155
+ )
156
+ ```
157
+
158
+ ### Parse GROMACS files
159
+
160
+ ```python
161
+ import os
162
+ from kbkit.parsers import TopFileParser, EdrFileParser, GroFileParser
163
+
164
+ syspath = "./examples/test_data/ethanol_water_26C/sys_405"
165
+ top_file = os.path.join(syspath, "sys_405.top")
166
+ gro_file = os.path.join(syspath, "sys_405.gro")
167
+ edr_file = os.path.join(syspath, "sys_405_npt.edr")
168
+
169
+ # determines molecules present in simulation and their counts
170
+ top_parser = TopFileParser(top_file)
171
+ print("molecule dict: ", top_parser.molecule_counts)
172
+ print("molecule names: ", top_parser.molecules)
173
+ print("total molecule number: ", top_parser.total_molecules)
174
+
175
+ # determines electron count for each molecule type
176
+ gro_parser = GroFileParser(gro_file)
177
+ print("electron dict: ", gro_parser.electron_count)
178
+ print("box volume: ", gro_parser.compute_box_volume())
179
+
180
+ # computes energy properties by calling gmx energy
181
+ edr_parser = EdrFileParser(edr_file)
182
+ print("List of available properties: ", edr_parser.available_properties())
183
+ print("Density array over simulation time: ", edr_parser.extract_timeseries("density"))
184
+ print("Average density with std deviation: ", edr_parser.average_property("density", return_std=True))
185
+ ```
186
+
187
+ ## Credits
188
+
189
+ This package was created with [Cookiecutter](https://github.com/audreyr/cookiecutter) and the [jevandezande/pixi-cookiecutter](https://github.com/jevandezande/pixi-cookiecutter) project template.