@@ -98,11 +98,11 @@ func NextOverhang(currentOverhangs []string) string {
9898}
9999
100100// optimizeOverhangIteration takes in a sequence and optimally fragments it.
101- func optimizeOverhangIteration (sequence string , minFragmentSize int , maxFragmentSize int , existingFragments []string , existingOverhangs []string ) ([]string , float64 , error ) {
101+ func optimizeOverhangIteration (sequence string , minFragmentSize int , maxFragmentSize int , existingFragments []string , excludeOverhangs [] string , includeOverhangs []string ) ([]string , float64 , error ) {
102102 // If the sequence is smaller than maxFragment size, stop iteration.
103103 if len (sequence ) < maxFragmentSize {
104104 existingFragments = append (existingFragments , sequence )
105- return existingFragments , SetEfficiency (existingOverhangs ), nil
105+ return existingFragments , SetEfficiency (excludeOverhangs ), nil
106106 }
107107
108108 // Make sure minFragmentSize > maxFragmentSize
@@ -136,23 +136,35 @@ func optimizeOverhangIteration(sequence string, minFragmentSize int, maxFragment
136136 var bestOverhangEfficiency float64
137137 var bestOverhangPosition int
138138 var alreadyExists bool
139+ var buildAvailable bool
139140 for overhangOffset := 0 ; overhangOffset <= maxFragmentSize - minFragmentSize ; overhangOffset ++ {
140141 // We go from max -> min, so we can maximize the size of our fragments
141142 overhangPosition := maxFragmentSize - overhangOffset
142143 overhangToTest := sequence [overhangPosition - 4 : overhangPosition ]
143144
144145 // Make sure overhang isn't already in set
145146 alreadyExists = false
146- for _ , existingOverhang := range existingOverhangs {
147- if existingOverhang == overhangToTest || transform .ReverseComplement (existingOverhang ) == overhangToTest {
147+ for _ , excludeOverhang := range excludeOverhangs {
148+ if excludeOverhang == overhangToTest || transform .ReverseComplement (excludeOverhang ) == overhangToTest {
148149 alreadyExists = true
149150 }
150151 }
151- if ! alreadyExists {
152+ // Make sure overhang is in set of includeOverhangs. If includeOverhangs is
153+ // blank, skip this check.
154+ buildAvailable = false
155+ if len (includeOverhangs ) == 0 {
156+ buildAvailable = true
157+ }
158+ for _ , includeOverhang := range includeOverhangs {
159+ if includeOverhang == overhangToTest || transform .ReverseComplement (includeOverhang ) == overhangToTest {
160+ buildAvailable = true
161+ }
162+ }
163+ if ! alreadyExists && buildAvailable {
152164 // See if this overhang is a palindrome
153165 if ! checks .IsPalindromic (overhangToTest ) {
154166 // Get this overhang set's efficiency
155- setEfficiency := SetEfficiency (append (existingOverhangs , overhangToTest ))
167+ setEfficiency := SetEfficiency (append (excludeOverhangs , overhangToTest ))
156168
157169 // If this overhang is more efficient than any other found so far, set it as the best!
158170 if setEfficiency > bestOverhangEfficiency {
@@ -167,16 +179,24 @@ func optimizeOverhangIteration(sequence string, minFragmentSize int, maxFragment
167179 return []string {}, float64 (0 ), fmt .Errorf ("bestOverhangPosition failed by equaling zero" )
168180 }
169181 existingFragments = append (existingFragments , sequence [:bestOverhangPosition ])
170- existingOverhangs = append (existingOverhangs , sequence [bestOverhangPosition - 4 :bestOverhangPosition ])
182+ excludeOverhangs = append (excludeOverhangs , sequence [bestOverhangPosition - 4 :bestOverhangPosition ])
171183 sequence = sequence [bestOverhangPosition - 4 :]
172- return optimizeOverhangIteration (sequence , minFragmentSize , maxFragmentSize , existingFragments , existingOverhangs )
184+ return optimizeOverhangIteration (sequence , minFragmentSize , maxFragmentSize , existingFragments , excludeOverhangs , includeOverhangs )
173185}
174186
175187// Fragment fragments a sequence into fragments between the min and max size,
176188// choosing fragment ends for optimal assembly efficiency. Since fragments will
177189// be inserted into either a vector or primer binding sites, the first 4 and
178190// last 4 base pairs are the initial overhang set.
179- func Fragment (sequence string , minFragmentSize int , maxFragmentSize int , existingOverhangs []string ) ([]string , float64 , error ) {
191+ func Fragment (sequence string , minFragmentSize int , maxFragmentSize int , excludeOverhangs []string ) ([]string , float64 , error ) {
192+ sequence = strings .ToUpper (sequence )
193+ return optimizeOverhangIteration (sequence , minFragmentSize , maxFragmentSize , []string {}, append ([]string {sequence [:4 ], sequence [len (sequence )- 4 :]}, excludeOverhangs ... ), []string {})
194+ }
195+
196+ // FragmentWithOverhangs fragments a sequence with only a certain overhang set.
197+ // This is useful if you are constraining the set of possible overhangs when
198+ // doing more advanced forms of cloning.
199+ func FragmentWithOverhangs (sequence string , minFragmentSize int , maxFragmentSize int , excludeOverhangs []string , includeOverhangs []string ) ([]string , float64 , error ) {
180200 sequence = strings .ToUpper (sequence )
181- return optimizeOverhangIteration (sequence , minFragmentSize , maxFragmentSize , []string {}, append ([]string {sequence [:4 ], sequence [len (sequence )- 4 :]}, existingOverhangs ... ))
201+ return optimizeOverhangIteration (sequence , minFragmentSize , maxFragmentSize , []string {}, append ([]string {sequence [:4 ], sequence [len (sequence )- 4 :]}, excludeOverhangs ... ), includeOverhangs )
182202}
0 commit comments