Skip to content

Commit 813b484

Browse files
authored
Merge pull request #24 from MatildaAslin/reads_per_sample_handler
Reads per sample handler
2 parents 7839c13 + 4f604fd commit 813b484

File tree

3 files changed

+136
-0
lines changed

3 files changed

+136
-0
lines changed

checkQC/default_config/config.yaml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ hiseq2500_rapidhighoutput_v4:
3030
- name: ErrorRateHandler
3131
warning: 1.5
3232
error: unknown
33+
- name: ReadsPerSampleHandler
34+
warning: 90 # 50 % of threshold for clusters pass filter
35+
error: unknown
3336
100-110:
3437
handlers:
3538
- name: ClusterPFHandler
@@ -41,6 +44,9 @@ hiseq2500_rapidhighoutput_v4:
4144
- name: ErrorRateHandler
4245
warning: 2
4346
error: unknown
47+
- name: ReadsPerSampleHandler
48+
warning: 90 # 50 % of threshold for clusters pass filter
49+
error: unknown
4450
120-130:
4551
handlers:
4652
- name: ClusterPFHandler
@@ -52,6 +58,9 @@ hiseq2500_rapidhighoutput_v4:
5258
- name: ErrorRateHandler
5359
warning: 2
5460
error: unknown
61+
- name: ReadsPerSampleHandler
62+
warning: 90 # 50 % of threshold for clusters pass filter
63+
error: unknown
5564

5665
hiseq2500_rapidrun_v2:
5766
50-70:
@@ -65,6 +74,9 @@ hiseq2500_rapidrun_v2:
6574
- name: ErrorRateHandler
6675
warning: 1.5
6776
error: unknown
77+
- name: ReadsPerSampleHandler
78+
warning: 55 # 50 % of threshold for clusters pass filter
79+
error: unknown
6880
100-125:
6981
handlers:
7082
- name: ClusterPFHandler
@@ -76,6 +88,9 @@ hiseq2500_rapidrun_v2:
7688
- name: ErrorRateHandler
7789
warning: 2
7890
error: unknown
91+
- name: ReadsPerSampleHandler
92+
warning: 55 # 50 % of threshold for clusters pass filter
93+
error: unknown
7994
150-175:
8095
handlers:
8196
- name: ClusterPFHandler
@@ -87,6 +102,9 @@ hiseq2500_rapidrun_v2:
87102
- name: ErrorRateHandler
88103
warning: unknown
89104
error: 3
105+
- name: ReadsPerSampleHandler
106+
warning: 55 # 50 % of threshold for clusters pass filter
107+
error: unknown
90108
250-265:
91109
handlers:
92110
- name: ClusterPFHandler
@@ -98,6 +116,9 @@ hiseq2500_rapidrun_v2:
98116
- name: ErrorRateHandler
99117
warning: 5
100118
error: unknown
119+
- name: ReadsPerSampleHandler
120+
warning: 55 # 50 % of threshold for clusters pass filter
121+
error: unknown
101122

102123
hiseqx_v2:
103124
150:
@@ -111,6 +132,9 @@ hiseqx_v2:
111132
- name: ErrorRateHandler
112133
warning: 5
113134
error: unknown
135+
- name: ReadsPerSampleHandler
136+
warning: 200 # 50 % of threshold for clusters pass filter
137+
error: unknown
114138

115139
# TODO These are not the real novaseq qc criteria, but they need to be determined
116140
# once we know what they are. /JD 2017-10-05
@@ -139,6 +163,9 @@ miseq_v2:
139163
- name: ErrorRateHandler
140164
warning: 1
141165
error: unknown
166+
- name: ReadsPerSampleHandler
167+
warning: 5 # 50 % of threshold for clusters pass filter
168+
error: unknown
142169
150:
143170
handlers:
144171
- name: ClusterPFHandler
@@ -150,6 +177,9 @@ miseq_v2:
150177
- name: ErrorRateHandler
151178
warning: 2
152179
error: uknown
180+
- name: ReadsPerSampleHandler
181+
warning: 5 # 50 % of threshold for clusters pass filter
182+
error: unknown
153183
250:
154184
handlers:
155185
- name: ClusterPFHandler
@@ -161,6 +191,9 @@ miseq_v2:
161191
- name: ErrorRateHandler
162192
warning: 5
163193
error: unknown
194+
- name: ReadsPerSampleHandler
195+
warning: 5 # 50 % of threshold for clusters pass filter
196+
error: unknown
164197

165198
miseq_v3:
166199
75:
@@ -174,6 +207,9 @@ miseq_v3:
174207
- name: ErrorRateHandler
175208
warning: 1.5
176209
error: unknown
210+
- name: ReadsPerSampleHandler
211+
warning: 9 # 50 % of threshold for clusters pass filter
212+
error: unknown
177213
300:
178214
handlers:
179215
- name: ClusterPFHandler
@@ -185,3 +221,6 @@ miseq_v3:
185221
- name: ErrorRateHandler
186222
warning: 5
187223
error: unknown
224+
- name: ReadsPerSampleHandler
225+
warning: 9 # 50 % of threshold for clusters pass filter
226+
error: unknown
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from checkQC.handlers.qc_handler import QCHandler, QCErrorFatal, QCErrorWarning
2+
from checkQC.parsers.stats_json_parser import StatsJsonParser
3+
from math import pow
4+
5+
class ReadsPerSampleHandler(QCHandler):
6+
7+
def __init__(self, *args, **kwargs):
8+
super().__init__(*args, **kwargs)
9+
self.conversion_results = None
10+
11+
def parser(self):
12+
return StatsJsonParser
13+
14+
def collect(self, signal):
15+
key, value = signal
16+
if key == "ConversionResults":
17+
self.conversion_results = value
18+
19+
def check_qc(self):
20+
21+
for lane_dict in self.conversion_results:
22+
lane_nbr = lane_dict["LaneNumber"]
23+
lane_demux = lane_dict["DemuxResults"]
24+
25+
for sample_id_info in lane_demux:
26+
27+
sample_id = sample_id_info["SampleId"]
28+
sample_total_reads = sample_id_info["NumberReads"] / pow(10,6)
29+
30+
if self.error() != self.UNKNOWN and sample_total_reads <= (float(self.error()) / float(len(lane_demux))):
31+
yield QCErrorFatal("Number of reads for sample {} was too low on lane {}, it was: {} M".format(sample_id, lane_nbr, sample_total_reads),
32+
ordering=int(lane_nbr))
33+
elif self.warning() != self.UNKNOWN and sample_total_reads <= (float(self.warning()) / float(len(lane_demux))):
34+
yield QCErrorWarning("Number of reads for sample {} was too low on lane {}, it was: {} M".format(sample_id, lane_nbr, sample_total_reads),
35+
ordering=int(lane_nbr))
36+
else:
37+
continue
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import unittest
2+
3+
from checkQC.handlers.reads_per_sample_handler import ReadsPerSampleHandler
4+
5+
from tests.test_utils import get_stats_json
6+
from tests.handlers.handler_test_base import HandlerTestBase
7+
8+
9+
class TestReadsPerSampleHandler(HandlerTestBase):
10+
11+
def setUp(self):
12+
key = "ConversionResults"
13+
qc_config = {'name': 'ReadsPerSampleHandler', 'error': 'unknown', 'warning': '90'}
14+
value = get_stats_json()["ConversionResults"]
15+
reads_per_sample_handler = ReadsPerSampleHandler(qc_config)
16+
reads_per_sample_handler.collect((key, value))
17+
self.reads_per_sample_handler = reads_per_sample_handler
18+
19+
def set_qc_config(self, qc_config):
20+
self.reads_per_sample_handler.qc_config = qc_config
21+
22+
def test_all_is_fine(self):
23+
qc_config = {'name': 'ReadsPerSampleHandler', 'error': '70', 'warning': '90'}
24+
self.set_qc_config(qc_config)
25+
errors_and_warnings = list(self.reads_per_sample_handler.check_qc())
26+
self.assertEqual(errors_and_warnings, [])
27+
28+
def test_warning(self):
29+
qc_config = {'name': 'ReadsPerSampleHandler', 'error': '100', 'warning': '400'}
30+
self.set_qc_config(qc_config)
31+
errors_and_warnings = list(self.reads_per_sample_handler.check_qc())
32+
self.assertEqual(len(errors_and_warnings), 4)
33+
34+
class_names = self.map_errors_and_warnings_to_class_names(errors_and_warnings)
35+
self.assertListEqual(class_names, ['QCErrorWarning', 'QCErrorWarning',
36+
'QCErrorWarning', 'QCErrorWarning'])
37+
38+
def test_error(self):
39+
qc_config = {'name': 'ReadsPerSampleHandler', 'error': '400', 'warning': '500'}
40+
self.set_qc_config(qc_config)
41+
errors_and_warnings = list(self.reads_per_sample_handler.check_qc())
42+
self.assertEqual(len(errors_and_warnings), 4)
43+
44+
class_names = self.map_errors_and_warnings_to_class_names(errors_and_warnings)
45+
self.assertListEqual(class_names, ['QCErrorFatal', 'QCErrorFatal',
46+
'QCErrorFatal', 'QCErrorFatal'])
47+
48+
def test_warning_when_error_unknown(self):
49+
qc_config = {'name': 'ReadsPerSampleHandler', 'error': 'unknown', 'warning': '400'}
50+
self.set_qc_config(qc_config)
51+
errors_and_warnings = list(self.reads_per_sample_handler.check_qc())
52+
self.assertEqual(len(errors_and_warnings), 4)
53+
54+
class_names = self.map_errors_and_warnings_to_class_names(errors_and_warnings)
55+
self.assertListEqual(class_names, ['QCErrorWarning', 'QCErrorWarning',
56+
'QCErrorWarning', 'QCErrorWarning'])
57+
58+
59+
if __name__ == '__main__':
60+
unittest.main()

0 commit comments

Comments
 (0)