예제 #1
0
    def join_neighboring_mols(self, mol_A: Chem.Mol, mol_B: Chem.Mol):
        """
        Joins two molecules by first calling _find_closest to find closest.
        That method does all the thinking.
        then by calling _join_atoms.

        :param mol_A:
        :param mol_B:
        :return:
        """
        # get closets atoms
        combo, candidates = self._find_all_closest(
            mol_A, mol_B)  # _find_all_closest is in communal
        anchor_A, anchor_B, distance = candidates[0]
        mol = self._join_atoms(combo,
                               anchor_A,
                               anchor_B,
                               distance,
                               linking=True)
        for anchor_A, anchor_B, distance in candidates[1:]:
            mol = self._join_atoms(combo,
                                   anchor_A,
                                   anchor_B,
                                   distance,
                                   linking=False)
        mol.SetProp('_Name',
                    mol_A.GetProp('_Name') + '~' + mol_B.GetProp('_Name'))
        return mol
예제 #2
0
    def merge_pair(self,
                   scaffold: Chem.Mol,
                   fragmentanda: Chem.Mol,
                   mapping: Optional = None) -> Chem.Mol:
        """
        To specify attachments use ``.merge``.
        To understand what is going on see ``.categorise``

        :param scaffold: mol to be added to.
        :param fragmentanda: mol to be fragmented
        :param mapping: see ``get_positional_mapping``. Optional in _pre_fragment_pairs
        :return:
        """
        done_already = []
        if self._debug_draw:
            print('Scaffold')
            self.draw_nicely(scaffold)
            print('To be added')
            self.draw_nicely(fragmentanda)
        fp = self._pre_fragment_pairs(scaffold, fragmentanda, mapping)
        # confusingly these are hit indexed.
        for anchor_index, attachment_details in fp.items():
            # anchor index is the fragment-to-added's internal atom that attaches
            if anchor_index in done_already:
                continue
            # fix rings.
            uniques = {
                atom.GetIdx()
                for atom in fragmentanda.GetAtoms()
                if 'overlapping' not in atom.GetProp('_Category')
            }
            team = self._recruit_team(fragmentanda, anchor_index, uniques)
            other_attachments = list((team & set(fp.keys())) - {anchor_index})
            other_attachment_details = []
            for other in other_attachments:
                other_attachment_details.append(fp[other])
                done_already.append(other)
            scaffold = self._merge_part(
                scaffold,
                fragmentanda,
                anchor_index=anchor_index,
                attachment_details=attachment_details,
                other_attachments=other_attachments,
                other_attachment_details=other_attachment_details)
        name_A = scaffold.GetProp('_Name')
        name_B = fragmentanda.GetProp('_Name')
        scaffold.SetProp('_Name', f'{name_A}-{name_B}')
        if self._debug_draw:
            print('Merged', scaffold.GetProp('_Name'))
            self.draw_nicely(scaffold)
        return scaffold
예제 #3
0
    def from_mol(cls, mol: Chem.Mol):
        field_names = fields(cls)

        kwargs = {}
        for field in field_names:
            field_name = cls._convert_field_to_sdf_field(field.name)
            val = mol.GetProp(field_name)
            val = field.type(val)
            kwargs[field.name] = val
        return RABFEResult(**kwargs)
예제 #4
0
    def origin_from_mol(self, mol: Chem.Mol = None):
        """
        these values are stored from Monster for scaffold, chimera and positioned_mol

        :param mol: Chem.Mol
        :return: stdev list for each atom
        """
        if mol is None:
            mol = self.positioned_mol
        if mol.HasProp('_Origins'):
            return json.loads(mol.GetProp('_Origins'))
        origin = []
        for atom in mol.GetAtoms():
            if atom.HasProp('_Origin'):
                x = atom.GetProp('_Origin')
                if x == 'none':
                    origin.append([])
                else:
                    origin.append(json.loads(x))
            else:
                origin.append([])
        return origin
예제 #5
0
 def template_sorter(t: Chem.Mol) -> int:
     n_atoms = max([
         len([k for k in m if k not in accounted_for])
         for m in self.maps[t.GetProp('_Name')]
     ])
     return n_atoms
예제 #6
0
    def simulate_pair(epoch: int, blocker: Chem.Mol, mol: Chem.Mol):
        verify_rabfe_pair(mol, blocker)
        mol_name = mol.GetProp("_Name")

        # generate the core_idxs
        core_idxs = setup_relative_restraints_by_distance(mol, blocker)
        mol_coords = get_romol_conf(mol)  # original coords

        num_complex_atoms = complex_coords.shape[0]
        num_solvent_atoms = solvent_coords.shape[0]

        # Use core_idxs to generate
        R, t = rmsd.get_optimal_rotation_and_translation(
            x1=complex_ref_x0[num_complex_atoms:][
                core_idxs[:, 1]],  # reference core atoms
            x2=mol_coords[core_idxs[:, 0]],  # mol core atoms
        )

        aligned_mol_coords = rmsd.apply_rotation_and_translation(
            mol_coords, R, t)

        ref_coords = complex_ref_x0[num_complex_atoms:]
        complex_host_coords = complex_ref_x0[:num_complex_atoms]
        complex_box0 = complex_ref_box0

        solvent_host_coords = solvent_ref_x0[:num_solvent_atoms]
        solvent_box0 = solvent_ref_box0

        # compute the free energy of swapping an interacting mol with a non-interacting reference mol
        complex_decouple_x0 = minimizer.minimize_host_4d(
            [mol, blocker_mol],
            complex_system,
            complex_host_coords,
            forcefield,
            complex_box0,
            [aligned_mol_coords, ref_coords],
        )
        complex_decouple_x0 = np.concatenate(
            [complex_decouple_x0, aligned_mol_coords, ref_coords])

        # compute the free energy of conversion in complex
        complex_conversion_x0 = minimizer.minimize_host_4d(
            [mol],
            complex_system,
            complex_host_coords,
            forcefield,
            complex_box0,
            [aligned_mol_coords],
        )
        complex_conversion_x0 = np.concatenate(
            [complex_conversion_x0, aligned_mol_coords])

        min_solvent_coords = minimizer.minimize_host_4d([mol], solvent_system,
                                                        solvent_host_coords,
                                                        forcefield,
                                                        solvent_box0)
        solvent_x0 = np.concatenate([min_solvent_coords, mol_coords])

        suffix = f"{mol_name}_{epoch}"

        seed = np.random.randint(np.iinfo(np.int32).max)

        # Order of these simulations should match the order in which predictions are computed to ensure
        # efficient use of parallelism.
        return {
            "solvent_conversion":
            binding_model_solvent_conversion.simulate_futures(
                ordered_params,
                mol,
                solvent_x0,
                solvent_box0,
                prefix="solvent_conversion_" + suffix,
                seed=seed,
            ),
            "solvent_decouple":
            binding_model_solvent_decouple.simulate_futures(
                ordered_params,
                mol,
                solvent_x0,
                solvent_box0,
                prefix="solvent_decouple_" + suffix,
                seed=seed,
            ),
            "complex_conversion":
            binding_model_complex_conversion.simulate_futures(
                ordered_params,
                mol,
                complex_conversion_x0,
                complex_box0,
                prefix="complex_conversion_" + suffix,
                seed=seed,
            ),
            "complex_decouple":
            binding_model_complex_decouple.simulate_futures(
                ordered_params,
                mol,
                blocker_mol,
                core_idxs,
                complex_decouple_x0,
                complex_box0,
                prefix="complex_decouple_" + suffix,
                seed=seed,
            ),
            "mol":
            mol,
            "blocker":
            blocker,
            "epoch":
            epoch,
            "seed":
            seed,
        }