def superimpose_alg(): while True: print("Chosse an option:") print("0 - To cancel") print("1 - For batch mode") print("2 - For single structure(In screen printing)") mode = input() if mode in [str(n) for n in range(3)]: break if mode == "0": return elif mode == "1": if os.path.exists(os.path.join(os.getcwd(), "rotated")): print("Rotated directory already exists in current directory!") print("Please remove it and try again.") return os.mkdir(os.path.join(os.getcwd(), "rotated")) xyz_1 = read_item(None, "Which item do you wish to compare to?", [".xyz"]) if xyz_1: xyz_1 = XyzFile(xyz_1) else:return while True: num_atoms = input("compare first N atoms (0 for all):\n") if num_atoms in [str(a) for a in range(xyz_1.n_atoms())]: num_atoms = int(num_atoms) break else: print("Invalid input for {}".format(xyz_1.name())) for file in file_weeder(["xyz"]): if not file == xyz_1.name(): xyz_2 = XyzFile(read_item(file)) xyz_3 = xyz_2.superimpose(xyz_1, num_atoms, True) xyz_3.save_file(os.path.join(os.getcwd(), "rotated")) xyz_1.std_cord(num_atoms).save_file(os.path.join(os.getcwd(), "rotated")) elif mode == "2": xyz_1 = read_item(None, "Which item do you wish to compare to?", [".xyz"]) if xyz_1: xyz_1 = XyzFile(xyz_1) else: return xyz_2 = read_item(None, "Which item do you wish to rotate?", [".xyz"]) if xyz_2: xyz_2 = XyzFile(xyz_2) else:return while True: num_atoms = input("compare first N atoms (0 for all):\n") if num_atoms in [str(a) for a in range(min([xyz_1.n_atoms(),xyz_2.n_atoms()]))]: num_atoms = int(num_atoms) break else: print("Invalid input for either or both {} and {}".format(xyz_1.name(),xyz_2.name())) xyz_2.superimpose(xyz_1, num_atoms, True).print_file() xyz_1.std_cord(num_atoms).print_file()
def xyz_ent(): weeded_list = file_weeder([".xyz"]) weeded_list = weeded_list if preferences.folder_op else sel_files(weeded_list) if not weeded_list: return for i in weeded_list: xyz = XyzFile(read_item(i)).enantiomer() xyz.save_file()
def aproximate(xyz_1, xyz_2, vertex): """Aproximate xyz_2 to xyz_1 from trajectory vertex. Returns [xyz_1+xyz_2, xyz_2]""" def min_dist(a, b): return min(math.sqrt(sum(pow(c - d, 2) for c, d in zip(bb, aa))) for bb in b for aa in a) xyz_a = [[float(a) for a in i] for i in xyz_1.cord_strip()] xyz_b = [[float(a) + b * 50 for a, b in zip(i, vertex)] for i in xyz_2.cord_strip()] for num in range(5): step_size = 1 / 2 ** num while True: if min_dist(xyz_a, xyz_b) < 2: xyz_b = [[a + b * step_size for a, b in zip(i, vertex)] for i in xyz_b] break else: xyz_b = [[a - b * step_size for a, b in zip(i, vertex)] for i in xyz_b] cordinates = [" ".join([a, *[str(c) for c in b]]) for a, b in zip(xyz_2.all_elements(), xyz_b)] return XyzFile([xyz_2.name(), xyz_2.n_atoms(), " ", *cordinates])
def xyz_insert(weeded_list): """Inserts geometries into both orca and gaussian input files""" extension = ".inp" if preferences.comp_software == "orca" else preferences.gauss_ext sub_folder = os.path.join(os.getcwd(),"inserted_input_files") if os.path.exists(sub_folder): print("'inserted_input_files' directory already exists in current directory!") print("Please remove it and try again!") return os.mkdir(sub_folder) for i in weeded_list: try: xyz = XyzFile(read_item(i)) if preferences.comp_software == "orca": comp_input = InpFile(read_item(i.replace(".xyz",extension))) else: comp_input = GjfFile(read_item(i.replace(".xyz",extension))) comp_input = comp_input.replace_cord(xyz) with open(os.path.join(sub_folder,i.replace(".xyz",extension)),"w") as file: file.write(comp_input.return_print) except FileNotFoundError: print("file " + i.replace(".xyz",extension) + " could not be found!") print("\nJob done!\nPlease lookup the inserted_input_files directory\n") return
def read_strucure(self): charge_mult = None title = None coordinates = [] for i, a in enumerate(self.list[self.hash_line:]): if i > 5 and not coordinates: break a = a.split(",") if len(a) == 2 and not coordinates: charge_mult = a continue if len(a) == 4: if a[0] in elements and all( is_str_float(a[n]) for n in [1, 2, 3]): coordinates.append(" ".join(a)) elif coordinates: break elif coordinates: break return charge_mult, XyzFile( [self.list[0], str(len(coordinates)), title, *coordinates])
def save_inp(self,parameters,index): if not preferences.folder_op: self.weeded_list = sel_files(self.weeded_list) if not self.weeded_list: return for i in self.weeded_list: if os.path.isfile(os.path.join(os.getcwd(), (i.replace(self.original_ext, ".inp")))): print(i.replace(self.original_ext,".inp") + " already exist on current directory!") continue xyz = LogFile(read_item(i)).last_xyz_obj() if self.use_logs else XyzFile(read_item(i)) inp_out = [] for idx_a, line in enumerate(parameters[0:index]): if self.use_logs and idx_a + 1 == len(parameters[0:index]): line = "* " + " ".join(LogFile(read_item(i)).charge_mult) inp_out.append(line.replace("FILENAME", i.replace(self.original_ext, "")) + "\n") for line in xyz.form_cord_block(): inp_out.append(line + "\n") for line in parameters[index + 1:]: inp_out.append(line + "\n") with open(os.path.join(os.getcwd(), (i.replace(self.original_ext,".inp"))), "w",newline="\n") as file: for line in inp_out: file.write(line) print(i.replace(self.original_ext, ".inp"), " created!") return
def first_xyz_obj(self): return XyzFile([ self.name, self.n_atoms, " ", *(" ".join(l) for l in self.first_cord_block()) ])
def any_xyz_obj(self, a_idx, b_idx, title=" ", name=False): if name == False: name = self.name return XyzFile([ name, self.n_atoms, title, *(" ".join(l) for l in self.xyz_cord_block(a_idx, b_idx)) ])
def xyz_obj(self): return XyzFile([ self.name(), self.n_atoms(), " ", *[" ".join(a) for a in self.cord_block()] ])
def start(): angles, p_angles, geodes = None, None, None xyz_1 = read_item(None, "Choose the molecule you want to solvate?", ["xyz"]) if xyz_1: xyz_1 = XyzFile(xyz_1).std_cord() else: return while True: print("Choose a trajectory englobing method") print("0 - To cancel") print("1 - Cubic gobling") print("2 - Icosahedron gobling") print("3 - Give a fulerene") usr_opt = input() if usr_opt == "0": return if usr_opt in ["1","2","3"]: break if usr_opt == "1": geodes = [[a,b,c] for a in [-1,1] for b in [-1,1] for c in [-1,1]] elif usr_opt == "2": k = (1 + math.sqrt(5)) / 2 geodes = [[0, 1, k], [0, -1, k], [0, -1, -k], [0, 1, -k], [k, 0, 1], [-k, 0, 1], [-k, 0, -1],[k, 0, -1], [1, k, 0], [-1, k, 0], [-1, -k, 0], [1, -k, 0]] elif usr_opt == "3": geodes = read_item(None, "Chose a fulerene", ["xyz"]) if geodes: geodes = XyzFile(geodes).std_cord().cord_strip() geodes = [[float(n) for n in i] for i in geodes] else: print("You need a to choose a trajectory engobling method") return xyz_2 = read_item(None, "Chose the solvent or counterion", ["xyz"]) if xyz_2: xyz_2 = XyzFile(xyz_2).std_cord() else: return while True: print("Orientation algorithm:") print("0 - To cancel") print("1 - Espherical ion") print("2 - 12 Random cubic orientations") print("3 - 24 Sistematic cubic rotations") usr_opt = input() if usr_opt in [str(a) for a in range(4)]: break if usr_opt == "0": return elif usr_opt == "1": angles = [0] p_angles = [["x", 0]] elif usr_opt == "2": angles = random.choices([math.pi * i for i in [0, 0.5, 1, 1.5]], k=3) rot = [["x", 0], ["x", .5], ["x", 1], ["x", 1.5], ["z", 0.5], ["z", 1.5]] p_angles = random.choices([[i[0], math.pi * i[1]] for i in rot], k=4) elif usr_opt == "3": angles = [math.pi * i for i in [0, 0.5, 1, 1.5]] rot = [["x", 0], ["x", .5], ["x", 1], ["x", 1.5], ["z", 0.5], ["z", 1.5]] p_angles = [[i[0], math.pi * i[1]] for i in rot] while True: save = input("Save individual files? (y/n)") if save in ["y", "n"]: break rot_alg(xyz_1, xyz_2, angles, p_angles, geodes, save)
def save_gjf(self,parameters,index): heavy_e, gjf_overwrite, folder_op = [preferences.heavy_atom,preferences.gjf_overwrite,preferences.folder_op] ecps, basis = None, None if not folder_op: self.weeded_list = sel_files(self.weeded_list) if not self.weeded_list: return if any([b in parameters for b in ["INSERT_GBS_BASIS","INSERT_GBS_ECP"]]): print("This parameter file requires an aditional gbs file.") print("Where should it be taken from?") print("0 - Current folder") print("1 - Builtins") print("2 - User defined") while True: option = input() if option in ["0","1","2"]: break if option == "0": files_dir = os.getcwd() elif option == "1": files_dir = self.p_files_dir elif option == "2": files_dir = self.user_files_dir gbs_files = file_weeder([".gbs"], cf=files_dir) print("Chosse one basis/ecp set\n0 - Cancel") for i, file in enumerate(gbs_files): print("{} - {}".format(i+1, file)) while True: option = input() if option in [str(a) for a in range(len(gbs_files)+1)]: break print("Invalid option") if option == "0": return with open(os.path.join(files_dir,gbs_files[int(option)-1])) as file: gbs_file = file.read().splitlines() basis, ecps = self.read_gbs(gbs_file) assert type(basis) == dict, "Basis was not read" assert type(ecps) == dict, "Ecps were not read" for i in self.weeded_list: try: gjf_out, rm_lines, = [], [] if os.path.isfile(os.path.join(os.getcwd(),(i.replace(self.original_ext,preferences.gauss_ext)))) and not gjf_overwrite: print(i.replace(self.original_ext,preferences.gauss_ext) + " already exist on current directory!") continue xyz = LogFile(read_item(i)).last_xyz_obj() if self.use_logs else XyzFile(read_item(i)) for idx_a,line in enumerate(parameters[0:index]): if self.use_logs and idx_a+1 == len(parameters[0:index]): line = " ".join(LogFile(read_item(i)).charge_mult) gjf_out.append(line.replace("FILENAME",i.replace(self.original_ext,""))+"\n") for line in xyz.form_cord_block(): gjf_out.append(line+"\n") possible = [str(b + 1) for b in range(xyz.n_atoms())] for line in parameters[index+1:]: # SCAN like: "B S APROX" or "B S DIST" is_mod_red = any("modredundant" in i.lower() for i in parameters[0:index]) s_line = line.split() while len(s_line) == 3: if s_line[0] != "B" or s_line[1] != "S": break if s_line[2] not in ["APROX","DIST"]: break if not is_mod_red: print("Missing 'modredundant' keyword?") break if xyz.n_atoms() <2: raise Exception(f"At least two atoms are neded in struture {xyz.name()} to perform a scan") atom=["a","b"] if s_line[-1] == "APROX": print(f"Detected bond scan (APROX) for xyz file {i}.") while not all(atom[a] in possible if atom[0] != atom[1] else False for a in [0,1]): atom = [input("Enter atom A: "),input("Enter atom B: ")] line = f"B {atom[0]} {atom[1]} S APROX" elif s_line[-1] == "DIST": print(f"Detected bond scan (DIST) for xyz file {i}.") while not all(atom[a] in possible if atom[0] != atom[1] else False for a in [0,1]): atom = [input("Enter atom A: "),input("Enter atom B: ")] line = f"B {atom[0]} {atom[1]} S DIST" s_line = line.split() break # SCAN like: "B 1 2 S APROX" or "B 1 2 S DIST" while len(s_line) == 5: if s_line[0] != "B" or s_line[3] != "S": break if not s_line[1].isdigit(): break if not s_line[2].isdigit(): break if s_line[4] not in ["APROX", "DIST"]: break if not is_mod_red: print("Missing 'modredundant' keyword?") break if xyz.n_atoms() < 2: raise Exception(f"At least two atoms are neded in struture {xyz.name()} to perform a scan") atoms_idx = [int(s_line[1])-1, int(s_line[2])-1] if any(True for a in atoms_idx if not a in range(xyz.n_atoms())): raise Exception(f"Scan atom numbers are larger than the number of atoms for: {xyz.name()}") atoms_cord = [i for idx,i in enumerate(xyz.cord_block()) if idx in atoms_idx] dist = math.sqrt(sum((float(i)-float(atoms_cord[1][idx]))**2 for idx,i in enumerate(atoms_cord[0]) if idx > 0)) ideal_dist=sum(b[1] for idx,b in enumerate(element_radii) if b[0] in [i[0] for i in atoms_cord])/100 if s_line[-1] == "APROX": line = line.replace("APROX",f"{1+int((dist-ideal_dist)/0.075)} -0.075") elif s_line[-1] == "DIST": line = line.replace("DIST",f"{1+int(ideal_dist/0.075)} 0.075") s_line = line.split() break # SCAN like: "D S" while len(s_line) == 2: if not is_mod_red: break if s_line[0] != "D" or s_line[1] != "S": break print(f"Detected dihedral scan for xyz file {i}.") if xyz.n_atoms() < 4: raise Exception(f"At least two four atoms are neded in struture {xyz.name()} to perform a dihedral scan") while True: atom = [input(f"Enter atom {a}: ") for a in ["A","B","C","D"]] atom = [a.strip() for a in atom] if not all([len(a.split()) == 1 and a.isdigit() for a in atom]): print("No non-numeric characters or spaces are allowed for atom numbers") continue if not len(set(atom)) == 4: print("No atom should be repeated!") continue if not all([a in possible for a in atom]): print("Atoms with incorrect number were found!") continue break while True: n_steps = input("Please give the number of steps to be taken: ").strip() if n_steps.isdigit(): break else: print("The number of steps must be an integer") while True: print("Please give the step size to be taken in degrees") size = input("The number must include a dot character as a decimal place (eg. '10.0'): ").strip() if is_str_float(size) and size.count(".") == 1: break else: print("Please make sure the number complies with formating rules!") line = f"D {' '.join(atom)} S {n_steps} {size}" s_line = line.split() break # READOPTIMIZE + NOTATOMS if line.replace(" ", "").lower() == "notatoms=": print("Please enter the atoms you want to freeze on structure {} separated by comma".format(xyz.name())) line = line + input(line) # READOPTIMIZE + ATOMS elif line.replace(" ", "").lower() == "noatomsatoms=": print("Please enter the atoms you want to optimize on structure {} separated by comma".format(xyz.name())) line = line + input(line) # BASIS like: "LIGHT_ELEMENT_BASIS 0" or "HEAVY_ELEMENT_BASIS 0" and ECP like "HEAVY_ELEMENT_ECP 0" elif len(s_line) == 2: if any(True for a in ["/gen","gen ","genecp"] if a in " ".join(parameters[0:index-3]).lower()): if s_line == ["LIGHT_ELEMENT_BASIS","0"]: elm = [a for a in xyz.elements() if elements.index(a) < heavy_e+1] if elm: line = line.replace("LIGHT_ELEMENT_BASIS"," ".join(elm)) else: for a in range(3): rm_lines.append(len(gjf_out)+a) elif s_line == ["HEAVY_ELEMENT_BASIS","0"]: elm = [a for a in xyz.elements() if elements.index(a) > heavy_e] if elm: line = line.replace("HEAVY_ELEMENT_BASIS"," ".join(elm)) else: for a in range(3): rm_lines.append(len(gjf_out)+a) if "pseudo=read" in " ".join(parameters[0:index - 3]).lower().replace(" ",""): if s_line == ["HEAVY_ELEMENT_ECP","0"]: elm = [a for a in xyz.elements() if elements.index(a) > heavy_e] if elm: line = line.replace("HEAVY_ELEMENT_ECP"," ".join(elm)) else: pattern = re.compile(r'pseudo.{0,3}=.{0,3}read',re.IGNORECASE) eval_lines = gjf_out[0:index-3] for idx_a,a in enumerate(eval_lines): gjf_out[idx_a] = pattern.sub("",a) rm_lines.append(len(gjf_out)) rm_lines.append(len(gjf_out)+1) # BASIS like: "INSERT_GBS_BASIS" elif "INSERT_GBS_BASIS" in line: for element in sorted(xyz.elements(),key=lambda x: elements.index(x)): for line_a in basis[element]: gjf_out.append(line_a+"\n") continue # ECP like: "INSERT_GBS_ECP" elif "INSERT_GBS_ECP" in line: if "pseudo=read" in " ".join(parameters[0:index - 3]).lower().replace(" ", ""): need_ecp = [a for a in xyz.elements() if elements.index(a) > preferences.heavy_atom] for element in sorted(need_ecp,key=lambda x: elements.index(x)): for line_a in ecps[element]: gjf_out.append(line_a+"\n") if not need_ecp: pattern = re.compile(r'pseudo.{0,3}=.{0,3}read', re.IGNORECASE) eval_lines = gjf_out[0:index - 3] for idx_a, a in enumerate(eval_lines): gjf_out[idx_a] = pattern.sub("", a) continue gjf_out.append(line.replace("FILENAME",i.replace(self.original_ext,""))+"\n") gjf_out.append("\n") with open(os.path.join(os.getcwd(),(i.replace(self.original_ext,preferences.gauss_ext))),"w") as gjf_file: for line in [i for idx,i in enumerate(gjf_out) if idx not in rm_lines]: gjf_file.write(line) print(i.replace(self.original_ext,preferences.gauss_ext)," created!") except TypeError as e: print("Error on file {}".format(i)) print(e) return