def test_failure(cleandir): """The operation should not deliver file output if the subprocess fails.""" file1 = os.path.join(cleandir, 'input') file2 = os.path.join(cleandir, 'output') # Make a shell script that acts like the type of tool we are wrapping. scriptname = os.path.join(cleandir, 'clicommand.sh') with open(scriptname, 'w') as fh: fh.write('\n'.join([ '#!' + shutil.which('bash'), '# Concatenate an input file and a string argument to an output file.', '# Mock a utility with the tested syntax.', '# clicommand.sh "some words" -i inputfile -o outputfile', 'exit 1\n' ])) os.chmod(scriptname, stat.S_IRWXU) filewriter1 = gmx.commandline_operation(scriptname, input_files={'-i': os.devnull}, output_files={'-o': file1}) filewriter2 = gmx.commandline_operation( scriptname, input_files={'-i': filewriter1.output.file['-o']}, output_files={'-o': file2}) # filewriter1 has a non-zero exit code and should have no output files available. with pytest.raises(KeyError): filewriter2.run()
def test_operation_dependence(self): """Confirm that dependent operations are only executed after their dependencies. In a sequence of two operations, write a two-line file one line at a time. Use a user-provided filename as a parameter to each operation. """ with tempfile.TemporaryDirectory() as directory: fh, filename = tempfile.mkstemp(dir=directory) os.close(fh) line1 = 'first line' subcommand = ' '.join( ['echo', '"{}"'.format(line1), '>>', filename]) commandline = ['-c', subcommand] filewriter1 = commandline_operation('bash', arguments=commandline) line2 = 'second line' subcommand = ' '.join( ['echo', '"{}"'.format(line2), '>>', filename]) commandline = ['-c', subcommand] filewriter2 = commandline_operation('bash', arguments=commandline, input=filewriter1) filewriter2.run() # Check that the file has the two expected lines with open(filename, 'r') as fh: lines = [text.rstrip() for text in fh] assert len(lines) == 2 assert lines[0] == line1 assert lines[1] == line2
def test_fr2(): """FR2: Output proxy establishes execution dependency. Confirm that dependent operations are only executed after their dependencies. In a sequence of two operations, write a two-line file one line at a time. Use a user-provided filename as a parameter to each operation. """ with tempfile.TemporaryDirectory() as directory: fh, filename = tempfile.mkstemp(dir=directory) os.close(fh) line1 = 'first line' subcommand = ' '.join(['echo', '"{}"'.format(line1), '>>', filename]) commandline = ['-c', subcommand] filewriter1 = gmx.commandline_operation('bash', arguments=commandline) line2 = 'second line' subcommand = ' '.join(['echo', '"{}"'.format(line2), '>>', filename]) commandline = ['-c', subcommand] filewriter2 = gmx.commandline_operation('bash', arguments=commandline, input=filewriter1) filewriter2.run() # Check that the file has the two expected lines with open(filename, 'r') as fh: lines = [text.rstrip() for text in fh] assert len(lines) == 2 assert lines[0] == line1 assert lines[1] == line2
def single_prep( self, name, #log = False, template="", additions=None, restrained=False): # Preperes a run and runs it. mdp_create(file_name=name + ".mdp", new_parameters=self.mdp_settings[name], new_keys=self.mdp_settings[name + "_keys"], old_file=template) executable = "gmx" arguments = ["grompp"] input_files = { "-f": name + ".mdp", "-c": self.configuration_file, "-p": "topol.top" } output_files = {"-o": name + ".tpr"} print("input_files:\n", input_files, "\noutput_files:\n", output_files) if additions: if "in" in additions: append_dict(input_files, additions["in"]) if "out" in additions: append_dict(output_files, additions["out"]) prep = gmx.commandline_operation(executable=executable, arguments=arguments, input_files=input_files, output_files=output_files) prep.run() print("prep " + name + ":\n", prep.output.erroroutput.result()) return prep
def grompp( structure_file: str, mdp_file: str, topology_file: str, index_file: str, tpr_file: str, mdp_output_file: str, ): input_files = { "-n": index_file, "-f": mdp_file, "-p": topology_file, "-c": structure_file, } output_files = {"-o": tpr_file, "-po": mdp_output_file} prep = gmx.commandline_operation( executable="gmx", arguments=["grompp"], input_files=input_files, output_files=output_files, ) prep.run() output = str(prep.output.erroroutput.result()).strip() if output: logger.info("grompp output:\n%s", output) return prep
def single_run(self, name, log = False, template = "", additions = None): # Preperes a run and runs it. mdp_create(file_name = name + ".mdp", new_parameters = self.mdp_settings[name], old_file = template) executable = "gmx" arguments = ["grompp"] input_files = {"-f": name + ".mdp", "-c": self.configuration_file, "-p": "topol.top"} output_files = {"-o" : name + ".tpr"} #print(name, "", executable, arguments, input_files, output_files,"","",sep="\n") if additions: if "in" in additions: append_dict(input_files, additions["in"]) if "out" in additions: append_dict(output_files, additions["out"]) #print(name, "", executable, arguments, input_files, output_files,"","",sep="\n") prep = gmx.commandline_operation(executable = executable, arguments = arguments, input_files = input_files, output_files = output_files) prep.run() print("prep "+ name + ":\n", prep.output.erroroutput.result()) mdrun = gmx.read_tpr(prep.output.file["-o"]) md = gmx.mdrun(mdrun) md.run() path = md.output.trajectory.result() path = path[:path.rfind("/") + 1] self.configuration_file = path + "confout.gro" if log: self.history.append(self.configuration_file) self.latest_path = path shutil.move(name + ".mdp", path + name + ".mdp")
def ions(self, new_parameters=None, new_keys=None, ions=None): # Adding ions to box if new_parameters == None: new_parameters = {} new_keys = [] if new_keys == None: new_keys = list(new_parameters.keys()) #ion_top = ".".join(self.configuration_file.split(".")[:-1]) + ".tpr" if ions is None or "pname" not in ions: pname = "NA" #get_pname() else: pname = ions["pname"] if ions is None or "nname" not in ions: nname = "CL" #get_nname() else: nname = ions["nname"] sim_name = "ions" self.mdp_settings[sim_name] = new_parameters self.mdp_settings[sim_name + "_keys"] = new_keys prep = self.single_prep(name=sim_name, template="mdp_templates/ions.mdp.templ") genion = gmx.commandline_operation( executable="gmx", arguments=["genion", "-pname", pname, "-nname", nname, "-neutral"], input_files={ "-s": prep.output.file["-o"], "-p": "topol.top" }, output_files={"-o": "ion_" + self.configuration_file}, stdin="SOL") genion.run() self.configuration_file = "ion_" + self.configuration_file self.make_index() print("ionate:\n", genion.output.erroroutput.result())
def test_fr9(): """FR9: *gmx.mdrun supports interface for binding MD plugins* (requires interaction with library development) """ import sample_restraint starting_structure = 'input_conf.gro' topology_file = 'input.top' run_parameters = 'params.mdp' initial_tpr = gmx.commandline_operation( 'gmx', 'grompp', input={ '-f': run_parameters, '-c': starting_structure, '-p': topology_file }, output={'-o': gmx.OutputFile('.tpr')}) simulation_input = gmx.read_tpr(initial_tpr.output.file['-o']) # Prepare a simple harmonic restraint between atoms 1 and 4 restraint_params = {'sites': [1, 4], 'R0': 2.0, 'k': 10000.0} restraint = sample_restraint.harmonic_restraint(input=restraint_params) md = gmx.mdrun(input=simulation_input, potential=sample_restraint)
def test_data_dependence(self): """Confirm that data dependencies correctly establish resolvable execution dependencies. In a sequence of two operations, write a two-line file one line at a time. Use the output of one operation as the input of another. """ with tempfile.TemporaryDirectory() as directory: file1 = os.path.join(directory, 'input') file2 = os.path.join(directory, 'output') # Make a shell script that acts like the type of tool we are wrapping. scriptname = os.path.join(directory, 'clicommand.sh') with open(scriptname, 'w') as fh: fh.write('\n'.join([ '#!' + shutil.which('bash'), '# Concatenate an input file and a string argument to an output file.', '# Mock a utility with the tested syntax.', '# clicommand.sh "some words" -i inputfile -o outputfile', 'echo $1 | cat $3 - > $5\n' ])) os.chmod(scriptname, stat.S_IRWXU) line1 = 'first line' filewriter1 = commandline_operation(scriptname, arguments=[line1], input_files={'-i': os.devnull}, output_files={'-o': file1}) line2 = 'second line' filewriter2 = commandline_operation( scriptname, arguments=[line2], input_files={'-i': filewriter1.output.file['-o']}, output_files={'-o': file2}) filewriter2.run() # Check that the files have the expected lines with open(file1, 'r') as fh: lines = [text.rstrip() for text in fh] assert len(lines) == 1 assert lines[0] == line1 with open(file2, 'r') as fh: lines = [text.rstrip() for text in fh] assert len(lines) == 2 assert lines[0] == line1 assert lines[1] == line2
def mdrun( mpi_rank: int, output_dir: str, tpr_file: str, check_point_file: str = None, mdrun_options: list = None, gpus_per_node: int = None, ): mpi_rank = mpi_rank - 1 cwd = os.path.abspath(os.getcwd()) os.chdir(output_dir) input_files = {"-s": tpr_file} if check_point_file is not None: input_files["-cpi"] = check_point_file # SPC increased state printing to every 5 minutes since swarms are short if mdrun_options is None: mdrun_options_parse = [] else: mdrun_options_parse = mdrun_options # Search for -nt number of threads option in mdrun_options. for i, o in enumerate(mdrun_options): if o == "-nt": number_threads = int(mdrun_options[i + 1]) pin_offset = str(mpi_rank * number_threads) mdrun_options_parse += [ "-pin", "on", "-pinoffset", f"{pin_offset}", "-pinstride", "1", ] break if gpus_per_node is not None: mpi_rank = str(mpi_rank % gpus_per_node) mdrun_options_parse += ["-gpu_id", f"{mpi_rank}"] md = gmx.commandline_operation( executable="gmx", arguments=["mdrun", "-cpt", "5"] + mdrun_options_parse, input_files=input_files, output_files={}, ) md.run() output = str(md.output.erroroutput.result()).strip() if output: logger.info("mdrun output:\n%s", output) os.chdir(cwd) # simulation_input = gmx.read_tpr(tpr_file) # md = gmx.mdrun(input=simulation_input) # md.run() # path = md.output.trajectory.result() # path = path[:path.rfind("/") + 1] # _move_all_files(path, output_dir) # os.removedirs(path) return md
def test_fr1(): """FR1: Wrap importable Python code. gmxapi compatible operations are implemented with simple machinery that allows compartmentalized progress on functionality to be highly decoupled from implementing user-facing tools. Tools are provided in `gmx.operation` and demonstrated by implementing `gmx.commandline_operation`. """ # commandline_operation helper creates a set of operations # that includes the discovery and execution of the program # named in `executable`. operation = gmx.commandline_operation(executable='true') operation.run() assert operation.output.returncode.result() == 0 operation = gmx.commandline_operation(executable='false') operation.run() assert operation.output.returncode.result() == 1
def test_file_dependency_chain(cleandir): """Test the command line wrapper input/output file handling. Operation output can be used as operation input. """ file1 = os.path.join(cleandir, 'input') file2 = os.path.join(cleandir, 'output') # Make a shell script that acts like the type of tool we are wrapping. scriptname = os.path.join(cleandir, 'clicommand.sh') with open(scriptname, 'w') as fh: fh.write('\n'.join([ '#!' + shutil.which('bash'), '# Concatenate an input file and a string argument to an output file.', '# Mock a utility with the tested syntax.', '# clicommand.sh "some words" -i inputfile -o outputfile', 'echo $1 | cat $3 - > $5\n' ])) os.chmod(scriptname, stat.S_IRWXU) line1 = 'first line' filewriter1 = gmx.commandline_operation(scriptname, arguments=[line1], input_files={'-i': os.devnull}, output_files={'-o': file1}) line2 = 'second line' filewriter2 = gmx.commandline_operation( scriptname, arguments=[line2], input_files={'-i': filewriter1.output.file['-o']}, output_files={'-o': file2}) filewriter2.run() # Check that the files have the expected lines with open(file1, 'r') as fh: lines = [text.rstrip() for text in fh] assert len(lines) == 1 assert lines[0] == line1 with open(file2, 'r') as fh: lines = [text.rstrip() for text in fh] assert len(lines) == 2 assert lines[0] == line1 assert lines[1] == line2
def box(self): # Creates MD-simulation box file_name = self.configuration_file box = gmx.commandline_operation( executable="gmx", arguments=["editconf", "-c", "-d", "1.0", "-bt", "cubic"], input_files={"-f": file_name}, output_files={"-o": "box" + file_name}) box.run() shutil.move("box" + file_name, file_name)
def split_traj(self): traj = gmx.commandline_operation(executable = "gmx", arguments = ["trjconv", "-sep"], input_files = {"-s": self.latest_path + "topol.tpr", "-f": self.latest_path + "traj_comp.xtc"}, output_files = {"-o": self.latest_path + "conf.gro"}, stdin = "0") traj.run() print("split_traj:\n", traj.output.erroroutput.result()) return self.latest_path
def test_fr3(): """FR3: Output proxy can be used as input.""" with tempfile.TemporaryDirectory() as directory: file1 = os.path.join(directory, 'input') file2 = os.path.join(directory, 'output') # Make a shell script that acts like the type of tool we are wrapping. scriptname = os.path.join(directory, 'clicommand.sh') with open(scriptname, 'w') as fh: fh.write('\n'.join(['#!' + shutil.which('bash'), '# Concatenate an input file and a string argument to an output file.', '# Mock a utility with the tested syntax.', '# clicommand.sh "some words" -i inputfile -o outputfile', 'echo $1 | cat $3 - > $5\n'])) os.chmod(scriptname, stat.S_IRWXU) line1 = 'first line' filewriter1 = gmx.commandline_operation(scriptname, arguments=[line1], input_files={'-i': os.devnull}, output_files={'-o': file1}) line2 = 'second line' filewriter2 = gmx.commandline_operation(scriptname, arguments=[line2], input_files={'-i': filewriter1.output.file['-o']}, output_files={'-o': file2}) filewriter2.run() # Check that the files have the expected lines with open(file1, 'r') as fh: lines = [text.rstrip() for text in fh] assert len(lines) == 1 assert lines[0] == line1 with open(file2, 'r') as fh: lines = [text.rstrip() for text in fh] assert len(lines) == 2 assert lines[0] == line1 assert lines[1] == line2
def make_index(c_file, o_file): # Generates index file for simulation runs b_file_name = backup_file(o_file, copy=False) maker = gmx.commandline_operation( executable="gmx", arguments=["make_ndx"], input_files={ "-f": c_file #, #"-n": b_file_name }, output_files={"-o": o_file}, stdin="q\n") maker.run() shutil.copyfileobj(open(b_file_name, "rb"), open(o_file, "ab")) log("make_index:\n" + str(maker.output.erroroutput.result()))
def get_angle(topology_file, index_file): angler = gmx.commandline_operation( executable="gmx", arguments=["gangle", "-g1", "dihedral", "-group1", "dihedrals"], input_files={ "-s": topology_file, "-n": index_file }, output_files={"-oall": "temp.xvg"}) angler.run() result = open("temp.xvg").read().split("\n")[-2] angles = result.split()[1:] #print(angles) angles = [float(angle) for angle in angles] os.remove("temp.xvg") return angles
def solvate(self, new_parameters=None): # Solvates box if 0 == self.is_solvated: file_name = self.configuration_file shutil.copyfile(self.topology_file, "unsol" + self.topology_file) solvate = gmx.commandline_operation( executable="gmx", arguments=["solvate"], input_files={ "-cp": file_name, "-p": self.topology_file }, output_files={"-o": "solv_" + file_name}) solvate.run() print("solvate:\n", solvate.output.erroroutput.result()) self.configuration_file = "solv_" + file_name self.is_solvated = 1
def test_fr4(): """FR4: Dimensionality and typing of named data causes generation of correct work topologies.""" N = 10 simulation_input = gmx.read_tpr(initial_tpr) # Array inputs imply array outputs. input_array = gmx.modify_input( simulation_input, params={'tau-t': [t / 10.0 for t in range(N)]}) md = gmx.mdrun(input_array) # An array of simulations rmsf = gmx.commandline_operation( 'gmx', 'rmsf', input={ '-f': md.output.trajectory, '-s': initial_tpr }, output={'-o': gmx.FileName(suffix='.xvg')})
def get_distance(conf_file, index_file, cv): # Extracts one CV distance from a Configuration file gr_sel = "com of group \"" + cv.pull_groups[0].get_name() +\ "\" plus com of group \"" +cv.pull_groups[1].get_name() + "\"" distancer = gmx.commandline_operation( executable="gmx", arguments=["distance", "-select", gr_sel], input_files={ "-s": conf_file, "-n": index_file }, output_files={"-oall": "temp.xvg"}) distancer.run() err = distancer.output.erroroutput.result() if err != "": print("get_distance:\n", err) result = open("temp.xvg").read().split("\n")[-2] dist = result.split()[-1] os.remove("temp.xvg") return [float(dist)]
def get_angle(conf_file, index_file): # Calls Gromacs gangle and the extracts dihedrals from resulting file angler = gmx.commandline_operation( executable="gmx", arguments=["gangle", "-g1", "dihedral", "-group1", "dihedrals"], input_files={ "-s": conf_file, "-n": index_file }, output_files={"-oall": "temp.xvg"}) angler.run() err = angler.output.erroroutput.result() if err != "": print("get_angle:\n", err) return [] result = open("temp.xvg").read().split("\n")[-2] angles = result.split()[1:] angles = [float(angle) for angle in angles] os.remove("temp.xvg") return angles
def single_prep( self, name, #log = False, template="", additions=None, restrained=False): new_path = self.main_path + name + "/" try: os.listdir(new_path) return None except FileNotFoundError: pass # Preperes an MD run mdp_create(file_name=name + ".mdp", new_parameters=self.mdp_settings[name], new_keys=self.mdp_settings[name + "_keys"], old_file=template) executable = "gmx" arguments = ["grompp"] input_files = { "-f": name + ".mdp", "-c": self.configuration_file, "-p": "topol.top" } output_files = {"-o": name + ".tpr"} print("input_files:\n", input_files, "\noutput_files:\n", output_files) if additions: if "in" in additions: append_dict(input_files, additions["in"]) if "out" in additions: append_dict(output_files, additions["out"]) prep = gmx.commandline_operation(executable=executable, arguments=arguments, input_files=input_files, output_files=output_files) prep.run() log("prep " + name + ":\n" + str(prep.output.erroroutput.result())) #input("Paus") return prep
def main(): print('''Welcome to an automated run of the Gromacs Lysozyme tutorial, this program should work on most systems containable within the same simulation box. Some files are necessary for running the program: - a *.pdb file describing a protein. - an "ions.mdp" file for the ion placement configurations - an "minim.mdp" file for energy minimization configurations - "nvt.mdp" AND "npt.mdp" files for equilibration" - "md.mdp" for the md run configurations.\n\n ''') try: #file_name = select_file("Please type the .pdb files name: ") file_name = "1aki.pdb" clean_name = clean_h2o(file_name, False) out_name = "processed_" + ".".join(file_name.split(".")[:-1]) + ".gro" box_name = "newbox_" + ".".join(file_name.split(".")[:-1]) + ".gro" solv_name = "solv_" + ".".join(file_name.split(".")[:-1]) + ".gro" is_name = "ion_" + solv_name """ Haven't been able to get this to work lately, meant to delete old backups might also unintentionally delete valuable work so not very safe. """ sp.run(["rm", "\#*"]) # First command line instruction pdb2gmx=gmx.commandline_operation(executable = "gmx", arguments = ["pdb2gmx", "-water", "spce", "-ff", "oplsaa"], input_files = {"-f": clean_name}, output_files = {"-o" : out_name}) pdb2gmx.run() print("pdb2gmx",pdb2gmx.output.erroroutput.result()) file_name = "conf.gro" box = gmx.commandline_operation(executable ="gmx", arguments = [ "editconf","-c", "-d", "1.0", "-bt", "cubic"], input_files = {"-f": pdb2gmx.output.file["-o"]}, output_files= {"-o": box_name}) box.run() print("box",box.output.erroroutput.result()) """ Until I get a grip on what I'm doing wrong with commandline_operation """ solvate = gmx.commandline_operation(executable = "gmx", arguments = ["solvate"], input_files = {"-cp": box.output.file["-o"], "-p": "topol.top"}, output_files = {"-o": solv_name}) solvate.run() print("solvate",solvate.output.erroroutput.result()) #ion_name = select_file("Please type the name of you ion .mdp files name") ion_name = "ions.mdp" ion_top = ".".join(ion_name.split(".")[:-1]) + ".tpr" pname = "NA" #get_pname() nname = "CL" #get_nname() tpr_assemble = gmx.commandline_operation(executable = "gmx", arguments = ["grompp"], input_files = {"-f": ion_name, "-c": solvate.output.file["-o"], "-p": "topol.top"}, output_files = {"-o": ion_top}) tpr_assemble.run() print("tpr_assemble",tpr_assemble.output.erroroutput.result()) #sp.run(["gmx", "genion", "-s", ion_top, "-o", is_name, "-p","topol.top",\ # "-pname", pname, "-nname", nname, "-neutral"], input="SOL", text=True) genion = gmx.commandline_operation(executable = "gmx", arguments = ["genion", "-pname", pname, "-nname", nname, "-neutral"], input_files = {"-s": tpr_assemble.output.file["-o"], "-p": "topol.top"}, output_files = {"-o": is_name}, stdin = "SOL") genion.run() print("genion", genion.output.erroroutput.result()) # Energy minimization emtprprep = gmx.commandline_operation(executable = "gmx", arguments = ["grompp"], input_files = {"-f": "minim.mdp", "-c": genion.output.file["-o"], "-p": "topol.top"}, output_files = {"-o": "em.tpr"}) emtprprep.run() print ("emtprprep", emtprprep.output.erroroutput.result()) #sp.run(["gmx", "grompp", "-f", "minim.mdp", "-c", is_name, "-p", "topol.top",\ # "-o", "em.tpr"]) emtpr = gmx.read_tpr(emtprprep.output.file["-o"]) em = gmx.mdrun(emtpr) em.run() #sp.run(["gmx", "mdrun", "-deffnm", "em"]) emgro=em.output.trajectory.result() emgro=emgro[:emgro.rfind('/') + 1] + "confout.gro" # Equilibration eq1tpr = gmx.commandline_operation(executable = "gmx", arguments = ["grompp"], input_files = {"-f": "nvt.mdp", "-c": emgro, "-r": emgro, "-p": "topol.top"}, output_files = {"-o": "nvt.tpr"}) eq1tpr.run() print ("eq1tpr", eq1tpr.output.erroroutput.result()) eq1tp = gmx.read_tpr(eq1tpr.output.file["-o"]) eq1=gmx.mdrun(eq1tp) eq1.run() #sp.run(["gmx", "grompp", "-f", "nvt.mdp", "-c", "em.gro", "-r", "em.gro", "-p",\ # "topol.top", "-o", "nvt.tpr"]) #sp.run(["gmx", "mdrun", "-deffnm", "nvt"]) eq1gro=eq1.output.trajectory.result() eq1gro=eq1gro[:eq1gro.rfind('/') + 1] + "confout.gro" # Equilibration 2 eq2tpr = gmx.commandline_operation(executable = "gmx", arguments = ["grompp"], input_files = {"-f": "npt.mdp", "-c": eq1gro, "-r": eq1gro, "-p": "topol.top"}, output_files = {"-o": "npt.tpr"}) eq2tpr.run() print ("eq2tpr", eq2tpr.output.erroroutput.result()) eq2tp = gmx.read_tpr(eq2tpr.output.file["-o"]) eq2 = gmx.mdrun(eq2tp) eq2.run() eq2out = eq2.output.trajectory.result() eq2out = eq2out[:eq2out.rfind('/') + 1] mdtpr = gmx.commandline_operation(executable = "gmx", arguments = ["grompp"], input_files = {"-f": "md.mdp", "-c": eq2out + "confout.gro", "-t": eq2out + "state.cpt", "-p": "topol.top"}, output_files = {"-o": "md_0_1.tpr"}) mdtpr.run() mdtp = gmx.read_tpr(mdtpr.output.file["-o"]) md = gmx.mdrun(mdtp) md.run() print("Finished") # RUN """sp.run(["gmx", "grompp", "-f", "md.mdp", "-c", "npt.gro", "-t", "npt.cpt", "-p", \ "topol.top", "-o", "md_0_1.tpr"]) sp.run(["gmx", "mdrun", "-deffnm", "md_0_1"])""" except stop: print ("*** Exiting program per users wishes ***") return
def spc_water_box(gmxcli): """Provide a TPR input file for a simple simulation. Prepare the MD input in a freshly created working directory. """ import gmxapi as gmx # TODO: (#2896) Fetch MD input from package / library data. # Example: # import pkg_resources # # Note: importing pkg_resources means setuptools is required for running this test. # # Get or build TPR file from data bundled via setup(package_data=...) # # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files # from gmx.data import tprfilename tempdir = tempfile.mkdtemp() testdir = os.path.dirname(__file__) with open(os.path.join(testdir, 'testdata.json'), 'r') as fh: testdata = json.load(fh) # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below) structurefile = os.path.join(tempdir, 'structure.gro') # We let `gmx solvate` use the default solvent. Otherwise, we would do # gro_input = testdata['solvent_structure'] # with open(structurefile, 'w') as fh: # fh.write('\n'.join(gro_input)) # fh.write('\n') topfile = os.path.join(tempdir, 'topology.top') top_input = testdata['solvent_topology'] # `gmx solvate` will append a line to the provided file with the molecule count, # so we strip the last line from the input topology. with open(topfile, 'w') as fh: fh.write('\n'.join(top_input[:-1])) fh.write('\n') solvate = gmx.commandline_operation( gmxcli, arguments=['solvate', '-box', '5', '5', '5'], # We use the default solvent instead of specifying one. # input_files={'-cs': structurefile}, output_files={ '-p': topfile, '-o': structurefile, }) if solvate.output.returncode.result() != 0: logging.debug(solvate.output.erroroutput.result()) raise RuntimeError('solvate failed in spc_water_box testing fixture.') mdp_input = [('integrator', 'md'), ('cutoff-scheme', 'Verlet'), ('nsteps', 2), ('nstxout', 1), ('nstvout', 1), ('nstfout', 1), ('tcoupl', 'v-rescale'), ('tc-grps', 'System'), ('tau-t', 1), ('ref-t', 298)] mdp_input = '\n'.join( [' = '.join([str(item) for item in kvpair]) for kvpair in mdp_input]) mdpfile = os.path.join(tempdir, 'md.mdp') with open(mdpfile, 'w') as fh: fh.write(mdp_input) fh.write('\n') tprfile = os.path.join(tempdir, 'topol.tpr') # We don't use mdout_mdp, but if we don't specify it to grompp, # it will be created in the current working directory. mdout_mdp = os.path.join(tempdir, 'mdout.mdp') grompp = gmx.commandline_operation(gmxcli, 'grompp', input_files={ '-f': mdpfile, '-p': solvate.output.file['-p'], '-c': solvate.output.file['-o'], '-po': mdout_mdp, }, output_files={'-o': tprfile}) tprfilename = grompp.output.file['-o'].result() if grompp.output.returncode.result() != 0: logging.debug(grompp.output.erroroutput.result()) raise RuntimeError('grompp failed in spc_water_box testing fixture.') # TODO: more inspection of grompp errors... assert os.path.exists(tprfilename) yield tprfilename # Clean up. # Note: these lines are not executed (and tempdir is not removed) if there # are exceptions before `yield` # TODO: Allow override to prevent removal of the temporary directory shutil.rmtree(tempdir)
def spc_water_box_collection(gmxcli, remove_tempdir): """Provide a collection of simulation input items for a simple simulation. Prepare the MD input in a freshly created working directory. Solvate a 5nm cubic box with spc water. Return a dictionary of the artifacts produced. """ import gmxapi as gmx # TODO: Remove this import when the the spc_water_box fixture is migrated to gmxapi.testsupport from gmxapi.testsupport import _cleandir # TODO: (#2896) Fetch MD input from package / library data. # Example: # import pkg_resources # # Note: importing pkg_resources means setuptools is required for running this test. # # Get or build TPR file from data bundled via setup(package_data=...) # # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files # from gmx.data import tprfilename with _cleandir(remove_tempdir) as tempdir: testdir = os.path.dirname(__file__) with open(os.path.join(testdir, 'testdata.json'), 'r') as fh: testdata = json.load(fh) # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below) structurefile = os.path.join(tempdir, 'structure.gro') # We let `gmx solvate` use the default solvent. Otherwise, we would do # gro_input = testdata['solvent_structure'] # with open(structurefile, 'w') as fh: # fh.write('\n'.join(gro_input)) # fh.write('\n') topfile = os.path.join(tempdir, 'topology.top') top_input = testdata['solvent_topology'] # `gmx solvate` will append a line to the provided file with the molecule count, # so we strip the last line from the input topology. with open(topfile, 'w') as fh: fh.write('\n'.join(top_input[:-1])) fh.write('\n') assert os.path.exists(topfile) solvate = gmx.commandline_operation( gmxcli, arguments=['solvate', '-box', '5', '5', '5'], # We use the default solvent instead of specifying one. # input_files={'-cs': structurefile}, output_files={ '-p': topfile, '-o': structurefile, }) assert os.path.exists(topfile) if solvate.output.returncode.result() != 0: logging.debug(solvate.output.stderr.result()) raise RuntimeError( 'solvate failed in spc_water_box testing fixture.') # Choose an exactly representable dt of 2^-9 ps (approximately 0.002) dt = 2.**-9. mdp_input = [('integrator', 'md'), ('dt', dt), ('cutoff-scheme', 'Verlet'), ('nsteps', 2), ('nstxout', 1), ('nstvout', 1), ('nstfout', 1), ('tcoupl', 'v-rescale'), ('tc-grps', 'System'), ('tau-t', 1), ('ref-t', 298)] mdp_input = '\n'.join([ ' = '.join([str(item) for item in kvpair]) for kvpair in mdp_input ]) mdpfile = os.path.join(tempdir, 'md.mdp') with open(mdpfile, 'w') as fh: fh.write(mdp_input) fh.write('\n') tprfile = os.path.join(tempdir, 'topol.tpr') # We don't use mdout_mdp, but if we don't specify it to grompp, # it will be created in the current working directory. mdout_mdp = os.path.join(tempdir, 'mdout.mdp') grompp = gmx.commandline_operation(gmxcli, 'grompp', input_files={ '-f': mdpfile, '-p': solvate.output.file['-p'], '-c': solvate.output.file['-o'], '-po': mdout_mdp, }, output_files={'-o': tprfile}) tprfilename = grompp.output.file['-o'].result() if grompp.output.returncode.result() != 0: logging.debug(grompp.output.stderr.result()) raise RuntimeError( 'grompp failed in spc_water_box testing fixture.') # TODO: more inspection of grompp errors... assert os.path.exists(tprfilename) collection = { 'tpr_filename': tprfilename, 'mdp_input_filename': mdpfile, 'mdp_output_filename': mdout_mdp, 'topology_filename': solvate.output.file['-p'].result(), 'gro_filename': solvate.output.file['-o'].result(), 'mdp_input_list': mdp_input } yield collection
def process_trajectory( files, path=".", begin=0, end=1.0e20, skip=1, output_group="all", center_group="protein", align=False, name_base="", name=None, ndx_path="index.ndx", tpr_path="topol.tpr", cat_overwrite=True, ): import os import gmxapi as gmx def did_it_run(command): did_it_run = True if command.output.returncode.result() != 0: print(command.output.erroroutput.result()) exit did_it_run = False return did_it_run """ Center structure, align structure, do pbc, skip frames and reduce output of given structure file or files. Parameters ---------- files: structure file or files.(xtc,trr,gro,pdb,cpt) path: path to structure file/s. skip: skip every skip frame. output_group: output group of index.ndx. center_group: center/align group of index.ndx. name_base: use this name to start the name output. name: use this name for the output ndx_path: index file path. tpr_path: tpr file path. cat_overwrite: overwrite frames when concating. Returns ------- """ # Asertions on input assert isinstance(cat_overwrite, bool), "cat_overwrite should be bool" assert os.path.exists(path), "Path does not exists." assert isinstance(files, str) or isinstance( files, list ), "File/s should be a string or list" if isinstance(files, str): assert os.path.isfile(path + f"/{files}"), "File" + files + " does not exist." else: for f in files: assert isinstance(f, str), "File content of files must be str." assert os.path.isfile(path + f"/{f}"), "File" + f + " does not exist." base, extension = f.split(".") assert extension == "xtc", "Can only concat xtcs." for f in [ndx_path, tpr_path]: assert os.path.isfile(path + f"/{f}"), "File" + f + " does not exist." assert isinstance(skip, int), "Skip should be int." for st in [path, output_group, center_group]: assert isinstance(st, str), f"{st} should be a string." if name is not None: assert isinstance(name, str), f"{name} should be a string" assert isinstance(name_base, str), f"{name_base} should be a string" cdminus = os.getcwd() os.chdir(path) if isinstance(files, list): if cat_overwrite: args = ["trjcat"] else: args = ["trjcat", "-cat"] catcomm = gmx.commandline_operation( "gmx", arguments=args, input_files={"-f": files}, output_files={"-o": "cat.xtc"}, ) catcomm.run() assert did_it_run(catcomm), "Concating failed failed" file = "cat.xtc" extension = "xtc" else: base, extension = files.split(".") file = files if extension == "cpt": extension = "gro" # Output name if name is None: if name_base != "": name_base = name_base + "_" if extension == "gro" or extension == "pdb": name = f"{name_base}{output_group}_pbc.{extension}" name_al = f"{name_base}{output_group}_pbc_al.{extension}" else: name = f"{name_base}{output_group}_sk{skip}_pbc.{extension}" name_al = f"{name_base}{output_group}_sk{skip}_pbc_al.{extension}" else: name_al = name begin_end = ["-b", str(begin), "-e", str(end)] for f in [name, name_al, "kk.xtc"]: if os.path.isfile(f): os.remove(f) # Cluster pbc trjconv0 = gmx.commandline_operation( "gmx", arguments=["trjconv", "-skip", str(skip), "-pbc", "cluster"] + begin_end, input_files={"-f": file, "-n": ndx_path, "-s": tpr_path}, stdin=f"{center_group} {output_group}", output_files={"-o": f"kk.{extension}"}, ) trjconv0.run() assert did_it_run(trjconv0), "Clustering failed" # Center and pbc trjconv1 = gmx.commandline_operation( "gmx", arguments=["trjconv", "-pbc", "mol", "-center"], input_files={"-f": f"kk.{extension}", "-n": ndx_path, "-s": tpr_path}, stdin=f"{center_group} {output_group}", output_files={"-o": name}, ) trjconv1.run() os.remove(f"kk.{extension}") assert did_it_run(trjconv1), "Pbc failed" # Align if align: trjconv2 = gmx.commandline_operation( "gmx", arguments=["trjconv", "-fit", "rot+trans"], input_files={"-f": name, "-n": ndx_path, "-s": tpr_path}, stdin=f"{center_group} {output_group}", output_files={"-o": name_al}, ) trjconv2.run() assert did_it_run(trjconv2), "Align failed" os.chdir(cdminus) return