Module overhang.OverhangSet
View Source
import itertools
import networkx
import tatapov
from .Overhang import Overhang, get_overhang_distance
from .tools import reverse_complement, enzyme_tatapov_lookup
class OverhangSet:
"""Class for *overhang sets*.
An overhang set is a collection of (mutually compatible) overhangs used for
DNA assembly.
**Parameters**
**overhangs**
> A list of overhang strings (`list`). Example: `["TAGG", "ATGG", "GACT"]`.
**enzyme**
> Enzyme used for assembly (`str`). Example: `"Esp3I"`.
**name**
> Name of the set (`str`).
"""
def __init__(self, overhangs, enzyme="Esp3I", name="Unnamed set"):
self.overhangs = [Overhang(overhang) for overhang in overhangs]
if len(set(overhangs)) != len(overhangs):
self.has_duplicates = True
else:
self.has_duplicates = False
self.overhang_input = overhangs
self.overhang_input_txt = ", ".join(self.overhang_input)
self.enzyme = enzyme
self.name = name
self.has_warnings = False # used during evaluation of set and reporting
self.has_errors = False # used during evaluation of set and reporting
self.overhang_length = len(self.overhang_input[0])
def inspect_overhangs(self, make_plot=True):
"""Inspect compatibility of overhangs and detect potential errors in the set."""
# DUPLICATES
if self.has_duplicates:
print("Incorrect set! Duplicate overhangs")
self.has_errors = True
# PALINDROMIC
self.palindromic_oh = []
self.palindromic_oh += [
overhang.overhang for overhang in self.overhangs if overhang.is_palindromic
]
if len(self.palindromic_oh) != 0:
self.palindromic_text = "Palindromic overhang(s): " + "; ".join(
self.palindromic_oh
)
print(("Incorrect set! " + self.palindromic_text))
self.has_errors = True
# REVERSE COMPLEMENT
nonpalindromic_oh = set(self.overhang_input) - set(self.palindromic_oh)
nonpalindromic_oh_rc = {reverse_complement(oh) for oh in nonpalindromic_oh}
rc_oh = nonpalindromic_oh & nonpalindromic_oh_rc
if rc_oh:
self.has_rc_error = True
self.rc_error_text = (
"Nonpalindromic overhang(s) with reverse complement: "
+ "; ".join(rc_oh)
)
print(("Incorrect set! " + self.rc_error_text))
self.has_errors = True
else:
self.has_rc_error = False
# SIMILAR OVERHANGS -- we do not consider it as a flaw
self.similar_overhangs = self.find_similar_overhangs()
# SET SIZE
# Based on Pryor et al., PLoS ONE (2020):
if self.overhang_length == 3: # check overhang length on first one
n = 10
if len(self.overhang_input) > n:
self.set_size_text = (
"Assembly fidelity significantly decreases when using "
+ "more than %d overhangs." % n
) # text used in report
print("Warning! " + self.set_size_text)
elif self.overhang_length == 4:
n = 20
if len(self.overhang_input) > n:
self.set_size_text = (
"Assembly fidelity significantly decreases when using "
+ "more than %d overhangs." % n
)
print("Warning! " + self.set_size_text)
else:
self.set_size_text = ""
# MISANNEALING
self.evaluate_annealing() # also sets `has_warnings`
# Tatapov plots:
if make_plot:
figwidth = len(self.overhang_input)
print(self.enzyme, "Tatapov plot (37 Celsius, 1 hour):")
data = tatapov.annealing_data["37C"][enzyme_tatapov_lookup[self.enzyme]]
subset = tatapov.data_subset(data, self.overhang_input, add_reverse=True)
self.ax, _ = tatapov.plot_data(subset, figwidth=figwidth, plot_color="Reds")
self.ax.figure.tight_layout()
self.ax.plot()
def evaluate_annealing(self):
"""Evaluate weakly anneals, self-misanneals and misanneals between overhangs.
Used in `inspect_overhangs()`.
"""
# Prepare data:
data = tatapov.annealing_data["37C"][enzyme_tatapov_lookup[self.enzyme]]
subset = tatapov.data_subset(data, self.overhang_input, add_reverse=True)
# WEAK ANNEALS
# See cutoff 400 in Pryor et al. Figure 2.
self.weak_anneals_list = [
[oh.overhang, oh.overhang_rc]
for oh in self.overhangs
if subset[oh.overhang][oh.overhang_rc] < 400
]
# Convert to text
self.weak_anneals = [
oh_pair[0] + "/" + oh_pair[1] for oh_pair in self.weak_anneals_list
]
self.weak_anneals = "; ".join(self.weak_anneals)
if not self.weak_anneals == "":
self.has_warnings = True
# SELF-MISANNEALS
self.self_misanneals_list = [
[oh.overhang, oh.overhang_rc]
for oh in self.overhangs
if subset[oh.overhang][oh.overhang] != 0
or subset[oh.overhang_rc][oh.overhang_rc] != 0
]
self.self_misanneals = [
oh_pair[0] + "/" + oh_pair[1] for oh_pair in self.self_misanneals_list
]
self.self_misanneals = "; ".join(self.self_misanneals)
if not self.self_misanneals == "":
self.has_warnings = True
# MISANNEALS
self.misanneals_list = []
for oh1, oh2 in itertools.combinations(self.overhangs, 2):
# 10 below is a good cutoff for misannealing pairs
if (
subset.loc[
[oh1.overhang, oh1.overhang_rc], [oh2.overhang, oh2.overhang_rc]
]
> 10
).any(axis=None):
# oh and reverse complement, in a list with its misannealing pair
self.misanneals_list += [
[[oh1.overhang, oh1.overhang_rc], [oh2.overhang, oh2.overhang_rc]]
]
# Create a text from the 4 overhangs, for the report:
self.misanneals = [
misannealing_pair[0][0]
+ "/"
+ misannealing_pair[0][1]
+ " ~ "
+ misannealing_pair[1][0]
+ "/"
+ misannealing_pair[1][1]
for misannealing_pair in self.misanneals_list
]
self.misanneals = "; ".join(self.misanneals)
if not self.misanneals == "":
self.has_warnings = True
def find_similar_overhangs(self, difference_threshold=None):
"""Find overhangs that differ in fewer nucleotides than the threshold.
**Parameters**
**difference_threshold**
> Acceptable number of matching nucleotides in an overhang pair (`int`).
Overhang pairs with fewer differences are marked as similar. Defaults to 0.
"""
if difference_threshold is None:
difference_threshold = 0
similar_overhangs = ""
for oh1, oh2 in itertools.combinations(self.overhangs, 2):
if get_overhang_distance(oh1, oh2) < difference_threshold:
similar_overhangs += (
oh1.overhang
+ "/"
+ oh1.overhang_rc
+ " ~ "
+ oh2.overhang
+ "/"
+ oh2.overhang_rc
+ " ; "
)
if similar_overhangs == "":
similar_overhangs = (
"No overhangs (including reverse complements) "
"differ by fewer than %d nucleotides." % difference_threshold
)
else:
similar_overhangs = (
"These overhang pairs (including reverse complements) have fewer than "
"%d differences: " % difference_threshold + similar_overhangs
)
return similar_overhangs
def find_perfect_subset(self):
"""Find a better overhang set by removing bad overhang interactions.
Bad interactions are weak anneals, self-misanneals and misanneals.
"""
self.inspect_overhangs(make_plot=False)
# REMOVE WEAK
oh_to_remove = [oh for oh_pair in self.weak_anneals_list for oh in oh_pair]
self.subset = set(self.overhang_input) - set(oh_to_remove)
# REMOVE SELF-MISANNEALING
oh_to_remove = [oh for oh_pair in self.self_misanneals_list for oh in oh_pair]
self.subset = set(self.subset) - set(oh_to_remove)
# REMOVE MISANNEALING
compatible_overhangs = []
misanneals_for_loop = [pair[0] + pair[1] for pair in self.misanneals_list]
for oh1, oh2 in itertools.combinations(self.subset, 2):
add_oh = True
for pair in misanneals_for_loop:
if oh1 in pair and oh2 in pair:
add_oh = False
break
if add_oh:
compatible_overhangs += [(oh1, oh2)]
graph = networkx.Graph(compatible_overhangs)
max_clique, clique_size = networkx.max_weight_clique(graph, None)
self.subset = max_clique
print("Overhangs in subset: " + str(self.subset))
print("Number of overhangs in subset: " + str(clique_size))
# Visualize subset:
figwidth = len(self.subset)
print(self.enzyme, "Tatapov plot (37 Celsius, 1 hour):")
data = tatapov.annealing_data["37C"][enzyme_tatapov_lookup[self.enzyme]]
subset = tatapov.data_subset(data, self.subset, add_reverse=True)
self.ax, _ = tatapov.plot_data(subset, figwidth=figwidth, plot_color="Reds")
self.ax.figure.tight_layout()
self.ax.plot()
Variables
enzyme_tatapov_lookup
Classes
OverhangSet
class OverhangSet(
overhangs,
enzyme='Esp3I',
name='Unnamed set'
)
Class for overhang sets.
An overhang set is a collection of (mutually compatible) overhangs used for DNA assembly.
Parameters
overhangs
A list of overhang strings (
list
). Example:["TAGG", "ATGG", "GACT"]
.
enzyme
Enzyme used for assembly (
str
). Example:"Esp3I"
.
name
Name of the set (
str
).
View Source
class OverhangSet:
"""Class for *overhang sets*.
An overhang set is a collection of (mutually compatible) overhangs used for
DNA assembly.
**Parameters**
**overhangs**
> A list of overhang strings (`list`). Example: `["TAGG", "ATGG", "GACT"]`.
**enzyme**
> Enzyme used for assembly (`str`). Example: `"Esp3I"`.
**name**
> Name of the set (`str`).
"""
def __init__(self, overhangs, enzyme="Esp3I", name="Unnamed set"):
self.overhangs = [Overhang(overhang) for overhang in overhangs]
if len(set(overhangs)) != len(overhangs):
self.has_duplicates = True
else:
self.has_duplicates = False
self.overhang_input = overhangs
self.overhang_input_txt = ", ".join(self.overhang_input)
self.enzyme = enzyme
self.name = name
self.has_warnings = False # used during evaluation of set and reporting
self.has_errors = False # used during evaluation of set and reporting
self.overhang_length = len(self.overhang_input[0])
def inspect_overhangs(self, make_plot=True):
"""Inspect compatibility of overhangs and detect potential errors in the set."""
# DUPLICATES
if self.has_duplicates:
print("Incorrect set! Duplicate overhangs")
self.has_errors = True
# PALINDROMIC
self.palindromic_oh = []
self.palindromic_oh += [
overhang.overhang for overhang in self.overhangs if overhang.is_palindromic
]
if len(self.palindromic_oh) != 0:
self.palindromic_text = "Palindromic overhang(s): " + "; ".join(
self.palindromic_oh
)
print(("Incorrect set! " + self.palindromic_text))
self.has_errors = True
# REVERSE COMPLEMENT
nonpalindromic_oh = set(self.overhang_input) - set(self.palindromic_oh)
nonpalindromic_oh_rc = {reverse_complement(oh) for oh in nonpalindromic_oh}
rc_oh = nonpalindromic_oh & nonpalindromic_oh_rc
if rc_oh:
self.has_rc_error = True
self.rc_error_text = (
"Nonpalindromic overhang(s) with reverse complement: "
+ "; ".join(rc_oh)
)
print(("Incorrect set! " + self.rc_error_text))
self.has_errors = True
else:
self.has_rc_error = False
# SIMILAR OVERHANGS -- we do not consider it as a flaw
self.similar_overhangs = self.find_similar_overhangs()
# SET SIZE
# Based on Pryor et al., PLoS ONE (2020):
if self.overhang_length == 3: # check overhang length on first one
n = 10
if len(self.overhang_input) > n:
self.set_size_text = (
"Assembly fidelity significantly decreases when using "
+ "more than %d overhangs." % n
) # text used in report
print("Warning! " + self.set_size_text)
elif self.overhang_length == 4:
n = 20
if len(self.overhang_input) > n:
self.set_size_text = (
"Assembly fidelity significantly decreases when using "
+ "more than %d overhangs." % n
)
print("Warning! " + self.set_size_text)
else:
self.set_size_text = ""
# MISANNEALING
self.evaluate_annealing() # also sets `has_warnings`
# Tatapov plots:
if make_plot:
figwidth = len(self.overhang_input)
print(self.enzyme, "Tatapov plot (37 Celsius, 1 hour):")
data = tatapov.annealing_data["37C"][enzyme_tatapov_lookup[self.enzyme]]
subset = tatapov.data_subset(data, self.overhang_input, add_reverse=True)
self.ax, _ = tatapov.plot_data(subset, figwidth=figwidth, plot_color="Reds")
self.ax.figure.tight_layout()
self.ax.plot()
def evaluate_annealing(self):
"""Evaluate weakly anneals, self-misanneals and misanneals between overhangs.
Used in `inspect_overhangs()`.
"""
# Prepare data:
data = tatapov.annealing_data["37C"][enzyme_tatapov_lookup[self.enzyme]]
subset = tatapov.data_subset(data, self.overhang_input, add_reverse=True)
# WEAK ANNEALS
# See cutoff 400 in Pryor et al. Figure 2.
self.weak_anneals_list = [
[oh.overhang, oh.overhang_rc]
for oh in self.overhangs
if subset[oh.overhang][oh.overhang_rc] < 400
]
# Convert to text
self.weak_anneals = [
oh_pair[0] + "/" + oh_pair[1] for oh_pair in self.weak_anneals_list
]
self.weak_anneals = "; ".join(self.weak_anneals)
if not self.weak_anneals == "":
self.has_warnings = True
# SELF-MISANNEALS
self.self_misanneals_list = [
[oh.overhang, oh.overhang_rc]
for oh in self.overhangs
if subset[oh.overhang][oh.overhang] != 0
or subset[oh.overhang_rc][oh.overhang_rc] != 0
]
self.self_misanneals = [
oh_pair[0] + "/" + oh_pair[1] for oh_pair in self.self_misanneals_list
]
self.self_misanneals = "; ".join(self.self_misanneals)
if not self.self_misanneals == "":
self.has_warnings = True
# MISANNEALS
self.misanneals_list = []
for oh1, oh2 in itertools.combinations(self.overhangs, 2):
# 10 below is a good cutoff for misannealing pairs
if (
subset.loc[
[oh1.overhang, oh1.overhang_rc], [oh2.overhang, oh2.overhang_rc]
]
> 10
).any(axis=None):
# oh and reverse complement, in a list with its misannealing pair
self.misanneals_list += [
[[oh1.overhang, oh1.overhang_rc], [oh2.overhang, oh2.overhang_rc]]
]
# Create a text from the 4 overhangs, for the report:
self.misanneals = [
misannealing_pair[0][0]
+ "/"
+ misannealing_pair[0][1]
+ " ~ "
+ misannealing_pair[1][0]
+ "/"
+ misannealing_pair[1][1]
for misannealing_pair in self.misanneals_list
]
self.misanneals = "; ".join(self.misanneals)
if not self.misanneals == "":
self.has_warnings = True
def find_similar_overhangs(self, difference_threshold=None):
"""Find overhangs that differ in fewer nucleotides than the threshold.
**Parameters**
**difference_threshold**
> Acceptable number of matching nucleotides in an overhang pair (`int`).
Overhang pairs with fewer differences are marked as similar. Defaults to 0.
"""
if difference_threshold is None:
difference_threshold = 0
similar_overhangs = ""
for oh1, oh2 in itertools.combinations(self.overhangs, 2):
if get_overhang_distance(oh1, oh2) < difference_threshold:
similar_overhangs += (
oh1.overhang
+ "/"
+ oh1.overhang_rc
+ " ~ "
+ oh2.overhang
+ "/"
+ oh2.overhang_rc
+ " ; "
)
if similar_overhangs == "":
similar_overhangs = (
"No overhangs (including reverse complements) "
"differ by fewer than %d nucleotides." % difference_threshold
)
else:
similar_overhangs = (
"These overhang pairs (including reverse complements) have fewer than "
"%d differences: " % difference_threshold + similar_overhangs
)
return similar_overhangs
def find_perfect_subset(self):
"""Find a better overhang set by removing bad overhang interactions.
Bad interactions are weak anneals, self-misanneals and misanneals.
"""
self.inspect_overhangs(make_plot=False)
# REMOVE WEAK
oh_to_remove = [oh for oh_pair in self.weak_anneals_list for oh in oh_pair]
self.subset = set(self.overhang_input) - set(oh_to_remove)
# REMOVE SELF-MISANNEALING
oh_to_remove = [oh for oh_pair in self.self_misanneals_list for oh in oh_pair]
self.subset = set(self.subset) - set(oh_to_remove)
# REMOVE MISANNEALING
compatible_overhangs = []
misanneals_for_loop = [pair[0] + pair[1] for pair in self.misanneals_list]
for oh1, oh2 in itertools.combinations(self.subset, 2):
add_oh = True
for pair in misanneals_for_loop:
if oh1 in pair and oh2 in pair:
add_oh = False
break
if add_oh:
compatible_overhangs += [(oh1, oh2)]
graph = networkx.Graph(compatible_overhangs)
max_clique, clique_size = networkx.max_weight_clique(graph, None)
self.subset = max_clique
print("Overhangs in subset: " + str(self.subset))
print("Number of overhangs in subset: " + str(clique_size))
# Visualize subset:
figwidth = len(self.subset)
print(self.enzyme, "Tatapov plot (37 Celsius, 1 hour):")
data = tatapov.annealing_data["37C"][enzyme_tatapov_lookup[self.enzyme]]
subset = tatapov.data_subset(data, self.subset, add_reverse=True)
self.ax, _ = tatapov.plot_data(subset, figwidth=figwidth, plot_color="Reds")
self.ax.figure.tight_layout()
self.ax.plot()
Methods
evaluate_annealing
def evaluate_annealing(
self
)
Evaluate weakly anneals, self-misanneals and misanneals between overhangs.
Used in inspect_overhangs()
.
View Source
def evaluate_annealing(self):
"""Evaluate weakly anneals, self-misanneals and misanneals between overhangs.
Used in `inspect_overhangs()`.
"""
# Prepare data:
data = tatapov.annealing_data["37C"][enzyme_tatapov_lookup[self.enzyme]]
subset = tatapov.data_subset(data, self.overhang_input, add_reverse=True)
# WEAK ANNEALS
# See cutoff 400 in Pryor et al. Figure 2.
self.weak_anneals_list = [
[oh.overhang, oh.overhang_rc]
for oh in self.overhangs
if subset[oh.overhang][oh.overhang_rc] < 400
]
# Convert to text
self.weak_anneals = [
oh_pair[0] + "/" + oh_pair[1] for oh_pair in self.weak_anneals_list
]
self.weak_anneals = "; ".join(self.weak_anneals)
if not self.weak_anneals == "":
self.has_warnings = True
# SELF-MISANNEALS
self.self_misanneals_list = [
[oh.overhang, oh.overhang_rc]
for oh in self.overhangs
if subset[oh.overhang][oh.overhang] != 0
or subset[oh.overhang_rc][oh.overhang_rc] != 0
]
self.self_misanneals = [
oh_pair[0] + "/" + oh_pair[1] for oh_pair in self.self_misanneals_list
]
self.self_misanneals = "; ".join(self.self_misanneals)
if not self.self_misanneals == "":
self.has_warnings = True
# MISANNEALS
self.misanneals_list = []
for oh1, oh2 in itertools.combinations(self.overhangs, 2):
# 10 below is a good cutoff for misannealing pairs
if (
subset.loc[
[oh1.overhang, oh1.overhang_rc], [oh2.overhang, oh2.overhang_rc]
]
> 10
).any(axis=None):
# oh and reverse complement, in a list with its misannealing pair
self.misanneals_list += [
[[oh1.overhang, oh1.overhang_rc], [oh2.overhang, oh2.overhang_rc]]
]
# Create a text from the 4 overhangs, for the report:
self.misanneals = [
misannealing_pair[0][0]
+ "/"
+ misannealing_pair[0][1]
+ " ~ "
+ misannealing_pair[1][0]
+ "/"
+ misannealing_pair[1][1]
for misannealing_pair in self.misanneals_list
]
self.misanneals = "; ".join(self.misanneals)
if not self.misanneals == "":
self.has_warnings = True
find_perfect_subset
def find_perfect_subset(
self
)
Find a better overhang set by removing bad overhang interactions.
Bad interactions are weak anneals, self-misanneals and misanneals.
View Source
def find_perfect_subset(self):
"""Find a better overhang set by removing bad overhang interactions.
Bad interactions are weak anneals, self-misanneals and misanneals.
"""
self.inspect_overhangs(make_plot=False)
# REMOVE WEAK
oh_to_remove = [oh for oh_pair in self.weak_anneals_list for oh in oh_pair]
self.subset = set(self.overhang_input) - set(oh_to_remove)
# REMOVE SELF-MISANNEALING
oh_to_remove = [oh for oh_pair in self.self_misanneals_list for oh in oh_pair]
self.subset = set(self.subset) - set(oh_to_remove)
# REMOVE MISANNEALING
compatible_overhangs = []
misanneals_for_loop = [pair[0] + pair[1] for pair in self.misanneals_list]
for oh1, oh2 in itertools.combinations(self.subset, 2):
add_oh = True
for pair in misanneals_for_loop:
if oh1 in pair and oh2 in pair:
add_oh = False
break
if add_oh:
compatible_overhangs += [(oh1, oh2)]
graph = networkx.Graph(compatible_overhangs)
max_clique, clique_size = networkx.max_weight_clique(graph, None)
self.subset = max_clique
print("Overhangs in subset: " + str(self.subset))
print("Number of overhangs in subset: " + str(clique_size))
# Visualize subset:
figwidth = len(self.subset)
print(self.enzyme, "Tatapov plot (37 Celsius, 1 hour):")
data = tatapov.annealing_data["37C"][enzyme_tatapov_lookup[self.enzyme]]
subset = tatapov.data_subset(data, self.subset, add_reverse=True)
self.ax, _ = tatapov.plot_data(subset, figwidth=figwidth, plot_color="Reds")
self.ax.figure.tight_layout()
self.ax.plot()
find_similar_overhangs
def find_similar_overhangs(
self,
difference_threshold=None
)
Find overhangs that differ in fewer nucleotides than the threshold.
Parameters
difference_threshold
Acceptable number of matching nucleotides in an overhang pair (
int
). Overhang pairs with fewer differences are marked as similar. Defaults to 0.
View Source
def find_similar_overhangs(self, difference_threshold=None):
"""Find overhangs that differ in fewer nucleotides than the threshold.
**Parameters**
**difference_threshold**
> Acceptable number of matching nucleotides in an overhang pair (`int`).
Overhang pairs with fewer differences are marked as similar. Defaults to 0.
"""
if difference_threshold is None:
difference_threshold = 0
similar_overhangs = ""
for oh1, oh2 in itertools.combinations(self.overhangs, 2):
if get_overhang_distance(oh1, oh2) < difference_threshold:
similar_overhangs += (
oh1.overhang
+ "/"
+ oh1.overhang_rc
+ " ~ "
+ oh2.overhang
+ "/"
+ oh2.overhang_rc
+ " ; "
)
if similar_overhangs == "":
similar_overhangs = (
"No overhangs (including reverse complements) "
"differ by fewer than %d nucleotides." % difference_threshold
)
else:
similar_overhangs = (
"These overhang pairs (including reverse complements) have fewer than "
"%d differences: " % difference_threshold + similar_overhangs
)
return similar_overhangs
inspect_overhangs
def inspect_overhangs(
self,
make_plot=True
)
Inspect compatibility of overhangs and detect potential errors in the set.
View Source
def inspect_overhangs(self, make_plot=True):
"""Inspect compatibility of overhangs and detect potential errors in the set."""
# DUPLICATES
if self.has_duplicates:
print("Incorrect set! Duplicate overhangs")
self.has_errors = True
# PALINDROMIC
self.palindromic_oh = []
self.palindromic_oh += [
overhang.overhang for overhang in self.overhangs if overhang.is_palindromic
]
if len(self.palindromic_oh) != 0:
self.palindromic_text = "Palindromic overhang(s): " + "; ".join(
self.palindromic_oh
)
print(("Incorrect set! " + self.palindromic_text))
self.has_errors = True
# REVERSE COMPLEMENT
nonpalindromic_oh = set(self.overhang_input) - set(self.palindromic_oh)
nonpalindromic_oh_rc = {reverse_complement(oh) for oh in nonpalindromic_oh}
rc_oh = nonpalindromic_oh & nonpalindromic_oh_rc
if rc_oh:
self.has_rc_error = True
self.rc_error_text = (
"Nonpalindromic overhang(s) with reverse complement: "
+ "; ".join(rc_oh)
)
print(("Incorrect set! " + self.rc_error_text))
self.has_errors = True
else:
self.has_rc_error = False
# SIMILAR OVERHANGS -- we do not consider it as a flaw
self.similar_overhangs = self.find_similar_overhangs()
# SET SIZE
# Based on Pryor et al., PLoS ONE (2020):
if self.overhang_length == 3: # check overhang length on first one
n = 10
if len(self.overhang_input) > n:
self.set_size_text = (
"Assembly fidelity significantly decreases when using "
+ "more than %d overhangs." % n
) # text used in report
print("Warning! " + self.set_size_text)
elif self.overhang_length == 4:
n = 20
if len(self.overhang_input) > n:
self.set_size_text = (
"Assembly fidelity significantly decreases when using "
+ "more than %d overhangs." % n
)
print("Warning! " + self.set_size_text)
else:
self.set_size_text = ""
# MISANNEALING
self.evaluate_annealing() # also sets `has_warnings`
# Tatapov plots:
if make_plot:
figwidth = len(self.overhang_input)
print(self.enzyme, "Tatapov plot (37 Celsius, 1 hour):")
data = tatapov.annealing_data["37C"][enzyme_tatapov_lookup[self.enzyme]]
subset = tatapov.data_subset(data, self.overhang_input, add_reverse=True)
self.ax, _ = tatapov.plot_data(subset, figwidth=figwidth, plot_color="Reds")
self.ax.figure.tight_layout()
self.ax.plot()