def extend_fragments(self): """Extend U.r with M.f, D.f with M.r identically, accounting for strand.""" U, M, D, _ = self.fragments U.r.ext += dna.revc(M.f.seq) D.f.ext += dna.revc(M.r.seq) return
def add_feature(self, search_str, label): """Label a feature by literal string match, failing silently. Does not label features that wrap around circular sequence Args: search_str (str): string representing feature label (str): feature name to display""" f_matches = re.finditer(search_str, str(self.seq), re.IGNORECASE) r_matches = () if search_str.lower() != dna.revc(search_str.lower()): # Don't label palindromes twice r_matches = re.finditer(dna.revc(search_str), str(self.seq), re.IGNORECASE) for m, strand in chain(izip_longest(f_matches, [1]), izip_longest(r_matches, [-1])): if m: feature = SeqFeature.SeqFeature( SeqFeature.FeatureLocation(m.start(), m.end(), strand), 'misc_feature') color = self.colors.next() feature.qualifiers = { 'label': [label], 'ApEinfo_fwdcolor': [color], 'ApEinfo_revcolor': [color], 'ApEinfo_graphicformat': ['arrow_data {{0 1 2 0 0 -1} {} 0} width 5 offset 0'] } self.features.append(feature) return
def extend_fragments(self): """First, extends primers to splice in_frame sequences between tag and U homology arm. Then calls superclass method to complete.""" # Use seq_no_ext to avoid duplication of overlap when ext modified # revc to top strand, concatenate, then revc back to bottom if self.T is not None: self.U.r.ext = dna.revc(''.join( [dna.revc(self.U.r.ext), self.T.seq_no_ext[:GIBSON_OVERLAP]])) self.T.f.ext = self.U.seq_no_ext[-GIBSON_OVERLAP:] + self.T.f.ext super(CtagDesign, self).extend_fragments() return
def extend_fragments(self): """While any fragment is missing extensions in its primers, fill from previous and next. If previous extended but not next, use the next unused UNS. Encountering UNS removes from list. Fragment identities not required. If existing overlap has UNS, must be on top strand.""" # Abuse list as circular linked list with modulo-n indexing n = len(self.fragments) if not any([p.ext for f in self.fragments for p in f.pair]): # If none of the fragments have extensions, # this is a generic design. Cycle through UNSs, O(n) time. for i in range(n): uns = self.uns_list.pop(0) self.fragments[i - 1].r.ext += dna.revc(uns) self.fragments[i].f.ext += uns return # Maximally examines each fragment once, O(n) time. # There must be at least one fragment with extensions: # start at that fragment. i = (i for i, f in enumerate(self.fragments) for p in f.pair if p.ext).next() prv = self.fragments[(i - 1) % n] cur = self.fragments[i] while not all([p.ext for f in self.fragments for p in f.pair]): i = self.fragments.index(cur) nxt = self.fragments[(i + 1) % n] if cur.f.ext: # Propagate to previous node if prv.r.ext: # Enforce assembly integrity: if cur.f.ext != dna.revc(prv.r.ext): try: dna.merge(prv.seq, cur.seq, dna.Gibson.min_overlap) except ValueError: print('Input fragment overlaps do not assemble.') raise else: prv.r.ext = dna.revc(cur.f.ext) else: if not prv.r.ext: # Assign the next unused UNS prv.r.ext = dna.revc(staged_uns) # Propagate previous extension to current. cur.f.ext = dna.revc(prv.r.ext) # Remove used UNS and point staged_uns to next unused UNS # (circular linked list) if cur.f.ext and cur.f.ext in self.uns_list: u = self.uns_list.index(cur.f.ext) self.uns_list.remove(cur.f.ext) staged_uns = self.uns_list[u % len(self.uns_list)] # Advance prv = cur cur = nxt
def test_Digest(self): a = dna.CutSite('ata') c = dna.CutSite('cgc') d = dna.Dna('AataAAAgcgA') x = dna.Digest((a, c), d) self.assertEquals(x.seq, 'ataAAAgcg'.lower()) # Nonpalindromic, searches opposite strand like primer pair x.pair = (c, a) self.assertEquals(x.seq, 'cgcTTTtat'.lower()) # CutSite C tandem palindrome d.base = 'AataAAAgcgcA' with self.assertRaises(ValueError): dna.Digest((a, c), d).seq # Palindromic a = dna.CutSite('aatt') c = dna.CutSite('ccgg') d = dna.Dna('AaattAAAccggA') x = dna.Digest((a, c), d) self.assertEquals(x.seq, 'aattAAAccgg'.lower()) d.circular = True # Now two products made, but returns top strand match only self.assertEquals(x.seq, 'aattAAAccgg'.lower()) # Flipping strand prioritizes the shorter match around the circuit d.base = dna.revc(d.seq) self.assertEquals(x.seq, 'aattTTccgg'.lower())
def add_cutsites(self): super(SoePcrMethod, self).add_cutsites() #Also check for cloning 8-cutters. Extend with sites including spacer. U, _, D, _ = self.fragments U.f.ext = ''.join( [SPACER_OUTER, V_CUTSITE_PAIR[0].seq, SPACER_INNER, U.f.ext]) # Map to top strand, concatenate, then reverse complement again D.r.ext = dna.revc(''.join( map(dna.revc, [D.r.ext, SPACER_INNER, V_CUTSITE_PAIR[1].seq, SPACER_OUTER]))) return
def test_Pcr(self): non = dna.Primer('tact') pal = dna.Primer('aatt') d = dna.Dna('AAAtactGGGaattAAA') pcr = dna.Pcr((non, pal), d) # palindromic primer has too many bindings with self.assertRaises(ValueError): pcr.seq new = dna.Primer('aattcc') pcr.pair = (non, new) self.assertEqual(pcr.seq, 'tactgggaatt') # Swapping pair returns reverse complement of product pcr.pair = pcr.pair[::-1] self.assertEqual(pcr.seq, dna.revc('tactgggaatt')) # Reversing each primer's orientation will raise exception # unless circular pcr.pair = [dna.Primer(dna.revc(p.seq)) for p in pcr.pair] with self.assertRaises(ValueError): pcr.seq pcr.template.circular = True self.assertEquals(pcr.seq, 'ggaattaaaaaatact')
def add_cutsites(self): """Just before assembly, check for integration 8-cutters and append sites flanking cassette. NEVER add to vector, as this results in a high frequency of Gibson recircularization (8p homology).""" # Integration only here. For cloning, SoePcr will extend. for site in INTEGRATION_CUTSITES: if not any([site.seq in f.search_seq for f in self.fragments]): # Append integration cutsite to interior of extension of # homology PCR primers self.U.f.ext = self.U.f.ext + site.seq # Map to top strand, concatenate, then reverse complement again self.D.r.ext = dna.revc(''.join( map(dna.revc, [site.seq, self.D.r.ext]))) return raise Exception('All supplied integration cutsites are ' + 'found in the assembly fragments.')
def colony_pcr(self): if not all([self.U, self.D]): raise AttributeError( 'Must first generate U and D fragments with flanking_pcrs().') full = self.locus.up + self.locus.seq + self.locus.down spacer = 30 start = full.index(self.U.f.base) - spacer end = full.index(dna.revc(self.D.r.base)) + len(self.D.r.base) + spacer options = { 'SEQUENCE_EXCLUDED_REGION': ','.join(map(str, (start, end - start))) } # Also set this region as a target to prevent N/Ctag from sidestepping options['SEQUENCE_TARGET'] = options['SEQUENCE_EXCLUDED_REGION'] size_range = (end - start, end - start + 2 * self.search) self.colony = tool.primer3_pcr(dna.Dna(full, name='STRAIN'), size_range=size_range, options=options)
def test_revc(self): self.assertEquals(dna.revc(self.s), 'agtaTCTC')
zip(('Lox-ZeoR', 'Lox-NourR', 'Lox-G418R', 'Lox-HygroR', 'pUC-AmpR'), [ paths.PLASMID_PREFIX + s for s in ('RMp4694.gb', 'RMp4930.gb', 'RMp4957.gb', 'RMp4954.gb', 'RMp1087.ape') ])) MAP_MOD_IN_FRAME = OrderedDict([('Knockout', False), ('Knockdown', False), ('Overexpression', False), ('Ntag', True), ('Ctag', True)]) # Module globals: small dna objects and dna-related variables M_BASE_PRIMER_PAIR = (dna.Primer('ctgattctgtggataaccgtagtc', name='RMo11228'), dna.Primer('gaattggttaattggttgtaacacat', name='RMo11229')) M_GIBSON_PRIMER_PAIR = copy.deepcopy(M_BASE_PRIMER_PAIR) M_GIBSON_PRIMER_PAIR[0].ext = UNS[4] M_GIBSON_PRIMER_PAIR[0].name = 'RMo11230' M_GIBSON_PRIMER_PAIR[1].ext = dna.revc(UNS[5]) M_GIBSON_PRIMER_PAIR[1].name = 'RMo11231' VECTOR = 'pUC-AmpR' V_GIBSON_PRIMER_PAIR = (dna.Primer(ext=UNS[-1], base='ggcggtaatacggttatcca', name='RMo11232'), dna.Primer(ext=dna.revc(UNS[0]), base='gcggaacccctatttgttta', name='RMo11233')) V_CUTSITE_PAIR = (dna.CutSite('ggcgcgcc', name='AscI'), dna.CutSite('cctgcagg', name='SbfI')) INTEGRATION_CUTSITES = [ dna.CutSite('gcggccgc', name='NotI'), dna.CutSite('gtttaaac', name='PmeI'), dna.CutSite('gcgatcgc', name='AsiSI'),