Source code for dnacauldron.AssemblyMix.RestrictionLigationMix

"""
"""

from copy import copy

from Bio import Restriction

from ..Fragment.StickyEndFragment import StickyEndFragment
from ..Filter import NoRestrictionSiteFilter
from .StickyEndAssemblyMix import StickyEndAssemblyMix
from ..biotools import autoselect_enzyme


[docs]class RestrictionLigationMix(StickyEndAssemblyMix): """Mix to represent and simulate restriction-ligation reactions. For reactions using type-2S enzymes (Golden Gate assembly etc.), see the helper function generate_type2s_restriction_mix(). Parameters ---------- parts List of Biopython records representing circular or blunt-end linear DNA fragments which will be restricted into sticky-end fragments and assembled toghether via sticky-end homologies. enzymes List of names of the enzyme to be used for the restriction fragments A list of StickyEndFragment instances, which will assemble together based of sticky ends perfect homologies. fragment_filters List of functions of the form fragment=>True/False. If a fragment generates a "False" by at least one filter, it is taken out of the mix (this is used to remove unstable fragments that won't make it to the final assembly, for instance fragments with internal restriction sites). name Name of the mix as it will appear in reports annotate_fragments_with_parts If True, final constructs will have annotations "From xxx" indicating which part each sequence segment comes from. """ def __init__( self, parts=None, enzymes=None, fragments=None, fragment_filters=(), name="restriction_mix", annotate_fragments_with_parts=True, ): # shallow copy seems sufficient and problem-free. # deepcopy would be safer but it is a computational bottleneck. self.parts = copy(parts) if parts else parts self.fragments = copy(fragments) if fragments else fragments if enzymes is not None: enzymes = [Restriction.__dict__[e] for e in enzymes] self.enzymes = enzymes self.fragment_filters = fragment_filters self.name = name self.annotate_fragments_with_parts = annotate_fragments_with_parts self.initialize()
[docs] def compute_digest(self, part): """Compute the fragments resulting from the digestion""" return StickyEndFragment.list_from_record_digestion(part, self.enzymes)
[docs] def compute_fragments(self): """Compute the (sticky-ended) fragments resulting from the digestion of the mix's parts by the mix's enzyme. Note that all fragments receive an annotation (feature) of type "source" that will show in the genbank of final constructs. """ self.fragments = [] for part in self.parts: for fragment in self.compute_digest(part): # The part is not a fragment if it hasn't been cut at all and # therefore doesn't have sticky ends. Exclude from fragments. if not hasattr(fragment.seq, "left_end"): continue fragment.original_part = part self.annotate_fragment_with_part(fragment) self.fragments.append(fragment)
def generate_type2s_restriction_mix(parts, enzyme="auto", name="type2s_mix"): """Return a Type-2S compatible RestrictionLigationMix. If enzyme is "auto", it will be autoselected among BsmBI, BsaI, etc. """ if enzyme == "auto": enzyme = autoselect_enzyme(parts) return RestrictionLigationMix( parts=parts, enzymes=[enzyme], fragment_filters=[NoRestrictionSiteFilter(str(enzyme))], name=name, )