示例#1
0
def from_snapshot(snapshot, scale=1.0):
    """Convert a Snapshot to a Compound.

    Snapshot can be a hoomd.data.Snapshot or a gsd.hoomd.Snapshot.

    Parameters
    ----------
    snapshot : hoomd._hoomd.SnapshotSystemData_float or gsd.hoomd.Snapshot
        Snapshot from which to build the mbuild Compound.
    scale : float, optional, default 1.0
        Value by which to scale the length values

    Returns
    -------
    comp : Compound

    Note
    ----
    GSD and HOOMD snapshots center their boxes on the origin (0,0,0), so the
    compound is shifted by half the box lengths
    """
    comp = Compound()
    bond_array = snapshot.bonds.group
    n_atoms = snapshot.particles.N

    if "SnapshotSystemData_float" in dir(hoomd._hoomd) and isinstance(
        snapshot, hoomd._hoomd.SnapshotSystemData_float
    ):
        # hoomd v2
        box = snapshot.box
        comp.box = Box.from_lengths_tilt_factors(
            lengths=np.array([box.Lx, box.Ly, box.Lz]) * scale,
            tilt_factors=np.array([box.xy, box.xz, box.yz]),
        )
    else:
        # gsd / hoomd v3
        box = snapshot.configuration.box
        comp.box = Box.from_lengths_tilt_factors(
            lengths=box[:3] * scale, tilt_factors=box[3:]
        )

    # GSD and HOOMD snapshots center their boxes on the origin (0,0,0)
    shift = np.array(comp.box.lengths) / 2
    # Add particles
    for i in range(n_atoms):
        name = snapshot.particles.types[snapshot.particles.typeid[i]]
        xyz = snapshot.particles.position[i] * scale + shift
        charge = snapshot.particles.charge[i]

        atom = Particle(name=name, pos=xyz, charge=charge)
        comp.add(atom, label=str(i))

    # Add bonds
    particle_dict = {idx: p for idx, p in enumerate(comp.particles())}
    for i in range(bond_array.shape[0]):
        atom1 = int(bond_array[i][0])
        atom2 = int(bond_array[i][1])
        comp.add_bond([particle_dict[atom1], particle_dict[atom2]])
    return comp
def reverse_map_molecule(molecule, target, mapping_moieties):
    print('unique')
    cg_molecule = clone(molecule)  # CG molecule
    aa_template = target[molecule.name]  # full aa Compound for molecule
    aa_moieties = mapping_moieties[
        molecule.name]  # list of lists of indices for each bead
    aa_molecule = Compound()  # this will have the final aa molecule
    cg_to_aa = []  # list of tuples containing (real index, aa atom)

    # now cycle through beads
    for index, bead in enumerate(cg_molecule.particles()):
        aa_atoms = Compound()  # placeholder for molecule atoms
        [
            aa_atoms.add(clone(aa_template.children[i]))
            for i in aa_moieties[index]
        ]
        aa_atoms.translate_to(bead.pos)  # shift to cg_bead position
        cg_to_aa += list(zip(aa_moieties[index], aa_atoms.children))

    # sort atoms in cg_to_aa and add them to the aa_molecule
    cg_to_aa = sorted(cg_to_aa)
    for atom in cg_to_aa:
        aa_molecule.add(clone(atom[1]))

    # add bonds from the template
    aa_template = aa_template.to_trajectory()
    for i, j in aa_template.top.bonds:
        aa_molecule.add_bond([aa_molecule[i.index], aa_molecule[j.index]])

    # equilibrate molecule and shift back to center
    # if the atom names match OpenBabel forcefield naming convention:
    try:
        aa_molecule.energy_minimization(steps=2500)

    # otherwise rename with just element names:
    except:
        atomnames = [i.name for i in aa_molecule]  # get the atomnames
        for atom in aa_molecule:  # make the atomnames elements
            atom.name = atom.name[0]

        aa_molecule.energy_minimization(steps=2500)

        for i, atom in enumerate(atomnames):
            aa_molecule[i].name = atomnames[i]

    #aa_molecule.translate(center)
    aa_molecule.name = molecule.name
    return aa_molecule