1# Copyright 2003-2008 by Leighton Pritchard. All rights reserved. 2# Revisions copyright 2008-2010 by Peter Cock. 3# 4# This file is part of the Biopython distribution and governed by your 5# choice of the "Biopython License Agreement" or the "BSD 3-Clause License". 6# Please see the LICENSE file that should have been included as part of this 7# package. 8# 9# Contact: Leighton Pritchard, The James Hutton Institute, 10# Invergowrie, Dundee, Scotland, DD2 5DA, UK 11# Leighton.Pritchard@hutton.ac.uk 12################################################################################ 13# 14# TODO: Make representation of Ymax and Ymin values at this level, so that 15# calculation of graph/axis drawing is simplified 16 17"""GraphSet module. 18 19Provides: 20 - GraphSet - container for GraphData objects 21 22For drawing capabilities, this module uses reportlab to draw and write 23the diagram: http://www.reportlab.com 24""" 25 26# ReportLab imports 27 28from reportlab.lib import colors 29 30from ._Graph import GraphData 31 32 33class GraphSet: 34 """Graph Set. 35 36 Attributes: 37 - id Unique identifier for the set 38 - name String describing the set 39 40 """ 41 42 def __init__(self, name=None): 43 """Initialize. 44 45 Arguments: 46 - name String identifying the graph set sensibly 47 48 """ 49 self.id = id # Unique identifier for the set 50 self._next_id = 0 # Holds unique ids for graphs 51 self._graphs = {} # Holds graphs, keyed by unique id 52 self.name = name # Holds description of graph 53 54 def new_graph( 55 self, 56 data, 57 name=None, 58 style="bar", 59 color=colors.lightgreen, 60 altcolor=colors.darkseagreen, 61 linewidth=1, 62 center=None, 63 colour=None, 64 altcolour=None, 65 centre=None, 66 ): 67 """Add a GraphData object to the diagram. 68 69 Arguments: 70 - data List of (position, value) int tuples 71 - name String, description of the graph 72 - style String ('bar', 'heat', 'line') describing how the graph 73 will be drawn 74 - color colors.Color describing the color to draw all or 'high' 75 (some styles) data (overridden by backwards compatible 76 argument with UK spelling, colour). 77 - altcolor colors.Color describing the color to draw 'low' (some 78 styles) data (overridden by backwards compatible argument 79 with UK spelling, colour). 80 - linewidth Float describing linewidth for graph 81 - center Float setting the value at which the x-axis 82 crosses the y-axis (overridden by backwards 83 compatible argument with UK spelling, centre) 84 85 Add a GraphData object to the diagram (will be stored internally). 86 """ 87 # Let the UK spelling (colour) override the USA spelling (color) 88 if colour is not None: 89 color = colour 90 if altcolour is not None: 91 altcolor = altcolour 92 if centre is not None: 93 center = centre 94 95 id = self._next_id # get id number 96 graph = GraphData(id, data, name, style, color, altcolor, center) 97 graph.linewidth = linewidth 98 self._graphs[id] = graph # add graph data 99 self._next_id += 1 # increment next id 100 return graph 101 102 def del_graph(self, graph_id): 103 """Remove a graph from the set, indicated by its id.""" 104 del self._graphs[graph_id] 105 106 def get_graphs(self): 107 """Return list of all graphs in the graph set, sorted by id. 108 109 Sorting is to ensure reliable stacking. 110 """ 111 return [self._graphs[id] for id in sorted(self._graphs)] 112 113 def get_ids(self): 114 """Return a list of all ids for the graph set.""" 115 return list(self._graphs.keys()) 116 117 def range(self): 118 """Return the lowest and highest base (or mark) numbers as a tuple.""" 119 lows, highs = [], [] 120 for graph in self._graphs.values(): 121 low, high = graph.range() 122 lows.append(low) 123 highs.append(high) 124 return (min(lows), max(highs)) 125 126 def data_quartiles(self): 127 """Return (minimum, lowerQ, medianQ, upperQ, maximum) values as a tuple.""" 128 data = [] 129 for graph in self._graphs.values(): 130 data += list(graph.data.values()) 131 data.sort() 132 datalen = len(data) 133 return ( 134 data[0], 135 data[datalen / 4], 136 data[datalen / 2], 137 data[3 * datalen / 4], 138 data[-1], 139 ) 140 141 def to_string(self, verbose=0): 142 """Return a formatted string with information about the set. 143 144 Arguments: 145 - verbose - Flag indicating whether a short or complete account 146 of the set is required 147 148 """ 149 if not verbose: 150 return "%s" % self 151 else: 152 outstr = ["\n<%s: %s>" % (self.__class__, self.name)] 153 outstr.append("%d graphs" % len(self._graphs)) 154 for key in self._graphs: 155 outstr.append("%s" % self._graphs[key]) 156 return "\n".join(outstr) 157 158 def __len__(self): 159 """Return the number of graphs in the set.""" 160 return len(self._graphs) 161 162 def __getitem__(self, key): 163 """Return a graph, keyed by id.""" 164 return self._graphs[key] 165 166 def __str__(self): 167 """Return a formatted string with information about the feature set.""" 168 outstr = ["\n<%s: %s>" % (self.__class__, self.name)] 169 outstr.append("%d graphs" % len(self._graphs)) 170 outstr = "\n".join(outstr) 171 return outstr 172