diff --git a/autosolvate/__main__.py b/autosolvate/__main__.py index 012a90a..64eec34 100644 --- a/autosolvate/__main__.py +++ b/autosolvate/__main__.py @@ -7,7 +7,7 @@ from autosolvate.autosolvate import * from autosolvate.generatetrajs import * from autosolvate.clustergen import * -from autosolvate.FFmetalcomplex import * +# from autosolvate.FFmetalcomplex import * from autosolvate.multicomponent import * ## Main function @@ -27,8 +27,9 @@ def main(args=None): print('Usage: autosolvate [OPTIONS]') print(' [NO OPTION] launches GUI') print(' boxgen [OPTIONS] generate initial structure') - print(' boxgen_metal[OPTIONS] generate initial structure for organometallic compounds') - print(' mdrun [OPTIONS] automated QM/MM trajectory generatio') + print(' boxgen_metal[OPTIONS] generate initial structure and forcefield for organometallic compounds') + print(' boxgen_multicomponent [OPTIONS] generate initial structure for multicomponent systems') + print(' mdrun [OPTIONS] automated QM/MM trajectory generation') print(' clustergen [OPTIONS] extract microsolvated clusters ') print(' -h, --help short usage description') print() diff --git a/autosolvate/dockers/_packmol_docker.py b/autosolvate/dockers/_packmol_docker.py index 5ba2a20..46ff4ba 100644 --- a/autosolvate/dockers/_packmol_docker.py +++ b/autosolvate/dockers/_packmol_docker.py @@ -112,6 +112,7 @@ def load_solute(self, doc: TextIO, box: SolvatedSystem) -> None: # doc.write('{:<15} {} \n'.format('structure', solute.pdb)) if not os.path.exists(os.path.join(self.workfolder, os.path.basename(solute.pdb))): shutil.copy(solute.pdb, os.path.join(self.workfolder, os.path.basename(solute.pdb))) + # this is actually a bug in packmol. The path to the pdb file cannot be too long. One have to copy the file to the working directory doc.write('{:<15} {} \n'.format('structure', os.path.basename(solute.pdb))) doc.write('{:<15} {:<5} \n'.format('number', 1)) doc.write('{:<10} {posx} {posy} {posz} {com} {com} {com}\n'.format('fixed', posx=solute_pos[0], posy=solute_pos[1], posz=solute_pos[2], com=0.0)) diff --git a/autosolvate/multicomponent.py b/autosolvate/multicomponent.py index d0d4cc5..0edfa90 100644 --- a/autosolvate/multicomponent.py +++ b/autosolvate/multicomponent.py @@ -17,6 +17,7 @@ import json import logging import inspect +import argparse from .molecule import * from .dockers import * @@ -33,7 +34,7 @@ class MulticomponentParamsBuilder(): xyzfile : str structure file name, can be any structural files that openbabel recognizes. name : array_like, Optional. default: the base name of the provided structure file. - Not used + residue_name : array_like, Optional. default: Residue name provided in pdb file or assigned as UAA, UAB, UAC, etc. Residue names for each fragments. A list of strings of three capital letters. Its length should equal to the number of fragments in xyzfile. If this parameter is not given, the residues will be assigned by "U" plus "AB","AC",..."AZ", "BA"... charge : dict | array_like, Optional. default: 0 @@ -186,7 +187,7 @@ class MixtureBuilder(): charge_method : str, Optional, default: "bcc" name of charge fitting method (bcc, resp) """ - def __init__(self, folder = WORKING_DIR, cube_size = 54, closeness = 2.0, charge_method = "bcc"): + def __init__(self, folder = WORKING_DIR, cube_size = 54, closeness = 2.0, charge_method = "bcc", prefix = None): self.solutes = [] self.solvents = [] self.folder = folder @@ -208,7 +209,7 @@ def __init__(self, folder = WORKING_DIR, cube_size = 54, closeness = 2.0, charge self.output_handler.setFormatter(self.output_formater) if len(self.logger.handlers) == 0: self.logger.addHandler(self.output_handler) - + self.systemprefix = prefix def add_complex_solute(self, xyzfile:str, fragment_charge = 0, fragment_spinmult = 1, number = 1, **kwargs): """ @@ -375,18 +376,14 @@ def add_solvent(self, xyzfile:str = "", name="", residue_name="SLV", charge=0, s self.solvents.append(self_solvent) def build(self): - system_name = "-".join([m.name for m in self.solutes] + [m.name for m in self.solvents]) + if not self.systemprefix: + system_name = "-".join([m.name for m in self.solutes] + [m.name for m in self.solvents]) + else: + system_name = self.systemprefix + self.solutes:List[Molecule] + self.solvents:List[Molecule] solute_numbers = [m.number for m in self.solutes] solvent_numbers = [m.number for m in self.solvents] - ''' - @DEBUG - comment left by Patrick Jun 12 2024. - the old way to define 'system_name' will cause bug, please have the person who wrote this to fix it. - ''' - ''' - @DEBUG - bug fixed by Fangning Ren on July 1 2024 - ''' system = SolvatedSystem(system_name, solute = self.solutes, solvent = self.solvents, cubesize=self.boxsize, closeness=self.closeness, solute_number = solute_numbers, solvent_number = solvent_numbers, @@ -394,10 +391,8 @@ def build(self): for docker in self.custom_solvation: docker.run(system) -def startmulticomponent_fromfile(jsonpath:str): - with open(jsonpath, "r") as f: - data = json.load(f) - data["folder"] = os.getcwd() +def startmulticomponent_fromdata(data:dict): + data["folder"] = WORKING_DIR signature = inspect.signature(MixtureBuilder.__init__) function_params = signature.parameters filtered_data = {k: v for k, v in data.items() if k in function_params} @@ -425,35 +420,79 @@ def startmulticomponent_fromfile(jsonpath:str): builder.add_solvent(**data["solvents"][i]) builder.build() - +def startmulticomponent_fromfile(file:str): + with open(file, "r") as f: + data = json.load(f) + startmulticomponent_fromdata(data) + +def create_parser_multicomponent(): + parser = argparse.ArgumentParser( + description='Add solvent box to a given solute and generate related force field parameters.', + epilog=''' + suggest usage: autosolvate multicomponent -f input.json \n -def startmulticomponent(argumentList): + if an input file is provided, all command line options will be ignored. \n + + If using command line as the traditional way, it will only generate a single solute with single solvent. \n + + This is a legacy feature, designed solely for the compatibility with the older version. It is not recommended for further use. + ''', + ) + + parser.add_argument('-f', '--file', type=str, help='json file containing the input parameters. Will ignore all other options if provided. Required when using multiple solvents') + parser.add_argument('-m', '--main', type=str, default='', help='solute xyz file') + parser.add_argument('-o', '--output', type=str, default='', help='prefix of the output file names') + parser.add_argument('-c', '--charge', type=int, default=0, help='formal charge of solute') + parser.add_argument('-u', '--spinmultiplicity',type=int, default=1, help='spin multiplicity of solute') + parser.add_argument('-s', '--solvent', type=str, default='water', help='solvent xyz files, Will use single solvent if provided.') + parser.add_argument('-g', '--chargemethod', type=str, default='bcc', help='name of charge fitting method (bcc, resp)') + parser.add_argument('-b', '--cubesize', type=float,default=54.0, help='size of solvent cube in angstroms') + parser.add_argument('-t', '--closeness', type=float,default=2.0, help='solute-solvent closeness setting. Automation is not possible for mixed solvent') + parser.add_argument('-r', '--srunuse', action='store_true', help='option to run inside a slurm job') + parser.add_argument('-e', '--gaussianexe', type=str, help='name of the Gaussian quantum chemistry package executable') + parser.add_argument('-d', '--gaussiandir', type=str, help='path to the Gaussian package') + parser.add_argument('-a', '--amberhome', type=str, help='path to the AMBER molecular dynamics package root directory') + return parser + + +def startmulticomponent(args): r""" Wrap function that parses command line options for autosolvate multicomponent module, generate solvent box and related force field parameters. Parameters ---------- - argumentList: list - The list contains the command line options to specify solute, solvent, and other options - related to structure and force field parameter generation. + None Command line option definitions - -m, --main solute xyz file - -s, --solvent name of solvent (water, methanol, chloroform, nma) - -o, --output prefix of the output file names - -c, --charge formal charge of solute - -u, --spinmultiplicity spin multiplicity of solute - -g, --chargemethod name of charge fitting method (bcc, resp) - -b, --cubesize size of solvent cube in angstroms - -r, --srunuse option to run inside a slurm job - -e, --gaussianexe name of the Gaussian quantum chemistry package executable used to generate electrostatic potential needed for RESP charge fitting - -d, --gaussiandir path to the Gaussian package - -a, --amberhome path to the AMBER molecular dynamics package root directory. Definition of the environment variable $AMBERHOME - -t, --closeness Solute-solvent closeness setting, for acetonitrile tolerance parameter in packmol in Å, for water, methanol, nma, chloroform the scaling factor in tleap, setting to 'automated' will automatically set this parameter based on solvent. - -l, --solventoff path to the custom solvent .off library file. Required if the user want to use some custom solvent other than the 5 solvents contained in AutoSolvate (TIP3P water, methanol, NMA, chloroform, MeCN) - -p, --solventfrcmod path to the custom solvent .frcmod file. Required if the user wants to use some custom solvent other than the 5 solvents contained in AutoSolvate. - -h, --help short usage description + -f, --file + json file containing the input parameters, Required when using multiple solvents + -m, --main + solute xyz file, not suggested to use when using multiple solvents + -o, --output + prefix of the output file names + -c, --charge + formal charge of solute + -u, --spinmultiplicity + spin multiplicity of solute + -s, --solvent + solvent xyz files, Will use single solvent if provided. Not suggested to use when using multiple solvents + -g, --chargemethod + name of charge fitting method (bcc, resp) + -b, --cubesize + size of solvent cube in angstroms + -t, --closeness + Solute-solvent closeness setting, for acetonitrile tolerance parameter in packmol in Å, for water, methanol, nma, chloroform the scaling factor in tleap, setting to 'automated' will automatically set this parameter based on solvent. + -r, --srunuse + option to run inside a slurm job + -e, --gaussianexe + name of the Gaussian quantum chemistry package executable used to generate electrostatic potential needed for RESP charge fitting + -d, --gaussiandir + path to the Gaussian package + -a, --amberhome + path to the AMBER molecular dynamics package root directory. Definition of the environment variable $AMBERHOME + -h, --help + short usage description Returns ------- @@ -461,111 +500,27 @@ def startmulticomponent(argumentList): Generates the structure files and save as ```.pdb```. Generates the MD parameter-topology and coordinates files and saves as ```.prmtop``` and ```.inpcrd``` """ #print(argumentList) - options = "hm:s:o:c:b:g:u:re:d:a:t:l:p:" - long_options = ["help", "main", "solvent", "output", "charge", "cubesize", "chargemethod", "spinmultiplicity", "srunuse","gaussianexe", "gaussiandir", "amberhome", "closeness","solventoff","solventfrcmod"] - arguments, values = getopt.getopt(argumentList, options, long_options) - solutexyz="" - solvent='water' - slu_netcharge=0 - cube_size=54 - charge_method="bcc" - slu_spinmult=1 - outputFile="" - srun_use=False - amberhome=None - gaussianexe=None - gaussiandir=None - closeness=0.8 - solvent_off="" - solvent_frcmod="" - #print(arguments) - #print(values) - for currentArgument, currentValue in arguments: - if currentArgument in ("-h", "--help"): - print('Usage: autosolvate boxgen_multicomponent [OPTIONS]') - print(' -m, --main solute xyz file') - print(' -s, --solvent_lists solvent xyz files, separated by slash. (ex. water.pdb/acetonitrile.pdb)') - # print(' -o, --output prefix of the output file names') # not currently supporting this option - print(' -c, --charge formal charge of solute') - print(' -u, --spinmultiplicity spin multiplicity of solute') - print(' -g, --chargemethod name of charge fitting method (bcc, resp)') # currently only support bcc - print(' -b, --cubesize size of solvent cube in angstroms') - # print(' -r, --srunuse option to run inside a slurm job') # not currently supporting this option - # print(' -e, --gaussianexe name of the Gaussian quantum chemistry package executable') # not currently supporting gaussian - # print(' -d, --gaussiandir path to the Gaussian package') # not currently supporting gaussian - # print(' -a, --amberhome path to the AMBER molecular dynamics package root directory') # not currently supporting amberhome - print(' -t, --closeness Solute-solvent closeness setting') - # print(' -l, --solventoff path to the custom solvent .off library file') # not currently supporting this option - # print(' -p, --solventfrcmod path to the custom solvent .frcmod file') # not currently supporting this option - print(' -h, --help short usage description') - exit() - elif currentArgument in ("-m", "--main"): - print ("Main/solutexyz", currentValue) - solutexyz=str(currentValue) - elif currentArgument in ("-s", "--solvent"): - print ("Solvent:", currentValue) - solvent=str(currentValue) - elif currentArgument in ("-o", "--output"): - print ("Output:", currentValue) - outputFile=str(currentValue) - elif currentArgument in ("-c", "--charge"): - print ("Charge:", currentValue) - slu_netcharge=int(currentValue) - elif currentArgument in ("-b", "--cubesize"): - print ("Cubesize:", currentValue) - cube_size=float(currentValue) - elif currentArgument in ("-g", "--chargemethod"): - print ("Chargemethod:", currentValue) - charge_method=str(currentValue) - elif currentArgument in ("-u", "--spinmultiplicity"): - print ("Spinmultiplicity:", currentValue) - slu_spinmult=int(currentValue) - elif currentArgument in ("-r", "--srunuse"): - print("usign srun") - srun_use=True - elif currentArgument in ("-e","--gaussianexe"): - print("Gaussian executable name:", currentValue) - gaussianexe = currentValue - elif currentArgument in ("-d","--gaussiandir"): - print("Gaussian package directory:", currentValue) - gaussiandir = currentValue - elif currentArgument in ("-a","--amberhome"): - print("Amber home directory:", currentValue) - amberhome = currentValue - elif currentArgument in ("-t", "--closeness"): - print("Solute-Solvente closeness parameter", currentValue) - closeness = currentValue - elif currentArgument in ("-l", "--solventoff"): - print("Custom solvent .off library path:", currentValue) - solvent_off = currentValue - elif currentArgument in ("-p", "--solventfrcmod"): - print("Custom solvent .frcmmod file path:", currentValue) - solvent_frcmod = currentValue - - if solutexyz == "": - print("Error! Solute xyzfile must be provided!\nExiting...") - exit() - elif not os.path.exists(solutexyz): - print("Error! Solute xyzfile path ", solutexyz, " does not exist!\nExiting...") - exit() - - try: - _, ext = os.path.splitext(solutexyz) - pybel.readfile(ext[1:], solutexyz).__next__() - except: - print("Error! Solute structure file format issue!") - print(solutexyz," cannot be opened with openbabel.\n Exiting...") - exit() - + parser = create_parser_multicomponent() + args = parser.parse_args(args) + cmd_dict = vars(args) + if "file" in cmd_dict and cmd_dict["file"] and os.path.exists(cmd_dict["file"]): + if not os.path.exists(cmd_dict["file"]): + raise FileNotFoundError(f"File {cmd_dict['file']} not found") + with open(cmd_dict["file"], "r") as f: + data = json.load(f) + else: + cmd_dict.pop("file") + data = convert_cmd_to_dict(cmd_dict) + data = correct_keyword(data) + check_inputs(data) + + json.dump(data, open("/home/fren5/AutoSolvate-update/autosolvate.json", "w"), indent=4) + json.dump(data, open("autosolvate.json", "w"), indent=4) global WORKING_DIR WORKING_DIR = os.getcwd() + startmulticomponent_fromdata(data) - builder = MixtureBuilder() - builder.add_solute(solutexyz, charge=slu_netcharge, spinmult=slu_spinmult) - for s in solvent.split("/"): - builder.add_solvent(s) - builder.build() - if __name__ == "__main__": - startmulticomponent(sys.argv[1:]) + startmulticomponent() + diff --git a/autosolvate/tests/test_multicomponent.py b/autosolvate/tests/test_multicomponent.py index 07f5f49..79d3b88 100644 --- a/autosolvate/tests/test_multicomponent.py +++ b/autosolvate/tests/test_multicomponent.py @@ -11,8 +11,6 @@ from . import helper_functions as hp - - def test_ionpair_solvation(tmpdir): """ @TODO: @@ -46,9 +44,6 @@ def test_ionpair_solvation(tmpdir): path_main_exist *= os.path.exists(f"{name}.{suffix}") assert path_main_exist -# assert hp.compare_pdb(f"water_solvated.pdb", hp.get_reference_dir(f"multicomponent/water_solvated.pdb")) -# assert hp.compare_inpcrd_prmtop(f"water_solvated.prmtop", hp.get_reference_dir(f"multicomponent/water_solvated.prmtop")) - def test_ionpair_solvation_custom_solvent(tmpdir): testName = "test_custom_ionpair_solvation" solutexyz = hp.get_input_dir("ionpair.pdb") @@ -73,8 +68,6 @@ def test_ionpair_solvation_custom_solvent(tmpdir): path_main_exist *= os.path.exists(f"{name}.{suffix}") assert path_main_exist - - def test_multicomponent(tmpdir): testName = "test_multicomponent" inpfname = "PAHs" @@ -125,10 +118,11 @@ def test_mixture_builder(): hp.get_reference_dir(f"multicomponent/naphthalene-acetonitrile-water.prmtop"), threshold = np.inf, # I set it to inf because packmol has some randomness in the output. This function will check the topology and force field parameters. ) - + def test_mixture_builder_file_input(): test_name = "test_mixture_builder_file_input" - startmulticomponent_fromfile(hp.get_input_dir("mixturebuilder_input1.json")) + inputfilepath = hp.get_input_dir("mixturebuilder_input1.json") + startmulticomponent(["-f", inputfilepath]) solute_path_exist = True solute_path_exist *= os.path.exists("naphthalene.mol2") @@ -152,3 +146,18 @@ def test_mixture_builder_file_input(): hp.get_reference_dir(f"multicomponent/naphthalene-acetonitrile-water.prmtop"), threshold = np.inf, # I set it to inf because packmol has some randomness in the output. This function will check the topology and force field parameters. ) + +def test_mixture_builder_cmd_input(): + """This is a legacy feature, designed solely to respect the habits of users of the older version. It is not recommended for use.""" + test_name = "test_mixture_builder_cmd_input" + solute_xyz = hp.get_input_dir("naphthalene_neutral.xyz") + startmulticomponent([ + "-m", solute_xyz, + "-o", "mybox", + "-c", "0", + "-u", "1", + "-s", "water", + "-b", "20", + "-t", "0.8", + ]) + assert os.path.exists("mybox.prmtop") \ No newline at end of file diff --git a/autosolvate/utils/__init__.py b/autosolvate/utils/__init__.py index cc63f11..86b5641 100644 --- a/autosolvate/utils/__init__.py +++ b/autosolvate/utils/__init__.py @@ -1,4 +1,5 @@ from .tools import * +from .inputparser import * from .tools_fffit import * from .frcmod import * from .check_executables import * diff --git a/autosolvate/utils/inputparser.py b/autosolvate/utils/inputparser.py index 2acf421..5aea04d 100644 --- a/autosolvate/utils/inputparser.py +++ b/autosolvate/utils/inputparser.py @@ -1,11 +1,115 @@ +# This module is here to process the json input of multicomponent.py + import os import re +import copy import json import shutil +from typing import Iterable, List, Dict, Any, Tuple + + +def convert_cmd_to_dict(argument_dict:Dict[str, Any]) -> Dict[str, Any]: + special_arguments = ["solute", "solvent"] + newdata = {} + for key, value in argument_dict.items(): + if key not in special_arguments: + newdata[key] = value + data = argument_dict + if "main" in data and data["main"]: + newdata["solute"] = dict() + newdata['solute']['xyzfile'] = data["main"] + if "charge" in data: + newdata["solute"]["charge"] = data["charge"] + if "spinmult" in data: + newdata["solute"]["spinmult"] = data["spinmult"] + if "solvent" in data and data["solvent"]: + newdata["solvent"] = dict() + if "solventoff" in data: + newdata["solvent"]["off"] = data["solventoff"] + if "solventfrcmod" in data: + newdata["solvent"]["frcmod"] = data["solventfrcmod"] + if "solvent" in data: + newdata["solvent"]["name"] = data["solvent"] + return newdata + + +def correct_keyword(data:dict) -> dict: + """ + Correct the key in the dictionary to the acceptable keys + """ + keyword_dict = { + "chargemethod": "charge_method", + "cubesize": "cube_size", + "fragmentcharge": "fragment_charge", + "fragmentspinmultiplicity": "fragment_spinmult", + "fragmentmultiplicity": "fragment_spinmult", + "spinmultiplicity": "spinmult", + "multiplicity": "spinmult", + "output": "prefix", + } + newdata = {} + for key, value in data.items(): + if key in keyword_dict: + newdata[keyword_dict[key]] = value + else: + newdata[key] = value + return newdata + +def add_missing_xyzfile_keyword(data:dict, support_input_format:Iterable[str] = ("xyz", "pdb", "mol2", "prep", "off", "lib")) -> dict: + if "xyzfile" in data: + return data + for key, value in data.items(): + if key in support_input_format and not "xyzfile" in data and isinstance(value, str) and os.path.isfile(value): + data["xyzfile"] = value + break + return data + +def overwrite_keyword(data:dict, arguments:List[Tuple[str, Any]]) -> dict: + """ + Overwrite the keyword in the dictionary with the arguments + """ + newdata = copy.deepcopy(data) + ignoredargs = [] + arguments + for key, value in arguments: + if isinstance(value, str) and value == "": + ignoredargs.append(key) + for key in ignoredargs: + arguments.remove((key, "")) + for key, value in arguments: + newdata[key] = value + if "main" in data and data["main"]: + newdata["solute"] = dict() + newdata['solute']['xyzfile'] = data["main"] + if "charge" in data: + newdata["solute"]["charge"] = data["charge"] + if "spinmult" in data: + newdata["solute"]["spinmult"] = data["spinmult"] + if "solvent" in data and data["solvent"]: + newdata["solvent"] = dict() + if "solventoff" in data: + newdata["solvent"]["off"] = data["solventoff"] + if "solventfrcmod" in data: + newdata["solvent"]["frcmod"] = data["solventfrcmod"] + if "solvent" in data: + newdata["solvent"]["name"] = data["solvent"] + return newdata -def parse_json_input(jsonpath:str): - with open(jsonpath, "r") as f: - data = json.load(f) - \ No newline at end of file +def check_inputs(data:dict) -> dict: + """ + Check if the input is valid + """ + if "solute" not in data and "solutes" not in data: + raise ValueError("No solute is provided") + if "solvent" not in data and "solvents" not in data: + raise ValueError("No solvent is provided") + if "solute" in data and "solutes" in data: + raise ValueError("You cannot provide both solute and solutes, only provide the solute argument if you want to use single solute") + if "solvent" in data and "solvents" in data: + raise ValueError("You cannot provide both solvent and solvents, only provide the solvent argument if you want to use single solvent") + if "solutes" in data and (not isinstance(data["solutes"], list) or len(data["solutes"]) == 0): + raise ValueError("solutes must be a list") + if "solvents" in data and (not isinstance(data["solvents"], list) or len(data["solvents"]) == 0): + raise ValueError("solvents must be a list") \ No newline at end of file diff --git a/autosolvate/utils/tools.py b/autosolvate/utils/tools.py index 7fb131e..8076da0 100644 --- a/autosolvate/utils/tools.py +++ b/autosolvate/utils/tools.py @@ -405,15 +405,7 @@ def get_residue_name_from_pdb(file_path:str) -> str: return residue_name -# processing input dictionary -def add_missing_xyzfile_keyword(data:dict, support_input_format:Iterable[str] = ("xyz", "pdb", "mol2", "prep")) -> dict: - if "xyzfile" in data: - return data - for key, value in data.items(): - if key in support_input_format and not "xyzfile" in data and isinstance(value, str) and os.path.isfile(value): - data["xyzfile"] = value - break - return data + diff --git a/docs/tutorial_multicomponent.rst b/docs/tutorial_multicomponent.rst index fd13066..04de158 100644 --- a/docs/tutorial_multicomponent.rst +++ b/docs/tutorial_multicomponent.rst @@ -4,16 +4,6 @@ The following tutorial illustrates the basic usage of **Autosolvate Multicompone There will be one example systems: naphthalene in mixed water and acetonitrile solvent. The tutorial will be broken down into three steps: -.. note:: - - Note:: - - Note to Autosolvate Developers - - I have not tested if the download links work properly in this document because I can not add this .rst file to https://autosolvate.readthedocs.io/en/latest/. - - Please test and make sure all the download link work properly. - Prerequisites diff --git a/test_water_acn.ipynb b/test_water_acn.ipynb index 7af1668..7cb6262 100644 --- a/test_water_acn.ipynb +++ b/test_water_acn.ipynb @@ -10,11 +10,123 @@ "%autoreload 2\n", "from autosolvate.autosolvate import *\n", "from autosolvate.multicomponent import *\n", + "\n", "import os \n", "ppath = \"/home/fren5/AutoSolvate-update/AutoSolvate\" \n", "os.chdir(ppath)" ] }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "usage: ipykernel_launcher.py [-h] [-f FILE] [-m MAIN] [-o OUTPUT] [-c CHARGE]\n", + " [-u SPINMULTIPLICITY] [-s SOLVENT]\n", + " [-g CHARGEMETHOD] [-b CUBESIZE] [-t CLOSENESS]\n", + " [-r] [-e GAUSSIANEXE] [-d GAUSSIANDIR]\n", + " [-a AMBERHOME]\n", + "\n", + "Add solvent box to a given solute and generate related force field parameters.\n", + "\n", + "optional arguments:\n", + " -h, --help show this help message and exit\n", + " -f FILE, --file FILE json file containing the input parameters, Required\n", + " when using multiple solvents\n", + " -m MAIN, --main MAIN solute xyz file\n", + " -o OUTPUT, --output OUTPUT\n", + " prefix of the output file names\n", + " -c CHARGE, --charge CHARGE\n", + " formal charge of solute\n", + " -u SPINMULTIPLICITY, --spinmultiplicity SPINMULTIPLICITY\n", + " spin multiplicity of solute\n", + " -s SOLVENT, --solvent SOLVENT\n", + " solvent xyz files, Will use single solvent if\n", + " provided.\n", + " -g CHARGEMETHOD, --chargemethod CHARGEMETHOD\n", + " name of charge fitting method (bcc, resp)\n", + " -b CUBESIZE, --cubesize CUBESIZE\n", + " size of solvent cube in angstroms\n", + " -t CLOSENESS, --closeness CLOSENESS\n", + " solute-solvent closeness setting. Automation is not\n", + " possible for mixed solvent\n", + " -r, --srunuse option to run inside a slurm job\n", + " -e GAUSSIANEXE, --gaussianexe GAUSSIANEXE\n", + " name of the Gaussian quantum chemistry package\n", + " executable\n", + " -d GAUSSIANDIR, --gaussiandir GAUSSIANDIR\n", + " path to the Gaussian package\n", + " -a AMBERHOME, --amberhome AMBERHOME\n", + " path to the AMBER molecular dynamics package root\n", + " directory\n", + "\n", + "suggest usage: autosolvate multicomponent -f input.json if an input file is\n", + "provided, all command line options will be ignored. If using command line as\n", + "the traditional way, it will only generate a single solute with single\n", + "solvent. This is a legacy feature, designed solely for the compatibility with\n", + "the older version. It is not recommended for further use.\n" + ] + }, + { + "ename": "SystemExit", + "evalue": "0", + "output_type": "error", + "traceback": [ + "An exception has occurred, use %tb to see the full traceback.\n", + "\u001b[0;31mSystemExit\u001b[0m\u001b[0;31m:\u001b[0m 0\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/fren5/psi4conda/envs/autosolvate/lib/python3.8/site-packages/IPython/core/interactiveshell.py:3516: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.\n", + " warn(\"To exit: use 'exit', 'quit', or Ctrl-D.\", stacklevel=1)\n" + ] + } + ], + "source": [ + "startmulticomponent([\n", + " \"-h\"\n", + "])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1 molecule converted\n" + ] + } + ], + "source": [ + "newpath = os.path.join(ppath, \"test_cmd_input\")\n", + "\n", + "if not os.path.exists(newpath):\n", + " os.makedirs(newpath)\n", + "\n", + "os.chdir(newpath)\n", + "inputdir = \"/home/fren5/AutoSolvate-update/AutoSolvate/autosolvate/tests/inputs\"\n", + "startmulticomponent([\n", + " \"-m\", os.path.join(inputdir, \"naphthalene_neutral.xyz\"),\n", + " \"-o\", \"mybox\",\n", + " \"-c\", \"0\",\n", + " \"-u\", \"1\",\n", + " \"-s\", \"water\",\n", + " \"-b\", \"20\",\n", + " \"-t\", \"0.8\",\n", + "])\n" + ] + }, { "cell_type": "code", "execution_count": 2,