def test_rmsd_confs(): methane1 = Conformer(name='methane1', charge=0, mult=1, atoms=[ Atom('C', -1.38718, 0.38899, 0.00000), Atom('H', -0.27778, 0.38899, -0.00000), Atom('H', -1.75698, 1.06232, 0.80041), Atom('H', -1.75698, -0.64084, 0.18291), Atom('H', -1.75698, 0.74551, -0.98332) ]) methane2 = Conformer(name='methane2', charge=0, mult=1, atoms=[ Atom('C', -1.38718, 0.38899, 0.00000), Atom('H', -0.43400, 0.50158, -0.55637), Atom('H', -2.23299, 0.69379, -0.64998), Atom('H', -1.36561, 1.03128, 0.90431), Atom('H', -1.51612, -0.67068, 0.30205) ]) # Methane but rotated should have an RMSD ~ 0 Angstroms assert not conf_is_unique_rmsd( conf=methane2, conf_list=[methane1], rmsd_tol=0.1)
def _generate_conformers(self, n_confs=None): """Generate conformers at the TS """ from autode.conformers.conformer import Conformer from autode.conformers.conf_gen import get_simanl_atoms from autode.conformers.conformers import conf_is_unique_rmsd n_confs = Config.num_conformers if n_confs is None else n_confs self.conformers = [] distance_consts = get_distance_constraints(self) with Pool(processes=Config.n_cores) as pool: results = [ pool.apply_async(get_simanl_atoms, (self, distance_consts, i)) for i in range(n_confs) ] conf_atoms_list = [res.get(timeout=None) for res in results] for i, atoms in enumerate(conf_atoms_list): conf = Conformer(name=f'{self.name}_conf{i}', charge=self.charge, mult=self.mult, atoms=atoms, dist_consts=distance_consts) # If the conformer is unique on an RMSD threshold if conf_is_unique_rmsd(conf, self.conformers): conf.solvent = self.solvent conf.graph = deepcopy(self.graph) self.conformers.append(conf) logger.info(f'Generated {len(self.conformers)} conformer(s)') return None
def _generate_conformers(self, n_confs=None): """ Use a simulated annealing approach to generate conformers for this molecule. Keyword Arguments: n_confs (int): Number of conformers requested if None default to autode.Config.num_conformers """ n_confs = n_confs if n_confs is not None else Config.num_conformers self.conformers = [] if self.smiles is not None and self.rdkit_conf_gen_is_fine: logger.info(f'Using RDKit to gen conformers. {n_confs} requested') method = AllChem.ETKDGv2() method.pruneRmsThresh = Config.rmsd_threshold method.numThreads = Config.n_cores logger.info( 'Running conformation generation with RDKit... running') conf_ids = list( AllChem.EmbedMultipleConfs(self.rdkit_mol_obj, numConfs=n_confs, params=method)) logger.info(' ... done') conf_atoms_list = [ get_atoms_from_rdkit_mol_object(self.rdkit_mol_obj, conf_id) for conf_id in conf_ids ] else: logger.info('Using simulated annealing to generate conformers') with Pool(processes=Config.n_cores) as pool: results = [ pool.apply_async(get_simanl_atoms, (self, None, i)) for i in range(n_confs) ] conf_atoms_list = [res.get(timeout=None) for res in results] for i, atoms in enumerate(conf_atoms_list): conf = Conformer(name=f'{self.name}_conf{i}', charge=self.charge, mult=self.mult, atoms=atoms) # If the conformer is unique on an RMSD threshold if conf_is_unique_rmsd(conf, self.conformers): conf.solvent = self.solvent self.conformers.append(conf) logger.info(f'Generated {len(self.conformers)} unique conformer(s)') return None
def test_conf_class(): h2_conf = Conformer( name='h2_conf', charge=0, mult=1, atoms=[Atom('H', 0.0, 0.0, 0.0), Atom('H', 0.0, 0.0, 0.7)]) assert hasattr(h2_conf, 'optimise') assert hasattr(h2_conf, 'dist_consts') assert h2_conf.n_atoms == 2 assert h2_conf.energy is None assert h2_conf.dist_consts is None h2_conf.optimise(method=orca) assert h2_conf.energy == -1.160780546661 assert h2_conf.atoms is not None assert h2_conf.n_atoms == 2 # Check that if the conformer calculation does not complete successfully # then don't raise an exception for a conformer h2_conf_broken = Conformer( name='h2_conf_broken', charge=0, mult=1, atoms=[Atom('H', 0.0, 0.0, 0.0), Atom('H', 0.0, 0.0, 0.7)]) h2_conf_broken.optimise(method=orca) assert h2_conf_broken.atoms is None assert h2_conf_broken.n_atoms == 0
def test_unique_confs(): conf1 = Conformer() conf2 = Conformer() conf3 = Conformer() # Set two energies the same and leave one as none.. conf1.energy = 1 conf2.energy = 1 unique_confs = get_unique_confs(conformers=[conf1, conf2, conf3]) assert len(unique_confs) == 1 assert type(unique_confs[0]) is Conformer assert unique_confs[0].energy == 1
def test_conf_class(): os.chdir(os.path.join(here, 'data', 'conformers')) h2_conf = Conformer( name='h2_conf', charge=0, mult=1, atoms=[Atom('H', 0.0, 0.0, 0.0), Atom('H', 0.0, 0.0, 0.7)]) assert hasattr(h2_conf, 'optimise') assert hasattr(h2_conf, 'dist_consts') assert h2_conf.n_atoms == 2 assert h2_conf.energy is None assert h2_conf.dist_consts is None h2_conf.optimise(method=orca) assert h2_conf.energy == -1.160780546661 assert h2_conf.atoms is not None assert h2_conf.n_atoms == 2 # Check that if the conformer calculation does not complete successfully then # don't raise an exception for a conformer h2_conf_broken = Conformer( name='h2_conf_broken', charge=0, mult=1, atoms=[Atom('H', 0.0, 0.0, 0.0), Atom('H', 0.0, 0.0, 0.7)]) h2_conf_broken.optimise(method=orca) assert h2_conf_broken.atoms is None assert h2_conf_broken.n_atoms == 0 os.remove('h2_conf_opt_orca.inp') os.remove('h2_conf_broken_opt_orca.inp') os.chdir(here)
def test_unique_confs_none(): conf1 = Conformer() conf1.energy = 0.1 # Conformer with energy just below the threshold conf2 = Conformer() conf2.energy = 0.1 + (0.9 / Constants.ha2kJmol) unique_confs = get_unique_confs(conformers=[conf1, conf2], energy_threshold_kj=1) assert len(unique_confs) == 1 # If the energy is above the threshold there should be two unique # conformers conf2.energy += 0.2 / Constants.ha2kJmol unique_confs = get_unique_confs(conformers=[conf1, conf2], energy_threshold_kj=1) assert len(unique_confs) == 2