Source code for dnacauldron.Fragment.HomologousFragment.HomologousFragment

from copy import deepcopy
from Bio.SeqRecord import SeqRecord
from ..Fragment import Fragment

try:
    # Biopython <1.78
    from Bio.Alphabet import DNAAlphabet

    has_dna_alphabet = True
except ImportError:
    # Biopython >=1.78
    has_dna_alphabet = False

from ...biotools import set_record_topology, crop_record_with_saddling_features


[docs]class HomologousFragment(Fragment):
[docs] @staticmethod def from_biopython_record(biopython_record): """Convert a Biopython record into a HomologousFragment (class change). """ new_record = deepcopy(biopython_record) new_record.original_part = biopython_record new_record.__class__ = HomologousFragment return new_record
[docs] def circularized( self, homology_checker, annotate_homology=False, annotation_type="homology", ): """Return the Biopython record obtained by cirularizing the result. Only works if the left and right sticky ends are compatible. The return is a simple Biopython record where the sticky end has been integrated in the sequence. """ double_self = self.assemble_with( self, homology_checker=homology_checker, annotate_homology=True, annotation_type="homology", ) def only_parts_indicators(feature): return feature.qualifiers.get("indicates_part", False) result = crop_record_with_saddling_features( record=double_self, start=len(self), end=len(double_self), filters=(only_parts_indicators,), ) result.__class__ = SeqRecord set_record_topology(result, "circular") return result
def _push_source_features(self, homology_size, side="left"): """Relocate one end of a feature so it won't be cut out when the fragment is cropped.""" if side == "left": maximum = len(self) - homology_size for f in self.features: if f.qualifiers.get("is_source", False): f.location.start = min(f.location.start, maximum) f.location.end = min(f.location.end, maximum) if side == "right": for f in self.features: if f.qualifiers.get("is_source", False): f.location.start = max(f.location.start, homology_size) f.location.end = max(f.location.end, homology_size)
[docs] def will_clip_in_this_order_with(self, other_fragment, homology_checker): """Return whether the fragment will assemble with anoter via homology recombination. homology_checker should be an HomologyChecker instance definining the homology conditions. """ homology_size = homology_checker.find_end_homologies(self, other_fragment) return homology_size > 0
[docs] def assemble_with( self, fragment, homology_checker, annotate_homology=True, annotation_type="homology", ): """Return the fragment resulting from the assembly of this fragment with another, in that order. Parameters ---------- fragment The other parameter to assemble with. homology_checker An HomologyChecker instance definining the homology conditions. annotate_homology If true, homologies will have an annotation in the final, predicted construct records. """ homology_size = homology_checker.find_end_homologies(self, fragment) if homology_size == 0: raise ValueError( "Only fragments with end homologies ends can be assembled." ) new_self = deepcopy(self) new_fragment = deepcopy(fragment) new_self._push_source_features(homology_size, side="left") new_fragment._push_source_features(homology_size, side="right") if annotate_homology: feature = self.create_homology_annotation( start=0, end=homology_size, annotation_type=annotation_type, label="homology", ) new_fragment.features.append(feature) def only_parts_indicators(feature): return feature.qualifiers.get("indicates_part", False) self_subrecord = crop_record_with_saddling_features( record=self, start=0, end=len(self) - homology_size, filters=(only_parts_indicators,), ) assert len(self_subrecord) == len(self[:-homology_size]) result = self_subrecord + new_fragment result.__class__ = HomologousFragment return result
[docs] @staticmethod def assemble( fragments, homology_checker, circularize=False, annotate_homologies=False, ): """Return the record obtained by assembling the fragments. Parameters ---------- fragments List of HomologousFragments to assemble. homology_checker An HomologyChecker instance definining the homology conditions. circularize True to also assemble the end flanks of the final construct. annotate_homologies If true, homologies will have an annotation in the final, predicted construct records. """ result = fragments[0] for fragment in fragments[1:]: result = result.assemble_with( fragment=fragment, homology_checker=homology_checker, annotate_homology=annotate_homologies, ) if circularize: result = result.circularized( annotate_homology=annotate_homologies, homology_checker=homology_checker, ) if has_dna_alphabet: # Biopython <1.78 result.seq.alphabet = DNAAlphabet() result.annotations["molecule_type"] = "DNA" return result