def _create_product(self): # copy of template that turns into product template = Chem.RWMol(self.reacting_mol) # reset atom map number on the INSTANCE VARIABLE template for atom in self.reacting_mol.GetAtoms(): if atom.GetAtomMapNum() == self.ALDEHYDE_O_MAP_NUM: atom.SetAtomMapNum(0) break # remove oxygen from unmasked aldehyde on LOCAL VARIABLE template for atom in list(template.GetAtoms()): if atom.GetAtomMapNum() == self.ALDEHYDE_O_MAP_NUM: template.RemoveAtom(atom.GetIdx()) elif atom.GetAtomMapNum() == self.ALDEHYDE_C_MAP_NUM: atom.SetNumExplicitHs(atom.GetTotalNumHs() + 2) # create bond between the peptide nitrogen atom and the aldehyde carbon map_nums = (self.NITROGEN_MAP_NUM, self.ALDEHYDE_C_MAP_NUM) template = utils.connect_mols(template, map_nums=map_nums, clear_map_nums=False) # create bond between reacting atom and the aldehyde carbon map_nums = (self.ALDEHYDE_C_MAP_NUM, self.EAS_MAP_NUM) self.products.append( utils.connect_mols(template, map_nums=map_nums, stereo=self.STEREOCHEMISTRY, clear_map_nums=False))
def _create_reactants(self): self._process_nucleophile() map_nums = (self.TEMPLATE_OLIGOMERIZATION_MAP_NUM, self.BACKBONE_NITROGEN_MAP_NUM) if isinstance(self.model, models.Sidechain): monomer = self._create_monomer() self.reactants = [ utils.connect_mols(monomer, self.template, map_nums=map_nums, clear_map_nums=False) ] else: # remove wildcard atom attached to n-terminus added in call to tag_monomer_connection_atom() wildcard_atom = utils.get_atom_with_map_num( self.reacting_atom, self.N_TERM_WILDCARD_MAP_NUM) self.reacting_mol = Chem.RWMol(self.reacting_mol) self.reacting_mol.RemoveAtom(wildcard_atom.GetIdx()) # connect template to monomer self.reactants = [ utils.connect_mols(self.reacting_mol, self.template, map_nums=map_nums, clear_map_nums=False) ]
def _create_product(self): reactant = Chem.RWMol( self.reactants[0] ) # copy of reactant molecule that will be transformed into product # reset atom map number on the INSTANCE VARIABLE reactant for atom in self.reactants[0].GetAtoms(): if atom.GetAtomMapNum() == self.TEMPLATE_ALDEHYDE_O_MAP_NUM: atom.SetAtomMapNum(0) break # remove oxygen from unmasked aldehyde on LOCAL VARIABLE reactant for atom in list(reactant.GetAtoms()): if atom.GetAtomMapNum() == self.TEMPLATE_ALDEHYDE_O_MAP_NUM: reactant.RemoveAtom(atom.GetIdx()) break # create bond between sidechain EAS carbon and unmasked aldehyde carbon map_nums = (self.NUCLEOPHILE_EAS_MAP_NUM, self.TEMPLATE_ALDEHYDE_C_MAP_NUM) reactant = utils.connect_mols(reactant, map_nums=map_nums, clear_map_nums=False) # create bond between peptide nitrogen and unmasked aldehyde carbon map_nums = (self.BACKBONE_NITROGEN_MAP_NUM, self.TEMPLATE_ALDEHYDE_C_MAP_NUM) self.products = [ utils.connect_mols(reactant, map_nums=map_nums, clear_map_nums=False) ]
def _create_product(self): # create local copy of reactant to transform into product reactant = Chem.RWMol(self.reactant) # reset atom map number on aldehyde oxygen on INSTANCE VARIABLE reactant for atom in self.reactant.GetAtoms(): if atom.GetAtomMapNum() == self.ALDEHYDE_O_MAP_NUM: atom.SetAtomMapNum(0) # remove pictet spangler aldehyde oxygen and set the pictet spangler aldehyde carbon's single bond with its # neighboring carbon to a double bond in LOCAL copy of reactant for atom in list(reactant.GetAtoms()): if atom.GetAtomMapNum() == self.ALDEHYDE_O_MAP_NUM: reactant.RemoveAtom(atom.GetIdx()) elif atom.GetAtomMapNum() == self.ALDEHYDE_C_MAP_NUM: carb_atom = atom for bond in atom.GetBonds(): if bond.GetBondType() == Chem.BondType.SINGLE: bond.SetBondType(Chem.BondType.DOUBLE) # adjust hydrogens carb_atom.SetNumExplicitHs(carb_atom.GetTotalNumHs() + 1) # connect backbone nitrogen to aldehyde carbon map_nums = (self.BACKBONE_NITROGEN_MAP_NUM, self.ALDEHYDE_C_MAP_NUM) self.products.append( utils.connect_mols(reactant, map_nums=map_nums, clear_map_nums=False))
def add_monomer(self, monomer, backbone): self.peptide = utils.remove_atom(self.peptide, self.carboxyl_atom) self.peptide = utils.connect_mols(self.peptide, monomer, map_nums=self.MAP_NUMS) self.pep_size += 1 self.backbone_prev = backbone
def _create_reactants(self): monomer = self._create_monomer() # attach a methyl to n-terminus so reaction matches indole at any position in peptide chain extra_atom = Chem.MolFromSmarts( f'[CH4:{self.N_TERM_WILDCARD_MAP_NUM}]') map_nums = (self.BACKBONE_NITROGEN_MAP_NUM, self.N_TERM_WILDCARD_MAP_NUM) self.monomer = utils.connect_mols(monomer, extra_atom, map_nums=map_nums, clear_map_nums=False) for atom in self.monomer.GetAtoms(): if atom.GetAtomMapNum( ) == self.N_TERM_WILDCARD_MAP_NUM: # change methyl to wildcard utils.atom_to_wildcard(atom) elif atom.GetAtomMapNum( ) == self.NUCLEOPHILE_EAS_MAP_NUM: # tag carbon adjacent to reacting atom for neighbor in atom.GetNeighbors(): if neighbor.GetTotalNumHs( ) == 1 and neighbor.GetIsAromatic(): neighbor.SetAtomMapNum(self.ADJ_CARBON_MAP_NUM) self.reactants = [self.monomer, self.template]
def test_connect_mols_fail_wrong_number_mols(mols, map_nums): mols = list(map(Chem.MolFromSmiles, mols)) with pytest.raises(utils.MergeError) as error: _ = utils.connect_mols(*mols, map_nums=map_nums) assert str(error.value) == 'Can only merge 1 or 2 molecules at a time.'
def generate(self, peptide, templates): """ Method that takes a peptide molecule and combines it with each type of template molecule to form template-peptide oligomers. """ template_peptides = [] for template in templates: peptide_mol = peptide.mol for atom_idx in chain.from_iterable( peptide_mol.GetSubstructMatches(self.ELIGIBLE_NITROGENS)): atom = peptide_mol.GetAtomWithIdx(atom_idx) atom.SetAtomMapNum(self.PEPTIDE_NITROGEN_MAP_NUM) template_peptide = utils.connect_mols( template.oligomerization_mol, peptide_mol, map_nums=self.MAP_NUMS) atom.SetAtomMapNum(0) template_peptides.append( models.TemplatePeptide.from_mol(template_peptide, template, peptide)) return template_peptides
def _create_monomer(self): """ Method for creating a monomer from a sidechain with the c-terminus changed to a wildcard. This is useful for reactions that need information about the positioning of monomer within the peptide chain in order to determine whether the reaction is valid or not. Returns: RDKit Mol: The monomer. """ # get modified backbone replacement = Chem.MolFromSmarts(f'[*:{self.C_TERM_WILDCARD_MAP_NUM}]') backbone = AllChem.ReplaceSubstructs(models.TAGGED_ALPHA_BACKBONE, models.CARBOXYL, replacement)[0] Chem.SanitizeMol(backbone) # tag n-terminus nitrogen for oligomerization for atom_idx in chain.from_iterable( backbone.GetSubstructMatches(models.N_TERM)): atom = backbone.GetAtomWithIdx(atom_idx) if atom.GetSymbol() == 'N': atom.SetAtomMapNum(self.BACKBONE_NITROGEN_MAP_NUM) break # create monomer map_nums = ( self.BACKBONE_OLIGOMERIZATION_MAP_NUM, # pylint: disable=maybe-no-member self.SIDECHAIN_OLIGOMERIZATION_MAP_NUM) # pylint: disable=maybe-no-member return utils.connect_mols(self.reacting_mol, backbone, map_nums=map_nums)
def test_connect_mols_fail_wrong_number_of_map_numbers(mols, map_nums): mols = list(map(Chem.MolFromSmiles, mols)) with pytest.raises(utils.MergeError) as error: _ = utils.connect_mols(*mols, map_nums=map_nums) assert str(error.value ) == 'Can only specify 2 distinct map numbers at a time.'
def test_connect_mols_fail_wrong_map_numbers(mols, map_nums): mols = list(map(Chem.MolFromSmiles, mols)) with pytest.raises(utils.MergeError) as error: _ = utils.connect_mols(*mols, map_nums=map_nums) assert str( error.value ) == 'Could not find 2 atoms with the given map numbers. Check for duplicate map numbers \
def test_connect_mols(mols, map_nums, stereo, clear_map_nums, expected_smiles): mols = list(map(Chem.MolFromSmiles, mols)) new_mol = utils.connect_mols(*mols, map_nums=map_nums, stereo=stereo, clear_map_nums=clear_map_nums) assert Chem.MolToSmiles(new_mol) == expected_smiles
def _create_product(self): # copy of monomer that will be changed into product monomer = deepcopy(self.monomer) for atom in monomer.GetAtoms(): if atom.GetAtomMapNum() == self.NUCLEOPHILE_EAS_MAP_NUM: eas_atom = atom elif atom.GetAtomMapNum() == self.ADJ_CARBON_MAP_NUM: adj_atom = atom # bond between eas_atom (i.e. the reacting atom) and adj_atom becomes single bond bond = monomer.GetBondBetweenAtoms(eas_atom.GetIdx(), adj_atom.GetIdx()) bond.SetBondType(Chem.BondType.SINGLE) eas_atom.SetNumExplicitHs(eas_atom.GetTotalNumHs() + 1) adj_atom.SetNumExplicitHs(adj_atom.GetTotalNumHs() + 1) for stereo1, stereo2 in self.STEREOCHEMISTRIES: # merge backbone nitrogen to adjacent carbon map_nums = (self.BACKBONE_NITROGEN_MAP_NUM, self.ADJ_CARBON_MAP_NUM) reactant = utils.connect_mols(monomer, map_nums=map_nums, clear_map_nums=False, stereo=stereo1) # merge template with monomer map_nums = (self.TEMPLATE_EAS_MAP_NUM, self.NUCLEOPHILE_EAS_MAP_NUM) self.products.append( utils.connect_mols(reactant, self.template, map_nums=map_nums, clear_map_nums=False, stereo=stereo2))
def methlyate_wrapper(*args, **kwargs): data = [] for original_mol in original_func(*args, **kwargs): data.append(original_mol) # find all combinations of candidate methylation sites matches = original_mol.mol.GetSubstructMatches( candidate_heteroatoms) for atom_idx in chain.from_iterable(matches): mol = original_mol.mol mol.GetAtomWithIdx(atom_idx).SetAtomMapNum(HETERO_ATOM_MAP_NUM) mol = utils.connect_mols(mol, methyl, map_nums=map_nums) new_mol = type(original_mol).add_modification( original_mol, mol, 'm') data.append(new_mol) return data
def generate(self, sidechain, backbones): """ Method that takes a sidechain and backbones creates new monomers. """ sidechain_mol = sidechain.mapped_mol utils.clear_isotopes(sidechain_mol) monomers = [] for backbone in backbones: monomer = utils.connect_mols(sidechain_mol, backbone.mol, map_nums=self.MAP_NUMS) monomers.append( models.Monomer.from_mol(monomer, backbone, sidechain)) return monomers
def _create_reactant(self): replacement = Chem.MolFromSmarts( f'[*:{self.BACKBONE_CARBOXYL_MAP_NUM}]') backbone = AllChem.ReplaceSubstructs(models.TAGGED_ALPHA_BACKBONE, self.CARBOXYL_W_EXTRA_C, replacement)[0] # tag n-terminus nitrogen for oligomerization and clear backbone carbon oligomerzation map num for atom in backbone.GetAtoms(): if atom.GetSymbol() == 'N': atom.SetAtomMapNum(self.BACKBONE_NITROGEN_MAP_NUM) elif atom.GetAtomMapNum() == self.BACKBONE_OLIGOMERIZATION_MAP_NUM: atom.SetAtomMapNum(0) map_nums = (self.TEMPLATE_OLIGOMERIZATION_MAP_NUM, self.BACKBONE_NITROGEN_MAP_NUM) self.reactant = utils.connect_mols(self.reacting_mol, backbone, map_nums=map_nums, clear_map_nums=False)
def _create_product(self): self.products = [ utils.connect_mols(*self.reactants, map_nums=self.MAP_NUMS, clear_map_nums=False) ]