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 _clone(self, clone_of=None, root_container=None): """A faster alternative to deepcopying. Does not resolve circular dependencies. This should be safe provided you never try to add the top of a Compound hierarchy to a sub-Compound. Clones compound hierarchy only, not the bonds. """ if root_container is None: root_container = self if clone_of is None: clone_of = dict() # If this compound has already been cloned, return that. if self in clone_of: return clone_of[self] # Otherwise we make a new clone. cls = self.__class__ newone = cls.__new__(cls) # Remember that we're cloning the new one of self. clone_of[self] = newone newone.name = deepcopy(self.name) newone.wrapped = clone(self.wrapped) if hasattr(self, 'index'): newone.index = deepcopy(self.index) if self.children is None: newone.children = None else: newone.children = OrderedSet() # Parent should be None initially. newone.parent = None newone.labels = OrderedDict() newone.referrers = set() newone.bond_graph = None # Add children to clone. if self.children: for child in self.children: newchild = child._clone(clone_of, root_container) newone.children.add(newchild) newchild.parent = newone # Copy labels, except bonds with atoms outside the hierarchy. if self.labels: for label, compound in self.labels.items(): if not isinstance(compound, list): newone.labels[label] = compound._clone( clone_of, root_container) compound.referrers.add(clone_of[compound]) else: # compound is a list of compounds, so we create an empty # list, and add the clones of the original list elements. newone.labels[label] = [] for subpart in compound: newone.labels[label].append( subpart._clone(clone_of, root_container)) # Referrers must have been handled already, or the will # be handled return newone
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