cutseq 0.0.5__tar.gz → 0.0.7__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.
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
# Created: 2024-04-19 18:57
|
|
8
8
|
|
|
9
9
|
import argparse
|
|
10
|
+
import importlib.metadata
|
|
10
11
|
import logging
|
|
11
12
|
import re
|
|
12
13
|
import subprocess
|
|
@@ -26,11 +27,13 @@ from cutadapt.modifiers import (
|
|
|
26
27
|
PairedEndRenamer,
|
|
27
28
|
QualityTrimmer,
|
|
28
29
|
Renamer,
|
|
30
|
+
SingleEndModifier,
|
|
29
31
|
SuffixRemover,
|
|
30
32
|
UnconditionalCutter,
|
|
31
33
|
)
|
|
32
34
|
from cutadapt.pipeline import PairedEndPipeline, SingleEndPipeline
|
|
33
35
|
from cutadapt.predicates import Predicate, TooShort
|
|
36
|
+
from cutadapt.report import Statistics
|
|
34
37
|
from cutadapt.runners import make_runner
|
|
35
38
|
from cutadapt.steps import (
|
|
36
39
|
PairedEndFilter,
|
|
@@ -40,6 +43,54 @@ from cutadapt.steps import (
|
|
|
40
43
|
)
|
|
41
44
|
from cutadapt.utils import Progress
|
|
42
45
|
|
|
46
|
+
# monkey patching ....
|
|
47
|
+
original_method = Statistics._collect_modifier
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def patched_problematic_method(self, *args, **kwargs):
|
|
51
|
+
try:
|
|
52
|
+
return original_method(self, *args, **kwargs)
|
|
53
|
+
except AssertionError:
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
Statistics._collect_modifier = patched_problematic_method
|
|
58
|
+
|
|
59
|
+
## Enhnace function for cutadapt
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class IsUntrimmedAny(Predicate):
|
|
63
|
+
"""
|
|
64
|
+
Select reads for which no adapter match was found
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
def __init__(self, ref_adapters):
|
|
68
|
+
self.ref_adapters = ref_adapters
|
|
69
|
+
|
|
70
|
+
def __repr__(self):
|
|
71
|
+
return "IsUntrimmedAny()"
|
|
72
|
+
|
|
73
|
+
def test(self, read, info):
|
|
74
|
+
# check not all adapters with ref_adapters are exist in the matches
|
|
75
|
+
match_adapters = [match.adapter for match in info.matches]
|
|
76
|
+
if any([adapter not in match_adapters for adapter in self.ref_adapters]):
|
|
77
|
+
return True
|
|
78
|
+
return False
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class ReverseComplementConverter(SingleEndModifier):
|
|
82
|
+
def __init__(self):
|
|
83
|
+
self.rcd = False
|
|
84
|
+
|
|
85
|
+
def __repr__(self):
|
|
86
|
+
return f"UnconditionalCutter(length={self.length})"
|
|
87
|
+
|
|
88
|
+
def __call__(self, read, info):
|
|
89
|
+
return read.reverse_complement()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
__version__ = importlib.metadata.version(__package__ or __name__)
|
|
93
|
+
|
|
43
94
|
logging.basicConfig(
|
|
44
95
|
level=logging.INFO,
|
|
45
96
|
format="%(asctime)s - %(levelname)s - %(message)s",
|
|
@@ -125,25 +176,6 @@ class CutadaptConfig:
|
|
|
125
176
|
self.threads = 1
|
|
126
177
|
|
|
127
178
|
|
|
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
|
-
|
|
147
179
|
def run_steps(steps, dry_run=False):
|
|
148
180
|
if dry_run:
|
|
149
181
|
print(
|
|
@@ -222,6 +254,10 @@ def pipeline_single(input1, output1, short1, untrimmed1, barcode, settings):
|
|
|
222
254
|
QualityTrimmer(cutoff_front=0, cutoff_back=settings.min_quality),
|
|
223
255
|
)
|
|
224
256
|
|
|
257
|
+
# step 9: reverse complement the read
|
|
258
|
+
if settings.reverse_complement:
|
|
259
|
+
modifiers.append(ReverseComplementConverter())
|
|
260
|
+
|
|
225
261
|
inpaths = InputPaths(input1)
|
|
226
262
|
|
|
227
263
|
with make_runner(inpaths, cores=settings.threads) as runner:
|
|
@@ -251,7 +287,7 @@ def pipeline_single(input1, output1, short1, untrimmed1, barcode, settings):
|
|
|
251
287
|
steps.append(
|
|
252
288
|
# TODO: --max-n=0 support
|
|
253
289
|
SingleEndFilter(
|
|
254
|
-
|
|
290
|
+
IsUntrimmedAny(ref_adapters),
|
|
255
291
|
outfiles.open_record_writer(untrimmed1, interleaved=False),
|
|
256
292
|
),
|
|
257
293
|
)
|
|
@@ -406,6 +442,10 @@ def pipeline_paired(
|
|
|
406
442
|
)
|
|
407
443
|
)
|
|
408
444
|
|
|
445
|
+
# step 9: reverse complement the read
|
|
446
|
+
if settings.reverse_complement:
|
|
447
|
+
modifiers.append((ReverseComplementConverter(), ReverseComplementConverter()))
|
|
448
|
+
|
|
409
449
|
inpaths = InputPaths(input1, input2)
|
|
410
450
|
|
|
411
451
|
with make_runner(inpaths, cores=settings.threads) as runner:
|
|
@@ -432,10 +472,10 @@ def pipeline_paired(
|
|
|
432
472
|
steps.append(
|
|
433
473
|
# TODO: --max-n=0 support
|
|
434
474
|
PairedEndFilter(
|
|
435
|
-
|
|
475
|
+
IsUntrimmedAny([adapter_inline5])
|
|
436
476
|
if barcode.inline5.len > 0
|
|
437
477
|
else None,
|
|
438
|
-
|
|
478
|
+
IsUntrimmedAny([adapter_inline3])
|
|
439
479
|
if barcode.inline3.len > 0
|
|
440
480
|
else None,
|
|
441
481
|
outfiles.open_record_writer(
|
|
@@ -463,6 +503,7 @@ def run_cutseq(args):
|
|
|
463
503
|
settings.threads = args.threads
|
|
464
504
|
settings.min_length = args.min_length
|
|
465
505
|
settings.dry_run = args.dry_run
|
|
506
|
+
settings.reverse_complement = args.reverse_complement
|
|
466
507
|
if len(args.input_file) == 1:
|
|
467
508
|
pipeline_single(
|
|
468
509
|
args.input_file[0],
|
|
@@ -565,6 +606,12 @@ def main():
|
|
|
565
606
|
|
|
566
607
|
parser.add_argument("--trim-polyA", action="store_true", help="Trim polyA tail.")
|
|
567
608
|
|
|
609
|
+
parser.add_argument(
|
|
610
|
+
"--reverse-complement",
|
|
611
|
+
action="store_true",
|
|
612
|
+
help="Reverse complement the reads.",
|
|
613
|
+
)
|
|
614
|
+
|
|
568
615
|
parser.add_argument(
|
|
569
616
|
"-t",
|
|
570
617
|
"--threads",
|
|
@@ -578,6 +625,11 @@ def main():
|
|
|
578
625
|
action="store_true",
|
|
579
626
|
help="Print command instead of running it.",
|
|
580
627
|
)
|
|
628
|
+
|
|
629
|
+
parser.add_argument(
|
|
630
|
+
"-V", "--version", action="version", version=f"%(prog)s {__version__}"
|
|
631
|
+
)
|
|
632
|
+
|
|
581
633
|
args = parser.parse_args()
|
|
582
634
|
|
|
583
635
|
if args.adapter_name is not None:
|
|
File without changes
|
|
File without changes
|