def to_task(self): logger.info1('Creating task for', self.digest) pxul.os.ensure_dir(self.outputdir) logger.debug('Ensured', self.outputdir, 'exists') cmd = 'bash %(script)s > %(log)s' % dict(script = SCRIPT_NAME, log = LOGFILE) task = wq.Task(cmd) # input files task.specify_buffer(SCRIPT_CONTENTS, SCRIPT_NAME , cache=True) task.specify_buffer(str(self._cpus), SCRIPT_INPUT_NAMES['cpus'],cache=True) task.specify_input_file(self._x , SCRIPT_INPUT_NAMES['x'] , cache=False, name='x_i') task.specify_input_file(self._v , SCRIPT_INPUT_NAMES['v'] , cache=False, name='v_i') task.specify_input_file(self._t , SCRIPT_INPUT_NAMES['t'] , cache=False, name='t_i') task.specify_input_file(self._tpr , SCRIPT_INPUT_NAMES['tpr'], cache=True , name='tpr') # output files task.specify_output_file(self.output_files['log'], LOGFILE , cache=False, name='log') task.specify_output_file(self.output_files['x'], SCRIPT_OUTPUT_NAMES['x'] , cache=False, name='x_o') task.specify_output_file(self.output_files['v'], SCRIPT_OUTPUT_NAMES['v'] , cache=False, name='v_o') task.specify_output_file(self.output_files['t'], SCRIPT_OUTPUT_NAMES['t'] , cache=False, name='t_o') self.check_binaries() for path in self._binaries: task.specify_input_file(path, cache=True) for name in self._trajfiles: task.specify_output_file(self.output_path(name), name, cache=False) logger.debug('Created task:\n', str(task)) return task
def to_task(self): logger.info1('Creating task for', self.digest) pxul.os.ensure_dir(self.outputdir) logger.debug('Ensured', self.outputdir, 'exists') cmd = 'bash %(script)s > %(log)s' % dict(script=SCRIPT_NAME, log=LOGFILE) task = wq.Task(cmd) # input files task.specify_buffer(SCRIPT_CONTENTS, SCRIPT_NAME, cache=True) task.specify_buffer(str(self._cpus), SCRIPT_INPUT_NAMES['cpus'], cache=True) task.specify_input_file(self._x, SCRIPT_INPUT_NAMES['x'], cache=False, name='x_i') task.specify_input_file(self._v, SCRIPT_INPUT_NAMES['v'], cache=False, name='v_i') task.specify_input_file(self._t, SCRIPT_INPUT_NAMES['t'], cache=False, name='t_i') task.specify_input_file(self._tpr, SCRIPT_INPUT_NAMES['tpr'], cache=True, name='tpr') # output files task.specify_output_file(self.output_files['log'], LOGFILE, cache=False, name='log') task.specify_output_file(self.output_files['x'], SCRIPT_OUTPUT_NAMES['x'], cache=False, name='x_o') task.specify_output_file(self.output_files['v'], SCRIPT_OUTPUT_NAMES['v'], cache=False, name='v_o') task.specify_output_file(self.output_files['t'], SCRIPT_OUTPUT_NAMES['t'], cache=False, name='t_o') self.check_binaries() for path in self._binaries: task.specify_input_file(path, cache=True) for name in self._trajfiles: task.specify_output_file(self.output_path(name), name, cache=False) logger.debug('Created task:\n', str(task)) return task
def relax(self, mdp, gammas=None, steps=None): logger.info1('Iterative equilibration') gammas = [1000, 100, 10, 1] if gammas is None else gammas name = self.name + '_itr_posres_eq' mdp_itr = suffix.mdp(name) mdp.SETUP.define = '-DPOSRES' if steps is not None: mdp.nsteps = steps mdp.set_velocity_generation() for g in gammas: mdp.dt = 0.001 mdp.set_gamma(g) logger.debug('using gamma =', g) logger.debug('using dt =', mdp.dt) mdp.save(mdp_itr) self._cn = name + '_gamma-%d' % g gmx.grompp( f = mdp_itr, c = suffix.gro(self.pn), t = suffix.trr(self.pn), p = self.top, o = suffix.tpr(self.cn) ) gmx.mdrun( s = suffix.tpr(self.cn), deffnm = self.cn, v = True ) self._pn = self.cn mdp.unset_velocity_generation()
def relax(self, mdp, gammas=None, steps=None): logger.info1('Iterative equilibration') gammas = [1000, 100, 10, 1] if gammas is None else gammas name = self.name + '_itr_posres_eq' mdp_itr = suffix.mdp(name) mdp.SETUP.define = '-DPOSRES' if steps is not None: mdp.nsteps = steps mdp.set_velocity_generation() for g in gammas: mdp.dt = 0.001 mdp.set_gamma(g) logger.debug('using gamma =', g) logger.debug('using dt =', mdp.dt) mdp.save(mdp_itr) self._cn = name + '_gamma-%d' % g gmx.grompp(f=mdp_itr, c=suffix.gro(self.pn), t=suffix.trr(self.pn), p=self.top, o=suffix.tpr(self.cn)) gmx.mdrun(s=suffix.tpr(self.cn), deffnm=self.cn, v=True) self._pn = self.cn mdp.unset_velocity_generation()
def tpr_set_scalar(tpr, name, value): logger.info1('Setting', name, '=', value, 'in', tpr) tmpfile = os.path.join(os.path.dirname(tpr), name + '.gps') with open(tmpfile, 'w') as fd: fd.write('%s\n' % value) guamps_set(f=tpr, s=name, i=tmpfile, O=True) os.unlink(tmpfile)
def save(self, path, overwrite=True): if os.path.exists(path) and not overwrite: raise ValueError, 'Path exists: %s' % path with open(path, 'w') as fd: fd.write(self.format()) logger.info1('Saved file %s' % os.path.abspath(path))
def tpr_get_scalar(tpr, name, mktype): logger.info1('Getting', name, 'from', tpr) tmpfile = os.path.join(os.path.dirname(tpr), name+'.gps') guamps_get(f=tpr, s=name, o=tmpfile) with open(tmpfile) as fd: value = fd.readline() value = mktype(value) os.unlink(tmpfile) return value
def wait(self): result = self.wq.wait(self._timeout) if result: logger.info1('%-15s' % 'Received', result.uuid) taskable = self._table[result.uuid] taskable.update_task(result) del self._table[result.uuid] self._persist(taskable) return taskable
def tpr_get_scalar(tpr, name, mktype): logger.info1('Getting', name, 'from', tpr) tmpfile = os.path.join(os.path.dirname(tpr), name + '.gps') guamps_get(f=tpr, s=name, o=tmpfile) with open(tmpfile) as fd: value = fd.readline() value = mktype(value) os.unlink(tmpfile) return value
def save(self, prefix=None, name='experiment.yaml'): prefix = self.name if prefix is None else prefix pxul.os.ensure_dir(prefix) ypath = os.path.join(prefix, name) with open(ypath, 'w') as fd: logger.info('Saving experiments:', fd.name) yaml.dump(self, fd, default_flow_style=False) logger.info1('Writing children') for k, r in self.runs.iteritems(): r.save(prefix=os.path.join(self.name, str(k)))
def initialize(self, pdb, ff='amber03', water='tip3p', ignh=True): logger.info1('Importing to GMX format') top = suffix.top(self.cn) gmx.pdb2gmx(f=pdb, o=suffix.gro(self.cn), p=top, ff=ff, water=water, ignh=ignh) self._top = top self._pn = self.cn
def initialize(self, pdb, ff='amber03', water='tip3p', ignh=True): logger.info1('Importing to GMX format') top = suffix.top(self.cn) gmx.pdb2gmx( f = pdb, o = suffix.gro(self.cn), p = top, ff = ff, water = water, ignh = ignh) self._top = top self._pn = self.cn
def minimize_vacuum(self, mdp): logger.info1('Minimization in vacuum') self._cn = self.name + '_EMV' cn, pn = self.cn, self.pn mdp_path = suffix.mdp(self.cn) mdp.save(mdp_path) tpr = suffix.tpr(cn) gmx.grompp(f=mdp_path, c=suffix.gro(pn), p=suffix.top(pn), o=tpr) gmx.mdrun( s=tpr, deffnm=cn, c=suffix.pdb(cn), nt=1, ) self._pn = self._cn
def equilibrate(self, mdp, steps=None): logger.info1('Equilibrating') self._cn = self.name + '_eq' if steps is not None: mdp.nsteps = steps mdp_path = suffix.mdp(self.cn) mdp.unset_velocity_generation() mdp.save(mdp_path) gmx.grompp(f=mdp_path, c=suffix.gro(self.pn), t=suffix.trr(self.pn), p=self.top, o=suffix.tpr(self.cn)) gmx.mdrun(s=suffix.tpr(self.cn), deffnm=self.cn, v=True)
def main(opts): if os.path.exists(state.CONFIG): logger.info1('Loading previous state from', state.CONFIG) cfg = state.Config.load(path=state.CONFIG) else: cfg = state.Config() cfg.update( backend = opts.backend, generations = opts.generations, time = opts.time, outputfreq = opts.outputfreq, cpus = opts.cpus, binaries = opts.binaries, seed = opts.seed ) cfg.write() logger.info('Configured:\n', str(cfg))
def minimize_vacuum(self, mdp): logger.info1('Minimization in vacuum') self._cn = self.name + '_EMV' cn, pn = self.cn, self.pn mdp_path = suffix.mdp(self.cn) mdp.save(mdp_path) tpr = suffix.tpr(cn) gmx.grompp( f = mdp_path, c = suffix.gro(pn), p = suffix.top(pn), o = tpr ) gmx.mdrun( s = tpr, deffnm = cn, c = suffix.pdb(cn), nt = 1, ) self._pn = self._cn
def equilibrate(self, mdp, steps=None): logger.info1('Equilibrating') self._cn = self.name + '_eq' if steps is not None: mdp.nsteps = steps mdp_path = suffix.mdp(self.cn) mdp.unset_velocity_generation() mdp.save(mdp_path) gmx.grompp( f = mdp_path, c = suffix.gro(self.pn), t = suffix.trr(self.pn), p = self.top, o = suffix.tpr(self.cn) ) gmx.mdrun( s = suffix.tpr(self.cn), deffnm = self.cn, v = True )
def prepare(self, pdb, ff = 'amber03', water = 'tip3p', ignh = True, mdp_min_vac = None, mdp_min_sol = None, mdp_run = None, iter_gammas = None, iter_steps = 500, eq_steps = 500, seed = None): cwd = os.getcwd() logger.info('Preparing %s with %s in %s' % (os.path.relpath(pdb, cwd), ff, cwd)) pdb = os.path.abspath(pdb) wa = os.path.join(self.workarea) name = os.path.splitext(os.path.basename(pdb))[0] mdp_min_vac = mdp_defaults.minimize_vacuum() if mdp_min_vac is None else mdp_min_vac.copy() mdp_min_sol = mdp_defaults.minimize_solvated() if mdp_min_sol is None else mdp_min_sol.copy() mdp_run = mdp_defaults.explicit_solvent() if mdp_run is None else mdp_run.copy() if seed is not None: mdp_run.seed(seed) self.name = name self._cn = name with pxul.os.StackDir(wa): self.initialize(pdb, ff=ff, water=water, ignh=ignh) self.minimize_vacuum(mdp_min_vac) self.solvate(mdp_min_sol) self.relax(copy.deepcopy(mdp_run), gammas=iter_gammas, steps=iter_steps) self.equilibrate(copy.deepcopy(mdp_run), steps=eq_steps) if not name: name = self.name conf = suffix.gro(name), suffix.gro(self.pn) top = suffix.top(name), self.top itp = suffix.itp(name), 'posre.itp' mdp = suffix.mdp(name) for new, old in [conf, top, itp]: shutil.copy(os.path.join(self.workarea, old), new) logger.info1('Saved file %s' % os.path.abspath(new)) with open(mdp, 'w') as fd: fd.write(str(mdp_run)) logger.info1('Saved file', os.path.abspath(fd.name)) # create tpr with velocities logger.info1('Creating run tpr') conf = conf[0] top = top[0] mdout = suffix.mdp('{}_mdout'.format(name)) tpr = suffix.tpr(name) gmx.grompp(f=mdp, c=conf, po=mdout, p=top, o=tpr, t=suffix.trr(os.path.join(self.workarea, self.pn))) return dict(conf=conf,top=top,mdout=mdout,tpr=tpr)
def task(self, tpr, x=None, v=None, t=None, outputdir=None, seed=None, digest=None): outdir = outputdir or tpr + '.mdq' pxul.os.ensure_dir(outdir) logger.debug('Ensured', outdir, 'exists') tpr2 = os.path.join(outdir, 'topol.tpr') shutil.copy(tpr, tpr2) logger.debug(tpr, '->', tpr2) gendir = os.path.join(outdir, '0') pxul.os.ensure_dir(gendir) logger.debug('Ensured', gendir, 'exists') gps = dict(x=os.path.join(gendir, SCRIPT_INPUT_NAMES['x']), v=os.path.join(gendir, SCRIPT_INPUT_NAMES['v']), t=os.path.join(gendir, SCRIPT_INPUT_NAMES['t'])) if x is not None: shutil.copy(x, gps['x']) logger.debug(x, '->', gps['x']) if v is not None: shutil.copy(v, gps['v']) logger.debug(v, '->', gps['v']) if t is not None: if type(t) is float: with open(gps['t'], 'w') as fd: fd.write(str(t)) logger.debug('Wrote', t, 'to', gps['t']) elif type(t) is str: shutil.copy(t, gps['t']) logger.debug(t, '->', gps['t']) else: raise ValueError, 'Illegal state: invalid time spec %s' % t for sel, key in SELECTIONS.iteritems(): logger.info1('Getting', sel, 'from', tpr2) guamps_get(f=tpr2, s=sel, o=gps[key]) if seed: logger.info1('Setting seed', seed) tpr_set_scalar(tpr2, 'ld_seed', seed) dt = tpr_get_scalar(tpr2, 'deltat', float) if self._picoseconds: nsteps = int(self._picoseconds / dt) logger.info1('Running for', self._picoseconds, 'ps as', nsteps, 'nsteps') tpr_set_scalar(tpr2, 'nsteps', nsteps) if self._outputfreq: freq = int(self._outputfreq / dt) # FIXME nstenergy, see badi/guamps#27 for attr in 'nstxout nstxtcout nstfout nstvout nstlog'.split(): logger.info1('Setting output frequency', self._outputfreq, 'for', attr, 'as', freq, 'steps', 'in', tpr2) tpr_set_scalar(tpr2, attr, freq) if not digest: logger.info1('Computing digest for', tpr2) sha256 = hashlib.sha256() sha256.update(open(tpr2, 'rb').read()) digest = sha256.hexdigest() task = Task(x=gps['x'], v=gps['v'], t=gps['t'], tpr=tpr2, outputdir=outdir, cpus=self._cpus, digest=digest) task.add_binary(self._mdrun) task.add_binary(self._guamps_get) task.add_binary(self._guamps_set) if self._keep_trajfiles: task.keep_trajfiles() logger.info('Prepared', digest, 'from', tpr) for k in self.__dict__: logger.info(10 * ' ', k.lstrip('_'), '=', getattr(self, k)) return task
def solvate(self, mdp, boxtype='triclinic', boxdist=1.0, solv='spc216.gro', concentration=0.15, neutral=True, pname='NA', nname='CL'): nbox = self.name + '_box' nwat = self.name + '_wat' nsolv = self.name + '_sol' logger.info1('Solvating') self._cn = nbox gmx.editconf( f = suffix.pdb(self.pn), o = suffix.gro(nbox), bt = boxtype, d = boxdist, ) self._cn = nwat gmx.genbox( cp = suffix.gro(nbox), cs = solv, p = self.top, o = suffix.gro(self.cn) ) gmx.grompp( f = suffix.mdp(self.pn), c = suffix.gro(self.cn), p = self.top, o = suffix.tpr(self.cn) ) # create atom indices for water pdb = suffix.pdb(self.cn) gmx.editconf( f = suffix.tpr(self.cn), o = pdb ) top = prody.parsePDB(pdb) sel = top.select('resname is SOL') idx = sel.getIndices() idx += 1 # GMX starts with 1, prody with 0 ndx = suffix.ndx(nwat) with open(ndx, 'w') as fd: fd.write('[ SOL ] \n') # GMX has a limited buffer for read ndx files idx = map(str, idx) idx = ' '.join(idx) idx = textwrap.wrap(idx) idx = '\n'.join(idx) fd.write(idx + '\n') gmx.genion( n = ndx, s = suffix.tpr(nwat), o = suffix.gro(nsolv), conc = concentration, neutral = neutral, pname = pname, nname = nname ) # figure out the number of solvent, cation, and anion molecules logger.info1('Calculating number of solvent, cation, and anion molecules') conf = open(suffix.gro(nsolv)).readlines() nsol = count_occurences('SOL', conf) / 3 ncat = count_occurences(pname, conf) nani = count_occurences(nname, conf) del conf # write a new topology file with the updated counts logger.info1('Generating new topology file') top = open(self.top).readlines() top = top[:-1] # the last line containts the number of solvent molecules, which is outdated top.append('SOL %s\n' % nsol) top.append('%s %s\n' % (pname, ncat)) top.append('%s %s\n' % (nname, nani)) top = ''.join(top) self._top = suffix.top(nsolv) open(self.top, 'w').write(top) self._pn = nsolv self._cn = nsolv # minimize the solvated system logger.info1('Minimizaing solvated system') mdp_path = suffix.mdp(self.cn) mdp.save(mdp_path) tpr = suffix.tpr(self.cn) gmx.grompp( f = mdp_path, c = suffix.gro(self.cn), p = self.top, o = tpr ) gmx.mdrun( s = tpr, deffnm = self.cn, ) self._pv = self.cn
def save(self, prefix='.', name='run.yaml'): pxul.os.ensure_dir(prefix) ypath = os.path.join(prefix, name) with open(ypath, 'w') as fd: logger.info1('Saving', fd.name) yaml.dump(self, fd)
def prepare(self, pdb, ff='amber03', water='tip3p', ignh=True, mdp_min_vac=None, mdp_min_sol=None, mdp_run=None, iter_gammas=None, iter_steps=500, eq_steps=500, seed=None): cwd = os.getcwd() logger.info('Preparing %s with %s in %s' % (os.path.relpath(pdb, cwd), ff, cwd)) pdb = os.path.abspath(pdb) wa = os.path.join(self.workarea) name = os.path.splitext(os.path.basename(pdb))[0] mdp_min_vac = mdp_defaults.minimize_vacuum( ) if mdp_min_vac is None else mdp_min_vac.copy() mdp_min_sol = mdp_defaults.minimize_solvated( ) if mdp_min_sol is None else mdp_min_sol.copy() mdp_run = mdp_defaults.explicit_solvent( ) if mdp_run is None else mdp_run.copy() if seed is not None: mdp_run.seed(seed) self.name = name self._cn = name with pxul.os.StackDir(wa): self.initialize(pdb, ff=ff, water=water, ignh=ignh) self.minimize_vacuum(mdp_min_vac) self.solvate(mdp_min_sol) self.relax(copy.deepcopy(mdp_run), gammas=iter_gammas, steps=iter_steps) self.equilibrate(copy.deepcopy(mdp_run), steps=eq_steps) if not name: name = self.name conf = suffix.gro(name), suffix.gro(self.pn) top = suffix.top(name), self.top itp = suffix.itp(name), 'posre.itp' mdp = suffix.mdp(name) for new, old in [conf, top, itp]: shutil.copy(os.path.join(self.workarea, old), new) logger.info1('Saved file %s' % os.path.abspath(new)) with open(mdp, 'w') as fd: fd.write(str(mdp_run)) logger.info1('Saved file', os.path.abspath(fd.name)) # create tpr with velocities logger.info1('Creating run tpr') conf = conf[0] top = top[0] mdout = suffix.mdp('{}_mdout'.format(name)) tpr = suffix.tpr(name) gmx.grompp(f=mdp, c=conf, po=mdout, p=top, o=tpr, t=suffix.trr(os.path.join(self.workarea, self.pn))) return dict(conf=conf, top=top, mdout=mdout, tpr=tpr)
def task(self, tpr, x=None, v=None, t=None, outputdir=None, seed=None, digest=None): outdir = outputdir or tpr + '.mdq' pxul.os.ensure_dir(outdir) logger.debug('Ensured', outdir, 'exists') tpr2 = os.path.join(outdir, 'topol.tpr') shutil.copy(tpr, tpr2) logger.debug(tpr, '->', tpr2) gendir = os.path.join(outdir, '0') pxul.os.ensure_dir(gendir) logger.debug('Ensured', gendir, 'exists') gps = dict(x = os.path.join(gendir, SCRIPT_INPUT_NAMES['x']), v = os.path.join(gendir, SCRIPT_INPUT_NAMES['v']), t = os.path.join(gendir, SCRIPT_INPUT_NAMES['t'])) if x is not None: shutil.copy(x, gps['x']) logger.debug(x, '->', gps['x']) if v is not None: shutil.copy(v, gps['v']) logger.debug(v, '->', gps['v']) if t is not None: if type(t) is float: with open(gps['t'], 'w') as fd: fd.write(str(t)) logger.debug('Wrote', t, 'to', gps['t']) elif type(t) is str: shutil.copy(t, gps['t']) logger.debug(t, '->', gps['t']) else: raise ValueError, 'Illegal state: invalid time spec %s' % t for sel, key in SELECTIONS.iteritems(): logger.info1('Getting', sel, 'from', tpr2) guamps_get(f=tpr2, s=sel, o=gps[key]) if seed: logger.info1('Setting seed', seed) tpr_set_scalar(tpr2, 'ld_seed', seed) dt = tpr_get_scalar(tpr2, 'deltat', float) if self._picoseconds: nsteps = int(self._picoseconds / dt) logger.info1('Running for', self._picoseconds, 'ps as', nsteps, 'nsteps') tpr_set_scalar(tpr2, 'nsteps', nsteps) if self._outputfreq: freq = int(self._outputfreq / dt) # FIXME nstenergy, see badi/guamps#27 for attr in 'nstxout nstxtcout nstfout nstvout nstlog'.split(): logger.info1('Setting output frequency', self._outputfreq, 'for', attr, 'as', freq, 'steps', 'in', tpr2) tpr_set_scalar(tpr2, attr, freq) if not digest: logger.info1('Computing digest for', tpr2) sha256 = hashlib.sha256() sha256.update(open(tpr2, 'rb').read()) digest = sha256.hexdigest() task = Task(x=gps['x'], v=gps['v'], t=gps['t'], tpr=tpr2, outputdir=outdir, cpus=self._cpus, digest=digest) task.add_binary(self._mdrun) task.add_binary(self._guamps_get) task.add_binary(self._guamps_set) if self._keep_trajfiles: task.keep_trajfiles() logger.info('Prepared', digest, 'from', tpr) for k in self.__dict__: logger.info(10*' ', k.lstrip('_'), '=', getattr(self, k)) return task
def tpr_set_scalar(tpr, name, value): logger.info1('Setting', name, '=', value, 'in', tpr) tmpfile = os.path.join(os.path.dirname(tpr), name +'.gps') with open(tmpfile, 'w') as fd: fd.write('%s\n' % value) guamps_set(f=tpr, s=name, i=tmpfile, O=True) os.unlink(tmpfile)
def solvate(self, mdp, boxtype='triclinic', boxdist=1.0, solv='spc216.gro', concentration=0.15, neutral=True, pname='NA', nname='CL'): nbox = self.name + '_box' nwat = self.name + '_wat' nsolv = self.name + '_sol' logger.info1('Solvating') self._cn = nbox gmx.editconf( f=suffix.pdb(self.pn), o=suffix.gro(nbox), bt=boxtype, d=boxdist, ) self._cn = nwat gmx.genbox(cp=suffix.gro(nbox), cs=solv, p=self.top, o=suffix.gro(self.cn)) gmx.grompp(f=suffix.mdp(self.pn), c=suffix.gro(self.cn), p=self.top, o=suffix.tpr(self.cn)) # create atom indices for water pdb = suffix.pdb(self.cn) gmx.editconf(f=suffix.tpr(self.cn), o=pdb) top = prody.parsePDB(pdb) sel = top.select('resname is SOL') idx = sel.getIndices() idx += 1 # GMX starts with 1, prody with 0 ndx = suffix.ndx(nwat) with open(ndx, 'w') as fd: fd.write('[ SOL ] \n') # GMX has a limited buffer for read ndx files idx = map(str, idx) idx = ' '.join(idx) idx = textwrap.wrap(idx) idx = '\n'.join(idx) fd.write(idx + '\n') gmx.genion(n=ndx, s=suffix.tpr(nwat), o=suffix.gro(nsolv), conc=concentration, neutral=neutral, pname=pname, nname=nname) # figure out the number of solvent, cation, and anion molecules logger.info1( 'Calculating number of solvent, cation, and anion molecules') conf = open(suffix.gro(nsolv)).readlines() nsol = count_occurences('SOL', conf) / 3 ncat = count_occurences(pname, conf) nani = count_occurences(nname, conf) del conf # write a new topology file with the updated counts logger.info1('Generating new topology file') top = open(self.top).readlines() top = top[: -1] # the last line containts the number of solvent molecules, which is outdated top.append('SOL %s\n' % nsol) top.append('%s %s\n' % (pname, ncat)) top.append('%s %s\n' % (nname, nani)) top = ''.join(top) self._top = suffix.top(nsolv) open(self.top, 'w').write(top) self._pn = nsolv self._cn = nsolv # minimize the solvated system logger.info1('Minimizaing solvated system') mdp_path = suffix.mdp(self.cn) mdp.save(mdp_path) tpr = suffix.tpr(self.cn) gmx.grompp(f=mdp_path, c=suffix.gro(self.cn), p=self.top, o=tpr) gmx.mdrun( s=tpr, deffnm=self.cn, ) self._pv = self.cn