Skip to content

Commit

Permalink
Merge branch 'main' of github.com:Koeng101/poly
Browse files Browse the repository at this point in the history
  • Loading branch information
Koeng101 committed Dec 7, 2023
2 parents b2efa8c + 38185e9 commit da9e61d
Show file tree
Hide file tree
Showing 11 changed files with 758 additions and 80 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@ 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)
- GoldenGates with methylated sequences using lowercase letters (#391)
- Generic parser is now implemented across all parsers for consistent interactions. [(#339)](https://github.com/TimothyStiles/poly/issues/339)
- Alternative start codons can now be used in the `synthesis/codon` DNA -> protein translation package [(#305)](https://github.com/TimothyStiles/poly/issues/305)
- Added a parser and writer for the `pileup` sequence alignment format [(#329)](https://github.com/TimothyStiles/poly/issues/329)
- Created copy methods for Feature and Location to address concerns raised by [(#342)](https://github.com/TimothyStiles/poly/issues/342)
- Created new methods to convert polyjson -> genbank.
- Created new `Feature.StoreSequence` method to enable [(#388)](https://github.com/TimothyStiles/poly/issues/388)
- Added seqhash v2 (#398)

### Changed
- **Breaking**: Genbank parser uses new custom multimap for `Feature.Attributes`, which allows for duplicate keys. This changes the type of Features.Attributes from `map[string]string` to `MultiMap[string, string]`, an alias for `map[string]string` defined in `multimap.go`. [(#383)](https://github.com/TimothyStiles/poly/issues/383)
Expand All @@ -25,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Adds functional test and fix for [(#313)](https://github.com/TimothyStiles/poly/issues/313).
- In addition to expanding the set of genbank files which can be validly parsed, the parser is more vocal when it encounters unusual syntax in the "feature" section. This "fail fast" approach is better as there were cases where inputs triggered a codepath which would neither return a valid Genbank object nor an error, and should help with debugging.
- Fixed bug that produced wrong overhang in linear, non-directional, single cut reactions. #408
>>>>>>> main
## [0.26.0] - 2023-07-22
Oops, we weren't keeping a changelog before this tag!
Expand Down
39 changes: 28 additions & 11 deletions clone/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ in a single tube and that is extraordinarily efficient (up to 50 parts) and is p
for new modular DNA part toolkits. Users can easily simulate GoldenGate assembly reactions
with just their input fragments + the enzyme name.
Unlike many other GoldenGate simulators, we support simulating GoldenGate with
methylated DNA sequences, which are represented as lowercased sequences in user
inputted sequences. Normally, this can be turned off, but can be used in the
special case of recursive GoldenGate reactions.
Let's build some DNA!
# Keoni
Expand Down Expand Up @@ -113,16 +118,17 @@ Base cloning functions begin here.

// CutWithEnzymeByName cuts a given sequence with an enzyme represented by the
// enzyme's name. It is a convenience wrapper around CutWithEnzyme that
// allows us to specify the enzyme by name.
func (enzymeManager EnzymeManager) CutWithEnzymeByName(part Part, directional bool, name string) ([]Fragment, error) {
// allows us to specify the enzyme by name. Set methylated flag to true if
// there is lowercase methylated DNA as part of the sequence.
func (enzymeManager EnzymeManager) CutWithEnzymeByName(part Part, directional bool, name string, methylated bool) ([]Fragment, error) {
// Get the enzyme from the enzyme map
enzyme, err := enzymeManager.GetEnzymeByName(name)
if err != nil {
// Return an error if there was an error
return []Fragment{}, err
}
// Cut the sequence with the enzyme
return CutWithEnzyme(part, directional, enzyme), nil
return CutWithEnzyme(part, directional, enzyme, methylated), nil
}

// GetEnzymeByName gets the enzyme by it's name. If the enzyme manager does not
Expand All @@ -135,13 +141,21 @@ func (enzymeManager EnzymeManager) GetEnzymeByName(name string) (Enzyme, error)
}

// CutWithEnzyme cuts a given sequence with an enzyme represented by an Enzyme struct.
func CutWithEnzyme(part Part, directional bool, enzyme Enzyme) []Fragment {
// If there is methylated parts of the target DNA, set the "methylated" flag to
// true and lowercase ONLY methylated DNA.
func CutWithEnzyme(part Part, directional bool, enzyme Enzyme, methylated bool) []Fragment {
var fragmentSequences []string
var sequence string

// Setup circular sequences
sequence := part.Sequence
if part.Circular {
sequence = strings.ToUpper(part.Sequence + part.Sequence)
} else {
sequence = strings.ToUpper(part.Sequence)
sequence = sequence + sequence
}

// If unmethylated, set everything to uppercase so that the enzyme regex
// works on all the sequence
if !methylated {
sequence = strings.ToUpper(sequence)
}

// Check for palindromes
Expand Down Expand Up @@ -343,11 +357,12 @@ Specific cloning functions begin here.
******************************************************************************/

// GoldenGate simulates a GoldenGate cloning reaction. As of right now, we only
// support BsaI, BbsI, BtgZI, and BsmBI.
func GoldenGate(sequences []Part, cuttingEnzyme Enzyme) (openConstructs []string, infiniteLoops []string) {
// support BsaI, BbsI, BtgZI, and BsmBI. Set methylated flag to true if there
// is lowercase methylated DNA as part of the sequence.
func GoldenGate(sequences []Part, cuttingEnzyme Enzyme, methylated bool) (openConstructs []string, infiniteLoops []string) {
var fragments []Fragment
for _, sequence := range sequences {
newFragments := CutWithEnzyme(sequence, true, cuttingEnzyme)
newFragments := CutWithEnzyme(sequence, true, cuttingEnzyme, methylated)
fragments = append(fragments, newFragments...)
}
openconstructs, infiniteloops := CircularLigate(fragments)
Expand All @@ -360,5 +375,7 @@ func GetBaseRestrictionEnzymes() []Enzyme {
{"BsaI", regexp.MustCompile("GGTCTC"), regexp.MustCompile("GAGACC"), 1, 4, "GGTCTC"},
{"BbsI", regexp.MustCompile("GAAGAC"), regexp.MustCompile("GTCTTC"), 2, 4, "GAAGAC"},
{"BtgZI", regexp.MustCompile("GCGATG"), regexp.MustCompile("CATCGC"), 10, 4, "GCGATG"},
{"PaqCI", regexp.MustCompile("CACCTGC"), regexp.MustCompile("GCAGGTG"), 4, 4, "CACCTGC"},
{"BsmBI", regexp.MustCompile("CGTCTC"), regexp.MustCompile("GAGACG"), 1, 4, "CGTCTC"},
}
}
37 changes: 27 additions & 10 deletions clone/clone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var popen = Part{"TAACTATCGTCTTGAGTCCAACCCGGTAAGACACGACTTATCGCCACTGGCAGCAGCCACTG

func TestCutWithEnzymeByName(t *testing.T) {
enzymeManager := NewEnzymeManager(GetBaseRestrictionEnzymes())
_, err := enzymeManager.CutWithEnzymeByName(popen, true, "EcoFake")
_, err := enzymeManager.CutWithEnzymeByName(popen, true, "EcoFake", false)
if err == nil {
t.Errorf("CutWithEnzymeByName should have failed when looking for fake restriction enzyme EcoFake")
}
Expand All @@ -25,7 +25,7 @@ func TestCutWithEnzyme(t *testing.T) {
// Test case of `<-bsaiComplement bsai-> <-bsaiComplement bsai->` where bsaI cuts off of a linear sequence. This tests the line:
// if !sequence.Circular && (overhangSet[len(overhangSet)-1].Position+enzyme.EnzymeSkip+enzyme.EnzymeOverhangLen > len(sequence))
sequence = Part{"ATATATA" + bsaiComplement + bsai + "ATGCATCGATCGACTAGCATG" + bsaiComplement + bsai[:8], false}
fragment, err := enzymeManager.CutWithEnzymeByName(sequence, true, "BsaI")
fragment, err := enzymeManager.CutWithEnzymeByName(sequence, true, "BsaI", false)
if err != nil {
t.Errorf("CutWithEnzyme should not have failed on test(1). Got error: %s", err)
}
Expand All @@ -39,7 +39,7 @@ func TestCutWithEnzyme(t *testing.T) {
// test(2)
// Now if we take the same sequence and circularize it, we get a different result
sequence.Circular = true
fragment, err = enzymeManager.CutWithEnzymeByName(sequence, true, "BsaI")
fragment, err = enzymeManager.CutWithEnzymeByName(sequence, true, "BsaI", false)
if err != nil {
t.Errorf("CutWithEnzyme should not have failed on test(2). Got error: %s", err)
}
Expand All @@ -57,7 +57,7 @@ func TestCutWithEnzyme(t *testing.T) {
// directionality flag to false. This tests the line:
// if len(overhangs) == 1 && !directional && !sequence.Circular
sequence = Part{"ATATATATATATATAT" + bsai + "GCGCGCGCGCGCGCGCGCGC", false}
fragment, err = enzymeManager.CutWithEnzymeByName(sequence, false, "BsaI")
fragment, err = enzymeManager.CutWithEnzymeByName(sequence, false, "BsaI", false)
if err != nil {
t.Errorf("CutWithEnzyme should not have failed on test(3). Got error: %s", err)
}
Expand All @@ -73,7 +73,7 @@ func TestCutWithEnzyme(t *testing.T) {
// tests the line:
// if len(overhangs) == 2 && !directional && sequence.Circular
sequence.Circular = true
fragment, err = enzymeManager.CutWithEnzymeByName(sequence, false, "BsaI")
fragment, err = enzymeManager.CutWithEnzymeByName(sequence, false, "BsaI", false)
if err != nil {
t.Errorf("CutWithEnzyme should not have failed on test(4). Got error: %s", err)
}
Expand All @@ -87,7 +87,7 @@ func TestCutWithEnzyme(t *testing.T) {
// test(5)
// This tests if we have a fragment where we do not care about directionality
// but have more than 1 cut site in our fragment. We can use pOpen for this.
fragment, err = enzymeManager.CutWithEnzymeByName(popen, false, "BbsI")
fragment, err = enzymeManager.CutWithEnzymeByName(popen, false, "BbsI", false)
if err != nil {
t.Errorf("CutWithEnzyme should not have failed on test(5). Got error: %s", err)
}
Expand Down Expand Up @@ -183,7 +183,7 @@ func TestSignalKilledGoldenGate(t *testing.T) {
t.Errorf("Error when getting Enzyme. Got error: %s", err)
}

clones, loopingClones := GoldenGate(fragments, bbsI)
clones, loopingClones := GoldenGate(fragments, bbsI, false)
if len(clones) != 1 {
t.Errorf("There should be 1 output Got: %d", len(clones))
}
Expand All @@ -210,15 +210,15 @@ func TestPanicGoldenGate(t *testing.T) {
t.Errorf("Error when getting Enzyme. Got error: %s", err)
}

_, _ = GoldenGate(fragments, bbsI)
_, _ = GoldenGate(fragments, bbsI, false)
}

func TestCircularCutRegression(t *testing.T) {
enzymeManager := NewEnzymeManager(GetBaseRestrictionEnzymes())
// This used to error with 0 fragments since the BsaI cut site is on the other
// side of the origin from its recognition site.
plasmid1 := Part{"AAACTACAAGACCCGCGCCGAGGTGAAGTTCGAGGGCGACACCCTGGTGAACCGCATCGAGCTGAAGGGCATCGACTTCAAGGAGGACGGCAACATCCTGGGGCACAAGCTGGAGTACAACTACAACAGCCACAACGTCTATATCATGGCCGACAAGCAGAAGAACGGCATCAAGGTGAACTTCAAGATCCGCCACAACATCGAGGACGGCAGCCGAGaccaagtcgcggccgcgaggtgtcaatcgtcggagtagggataacagggtaatccgctgagcaataactagcataaccccttggggcctctaaacgggtcttgaggggttttttgcatggtcatagctgtttcctgttacgccccgccctgccactcgtcgcagtactgttgtaattcattaagcattctgccgacatggaagccatcacaaacggcatgatgaacctgaatcgccagcggcatcagcaccttgtcgccttgcgtataatatttgcccatggtgaaaacgggggcgaagaagttgtccatattggccacgtttaaatcaaaactggtgaaactcacccagggattggctgacacgaaaaacatattctcaataaaccctttagggaaataggccaggttttcaccgtaacacgccacatcttgcgaatatatgtgtagaaactgccggaaatcgtcgtggtattcactccagagggatgaaaacgtttcagtttgctcatggaaaacggtgtaacaagggtgaacactatcccatatcaccagctcaccatccttcattgccatacgaaattccggatgagcattcatcaggcgggcaagaatgtgaataaaggccggataaaacttgtgcttatttttctttacggtctttaaaaaggccgtaatatccagctgaacggtctggttataggtacattgagcaactgactgaaatgcctcaaaatgttctttacgatgccattgggatatatcaacggtggtatatccagtgatttttttctccattttagcttccttagctcctgaaaatctcgataactcaaaaaatacgcccggtagtgatcttatttcattatggtgaaagttggaacctcttacgtgccgatcatttccataggctccgcccccctgacgagcatcacaaaaatcgacgctcaagtcagaggtggcgaaacccgacaggactataaagataccaggcgtttccccctggaagctccctcgtgcgctctcctgttccgaccctgccgcttaccggatacctgtccgcctttctcccttcgggaagcgtggcgctttctcatagctcacgctgtaggtatctcagttcggtgtaggtcgttcgctccaagctgggctgtgtgcacgaaccccccgttcagcccgaccgctgcgccttatccggtaactatcgtcttgagtccaacccggtaagacacgacttatcgccactggcagcagccactggtaacaggattagcagagcgaggtatgtaggcggtgctacagagttcttgaagtggtggcctaactacggctacactagaaggacagtatttggtatctgcgctctgctgaagccagttaccttcggaaaaagagttggtagctcttgatccggcaaacaaaccaccgctggtagcggtggtttttttgtttgcaagcagcagattacgcgcagaaaaaaaggatctcaagtaaaacgacggccagtagtcaaaagcctccgaccggaggcttttgacttggttcaggtggagtggcggccgcgacttgGTCTC", true}
newFragments, err := enzymeManager.CutWithEnzymeByName(plasmid1, true, "BsaI")
newFragments, err := enzymeManager.CutWithEnzymeByName(plasmid1, true, "BsaI", false)
if err != nil {
t.Errorf("Failed to cut: %s", err)
}
Expand All @@ -227,13 +227,30 @@ func TestCircularCutRegression(t *testing.T) {
}
}

func TestMethylatedGoldenGate(t *testing.T) {
pOpenV3Methylated := Part{"AGGGTAATGGTCTCTCGAGACcAAGTCGTCATAGCTGTTTCCTGAGAGCTTGGCAGGTGATGACACACATTAACAAATTTCGTGAGGAGTCTCCAGAAGAATGCCATTAATTTCCATAGGCTCCGCCCCCCTGACGAGCATCACAAAAATCGACGCTCAAGTCAGAGGTGGCGAAACCCGACAGGACTATAAAGATACCAGGCGTTTCCCCCTGGAAGCTCCCTCGTGCGCTCTCCTGTTCCGACCCTGCCGCTTACCGGATACCTGTCCGCCTTTCTCCCTTCGGGAAGCGTGGCGCTTTCTCATAGCTCACGCTGTAGGTATCTCAGTTCGGTGTAGGTCGTTCGCTCCAAGCTGGGCTGTGTGCACGAACCCCCCGTTCAGCCCGACCGCTGCGCCTTATCCGGTAACTATCGTCTTGAGTCCAACCCGGTAAGACACGACTTATCGCCACTGGCAGCAGCCACTGGTAACAGGATTAGCAGAGCGAGGTATGTAGGCGGTGCTACAGAGTTCTTGAAGTGGTGGCCTAACTACGGCTACACTAGAAGAACAGTATTTGGTATCTGCGCTCTGCTGAAGCCAGTTACCTTCGGAAAAAGAGTTGGTAGCTCTTGATCCGGCAAACAAACCACCGCTGGTAGCGGTGGTTTTTTTGTTTGCAAGCAGCAGATTACGCGCAGAAAAAAAGGATCTCAAGAAGGCCTACTATTAGCAACAACGATCCTTTGATCTTTTCTACGGGGTCTGACGCTCAGTGGAACGAAAACTCACGTTAAGGGATTTTGGTCATGAGATTATCAAAAAGGATCTTCACCTAGATCCTTTTAAATTAAAAATGAAGTTTTAAATCAATCTAAAGTATATATGAGTAAACTTGGTCTGACAGTTACCAATGCTTAATCAGTGAGGCACCTATCTCAGCGATCTGTCTATTTCGTTCATCCATAGTTGCCTGACTCCCCGTCGTGTAGATAACTACGATACGGGAGGGCTTACCATCTGGCCCCAGTGCTGCAATGATACCGCGAGAACCACGCTCACCGGCTCCAGATTTATCAGCAATAAACCAGCCAGCCGGAAGGGCCGAGCGCAGAAGTGGTCCTGCAACTTTATCCGCCTCCATCCAGTCTATTAATTGTTGCCGGGAAGCTAGAGTAAGTAGTTCGCCAGTTAATAGTTTGCGCAACGTTGTTGCCATTGCTACAGGCATCGTGGTGTCACGCTCGTCGTTTGGTATGGCTTCATTCAGCTCCGGTTCCCAACGATCAAGGCGAGTTACATGATCCCCCATGTTGTGCAAAAAAGCGGTTAGCTCCTTCGGTCCTCCGATCGTTGTCAGAAGTAAGTTGGCCGCAGTGTTATCACTCATGGTTATGGCAGCACTGCATAATTCTCTTACTGTCATGCCATCCGTAAGATGCTTTTCTGTGACTGGTGAGTACTCAACCAAGTCATTCTGAGAATAGTGTATGCGGCGACCGAGTTGCTCTTGCCCGGCGTCAATACGGGATAATACCGCGCCACATAGCAGAACTTTAAAAGTGCTCATCATTGGAAAACGTTCTTCGGGGCGAAAACTCTCAAGGATCTTACCGCTGTTGAGATCCAGTTCGATGTAACCCACTCGTGCACCCAACTGATCTTCAGCATCTTTTACTTTCACCAGCGTTTCTGGGTGAGCAAAAACAGGAAGGCAAAATGCCGCAAAAAAGGGAATAAGGGCGACACGGAAATGTTGAATACTCATACTCTTCCTTTTTCAATATTATTGAAGCATTTATCAGGGTTATTGTCTCATGAGCGGATACATATTTGAATGTATTTAGAAAAATAAACAAATAGGGGTTCCGCGCACCTGCACCAGTCAGTAAAACGACGGCCAGTGACTTgGTCTCGAGACCTAGGGATA", false}
frag1 := Part{"AGTTGCAGTATCTAACCCGCGGTCTCTGTCTCATCTCACTTAATCTTCTGTACTCTGAAGAGGAGTGGGAAATACCAAGAAAAACATCAAACTCGAATGATTTTCCCAAACCCCTACCACAAGATATTCATCAGCTGCGAGATGAGACCATACTGTAAGAACCACGCGGT", false}
frag2 := Part{"AGTTGCAGTATCTAACCCGCGGTCTCTGAGATAGGCTGATCAGGAGCAAGCTCGTACGAGAAGAAACAAAATGACAAAAAAAATCCTATACTATATAGGTTACAAATAAAAAAGTATCAAAAATGAAGCTGAGACCATACTGTAAGAACCACGCGGTAAAAGACGCTACG", false}
frag3 := Part{"AGTTGCAGTATCTAACCCGCGGTCTCTAAGCCTGCATCTCTCAGGCAAATGGCATTCTGACATCCTCTTGATTACGAGTGAGACCATACTGTAAGAACCACGCGGCTGAACCTCCAGCGGACTCAGTCGCGAAAATACTTACCAAAGGACCGAATTCACCGATCGAACGG", false}

enzymeManager := NewEnzymeManager(GetBaseRestrictionEnzymes())
bsai, err := enzymeManager.GetEnzymeByName("BsaI")
if err != nil {
t.Errorf("Error when getting Enzyme. Got error: %s", err)
}
clones, _ := GoldenGate([]Part{pOpenV3Methylated, frag1, frag2, frag3}, bsai, true)
if len(clones) != 1 {
t.Errorf("Should have gotten a single clone")
}
}

func benchmarkGoldenGate(b *testing.B, enzymeManager EnzymeManager, parts []Part) {
bbsI, err := enzymeManager.GetEnzymeByName("BbsI")
if err != nil {
b.Errorf("Error when getting Enzyme. Got error: %s", err)
}
for n := 0; n < b.N; n++ {
_, _ = GoldenGate(parts, bbsI)
_, _ = GoldenGate(parts, bbsI, false)
}
}

Expand Down
2 changes: 1 addition & 1 deletion clone/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func ExampleGoldenGate() {
if err != nil {
log.Fatalf("Something went wrong when trying to get the enzyme. Got error: %s", err)
}
Clones, _ := clone.GoldenGate([]clone.Part{fragment1, fragment2, popen}, bbsI)
Clones, _ := clone.GoldenGate([]clone.Part{fragment1, fragment2, popen}, bbsI, false)

fmt.Println(seqhash.RotateSequence(Clones[0]))
// Output: AAAAAAAGGATCTCAAGAAGGCCTACTATTAGCAACAACGATCCTTTGATCTTTTCTACGGGGTCTGACGCTCAGTGGAACGAAAACTCACGTTAAGGGATTTTGGTCATGAGATTATCAAAAAGGATCTTCACCTAGATCCTTTTAAATTAAAAATGAAGTTTTAAATCAATCTAAAGTATATATGAGTAAACTTGGTCTGACAGTTACCAATGCTTAATCAGTGAGGCACCTATCTCAGCGATCTGTCTATTTCGTTCATCCATAGTTGCCTGACTCCCCGTCGTGTAGATAACTACGATACGGGAGGGCTTACCATCTGGCCCCAGTGCTGCAATGATACCGCGAGAACCACGCTCACCGGCTCCAGATTTATCAGCAATAAACCAGCCAGCCGGAAGGGCCGAGCGCAGAAGTGGTCCTGCAACTTTATCCGCCTCCATCCAGTCTATTAATTGTTGCCGGGAAGCTAGAGTAAGTAGTTCGCCAGTTAATAGTTTGCGCAACGTTGTTGCCATTGCTACAGGCATCGTGGTGTCACGCTCGTCGTTTGGTATGGCTTCATTCAGCTCCGGTTCCCAACGATCAAGGCGAGTTACATGATCCCCCATGTTGTGCAAAAAAGCGGTTAGCTCCTTCGGTCCTCCGATCGTTGTCAGAAGTAAGTTGGCCGCAGTGTTATCACTCATGGTTATGGCAGCACTGCATAATTCTCTTACTGTCATGCCATCCGTAAGATGCTTTTCTGTGACTGGTGAGTACTCAACCAAGTCATTCTGAGAATAGTGTATGCGGCGACCGAGTTGCTCTTGCCCGGCGTCAATACGGGATAATACCGCGCCACATAGCAGAACTTTAAAAGTGCTCATCATTGGAAAACGTTCTTCGGGGCGAAAACTCTCAAGGATCTTACCGCTGTTGAGATCCAGTTCGATGTAACCCACTCGTGCACCCAACTGATCTTCAGCATCTTTTACTTTCACCAGCGTTTCTGGGTGAGCAAAAACAGGAAGGCAAAATGCCGCAAAAAAGGGAATAAGGGCGACACGGAAATGTTGAATACTCATACTCTTCCTTTTTCAATATTATTGAAGCATTTATCAGGGTTATTGTCTCATGAGCGGATACATATTTGAATGTATTTAGAAAAATAAACAAATAGGGGTTCCGCGCACCTGCACCAGTCAGTAAAACGACGGCCAGTAGTCAAAAGCCTCCGACCGGAGGCTTTTGACTTGGTTCAGGTGGAGTGGGAGAAACACGTGGCAAACATTCCGGTCTCAAATGGAAAAGAGCAACGAAACCAACGGCTACCTTGACAGCGCTCAAGCCGGCCCTGCAGCTGGCCCGGGCGCTCCGGGTACCGCCGCGGGTCGTGCACGTCGTTGCGCGGGCTTCCTGCGGCGCCAAGCGCTGGTGCTGCTCACGGTGTCTGGTGTTCTGGCAGGCGCCGGTTTGGGCGCGGCACTGCGTGGGCTCAGCCTGAGCCGCACCCAGGTCACCTACCTGGCCTTCCCCGGCGAGATGCTGCTCCGCATGCTGCGCATGATCATCCTGCCGCTGGTGGTCTGCAGCCTGGTGTCGGGCGCCGCCTCCCTCGATGCCAGCTGCCTCGGGCGTCTGGGCGGTATCGCTGTCGCCTACTTTGGCCTCACCACACTGAGTGCCTCGGCGCTCGCCGTGGCCTTGGCGTTCATCATCAAGCCAGGATCCGGTGCGCAGACCCTTCAGTCCAGCGACCTGGGGCTGGAGGACTCGGGGCCTCCTCCTGTCCCCAAAGAAACGGTGGACTCTTTCCTCGACCTGGCCAGAAACCTGTTTCCCTCCAATCTTGTGGTTGCAGCTTTCCGTACGTATGCAACCGATTATAAAGTCGTGACCCAGAACAGCAGCTCTGGAAATGTAACCCATGAAAAGATCCCCATAGGCACTGAGATAGAAGGGATGAACATTTTAGGATTGGTCCTGTTTGCTCTGGTGTTAGGAGTGGCCTTAAAGAAACTAGGCTCCGAAGGAGAGGACCTCATCCGTTTCTTCAATTCCCTCAACGAGGCGACGATGGTGCTGGTGTCCTGGATTATGTGGTACGTACCTGTGGGCATCATGTTCCTTGTTGGAAGCAAGATCGTGGAAATGAAAGACATCATCGTGCTGGTGACCAGCCTGGGGAAATACATCTTCGCATCTATATTGGGCCACGTCATTCATGGTGGTATCGTCCTGCCGCTGATTTATTTTGTTTTCACACGAAAAAACCCATTCAGATTCCTCCTGGGCCTCCTCGCCCCATTTGCGACAGCATTTGCTACGTGCTCCAGCTCAGCGACCCTTCCCTCTATGATGAAGTGCATTGAAGAGAACAATGGTGTGGACAAGAGGATCTCCAGGTTTATTCTCCCCATCGGGGCCACCGTGAACATGGACGGAGCAGCCATCTTCCAGTGTGTGGCCGCGGTGTTCATTGCGCAACTCAACAACGTAGAGCTCAACGCAGGACAGATTTTCACCATTCTAGTGACTGCCACAGCGTCCAGTGTTGGAGCAGCAGGCGTGCCAGCTGGAGGGGTCCTCACCATTGCCATTATCCTGGAGGCCATTGGGCTGCCTACTCATGATCTGCCTCTGATCCTGGCTGTGGACTGGATTGTGGACCGGACCACCACGGTGGTGAATGTGGAAGGGGATGCCCTGGGTGCAGGCATTCTCCACCACCTGAATCAGAAGGCAACAAAGAAAGGCGAGCAGGAACTTGCTGAGGTGAAAGTGGAAGCCATCCCCAACTGCAAGTCTGAGGAGGAAACCTCGCCCCTGGTGACACACCAGAACCCCGCTGGCCCCGTGGCCAGTGCCCCAGAACTGGAATCCAAGGAGTCGGTTCTGTGAAGAGCTTAGAGACCGACGACTGCCTAAGGACATTCGCTGAGGTGTCAATCGTCGGAGCCGCTGAGCAATAACTAGCATAACCCCTTGGGGCCTCTAAACGGGTCTTGAGGGGTTTTTTGCATGGTCATAGCTGTTTCCTGAGAGCTTGGCAGGTGATGACACACATTAACAAATTTCGTGAGGAGTCTCCAGAAGAATGCCATTAATTTCCATAGGCTCCGCCCCCCTGACGAGCATCACAAAAATCGACGCTCAAGTCAGAGGTGGCGAAACCCGACAGGACTATAAAGATACCAGGCGTTTCCCCCTGGAAGCTCCCTCGTGCGCTCTCCTGTTCCGACCCTGCCGCTTACCGGATACCTGTCCGCCTTTCTCCCTTCGGGAAGCGTGGCGCTTTCTCATAGCTCACGCTGTAGGTATCTCAGTTCGGTGTAGGTCGTTCGCTCCAAGCTGGGCTGTGTGCACGAACCCCCCGTTCAGCCCGACCGCTGCGCCTTATCCGGTAACTATCGTCTTGAGTCCAACCCGGTAAGACACGACTTATCGCCACTGGCAGCAGCCACTGGTAACAGGATTAGCAGAGCGAGGTATGTAGGCGGTGCTACAGAGTTCTTGAAGTGGTGGCCTAACTACGGCTACACTAGAAGAACAGTATTTGGTATCTGCGCTCTGCTGAAGCCAGTTACCTTCGGAAAAAGAGTTGGTAGCTCTTGATCCGGCAAACAAACCACCGCTGGTAGCGGTGGTTTTTTTGTTTGCAAGCAGCAGATTACGCGCAG
Expand Down
Loading

0 comments on commit da9e61d

Please sign in to comment.