def count_solvent_molecules(tpr, solvent="water"): """Count number of solvent molecules from index file. .. Note:: Only solvent="water" or "octanol" supported. New selections can be added to :data:`solvent_selections`. """ # This would be MUCH easier in MDAnalysis but I don't want to add # this as a dependency to mdpow. g_select would also work but that's # more recent and also requires reading of an xvg file. solventgroup = "solvent_%(solvent)s" % vars() # should not start with a number for make_ndx!! try: cmd = ['keep 0', 'del 0', solvent_selections[solvent], 'name 0 %(solventgroup)s' % vars(), 'q'] except KeyError: raise NotImplementedError("solvent %(solvent)r not supported" % vars()) fd, tmpndx = tempfile.mkstemp(suffix=".ndx") try: # silent, no screen output!! rc,output,junk = gromacs.cbook.make_ndx_captured(f=tpr, o=tmpndx, input=cmd, stderr=False) if rc != 0: out = "\n".join(["GMX_FATAL: %s" % s for s in (junk + "\n\n" + output).split("\n")]) errmsg = "Failed to build index. Look at the output below for hints:\n" + out logger.error(errmsg) raise GromacsError(errmsg) finally: unlink_gmx(tmpndx) try: ndx = gromacs.cbook.parse_ndxlist(output) except AttributeError: logger.error("Failed to find solvent %(solvent)r. Maybe specify solvent='octanol'?", vars()) raise ValueError("Failed to properly construct/parse make_ndx output.") N_solvent = None for rec in ndx: if rec['name'] == solventgroup: N_solvent = rec['natoms'] # == number of molecules as one atom per molecule break if N_solvent is None: errmsg = "Failed to find solvent %(solvent)r in %(tpr)r" % vars() logger.error(errmsg) raise ValueError(errmsg) logger.info("Found %(N_solvent)d %(solvent)s solvent molecules in %(tpr)r", vars()) return N_solvent
def get_observables(edr, observables=None, **kwargs): """Run :program:`g_energy` to get thermodynamic averages. :Arguments: *edr* Gromacs energy file *observables* list of energy (thermodynamic) averages to be computed; the default (for ``None``) is :: ["Pressure", "Volume", "Density", "Temperature"] *kwargs* other keywords are passed to :class:`gromacs.tools.G_energy`; for instance, *b* sets the start time (in ps) and *o* sets the output file name :Returns: :class:`~numpy.core.records.recarray` with the observable name in the first column ("*Energy*") and subsequent columns containing the exact averages produced by :program:`g_energy`. """ if observables is None: observables = ["Pressure", "Volume", "Density", "Temperature"] logger.info("Analyzing observables %(observables)r in energy file %(edr)r...", vars()) kwargs['input'] = observables kwargs['f'] = edr kwargs['stdout'] = False # required for processing kwargs['stderr'] = False # suppress stderr fd, kwargs['o'] = tempfile.mkstemp(suffix=".xvg") try: rc, data, stderr = gromacs.g_energy(**kwargs) if rc != 0: logger.error("g_energy failed") raise GromacsError("g_energy failed --- see output below:\n\n" + stderr + data) finally: unlink_gmx(kwargs['o']) return parse_energy(data)