-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathqualitymetrics_test.go
More file actions
140 lines (133 loc) · 3.39 KB
/
qualitymetrics_test.go
File metadata and controls
140 lines (133 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package main
import (
"fmt"
"math"
"testing"
)
// Test quality metric calculations
func TestQualityMetricCalculations(t *testing.T) {
tests := []struct {
name string
qual []byte
metric QualityMetric
minPhred int
want float64
}{
{
name: "AvgPhred - All high quality",
qual: []byte("IIIII"), // ASCII 73 = Phred 40
metric: AvgPhred,
minPhred: DEFAULT_MIN_PHRED,
want: 40.0,
},
{
name: "AvgPhred - Mixed quality",
qual: []byte("I$$I$"), // Mix of Phred 40 and 3
metric: AvgPhred,
minPhred: DEFAULT_MIN_PHRED,
want: 5.21791,
},
{
name: "AvgPhred - Empty quality",
qual: []byte{},
metric: AvgPhred,
minPhred: DEFAULT_MIN_PHRED,
want: 0.0,
},
{
name: "MaxEE - All high quality",
qual: []byte("IIIII"),
metric: MaxEE,
minPhred: DEFAULT_MIN_PHRED,
want: 0.0005,
},
{
name: "MaxEE - Empty quality",
qual: []byte{},
metric: MaxEE,
minPhred: DEFAULT_MIN_PHRED,
want: math.Inf(1),
},
{
name: "LQCount - No low quality bases",
qual: []byte("IIIII"),
metric: LQCount,
minPhred: 30,
want: 0,
},
{
name: "LQCount - All low quality bases",
qual: []byte("$$$$$"),
metric: LQCount,
minPhred: 30,
want: 5,
},
{
name: "LQPercent - Half low quality bases",
qual: []byte("II$$$"),
metric: LQPercent,
minPhred: 30,
want: 60.0,
},
{
name: "MaxEE - Single very low quality base",
qual: []byte("$"), // ASCII 36 = Phred 3
metric: MaxEE,
minPhred: DEFAULT_MIN_PHRED,
want: 0.5011872336272722, // Error prob for Phred 3
},
{
name: "Meep - Mixed quality",
qual: []byte("I$$I$"), // Mix of Phred 40 and 3
metric: Meep,
minPhred: DEFAULT_MIN_PHRED,
want: 30.07523, // (sum of error probs * 100) / len
},
{
name: "LQCount - Custom minPhred threshold",
qual: []byte("BBBBB"), // ASCII 66 = Phred 33
metric: LQCount,
minPhred: 35,
want: 5, // All bases below Phred 35
},
{
name: "LQPercent - Single base at threshold",
qual: []byte("0"), // ASCII 48 = Phred 15
metric: LQPercent,
minPhred: 15,
want: 0.0, // Base exactly at threshold
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
record := createTestRecord("test", "ACGT", string(tt.qual))
got := calculateQuality(record, tt.metric, tt.minPhred)
// Use approximate comparison for floating point values
if math.Abs(got-tt.want) > 0.00001 {
t.Errorf("calculateQuality() = %v, want %v", got, tt.want)
}
})
}
}
// TestErrorProbabilitiesInit tests a few key values from the pre-computed errorProbs array
func TestErrorProbabilitiesInit(t *testing.T) {
tests := []struct {
phred byte
want float64
}{
{33, 1}, // Phred 0 (33 - 33 = 0)
{43, 0.1}, // Phred 10 (43 - 33 = 10)
{53, 0.01}, // Phred 20 (53 - 33 = 20)
{63, 0.001}, // Phred 30 (63 - 33 = 30)
{73, 0.0001}, // Phred 40 (73 - 33 = 40)
{83, 0.00001}, // Phred 50 (83 - 33 = 50)
{93, 0.000001}, // Phred 60 (93 - 33 = 60)
}
for _, tt := range tests {
t.Run(fmt.Sprintf("Phred%d", tt.phred-PHRED_OFFSET), func(t *testing.T) {
if got := errorProbs[tt.phred]; math.Abs(got-tt.want) > 1e-10 {
t.Errorf("errorProbs[%d] = %v, want %v", tt.phred, got, tt.want)
}
})
}
}