CodeEntropy 2.1.1__py3-none-any.whl → 2.2.0__py3-none-any.whl

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.
CodeEntropy/__init__.py CHANGED
@@ -8,4 +8,4 @@ entropy estimates, supporting a wide range of applications in molecular simulati
8
8
  and statistical mechanics.
9
9
  """
10
10
 
11
- __version__ = "2.1.1"
11
+ __version__ = "2.2.0"
@@ -335,8 +335,14 @@ class CodeEntropyRunner:
335
335
  kcal_units = args.kcal_force_units
336
336
 
337
337
  if forcefile is None:
338
- logger.debug(f"Loading Universe with {tprfile} and {trrfile}")
339
- return mda.Universe(tprfile, trrfile, format=fileformat)
338
+ if fileformat == "LAMMPSDUMP":
339
+ logger.debug(
340
+ f"Loading Universe with {tprfile} and {trrfile} (LAMMPSDUMP)"
341
+ )
342
+ return universe_operations.convert_lammps(tprfile, trrfile, fileformat)
343
+ else:
344
+ logger.debug(f"Loading Universe with {tprfile} and {trrfile}")
345
+ return mda.Universe(tprfile, trrfile, format=fileformat)
340
346
 
341
347
  return universe_operations.merge_forces(
342
348
  tprfile, trrfile, forcefile, fileformat, kcal_units
@@ -53,7 +53,7 @@ class ConfigurationalEntropyNode:
53
53
  fragments = universe.atoms.fragments
54
54
  results: dict[int, dict[str, float]] = {}
55
55
 
56
- for group_id, mol_ids in groups.items():
56
+ for group_id, mol_ids in sorted(groups.items()):
57
57
  results[group_id] = {"ua": 0.0, "res": 0.0, "poly": 0.0}
58
58
  if not mol_ids:
59
59
  continue
@@ -52,7 +52,7 @@ class OrientationalEntropyNode:
52
52
 
53
53
  results: dict[int, float] = {}
54
54
 
55
- for group_id, mol_ids in groups.items():
55
+ for group_id, mol_ids in sorted(groups.items()):
56
56
  results[group_id] = 0
57
57
  if not mol_ids:
58
58
  continue
@@ -90,7 +90,7 @@ class VibrationalEntropyNode:
90
90
 
91
91
  results: dict[int, dict[str, dict[str, float]]] = {}
92
92
 
93
- for group_id, mol_ids in groups.items():
93
+ for group_id, mol_ids in sorted(groups.items()):
94
94
  results[group_id] = {}
95
95
  if not mol_ids:
96
96
  continue
@@ -198,7 +198,7 @@ class VibrationalEntropyNode:
198
198
  if isinstance(gid2i, dict) and gid2i:
199
199
  return gid2i
200
200
  groups = shared_data["groups"]
201
- return {gid: i for i, gid in enumerate(groups.keys())}
201
+ return {gid: i for i, gid in enumerate(sorted(groups.keys()))}
202
202
 
203
203
  def _get_ua_frame_counts(self, shared_data: Mapping[str, Any]) -> dict[CovKey, int]:
204
204
  """Extract per-(group,residue) frame counts for united-atom covariances.
@@ -96,7 +96,7 @@ class EntropyWorkflow:
96
96
 
97
97
  This orchestrates the complete entropy pipeline:
98
98
  1. Build trajectory slice.
99
- 2. Apply atom selection to create a reduced universe.
99
+ 2. Apply atom and frame selection to create a reduced universe.
100
100
  3. Detect hierarchy levels.
101
101
  4. Group molecules.
102
102
  5. Split groups into water and non-water.
@@ -233,21 +233,31 @@ class EntropyWorkflow:
233
233
  return math.floor((end - start) / step)
234
234
 
235
235
  def _build_reduced_universe(self) -> Any:
236
- """Apply atom selection and return the reduced universe.
237
-
238
- If `selection_string` is "all", the original universe is returned.
236
+ """Apply atom and frame selection and return the reduced universe.
239
237
 
240
238
  Returns:
241
- MDAnalysis Universe (original or reduced).
239
+ MDAnalysis Universe (reduced according to user selections).
242
240
  """
243
241
  selection = self._args.selection_string
242
+ start = self._args.start
243
+ end = len(self._universe.trajectory) if self._args.end == -1 else self._args.end
244
+ step = self._args.step
244
245
  if selection == "all":
245
- return self._universe
246
+ reduced_atoms = self._universe
247
+ else:
248
+ reduced_atoms = self._universe_operations.select_atoms(
249
+ self._universe, selection
250
+ )
251
+ name = f"{len(reduced_atoms.trajectory)}_frame_dump_atom_selection"
252
+ self._run_manager.write_universe(reduced_atoms, name)
253
+
254
+ reduced_frames = self._universe_operations.select_frames(
255
+ reduced_atoms, start, end, step
256
+ )
257
+ name = f"{len(reduced_frames.trajectory)}_frame_dump_frame_selection"
258
+ self._run_manager.write_universe(reduced_frames, name)
246
259
 
247
- reduced = self._universe_operations.select_atoms(self._universe, selection)
248
- name = f"{len(reduced.trajectory)}_frame_dump_atom_selection"
249
- self._run_manager.write_universe(reduced, name)
250
- return reduced
260
+ return reduced_frames
251
261
 
252
262
  def _detect_levels(self, reduced_universe: Any) -> Any:
253
263
  """Detect hierarchy levels for each molecule in the reduced universe.
@@ -293,7 +303,7 @@ class EntropyWorkflow:
293
303
 
294
304
  water_groups = {
295
305
  gid: mol_ids
296
- for gid, mol_ids in groups.items()
306
+ for gid, mol_ids in sorted(groups.items())
297
307
  if any(
298
308
  res.resid in water_resids
299
309
  for mol in [universe.atoms.fragments[i] for i in mol_ids]
@@ -301,7 +311,7 @@ class EntropyWorkflow:
301
311
  )
302
312
  }
303
313
  nonwater_groups = {
304
- gid: g for gid, g in groups.items() if gid not in water_groups
314
+ gid: g for gid, g in sorted(groups.items()) if gid not in water_groups
305
315
  }
306
316
  return nonwater_groups, water_groups
307
317
 
@@ -354,7 +364,7 @@ class EntropyWorkflow:
354
364
  except (TypeError, ValueError):
355
365
  logger.warning("Skipping invalid entry: %s, %s", group_id, result)
356
366
 
357
- for group_id, total in entropy_by_group.items():
367
+ for group_id, total in sorted(entropy_by_group.items()):
358
368
  self._reporter.molecule_data.append(
359
369
  (group_id, "Group Total", "Group Total Entropy", total)
360
370
  )