Source code for pestifer.tasks.continuation

# Author: Cameron F. Abrams, <cfa22@drexel.edu>
"""
Definition of the :class:`ContinuationTask` class for resetting the task chain to named values of the psf, pdb, xsc, and coor files.

Usage is described in the :ref:`config_ref tasks continuation` documentation.
"""
import logging
import shutil

from .psfgen import PsfgenTask
from ..core.artifacts import *
from ..core.errors import PestiferBuildError
logger = logging.getLogger(__name__)


def _ensure_in_cwd(filepath: str) -> str:
    """Return filepath unchanged if it is already in the CWD; otherwise copy it here and return the basename."""
    if not filepath:
        return filepath
    src = Path(filepath).resolve()
    if src.parent == Path.cwd():
        return filepath
    dest = Path.cwd() / src.name
    if not dest.exists() or not dest.samefile(src):
        shutil.copy2(src, dest)
        logger.info(f'Copied {src}{dest}')
    return src.name

[docs] class ContinuationTask(PsfgenTask): """ This task only resets the task chain to named values of the psf, pdb, xsc, and coor files """ _yaml_header = 'continuation'
[docs] def do(self): self.next_basename() # must have psf, either coor or pdb psf: str = self.specs.get('psf', '') # must have either coor or pdb coor: str = self.specs.get('coor','') pdb: str = self.specs.get('pdb','') xsc: str = self.specs.get('xsc','') vel: str = self.specs.get('vel','') if not psf: raise PestiferBuildError('psf file must be specified in the continuation task') if not coor and not pdb: raise PestiferBuildError('Either coor or pdb file must be specified in the continuation task') psf = _ensure_in_cwd(psf) coor = _ensure_in_cwd(coor) pdb = _ensure_in_cwd(pdb) xsc = _ensure_in_cwd(xsc) vel = _ensure_in_cwd(vel) if coor and not pdb: pdb = self.coor_to_pdb(coor, psf) if pdb and not coor: coor = self.pdb_to_coor(pdb) topolines = [] with open(psf, 'r') as f: for line in f: line = line.strip() if line and line.startswith("REMARKS topology"): topolines.append(line) if '!NATOM' in line: break if not topolines: raise PestiferBuildError('No topology information found in PSF file') streamfiles = [] for topoline in topolines: tokens = topoline.split() toponame = os.path.basename(tokens[-1]) if toponame.endswith('.str'): streamfiles.append(toponame) # any md task will at a minimum ensure all of charmmff's top-level parameter # files are copied to the CWD. Since this PSF also lists stream files # in its topology remarks, the continuation task will also preemptively # copy them to cwd and register them as artifacts CC = self.resource_manager.charmmff_content for streamfile in streamfiles: CC.copy_charmmfile_local(streamfile) self.register([CharmmffStreamFileArtifact(x) for x in streamfiles], key='charmmff_streamfiles', artifact_type=CharmmffStreamFileArtifacts) self.register(dict( psf=PSFFileArtifact(psf), pdb=PDBFileArtifact(pdb), coor=NAMDCoorFileArtifact(coor), xsc=NAMDXscFileArtifact(xsc) if xsc else None, vel=NAMDVelFileArtifact(vel) if vel else None), key='state', artifact_type=StateArtifacts) self.update_molecule() self.result = 0 return self.result