annotate roi_plot_thumbnails.py @ 1:0ac4f6f3d984 draft

Uploaded
author holtgrewe
date Mon, 06 May 2013 12:34:43 -0400
parents 61d9bdb6d519
children 170e48a55078
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
1 #!/usr/bin/env python
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
2 """Thumbnail Plot Generator.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
3
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
4 This report generator uses the binary roi_plot_thumbnails (C++ program, must
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
5 be in PATH) to generate many PNG images with small ROI plots. It then creates
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
6 a HTML file that includes the PNG and adds an overlay image link map such that
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
7 when the user clicks on a plot, she is transfered to the according position in
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
8 a local IGV or the UCSC genome browser, for example.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
9 """
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
10
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
11 __author__ = 'Manuel Holtgrewe <manuel.holtgrewe@fu-berlin.de>'
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
12 __copyright__ = 'Copyring 2013, Freie Universitaet Berlin'
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
13 __license__ = 'BSD 3-clause'
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
14
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
15 # TODO(holtgrew): Use Cheetah templates to generate HTML.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
16 # TODO(holtgrew): Call roi_plot_thumbnails from Python script.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
17 # TODO(holtgrew): from __future__ use print_function
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
18
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
19
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
20 import argparse
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
21 import math
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
22 import os.path
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
23 import sys
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
24
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
25 import ngs_roi.app
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
26 import ngs_roi.argparse
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
27 import ngs_roi.io
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
28
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
29
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
30 class LinkRegion(object):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
31 """Region on picture with genomic interval."""
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
32
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
33 def __init__(self, x1, y1, x2, y2, ref, begin_pos, end_pos):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
34 self.x1 = x1
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
35 self.x2 = x2
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
36 self.y1 = y1
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
37 self.y2 = y2
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
38 self.ref = ref
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
39 self.begin_pos = begin_pos
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
40 self.end_pos = end_pos
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
41
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
42
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
43 class RoiPlotGrid(object):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
44 """A grid of ROI plots.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
45
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
46 width -- width one one plot
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
47 height -- height of one plot
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
48 """
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
49
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
50 # Border in each direction.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
51 BORDER = 0
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
52 # Spacing between plots.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
53 SPACE = 2
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
54
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
55 def __init__(self, width, height, columns, rows, bg_plot=(0, 0, 0, 10),
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
56 frame_col=(80, 80, 80, 255), fg_col=(0, 0, 0, 255)):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
57 # Properties of the grid.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
58 self.width = float(width)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
59 self.height = float(height)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
60 self.columns = columns
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
61 self.rows = rows
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
62 # State.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
63 self.idx = 0 # currently drawn plot
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
64 self.canvas_width = 2 * self.BORDER + columns * width + (columns - 1) * self.SPACE
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
65 self.canvas_height = 2 * self.BORDER + rows * height + (rows - 1) * self.SPACE
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
66 # Colors.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
67 self.bg_plot = bg_plot
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
68 self.frame_col = frame_col
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
69 self.fg_color = fg_col
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
70 # List of link region for image map.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
71 self.link_regions = []
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
72
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
73 def plotStart(self, idx):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
74 """Return pair with start coordinates of plot."""
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
75 row = idx / self.columns
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
76 col = idx % self.columns
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
77 x = self.BORDER + col * (self.width + self.SPACE)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
78 y = self.BORDER + row * (self.height + self.SPACE)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
79 return x, y
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
80
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
81 def plotRecord(self, record):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
82 """Register plotting of a record."""
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
83 start_x, start_y = self.plotStart(self.idx)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
84 self.idx += 1
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
85 # Register link region.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
86 self.link_regions.append(LinkRegion(
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
87 start_x, start_y, start_x + self.width, start_y + self.height,
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
88 record.ref, record.start_pos, record.end_pos))
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
89
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
90
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
91 class GridLinks(object):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
92 """Link information for one grid."""
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
93
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
94 def __init__(self, file_name, link_regions):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
95 self.file_name = file_name
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
96 self.link_regions = link_regions
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
97
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
98
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
99 class PlotThumbnailsApp(ngs_roi.app.App):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
100 def __init__(self, args):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
101 # Call parent's constructor.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
102 ngs_roi.app.App.__init__(self, args)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
103 self.prepareOutDir()
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
104 # Initialize members.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
105 self.grid = None
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
106 self.plot_idx = 0
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
107 self.grid_links = []
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
108
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
109 def run(self):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
110 # Load ROI records.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
111 print >>sys.stderr, 'Loading ROI'
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
112
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
113 # Create plots.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
114 runner = ngs_roi.app.PlotThumbnailsRunner(self.args)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
115 runner.run()
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
116
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
117 # Create HTML.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
118 print >>sys.stderr, 'Creating HTML...'
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
119 num_plots = self.args.num_cols * self.args.num_rows # plots on grid
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
120 for i, roi in enumerate(ngs_roi.io.RoiFile(self.args.in_file)):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
121 if self.args.max_rois > 0 and i >= self.args.max_rois:
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
122 break
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
123 # Write out old grid (if any) and create new one.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
124 if i % num_plots == 0:
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
125 if self.grid:
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
126 print >>sys.stderr, ' Writing plot %d...' % self.plot_idx
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
127 self.writeGrid()
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
128 self.grid = RoiPlotGrid(self.args.plot_width, self.args.plot_height,
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
129 self.args.num_cols, self.args.num_rows)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
130 # Put the next plot on the grid.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
131 self.grid.plotRecord(roi)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
132 print >>sys.stderr, ' Writing plot %d...' % self.plot_idx
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
133 self.writeGrid() # Write last grid.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
134 self.createHtml(self.args.out_file)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
135 return 0
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
136
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
137 def writeGrid(self):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
138 """Register writing of grid."""
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
139 if not self.grid:
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
140 return
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
141 # Append grid info.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
142 file_name = 'thumbnail_%d.png' % self.plot_idx
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
143 file_name = os.path.join(self.args.out_dir, file_name)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
144 self.plot_idx += 1
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
145 self.grid_links.append(GridLinks(os.path.basename(file_name), self.grid.link_regions))
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
146
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
147 def createHtml(self, file_name):
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
148 print >>sys.stderr, 'Writing HTML to %s' % file_name
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
149 with open(file_name, 'wb') as f:
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
150 f.write('<html><body>\n')
1
0ac4f6f3d984 Uploaded
holtgrewe
parents: 0
diff changeset
151 f.write('<h1>ROI Thumbnail Plots</h1>')
0
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
152 for gl in self.grid_links:
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
153 vals = (gl.file_name, gl.file_name, self.grid.canvas_width, self.grid.canvas_height)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
154 f.write('<img src="%s" usemap="#%s" width="%d" height="%d" />\n' % vals)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
155 f.write('<map name="%s">\n' % gl.file_name)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
156 for lr in gl.link_regions:
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
157 locus = (lr.ref, lr.begin_pos + 1, lr.end_pos)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
158 vals = {'x1': lr.x1, 'x2': lr.x2, 'y1': lr.y1, 'y2': lr.y2,
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
159 'title': '%s %d-%d' % locus,
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
160 'href': self.buildHref(lr.ref, lr.begin_pos, lr.end_pos),
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
161 'onclick': ''}
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
162 # Add onclick handler to prevent opening of new window.
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
163 vals['target_attr'] = ''
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
164 if self.args.link_target:
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
165 vals['target_attr'] = ' target="%s"' % self.args.link_target
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
166 if self.args.link_type == 'local_igv':
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
167 vals['target_attr'] = ' target="empty"'
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
168 f.write(' <area shape="rect" coords="%(x1)d,%(y1)d,%(x2)d,%(y2)d" '
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
169 'alt="%(title)s" title="%(title)s" href="%(href)s"%(target_attr)s />\n' % vals)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
170 f.write('</map>\n')
1
0ac4f6f3d984 Uploaded
holtgrewe
parents: 0
diff changeset
171 f.write('<iframe name="empty" height="0" width="0" src="about:blank"></iframe>\n')
0ac4f6f3d984 Uploaded
holtgrewe
parents: 0
diff changeset
172 f.write('<div><code>' + str(self.args) + '</code></div></body></html>\n')
0
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
173
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
174
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
175 def main():
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
176 """Program entry point."""
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
177 parser = argparse.ArgumentParser(description='Plot ROI file.')
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
178 ngs_roi.argparse.addFileArguments(parser)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
179 ngs_roi.argparse.addPlotGridArguments(parser)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
180 ngs_roi.argparse.addLinkArguments(parser)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
181 args = parser.parse_args()
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
182 ngs_roi.argparse.applyFileDefaults(args)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
183
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
184 app = PlotThumbnailsApp(args)
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
185 return app.run()
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
186
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
187
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
188 if __name__ == '__main__':
61d9bdb6d519 Uploaded
holtgrewe
parents:
diff changeset
189 sys.exit(main())