From 04742ab252cca919668049cda9f90566c2638d87 Mon Sep 17 00:00:00 2001 From: BjornFJohansson Date: Tue, 17 Oct 2023 18:37:03 +0100 Subject: [PATCH] bugfixes --- src/pydna/assembly.py | 9 ++++--- src/pydna/design.py | 7 +++-- tests/test_module_assembly.py | 51 +++++++++++++++++++++++++++++++++++ tests/test_module_design.py | 9 +++++++ 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/src/pydna/assembly.py b/src/pydna/assembly.py index 6e36e450..2e39618c 100644 --- a/src/pydna/assembly.py +++ b/src/pydna/assembly.py @@ -245,8 +245,8 @@ def __init__(self, frags=None, limit=25, algorithm=common_sub_strings): if start1 <= ft.location.start and start2 + G.nodes[node2]["length"] >= ft.location.end ] - for feat in feats: - feat.location += -start1 + # for feat in feats: + # feat.location += -start1 G.add_edge( node1, @@ -304,10 +304,11 @@ def assemble_linear(self, start=None, end=None, max_nodes=None): node, "end", piece=slice(start, len(lastfragment["mixed"])), - features=[f for f in lastfragment["features"] if start <= f.location.end], + features=[f for f in lastfragment["features"] if start <= f.location.start], seq=lastfragment["mixed"], name=lastfragment["name"], ) + # breakpoint() # add edges from nodes in last reverse complement sequence to "end_rc" lastfragmentrc = self.rcfragments[lastfragment["mixed"]] @@ -316,7 +317,7 @@ def assemble_linear(self, start=None, end=None, max_nodes=None): node, "end_rc", piece=slice(start, len(lastfragmentrc["mixed"])), - features=[f for f in lastfragmentrc["features"] if start <= f.location.end], + features=[f for f in lastfragmentrc["features"] if start <= f.location.start], seq=lastfragmentrc["mixed"], name=lastfragmentrc["name"], ) diff --git a/src/pydna/design.py b/src/pydna/design.py index 6c0ead34..84f4dd56 100755 --- a/src/pydna/design.py +++ b/src/pydna/design.py @@ -18,7 +18,7 @@ import math as _math import os as _os import copy as _copy - +from pydna.amplicon import Amplicon as _Amplicon from pydna.amplify import Anneal as _Anneal from pydna.amplify import pcr as _pcr from pydna.dseqrecord import Dseqrecord as _Dseqrecord @@ -121,11 +121,14 @@ def design(target_tm, template): """returns a string""" tmp = 0 length = limit + tlen = len(template) p = str(template.seq[:length]) while tmp < target_tm: length += 1 p = str(template.seq[:length]) tmp = tm_func(p) + if length >= tlen: + break ps = p[:-1] tmps = tm_func(str(ps)) _module_logger.debug(((p, tmp), (ps, tmps))) @@ -179,7 +182,7 @@ def design(target_tm, template): ampl = _Anneal((fp, rp), template, limit=limit) - prod = ampl.products[0] + prod = ampl.products[0] if ampl.products else _Amplicon("") if len(ampl.products) > 1: import warnings as _warnings diff --git a/tests/test_module_assembly.py b/tests/test_module_assembly.py index feaa6ae7..4e2c8bf6 100644 --- a/tests/test_module_assembly.py +++ b/tests/test_module_assembly.py @@ -737,6 +737,57 @@ def test_marker_replacement_on_plasmid(monkeypatch): assert pMEC1135.features[-1].extract(pMEC1135).seq == candidate.features[-1].extract(candidate).seq +def test_linear_with_annotations2(monkeypatch): + # Thanks to James Bagley for finding this bug + # https://github.com/JamesBagley + from pydna._pretty import pretty_str + from pydna.assembly import Assembly + from pydna.dseqrecord import Dseqrecord + + a = Dseqrecord("acgatgctatactgtgCCNCCtgtgctgtgctcta") + a.add_feature(0, 10, label='a_feat') + a_feat_seq = a.features[0].extract(a) + # 12345678901234 + b = Dseqrecord("tgtgctgtgctctaTTTTTTTtattctggctgtatcCCCCCC") + b.add_feature(0, 10, label='b_feat') + b_feat_seq = b.features[0].extract(b) + + # 123456789012345 + c = Dseqrecord("GtattctggctgtatcGGGGGtacgatgctatactgtg") + c.add_feature(0, 10, label='c_feat') + c_feat_seq = c.features[0].extract(c) + + feature_sequences = {'a_feat': a_feat_seq, 'b_feat': b_feat_seq, 'c_feat': c_feat_seq} + + a.name = "aaa" # 1234567890123456 + b.name = "bbb" + c.name = "ccc" + asm = Assembly((a, b, c), limit=14) + x = asm.assemble_linear()[0] + # print(x.features) + # print(x) + answer = 'aaa|14\n \\/\n /\\\n 14|bbb|15\n \\/\n /\\\n 15|ccc' + + assert x.figure() == answer.strip() + answer = 'acgatgctatactgtgCCNCCtgtgctgtgctcta\n TGTGCTGTGCTCTA\n tgtgctgtgctctaTTTTTTTtattctggctgtatc\n TATTCTGGCTGTATC\n tattctggctgtatcGGGGGtacgatgctatactgtg\n' + assert x.detailed_figure() + for feat in x.features: + try: + assert feat.extract(x).seq == feature_sequences[feat.qualifiers['label']].seq + except AssertionError: + print(feat.qualifiers['label']) + print(feat.extract(x).seq, 'extracted feat') + print(feature_sequences[feat.qualifiers['label']].seq, 'original feat') + assert feat.extract(x).seq == feature_sequences[feat.qualifiers['label']].seq + + +# acgatgctatactgtgCCNCCtgtgctgtgctcta +# TGTGCTGTGCTCTA +# tgtgctgtgctctaTTTTTTTtattctggctgtatcCCCCCC +# TATTCTGGCTGTATC +# GtattctggctgtatcGGGGGtacgatgctatactgtg + + if __name__ == "__main__": # pytest.main([__file__, "-x", "-vv", "-s"]) pytest.main([__file__, "-x", "-vv", "-s", "--profile"]) diff --git a/tests/test_module_design.py b/tests/test_module_design.py index 477a7a0e..86d4f735 100755 --- a/tests/test_module_design.py +++ b/tests/test_module_design.py @@ -300,5 +300,14 @@ def test_circular_assembly_fragments2(): ) +def test_too_short_template(): + from pydna.amplicon import Amplicon + from pydna.design import primer_design + from pydna.dseqrecord import Dseqrecord + + fragment = Dseqrecord("GCCACCATGG") + assert primer_design(fragment) == Amplicon("") + + if __name__ == "__main__": pytest.cmdline.main([__file__, "-v", "-s"])