def tie_break(n_diff1, n_diff2): theta1 = calc_bend_angle(n, n_diff1) theta2 = calc_bend_angle(n, n_diff2) if abs(theta1-target_theta) < abs(theta2-target_theta): return n_diff1 return n_diff2
def print_candidate(num_segments, n_diff, num_potential_strands, n_diff_period): print('\n') theta = calc_bend_angle(num_segments*7, n_diff) theta_error = (360-theta)/3.6 print str(num_potential_strands) + ' strands per well,', print str(num_segments) + ' segments,', print "{0:.2f}".format(theta_error) + '% theta error,', print str(num_segments*7) + ' bp long,', print str(n_diff) + " insertions/deletions ,", print str(n_diff/num_segments*n_diff_period) + ' insertions/deletions per', if n_diff_period == 1: print "segment" else: print str(n_diff_period) + ' segments' #calc_bend_angle(num_segments*7, n_diff, True, False, False) if abs(theta_error) < min_theta_error_candidate["theta_error"]: min_theta_error_candidate["theta_error"] = abs(theta_error) min_theta_error_candidate["num_segments"] = num_segments min_theta_error_candidate["n_diff"] = n_diff min_theta_error_candidate["n_diff_period"] = n_diff_period min_theta_error_candidate["num_potential_strands"] = num_potential_strands
def solve_for_n_diff(n, target_theta=360): tolerance = 0.01 n_diff = 0 # num insertions deletions last_n_diff = -1 n_diff_max = n n_diff_min = 0 theta = 0 def tie_break(n_diff1, n_diff2): theta1 = calc_bend_angle(n, n_diff1) theta2 = calc_bend_angle(n, n_diff2) if abs(theta1-target_theta) < abs(theta2-target_theta): return n_diff1 return n_diff2 ##binary search across integer n_diff to find right theta for length while abs(theta-target_theta) > tolerance: if theta < target_theta: n_diff_min = n_diff else: n_diff_max = n_diff n_diff = round((n_diff_max+n_diff_min)/2.0) if last_n_diff == n_diff: if n_diff-1 < n_diff_min: if n_diff+1 > n_diff_max: break else: n_diff += 1 else: n_diff -= 1 if n_diff == n_diff_max or n_diff == n_diff_min:# we've already tried this one n_diff = tie_break(n_diff, last_n_diff) break theta = calc_bend_angle(n, n_diff) last_n_diff = n_diff return n_diff
for num_potential_strands in range(num_potential_strands_range[0], num_potential_strands_range[1]+1): min_num_segments = int(math.ceil(num_segments_range[0]/float(num_potential_strands))*num_potential_strands) for num_segments in range(min_num_segments, num_segments_range[1]+1, num_potential_strands): if num_segments % 3 != 0: continue if num_segments_min > num_segments: continue n = num_segments*num_bp_per_segment n_diff = solve_for_n_diff(n) num_segments_factors = factors(num_segments) for i, val in enumerate(num_segments_factors): remainder = n_diff/val - round(n_diff/val) if abs(remainder*val) < tolerance and (round(n_diff/val) in num_segments_factors): factor1 = val factor2 = round(n_diff/val) n_diff = factor1*factor2 print_candidate(num_segments, n_diff, num_potential_strands, num_segments/max(factor1, factor2)) print "\n\n" print "candidate with min theta error:" print_candidate(min_theta_error_candidate["num_segments"], min_theta_error_candidate["n_diff"], min_theta_error_candidate["num_potential_strands"], min_theta_error_candidate["n_diff_period"]) print calc_bend_angle(min_theta_error_candidate["num_segments"]*num_bp_per_segment, min_theta_error_candidate["n_diff"], True, False, True) print "\n"