def score(seq): s1, s2 = seq[int(len(seq) / 2):], seq[:int(len(seq) / 2)] if abs(melting.temp(s1) - 72.5) < 7.5 and abs(melting.temp(s2) - 72.5) < 7.5 and abs( gc(s1) - 0.5) < 0.1 and abs(gc(s2) - 0.5) and (s2[0] == "A" or s2[0] == "T"): ssc = sec(s1, s2) return ssc return 0
def test_low_cation_ratio(): expected_tm = 82.2 given_tm = melting.temp("GCGCGCGCGCGCGCGC", DNA_c=200, Na_c=500, Mg_c=3, dNTPs_c=0.8) assert within_margin(given_tm, expected_tm, margin=1)
def test_melting(): # Temps taken from https://www.idtdna.com/calc/analyzer # on 2015-10-29 using qPCR parameters: # - Oligo Conc: 0.2 uM # - Na+ Conc: 50mM # - Mg++ Conc: 3mM # - dNTPs Conc: 0.8mM idt_temps = { "ATGCATGC": 26.2, "CCCCTTTT": 21.7, "GCGCGCGCGCGCGCGC": 76.6, } for seq, expected_tm in idt_temps.items(): given_tm = melting.temp(seq, DNA_c=200, Na_c=50, Mg_c=3, dNTPs_c=0.8) assert within_margin(given_tm, expected_tm)
def test_uncorrected_tm(): corrected = melting.temp("ATGCATGC") uncorrected = melting.temp("ATGCATGC", uncorrected=True) assert corrected != uncorrected
def update_tm(self): self.tm = melting.temp(self.seq)
def design(sense_oligo, antisense_oligo, guide_context, orientation): #identify strand for Tm comparison and tagging orient_error = 'Orientation not correctly specified.\n' if orientation == 'sense': i = 0 j = 1 elif orientation == 'antisense': i = 1 j = 0 else: print(orient_error) return #convert sequences to Seq objects for manipulation sense = Seq(sense_oligo) antisense = Seq(antisense_oligo) context = Seq(guide_context) primers = (sense, antisense) #check guide sequence + context is big enough for design size_error = 'Guide and context is not big enough for design' if len(context) < 35: print(size_error) return #calculate Tm for primers MT = [] for primer in primers: temptm = melting.temp(primer, DNA_c=1000, Mg_c=1.5, dNTPs_c=0.2) MT.append(temptm) #design headloop tags frame = 0 poss_rc = [] #initialise lists poss_offset = [] master_rc = [] #initialise master lists master_offset = [] while frame < 3: #create list of possible reverse complement tags temp_rc = context[frame:(frame + 20)] #extract sequence rc = temp_rc.reverse_complement() #reverse complement temp_rc rc_temp_tm = melting.temp(rc, DNA_c=1000, Mg_c=1.5, dNTPs_c=0.2) #calculate Tm melting method rc_temp_diff = abs( MT[i] - rc_temp_tm) #calculate Tm difference with sense primer if rc_temp_diff < 3: rc_flag = 0 else: rc_flag = 1 poss_rc = (rc, rc_temp_tm, rc_temp_diff, frame, rc_flag) #create list master_rc.append(poss_rc) #append to master list #create list of possible offset tags offset = context[(frame + 12):(frame + 32)] #extract offset sequence off_temp_tm = melting.temp(offset, DNA_c=1000, Mg_c=1.5, dNTPs_c=0.2) #calculate Tm melting method off_temp_diff = abs( MT[j] - off_temp_tm) #calculate Tm difference with antisense primer if off_temp_diff < 3: off_flag = 0 else: off_flag = 1 poss_offset = (offset, off_temp_tm, off_temp_diff, frame, off_flag ) #create list master_offset.append(poss_offset) #append to master list frame = frame + 1 #frameshift by 1 #sort lists of optional tags by Tm difference with primer and, in tiebreaks, position master_rc.sort(key=lambda x: (x[2], x[3])) master_offset.sort(key=lambda x: (x[2], -x[3])) #concatenate headloop tags with correct primer, depending on strand orientation if orientation == 'sense': temp_sense_hl = master_rc[0][ 0] + sense #create headloop sense primer sequence temp_antisense_hl = master_offset[0][ 0] + antisense #create headloop antisense primer sequence #formats seq records sense_hl = SeqRecord(temp_sense_hl, id='Sense HL') if master_rc[0][4] == 1: sense_hl.description = 'WARNING: Could not optimise sense headloop tag (Tm difference > 3\u00b0C)' else: sense_hl.description = 'Tm difference < 3\u00b0C' antisense_hl = SeqRecord(temp_antisense_hl, id='Antisense HL') if master_offset[0][4] == 1: antisense_hl.description = 'WARNING: Could not optimise antisense headloop tag (Tm difference > 3\u00b0C)' else: antisense_hl.description = 'Tm difference < 3\u00b0C' else: temp_antisense_hl = master_rc[0][ 0] + antisense #create headloop antisense primer sequence temp_sense_hl = master_offset[0][0] + sense #formats seq records sense_hl = SeqRecord(temp_sense_hl, id='Sense HL') if master_offset[0][4] == 1: sense_hl.description = 'WARNING: Could not optimise sense headloop tag (Tm difference > 3\u00b0C)' else: sense_hl.description = 'Tm difference < 3\u00b0C' antisense_hl = SeqRecord(temp_antisense_hl, id='Antisense HL') if master_rc[0][4] == 1: antisense_hl.description = 'WARNING: Could not optimise antisense headloop tag (Tm difference > 3\u00b0C)' else: antisense_hl.description = 'Tm difference < 3\u00b0C' return (sense_hl, antisense_hl)
def calc_Tm(s, digits=3): ''' calculate Tm using the method in melting, as the primer3.calcTm produces -999999.9999 for some sequences ''' tm = melting.temp(s, DNA_c=50, Na_c=50, Mg_c=0, dNTPs_c=0.8); return(round(tm,digits));