Skip to content

Commit c18e010

Browse files
committed
tests
2 parents a06e379 + 5d6697a commit c18e010

16 files changed

Lines changed: 477 additions & 51 deletions

File tree

.github/workflows/release.yaml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,30 +163,36 @@ jobs:
163163
sed -i "s/^{% set version = \".*\" %}$/{% set version = \"${{ github.event.inputs.version }}\" %}/" conda-recipe/meta.yaml
164164
grep '{% set version' conda-recipe/meta.yaml
165165
166-
- name: Setup Conda
166+
- name: Setup Conda (conda-forge only)
167167
uses: conda-incubator/setup-miniconda@v3
168168
with:
169169
miniforge-variant: Miniforge3
170170
python-version: "3.12"
171-
auto-activate-base: false
171+
auto-activate: false
172+
conda-remove-defaults: true
173+
channels: conda-forge
174+
channel-priority: strict
172175

173176
- name: Install build tools
174177
shell: bash -l {0}
175178
run: |
176179
conda install -y conda-build anaconda-client
177-
conda config --add channels conda-forge
178-
conda config --set channel_priority strict
179180
conda config --set anaconda_upload no
180181
181182
- name: Build package
182183
shell: bash -l {0}
184+
env:
185+
PIP_NO_INDEX: "0"
183186
run: |
187+
PKG_PATH=$(conda build conda-recipe --output)
188+
echo "PKG_PATH=$PKG_PATH" >> "$GITHUB_ENV"
184189
conda build conda-recipe
190+
test -f "$PKG_PATH"
191+
echo "Built: $PKG_PATH"
185192
186193
- name: Upload to Anaconda
187194
shell: bash -l {0}
188195
env:
189196
ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
190197
run: |
191-
PKG_PATH=$(conda build conda-recipe --output)
192198
anaconda -t "$ANACONDA_API_TOKEN" upload "$PKG_PATH" --user CCPBioSim --force

CodeEntropy/entropy/nodes/orientational.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ def run(self, shared_data: MutableMapping[str, Any], **_: Any) -> dict[str, Any]
5353
results: dict[int, float] = {}
5454

5555
for group_id, mol_ids in groups.items():
56+
results[group_id] = 0
57+
if not mol_ids:
58+
continue
5659
rep_mol_id = mol_ids[0]
5760
highest_level = levels[rep_mol_id][-1]
5861

CodeEntropy/entropy/workflow.py

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,15 @@ def __init__(
9494
def execute(self) -> None:
9595
"""Run the full entropy workflow and emit results.
9696
97-
This method orchestrates the complete pipeline, populates shared data,
98-
and triggers the DAG/graph executions. Final results are logged and saved
99-
via `ResultsReporter`.
97+
This orchestrates the complete entropy pipeline:
98+
1. Build trajectory slice.
99+
2. Apply atom selection to create a reduced universe.
100+
3. Detect hierarchy levels.
101+
4. Group molecules.
102+
5. Split groups into water and non-water.
103+
6. Optionally compute water entropy (only if solute exists).
104+
7. Run level DAG and entropy graph.
105+
8. Finalize and persist results.
100106
"""
101107
traj = self._build_trajectory_slice()
102108
console.print(
@@ -110,9 +116,11 @@ def execute(self) -> None:
110116
reduced_universe, self._args.grouping
111117
)
112118

113-
nonwater_groups, water_groups = self._split_water_groups(groups)
119+
nonwater_groups, water_groups = self._split_water_groups(
120+
reduced_universe, groups
121+
)
114122

115-
if self._args.water_entropy and water_groups:
123+
if self._args.water_entropy and water_groups and nonwater_groups:
116124
self._compute_water_entropy(traj, water_groups)
117125
else:
118126
nonwater_groups.update(water_groups)
@@ -255,25 +263,40 @@ def _detect_levels(self, reduced_universe: Any) -> Any:
255263
return levels
256264

257265
def _split_water_groups(
258-
self, groups: Mapping[int, Any]
266+
self,
267+
universe: Any,
268+
groups: Mapping[int, Any],
259269
) -> tuple[dict[int, Any], dict[int, Any]]:
260270
"""Partition molecule groups into water and non-water groups.
261271
272+
This method identifies which molecule groups correspond to water
273+
molecules based on residue membership.
274+
262275
Args:
263-
groups: Mapping of group id -> molecule ids.
276+
universe (Any):
277+
The MDAnalysis Universe used to build the molecule groups
278+
(typically the reduced_universe).
279+
groups (Mapping[int, Any]):
280+
Mapping of group_id -> list of molecule fragment indices.
264281
265282
Returns:
266-
Tuple of (nonwater_groups, water_groups).
283+
Tuple[Dict[int, Any], Dict[int, Any]]:
284+
A tuple containing:
285+
286+
- nonwater_groups:
287+
Mapping of group_id -> molecule ids that are NOT water.
288+
- water_groups:
289+
Mapping of group_id -> molecule ids that contain water.
267290
"""
268-
water_atoms = self._universe.select_atoms("water")
291+
water_atoms = universe.select_atoms("water")
269292
water_resids = {res.resid for res in water_atoms.residues}
270293

271294
water_groups = {
272295
gid: mol_ids
273296
for gid, mol_ids in groups.items()
274297
if any(
275298
res.resid in water_resids
276-
for mol in [self._universe.atoms.fragments[i] for i in mol_ids]
299+
for mol in [universe.atoms.fragments[i] for i in mol_ids]
277300
for res in mol.residues
278301
)
279302
}
@@ -294,10 +317,10 @@ def _compute_water_entropy(
294317
if not water_groups or not self._args.water_entropy:
295318
return
296319

297-
water_entropy = WaterEntropy(self._args)
320+
water_entropy = WaterEntropy(self._args, self._reporter)
298321

299322
for group_id in water_groups.keys():
300-
water_entropy._calculate_water_entropy(
323+
water_entropy.calculate_and_log(
301324
universe=self._universe,
302325
start=traj.start,
303326
end=traj.end,

CodeEntropy/levels/neighbors.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def get_symmetry(self, universe, groups):
126126
universe, molecules[0]
127127
)
128128

129-
symmetry_number[group_id] = self._get_symmetry(
129+
symmetry_number[group_id] = self._get_symmetry_number(
130130
rdkit_mol, number_heavy, number_hydrogen
131131
)
132132

@@ -180,7 +180,7 @@ def _get_rdkit_mol(self, universe, mol_id):
180180

181181
return rdkit_mol, number_heavy, number_hydrogen
182182

183-
def _get_symmetry(self, rdkit_mol, number_heavy, number_hydrogen):
183+
def _get_symmetry_number(self, rdkit_mol, number_heavy, number_hydrogen):
184184
"""
185185
Calculate symmetry number for the molecule.
186186

CodeEntropy/levels/search.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -173,17 +173,16 @@ def get_distance(self, j_position, i_position, dimensions):
173173
dimensions: the dimensions of the simulation box
174174
175175
Returns:
176-
distance: the distance between the two points
176+
distance: float, the distance between the two points
177177
"""
178+
# Difference in positions
179+
delta = np.abs(j_position - i_position)
178180

179-
x = []
180-
total = 0
181-
for coord in range(3):
182-
x.append(j_position[coord] - i_position[coord])
183-
if x[coord] > 0.5 * dimensions[coord]:
184-
x[coord] = x[coord] - dimensions[coord]
185-
total += x[coord] ** 2
186-
distance = np.sqrt(total)
181+
# Account for periodic boundary conditions
182+
delta = np.where(delta > 0.5 * dimensions, delta - dimensions, delta)
183+
184+
# Get distance value
185+
distance = np.sqrt((delta**2).sum(axis=-1))
187186

188187
return distance
189188

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ CodeEntropy
88
| **Documentation** | [![Weekly Docs](https://github.com/CCPBioSim/CodeEntropy/actions/workflows/weekly-docs.yaml/badge.svg)](https://github.com/CCPBioSim/CodeEntropy/actions/workflows/weekly-docs.yaml) [![Docs - Status](https://app.readthedocs.org/projects/codeentropy/badge/?version=latest)](https://codeentropy.readthedocs.io/en/latest/?badge=latest) |
99
| **Citation** | [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.17570721.svg)](https://doi.org/10.5281/zenodo.17570721) |
1010
| **PyPI** | ![PyPI - Status](https://img.shields.io/pypi/status/codeentropy?logo=pypi&logoColor=white) ![PyPI - Version](https://img.shields.io/pypi/v/codeentropy?logo=pypi&logoColor=white) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/CodeEntropy) ![PyPI - Total Downloads](https://img.shields.io/pepy/dt/codeentropy?logo=pypi&logoColor=white&color=blue) ![PyPI - Monthly Downloads](https://img.shields.io/pypi/dm/CodeEntropy?logo=pypi&logoColor=white&color=blue) |
11+
| **Anaconda** | [![Anaconda.org](https://anaconda.org/CCPBioSim/codeentropy/badges/version.svg)](https://anaconda.org/CCPBioSim/codeentropy/) [![Last Updated](https://anaconda.org/CCPBioSim/codeentropy/badges/latest_release_date.svg)](https://anaconda.org/CCPBioSim/codeentropy) [![Platforms](https://anaconda.org/CCPBioSim/codeentropy/badges/platforms.svg)](https://anaconda.org/CCPBioSim/codeentropy) [![License](https://anaconda.org/CCPBioSim/codeentropy/badges/license.svg)](https://anaconda.org/CCPBioSim/codeentropy) [![Downloads](https://anaconda.org/CCPBioSim/codeentropy/badges/downloads.svg)](https://anaconda.org/CCPBioSim/codeentropy)|
1112
| **Quality** | [![Coverage Status](https://coveralls.io/repos/github/CCPBioSim/CodeEntropy/badge.svg?branch=main)](https://coveralls.io/github/CCPBioSim/CodeEntropy?branch=main) |
1213

1314
CodeEntropy is a Python package for computing the configurational entropy of macromolecular systems using forces sampled from molecular dynamics (MD) simulations. It implements the multiscale cell correlation method to provide accurate and efficient entropy estimates, supporting a wide range of applications in molecular simulation and statistical mechanics.
1415

1516
<p align="center">
16-
<img src="docs/_static/logos/biosim-codeentropy_logo_light.png#gh-light-mode-only" alt="CodeEntropy logo" width="300"/>
17-
<img src="docs/_static/logos/biosim-codeentropy_logo_dark.png#gh-dark-mode-only" alt="CodeEntropy logo" width="300"/>
17+
<img src="docs/_static/logos/biosim-codeentropy_logo_light.png#gh-dark-mode-only" alt="CodeEntropy logo" width="300"/>
18+
<img src="docs/_static/logos/biosim-codeentropy_logo_dark.png#gh-light-mode-only" alt="CodeEntropy logo" width="300"/>
1819
</p>
1920

2021
See [CodeEntropy’s documentation](https://codeentropy.readthedocs.io/en/latest/) for more information.

conda-recipe/meta.yaml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{% set name = "CodeEntropy" %}
1+
{% set name = "codeentropy" %}
22
{% set version = "0.0.0" %}
33

44
package:
@@ -10,7 +10,9 @@ source:
1010

1111
build:
1212
noarch: python
13-
script: python -m pip install . -vv --no-deps
13+
script: |
14+
python -m pip install . -vv --no-deps
15+
PIP_NO_INDEX=0 python -m pip install -vv --index-url https://pypi.org/simple waterEntropy
1416
entry_points:
1517
- CodeEntropy=CodeEntropy.cli:main
1618

@@ -20,20 +22,22 @@ requirements:
2022
- pip
2123
- flit-core >=3.4,<4
2224
run:
23-
- python >=3.11
25+
- python >=3.12
2426
- numpy >=2.3,<3.0
2527
- mdanalysis >=2.10,<3.0
2628
- pandas >=3.0,<3.1
2729
- psutil >=7.1,<8.0
2830
- pyyaml >=6.0,<7.0
29-
- python-json-logger >=4.0,<5.0
31+
- python-json-logger >=2.0,<3.0
3032
- rich >=14.2,<15.0
31-
- art >=6.5,<7.0
33+
- python-art >=6.5,<7.0
3234
- networkx >=3.6,<3.7
3335
- matplotlib >=3.10,<3.11
34-
- waterentropy >=2,<2.1
3536
- requests >=2.32,<3.0
3637
- rdkit>=2025.9.5
38+
- dask >=2026.1.2,<2026.2.0
39+
- distributed >=2026.1.2,<2026.2.0
40+
- dask-jobqueue >=0.9,<0.10
3741

3842
test:
3943
imports:

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@
7474
# -- Options for HTML output -------------------------------------------------
7575
html_theme = "furo"
7676
html_theme_options = {
77-
"light_logo": "logos/biosim-codeentropy_logo_light.png",
78-
"dark_logo": "logos/biosim-codeentropy_logo_dark.png",
77+
"dark_logo": "logos/biosim-codeentropy_logo_light.png",
78+
"light_logo": "logos/biosim-codeentropy_logo_dark.png",
7979
}
8080

8181
html_static_path = ["_static"]

docs/getting_started.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Install CodeEntropy:
5151

5252
.. code-block:: bash
5353
54-
conda install -c conda-forge -c CCPBioSim CodeEntropy
54+
conda install -c conda-forge -c CCPBioSim codeentropy
5555
5656
5757
Input Files
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"args": {
3+
"top_traj_file": [
4+
"../../test_data/Liquids_simulation_data/GAFF/water/molecules.top",
5+
"../../test_data/Liquids_simulation_data/GAFF/water/trajectory.crd"
6+
],
7+
"force_file": "../../test_data/Liquids_simulation_data/GAFF/water/forces.frc",
8+
"file_format": "MDCRD",
9+
"kcal_force_units": false,
10+
"selection_string": "all",
11+
"start": 0,
12+
"end": 1,
13+
"step": 1,
14+
"bin_width": 30,
15+
"temperature": 298.0,
16+
"verbose": false,
17+
"output_file": "/home/tdo96567/BioSim/temp/water/job008/output_file.json",
18+
"force_partitioning": 0.5,
19+
"water_entropy": true,
20+
"grouping": "molecules",
21+
"combined_forcetorque": true,
22+
"customised_axes": true
23+
},
24+
"provenance": {
25+
"python": "3.14.0",
26+
"platform": "Linux-6.6.87.2-microsoft-standard-WSL2-x86_64-with-glibc2.39",
27+
"codeentropy_version": "2.0.0",
28+
"git_sha": "cba3d8ea4118e00b25ee5a58d7ba951e4894b5c0"
29+
},
30+
"groups": {
31+
"0": {
32+
"components": {
33+
"united_atom:Transvibrational": 79.20298312418278,
34+
"united_atom:Rovibrational": 50.90260688502127,
35+
"united_atom:Conformational": 0.0
36+
},
37+
"total": 130.10559000920404
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)