def test_replace_pattern_in_structure__replace_hydrogens_in_octane_with_nothing(octane):
    # CH3 CH2 CH2 CH2 CH2 CH2 CH2 CH3 #
    search_pattern = Atoms(elements='H', positions=[(0, 0, 0)])
    replace_pattern = Atoms()

    final_structure = replace_pattern_in_structure(octane, search_pattern, replace_pattern)
    assert list(final_structure.elements) == ["C"] * 8
def test_replace_pattern_in_structure__replacement_pattern_across_pbc_gets_coordinates_within_unit_cell():
    structure = Atoms(elements='CNNF', positions=[(9.1, 0., 0), (0.1, 0., 0), (1.1, 0., 0.), (2.1, 0., 0.)], cell=10*np.identity(3))
    search_pattern = Atoms(elements='CN', positions=[(0., 0., 0), (1.0, 0., 0.)])
    replace_pattern = search_pattern
    final_structure = replace_pattern_in_structure(structure, search_pattern, replace_pattern)
    assert Counter(final_structure.elements) == Counter(structure.elements)
    assert_structure_positions_are_unchanged(structure, final_structure)
def test_replace_pattern_in_structure__replace_hydrogens_in_octane_with_fluorines_half_the_time(octane):
    search_pattern = Atoms(elements='H', positions=[(0, 0, 0)])
    replace_pattern = Atoms(elements='F', positions=[(0, 0, 0)])
    match_indices = find_pattern_in_structure(octane, search_pattern)
    final_structure = replace_pattern_in_structure(octane, search_pattern, replace_pattern, replace_fraction=0.5)
    assert Counter(final_structure.elements) == {"H":9, "F": 9, "C": 8}
    assert_structure_positions_are_unchanged(octane, final_structure)
def test_replace_pattern_in_structure__overlapping_match_patterns_errors():
    structure = Atoms(elements='CNNC', positions=[(0., 0., 0), (1.0, 0., 0.), (2.0, 0., 0.), (3.0, 0., 0.)], cell=100*np.identity(3))
    search_pattern = Atoms(elements='NNC', positions=[(0., 0., 0), (1.0, 0., 0.), (2.0, 0., 0.)])
    replace_pattern = Atoms(elements='FFC', positions=[(0., 0., 0), (1.0, 0., 0.), (2.0, 0., 0.)])

    with pytest.raises(AtomsShouldNotBeDeletedTwice):
        final_structure = replace_pattern_in_structure(structure, search_pattern, replace_pattern)
def test_replace_pattern_in_structure__replace_CH3_in_octane_with_CH3(octane):
    search_pattern = Atoms(elements='CHHH', positions=[(0, 0, 0), (-0.538, -0.635,  0.672), (-0.397,  0.993,  0.052), (-0.099, -0.371, -0.998)])
    replace_pattern = Atoms(elements='CHHH', positions=search_pattern.positions)
    final_structure = replace_pattern_in_structure(octane, search_pattern, replace_pattern)
    assert Counter(final_structure.elements) == {"C": 8, "H": 18}
    # note the positions are not EXACTLY the same because the original structure has slightly
    # different coordinates for the two CH3 groups!
    assert_structure_positions_are_unchanged(octane, final_structure, max_delta=0.1)
def test_replace_pattern_in_structure__two_points_on_x_axis_positions_are_unchanged():
    structure = Atoms(elements='CNNC', positions=[(0., 0., 0), (1.0, 0., 0.), (2.0, 0., 0.), (3.0, 0., 0.)], cell=100*np.identity(3))
    search_pattern = Atoms(elements='NN', positions=[(0.0, 0., 0), (1.0, 0., 0.)])
    replace_pattern = Atoms(elements='FF', positions=[(0., 0., 0), (1.0, 0., 0.)])

    final_structure = replace_pattern_in_structure(structure, search_pattern, replace_pattern)
    assert Counter(final_structure.elements) == {"C":2, "F": 2}
    assert_structure_positions_are_unchanged(structure, final_structure)
def test_replace_pattern_in_structure__replace_no_bonds_linker_with_linker_with_bonds_angles_has_bonds_angles(uio66_linker_no_bonds, uio66_linker_some_bonds):
    structure = uio66_linker_no_bonds.copy()
    structure.cell = 100*np.identity(3)
    final_structure = replace_pattern_in_structure(structure, uio66_linker_no_bonds, uio66_linker_some_bonds, axis1a_idx=0, axis1b_idx=15)

    assert Counter(final_structure.elements) == {'C': 8, 'O': 4, 'H': 4}
    assert_structure_positions_are_unchanged(structure, final_structure, max_delta=0.1)
    assert_topo(final_structure.dihedrals, uio66_linker_some_bonds.dihedrals,
                final_structure.dihedral_types, uio66_linker_some_bonds.dihedral_types,
                final_structure.dihedral_type_coeffs, uio66_linker_some_bonds.dihedral_type_coeffs)
def test_replace_pattern_in_structure__special2_rotated_pattern_replaced_with_itself_does_not_change_positions():
    search_pattern = Atoms(elements='CCH', positions=[(0., 0., 0.), (4., 0., 0.),(0., 1., 0.)])
    replace_pattern = Atoms(elements='FFHe', positions=search_pattern.positions)
    structure = search_pattern.copy()
    structure.cell = 15 * np.identity(3)
    r = R.from_quat([ 0.02814096,  0.99766676,  0.03984918, -0.04776152])
    structure.positions = r.apply(structure.positions)
    structure.positions = structure.positions % 15
    final_structure = replace_pattern_in_structure(structure, search_pattern, replace_pattern, axis1a_idx=0, axis1b_idx=1)
    assert_structure_positions_are_unchanged(structure, final_structure)
def test_replace_pattern_in_structure__in_uio66_replacing_linker_with_linker_does_not_change_positions():
    with Path("tests/uio66/uio66.cif") as path:
        structure = Atoms.load_cif(path)
    with Path("tests/uio66/uio66-linker.cif") as path:
        search_pattern = Atoms.load_cif(path)
    with Path("tests/uio66/uio66-linker-fluorinated.cif") as path:
        replace_pattern = Atoms.load_cif(path)

    final_structure = replace_pattern_in_structure(structure, search_pattern, replace_pattern)
    assert Counter(final_structure.elements) == {'C': 192, 'O': 120, 'F': 96, 'Zr': 24}
def test_replace_pattern_in_structure__pattern_and_reverse_pattern_on_x_axis_positions_are_unchanged():
    structure = Atoms(elements='HHCCCHH', positions=[(-1., 1, 0), (-1., -1, 0), (0., 0., 0), (1., 0., 0.), (3., 0., 0.), (4., 1, 0), (4., -1, 0)], cell=7*np.identity(3))
    structure.translate([2, 2, 0.1])
    search_pattern = Atoms(elements='HHC', positions=[(0., 1, 0), (0., -1, 0), (1., 0., 0.)])
    replace_pattern = Atoms(elements='HHC', positions=[(0., 1, 0), (0., -1, 0), (1., 0., 0.)])

    final_structure = replace_pattern_in_structure(structure, search_pattern, replace_pattern)

    assert Counter(final_structure.elements) == {"C":3, "H": 4}
    assert_structure_positions_are_unchanged(structure, final_structure)
def test_replace_pattern_in_structure__special_rotated_pattern_replaced_with_itself_does_not_change_positions():
    search_pattern = Atoms(elements='CCH', positions=[(0., 0., 0.), (4., 0., 0.),(0., 1., 0.)])
    replace_pattern = Atoms(elements='FFHe', positions=search_pattern.positions)
    structure = search_pattern.copy()
    structure.cell = [15] * np.identity(3)
    r = R.from_quat([-0.4480244,  -0.50992783,  0.03212454, -0.7336319 ])
    structure.positions = r.apply(structure.positions)
    structure.positions = structure.positions % 15
    final_structure = replace_pattern_in_structure(structure, search_pattern, replace_pattern, axis1a_idx=0, axis1b_idx=1)
    assert_structure_positions_are_unchanged(structure, final_structure)
def test_replace_pattern_in_structure__3way_symmetrical_structure_raises_position_exception():
    structure = Atoms(elements='CCHH', positions=[(0., 0., 0.), (1., 0., 0.),(0., 1., 0.), (0., 0., 1.)])
    structure.translate((3,3,3))
    structure.cell = 15 * np.identity(3)

    search_pattern = structure.copy()

    replace_pattern = Atoms(elements='FFHeHe', positions=search_pattern.positions)

    with pytest.raises(PositionsNotEquivalent):
        final_structure = replace_pattern_in_structure(structure, search_pattern, replace_pattern, verbose=True)
def test_replace_pattern_in_structure__three_points_on_x_axis_positions_are_unchanged():
    # this test exists to verify that for a search pattern with more than 2 atoms where all atoms lie on the same axis
    # there are no errors, since there is an extra unnecessary quaternion calcuation to orient the replacement pattern
    # into the final position
    structure = Atoms(elements='CNNNC', positions=[(0., 0., 0), (1., 0., 0.), (2., 0., 0.), (3., 0., 0.), (4., 0., 0.)], cell=100*np.identity(3))
    search_pattern = Atoms(elements='NNN', positions=[(0., 0., 0), (1.0, 0., 0.), (2.0, 0., 0.)])
    replace_pattern = Atoms(elements='FFF', positions=[(0., 0., 0), (1.0, 0., 0.), (2.0, 0., 0.)])

    final_structure = replace_pattern_in_structure(structure, search_pattern, replace_pattern)
    assert Counter(final_structure.elements) == {"C":2, "F": 3}
    assert_structure_positions_are_unchanged(structure, final_structure)
def test_replace_pattern_in_structure__100_randomly_rotated_patterns_replaced_with_itself_does_not_change_positions():
    search_pattern = Atoms(elements='CCH', positions=[(0., 0., 0.), (4., 0., 0.),(0., 1., 0.)])
    replace_pattern = Atoms(elements='FFHe', positions=search_pattern.positions)
    structure = search_pattern.copy()
    structure.cell = 15 * np.identity(3)
    for _ in range(100):
        r = R.random(1)
        print("quat: ", r.as_quat())
        structure.positions = r.apply(structure.positions)
        dp = np.random.random(3) * 15
        print(dp)
        structure.translate(dp)
        structure.positions = structure.positions % 15
        final_structure = replace_pattern_in_structure(structure, search_pattern, replace_pattern, axis1a_idx=0, axis1b_idx=1)
        assert_structure_positions_are_unchanged(structure, final_structure)
Beispiel #15
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)
def test_replace_pattern_in_structure__in_hkust1_offset_replacing_benzene_with_benzene_does_not_change_positions(hkust1_cif, benzene):
    hkust1_cif.translate((-4,-4,-4))
    hkust1_cif.positions = hkust1_cif.positions % np.diag(hkust1_cif.cell)
    final_structure = replace_pattern_in_structure(hkust1_cif, benzene, benzene, axis1a_idx=0, axis1b_idx=7)
    assert Counter(final_structure.elements) == Counter(hkust1_cif.elements)
    assert_structure_positions_are_unchanged(hkust1_cif, final_structure, max_delta=0.1)
def test_replace_pattern_in_structure__in_hkust1_replacing_benzene_with_benzene_does_not_change_positions(hkust1_cif, benzene):
    final_structure = replace_pattern_in_structure(hkust1_cif, benzene, benzene, axis1a_idx=0, axis1b_idx=7)
    assert Counter(final_structure.elements) == Counter(hkust1_cif.elements)
    assert_structure_positions_are_unchanged(hkust1_cif, final_structure, max_delta=0.1)
Beispiel #18
0
for repldims in all_repldims:
    structure = uio67.replicate(repldims=repldims)
    time_s = time.process_time()
    perf_s = time.perf_counter()
    patterns = find_pattern_in_structure(structure, uio67_linker)
    output_csv.writerow(
        ("uio67", "%dx%dx%dx" % repldims, len(structure),
         len(patterns), 24 * repldims[0] * repldims[1] * repldims[2],
         time.process_time() - time_s, time.perf_counter() - perf_s))

for repldims in all_repldims:
    structure = uio66.replicate(repldims=repldims)
    time_s = time.process_time()
    perf_s = time.perf_counter()
    patterns = replace_pattern_in_structure(structure, uio66_linker,
                                            uio66_linker)
    output_csv.writerow(
        ("uio66", "%dx%dx%dx" % repldims, len(structure), len(patterns),
         time.process_time() - time_s, time.perf_counter() - perf_s))

for repldims in all_repldims:
    structure = uio67.replicate(repldims=repldims)
    time_s = time.process_time()
    perf_s = time.perf_counter()
    patterns = replace_pattern_in_structure(structure, uio67_linker,
                                            uio67_linker)
    output_csv.writerow(
        ("uio67", "%dx%dx%dx" % repldims, len(structure), len(patterns),
         time.process_time() - time_s, time.perf_counter() - perf_s))
Beispiel #19
0
def mofun_cli(inputpath,
              outputpath,
              find_path=None,
              replace_path=None,
              replace_fraction=1.0,
              axis1a_idx=0,
              axis1b_idx=-1,
              axis2_idx=None,
              dumppath=None,
              chargefile=None,
              replicate=None,
              mic=None,
              framework_element=None,
              pp=False):
    atoms = Atoms.load(inputpath)

    # upate positions from lammps dump file
    if dumppath is not None:
        # update positions in original atoms file with new positions
        dumpatoms = ase.io.read(dumppath, format="lammps-dump-text")
        assert len(dumpatoms.positions) == len(atoms.positions)
        atoms.positions = dumpatoms.positions

    # update charges
    if chargefile is not None:
        charges = np.array(
            [float(line.strip()) for line in chargefile if line.strip() != ''])
        assert len(charges) == len(atoms.positions)
        atoms.charges = charges

    if replicate is not None:
        atoms = atoms.replicate(replicate)

    # replicate to meet minimum image convention, if necessary
    if mic is not None:
        repls = np.array(np.ceil(2 * mic / np.diag(atoms.cell)), dtype=int)
        atoms = atoms.replicate(repls)

    if pp:
        assign_pair_params_to_structure(atoms)

    if replace_path is not None and find_path is None:
        print("Cannot perform a replace operation without a find operation")
    elif find_path is not None:
        search_pattern = Atoms.load(find_path)
        if replace_path is not None:
            replace_pattern = Atoms.load(replace_path)
            atoms = replace_pattern_in_structure(
                atoms,
                search_pattern,
                replace_pattern,
                axis1a_idx=axis1a_idx,
                axis1b_idx=axis1b_idx,
                axis2_idx=axis2_idx,
                replace_fraction=replace_fraction)
        else:
            results = find_pattern_in_structure(atoms, search_pattern)
            print("Found %d instances of the search_pattern in the structure" %
                  len(results))
            print(results)

    # set framework elements to specified element-only works on ASE exports
    if framework_element is not None:
        atoms.symbols[atoms.atom_groups == 0] = framework_element

    if outputpath.suffix in ['.lmpdat', '.mol']:
        atoms.save(outputpath)
    else:
        print("INFO: Trying output using ASE")
        aseatoms = atoms.to_ase()
        if framework_element is not None:
            aseatoms.symbols[atoms.atom_groups == 0] = framework_element

        aseatoms.set_pbc(True)
        aseatoms.write(outputpath)
def test_replace_pattern_in_structure__replace_hydrogens_in_octane_with_nothing_quarter_time(octane):
    search_pattern = Atoms(elements='H', positions=[(0, 0, 0)])
    final_structure = replace_pattern_in_structure(octane, search_pattern, Atoms(), replace_fraction=0.25)
    assert Counter(final_structure.elements) == {"H": 14, "C": 8}
def test_replace_pattern_in_structure__replace_hydrogens_in_octane_with_hydrogens(octane):
    search_pattern = Atoms(elements='H', positions=[(0, 0, 0)])
    replace_pattern = search_pattern
    final_structure = replace_pattern_in_structure(octane, search_pattern, replace_pattern)
    assert Counter(final_structure.elements) == {"H": 18, "C": 8}
    assert_structure_positions_are_unchanged(octane, final_structure)