|
23 | 23 | from maicos.lib.math import center_cluster |
24 | 24 | from maicos.lib.util import get_compound |
25 | 25 | from maicos.lib.weights import density_weights |
| 26 | +from tqdm import tqdm |
26 | 27 |
|
27 | | -from fairmd.lipids import progress |
28 | 28 | from fairmd.lipids.auxiliary.jsonEncoders import CompactJSONEncoder |
29 | 29 | from fairmd.lipids.core import System |
30 | 30 | from fairmd.lipids.molecules import lipids_set |
@@ -268,11 +268,82 @@ def traj_centering_for_maicos_mda( |
268 | 268 | with contextlib.suppress(FileNotFoundError): |
269 | 269 | os.remove(xtccentered) |
270 | 270 |
|
271 | | - with mda.Writer(xtccentered, universe.atoms.n_atoms) as W: |
272 | | - for ts in progress( |
273 | | - universe.trajectory[eq_frame:], |
274 | | - desc="Centering trajectory (MDAnalysis)", |
275 | | - ): |
| 271 | + # Get trajectory info |
| 272 | + topo_path = universe.filename |
| 273 | + traj_path = universe.trajectory.filename |
| 274 | + dt = universe.trajectory.dt |
| 275 | + n_frames = universe.trajectory.n_frames |
| 276 | + eq_frame = int(eq_time / dt) if dt > 0 else 0 |
| 277 | + |
| 278 | + if logger: |
| 279 | + logger.info(f"Sequential trajectory centering: {n_frames - eq_frame} frames") |
| 280 | + |
| 281 | + # Use the chunk helper for the entire frame range |
| 282 | + _center_trajectory_chunk( |
| 283 | + topo_path, |
| 284 | + traj_path, |
| 285 | + last_atom, |
| 286 | + eq_frame, |
| 287 | + n_frames, |
| 288 | + xtccentered, |
| 289 | + ) |
| 290 | + |
| 291 | + return xtccentered |
| 292 | + |
| 293 | + |
| 294 | +def _center_trajectory_chunk( |
| 295 | + topo_path: str, |
| 296 | + traj_path: str, |
| 297 | + last_atom: str, |
| 298 | + start_frame: int, |
| 299 | + stop_frame: int, |
| 300 | + temp_output: str, |
| 301 | + chunk_id: int = 0, |
| 302 | + total_chunks: int = 1, |
| 303 | + tqdm_position: int | None = None, |
| 304 | +) -> tuple[str, int, int]: |
| 305 | + """ |
| 306 | + Process a single trajectory chunk for parallel centering. |
| 307 | +
|
| 308 | + Worker function that must re-instantiate Universe for process safety. |
| 309 | + Uses the same centering logic as traj_centering_for_maicos_mda. |
| 310 | +
|
| 311 | + Args: |
| 312 | + topo_path: Path to topology file (GRO, PDB, etc.). |
| 313 | + traj_path: Path to trajectory file (XTC, etc.). |
| 314 | + last_atom: Atom name for centering reference. |
| 315 | + start_frame: Starting frame index (inclusive). |
| 316 | + stop_frame: Stopping frame index (exclusive). |
| 317 | + temp_output: Path for temporary output file. |
| 318 | + chunk_id: Identifier for this chunk (0-indexed). |
| 319 | + total_chunks: Total number of chunks being processed. |
| 320 | + tqdm_position: Position for tqdm progress bar (enables per-worker progress). |
| 321 | +
|
| 322 | + Returns: |
| 323 | + Tuple of (output_path, chunk_id, total_chunks) for logging by caller. |
| 324 | + """ |
| 325 | + u = mda.Universe(topo_path, traj_path) |
| 326 | + |
| 327 | + refgroup = u.select_atoms(f"name {last_atom}") |
| 328 | + ref_weights = refgroup.masses |
| 329 | + wrap_compound = get_compound(u.atoms) |
| 330 | + |
| 331 | + n_frames = stop_frame - start_frame |
| 332 | + |
| 333 | + with mda.Writer(temp_output, u.atoms.n_atoms) as W: |
| 334 | + # Use tqdm if position is provided for per-worker progress |
| 335 | + frame_iter = u.trajectory[start_frame:stop_frame] |
| 336 | + if tqdm_position is not None: |
| 337 | + frame_iter = tqdm( |
| 338 | + frame_iter, |
| 339 | + total=n_frames, |
| 340 | + desc=f"Worker {chunk_id + 1}/{total_chunks}", |
| 341 | + position=tqdm_position, |
| 342 | + leave=False, |
| 343 | + ncols=80, |
| 344 | + ) |
| 345 | + |
| 346 | + for ts in frame_iter: |
276 | 347 | # unwrap |
277 | 348 | u.atoms.unwrap(compound=wrap_compound) |
278 | 349 |
|
|
0 commit comments