comparison roi_plot_thumbnails.py @ 0:61d9bdb6d519 draft

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