annotate tools/human_genome_variation/senatag.py @ 1:cdcb0ce84a1b

Uploaded
author xuebing
date Fri, 09 Mar 2012 19:45:15 -0500
parents 9071e359b9a3
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
1 #!/usr/bin/env python
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
2
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
3 """
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
4 This tool takes the following file pairs as input:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
5 a) input_snp : A file with identifiers for SNPs (one on each line)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
6 b) ldfile : A file where each line has the following
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
7 snp list
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
8 where "snp" is an identifier for one SNP and the "list" is a
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
9 comma separated list of all the other snps that are in LD with
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
10 it (as per some threshold of rsquare)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
11
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
12 The output is a set of tag SNPs for the given datasets
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
13
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
14 The algorithm is as follows:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
15
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
16 a) Construct a graph for each population, where each node is a SNP and two nodes
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
17 are connected using an edge iff they are in LD.
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
18 b) For each SNP, count the total number of connected nodes, which have not yet
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
19 been visited.
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
20 c) Find the SNP with the highest count and assign it to be a tag SNP.
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
21 d) Mark that SNP and all the snps connected to it as "visited". This should be
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
22 done for each population.
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
23 e) Continue steps b-e until all SNPs, in all populations have been visited.
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
24 """
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
25
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
26 from sys import argv, stderr, exit
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
27 from getopt import getopt, GetoptError
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
28
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
29 import os
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
30 import heapq
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
31
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
32 __author__ = "Aakrosh Ratan"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
33 __email__ = "ratan@bx.psu.edu"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
34
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
35 # do we want the debug information to be printed?
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
36 debug_flag = False
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
37
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
38 class node:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
39 def __init__(self, name):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
40 self.name = name
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
41 self.edges = []
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
42 self.visited = False
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
43
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
44 # return the number of nodes connected to this node, that have yet to be
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
45 # visited
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
46 def num_not_visited(self):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
47 num = 0
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
48 for n in self.edges:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
49 if n.visited == False: num += 1
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
50 return num
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
51
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
52 def __cmp__(self, other):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
53 return other.num_not_visited() - self.num_not_visited()
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
54
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
55 def __str__(self):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
56 return self.name
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
57
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
58 class graph:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
59 def __init__(self):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
60 self.nodes = {}
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
61
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
62 def __str__(self):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
63 string = ""
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
64 for n1 in self.nodes.values():
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
65 n2s = [x.name for x in n1.edges]
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
66 string += "%s %s\n" % (n1.name, ",".join(n2s))
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
67 return string[:-1]
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
68
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
69 def add_node(self, n):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
70 self.nodes[n.name] = n
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
71
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
72 def add_edges(self, n1, n2):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
73 assert n1.name in self.nodes
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
74 assert n2.name in self.nodes
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
75 n1.edges.append(n2)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
76 n2.edges.append(n1)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
77
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
78 def check_graph(self):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
79 for n in self.nodes.values():
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
80 ms = [x for x in n.edges]
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
81 for m in ms:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
82 if n not in m.edges:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
83 print >> stderr, "check : %s - %s" % (n,m)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
84
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
85 def construct_graph(ldfile, snpfile):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
86 # construct the initial graph. add all the SNPs as nodes
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
87 g = graph()
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
88 file = open(snpfile, "r")
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
89
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
90 for line in file:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
91 # ignore empty lines and add the remainder to the graph
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
92 if len(line.strip()) == 0: continue
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
93 n = node(line.strip())
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
94 g.add_node(n)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
95
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
96 file.close()
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
97 print >> stderr, "Added %d nodes to a graph" % len(g.nodes)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
98
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
99 # now add all the edges
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
100 file = open(ldfile, "r")
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
101
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
102 for line in file:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
103 tokens = line.split()
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
104 assert len(tokens) == 2
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
105
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
106 # if this node is in the graph, then we need to construct an edge from
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
107 # this node to all the nodes which are highly related to it
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
108 if tokens[0] in g.nodes:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
109 n1 = g.nodes[tokens[0]]
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
110 n2s = [g.nodes[x] for x in tokens[1].split(",")]
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
111
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
112 for n2 in n2s:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
113 g.add_edges(n1, n2)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
114
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
115 file.close()
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
116 print >> stderr, "Added all edges to the graph"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
117
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
118 return g
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
119
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
120 def check_output(g, tagsnps):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
121 # find all the nodes in the graph
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
122 allsnps = [x.name for x in g.nodes.values()]
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
123
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
124 # find the nodes that are covered by our tagsnps
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
125 mysnps = [x.name for x in tagsnps]
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
126
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
127 for n in tagsnps:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
128 for m in n.edges:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
129 mysnps.append(m.name)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
130
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
131 mysnps = list(set(mysnps))
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
132
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
133 if set(allsnps) != set(mysnps):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
134 diff = list(set(allsnps) - set(mysnps))
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
135 print >> stderr, "%s are not covered" % ",".join(diff)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
136
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
137 def main(ldfile, snpsfile, required, excluded):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
138 # construct the graph
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
139 g = construct_graph(ldfile, snpsfile)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
140 if debug_flag == True: g.check_graph()
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
141
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
142 tagsnps = []
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
143 neighbors = {}
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
144
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
145 # take care of the SNPs that are required to be TagSNPs
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
146 for s in required:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
147 t = g.nodes[s]
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
148
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
149 t.visited = True
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
150 ns = []
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
151
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
152 for n in t.edges:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
153 if n.visited == False: ns.append(n.name)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
154 n.visited = True
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
155
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
156 tagsnps.append(t)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
157 neighbors[t.name] = list(set(ns))
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
158
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
159 # find the tag SNPs for this graph
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
160 data = [x for x in g.nodes.values()]
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
161 heapq.heapify(data)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
162
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
163 while data:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
164 s = heapq.heappop(data)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
165
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
166 if s.visited == True or s.name in excluded: continue
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
167
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
168 s.visited = True
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
169 ns = []
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
170
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
171 for n in s.edges:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
172 if n.visited == False: ns.append(n.name)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
173 n.visited = True
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
174
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
175 tagsnps.append(s)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
176 neighbors[s.name] = list(set(ns))
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
177
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
178 heapq.heapify(data)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
179
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
180 for s in tagsnps:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
181 if len(neighbors[s.name]) > 0:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
182 print "%s\t%s" % (s, ",".join(neighbors[s.name]))
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
183 continue
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
184 print s
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
185
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
186 if debug_flag == True: check_output(g, tagsnps)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
187
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
188 def read_list(filename):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
189 assert os.path.exists(filename) == True
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
190 file = open(filename, "r")
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
191 list = {}
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
192
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
193 for line in file:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
194 list[line.strip()] = 1
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
195
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
196 file.close()
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
197 return list
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
198
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
199 def usage():
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
200 f = stderr
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
201 print >> f, "usage:"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
202 print >> f, "senatag [options] neighborhood.txt inputsnps.txt"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
203 print >> f, "where inputsnps.txt is a file of snps from one population"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
204 print >> f, "where neighborhood.txt is neighborhood details for the pop."
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
205 print >> f, "where the options are:"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
206 print >> f, "-h,--help : print usage and quit"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
207 print >> f, "-d,--debug: print debug information"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
208 print >> f, "-e,--excluded : file with names of SNPs that cannot be TagSNPs"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
209 print >> f, "-r,--required : file with names of SNPs that should be TagSNPs"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
210
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
211 if __name__ == "__main__":
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
212 try:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
213 opts, args = getopt(argv[1:], "hdr:e:",\
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
214 ["help", "debug", "required=", "excluded="])
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
215 except GetoptError, err:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
216 print str(err)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
217 usage()
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
218 exit(2)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
219
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
220 required = {}
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
221 excluded = {}
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
222
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
223 for o, a in opts:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
224 if o in ("-h", "--help"):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
225 usage()
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
226 exit()
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
227 elif o in ("-d", "--debug"):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
228 debug_flag = True
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
229 elif o in ("-r", "--required"):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
230 required = read_list(a)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
231 elif o in ("-e", "--excluded"):
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
232 excluded = read_list(a)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
233 else:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
234 assert False, "unhandled option"
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
235
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
236 if len(args) != 2:
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
237 usage()
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
238 exit(3)
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
239
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
240 assert os.path.exists(args[0]) == True
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
241 assert os.path.exists(args[1]) == True
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
242
9071e359b9a3 Uploaded
xuebing
parents:
diff changeset
243 main(args[0], args[1], required, excluded)