|
a |
|
b/singlecellmultiomics/fragment/scartrace.py |
|
|
1 |
from singlecellmultiomics.utils.sequtils import reverse_complement |
|
|
2 |
from singlecellmultiomics.fragment import Fragment |
|
|
3 |
|
|
|
4 |
class ScarTraceFragment(Fragment): |
|
|
5 |
""" |
|
|
6 |
Fragment definition for ScarTrace |
|
|
7 |
""" |
|
|
8 |
|
|
|
9 |
def __init__(self, reads,scartrace_r1_primers=None, **kwargs): |
|
|
10 |
Fragment.__init__(self, reads, **kwargs) |
|
|
11 |
self.scartrace_r1_primers = scartrace_r1_primers |
|
|
12 |
assert scartrace_r1_primers is not None, 'please supply primer sequences' |
|
|
13 |
|
|
|
14 |
# remove the set_umi function |
|
|
15 |
def set_umi(self, **kwargs): |
|
|
16 |
pass |
|
|
17 |
|
|
|
18 |
def is_valid(self): |
|
|
19 |
""" Check if R1 starts with the defined primers and if R2 and R1 are mapped |
|
|
20 |
|
|
|
21 |
Returns: |
|
|
22 |
bool |
|
|
23 |
""" |
|
|
24 |
if not self.has_R1() or not self.has_R2(): |
|
|
25 |
if not self.has_R1(): |
|
|
26 |
self.set_meta('fr','no_R1', as_set=True) |
|
|
27 |
if not self.has_R2(): |
|
|
28 |
self.set_meta('fr','no_R2', as_set=True) |
|
|
29 |
return False |
|
|
30 |
|
|
|
31 |
if self[0].is_unmapped or self[1].is_unmapped: |
|
|
32 |
self.set_meta('fr','unmapped_mate', as_set=True) |
|
|
33 |
return False |
|
|
34 |
|
|
|
35 |
r1_seq = self.get_R1().seq |
|
|
36 |
|
|
|
37 |
if self.get_R1().is_reverse: |
|
|
38 |
r1_seq = reverse_complement(r1_seq) |
|
|
39 |
|
|
|
40 |
if any( r1_seq.startswith(primer) for primer in self.scartrace_r1_primers ): |
|
|
41 |
# Good |
|
|
42 |
return True |
|
|
43 |
|
|
|
44 |
self.set_meta('fr','primer_not_matching', as_set=True) |
|
|
45 |
# Bad |
|
|
46 |
return False |
|
|
47 |
|
|
|
48 |
|
|
|
49 |
|
|
|
50 |
|
|
|
51 |
# Replace the equality function |
|
|
52 |
def __eq__(self, other): # other can also be a Molecule! |
|
|
53 |
# Make sure fragments map to the same strand, cheap comparisons |
|
|
54 |
if self.sample != other.sample: |
|
|
55 |
return False |
|
|
56 |
|
|
|
57 |
if self.strand != other.strand: |
|
|
58 |
return False |
|
|
59 |
|
|
|
60 |
if min(abs(self.span[1] - |
|
|
61 |
other.span[1]), abs(self.span[2] - |
|
|
62 |
other.span[2])) > self.assignment_radius: |
|
|
63 |
return False |
|
|
64 |
|
|
|
65 |
# Sample matches and starting position is within the defined span |
|
|
66 |
# radius |
|
|
67 |
return True |