@@ -98,11 +98,11 @@ func NextOverhang(currentOverhangs []string) string {
98
98
}
99
99
100
100
// 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 ) {
102
102
// If the sequence is smaller than maxFragment size, stop iteration.
103
103
if len (sequence ) < maxFragmentSize {
104
104
existingFragments = append (existingFragments , sequence )
105
- return existingFragments , SetEfficiency (existingOverhangs ), nil
105
+ return existingFragments , SetEfficiency (excludeOverhangs ), nil
106
106
}
107
107
108
108
// Make sure minFragmentSize > maxFragmentSize
@@ -136,23 +136,35 @@ func optimizeOverhangIteration(sequence string, minFragmentSize int, maxFragment
136
136
var bestOverhangEfficiency float64
137
137
var bestOverhangPosition int
138
138
var alreadyExists bool
139
+ var buildAvailable bool
139
140
for overhangOffset := 0 ; overhangOffset <= maxFragmentSize - minFragmentSize ; overhangOffset ++ {
140
141
// We go from max -> min, so we can maximize the size of our fragments
141
142
overhangPosition := maxFragmentSize - overhangOffset
142
143
overhangToTest := sequence [overhangPosition - 4 : overhangPosition ]
143
144
144
145
// Make sure overhang isn't already in set
145
146
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 {
148
149
alreadyExists = true
149
150
}
150
151
}
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 {
152
164
// See if this overhang is a palindrome
153
165
if ! checks .IsPalindromic (overhangToTest ) {
154
166
// Get this overhang set's efficiency
155
- setEfficiency := SetEfficiency (append (existingOverhangs , overhangToTest ))
167
+ setEfficiency := SetEfficiency (append (excludeOverhangs , overhangToTest ))
156
168
157
169
// If this overhang is more efficient than any other found so far, set it as the best!
158
170
if setEfficiency > bestOverhangEfficiency {
@@ -167,16 +179,24 @@ func optimizeOverhangIteration(sequence string, minFragmentSize int, maxFragment
167
179
return []string {}, float64 (0 ), fmt .Errorf ("bestOverhangPosition failed by equaling zero" )
168
180
}
169
181
existingFragments = append (existingFragments , sequence [:bestOverhangPosition ])
170
- existingOverhangs = append (existingOverhangs , sequence [bestOverhangPosition - 4 :bestOverhangPosition ])
182
+ excludeOverhangs = append (excludeOverhangs , sequence [bestOverhangPosition - 4 :bestOverhangPosition ])
171
183
sequence = sequence [bestOverhangPosition - 4 :]
172
- return optimizeOverhangIteration (sequence , minFragmentSize , maxFragmentSize , existingFragments , existingOverhangs )
184
+ return optimizeOverhangIteration (sequence , minFragmentSize , maxFragmentSize , existingFragments , excludeOverhangs , includeOverhangs )
173
185
}
174
186
175
187
// Fragment fragments a sequence into fragments between the min and max size,
176
188
// choosing fragment ends for optimal assembly efficiency. Since fragments will
177
189
// be inserted into either a vector or primer binding sites, the first 4 and
178
190
// 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 ) {
180
200
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 )
182
202
}
0 commit comments