From d0f6ab370d5e0dd953567692cbb755d6fb4732ea Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 30 Nov 2023 20:56:46 -0800 Subject: [PATCH] fixed bug that produced wrong overhang in linear, non-directional, single cut reactions. (#408) * fixed bug that produced wrong overhang in linear, non-directional, single cut reactions. --- CHANGELOG.md | 25 +------------------------ clone/clone.go | 10 +++++++++- clone/clone_test.go | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5337e311..773e1262a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,28 +7,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Added -- Alternative start codons can now be used in the `synthesis/codon` DNA -> protein translation package (#305) -- Added a parser and writer for the `pileup` sequence alignment format (#329) -- Added statistics to the `synthesis/codon` package (keeping track of the observed start codon occurrences in a translation table) (#350) -- Added option to fragmenter to fragment with only certain overhangs (#387) - - - - ### Fixed -- `fastq` parser no longer becomes de-aligned when reading (#325) -- `fastq` now handles optionals correctly (#323) -- No more data race in GoldenGate (#276) - -### Breaking -- CutWithEnzymeByName is now a receiver of EnzymeManager. GoldenGate now takes an Enzyme instead of the name of an enzyme. -This is an effort to remove dependence on some package level global state and build some flexibility managing enzymes -over the lifetime of the program. -- Enzyme.OverhangLen is now named Enzyme.OverhangLength - -## [0.26.0] - 2023-07-22 -Oops, we weren't keeping a changelog before this tag! - -[unreleased]: https://github.com/TimothyStiles/poly/compare/v0.26.0...main -[0.26.0]: https://github.com/TimothyStiles/poly/releases/tag/v0.26.0 +- Fixed bug that produced wrong overhang in linear, non-directional, single cut reactions. #408 \ No newline at end of file diff --git a/clone/clone.go b/clone/clone.go index cc9939ba1..4b9096bf8 100644 --- a/clone/clone.go +++ b/clone/clone.go @@ -188,7 +188,15 @@ func CutWithEnzyme(part Part, directional bool, enzyme Enzyme) []Fragment { // In the case of a single cut in a linear sequence, we get two fragments with only 1 stick end fragmentSequence1 := sequence[overhangs[0].Position+overhangs[0].Length:] fragmentSequence2 := sequence[:overhangs[0].Position] - overhangSequence := sequence[overhangs[0].Position : overhangs[0].Position+overhangs[0].Length] + + var overhangSequence string + + if len(forwardOverhangs) > 0 { + overhangSequence = sequence[overhangs[0].Position : overhangs[0].Position+overhangs[0].Length] + } else { + overhangSequence = sequence[overhangs[0].Position-overhangs[0].Length : overhangs[0].Position] + } + fragments = append(fragments, Fragment{fragmentSequence1, overhangSequence, ""}) fragments = append(fragments, Fragment{fragmentSequence2, "", overhangSequence}) return fragments diff --git a/clone/clone_test.go b/clone/clone_test.go index fb5ade198..ce59a7780 100644 --- a/clone/clone_test.go +++ b/clone/clone_test.go @@ -96,6 +96,43 @@ func TestCutWithEnzyme(t *testing.T) { } } +func TestCutWithEnzymeRegression(t *testing.T) { + sequence := "AGCTGCTGTTTAAAGCTATTACTTTGAGACC" // this is a real sequence I came across that was causing problems + + part := Part{sequence, false} + + // get enzymes with enzyme manager + enzymeManager := NewEnzymeManager(GetBaseRestrictionEnzymes()) + bsa1, err := enzymeManager.GetEnzymeByName("BsaI") + if err != nil { + t.Errorf("Error when getting Enzyme. Got error: %s", err) + } + + // cut with BsaI + fragments := CutWithEnzyme(part, false, bsa1) + + // check that the fragments are correct + if len(fragments) != 2 { + t.Errorf("Expected 2 fragments, got: %d", len(fragments)) + } + + if fragments[0].ForwardOverhang != "ACTT" { + t.Errorf("Expected forward overhang to be ACTT, got: %s", fragments[0].ForwardOverhang) + } + + if fragments[0].ReverseOverhang != "" { + t.Errorf("Expected reverse overhang to be GAGT, got: %s", fragments[0].ReverseOverhang) + } + + if fragments[1].ForwardOverhang != "" { + t.Errorf("Expected forward overhang to be empty, got: %s", fragments[1].ForwardOverhang) + } + + if fragments[1].ReverseOverhang != "ACTT" { + t.Errorf("Expected reverse overhang to be GAGT, got: %s", fragments[1].ReverseOverhang) + } +} + func TestCircularLigate(t *testing.T) { // The following tests for complementing overhangs. Specific, this line: // newSeed := Fragment{seedFragment.Sequence + seedFragment.ReverseOverhang + ReverseComplement(newFragment.Sequence), seedFragment.ForwardOverhang, ReverseComplement(newFragment.ForwardOverhang)}