cutseq 0.0.4__tar.gz → 0.0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -18,6 +18,7 @@ from cutadapt.adapters import (
|
|
|
18
18
|
NonInternalFrontAdapter,
|
|
19
19
|
PrefixAdapter,
|
|
20
20
|
RightmostFrontAdapter,
|
|
21
|
+
SuffixAdapter,
|
|
21
22
|
)
|
|
22
23
|
from cutadapt.files import InputPaths, OutputFiles
|
|
23
24
|
from cutadapt.modifiers import (
|
|
@@ -29,13 +30,11 @@ from cutadapt.modifiers import (
|
|
|
29
30
|
UnconditionalCutter,
|
|
30
31
|
)
|
|
31
32
|
from cutadapt.pipeline import PairedEndPipeline, SingleEndPipeline
|
|
32
|
-
from cutadapt.predicates import
|
|
33
|
+
from cutadapt.predicates import Predicate, TooShort
|
|
33
34
|
from cutadapt.runners import make_runner
|
|
34
35
|
from cutadapt.steps import (
|
|
35
|
-
InfoFileWriter,
|
|
36
36
|
PairedEndFilter,
|
|
37
37
|
PairedEndSink,
|
|
38
|
-
PairedSingleEndStep,
|
|
39
38
|
SingleEndFilter,
|
|
40
39
|
SingleEndSink,
|
|
41
40
|
)
|
|
@@ -118,7 +117,7 @@ class BarcodeConfig:
|
|
|
118
117
|
class CutadaptConfig:
|
|
119
118
|
def __init__(self):
|
|
120
119
|
self.rname_suffix = False
|
|
121
|
-
self.
|
|
120
|
+
self.ensure_inline_barcode = False
|
|
122
121
|
self.trim_polyA = False
|
|
123
122
|
self.min_length = 20
|
|
124
123
|
self.min_quality = 20
|
|
@@ -126,6 +125,25 @@ class CutadaptConfig:
|
|
|
126
125
|
self.threads = 1
|
|
127
126
|
|
|
128
127
|
|
|
128
|
+
class IsUntrimmedRef(Predicate):
|
|
129
|
+
"""
|
|
130
|
+
Select reads for which no adapter match was found
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
def __init__(self, ref_adapters):
|
|
134
|
+
self.ref_adapters = ref_adapters
|
|
135
|
+
|
|
136
|
+
def __repr__(self):
|
|
137
|
+
return "IsUntrimmedRef()"
|
|
138
|
+
|
|
139
|
+
def test(self, read, info):
|
|
140
|
+
# check not all adapters with ref_adapters are exist in the matches
|
|
141
|
+
match_adapters = [match.adapter for match in info.matches]
|
|
142
|
+
if any([adapter not in match_adapters for adapter in self.ref_adapters]):
|
|
143
|
+
return True
|
|
144
|
+
return False
|
|
145
|
+
|
|
146
|
+
|
|
129
147
|
def run_steps(steps, dry_run=False):
|
|
130
148
|
if dry_run:
|
|
131
149
|
print(
|
|
@@ -138,7 +156,7 @@ def run_steps(steps, dry_run=False):
|
|
|
138
156
|
return process.stdout.decode(), process.stderr.decode()
|
|
139
157
|
|
|
140
158
|
|
|
141
|
-
def pipeline_single(input1, output1, short1,
|
|
159
|
+
def pipeline_single(input1, output1, short1, untrimmed1, barcode, settings):
|
|
142
160
|
modifiers = []
|
|
143
161
|
# step 1: remove suffix in the read name
|
|
144
162
|
modifiers.extend([SuffixRemover(".1"), SuffixRemover("/1")])
|
|
@@ -162,14 +180,11 @@ def pipeline_single(input1, output1, short1, untrimed1, barcode, settings):
|
|
|
162
180
|
)
|
|
163
181
|
# step 4: trim inline barcode
|
|
164
182
|
if barcode.inline5.len > 0:
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
[PrefixAdapter(sequence=barcode.inline5.fw, max_errors=0.2)],
|
|
168
|
-
times=1,
|
|
169
|
-
)
|
|
170
|
-
)
|
|
183
|
+
adapter_inline5 = PrefixAdapter(sequence=barcode.inline5.fw, max_errors=0.2)
|
|
184
|
+
modifiers.append(AdapterCutter([adapter_inline5], times=1))
|
|
171
185
|
if barcode.inline3.len > 0:
|
|
172
|
-
|
|
186
|
+
adapter_inline3 = SuffixAdapter(sequence=barcode.inline3.fw, max_errors=0.2)
|
|
187
|
+
modifiers.append(AdapterCutter([adapter_inline3], times=1))
|
|
173
188
|
|
|
174
189
|
# step 5: extract UMI
|
|
175
190
|
if barcode.umi5.len > 0:
|
|
@@ -215,19 +230,35 @@ def pipeline_single(input1, output1, short1, untrimed1, barcode, settings):
|
|
|
215
230
|
qualities=runner.input_file_format().has_qualities(),
|
|
216
231
|
interleaved=False,
|
|
217
232
|
)
|
|
218
|
-
steps = [
|
|
233
|
+
steps = []
|
|
234
|
+
steps.append(
|
|
219
235
|
# --info-file=info.txt
|
|
220
236
|
# PairedSingleEndStep(InfoFileWriter(outfiles.open_text("info.txt"))),
|
|
221
237
|
# -m 10
|
|
222
238
|
SingleEndFilter(
|
|
223
239
|
TooShort(settings.min_length), outfiles.open_record_writer(short1)
|
|
224
240
|
),
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
241
|
+
)
|
|
242
|
+
if (
|
|
243
|
+
settings.ensure_inline_barcode
|
|
244
|
+
and barcode.inline5.len + barcode.inline3.len > 0
|
|
245
|
+
):
|
|
246
|
+
ref_adapters = []
|
|
247
|
+
if barcode.inline5.len > 0:
|
|
248
|
+
ref_adapters.append(adapter_inline5)
|
|
249
|
+
if barcode.inline3.len > 0:
|
|
250
|
+
ref_adapters.append(adapter_inline3)
|
|
251
|
+
steps.append(
|
|
252
|
+
# TODO: --max-n=0 support
|
|
253
|
+
SingleEndFilter(
|
|
254
|
+
IsUntrimmedRef(ref_adapters),
|
|
255
|
+
outfiles.open_record_writer(untrimmed1, interleaved=False),
|
|
256
|
+
),
|
|
257
|
+
)
|
|
258
|
+
steps.append(
|
|
228
259
|
# -o
|
|
229
260
|
SingleEndSink(outfiles.open_record_writer(output1, interleaved=False)),
|
|
230
|
-
|
|
261
|
+
)
|
|
231
262
|
pipeline = SingleEndPipeline(modifiers, steps)
|
|
232
263
|
_stats = runner.run(pipeline, Progress(), outfiles)
|
|
233
264
|
# _ = stats.as_json()
|
|
@@ -241,7 +272,7 @@ def pipeline_paired(
|
|
|
241
272
|
output2,
|
|
242
273
|
short1,
|
|
243
274
|
short2,
|
|
244
|
-
|
|
275
|
+
untrimmed1,
|
|
245
276
|
untrimmed2,
|
|
246
277
|
barcode,
|
|
247
278
|
settings,
|
|
@@ -290,23 +321,19 @@ def pipeline_paired(
|
|
|
290
321
|
)
|
|
291
322
|
# step 4: trim inline barcode
|
|
292
323
|
if barcode.inline5.len > 0:
|
|
324
|
+
adapter_inline5 = PrefixAdapter(sequence=barcode.inline5.fw, max_errors=0.2)
|
|
293
325
|
modifiers.append(
|
|
294
326
|
(
|
|
295
|
-
AdapterCutter(
|
|
296
|
-
[PrefixAdapter(sequence=barcode.inline5.fw, max_errors=0.2)],
|
|
297
|
-
times=1,
|
|
298
|
-
),
|
|
327
|
+
AdapterCutter([adapter_inline5], times=1),
|
|
299
328
|
UnconditionalCutter(-barcode.inline5.len),
|
|
300
329
|
)
|
|
301
330
|
)
|
|
302
331
|
if barcode.inline3.len > 0:
|
|
332
|
+
adapter_inline3 = PrefixAdapter(sequence=barcode.inline3.rc, max_errors=0.2)
|
|
303
333
|
modifiers.append(
|
|
304
334
|
(
|
|
305
335
|
UnconditionalCutter(-barcode.inline3.len),
|
|
306
|
-
AdapterCutter(
|
|
307
|
-
[BackAdapter(sequence=barcode.inline3.rc, max_errors=0.2)],
|
|
308
|
-
times=1,
|
|
309
|
-
),
|
|
336
|
+
AdapterCutter([adapter_inline3], times=1),
|
|
310
337
|
)
|
|
311
338
|
)
|
|
312
339
|
|
|
@@ -387,21 +414,40 @@ def pipeline_paired(
|
|
|
387
414
|
qualities=runner.input_file_format().has_qualities(),
|
|
388
415
|
interleaved=False,
|
|
389
416
|
)
|
|
390
|
-
steps = [
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
417
|
+
steps = []
|
|
418
|
+
# --info-file=info.txt
|
|
419
|
+
# PairedSingleEndStep(InfoFileWriter(outfiles.open_text("info.txt"))),
|
|
420
|
+
# -m 10:10
|
|
421
|
+
steps.append(
|
|
394
422
|
PairedEndFilter(
|
|
395
423
|
TooShort(settings.min_length),
|
|
396
424
|
TooShort(settings.min_length),
|
|
397
425
|
outfiles.open_record_writer(short1, short2, interleaved=False),
|
|
398
|
-
)
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
426
|
+
)
|
|
427
|
+
)
|
|
428
|
+
if (
|
|
429
|
+
settings.ensure_inline_barcode
|
|
430
|
+
and barcode.inline5.len + barcode.inline3.len > 0
|
|
431
|
+
):
|
|
432
|
+
steps.append(
|
|
433
|
+
# TODO: --max-n=0 support
|
|
434
|
+
PairedEndFilter(
|
|
435
|
+
IsUntrimmedRef([adapter_inline5])
|
|
436
|
+
if barcode.inline5.len > 0
|
|
437
|
+
else None,
|
|
438
|
+
IsUntrimmedRef([adapter_inline3])
|
|
439
|
+
if barcode.inline3.len > 0
|
|
440
|
+
else None,
|
|
441
|
+
outfiles.open_record_writer(
|
|
442
|
+
untrimmed1, untrimmed2, interleaved=False
|
|
443
|
+
),
|
|
444
|
+
pair_filter_mode="any",
|
|
445
|
+
)
|
|
446
|
+
)
|
|
447
|
+
steps.append(
|
|
402
448
|
# -o ... -p ...
|
|
403
|
-
PairedEndSink(outfiles.open_record_writer(output1, output2))
|
|
404
|
-
|
|
449
|
+
PairedEndSink(outfiles.open_record_writer(output1, output2))
|
|
450
|
+
)
|
|
405
451
|
pipeline = PairedEndPipeline(modifiers, steps)
|
|
406
452
|
_stats = runner.run(pipeline, Progress(), outfiles)
|
|
407
453
|
# _ = stats.as_json()
|
|
@@ -411,12 +457,9 @@ def pipeline_paired(
|
|
|
411
457
|
def run_cutseq(args):
|
|
412
458
|
barcode_config = BarcodeConfig(args.adapter_scheme.upper())
|
|
413
459
|
settings = CutadaptConfig()
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
settings.discarded_untrimmed = True
|
|
418
|
-
if args.trim_polyA:
|
|
419
|
-
settings.trim_polyA = True
|
|
460
|
+
settings.rname_suffix = args.with_rname_suffix
|
|
461
|
+
settings.ensure_inline_barcode = args.ensure_inline_barcode
|
|
462
|
+
settings.trim_polyA = args.trim_polyA
|
|
420
463
|
settings.threads = args.threads
|
|
421
464
|
settings.min_length = args.min_length
|
|
422
465
|
settings.dry_run = args.dry_run
|
|
@@ -506,6 +549,12 @@ def main():
|
|
|
506
549
|
action="store_true",
|
|
507
550
|
help="R1 and R2 suffix cotains suffix. MGI platform.",
|
|
508
551
|
)
|
|
552
|
+
|
|
553
|
+
parser.add_argument(
|
|
554
|
+
"--ensure-inline-barcode",
|
|
555
|
+
action="store_true",
|
|
556
|
+
help="Output discarded reads without inline barcode.",
|
|
557
|
+
)
|
|
509
558
|
parser.add_argument(
|
|
510
559
|
"-U",
|
|
511
560
|
"--untrimmed-file",
|
|
@@ -584,12 +633,8 @@ def main():
|
|
|
584
633
|
args.short_file = validate_output_file(
|
|
585
634
|
args.short_file, args.input_file, args.output_prefix, "short"
|
|
586
635
|
)
|
|
587
|
-
args.untrimmed_file = (
|
|
588
|
-
|
|
589
|
-
args.untrimmed_file, args.input_file, args.output_prefix, "untrimmed"
|
|
590
|
-
)
|
|
591
|
-
if args.untrimmed_file is not None
|
|
592
|
-
else [None] * len(args.input_file)
|
|
636
|
+
args.untrimmed_file = validate_output_file(
|
|
637
|
+
args.untrimmed_file, args.input_file, args.output_prefix, "untrimmed"
|
|
593
638
|
)
|
|
594
639
|
|
|
595
640
|
run_cutseq(args)
|
|
File without changes
|
|
File without changes
|