def add_angle_inducing_insertions_deletions(design: sc.Design) -> None: # insertion followed by deletion start = 59 end = start + (32 * 12) for helix in [1, 5, 7, 11, 13]: for offset in range(start, end, 32): design.add_insertion(helix, offset, 1) design.add_deletion(helix, offset + 16) # deletion followed by insertion for helix in [2, 4, 8, 10, 14]: for offset in range(start, end, 32): design.add_deletion(helix, offset) design.add_insertion(helix, offset + 16, 1)
def add_domains_for_barrel_seam(design: sc.Design) -> None: top_staples_5p = design.strands_starting_on_helix(0) top_staples_3p = design.strands_ending_on_helix(0) bot_staples_5p = design.strands_starting_on_helix(15) bot_staples_3p = design.strands_ending_on_helix(15) # remove scaffold top_staples_5p = [st for st in top_staples_5p if len(st.domains) <= 3] top_staples_3p = [st for st in top_staples_3p if len(st.domains) <= 3] bot_staples_5p = [st for st in bot_staples_5p if len(st.domains) <= 3] bot_staples_3p = [st for st in bot_staples_3p if len(st.domains) <= 3] top_staples_5p.sort(key=lambda stap: stap.offset_5p()) top_staples_3p.sort(key=lambda stap: stap.offset_3p()) bot_staples_5p.sort(key=lambda stap: stap.offset_5p()) bot_staples_3p.sort(key=lambda stap: stap.offset_3p()) for top_5p, top_3p, bot_5p, bot_3p in zip(top_staples_5p, top_staples_3p, bot_staples_5p, bot_staples_3p): ss_top = sc.Domain(helix=0, forward=False, start=top_5p.first_domain().end, end=top_3p.last_domain().start) ss_bot = sc.Domain(helix=15, forward=True, start=bot_3p.last_domain().end, end=bot_5p.first_domain().start) design.insert_domain(bot_5p, 0, ss_top) design.insert_domain(top_5p, 0, ss_bot)
def add_adapters(design: sc.Design) -> None: # left adapters left_inside_seed = 48 left_outside_seed = left_inside_seed - 26 for bot_helix in range(2, 18, 2): top_helix = bot_helix - 1 if bot_helix != 2 else 17 ss_top = sc.Domain(helix=top_helix, forward=True, start=left_outside_seed, end=left_inside_seed) ss_bot = sc.Domain(helix=bot_helix, forward=False, start=left_outside_seed, end=left_inside_seed) idt = sc.IDTFields(name=f'adap-left-{top_helix}-{bot_helix}', scale='25nm', purification='STD') adapter = sc.Strand(domains=[ss_bot, ss_top], idt=idt) design.add_strand(adapter) # right adapters right_inside_seed = 464 right_outside_seed = right_inside_seed + 26 for bot_helix in range(2, 18, 2): top_helix = bot_helix - 1 if bot_helix != 2 else 17 ss_top = sc.Domain(helix=top_helix, forward=True, start=right_inside_seed, end=right_outside_seed) ss_bot = sc.Domain(helix=bot_helix, forward=False, start=right_inside_seed, end=right_outside_seed) idt = sc.IDTFields(name=f'adap-right-{top_helix}-{bot_helix}', scale='25nm', purification='STD') adapter = sc.Strand(domains=[ss_top, ss_bot], idt=idt) design.add_strand(adapter)
def add_tiles_and_assign_dna(design: sc.Design) -> None: # left tiles left_left = 11 left_right = 32 for top_helix, seq in zip(range(2, 18, 2), tile_dna_seqs): bot_helix = top_helix + 1 ss_top = sc.Domain(helix=top_helix, forward=True, start=left_left, end=left_right) ss_bot = sc.Domain(helix=bot_helix, forward=False, start=left_left, end=left_right) idt = sc.IDTFields(name=f'tile-left-{top_helix}-{bot_helix}', scale='25nm', purification='STD') tile = sc.Strand(domains=[ss_bot, ss_top], color=sc.Color(0, 0, 0), idt=idt) design.add_strand(tile) design.assign_dna(tile, seq) # right tiles right_left = 480 right_right = 501 for top_helix, seq in zip(range(2, 18, 2), tile_dna_seqs): bot_helix = top_helix + 1 ss_top = sc.Domain(helix=top_helix, forward=True, start=right_left, end=right_right) ss_bot = sc.Domain(helix=bot_helix, forward=False, start=right_left, end=right_right) idt = sc.IDTFields(name=f'tile-right-{top_helix}-{bot_helix}', scale='25nm', purification='STD') tile = sc.Strand(domains=[ss_bot, ss_top], color=sc.Color(0, 0, 0), idt=idt) design.add_strand(tile) design.assign_dna(tile, seq)
def move_top_and_bottom_staples_within_column_boundaries(design: sc.Design): top_staples = design.strands_starting_on_helix(0) bot_staples = design.strands_starting_on_helix(15) bot_staples.remove(design.scaffold) for top_staple in top_staples: current_end = top_staple.domains[0].end design.set_end(top_staple.domains[0], current_end - 8) for bot_staple in bot_staples: current_start = bot_staple.domains[0].start design.set_start(bot_staple.domains[0], current_start + 8)
def valid_deletion_offset(design: sc.Design, helix: int, offset: int) -> bool: domains_at_offset = design.domains_at(helix, offset) if len(domains_at_offset) > 2: raise ValueError(f'Invalid Design; more than two Substrands found at ' f'helix {helix} and offset {offset}: ' f'{domains_at_offset}') elif len(domains_at_offset) != 2: return False for ss in domains_at_offset: if offset in ss.deletions: return False # already a deletion there if offset in (insertion[0] for insertion in ss.insertions): return False # already an insertion there if offset == ss.start: return False # no 5' end if offset == ss.end - 1: return False # no 3' end return True
def add_scaffold_crossovers(design: sc.Design) -> None: for helix in range(1, 23, 2): # scaffold interior crossovers design.add_full_crossover(helix=helix, helix2=helix + 1, offset=144, forward=False) for helix in range(0, 23, 2): # scaffold edges crossovers design.add_half_crossover(helix=helix, helix2=helix + 1, offset=0, forward=True) design.add_half_crossover(helix=helix, helix2=helix + 1, offset=287, forward=True)
def add_crossovers(design: sc.Design) -> None: # staples interior for offset in range(84, 1246, 42): design.add_full_crossover(helix=0, helix2=1, offset=offset, forward=False) design.add_full_crossover(helix=3, helix2=4, offset=offset, forward=True) for offset in range(56, 1246, 42): design.add_full_crossover(helix=1, helix2=2, offset=offset, forward=True) design.add_full_crossover(helix=4, helix2=5, offset=offset, forward=False) for offset in range(70, 1246, 42): design.add_full_crossover(helix=2, helix2=3, offset=offset, forward=False) design.add_full_crossover(helix=5, helix2=0, offset=offset, forward=True) for offset in range(49, 1245, 42): # extra crossovers 5 - 0 for some reason design.add_full_crossover(helix=5, helix2=0, offset=offset, forward=True) # staples edges design.add_half_crossover(helix=0, helix2=1, offset=42, forward=False) design.add_half_crossover(helix=3, helix2=4, offset=42, forward=True) design.add_half_crossover(helix=0, helix2=5, offset=1245, forward=False) design.add_half_crossover(helix=2, helix2=3, offset=1245, forward=False) # scaffold interior for offset in range(58, 1250, 42): design.add_full_crossover(helix=0, helix2=1, offset=offset, forward=True) for offset in range(30, 1250, 42): design.add_full_crossover(helix=1, helix2=2, offset=offset, forward=False) for offset in range(54, 1250, 42): design.add_full_crossover(helix=2, helix2=3, offset=offset, forward=True) for offset in range(26, 1250, 42): design.add_full_crossover(helix=3, helix2=4, offset=offset, forward=False) # scaffold edges design.add_half_crossover(helix=0, helix2=1, offset=16, forward=True) design.add_half_crossover(helix=2, helix2=3, offset=12, forward=True) design.add_half_crossover(helix=4, helix2=5, offset=19, forward=True) design.add_half_crossover(helix=0, helix2=1, offset=1275, forward=True) design.add_half_crossover(helix=2, helix2=3, offset=1271, forward=True) design.add_half_crossover(helix=4, helix2=5, offset=1278, forward=True)
def add_nicks(design: sc.Design) -> None: design.add_nick(helix=5, offset=399, forward=False) # scaffold for offset in range(56, 1246, 42): design.add_nick(helix=0, offset=offset, forward=False) design.add_nick(helix=3, offset=offset, forward=True) for offset in range(70, 1246, 42): design.add_nick(helix=1, offset=offset, forward=True) design.add_nick(helix=4, offset=offset, forward=False) for offset in range(84, 1246, 42): design.add_nick(helix=2, offset=offset, forward=False) design.add_nick(helix=5, offset=offset, forward=True)
def add_scaffold_nicks(design: sc.Design): crossovers = [] for helix in range(3, maxhelix, 2): if not design.strands_starting_on_helix(helix): pass else: hel1 = helix #first starting helix break for helix in range(hel1, maxhelix, 2): scafdom1 = design.strands_starting_on_helix(helix) scafdom2 = design.strands_starting_on_helix(helix + 1) if not (scafdom1 and scafdom2): #check for empty helix at the end of the design break imghelix = int((helix - 1) / 2) if (1 in img[imghelix]) and (1 in img[imghelix + 1]): interstarts = [] interends = [] for dom in range(1, len(img[imghelix])): if (bool(img[imghelix][dom] and img[imghelix+1][dom])) and \ (not bool(img[imghelix][dom-1] and img[imghelix+1][dom-1])): interstarts.append(dom) if (not bool(img[imghelix][dom] and img[imghelix+1][dom])) and \ (bool(img[imghelix][dom-1] and img[imghelix+1][dom-1])): interends.append(dom) interstarts = [x * block for x in interstarts] interends = [x * block for x in interends] for i in range(len(interstarts)): #finds the scaffold crossover offset position 'nickoff', for the square lattice, #closest to the center of the intersection of helices that are crossing over closestoff = int((interstarts[i] + interends[i]) / 2) - 2 closerem = (closestoff) % 32 if (closerem < 10): nickoff = 3 + 32 * int(closestoff / 32) if nickoff <= interstarts[i]: nickoff = 3 + 32 * int(closestoff / 32) + 10 elif nickoff >= interends[i]: nickoff = 3 + 32 * int(closestoff / 32) - 11 elif (closerem > 10) and (closerem < 21): nickoff = 3 + 32 * int(closestoff / 32) + 10 if nickoff <= interstarts[i]: nickoff = 3 + 32 * int(closestoff / 32) + 21 elif nickoff >= interends[i]: nickoff = 3 + 32 * int(closestoff / 32) elif (closerem > 21) and (closerem < 32): nickoff = 3 + 32 * int(closestoff / 32) + 21 if nickoff <= interstarts[i]: nickoff = 3 + 32 * int(closestoff / 32) + 32 elif nickoff >= interends[i]: nickoff = 3 + 32 * int(closestoff / 32) + 10 else: nickoff = 3 + 32 * int(closestoff / 32) + closerem design.add_nick(helix=helix, offset=nickoff, forward=helix % 2 == 0) design.add_nick(helix=helix + 1, offset=nickoff, forward=helix % 2 == 1) crossovers.append( sc.Crossover(helix=helix, helix2=helix + 1, offset=nickoff, forward=False)) design.add_nick(helix=helix, offset=nickoff, forward=helix % 2 == 0) design.add_crossovers(crossovers)
def add_staple_nicks(design: sc.Design): crossovers = [] for helix in range(3, maxhelix, 2): if not design.strands_starting_on_helix(helix): pass else: hel1 = helix #first starting helix break for helix in range(hel1, maxhelix, 2): scafdom1 = design.strands_starting_on_helix(helix) scafdom2 = design.strands_starting_on_helix(helix + 1) if not (scafdom1 and scafdom2): #check for empty helix at the end of the design break for helix in range(maxhelix): if helix % 2 == 0: for offset in range(block * cmax): if (offset % 32 == 0) and (design.domains_at(helix, offset)): if domain_end(design, helix, offset): #no nick if domain end continue #Prevent very short staples if (design.domains_at(helix, offset-16)) and \ (design.domains_at(helix, offset+16)): design.add_nick(helix=helix, offset=offset, forward=helix % 2 == 1) if 0<=(offset-8)<=block*cmax and \ (design.domains_at(helix, offset-16)) and \ (design.domains_at(helix, offset)) and \ (design.domains_at(helix+1, offset-8)) and \ (design.domains_at(helix+1, offset-9)) and \ not domain_end(design, helix, offset-8): crossovers.append(sc.Crossover(helix=helix, helix2=helix + 1, \ offset=offset-8, forward=helix % 2 == 1)) else: for offset in range(block * cmax): if ((offset + 16) % 32 == 0) and (design.domains_at( helix, offset)): if domain_end(design, helix, offset): continue #Prevent very short staples if (design.domains_at(helix, offset-16)) and \ (design.domains_at(helix, offset+16)): design.add_nick(helix=helix, offset=offset, forward=helix % 2 == 1) if 0<=(offset-8)<=block*cmax and \ (design.domains_at(helix, offset-16)) and \ (design.domains_at(helix, offset)) and \ (design.domains_at(helix+1, offset-8)) and \ (design.domains_at(helix+1, offset-9)) and \ not domain_end(design, helix, offset-8): crossovers.append(sc.Crossover(helix=helix, helix2=helix + 1, \ offset=offset-8, forward=helix % 2 == 1)) design.add_crossovers(crossovers)
def add_staple_nicks(design: sc.Design): crossovers = [] midgap = 3 state = 0 every = -1 #skip every xth crossover for helix in range(3, maxhelix, 2): if not design.strands_starting_on_helix(helix): pass else: hel1 = helix #first starting helix break for helix in range(hel1, maxhelix, 2): scafdom1 = design.strands_starting_on_helix(helix) scafdom2 = design.strands_starting_on_helix(helix + 1) if not (scafdom1 and scafdom2): #check for empty helix at the end of the design break for helix in range(maxhelix): if helix % 2 == 0: for offset in range(block * cmax): if (((offset-3)%32==0) or \ ((offset-3)%32==10) or \ ((offset-3)%32==21)) and \ (design.domains_at(helix, offset+midgap)): state = state + 1 if not every == -1: if state % every == 0: # print(str(helix)+' '+str(offset)) continue if domain_end(design, helix, offset + midgap): #no nick if domain end continue #Prevent very short staples if long_stap_cond(design, helix, offset + midgap) == True: design.add_nick(helix=helix, offset=offset + midgap, forward=helix % 2 == 1) if cross_conds(design, helix, offset): crossovers.append(sc.Crossover(helix=helix, helix2=helix + 1, \ offset=offset, forward=helix % 2 == 1)) elif helix == 2: print("not here " + str(offset)) else: for offset in range(block * cmax): if (((offset-8)%32==0) or \ ((offset-8)%32==11) or \ ((offset-8)%32==21)) and \ (design.domains_at(helix, offset+midgap)): state = state + 1 if not every == -1: if state % every == 0: # print(str(helix)+' '+str(offset)) continue if domain_end(design, helix, offset + midgap): #no nick if domain end continue # #Prevent very short staples # if long_stap_cond(design, helix, offset+midgap)==True: # design.add_nick(helix=helix, offset=offset+midgap, forward=helix % 2 == 1) if cross_conds(design, helix, offset): crossovers.append(sc.Crossover(helix=helix, helix2=helix + 1, \ offset=offset, forward=helix % 2 == 1)) design.add_crossovers(crossovers)
def add_scaffold_nicks(design: sc.Design): for helix in range(1, 24): design.add_nick(helix=helix, offset=152, forward=helix % 2 == 0)
def add_deletions(design: sc.Design): for helix in range(24): for offset in range(27, 294, 48): design.add_deletion(helix, offset)
def add_staple_nicks(design: sc.Design): for helix in range(24): start_offset = 32 if helix % 2 == 0 else 48 for offset in range(start_offset, 280, 32): design.add_nick(helix, offset, forward=helix % 2 == 1)
def export_idt_plate_file(design: sc.Design): for strand in design.strands: if strand != design.scaffold: strand.set_default_idt(use_default_idt=True) design.write_idt_plate_excel_file(use_default_plates=True)
def add_twist_correction_deletions(design: sc.Design) -> None: for helix in range(24): for offset in range(19, 286, 48): design.add_deletion(helix, offset)
def add_staple_nicks(design: sc.Design) -> None: for helix in range(24): start_offset = 24 if helix % 2 == 0 else 40 for offset in range(start_offset, 272, 32): design.add_nick(helix, offset, forward=helix % 2 == 1)
def add_twist_correct_deletions(design: sc.Design) -> None: # I choose between 3 and 4 offset arbitrarily for twist-correction deletions for some reason, # so they have to be hard-coded. for col, offset in zip(range(4, 29, 3), [4, 3, 3, 4, 3, 3, 3, 3, 3]): for helix in range(2, 18): design.add_deletion(helix, 16 * col + offset)
def adjust_helix_grid_and_positions(design: sc.Design): design.grid = sc.Grid.none for helix in design.helices.values(): helix.grid_position = None position3d = idx_to_position(helix.idx) helix.position = position3d
def add_precursor_staples(design: sc.Design): staples = [sc.Strand([sc.Domain(helix=helix, forward=helix % 2 == 1, start=8, end=296)]) for helix in range(24)] for staple in staples: design.add_strand(staple)
def add_staple_nicks(design: sc.Design, nick_locations): """Adds nicks ot the precursor staple strands""" for helix in range(len(nick_locations)): forward = sc_general.forward_strand(helix, 'staple') for nick in nick_locations[helix]: design.add_nick(helix = helix, offset = nick, forward = forward)