GraDiv 0.1.0__py3-none-any.whl
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.
- gradiv/__init__.py +7 -0
- gradiv/_version.py +21 -0
- gradiv/algo.py +163 -0
- gradiv/functions.py +91 -0
- gradiv/main.py +241 -0
- gradiv/pggraph.py +361 -0
- gradiv/polymorphism.py +49 -0
- gradiv/tests.py +17 -0
- gradiv-0.1.0.dist-info/METADATA +763 -0
- gradiv-0.1.0.dist-info/RECORD +14 -0
- gradiv-0.1.0.dist-info/WHEEL +5 -0
- gradiv-0.1.0.dist-info/entry_points.txt +5 -0
- gradiv-0.1.0.dist-info/licenses/LICENSE +674 -0
- gradiv-0.1.0.dist-info/top_level.txt +1 -0
gradiv/pggraph.py
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import pysam
|
|
2
|
+
import sqlite3
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import shutil
|
|
5
|
+
from pybedtools import BedTool
|
|
6
|
+
|
|
7
|
+
d_sens = {1:'+', -1:'-', '+':1, '-':-1} #used to convert segment sense from numeric to symbol and vice versa
|
|
8
|
+
|
|
9
|
+
class Node:
|
|
10
|
+
"""
|
|
11
|
+
Node class representing a segment in a pangenome graph.
|
|
12
|
+
|
|
13
|
+
Attributes:
|
|
14
|
+
identifier: segment identifier (without sense)
|
|
15
|
+
sense: sense of the segment (1: forward, -1: reverse)
|
|
16
|
+
sequence: sequence of the segment
|
|
17
|
+
samples: set of samples using the segment (only genome)
|
|
18
|
+
complete_samples: set of samples using the segment (genome, chromosome and haplotype)
|
|
19
|
+
current_nodes: dictionary storaging all nodes used: parent(s), children and grandchildren (only used in parent node)
|
|
20
|
+
children: set of children nodes' full IDs (+/-ID)
|
|
21
|
+
parents: set of parents nodes' full IDs (+/-ID)
|
|
22
|
+
"""
|
|
23
|
+
def __init__(self, bam_segment:pysam.libcalignedsegment.AlignedSegment, sense:int) -> None:
|
|
24
|
+
"""
|
|
25
|
+
Initialize node
|
|
26
|
+
:param bam_segment: pysam BAM aligned segment from a GraTools index
|
|
27
|
+
:param graph_index: GraphIndex instance
|
|
28
|
+
:param sense: Sense of the segment: 1/-1
|
|
29
|
+
"""
|
|
30
|
+
self.identifier = bam_segment.query_name
|
|
31
|
+
self.sense = sense
|
|
32
|
+
if sense == -1:
|
|
33
|
+
self.sequence = Node.reverse_complement(bam_segment.query_sequence)
|
|
34
|
+
else :
|
|
35
|
+
self.sequence = bam_segment.query_sequence
|
|
36
|
+
self.samples = None
|
|
37
|
+
self.add_samples(bam_segment)
|
|
38
|
+
self.complete_samples = None
|
|
39
|
+
self.add_complete_samples(bam_segment)
|
|
40
|
+
self.current_nodes = None # only used for parent node
|
|
41
|
+
self.children = set()
|
|
42
|
+
self.parents = set()
|
|
43
|
+
|
|
44
|
+
def __str__(self) -> str:
|
|
45
|
+
return f'Node {self.get_full_id()} : {self.sequence}. Parents: {self.parents}. Children: {self.children}. Samples: {self.samples}.'
|
|
46
|
+
|
|
47
|
+
def __repr__(self) -> str:
|
|
48
|
+
return f'Node {self.get_full_id()}'
|
|
49
|
+
|
|
50
|
+
def add_samples (self, bam_segment) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Add samples supported by the node (only account sample name)
|
|
53
|
+
:param bam_segment: BAM segment
|
|
54
|
+
:return: None
|
|
55
|
+
"""
|
|
56
|
+
txt_samples = bam_segment.get_tag('SW')
|
|
57
|
+
samples_set = set(elm.split(";")[0] for elm in txt_samples.split(','))
|
|
58
|
+
self.samples = samples_set
|
|
59
|
+
|
|
60
|
+
def add_complete_samples (self, bam_segment) -> None:
|
|
61
|
+
"""
|
|
62
|
+
Add samples supported by the node (account sample name, chromosome and haplotype)
|
|
63
|
+
:param bam_segment: BAM segment
|
|
64
|
+
:return:None
|
|
65
|
+
"""
|
|
66
|
+
txt_samples = bam_segment.get_tag('SW')
|
|
67
|
+
samples = txt_samples.split(',')
|
|
68
|
+
samples_set = set(tuple(s.split(';')) for s in samples)
|
|
69
|
+
self.complete_samples = samples_set
|
|
70
|
+
|
|
71
|
+
def add_children(self, links:dict) -> None:
|
|
72
|
+
"""
|
|
73
|
+
Add children nodes' full IDs to children attribute
|
|
74
|
+
:param links: Dictionnary of current parent->child links
|
|
75
|
+
:return: None
|
|
76
|
+
"""
|
|
77
|
+
for parent_node in self.current_nodes.keys():
|
|
78
|
+
if parent_node in links.keys():
|
|
79
|
+
children = links[parent_node]
|
|
80
|
+
for child in children:
|
|
81
|
+
if self.current_nodes[child].samples.intersection(self.current_nodes[parent_node].samples):
|
|
82
|
+
if not self.current_nodes[parent_node].children:
|
|
83
|
+
self.current_nodes[parent_node].children = {child}
|
|
84
|
+
else:
|
|
85
|
+
self.current_nodes[parent_node].children.add(child)
|
|
86
|
+
|
|
87
|
+
def add_parents(self, graph_index:'GraphIndex') -> None:
|
|
88
|
+
"""
|
|
89
|
+
Add parents nodes' full IDs to parents attribute
|
|
90
|
+
:param graph_index: GraphIndex instance
|
|
91
|
+
:return: None
|
|
92
|
+
"""
|
|
93
|
+
for grandchild in self.get_grand_children():
|
|
94
|
+
self.current_nodes[grandchild].parents = set()
|
|
95
|
+
for link in graph_index.query_links(grandchild[1:]):
|
|
96
|
+
if link[3] == grandchild[1:]:
|
|
97
|
+
if link[0] == grandchild[1:]:
|
|
98
|
+
raise ValueError('Cycle detected')
|
|
99
|
+
else:
|
|
100
|
+
self.current_nodes[grandchild].parents.add(f'{d_sens[link[1]]}{link[0]}')
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def get_links(self, graph_index:'GraphIndex') -> tuple:
|
|
104
|
+
"""
|
|
105
|
+
Get all current parent->child links as a dictionary with IDs as keys and set of IDs as items.
|
|
106
|
+
Returns 4 variables : links dictionary, forward nodes as a set, reverse nodes as a set and boolean (True if not enough children to find a bubble).
|
|
107
|
+
:param graph_index: GraphIndex instance
|
|
108
|
+
:return: tuple of a links dictionary, forward set and reverse set
|
|
109
|
+
"""
|
|
110
|
+
links = {}
|
|
111
|
+
children = set()
|
|
112
|
+
forward_nodes = set()
|
|
113
|
+
reverse_nodes = set()
|
|
114
|
+
n_children_forward = 0
|
|
115
|
+
n_children_reverse = 0
|
|
116
|
+
# parse parent's children
|
|
117
|
+
for link in graph_index.query_links(self.identifier):
|
|
118
|
+
if link[0] == self.identifier: # only take links where the node is parent
|
|
119
|
+
parent_id = d_sens[link[1]] + link[0]
|
|
120
|
+
if link[3] == self.identifier:
|
|
121
|
+
raise ValueError('Cycle detected')
|
|
122
|
+
else:
|
|
123
|
+
if link[1] == 1:
|
|
124
|
+
forward_nodes.add(link[0])
|
|
125
|
+
n_children_forward += 1
|
|
126
|
+
else:
|
|
127
|
+
reverse_nodes.add(link[0])
|
|
128
|
+
n_children_reverse += 1
|
|
129
|
+
child_id = d_sens[link[4]] + link[3]
|
|
130
|
+
children.add(child_id)
|
|
131
|
+
if link[4] == 1:
|
|
132
|
+
forward_nodes.add(link[3])
|
|
133
|
+
else:
|
|
134
|
+
reverse_nodes.add(link[3])
|
|
135
|
+
if parent_id not in links.keys():
|
|
136
|
+
links[parent_id] = {child_id}
|
|
137
|
+
else :
|
|
138
|
+
links[parent_id].add(child_id)
|
|
139
|
+
if n_children_forward + n_children_reverse < 2 :
|
|
140
|
+
return links, forward_nodes, reverse_nodes, True
|
|
141
|
+
# parse children's children
|
|
142
|
+
for child in children:
|
|
143
|
+
for link in graph_index.query_links(child[1:]):
|
|
144
|
+
if link[0] == child[1:]: # only take links where the node is parent
|
|
145
|
+
if link[3] == child[1:]:
|
|
146
|
+
raise ValueError('Cycle detected')
|
|
147
|
+
else:
|
|
148
|
+
grand_child_id = d_sens[link[4]] + link[3]
|
|
149
|
+
if link[4] == 1:
|
|
150
|
+
forward_nodes.add(link[3])
|
|
151
|
+
else:
|
|
152
|
+
reverse_nodes.add(link[3])
|
|
153
|
+
if child not in links.keys():
|
|
154
|
+
links[child] = {grand_child_id}
|
|
155
|
+
else :
|
|
156
|
+
links[child].add(grand_child_id)
|
|
157
|
+
return links, forward_nodes, reverse_nodes, False
|
|
158
|
+
|
|
159
|
+
def create_nodes(self, nodes_id_set:set[str], sense:int, graph_index:'GraphIndex') -> None:
|
|
160
|
+
"""
|
|
161
|
+
Create nodes and store them in a dictionary (current_nodes attribute)
|
|
162
|
+
:param nodes_id_set: Set of node IDs (without sense)
|
|
163
|
+
:param sense: Sense + or -
|
|
164
|
+
:param graph_index: GraphIndex instance
|
|
165
|
+
:return: None
|
|
166
|
+
"""
|
|
167
|
+
for node_id in nodes_id_set:
|
|
168
|
+
full_id = str(d_sens[sense]) + node_id
|
|
169
|
+
if full_id not in self.current_nodes.keys():
|
|
170
|
+
segment = graph_index.query_segment(segment_id=node_id)
|
|
171
|
+
self.current_nodes[full_id] = Node(bam_segment=segment, sense=sense)
|
|
172
|
+
|
|
173
|
+
def get_grand_children(self) -> set[str] :
|
|
174
|
+
"""
|
|
175
|
+
:return: Dictionary of all grand children nodes
|
|
176
|
+
"""
|
|
177
|
+
grand_children = set()
|
|
178
|
+
for child_id in self.children:
|
|
179
|
+
for grandchild_id in self.current_nodes[child_id].children:
|
|
180
|
+
grand_children.add(grandchild_id)
|
|
181
|
+
return grand_children
|
|
182
|
+
|
|
183
|
+
def get_full_id(self):
|
|
184
|
+
"""
|
|
185
|
+
:return: Full ID of the node (+/-ID)
|
|
186
|
+
"""
|
|
187
|
+
return f'{d_sens[self.sense]}{self.identifier}'
|
|
188
|
+
|
|
189
|
+
def display_filiation(self):
|
|
190
|
+
"""
|
|
191
|
+
Display the node's filiation tree (from parent to granchildren)
|
|
192
|
+
"""
|
|
193
|
+
print(self.get_full_id())
|
|
194
|
+
for child in self.children:
|
|
195
|
+
print('\t|_', child)
|
|
196
|
+
for grandchild in self.current_nodes[child].children:
|
|
197
|
+
print('\t\t|_', grandchild)
|
|
198
|
+
|
|
199
|
+
@classmethod
|
|
200
|
+
def reverse_complement(cls, sequence:str) -> str:
|
|
201
|
+
"""
|
|
202
|
+
:param sequence: DNA sequence
|
|
203
|
+
:return: Reverse complement of the sequence
|
|
204
|
+
"""
|
|
205
|
+
rc_seq = ''
|
|
206
|
+
complements = {'A': 'T', 'C': 'G', 'G': 'C', 'T': 'A'}
|
|
207
|
+
for c in reversed(sequence):
|
|
208
|
+
if c in complements.keys():
|
|
209
|
+
rc_seq += complements[c]
|
|
210
|
+
else:
|
|
211
|
+
rc_seq += c
|
|
212
|
+
return rc_seq
|
|
213
|
+
|
|
214
|
+
@classmethod
|
|
215
|
+
def shared_samples(cls, node1:'Node', *args:'Node') -> set['Node']:
|
|
216
|
+
"""
|
|
217
|
+
Get shared samples between two nodes or more
|
|
218
|
+
:param node1: Node
|
|
219
|
+
:param args: Node(s)
|
|
220
|
+
:return: Set of samples
|
|
221
|
+
"""
|
|
222
|
+
#TODO: base off genome + chr + haplotype
|
|
223
|
+
intersection = node1.samples.copy()
|
|
224
|
+
for node in args:
|
|
225
|
+
intersection.intersection_update(node.samples)
|
|
226
|
+
return intersection
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class GraphIndex :
|
|
231
|
+
"""
|
|
232
|
+
Class representing a GraTools index and GraDiv genotype tables
|
|
233
|
+
|
|
234
|
+
Attributes:
|
|
235
|
+
gratools_directory: Path to GraTools index directory
|
|
236
|
+
pg_name: Pangenome graph name
|
|
237
|
+
samples: list of samples (used for outputs)
|
|
238
|
+
bam_path: path to BAM file
|
|
239
|
+
bam_file: open pysam alignment file
|
|
240
|
+
bam_index: index of BAM file on segment ID
|
|
241
|
+
bam_file_for_parsing: second open pysam alignment file for linear parsing
|
|
242
|
+
bed_directory_path: path to BED files directory
|
|
243
|
+
bed_files: dictionary of BED files path with sample name as key
|
|
244
|
+
db_path: path to links database
|
|
245
|
+
conn: sqlite3 connector to the link database
|
|
246
|
+
gradiv_directory: output directory path
|
|
247
|
+
id_table_path: path to genotype table with node IDs
|
|
248
|
+
seq_table_path: path to genotype table with node sequences
|
|
249
|
+
stats_path: path to statistics file output
|
|
250
|
+
"""
|
|
251
|
+
def __init__(self, gratools_directory:str):
|
|
252
|
+
"""
|
|
253
|
+
Initialize a graph index
|
|
254
|
+
:param gratools_directory: Path to GraTools index directory
|
|
255
|
+
"""
|
|
256
|
+
self.gratools_directory = Path(gratools_directory).resolve()
|
|
257
|
+
self.pg_name = self.gratools_directory.name.split('_GraTools_INDEX')[0]
|
|
258
|
+
self.samples = [] #TODO: add chromosome ?
|
|
259
|
+
|
|
260
|
+
# BAM related attributes
|
|
261
|
+
self.bam_path = self.gratools_directory / f'bam_files/{self.pg_name}.bam'
|
|
262
|
+
self.bam_file = pysam.AlignmentFile(str(self.bam_path), 'rb', check_sq=False) # intended for query
|
|
263
|
+
self.bam_index = None
|
|
264
|
+
self.bam_file_for_parsing = None
|
|
265
|
+
|
|
266
|
+
# BED related attributes
|
|
267
|
+
self.bed_directory_path = self.gratools_directory / 'bed_files'
|
|
268
|
+
self.bed_files = {}
|
|
269
|
+
for file in self.bed_directory_path.iterdir():
|
|
270
|
+
if file.suffix == '.bed':
|
|
271
|
+
self.bed_files[file.stem] = file
|
|
272
|
+
self.samples.append(file.stem)
|
|
273
|
+
self.samples = sorted(self.samples)
|
|
274
|
+
|
|
275
|
+
# Links DB related attributes
|
|
276
|
+
self.db_path = self.gratools_directory / f'links_{self.pg_name}.db'
|
|
277
|
+
self.conn = sqlite3.connect(str(self.db_path))
|
|
278
|
+
|
|
279
|
+
# Genotype tables related attributes
|
|
280
|
+
self.gradiv_directory = self.gratools_directory.parent / f'{self.pg_name}_gradiv'
|
|
281
|
+
self.id_table_path = self.gradiv_directory / f'{self.pg_name}_id_table.csv'
|
|
282
|
+
self.seq_table_path = self.gradiv_directory / f'{self.pg_name}_seq_table.csv'
|
|
283
|
+
self.stats_path = self.gradiv_directory / f'{self.pg_name}_stats.csv'
|
|
284
|
+
|
|
285
|
+
def make_bam_index_on_reads(self) -> None:
|
|
286
|
+
"""
|
|
287
|
+
Index BAM file on segment ID
|
|
288
|
+
:return: None
|
|
289
|
+
"""
|
|
290
|
+
self.bam_index = pysam.IndexedReads(self.bam_file)
|
|
291
|
+
self.bam_index.build()
|
|
292
|
+
|
|
293
|
+
def query_segment (self, segment_id:str) -> pysam.AlignedSegment|None:
|
|
294
|
+
"""
|
|
295
|
+
Query segment from BAM file on ID
|
|
296
|
+
:param segment_id: Segment ID
|
|
297
|
+
:return: BAM segment or None
|
|
298
|
+
"""
|
|
299
|
+
read_iterator = self.bam_index.find(segment_id)
|
|
300
|
+
for read in read_iterator:
|
|
301
|
+
return read
|
|
302
|
+
return None
|
|
303
|
+
|
|
304
|
+
def open_bam_for_parsing(self) -> None:
|
|
305
|
+
"""
|
|
306
|
+
Make temporary BAM file to parallelize BAM parsing and node query
|
|
307
|
+
:return: None
|
|
308
|
+
"""
|
|
309
|
+
self.bam_file_for_parsing = pysam.AlignmentFile(str(self.bam_path), 'rb', check_sq=False)
|
|
310
|
+
|
|
311
|
+
def close(self):
|
|
312
|
+
"""
|
|
313
|
+
Closes connections, files and removes temporary file
|
|
314
|
+
:return:
|
|
315
|
+
"""
|
|
316
|
+
self.conn.close()
|
|
317
|
+
self.bam_file.close()
|
|
318
|
+
if self.bam_file_for_parsing :
|
|
319
|
+
self.bam_file_for_parsing.close()
|
|
320
|
+
|
|
321
|
+
def query_links(self, segment_id: str) -> list:
|
|
322
|
+
"""
|
|
323
|
+
Fetch links from or to the segment
|
|
324
|
+
:param segment_id: query segment id
|
|
325
|
+
:return: list of rows
|
|
326
|
+
"""
|
|
327
|
+
cursor = self.conn.cursor()
|
|
328
|
+
cursor.execute('''
|
|
329
|
+
SELECT * FROM links WHERE seg_id_1 = ? OR seg_id_2 = ?
|
|
330
|
+
''', (segment_id, segment_id))
|
|
331
|
+
return cursor.fetchall()
|
|
332
|
+
|
|
333
|
+
def query_all_links(self) -> list:
|
|
334
|
+
"""
|
|
335
|
+
Fetch all links from the link database (intended for debug)
|
|
336
|
+
:return: list of rows
|
|
337
|
+
"""
|
|
338
|
+
cursor = self.conn.cursor()
|
|
339
|
+
cursor.execute('SELECT * FROM links')
|
|
340
|
+
return cursor.fetchall()
|
|
341
|
+
|
|
342
|
+
def make_gradiv_directory(self) -> None:
|
|
343
|
+
"""
|
|
344
|
+
Make gradiv directory if it does not exist
|
|
345
|
+
:return: None
|
|
346
|
+
"""
|
|
347
|
+
self.gradiv_directory.mkdir(parents=True, exist_ok=True)
|
|
348
|
+
|
|
349
|
+
def get_site_position(self, node_id:str, query:str, chrom:str) -> int:
|
|
350
|
+
"""
|
|
351
|
+
Get polymorphism position
|
|
352
|
+
:param node_id: ID (with sense) of node before the polymorphism
|
|
353
|
+
:param query: Query to use as a coordinate reference
|
|
354
|
+
:param chrom: Chromosome
|
|
355
|
+
:return: Position of
|
|
356
|
+
"""
|
|
357
|
+
bed_file = BedTool(str(self.bed_files[query]))
|
|
358
|
+
for interval in bed_file :
|
|
359
|
+
if interval.name == node_id and interval.chrom == chrom:
|
|
360
|
+
return interval.stop
|
|
361
|
+
return -1
|
gradiv/polymorphism.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import gradiv.pggraph as pggraph
|
|
2
|
+
|
|
3
|
+
class Polymorphism:
|
|
4
|
+
def __init__(self) -> None:
|
|
5
|
+
"""
|
|
6
|
+
Class representing one polymorphism
|
|
7
|
+
"""
|
|
8
|
+
self.node_per_sample = {}
|
|
9
|
+
|
|
10
|
+
def __str__(self) -> str:
|
|
11
|
+
return str(self.node_per_sample)
|
|
12
|
+
|
|
13
|
+
def add_substitution(self, parent:pggraph.Node, substitution_nodes:set[pggraph.Node], grandchild:pggraph.Node) -> None:
|
|
14
|
+
"""
|
|
15
|
+
Add alleles (as node IDs) corresponding to the samples involved in a substitution at this site. Can be used to add the node of an insertion.
|
|
16
|
+
:param parent: Node before the substitution
|
|
17
|
+
:param substitution_nodes: Set of node IDs involved in a substitution at this site
|
|
18
|
+
:param grandchild: Node after the substitution
|
|
19
|
+
:return: None
|
|
20
|
+
"""
|
|
21
|
+
for site_node_id in substitution_nodes:
|
|
22
|
+
allele_samples = pggraph.Node.shared_samples(parent, parent.current_nodes[site_node_id], grandchild)
|
|
23
|
+
for sample in allele_samples:
|
|
24
|
+
self.node_per_sample[sample] = parent.current_nodes[site_node_id].get_full_id()
|
|
25
|
+
|
|
26
|
+
def add_deletion(self, parent:pggraph.Node, grandchild:pggraph.Node) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Add deletion (*) corresponding to the samples involved in a deletion at this site
|
|
29
|
+
:param parent: Node before the deletion
|
|
30
|
+
:param grandchild: Node after the deletion
|
|
31
|
+
:return: None
|
|
32
|
+
"""
|
|
33
|
+
excluded_nodes_id = parent.children.difference({grandchild.get_full_id()})
|
|
34
|
+
excluded_samples = set()
|
|
35
|
+
for en_id in excluded_nodes_id:
|
|
36
|
+
excluded_samples.update(parent.current_nodes[en_id].samples)
|
|
37
|
+
allele_samples = pggraph.Node.shared_samples(parent, grandchild).difference(excluded_samples)
|
|
38
|
+
for sample in allele_samples:
|
|
39
|
+
self.node_per_sample[sample] = "*"
|
|
40
|
+
|
|
41
|
+
def add_undefined_values(self, all_samples:list[str]) -> None:
|
|
42
|
+
"""
|
|
43
|
+
Add undefined values (?) to samples not involved in the polymorphism
|
|
44
|
+
:param all_samples: List of all samples in the graph
|
|
45
|
+
:return: None
|
|
46
|
+
"""
|
|
47
|
+
for sample in all_samples:
|
|
48
|
+
if sample not in self.node_per_sample.keys():
|
|
49
|
+
self.node_per_sample[sample] = "?"
|
gradiv/tests.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import pysam
|
|
2
|
+
from pybedtools import BedTool
|
|
3
|
+
import gradiv.pggraph as pggraph
|
|
4
|
+
import pathlib
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
bam_for_linear_parsing = pysam.AlignmentFile('/home/imbert/Bureau/gradiv/test_data/test_graph_GraTools_INDEX/bam_files/test_graph.bam', check_sq=False)
|
|
9
|
+
bam_for_query = pysam.AlignmentFile('/home/imbert/Bureau/gradiv/test_data/test_graph_GraTools_INDEX/bam_files/test_graph.bam', check_sq=False)
|
|
10
|
+
bam_index = pysam.IndexedReads(bam_for_query)
|
|
11
|
+
|
|
12
|
+
for segment in bam_for_linear_parsing:
|
|
13
|
+
print(f'Parsing segment {segment.query_name}')
|
|
14
|
+
print("ok")
|
|
15
|
+
|
|
16
|
+
bam_for_linear_parsing.close()
|
|
17
|
+
bam_for_query.close()
|