-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathconvertToGFA.py
executable file
·123 lines (102 loc) · 5.43 KB
/
convertToGFA.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python
'''****************************************************************************
* Program - Convert To GFA format
* Author - Mayank Pahadia
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
****************************************************************************'''
'''****************************************************************************
* To run the program, pass three arguments with the python script on command line.
* For example - python convertToGFA.py inputFileName outputFileName kmerSize
* Logic - It reads through the fasta file with all the unitigs information
* and link information and outputs it in the GFA format.
****************************************************************************'''
import sys
import argparse
def write_segment(name,segment,optional,g,links):
add = ""
add += "S\t" #for segment
add += name #id of segment
add += "\t"
add += segment #segment itself
add += "\t"
for i in optional: #optional tags
add+=i
add+="\t"
#adding Segment to the file
g.write(add.strip()+"\n")
for j in links: #adding all the links of the current segment to the GFA file
g.write(j)
def main():
parser = argparse.ArgumentParser(description="Convert a bcalm-generated FASTA to a GFA.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('inputFilename', help='Input FASTA file')
parser.add_argument('outputFilename', help='Output GFA file')
parser.add_argument('kmerSize', type=int, help='k-mer length')
parser.add_argument('-s', '--single-directed', action='store_true',
help='Avoid outputting the whole skew-simmetric graph and output only one edge between two nodes',
dest='single_directed')
args = parser.parse_args()
with open(args.inputFilename) as f:
#name stores the id of the unitig
#optional is a list which stores all the optional tags of a segment
#links stores all the link information about a segment
name = ""
optional=[]
links=[]
g = open(args.outputFilename,'w')
#adding Header to the file
k = int(args.kmerSize)
g.write('H\tVN:Z:1.0\tks:i:%d\n' %k) # includes the k-mer size
print("GFA file open")
#firstLine is for implemetation purpose so that we don't add some garbage value to the output file.
firstLine = 0
#segment stores the segment till present, in a fasta file, segment can be on many lines, hence we need to get the whole segment from all the lines
segment = ""
for line in f:
line = line.replace("\n","")
if(line[0]!=">"):
#segment might be in more than one line, hence we get the whole segment first, and then put it in the GFA file.
segment += line
if(line[0]==">"):
if(firstLine!=0):#if it's not the firstline in the input file, we store the input in GFA format in the output file
write_segment(name,segment,optional,g,links)
segment = ""
firstLine = 1
#once the previous segment and it's information has been stored, we start the next segment and it's information
a = line.split(" ")
name=a[0][1:] #get the id
optional=[]
links = []
#we skip the first value because the first value is ">ID"
for i in range(1,len(a)):
#we need this because the line can end with a space, hence we get one extra value in our list.
if(a[i]==""):
continue
if(a[i][0:2] == "MA"): #previous bcalm2 versions had "MA=[xxx]" optional tag as well, kept it just for compatibility, and reformated
optional.append(a[i][0:2]+":f:"+a[i][2:])
elif(a[i][0:2] == "L:"): #for links
b = a[i].split(":")
k1 = int(args.kmerSize)-1
if args.single_directed:
if name < b[2]:
links.append("L\t"+name+"\t"+b[1]+"\t"+b[2]+"\t"+b[3]+"\t"+str(k1)+"M\n")
elif name == b[2] and not (b[1] == b[3] == '-'): # manage links between the same unitig
links.append("L\t"+name+"\t"+b[1]+"\t"+b[2]+"\t"+b[3]+"\t"+str(k1)+"M\n")
else:
links.append("L\t"+name+"\t"+b[1]+"\t"+b[2]+"\t"+b[3]+"\t"+str(k1)+"M\n")
else: #all the other optional tags
optional.append(a[i])
#we will miss the last one, because it won't go into the if condition - if(line[0]==">") and hence won't add the segment to the file.
write_segment(name,segment,optional,g,links)
print("done")
g.close()
if __name__ == "__main__":
main()