mirror of
https://github.com/metabarcoding/obitools4.git
synced 2026-11-09 09:24:41 +00:00
78 lines
2.6 KiB
Go
78 lines
2.6 KiB
Go
package obiprimer
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"math/rand"
|
||
|
|
"reflect"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestAmpBatches(t *testing.T) {
|
||
|
|
cases := []struct {
|
||
|
|
count []int
|
||
|
|
budget int
|
||
|
|
want [][2]int
|
||
|
|
}{
|
||
|
|
{[]int{3, 3, 3}, 0, [][2]int{{0, 3}}},
|
||
|
|
{[]int{3, 3, 3}, 100, [][2]int{{0, 3}}},
|
||
|
|
{[]int{3, 3, 3}, 6, [][2]int{{0, 2}, {2, 3}}},
|
||
|
|
{[]int{3, 3, 3}, 1, [][2]int{{0, 1}, {1, 2}, {2, 3}}}, // a pair above the budget goes alone
|
||
|
|
{[]int{9, 1, 1}, 5, [][2]int{{0, 1}, {1, 3}}},
|
||
|
|
{nil, 5, nil},
|
||
|
|
{[]int{0, 0}, 5, [][2]int{{0, 2}}},
|
||
|
|
}
|
||
|
|
for _, c := range cases {
|
||
|
|
if got := ampBatches(c.count, c.budget); !reflect.DeepEqual(got, c.want) {
|
||
|
|
t.Errorf("ampBatches(%v, %d) = %v, want %v", c.count, c.budget, got, c.want)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// The batches of phase 2 only bound the memory: whatever their size, the pairs,
|
||
|
|
// their indices and their sites on the reference are the same.
|
||
|
|
func TestAmpBudgetDoesNotChangeTheResult(t *testing.T) {
|
||
|
|
s := newSynthetic(10, -1, 5)
|
||
|
|
// non-targets sharing barcodes with targets, and counterexamples
|
||
|
|
for k, role := range []Role{Other, Other, CounterExample, Other, CounterExample} {
|
||
|
|
cp := append([]byte(nil), s.corpus.Seqs[k*2].Sequence()...)
|
||
|
|
if role == CounterExample {
|
||
|
|
for i := s.pos; i < s.pos+10; i++ { // no forward site: not amplified
|
||
|
|
cp[i] = "cgta"[strings.IndexByte("acgt", cp[i])]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
s.corpus.Seqs = append(s.corpus.Seqs, obiseq.NewBioSequence(strings.Repeat("x", k+1), cp, ""))
|
||
|
|
s.corpus.Roles = append(s.corpus.Roles, role)
|
||
|
|
s.taxa.Of = append(s.taxa.Of, int32(100+k%3))
|
||
|
|
}
|
||
|
|
// a few unrelated sequences, with a taxon of their own or none
|
||
|
|
rng := rand.New(rand.NewSource(9))
|
||
|
|
for k := 0; k < 3; k++ {
|
||
|
|
s.corpus.Seqs = append(s.corpus.Seqs, obiseq.NewBioSequence("u"+strings.Repeat("y", k), []byte(strings.ToLower(randDNA(rng, 300))), ""))
|
||
|
|
s.corpus.Roles = append(s.corpus.Roles, Other)
|
||
|
|
s.taxa.Of = append(s.taxa.Of, int32(k-1))
|
||
|
|
}
|
||
|
|
|
||
|
|
run := func(budget int) []PairStats {
|
||
|
|
p := s.params()
|
||
|
|
p.MinSpecificity = 0 // keep every pair: the stress case of the batches
|
||
|
|
p.FalsePositive = 1
|
||
|
|
p.Reference = "s3"
|
||
|
|
p.AmpBudget = budget
|
||
|
|
pairs, info, err := Search(s.corpus, s.taxa, p)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if info.Pair.Candidates < 2 {
|
||
|
|
t.Fatalf("budget %d: only %d pairs reach phase 2b, the test needs several", budget, info.Pair.Candidates)
|
||
|
|
}
|
||
|
|
return pairs
|
||
|
|
}
|
||
|
|
want := run(0)
|
||
|
|
for _, budget := range []int{1, 7, 50, 1000} {
|
||
|
|
if got := run(budget); !reflect.DeepEqual(got, want) {
|
||
|
|
t.Errorf("budget %d changes the result:\n got %d pairs\nwant %d pairs", budget, len(got), len(want))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|