Ejemplo n.º 1
0
def test_butene(tmpdir):
    os.chdir(tmpdir)

    butene = Molecule(name='z-but-2-ene',
                      charge=0,
                      mult=1,
                      atoms=[
                          Atom('C', -1.69185, -0.28379, -0.01192),
                          Atom('C', -0.35502, -0.40751, 0.01672),
                          Atom('C', -2.39437, 1.04266, -0.03290),
                          Atom('H', -2.13824, 1.62497, 0.87700),
                          Atom('H', -3.49272, 0.88343, -0.05542),
                          Atom('H', -2.09982, 1.61679, -0.93634),
                          Atom('C', 0.57915, 0.76747, 0.03048),
                          Atom('H', 0.43383, 1.38170, -0.88288),
                          Atom('H', 1.62959, 0.40938, 0.05452),
                          Atom('H', 0.39550, 1.39110, 0.93046),
                          Atom('H', -2.29700, -1.18572, -0.02030),
                          Atom('H', 0.07422, -1.40516, 0.03058)
                      ])

    butene.graph.nodes[0]['stereo'] = True
    butene.graph.nodes[1]['stereo'] = True

    # Conformer generation should retain the stereochemistry
    atoms = conf_gen.get_simanl_atoms(species=butene)
    regen = Molecule(name='regenerated_butene', atoms=atoms, charge=0, mult=1)

    regen.print_xyz_file()
    regen_coords = regen.get_coordinates()

    # The Z-butene isomer has a r(C_1 C_2) < 3.2 Å where C_1C=CC_2
    assert np.linalg.norm(regen_coords[6] - regen_coords[2]) < 3.6

    os.chdir(here)
Ejemplo n.º 2
0
def init_smiles(molecule, smiles):
    """
    Initialise a molecule from a SMILES string
    Arguments:
        molecule (autode.molecule.Molecule):
        smiles (str): SMILES string
    """
    # Assume that the RDKit conformer generation algorithm is not okay for
    # metals
    molecule.rdkit_conf_gen_is_fine = False

    parser = parse_smiles(smiles)

    molecule.charge = parser.charge
    molecule.mult = calc_multiplicity(
        molecule=molecule, n_radical_electrons=parser.n_radical_electrons)

    molecule.set_atoms(atoms=parser.atoms)

    make_graph(molecule, bond_list=parser.bonds)

    for stereocentre in parser.stereocentres:
        molecule.graph.nodes[stereocentre]['stereo'] = True
    for bond_index in parser.bond_order_dict.keys():
        bond = parser.bonds[bond_index]
        molecule.graph.edges[bond]['pi'] = True

    molecule.set_atoms(atoms=get_simanl_atoms(molecule))
    check_bonds(molecule, bonds=parser.bonds)

    return None
Ejemplo n.º 3
0
def test_ts_conformer(tmpdir):
    os.chdir(tmpdir)

    ch3cl = Reactant(charge=0,
                     mult=1,
                     atoms=[
                         Atom('Cl', 1.63664, 0.02010, -0.05829),
                         Atom('C', -0.14524, -0.00136, 0.00498),
                         Atom('H', -0.52169, -0.54637, -0.86809),
                         Atom('H', -0.45804, -0.50420, 0.92747),
                         Atom('H', -0.51166, 1.03181, -0.00597)
                     ])
    f = Reactant(charge=-1, mult=1, atoms=[Atom('F', 4.0, 0.0, 0.0)])

    ch3f = Product(charge=0,
                   mult=1,
                   atoms=[
                       Atom('C', -0.05250, 0.00047, -0.00636),
                       Atom('F', 1.31229, -0.01702, 0.16350),
                       Atom('H', -0.54993, -0.04452, 0.97526),
                       Atom('H', -0.34815, 0.92748, -0.52199),
                       Atom('H', -0.36172, -0.86651, -0.61030)
                   ])
    cl = Reactant(charge=-1, mult=1, atoms=[Atom('Cl', 4.0, 0.0, 0.0)])

    f_ch3cl_tsguess = TSguess(reactant=ReactantComplex(f, ch3cl),
                              product=ProductComplex(ch3f, cl),
                              atoms=[
                                  Atom('F', -2.66092, -0.01426, 0.09700),
                                  Atom('Cl', 1.46795, 0.05788, -0.06166),
                                  Atom('C', -0.66317, -0.01826, 0.02488),
                                  Atom('H', -0.78315, -0.58679, -0.88975),
                                  Atom('H', -0.70611, -0.54149, 0.97313),
                                  Atom('H', -0.80305, 1.05409, 0.00503)
                              ])

    f_ch3cl_tsguess.bond_rearrangement = BondRearrangement(breaking_bonds=[
        (2, 1)
    ],
                                                           forming_bonds=[(0,
                                                                           2)])

    f_ch3cl_ts = TransitionState(ts_guess=f_ch3cl_tsguess)

    atoms = conf_gen.get_simanl_atoms(
        species=f_ch3cl_ts, dist_consts=get_distance_constraints(f_ch3cl_ts))

    regen = Molecule(name='regenerated_ts', charge=-1, mult=1, atoms=atoms)
    # regen.print_xyz_file()

    # Ensure the making/breaking bonds retain their length
    regen_coords = regen.get_coordinates()
    assert are_coords_reasonable(regen_coords) is True

    assert 1.9 < np.linalg.norm(regen_coords[0] - regen_coords[2]) < 2.1
    assert 2.0 < np.linalg.norm(regen_coords[1] - regen_coords[2]) < 2.2

    os.chdir(here)
Ejemplo n.º 4
0
def test_conf_gen(tmpdir):
    os.chdir(tmpdir)

    atoms = conf_gen.get_simanl_atoms(species=methane)
    assert len(atoms) == 5
    assert os.path.exists('methane_conf0_siman.xyz')

    # Rerunning the conformer generation should read the generated .xyz file
    atoms = conf_gen.get_simanl_atoms(species=methane)
    assert len(atoms) == 5

    os.remove('methane_conf0_siman.xyz')

    # Ensure the new graph is identical
    regen = Molecule(name='regenerated_methane', atoms=atoms)

    assert regen.graph.edges == methane.graph.edges
    assert regen.graph.nodes == methane.graph.nodes

    os.chdir(here)
Ejemplo n.º 5
0
def init_organic_smiles(molecule, smiles):
    """
    Initialise a molecule from a SMILES string, set the charge, multiplicity (
    if it's not already specified) and the 3D geometry using RDKit

    Arguments:
        molecule (autode.molecule.Molecule):
        smiles (str): SMILES string
    """

    try:
        molecule.rdkit_mol_obj = Chem.MolFromSmiles(smiles)

        if molecule.rdkit_mol_obj is None:
            logger.warning('RDKit failed to initialise a molecule')
            return init_smiles(molecule, smiles)

        molecule.rdkit_mol_obj = Chem.AddHs(molecule.rdkit_mol_obj)
    except RuntimeError:
        raise RDKitFailed

    molecule.charge = Chem.GetFormalCharge(molecule.rdkit_mol_obj)
    molecule.mult = calc_multiplicity(molecule,
                                      NumRadicalElectrons(molecule.rdkit_mol_obj))
    bonds = [(bond.GetBeginAtomIdx(), bond.GetEndAtomIdx())
             for bond in molecule.rdkit_mol_obj.GetBonds()]

    # Generate a single 3D structure using RDKit's ETKDG conformer generation
    # algorithm
    method = AllChem.ETKDGv2()
    method.randomSeed = 0xf00d
    AllChem.EmbedMultipleConfs(molecule.rdkit_mol_obj, numConfs=1, params=method)
    molecule.atoms = atoms_from_rdkit_mol(molecule.rdkit_mol_obj, conf_id=0)
    make_graph(molecule, bond_list=bonds)

    # Revert back to RR if RDKit fails to return a sensible geometry
    if not are_coords_reasonable(coords=molecule.coordinates):
        molecule.rdkit_conf_gen_is_fine = False
        molecule.atoms = get_simanl_atoms(molecule, save_xyz=False)

    for atom, _ in Chem.FindMolChiralCenters(molecule.rdkit_mol_obj):
        molecule.graph.nodes[atom]['stereo'] = True

    for bond in molecule.rdkit_mol_obj.GetBonds():
        if bond.GetBondType() != Chem.rdchem.BondType.SINGLE:
            molecule.graph.edges[bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()]['pi'] = True
        if bond.GetStereo() != Chem.rdchem.BondStereo.STEREONONE:
            molecule.graph.nodes[bond.GetBeginAtomIdx()]['stereo'] = True
            molecule.graph.nodes[bond.GetEndAtomIdx()]['stereo'] = True

    check_bonds(molecule, bonds=molecule.rdkit_mol_obj.GetBonds())

    return None
Ejemplo n.º 6
0
def test_chiral_rotation(tmpdir):
    os.chdir(tmpdir)

    chiral_ethane = Molecule(name='chiral_ethane',
                             charge=0,
                             mult=1,
                             atoms=[
                                 Atom('C', -0.26307, 0.59858, -0.07141),
                                 Atom('C', 1.26597, 0.60740, -0.09729),
                                 Atom('Cl', -0.91282, 2.25811, 0.01409),
                                 Atom('F', -0.72365, -0.12709, 1.01313),
                                 Atom('H', -0.64392, 0.13084, -1.00380),
                                 Atom('Cl', 1.93888, 1.31880, 1.39553),
                                 Atom('H', 1.61975, 1.19877, -0.96823),
                                 Atom('Br', 1.94229, -1.20011, -0.28203)
                             ])

    chiral_ethane.graph.nodes[0]['stereo'] = True
    chiral_ethane.graph.nodes[1]['stereo'] = True

    atoms = conf_gen.get_simanl_atoms(chiral_ethane)
    regen = Molecule(name='regenerated_ethane', charge=0, mult=1, atoms=atoms)

    regen_coords = regen.get_coordinates()
    coords = chiral_ethane.get_coordinates()

    # Atom indexes of the C(C)(Cl)(F)(H) chiral centre
    ccclfh = [0, 1, 2, 3, 4]

    # Atom indexes of the C(C)(Cl)(Br)(H) chiral centre
    ccclbrh = [1, 0, 5, 7, 6]

    for centre_idxs in [ccclfh, ccclbrh]:
        # Ensure the fragmented centres map almost identically
        # if calc_rmsd(template_coords=coords[centre_idxs], coords_to_
        # fit=regen_coords[centre_idxs]) > 0.5:
        #     chiral_ethane.print_xyz_file(filename=os.path.join(here,
        # 'chiral_ethane.xyz'))
        #     regen.print_xyz_file(filename=os.path.join(here, 'regen.xyz'))

        # RMSD on the 5 atoms should be < 0.5 Å
        assert calc_rmsd(coords1=coords[centre_idxs],
                         coords2=regen_coords[centre_idxs]) < 0.5

    os.chdir(here)
Ejemplo n.º 7
0
def test_conf_gen_dist_const(tmpdir):
    os.chdir(tmpdir)

    hydrogen = Molecule(
        name='H2',
        charge=0,
        mult=1,
        atoms=[Atom(atomic_symbol='H'),
               Atom(atomic_symbol='H', z=0.7)])

    # H2 at a bond length (r) of 0.7 Å has a bond
    assert len(hydrogen.graph.edges) == 1

    # H2 at r = 1.5 Å is definitely not bonded
    atoms = conf_gen.get_simanl_atoms(species=hydrogen,
                                      dist_consts={(0, 1): 1.5})

    long_hydrogen = Molecule(name='H2', atoms=atoms, charge=0, mult=1)
    assert long_hydrogen.n_atoms == 2
    assert len(long_hydrogen.graph.edges) == 0

    os.chdir(here)
Ejemplo n.º 8
0
from autode.input_output import xyz_file_to_atoms
from autode.conformers import conf_gen, Conformer
from autode.methods import XTB

# Initialise the complex from a .xyz file containing a square planar structure
vaskas = Molecule(name='vaskas', atoms=xyz_file_to_atoms('vaskas.xyz'))

# Set up some distance constraints where the keys are the atom indexes and
# the value the distance in Å. Fixing the Cl-P, Cl-P and Cl-C(=O) distances
# enforces a square planar geometry
distance_constraints = {
    (1, 2): vaskas.get_distance(1, 2),
    (1, 3): vaskas.get_distance(1, 3),
    (1, 4): vaskas.get_distance(1, 4)
}

# Generate 5 conformers
for n in range(5):

    # Apply random displacements to each atom and minimise under a bonded +
    # repulsive forcefield including the distance constraints
    atoms = conf_gen.get_simanl_atoms(species=vaskas,
                                      dist_consts=distance_constraints,
                                      conf_n=n)

    # Generate a conformer from these atoms then optimise with XTB
    conformer = Conformer(name=f'vaskas_conf{n}', atoms=atoms)

    conformer.optimise(method=XTB())
    conformer.print_xyz_file()