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
def reverse_map_solvent(cg_molecule,
                        target,
                        sol_per_bead=4,
                        cutoff=2,
                        scaling_factor=5):
    """
    molecules: list of water beads
    target: single atomistic solvent molecule
    sol_per_bead: number of atomistic solvent molecules per CG bead
    cutoff: max distance an atomistic molecule can be placed from the
        center of the CG bead
    """

    solvent = Compound()  # will contain all the solvent molecules in a bead
    solvent_molecule = Compound()  # placeholder for each single molecule

    # for each atomistic molcule
    print("unique")
    for i in range(sol_per_bead):
        # get a random vector by which to shift the atomistic molecule
        """
        randx = cutoff * (1 - 2 * np.random.rand())
        randy = np.sqrt(cutoff**2 - randx**2) * (1 - 2 * np.random.rand()) # randy bobandy
        randz = np.sqrt(cutoff**2 - randx**2 - randy**2) * (1 - 2 * np.random.rand())
        """
        randx = 0.0
        randy = 0.0
        randz = 0.0
        if i == 0:
            randx += 1.0
        elif i == 1:
            randx -= 1.0
        elif i == 2:
            randy += 1.0
        elif i == 3:
            randy -= 1.0

        shift_vec = np.array([randx, randy, randz])
        shift_vec *= 0.2
        #np.random.shuffle(shift_vec)

        # get random angles to spin the solvent molecule by
        theta = 2 * np.pi * np.random.rand()
        phi = np.pi * np.random.rand()

        # make a solvent molecule compound and shift it to the correct position
        solvent_molecule = clone(target)
        solvent_molecule.translate_to(cg_molecule.pos + shift_vec)
        solvent_molecule.spin(theta, [0, 0, 1])
        solvent_molecule.spin(phi, [1, 0, 0])

        # add the molecule to the bead compound
        solvent.add(solvent_molecule)

    # time to minimize the energy!
    # try with current atom names
    """
    try:
        solvent.energy_minimization(steps=500)

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

        solvent.energy_minimization(steps=500)

        for i, atom in enumerate(atomnames):
            solvent[i].name = atomnames[i]
    """
    # scale the solvent by 5

    # get a list of individual molecules (so that it separates them into residues)
    solvent = [clone(child) for child in solvent.children]

    for i, solvent_compound in enumerate(solvent):
        solvent[i].name = cg_molecule.name
        solvent[i].translate_to(np.array(solvent[i].pos) * scaling_factor)
    return solvent