def _apply(self, molecules: List[Molecule]) -> ComponentResult: """ Fragment the molecules using the WBOFragmenter. Parameters: molecules: The list of molecules which should be processed by this component. Note: * If the input molecule fails fragmentation it will be fail this component and be removed even when `include_parent` is set to true. * When a molecule can not be fragmented to meet the wbo threshold the parent is likely to be included in the dataset. * """ from fragmenter import fragment result = self._create_result() for molecule in molecules: # not having a conformer can cause issues if molecule.n_conformers == 0: molecule.generate_conformers(n_conformers=1) if self.include_parent: result.add_molecule(molecule) fragment_factory = fragment.WBOFragmenter( molecule=molecule.to_openeye(), functional_groups=self.functional_groups, verbose=False, ) try: fragment_factory.fragment( threshold=self.threshold, keep_non_rotor_ring_substituents=self. keep_non_rotor_ring_substituents, ) # we need to store the central bond which was fragmented around # to make sure this is the bond we torsiondrive around fragmets_dict = fragment_factory.to_torsiondrive_json() # check we have fragments if fragmets_dict: for fragment_data in fragmets_dict.values(): frag_mol = Molecule.from_mapped_smiles( mapped_smiles=fragment_data["identifiers"] ["canonical_isomeric_explicit_hydrogen_mapped_smiles"] ) torsion_index = tuple(fragment_data["dihedral"][0]) # this is stored back into the molecule and will be used when generating the cmiles tags latter torsion_tag = TorsionIndexer() torsion_tag.add_torsion(torsion=torsion_index) frag_mol.properties["dihedrals"] = torsion_tag result.add_molecule(frag_mol) # if we have no fragments and we dont want the parent then we failed to fragment elif not fragmets_dict and not self.include_parent: result.filter_molecule(molecule) except (RuntimeError, ValueError): # this will catch cmiles errors for molecules with undefined stero result.filter_molecule(molecule) return result
def fragment(self, molecule: Molecule) -> List[FragmentData]: """ Fragment the molecule using the WBOFragmenter. Parameters: molecule: The openff molecule to be fragmented using the provided class settings Returns: A list of FragmentData schema which details how a parent molecule is related to a fragment and which bond we fragmented around. Raises: FragmenterError: If the molecule can not be fragmented. """ from fragmenter import fragment # make sure the molecule has at least one conformer as this can cause issues if molecule.n_conformers == 0: molecule.generate_conformers(n_conformers=1) # set up the fragmenter fragment_factory = fragment.WBOFragmenter( molecule=molecule.to_openeye(), verbose=False) fragments: List[FragmentData] = [] try: # fragment the molecule fragment_factory.fragment( threshold=self.wbo_threshold, keep_non_rotor_ring_substituents=self. keep_non_rotor_ring_substituents, ) # now we work out the relation between the fragment and the parent fragments_data = fragment_factory.to_torsiondrive_json() # now store the data for data in fragments_data.values(): off_frag = Molecule.from_mapped_smiles( data["identifiers"] ["canonical_isomeric_explicit_hydrogen_mapped_smiles"]) # get the fragment parent mapping frag_dihedral = data["dihedral"][0][1:3] # in some cases we get one fragment back which is the parent molecule # we should not work out a mapping if not molecule.is_isomorphic_with(off_frag): mapping = self._get_fragment_parent_mapping( fragment=off_frag, parent=molecule) # get the parent torsion parent_dihedral = tuple( [mapping[i] for i in frag_dihedral]) parent_molecule = molecule else: # reuse the current fragment data as dummy parent data mapping = dict((i, i) for i in range(molecule.n_atoms)) parent_dihedral = frag_dihedral parent_molecule = off_frag # this is the data we need so make the fragmnetdata frag_data = FragmentData( parent_molecule=parent_molecule, parent_torsion=parent_dihedral, fragment_molecule=off_frag, fragment_torsion=frag_dihedral, fragment_attributes=data["identifiers"], fragment_parent_mapping=mapping, ) fragments.append(frag_data) return fragments except RuntimeError: raise FragmenterError( f"The molecule {molecule} could not be fragmented so no fitting target was made." )
for ki in key_list: print(ki) try: os.mkdir(ki) except FileExistsError: print('{} directory already exists. Files will be overwritten'.format( ki)) mapped_smiles = kinase_inhibitors[ki][ 'canonical_isomeric_explicit_hydrogen_mapped_smiles'] chemi.mol_to_image_atoms_label(mapped_smiles, map_idx=True, fname='{}/{}_mapped.png'.format(ki, ki)) mol = oechem.OEMol() oechem.OESmilesToMol(mol, mapped_smiles) fragmenter = fragment.WBOFragmenter(mol) fragmenter.fragment(threshold=1.0, strict_stereo=False, strict_types=False, keep_non_rotor_ring_substituents=False ) # Try without keeping nonrotors on ring atoms_bonds = get_atoms_bonds_from_fragment(fragmenter.fragments) fragments_to_drive = {} with PdfPages('{}/{}_fragment_growth_2.pdf'.format(ki, ki)) as pdf: for target_bond in fragmenter.fragments: key = workflow_api.serialize_key(target_bond) fragments_to_drive[key] = {'path_length': [], 'wbo': []} atoms = copy.deepcopy(atoms_bonds[target_bond][0]) bonds = copy.deepcopy(atoms_bonds[target_bond][1]) pl_wbos, pl_fragments = get_wbo_growth( fragmenter, fragmenter.fragments[target_bond], atoms, bonds,
from fragmenter import fragment, chemi import json """ This is an example script to generate fragments from a molecule Note: The current fragmentation scheme is not optimal yet so it can be slow for larger molecules. """ # Create an oemol from a SMILES oemol = chemi.smiles_to_oemol( 'OC1(CN(C1)C(=O)C1=C(NC2=C(F)C=C(I)C=C2)C(F)=C(F)C=C1)[C@@H]1CCCCN1', name='Cobimetinib') # Instantiate a fragmenter engine frag_engine = fragment.WBOFragmenter(oemol) # Use default options to fragment molecule. frag_engine.fragment() # Generate PDF with fragments frag_engine.depict_fragments(fname='example_fragments.pdf') # Generate input for torsiondrive jobs. These jobs will drive the central rotatable bond in the fragment td_inputs = frag_engine.to_torsiondrive_json(max_confs=10) with open('example_td_inputs.json', 'w') as f: json.dump(td_inputs, f, indent=2, sort_keys=True) # If you want to only generate starting conformations for other calculations, use `to_qcschema_mols` qcschema_mols = frag_engine.to_qcschema_mols(max_confs=10) with open('example_qcschema_mols.json', 'w') as f: json.dump(qcschema_mols, f, indent=2, sort_keys=True)