def check_isomorphic(conformer): """ Compares whatever is in the log file 'f' to the SMILES of the passed in 'conformer' """ starting_molecule = RMGMolecule(smiles=conformer.smiles) starting_molecule = starting_molecule.to_single_bonds() atoms = self.read_log( os.path.join(scratch_dir, f) ) test_molecule = RMGMolecule() test_molecule.from_xyz( atoms.arrays["numbers"], atoms.arrays["positions"] ) if not starting_molecule.is_isomorphic(test_molecule): logging.info( "Output geometry of {} is not isomorphic with input geometry".format(calc.label)) return False else: logging.info( "{} was successful and was validated!".format(calc.label)) return True
def calculate_symmetry_number(self): numbers = self.ase_molecule.numbers positions = self.ase_molecule.positions mol = RMGMolecule() mol.from_xyz(numbers, positions) try: species = RMGSpecies(molecule=[mol]) self._symmetry_number = species.get_symmetry_number() except ValueError: self._symmetry_number = mol.get_symmetry_number() return self._symmetry_number
def geo_to_mol(coords, nums): """ Convert molecular geometry specified by atomic coordinates and atomic numbers to RMG molecule. Use Open Babel for most cases because it's better at recognizing long bonds. Use RMG for hydrogen because Open Babel can't do it for mysterious reasons. """ if list(nums) == [1, 1]: mol = Molecule() mol.from_xyz(nums, coords) else: xyz = '{}\n\n'.format(len(nums)) xyz += '\n'.join( '{0} {1[0]: .10f} {1[1]: .10f} {1[2]: .10f}'.format(n, c) for n, c in zip(nums, coords)) mol = pybel.readstring('xyz', xyz) mol = pybel_to_rmg(mol) return mol
def opt_conf(i, rmsd_cutoff): """ A helper function to optimize the geometry of a conformer. Only for use within this parent function """ conformer = conformers[i] calculator = conformer.ase_molecule.get_calculator() labels = [] for bond in conformer.get_bonds(): labels.append(bond.atom_indices) if isinstance(conformer, TS): label = conformer.reaction_label ind1 = conformer.rmg_molecule.get_labeled_atoms("*1")[0].sorting_label ind2 = conformer.rmg_molecule.get_labeled_atoms("*3")[0].sorting_label labels.append([ind1, ind2]) type = 'ts' else: label = conformer.smiles type = 'species' if isinstance(calc, FileIOCalculator): if calculator.directory: directory = calculator.directory else: directory = 'conformer_logs' calculator.label = "{}_{}".format(conformer.smiles, i) calculator.directory = os.path.join(directory, label,'{}_{}'.format(conformer.smiles, i)) if not os.path.exists(calculator.directory): try: os.makedirs(calculator.directory) except OSError: logging.info("An error occured when creating {}".format(calculator.directory)) calculator.atoms = conformer.ase_molecule conformer.ase_molecule.set_calculator(calculator) opt = BFGS(conformer.ase_molecule, logfile=None) if type == 'species': if isinstance(i,int): c = FixBondLengths(labels) conformer.ase_molecule.set_constraint(c) try: opt.run(steps=1e6) except RuntimeError: logging.info("Optimization failed...we will use the unconverged geometry") pass if str(i) == 'ref': conformer.update_coords_from("ase") try: rmg_mol = Molecule() rmg_mol.from_xyz( conformer.ase_molecule.arrays["numbers"], conformer.ase_molecule.arrays["positions"] ) if not rmg_mol.is_isomorphic(reference_mol): logging.info("{}_{} is not isomorphic with reference mol".format(conformer,str(i))) return False except AtomTypeError: logging.info("Could not create a RMG Molecule from optimized conformer coordinates...assuming not isomorphic") return False if type == 'ts': c = FixBondLengths(labels) conformer.ase_molecule.set_constraint(c) try: opt.run(fmax=0.20, steps=1e6) except RuntimeError: logging.info("Optimization failed...we will use the unconverged geometry") pass conformer.update_coords_from("ase") energy = get_energy(conformer) conformer.energy = energy if len(return_dict)>0: conformer_copy = conformer.copy() for index,post in return_dict.items(): conf_copy = conformer.copy() conf_copy.ase_molecule.positions = post conf_copy.update_coords_from("ase") rmsd = rdMolAlign.GetBestRMS(conformer_copy.rdkit_molecule,conf_copy.rdkit_molecule) if rmsd <= rmsd_cutoff: return True if str(i) != 'ref': return_dict[i] = conformer.ase_molecule.get_positions() return True
def validate_irc(self): """ A method to verify an IRC calc """ logging.info("Validating IRC file...") irc_path = os.path.join( self.directory, "ts", self.conformer.reaction_label, "irc", self.conformer.reaction_label + "_irc_" + self.conformer.direction + "_" + str(self.conformer.index) + ".log") complete, converged = self.verify_output_file(irc_path) if not complete: logging.info("It seems that the IRC claculation did not complete") return False if not converged: logging.info("The IRC calculation did not converge...") return False pth1 = list() steps = list() with open(irc_path) as output_file: for line in output_file: line = line.strip() if line.startswith('Point Number:'): if int(line.split()[2]) > 0: if int(line.split()[-1]) == 1: pt_num = int(line.split()[2]) pth1.append(pt_num) else: pass elif line.startswith('# OF STEPS ='): num_step = int(line.split()[-1]) steps.append(num_step) # This indexes the coordinate to be used from the parsing if steps == []: logging.error('No steps taken in the IRC calculation!') return False else: pth1End = sum(steps[:pth1[-1]]) # Compare the reactants and products irc_parse = ccread(irc_path) atomcoords = irc_parse.atomcoords atomnos = irc_parse.atomnos mol1 = RMGMolecule() mol1.from_xyz(atomnos, atomcoords[pth1End]) mol2 = RMGMolecule() mol2.from_xyz(atomnos, atomcoords[-1]) test_reaction = RMGReaction( reactants=mol1.split(), products=mol2.split(), ) r, p = self.conformer.reaction_label.split("_") reactants = [] products = [] for react in r.split("+"): react = RMGMolecule(smiles=react) reactants.append(react) for prod in p.split("+"): prod = RMGMolecule(smiles=prod) products.append(prod) possible_reactants = [] possible_products = [] for reactant in reactants: possible_reactants.append( reactant.generate_resonance_structures()) for product in products: possible_products.append( product.generate_resonance_structures()) possible_reactants = list(itertools.product(*possible_reactants)) possible_products = list(itertools.product(*possible_products)) for possible_reactant in possible_reactants: reactant_list = [] for react in possible_reactant: reactant_list.append(react.to_single_bonds()) for possible_product in possible_products: product_list = [] for prod in possible_product: product_list.append(prod.to_single_bonds()) target_reaction = RMGReaction( reactants=list(reactant_list), products=list(product_list)) if target_reaction.is_isomorphic(test_reaction): logging.info("IRC calculation was successful!") return True logging.info("IRC calculation failed for {} :(".format(irc_path)) return False