Пример #1
0
def functionalize_structure_with_linkers(structure_path,
                                         linker_path,
                                         fnlinkers,
                                         output_dir=Path()):
    linker = Atoms.from_cml(Path(linker_path))
    structure = Atoms.from_cif(structure_path)
    output_dir = Path(output_dir)
    assign_pair_params_to_structure(structure)
    for fnlinker_path in fnlinkers:
        print("reading %s" % fnlinker_path)
        fnlinker = Atoms.from_lammps_data(open(fnlinker_path, "r"),
                                          use_comment_for_type_labels=True)
        try:
            new_structure = replace_pattern_in_structure(
                structure, linker, fnlinker)
            with open(
                    output_dir.joinpath(Path(fnlinker_path).stem + ".lmpdat"),
                    "w") as fd:
                new_structure.to_lammps_data(fd)
        except Exception as e:
            print("ERROR! ", e.args)
Пример #2
0
def check_cml_files(paths, linker, num_linkers, position_check_indices=[]):
    """ checks if more coordinates were changed in functionalized linker than just the newly added
    functional group atoms
    """
    for fnlinker_path in paths:
        fnlinker = Atoms.from_cml(fnlinker_path)
        match_pairs = find_unchanged_atom_pairs(linker, fnlinker)
        if len(match_pairs) == (len(linker) - num_linkers):
            marker = ""
        else:
            marker = "*"
            bad_indices = set(
                np.argwhere(fnlinker.positions[0:len(linker), :] !=
                            linker.positions[0:len(linker), :])[:, 0])
            marker += ".".join([str(i + 1) for i in bad_indices])

        if (fnlinker[position_check_indices].positions !=
                linker[position_check_indices].positions).any():
            position_marker = "P"
        else:
            position_marker = ""
        print("%s%s %s: unchanged %d/%d" %
              (marker, position_marker, fnlinker_path, len(match_pairs),
               len(fnlinker)))
Пример #3
0
                            linker.positions[0:len(linker), :])[:, 0])
            marker += ".".join([str(i + 1) for i in bad_indices])

        if (fnlinker[position_check_indices].positions !=
                linker[position_check_indices].positions).any():
            position_marker = "P"
        else:
            position_marker = ""
        print("%s%s %s: unchanged %d/%d" %
              (marker, position_marker, fnlinker_path, len(match_pairs),
               len(fnlinker)))


# check UIO-66 linkers
linker_path = Path("linkers-cml/uio66.cml")
linker = Atoms.from_cml(linker_path)
all_linkers = list(Path("linkers-cml").glob("uio66-*.cml"))
double_linkers = list(Path("linkers-cml").glob("uio66-*-2.cml"))
non_double_linkers = set(all_linkers) - set(double_linkers)

print("\nUIO-66 two linkers")
check_cml_files(double_linkers, linker, 2, (0, 14))
print("\nUIO-66 one linker (and more than two linkers)")
check_cml_files(non_double_linkers, linker, 1, (0, 14))

# check UIO-67 linkers
linker_path = Path("linkers-cml/uio67.cml")
linker = Atoms.from_cml(linker_path)
all_linkers = list(Path("linkers-cml").glob("uio67-*.cml"))
double_linkers = list(Path("linkers-cml").glob("uio67-*-2.cml"))
non_double_linkers = set(all_linkers) - set(double_linkers)
Пример #4
0
"""
convert all linkers to cif files, so our lammps-data file can be compared to the pete-boyd code

You will need to run
```
gsed -i -e 's/_atom_site_Cartn_/_atom_site_/g' *.cif
```
afterwards so that the cif has the labels that Lammps-interface requires

```fish
for x in ../linkers-cif/*.cif
    lammps-interface --molecule-ff=UFF $x
end
```
"""

from pathlib import Path

import numpy as np

from mofun import Atoms

out_path = Path("linkers-cif")
for fnlinker_path in Path("linkers-cml").glob("*.cml"):
    print("reading %s" % fnlinker_path)
    fnlinker = Atoms.from_cml(fnlinker_path)
    fnlinker.cell = cell = 50 * np.identity(3)
    fnlinker.to_ase().write(out_path.joinpath(fnlinker_path.stem + ".cif"))
Пример #5
0
def cml2lmpdat_typed_parameterized_for_new_atoms(fnlinker_path, linker_path=None, outpath="-"):

    uff_rules = {
        "H": [
            ("H_b", dict(n=2)),
            ("H_", {})
        ],
        "N": [
            ("N_R", dict(n=3, aromatic=True)),
            ("N_1", dict(neighbors=("N","N")))
        ],
        "O": [("O_1", dict(n=1))],
        "C": [("C_R", dict(n=3, aromatic=True))]
    }
    bond_order_rules = [({'N_1'}, 2), ({'N_1', 'N_2'}, 2)]

    linker = None
    if linker_path is not None:
        linker = Atoms.from_cml(linker_path)

    fnlinker = Atoms.from_cml(fnlinker_path)

    # assign uff atom types using mofun.rough_uff
    g = nx.Graph()
    g.add_edges_from(fnlinker.bonds)
    uff_types = ruff.assign_uff_atom_types(g, fnlinker.elements, override_rules=uff_rules)
    fnlinker.retype_atoms_from_uff_types(uff_types)

    # calculate all possible many-body terms
    fnlinker.calc_angles()
    fnlinker.calc_dihedrals()


    if linker is not None:
        # remove any dihedrals, angles and bonds that are unchanged from the original linker,
        # as we are only going to relax the new functional group, leaving everything else fixed.
        print("Num dihedrals, angles, bonds: %d, %d, %d" % (len(fnlinker.dihedrals), len(fnlinker.angles), len(fnlinker.bonds)))
        match_pairs = find_unchanged_atom_pairs(linker, fnlinker)
        unchanged_atom_indices = set()
        if len(match_pairs) > 0:
            unchanged_atom_indices = set(list(zip(*match_pairs))[1])

        # assign atoms to molecules where 0 is original linker, 1 is for new functional group atoms
        fnlinker.atom_groups = [0 if i in unchanged_atom_indices else 1 for i in range(len(fnlinker))]

        fnlinker.bonds = delete_if_all_in_set(fnlinker.bonds, unchanged_atom_indices)
        fnlinker.angles = delete_if_all_in_set(fnlinker.angles, unchanged_atom_indices)


    # calculate potential parameters and assign type #s to linker
    fnlinker.pair_params = ['%10.6f %10.6f # %s' % (*ruff.pair_params(a1), a1) for a1 in fnlinker.atom_type_labels]

    bond_types = [order_types([uff_types[b1], uff_types[b2]]) for b1, b2 in fnlinker.bonds]
    unique_bond_types = list(dict.fromkeys(bond_types).keys())
    fnlinker.bond_types = [unique_bond_types.index(bt) for bt in bond_types]
    bond_params = [(*ruff.bond_params(a1, a2, bond_order_rules=bond_order_rules), "%s %s" % (a1, a2)) for (a1, a2) in unique_bond_types]
    fnlinker.bond_type_params = ['%10.6f %10.6f # %s' % params for params in bond_params]

    angle_types = [order_types([uff_types[a] for a in atoms]) for atoms in fnlinker.angles]
    unique_angle_types = list(dict.fromkeys(angle_types).keys())
    fnlinker.angle_types = [unique_angle_types.index(a) for a in angle_types]
    angle_params = [(*ruff.angle_params(*a_ids, bond_order_rules=bond_order_rules), "%s %s %s" % a_ids) for a_ids in unique_angle_types]
    fnlinker.angle_type_params = [angle2lammpsdat(a) for a in angle_params]

    num_dihedrals_per_bond = Counter([order_types([a2, a3]) for _, a2, a3, _ in fnlinker.dihedrals])
    if linker is not None:
        fnlinker.dihedrals = delete_if_all_in_set(fnlinker.dihedrals, unchanged_atom_indices)

    dihedral_types = [(*order_types([uff_types[a] for a in atoms]),
                            num_dihedrals_per_bond[order_types([atoms[1], atoms[2]])])
                        for atoms in fnlinker.dihedrals]
    unique_dihedral_types = list(dict.fromkeys(dihedral_types).keys())
    dihedral_params = [ruff.dihedral_params(*a_ids, bond_order_rules=bond_order_rules) for a_ids in unique_dihedral_types]

    # delete any dihedrals when the params come back None (i.e. for *_1)
    for i in reversed(range(len(dihedral_params))):
        if dihedral_params[i] is None:
            none_dihedral = unique_dihedral_types[i]
            print(len(fnlinker.dihedrals), len(dihedral_types), len(unique_dihedral_types), len(dihedral_params))

            fnlinker.dihedrals = [d for j, d in enumerate(fnlinker.dihedrals) if dihedral_types[j] != none_dihedral]
            dihedral_types = [d for d in dihedral_types if d != none_dihedral]

            del(unique_dihedral_types[i])
            del(dihedral_params[i])
            print(len(fnlinker.dihedrals), len(dihedral_types), len(unique_dihedral_types), len(dihedral_params))

    # assign dihedral types
    fnlinker.dihedral_types = [unique_dihedral_types.index(a) for a in dihedral_types]
    dihedral_params = [(*ruff.dihedral_params(*a_ids, bond_order_rules=bond_order_rules), "%s %s %s %s M=%d" % a_ids) for a_ids in unique_dihedral_types]
    fnlinker.dihedral_type_params = ['%s %10.6f %d %d # %s' % params for params in dihedral_params]

    print("Num dihedrals, angles, bonds: %d, %d, %d" % (len(fnlinker.dihedrals), len(fnlinker.angles), len(fnlinker.bonds)))

    # output lammps-data file
    with open(outpath, "w") as f:
        fnlinker.to_lammps_data(f)