comparison bin/pact_wrapper.py @ 0:d67268158946 draft

planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author bcclaywell
date Mon, 12 Oct 2015 17:43:33 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:d67268158946
1 #!/usr/bin/env python
2
3 import argparse
4 from os import path
5 import re
6 import os
7 import csv
8 import shutil
9 import subprocess
10
11
12 setting_template = """
13 # TREE MANIPULATION
14 {prune}
15
16 # TREE OUTPUT
17 print rule tree # print out the tree...
18
19 # SUMMARY STATS
20 summary tmrca # time to mrca
21 summary proportions # proportions on trunk of geneology
22 summary coal rates # coalescent rates; separate for each label
23 summary mig rates # migration rates; separate for each label pair
24 #summary fst # diversity between vs within labels
25
26 skyline settings -{sky_start} -{sky_end} {sky_interval}
27 skyline proportions
28 """
29
30
31 def tips_from_label(meta_reader, label, deme_col="deme"):
32 return [row['sequence'] for row in meta_reader if row[deme_col] == label]
33
34 def tips_from_labels(meta_reader, labels, deme_col="deme"):
35 return [row['sequence'] for row in meta_reader if row[deme_col] in labels]
36
37 def translate_tips(tips, translation):
38 result = list()
39 for tip in tips:
40 try:
41 result.append(translation[tip])
42 except KeyError:
43 pass
44 return result
45
46
47 def translation_from_nexus(handle):
48 """This reads the seqname -> id translation from the trees file. Should probably eventually move this out
49 and into a separate file so that we can use the results in plotting. Not now though..."""
50 in_trans = False
51 trans = dict()
52 for line in handle:
53 if re.search("Translate", line):
54 # This is the demarkator for the translation section of the nexus file
55 in_trans = True
56 continue
57 if in_trans:
58 if re.match(";", line):
59 # If we hit this, we've reached the end of the translation region
60 break
61 else:
62 # Otherwise we're still in the Translate region, so populate trans
63 index, name = line.strip().strip(',').split()
64 trans[name] = index
65 return trans
66
67
68 def prune_tips_string(tips, args):
69 if args.translate_trees:
70 trans = translation_from_nexus(file(args.trees_in))
71 tips = translate_tips(tips, trans)
72 return "prune to tips " + " ".join(tips)
73
74
75 def prune_string(args):
76 if args.labels:
77 if args.metadata:
78 labels = args.labels.replace("\"", "").replace("'", "").split()
79 print "Pruning to labels:", labels
80 tips = tips_from_labels(csv.DictReader(args.metadata), labels, deme_col=args.deme_col)
81 print "Tips for labels are:", tips
82 return prune_tips_string(tips, args)
83 else:
84 return "prune to label " + args.labels
85
86 elif args.tip_file or args.tips:
87 if args.tip_file:
88 tips = args.tip_file.read().split()
89 else:
90 tips = args.tips.replace("'", "").replace("\"", "").split()
91 print "Tips specified are:", tips
92 return prune_tips_string(tips, args)
93 else:
94 return ""
95
96
97 def get_args():
98 parser = argparse.ArgumentParser()
99 parser.add_argument('trees_in')
100 parser.add_argument('-t', '--tips', help="List of tips in quotes")
101 parser.add_argument('-T', '--tip-file', help="File of tips sep by space", type=argparse.FileType('r'))
102 parser.add_argument('-r', '--translate-trees', action="store_true", default=False,
103 help="""If flagged, the trees_in file will be used for translating tip names from indices to actual
104 tip names; this is necessary for BEAST runs only""")
105 parser.add_argument('-m', '--metadata', type=argparse.FileType('r'),
106 help="""Required for filtering by deme/label with the beast method""")
107 parser.add_argument('-l', '--labels')
108 parser.add_argument('-s', '--sky-start', default=2.0, type=float,
109 help="How far back to compute skyline statistics (should be a potive number)")
110 parser.add_argument('-S', '--trim-start', type=float,
111 help="""Trim the tree from 0 back to the specified time; overrides sky-start for skyline plots.
112 (should be a positive number)""")
113 parser.add_argument('-e', '--trim-end', default=0.0, type=float,
114 help="Most recent time to trim to in time interval; will also be used for sky (should be non-negative)")
115 parser.add_argument('-o', '--out-dir')
116 parser.add_argument('-p', '--prune-to-trunk', action="store_true", default=False)
117 parser.add_argument('-d', '--deme-col', default="deme", help="Deme column in metadata file")
118 return parser.parse_args()
119
120
121 def main():
122 args = get_args()
123
124 # Create the param file in the proper directory
125 outfile = file(path.join(args.out_dir, 'in.param'), 'w')
126
127 prune = prune_string(args)
128 if args.prune_to_trunk:
129 prune += "\nprune to trunk"
130
131 if args.trim_start:
132 prune += "\ntrim ends -%s -%s" % (args.trim_start, args.trim_end)
133
134 sky_start = args.trim_start if args.trim_start else args.sky_start
135 sky_end = args.trim_end
136 sky_interval = abs(sky_end - sky_start) / 100
137 outfile.write(setting_template.format(
138 prune=prune,
139 sky_end=sky_end,
140 sky_start=sky_start,
141 sky_interval=sky_interval))
142 outfile.close()
143
144 # Copy the tree file over to the directory
145 shutil.copyfile(args.trees_in, path.join(args.out_dir, 'in.trees'))
146
147 # Actually run PACT
148 os.chdir(args.out_dir)
149 subprocess.check_call(['pact'])
150
151
152 if __name__ == '__main__':
153 main()
154
155