Source code for glypy.composition.composition_transform


from ..utils import make_counter
from ..structure.base import SaccharideCollection, SaccharideBase, SubstituentBase
from ..structure import Substituent
from ..structure import Monosaccharide
from ..structure import Modification
from .composition import Composition
from six import string_types as basestring


[docs]def derivatize(saccharide, substituent): r''' For each monosaccharide and viable substituent, attach the specified substituent. .. warning:: This function mutates the input `saccharide` object, because copying objects is expensive. If you want to continue using the underivatized object, create a copy of it using the object's `clone` method. When called on an instance of :class:`SaccharideCollection`, such as |Glycan| or :class:`GlycanComposition`, that type's `_derivatized` method will be called for any special book-keeping that must be done. This is a NoOp for |Glycan| See Also -------- :func:`strip_derivitization` ''' if isinstance(substituent, basestring): substituent = Substituent(substituent) id_base = make_counter(-substituent.id * 32) if isinstance(saccharide, SaccharideCollection): for node in saccharide: if node.node_type is SaccharideBase.node_type: _strip_derivatization_monosaccharide(node) _derivatize_monosaccharide(node, substituent, id_base) elif node.node_type is SubstituentBase.node_type: _strip_derivatization_substituent(node) _derivatize_substituent(node, substituent, id_base) saccharide._derivatized(substituent, id_base) elif isinstance(saccharide, SaccharideBase): _derivatize_monosaccharide(saccharide, substituent, id_base) return saccharide
def _derivatize_monosaccharide(monosaccharide_obj, substituent, id_base=None): ''' The internal worker for :func:`derivatize`. It should not be called directly. Adds a copy of `substituent` to every open position on `monosaccharide_obj` and its substituents and reducing end Parameters ---------- monosaccharide_obj: Monosaccharide substituent: Substituent id_base: function or None Returns ------- monosaccharide_obj ''' if id_base is None: id_base = make_counter(-substituent.id * 32) attachment_composition_loss = substituent.attachment_composition_loss() open_sites, unknowns = monosaccharide_obj.open_attachment_sites() for site in open_sites[unknowns:]: s = substituent.clone() s.id = id_base() s._derivatize = True monosaccharide_obj.add_substituent( s, parent_loss=attachment_composition_loss, position=site, child_loss=Composition(H=1), child_position=1) for p, subst in monosaccharide_obj.substituents(): _derivatize_substituent(subst, substituent, id_base) red_end = monosaccharide_obj.reducing_end if red_end is not None: _derivatize_reducing_end(red_end, substituent, id_base) for pos, mod in monosaccharide_obj.modifications.items(): if mod == Modification.a: s = substituent.clone() s._derivatize = True s.id = id_base() monosaccharide_obj.add_substituent( s, position=pos, parent_loss=attachment_composition_loss, max_occupancy=3, child_loss=Composition(H=1), child_position=1) def _derivatize_substituent(subst, deriv, id_base): if subst.is_nh_derivatizable and deriv.can_nh_derivatize: s = deriv.clone() s._derivatize = True s.id = id_base() subst.add_substituent(s, position=2, child_position=1) def _derivatize_reducing_end(reducing_end, substituent, id_base=None): attachment_composition_loss = substituent.attachment_composition_loss() for i in range(1, reducing_end.valence + 1): s = substituent.clone() s._derivatize = True s.id = id_base() reducing_end.add_substituent( s, parent_loss=attachment_composition_loss, max_occupancy=3, position=i, child_loss=Composition(H=1), child_position=1)
[docs]def strip_derivatization(saccharide): ''' For each monosaccharide and viable substituent, remove all substituents added by :func:`derivatize`. .. warning:: This function, like :func:`derivatize`, will mutate the input `saccharide`. When called on an instance of :class:`SaccharideCollection`, such as |Glycan| or :class:`GlycanComposition`, that type's `_strip_derivatization` method will be called for any special book-keeping that must be done. This is a NoOp for |Glycan| See Also -------- :func:`.derivatize` ''' if isinstance(saccharide, SaccharideCollection): for node in saccharide: if node.node_type is SaccharideBase.node_type: _strip_derivatization_monosaccharide(node) elif node.node_type is SubstituentBase.node_type: _strip_derivatization_substituent(node) saccharide._strip_derivatization() else: _strip_derivatization_monosaccharide(saccharide) return saccharide
def _strip_derivatization_monosaccharide(monosaccharide_obj): for pos, subst_link in list(monosaccharide_obj.substituent_links.items()): if subst_link.child._derivatize: monosaccharide_obj.drop_substituent(pos, subst_link.child) else: sub_node = subst_link.child _strip_derivatization_substituent(sub_node) red_end = monosaccharide_obj.reducing_end if red_end is not None: _strip_derivatization_reducing_end(red_end) def _strip_derivatization_substituent(sub_node): for sub_pos, subst_link in list(sub_node.links.items()): try: if subst_link.child._derivatize: sub_node.drop_substituent(sub_pos, subst_link.child) except AttributeError: if subst_link.child.node_type is Monosaccharide.node_type: _strip_derivatization_monosaccharide(subst_link.child) def _strip_derivatization_reducing_end(reducing_end): for pos, subst_link in list(reducing_end.links.items()): if subst_link.child._derivatize: reducing_end.drop_substituent(pos, subst_link.child) def has_derivatization(residue): if residue.node_type is Monosaccharide.node_type: for link in residue.substituent_links.values(): if link.child._derivatize: return link.child return None # WIP class DerivatizeBase(object): # pragma: no cover def __init__(self, substituent, white_list, black_list, *args, **kwargs): self.substituent = substituent self.white_list = white_list self.black_list = black_list def on_reducing_end(self, node): pass def on_terminal(self, node): pass def on_substituent(self, node): pass