Back to index

python-biopython  1.60
Comparative.py
Go to the documentation of this file.
00001 """Plots to compare information between different sources.
00002 
00003 This file contains high level plots which are designed to be used to
00004 compare different types of information. The most basic example is comparing
00005 two variables in a traditional scatter plot.
00006 """
00007 # reportlab
00008 from reportlab.pdfgen import canvas
00009 from reportlab.lib import colors
00010 from reportlab.graphics.charts.lineplots import LinePlot
00011 from reportlab.lib.pagesizes import letter
00012 from reportlab.lib.units import inch
00013 
00014 from reportlab.graphics.shapes import Drawing, String, Group
00015 from reportlab.graphics import renderPDF, renderPS
00016 from reportlab.graphics.charts.markers import *
00017 
00018 from Bio.Graphics import _write
00019 
00020 class ComparativeScatterPlot(object):
00021     """Display a scatter-type plot comparing two different kinds of info.
00022 
00023     Attributes;
00024 
00025     o display_info -- a 2D list of the information we'll be outputting. Each
00026     top level list is a different data type, and each data point is a two-tuple
00027     of the coordinates of a point. So if you had two distributions of points,
00028     it should look like:
00029 
00030     display_info = [[(1, 2), (3, 4)],
00031                     [(5, 6), (7, 8)]]
00032 
00033     if everything is just one set of points, display_info can look like:
00034 
00035     display_info = [[(1, 2), (3, 4), (5, 6)]]
00036     """
00037     def __init__(self, output_format = 'pdf'):
00038         # customizable attributes
00039         self.number_of_columns = 1
00040         self.page_size = letter
00041         self.title_size = 20
00042 
00043         self.output_format = output_format
00044 
00045         # the information we'll be writing
00046         self.display_info = []
00047 
00048         # inital colors and shapes used for drawing points
00049         self.color_choices = [colors.red, colors.green, colors.blue,
00050                               colors.yellow, colors.orange, colors.black]
00051         self.shape_choices = [makeFilledCircle, makeEmptySquare,
00052                               makeFilledDiamond, makeFilledSquare,
00053                               makeEmptyCircle, makeSmiley]
00054 
00055     def draw_to_file(self, output_file, title):
00056         """Write the comparative plot to a file.
00057 
00058         Arguments:
00059 
00060         o output_file - The name of the file to output the information to,
00061                         or a handle to write to.
00062 
00063         o title - A title to display on the graphic.
00064         """
00065         width, height = self.page_size
00066         cur_drawing = Drawing(width, height)
00067 
00068         self._draw_title(cur_drawing, title, width, height)
00069 
00070         start_x = inch * .5
00071         end_x = width - inch * .5
00072         end_y = height - 1.5 * inch
00073         start_y = .5 * inch
00074         self._draw_scatter_plot(cur_drawing, start_x, start_y, end_x, end_y)
00075 
00076         return _write(cur_drawing, output_file, self.output_format)
00077 
00078     def _draw_title(self, cur_drawing, title, width, height):
00079         """Add a title to the page we are outputting.
00080         """
00081         title_string = String(width / 2, height - inch, title)
00082         title_string.fontName = 'Helvetica-Bold'
00083         title_string.fontSize = self.title_size
00084         title_string.textAnchor = "middle"
00085 
00086         cur_drawing.add(title_string)
00087 
00088     def _draw_scatter_plot(self, cur_drawing, x_start, y_start,
00089                            x_end, y_end):
00090         """Draw a scatter plot on the drawing with the given coordinates.
00091         """
00092         scatter_plot = LinePlot()
00093 
00094         # set the dimensions of the scatter plot
00095         scatter_plot.x = x_start
00096         scatter_plot.y = y_start
00097         scatter_plot.width = abs(x_start - x_end)
00098         scatter_plot.height = abs(y_start - y_end)
00099 
00100         scatter_plot.data = self.display_info
00101 
00102         scatter_plot.joinedLines = 0
00103 
00104         # set the axes of the plot
00105         x_min, x_max, y_min, y_max = self._find_min_max(self.display_info)
00106         scatter_plot.xValueAxis.valueMin = x_min
00107         scatter_plot.xValueAxis.valueMax = x_max
00108         scatter_plot.xValueAxis.valueStep = (x_max - x_min) / 10.0
00109 
00110         scatter_plot.yValueAxis.valueMin = y_min
00111         scatter_plot.yValueAxis.valueMax = y_max
00112         scatter_plot.yValueAxis.valueStep = (y_max - y_min) / 10.0
00113 
00114         self._set_colors_and_shapes(scatter_plot, self.display_info)
00115         
00116         cur_drawing.add(scatter_plot)
00117 
00118     def _set_colors_and_shapes(self, scatter_plot, display_info):
00119         """Set the colors and shapes of the points displayed.
00120 
00121         By default this just sets all of the points according to the order
00122         of colors and shapes defined in self.color_choices and
00123         self.shape_choices. The first 5 shapes and colors are unique, the
00124         rest of them are just set to the same color and shape (since I
00125         ran out of shapes!).
00126 
00127         You can change how this function works by either changing the
00128         values of the color_choices and shape_choices attributes, or
00129         by inheriting from this class and overriding this function.
00130         """
00131         for value_num in range(len(display_info)):
00132             # if we have unique colors, add them
00133             if (value_num + 1) < len(self.color_choices):
00134                 scatter_plot.lines[value_num].strokeColor = \
00135                     self.color_choices[value_num]
00136                 scatter_plot.lines[value_num].symbol = \
00137                     self.shape_choices[value_num]
00138             # otherwise just use the last number
00139             else:
00140                 scatter_plot.lines[value_num].strokeColor = \
00141                   self.color_choices[-1]
00142                 scatter_plot.lines[value_num].symbol = \
00143                   self.shape_choices[-1]
00144 
00145     def _find_min_max(self, info):
00146         """Find the min and max for the x and y coordinates in the given data.
00147         """
00148         x_min = info[0][0][0]
00149         x_max = info[0][0][0]
00150         y_min = info[0][0][1]
00151         y_max = info[0][0][1]
00152 
00153         for two_d_list in info:
00154             for x, y in two_d_list:
00155                 if x > x_max:
00156                     x_max = x
00157                 if x < x_min:
00158                     x_min = x
00159                 if y > y_max:
00160                     y_max = y
00161                 if y < y_min:
00162                     y_min = y
00163 
00164         return x_min, x_max, y_min, y_max