Mercurial > repos > miller-lab > genome_diversity
comparison dpmix_plot.py @ 31:a631c2f6d913
Update to Miller Lab devshed revision 3c4110ffacc3
author | Richard Burhans <burhans@bx.psu.edu> |
---|---|
date | Fri, 20 Sep 2013 13:25:27 -0400 |
parents | 8997f2ca8c7a |
children |
comparison
equal
deleted
inserted
replaced
30:4188853b940b | 31:a631c2f6d913 |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 | 2 |
3 import os | 3 import os |
4 import sys | 4 import sys |
5 import math | 5 import math |
6 | |
6 import matplotlib as mpl | 7 import matplotlib as mpl |
7 mpl.use('PDF') | 8 mpl.use('PDF') |
9 from matplotlib.backends.backend_pdf import PdfPages | |
8 import matplotlib.pyplot as plt | 10 import matplotlib.pyplot as plt |
9 from matplotlib.path import Path | 11 from matplotlib.path import Path |
10 import matplotlib.patches as patches | 12 import matplotlib.patches as patches |
11 | 13 |
12 ################################################################################ | 14 ################################################################################ |
224 # labels.append('{0:.1f}'.format(vals[-1]/math.pow(10, digits))) | 226 # labels.append('{0:.1f}'.format(vals[-1]/math.pow(10, digits))) |
225 | 227 |
226 return vals, labels | 228 return vals, labels |
227 | 229 |
228 ################################################################################ | 230 ################################################################################ |
231 ################################################################################ | |
232 ################################################################################ | |
233 ################################################################################ | |
234 | |
235 def space_for_legend(plot_params): | |
236 space = 0.0 | |
237 | |
238 legend_states = plot_params['legend_states'] | |
239 if legend_states: | |
240 ind_space = plot_params['ind_space'] | |
241 ind_height = plot_params['ind_height'] | |
242 space += len(legend_states) * (ind_space + ind_height) - ind_space | |
243 | |
244 return space | |
245 | |
246 ################################################################################ | |
247 | |
248 def space_for_chroms(plot_params, chroms, individuals, data): | |
249 space_dict = {} | |
250 | |
251 chrom_height = plot_params['chrom_height'] | |
252 ind_space = plot_params['ind_space'] | |
253 ind_height = plot_params['ind_height'] | |
254 | |
255 for chrom in chroms: | |
256 space_dict[chrom] = chrom_height | |
257 | |
258 individual_count = 0 | |
259 for individual in individuals: | |
260 if individual in data[chrom]: | |
261 individual_count += 1 | |
262 | |
263 space_dict[chrom] += individual_count * (ind_space + ind_height) | |
264 | |
265 return space_dict | |
266 | |
267 ################################################################################ | |
229 | 268 |
230 def make_dpmix_plot(input_dbkey, input_file, output_file, galaxy_data_index_dir, state2name=None, populations=3): | 269 def make_dpmix_plot(input_dbkey, input_file, output_file, galaxy_data_index_dir, state2name=None, populations=3): |
231 fs_chrom_len = build_chrom_len_dict(input_dbkey, galaxy_data_index_dir) | 270 fs_chrom_len = build_chrom_len_dict(input_dbkey, galaxy_data_index_dir) |
232 chroms, individuals, data, chrom_len, used_states = parse_input_file(input_file) | 271 chroms, individuals, data, chrom_len, used_states = parse_input_file(input_file) |
233 | 272 |
234 if populations == 3: | 273 ## populate chrom_len |
235 make_state_rectangle = make_state_rectangle_3pop | |
236 elif populations == 2: | |
237 make_state_rectangle = make_state_rectangle_2pop | |
238 else: | |
239 pass | |
240 | |
241 for chrom in chrom_len.keys(): | 274 for chrom in chrom_len.keys(): |
242 if chrom in fs_chrom_len: | 275 if chrom in fs_chrom_len: |
243 chrom_len[chrom] = fs_chrom_len[chrom] | 276 chrom_len[chrom] = fs_chrom_len[chrom] |
244 | 277 |
245 #check_chroms(chroms, chrom_len, input_dbkey) | 278 #check_chroms(chroms, chrom_len, input_dbkey) |
246 check_data(data, chrom_len, input_dbkey) | 279 check_data(data, chrom_len, input_dbkey) |
247 | 280 |
248 ## units below are inches | 281 ## plot parameters |
249 top_space = 0.10 | 282 plot_params = { |
250 chrom_space = 0.25 | 283 'plot_dpi': 300, |
251 chrom_height = 0.25 | 284 'page_width': 8.50, |
252 ind_space = 0.10 | 285 'page_height': 11.00, |
253 ind_height = 0.25 | 286 'top_margin': 0.10, |
254 | 287 'bottom_margin': 0.10, |
255 total_height = 0.0 | 288 'chrom_space': 0.25, |
256 | 289 'chrom_height': 0.25, |
257 ## make a legend | 290 'ind_space': 0.10, |
258 ## only print out states that are | 291 'ind_height': 0.25, |
292 'legend_space': 0.10 | |
293 } | |
294 | |
295 ## in the legend, only print out states that are | |
259 ## 1) in the data | 296 ## 1) in the data |
260 ## - AND - | 297 ## - AND - |
261 ## 2) in the state2name map | 298 ## 2) in the state2name map |
262 ## here, we only calculate the space needed | |
263 legend_states = [] | 299 legend_states = [] |
264 if state2name is not None: | 300 if state2name is not None: |
265 for state in used_states: | 301 for state in used_states: |
266 if state in state2name: | 302 if state in state2name: |
267 legend_states.append(state) | 303 legend_states.append(state) |
268 | 304 |
269 if legend_states: | 305 plot_params['legend_states'] = legend_states |
270 total_height += len(legend_states) * (ind_space + ind_height) | 306 |
271 total_height += (top_space - ind_space) | 307 ## choose the correct make_state_rectangle method |
272 at_top = False | 308 if populations == 3: |
273 else: | 309 plot_params['rectangle_method'] = make_state_rectangle_3pop |
274 at_top = True | 310 elif populations == 2: |
275 | 311 plot_params['rectangle_method'] = make_state_rectangle_2pop |
276 for chrom in chroms: | 312 |
277 if at_top: | 313 pdf_pages = PdfPages(output_file) |
278 total_height += (top_space + chrom_height) | 314 |
279 at_top = False | 315 ## generate a list of chroms for each page |
316 | |
317 needed_for_legend = space_for_legend(plot_params) | |
318 needed_for_chroms = space_for_chroms(plot_params, chroms, individuals, data) | |
319 | |
320 chrom_space_per_page = plot_params['page_height'] | |
321 chrom_space_per_page -= plot_params['top_margin'] + plot_params['bottom_margin'] | |
322 chrom_space_per_page -= needed_for_legend + plot_params['legend_space'] | |
323 chrom_space_per_page -= plot_params['chrom_space'] | |
324 | |
325 chroms_left = chroms[:] | |
326 pages = [] | |
327 | |
328 space_left = chrom_space_per_page | |
329 chrom_list = [] | |
330 | |
331 while chroms_left: | |
332 chrom = chroms_left.pop(0) | |
333 space_needed = needed_for_chroms[chrom] + plot_params['chrom_space'] | |
334 if (space_needed > chrom_space_per_page): | |
335 print >> sys.stderr, 'Multipage chroms not yet supported' | |
336 sys.exit(1) | |
337 | |
338 ## sometimes 1.9 - 1.9 < 0 (-4.4408920985e-16) | |
339 ## so, we make sure it's not more than a millimeter over | |
340 if space_left - space_needed > -0.04: | |
341 chrom_list.append(chrom) | |
342 space_left -= space_needed | |
280 else: | 343 else: |
281 total_height += (top_space + chrom_space + chrom_height) | 344 pages.append(chrom_list[:]) |
282 | 345 chrom_list = [] |
283 individual_count = 0 | 346 chroms_left.insert(0, chrom) |
284 for individual in individuals: | 347 space_left = chrom_space_per_page |
285 if individual in data[chrom]: | 348 |
286 individual_count += 1 | 349 ############################################################################ |
287 total_height += individual_count * (ind_space + ind_height) | 350 |
288 | 351 plot_dpi = plot_params['plot_dpi'] |
289 width = 7.5 | 352 page_width = plot_params['page_width'] |
290 height = math.ceil(total_height) | 353 page_height = plot_params['page_height'] |
291 | 354 top_margin = plot_params['top_margin'] |
292 bottom = 1.0 | 355 ind_space = plot_params['ind_space'] |
293 | 356 ind_height = plot_params['ind_height'] |
294 fig = plt.figure(figsize=(width, height)) | 357 make_state_rectangle = plot_params['rectangle_method'] |
295 | 358 legend_space = plot_params['legend_space'] |
296 if legend_states: | 359 chrom_space = plot_params['chrom_space'] |
297 at_top = True | 360 chrom_height = plot_params['chrom_height'] |
298 for state in sorted(legend_states): | 361 |
299 if at_top: | 362 for page in pages: |
300 bottom -= (top_space + ind_height)/height | 363 fig = plt.figure(figsize=(page_width, page_height), dpi=plot_dpi) |
301 at_top = False | 364 bottom = 1.0 - (top_margin/page_height) |
365 | |
366 # print legend | |
367 if legend_states: | |
368 top = True | |
369 for state in sorted(legend_states): | |
370 if top: | |
371 bottom -= ind_height/page_height | |
372 top = False | |
373 else: | |
374 bottom -= (ind_space + ind_height)/page_height | |
375 | |
376 ax1 = fig.add_axes([0.0, bottom, 0.09, ind_height/page_height]) | |
377 plt.axis('off') | |
378 ax1.set_xlim(0, 1) | |
379 ax1.set_ylim(0, 1) | |
380 for patch in make_state_rectangle(0, 1, state, 'legend', state2name[state]): | |
381 ax1.add_patch(patch) | |
382 | |
383 ax2 = fig.add_axes([0.10, bottom, 0.88, ind_height/page_height], frame_on=False) | |
384 plt.axis('off') | |
385 plt.text(0.0, 0.5, state2name[state], fontsize=10, ha='left', va='center') | |
386 | |
387 bottom -= legend_space/page_height | |
388 | |
389 # print chroms | |
390 top = True | |
391 for chrom in page: | |
392 length = chrom_len[chrom] | |
393 vals, labels = tick_foo(0, length) | |
394 | |
395 if top: | |
396 bottom -= chrom_height/page_height | |
397 top = False | |
302 else: | 398 else: |
303 bottom -= (ind_space + ind_height)/height | 399 bottom -= (chrom_space + chrom_height)/page_height |
304 ## add code here to draw legend | 400 |
305 # [left, bottom, width, height] | 401 ax = fig.add_axes([0.0, bottom, 1.0, chrom_height/page_height]) |
306 ax1 = fig.add_axes([0.0, bottom, 0.09, ind_height/height]) | |
307 plt.axis('off') | |
308 ax1.set_xlim(0, 1) | |
309 ax1.set_ylim(0, 1) | |
310 for patch in make_state_rectangle(0, 1, state, 'legend', state2name[state]): | |
311 ax1.add_patch(patch) | |
312 | |
313 ax2 = fig.add_axes([0.10, bottom, 0.88, ind_height/height], frame_on=False) | |
314 plt.axis('off') | |
315 plt.text(0.0, 0.5, state2name[state], fontsize=10, ha='left', va='center') | |
316 else: | |
317 at_top = True | |
318 | |
319 for_webb = False | |
320 | |
321 for chrom in chroms: | |
322 length = chrom_len[chrom] | |
323 vals, labels = tick_foo(0, length) | |
324 | |
325 if at_top: | |
326 bottom -= (top_space + chrom_height)/height | |
327 at_top = False | |
328 else: | |
329 bottom -= (top_space + chrom_space + chrom_height)/height | |
330 | |
331 if not for_webb: | |
332 ax = fig.add_axes([0.0, bottom, 1.0, chrom_height/height]) | |
333 plt.axis('off') | 402 plt.axis('off') |
334 plt.text(0.5, 0.5, chrom, fontsize=14, ha='center') | 403 plt.text(0.5, 0.5, chrom, fontsize=14, ha='center') |
335 | 404 |
336 individual_count = 0 | 405 individual_count = 0 |
337 for individual in individuals: | 406 for individual in individuals: |
338 if individual in data[chrom]: | 407 if individual in data[chrom]: |
339 individual_count += 1 | 408 individual_count += 1 |
340 | 409 |
341 i = 0 | 410 i = 0 |
342 for individual in individuals: | 411 for individual in individuals: |
343 if individual in data[chrom]: | 412 if individual in data[chrom]: |
344 i += 1 | 413 i += 1 |
345 | 414 bottom -= (ind_space + ind_height)/page_height |
346 bottom -= (ind_space + ind_height)/height | 415 |
347 if not for_webb: | 416 ax1 = fig.add_axes([0.0, bottom, 0.09, ind_height/page_height]) |
348 # [left, bottom, width, height] | |
349 ax1 = fig.add_axes([0.0, bottom, 0.09, ind_height/height]) | |
350 plt.axis('off') | 417 plt.axis('off') |
351 plt.text(1.0, 0.5, individual, fontsize=10, ha='right', va='center') | 418 plt.text(1.0, 0.5, individual, fontsize=10, ha='right', va='center') |
352 # [left, bottom, width, height] | 419 |
353 ax2 = fig.add_axes([0.10, bottom, 0.88, ind_height/height], frame_on=False) | 420 ax2 = fig.add_axes([0.10, bottom, 0.88, ind_height/page_height], frame_on=False) |
354 ax2.set_xlim(0, length) | 421 ax2.set_xlim(0, length) |
355 ax2.set_ylim(0, 1) | 422 ax2.set_ylim(0, 1) |
356 if i != individual_count: | 423 |
357 plt.axis('off') | 424 if i != individual_count: |
358 else: | 425 plt.axis('off') |
359 if not for_webb: | 426 else: |
360 ax2.tick_params(top=False, left=False, right=False, labelleft=False) | 427 ax2.tick_params(top=False, left=False, right=False, labelleft=False) |
361 ax2.set_xticks(vals) | 428 ax2.set_xticks(vals) |
362 ax2.set_xticklabels(labels) | 429 ax2.set_xticklabels(labels) |
363 else: | 430 |
364 plt.axis('off') | 431 for p1, p2, state in sorted(data[chrom][individual]): |
365 for p1, p2, state in sorted(data[chrom][individual]): | 432 for patch in make_state_rectangle(p1, p2, state, chrom, individual): |
366 #for patch in make_state_rectangle(p1, p2, state, chrom, individual): | 433 ax2.add_patch(patch) |
367 for patch in make_state_rectangle(p1, p2, state, chrom, individual): | 434 |
368 ax2.add_patch(patch) | 435 # extend last state to end of chrom |
369 | 436 if p2 < length: |
370 plt.savefig(output_file) | 437 for patch in make_state_rectangle(p2, length, state, chrom, individual): |
438 ax2.add_patch(patch) | |
439 | |
440 | |
441 pdf_pages.savefig(fig) | |
442 plt.close(fig) | |
443 | |
444 pdf_pages.close() | |
371 | 445 |
372 ################################################################################ | 446 ################################################################################ |
373 | 447 |
374 if __name__ == '__main__': | 448 if __name__ == '__main__': |
375 input_dbkey, input_file, output_file, galaxy_data_index_dir = sys.argv[1:5] | 449 make_dpmix_plot('loxAfr3', 'output.dat', 'output2_files/picture.pdf', '/scratch/galaxy/home/oocyte/galaxy_oocyte/tool-data', state2name={0: 'heterochromatin', 1: 'reference', 2: 'asian'}, populations=2) |
376 make_dpmix_plot(input_dbkey, input_file, output_file, galaxy_data_index_dir) | 450 # input_dbkey, input_file, output_file, galaxy_data_index_dir = sys.argv[1:5] |
451 # make_dpmix_plot(input_dbkey, input_file, output_file, galaxy_data_index_dir) | |
377 sys.exit(0) | 452 sys.exit(0) |
378 | 453 |
379 ## notes | 454 ## notes |
380 # 1) pass in a state to name mapping | 455 # 1) pass in a state to name mapping |
381 # 2) only print out names for states which exist in the data, and are in the state to name mapping | 456 # 2) only print out names for states which exist in the data, and are in the state to name mapping |