def drawTaskPie(self, imgPie, dicTaskTree, globalTimespan = -1, parentTimespan = -1, radiusDelta = 10, radiusInner = 0, angleStart = 0, angleEnd = 360): if globalTimespan == -1: globalTimespan = 0 for strBranchName in dicTaskTree: globalTimespan += dicTaskTree[strBranchName]["time"] if parentTimespan == -1: parentTimespan = 0 for strBranchName in dicTaskTree: parentTimespan += dicTaskTree[strBranchName]["time"] if parentTimespan > 0: nSegments = len(dicTaskTree) radiusOuter = radiusInner + radiusDelta nCenterX = imgPie.columns() / 2 nCenterY = imgPie.rows() / 2 nStartXOuter = nCenterX - radiusOuter nStartYOuter = nCenterY - radiusOuter nEndXOuter = nCenterX + radiusOuter nEndYOuter = nCenterY + radiusOuter nStartXInner = nCenterX - radiusInner nStartYInner = nCenterY - radiusInner nEndXInner = nCenterX + radiusInner nEndYInner = nCenterY + radiusInner dAngleOffset = 0 for strBranchName in dicTaskTree: dAngleWidth = float(dicTaskTree[strBranchName]["time"]) / float(parentTimespan) * (angleEnd - angleStart) if dAngleWidth > 0: dStartingAngle = angleStart + dAngleOffset dEndingAngle = dStartingAngle + dAngleWidth dAngleOffset += dAngleWidth if "children" in dicTaskTree[strBranchName]: if len(dicTaskTree[strBranchName]["children"]) > 0: self.drawTaskPie(imgPie, dicTaskTree[strBranchName]["children"], globalTimespan, dicTaskTree[strBranchName]["time"], radiusDelta, radiusOuter, dStartingAngle, dEndingAngle) dTimeSpanDegree = float(dicTaskTree[strBranchName]["time"]) / float(globalTimespan) imgPie.strokeColor(Color(int(255 * dTimeSpanDegree), 0, int(255 * (1.0 - dTimeSpanDegree)))) lstDrawables = DrawableList() lstDrawables.append(DrawableLine(nCenterX + radiusInner * math.cos(math.radians(dStartingAngle)), nCenterY + radiusInner * math.sin(math.radians(dStartingAngle)), nCenterX + radiusOuter * math.cos(math.radians(dStartingAngle)), nCenterY + radiusOuter * math.sin(math.radians(dStartingAngle)))) lstDrawables.append(DrawableArc(nStartXOuter, nStartYOuter, nEndXOuter, nEndYOuter, dStartingAngle, dEndingAngle)) lstDrawables.append(DrawableLine(nCenterX + radiusInner * math.cos(math.radians(dEndingAngle)), nCenterY + radiusInner * math.sin(math.radians(dEndingAngle)), nCenterX + radiusOuter * math.cos(math.radians(dEndingAngle)), nCenterY + radiusOuter * math.sin(math.radians(dEndingAngle)))) lstDrawables.append(DrawableArc(nStartXInner, nStartYInner, nEndXInner, nEndYInner, dStartingAngle, dEndingAngle)) imgPie.draw(lstDrawables)
def draw(self): self.hide_line_markers = True Pie.__base__.draw(self) if not self.has_gdata: return radius = (min([self.graph_width, self.graph_height]) / 2.0) * 0.8 #diameter = self.graph_height #top_x = self.graph_left + (self.graph_width - diameter) / 2.0 center_x = self.graph_left + (self.graph_width / 2.0) center_y = self.graph_top + (self.graph_height / 2.0) - 10 total_sum = self.sums_for_pie() prev_degrees = self.zero_degree def percentages_compare(comp_a, comp_b): """Use full data since we can easily calculate percentages""" if comp_a['values'][0] > comp_b['values'][0]: return 1 elif comp_a['values'][0] < comp_b['values'][0]: return -1 return 0 sorted(self.gdata, cmp=percentages_compare) dl = DrawableList() for data_row in self.gdata: if data_row['values'][0] > 0: dl.append(DrawableStrokeColor(data_row['color'])) dl.append(DrawableFillColor('transparent')) # stroke width should be equal to radius. # we'll draw centered on (radius / 2) dl.append(DrawableStrokeWidth(radius)) current_degrees = (float(data_row['values'][0]) \ / total_sum) * 360.0 # ellipse will draw the the stroke centered on # the first two parameters offset by the second two. # therefore, in order to draw a circle of the proper diameter # we must center the stroke at # half the radius for both x and y dl.append(DrawableEllipse(center_x, center_y, radius / 2.0, radius / 2.0, prev_degrees, prev_degrees + current_degrees + 0.5)) # <= +0.5 'fudge factor' gets rid of the ugly gaps half_angle = prev_degrees + \ ((prev_degrees + current_degrees) - prev_degrees) / 2 label_val = round(float(data_row['values'][0]) / \ total_sum * 100.0) if not (label_val < self.hide_labels_less_than): label_string = str(label_val) + '%%' self.draw_label(center_x, center_y, half_angle, radius + (radius * TEXT_OFFSET_PERCENTAGE), label_string) prev_degrees += current_degrees # TODO debug a circle where the text is drawn... self.base_image.draw(dl)
def draw(self): self.get_maximum_by_stack() StackedArea.__base__.draw(self) if not self.has_gdata: return dl = DrawableList() self.x_increment = self.graph_width / float(self.column_count - 1) dl.append(DrawableStrokeColor('transparent')) height = [0 for i in range(self.column_count)] data_points = None if self.last_series_goes_on_bottom: self.norm_data.reverse() for data_row in self.norm_data: prev_data_points = data_points data_points = [] dl.append(DrawableFillColor(Color(data_row['color']))) for index, data_point in enumerate(data_row['values']): # Use incremented x and scaled y new_x = self.graph_left + (self.x_increment * index) new_y = self.graph_top + (self.graph_height - data_point * \ self.graph_height - height[index]) height[index] += (data_point * self.graph_height) data_points.append(new_x) data_points.append(new_y) self.draw_label(new_x, index) if prev_data_points: poly_points = copy.copy(data_points) tmp_max_point = len(prev_data_points) / 2 - 1 for i in range(tmp_max_point, -1, -1): poly_points.append(prev_data_points[2 * i]) poly_points.append(prev_data_points[2 * i + 1]) poly_points.append(data_points[0]) poly_points.append(data_points[1]) else: poly_points = copy.copy(data_points) poly_points.append(self.graph_right) poly_points.append(self.graph_bottom - 1) poly_points.append(self.graph_left) poly_points.append(self.graph_bottom - 1) poly_points.append(data_points[0]) poly_points.append(data_points[1]) # generate CoordinateList coordinates = [Coordinate(poly_points[i], poly_points[i + 1]) \ for i in range(0, len(poly_points), 2)] cl = CoordinateList() for c in coordinates: cl.append(c) dl.append(DrawablePolyline(cl)) dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl)
def draw_bars(self): self.dl = DrawableList() self.bar_spacing = self.bar_spacing or 0.9 self.bars_width = self.graph_height / float(self.column_count) self.bar_width = self.bars_width * self.bar_spacing / len(self.norm_data) self.dl.append(DrawableStrokeOpacity(0.0)) height = [0 for i in range(self.column_count)] length = [self.graph_left for i in range(self.column_count)] padding = (self.bar_width * (1 - self.bar_spacing)) / 2 for row_index, data_row in enumerate(self.norm_data): for point_index, data_point in enumerate(data_row['values']): self.dl.append(DrawableFillColor(Color(data_row['color']))) if type(self.transparent) is float: self.dl.append(DrawableFillOpacity(self.transparent)) elif self.transparent is True: self.dl.append(DrawableFillOpacity(base.DEFAULT_TRANSPARENCY)) # Using the original calcs from the stacked bar chart # to get the difference between # part of the bart chart we wish to stack. temp1 = self.graph_left + (self.graph_width - \ data_point * self.graph_width - height[point_index]) temp2 = self.graph_left + self.graph_width - height[point_index] difference = temp2 - temp1 left_x = length[point_index] - 1 left_y = self.graph_top + (self.bars_width * point_index) + \ (self.bar_width * row_index) + padding right_x = left_x + difference right_y = left_y + self.bar_width height[point_index] += (data_point * self.graph_width) self.dl.append(DrawableRectangle(left_x, left_y, right_x, right_y)) # Calculate center based on bar_width and current row label_center = self.graph_top + \ (self.bars_width * point_index + self.bars_width / 2) self.draw_label(label_center, point_index) if self.additional_line_values: _gdata = self.find_label(data_row['label']) self.draw_values(left_y + self.bar_width / 2, _gdata['values'][point_index]) self.dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(self.dl)
def draw_label(self, x_offset, index): if self.hide_line_markers: return if index in self.labels and index not in self.labels_seen: y_offset = self.graph_bottom + LABEL_MARGIN dl = DrawableList() dl.append(DrawableFillColor(Color(self.font_color))) dl.append(DrawableGravity(GravityType.NorthWestGravity)) font = self.font if self.font else DEFAULT_FONT dl.append(DrawableFont(font, StyleType.NormalStyle, 400, StretchType.NormalStretch)) dl.append(DrawableStrokeColor(Color('transparent'))) dl.append(DrawablePointSize(self.marker_font_size)) label_font_height = self.calculate_caps_height(self.marker_font_size) / 2 label_text_width = self.calculate_width(self.marker_font_size, self.labels[index]) dl.append(DrawableText(x_offset - label_text_width / 2.0, y_offset + label_font_height, self.labels[index])) dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl) self.labels_seen[index] = 1
def draw_line_markers(self): if self.hide_line_markers: return self.base_image.draw(DrawableStrokeAntialias(False)) if self.y_axis_increment is None: # Try to use a number of horizontal lines that will come out even. # # TODO Do the same for larger numbers...100, 75, 50, 25 if self.marker_count is None: for lines in range(3, 7): if self.spread % lines == 0.0: self.marker_count = lines break self.marker_count = self.marker_count or 4 if self.spread > 0: self.increment = self.significant(self.spread / self.marker_count) else: self.increment = 1 else: # TODO Make this work for negative values self.maximum_value = max([math.ceil(self.maximum_value), self.y_axis_increment]) self.minimum_value = math.floor(self.minimum_value) self.calculate_spread() self.normalize(force=True) self.marker_count = int(self.spread / self.y_axis_increment) self.increment = self.y_axis_increment self.increment_scaled = float(self.graph_height) / (self.spread / self.increment) # Draw horizontal line markers and annotate with numbers dl = DrawableList() for index in range(self.marker_count + 1): y = self.graph_top + self.graph_height - float(index) * self.increment_scaled dl.append(DrawableFillColor(Color(self.marker_color))) dl.append(DrawableLine(self.graph_left, y, self.graph_right, y)) marker_label = index * self.increment + float(self.minimum_value) if not self.hide_line_numbers: dl.append(DrawableFillColor(Color(self.font_color))) font = self.font if self.font else DEFAULT_FONT dl.append(DrawableFont(font, StyleType.NormalStyle, 400, StretchType.NormalStretch)) dl.append(DrawableStrokeColor('transparent')) marker_font_size = self.scale_fontsize(self.marker_font_size) dl.append(DrawablePointSize(marker_font_size)) # Vertically center with 1.0 for the height dl.append(DrawableGravity(GravityType.NorthWestGravity)) x = self.calculate_width(self.marker_font_size, marker_label) / 2 y = y + self.calculate_caps_height(marker_font_size) / 3 dl.append(DrawableText(self.graph_left - LABEL_MARGIN - x, y, self.label(marker_label))) dl.append(DrawableScaling(self.scale, self.scale)) dl.append(DrawableStrokeAntialias(True)) self.base_image.draw(dl)
def draw_label(self, y_offset, index): if index in self.labels and index not in self.labels_seen: dl = DrawableList() dl.append(DrawableFillColor(Color(self.font_color))) font = self.font if self.font else base.DEFAULT_FONT dl.append(DrawableFont(font, StyleType.NormalStyle, 400, StretchType.NormalStretch)) dl.append(DrawableStrokeColor('transparent')) dl.append(DrawablePointSize(self.marker_font_size)) dl.append(DrawableGravity(GravityType.NorthEastGravity)) font_hight = self.calculate_caps_height(self.marker_font_size) #text_width = self.calculate_width(self.marker_font_size, # self.labels[index]) x = self.raw_columns - self.graph_left + base.LABEL_MARGIN y = y_offset + font_hight / 2.0 dl.append(DrawableText(x, y, self.labels[index])) self.labels_seen[index] = 1 dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl)
def draw(self): self.has_left_labels = True Dot.__base__.draw(self) if not self.has_gdata: return spacing_factor = 1.0 self.items_width = self.graph_height / float(self.column_count) self.item_width = self.items_width * \ spacing_factor / len(self.norm_data) dl = DrawableList() dl.append(DrawableStrokeOpacity(0.0)) padding = (self.items_width * (1 - spacing_factor)) / 2 for row_index, data_row in enumerate(self.norm_data): for point_index, data_point in enumerate(data_row['values']): x_pos = self.graph_left + (data_point * self.graph_width) - \ round(float(self.item_width) / 6.0) y_pos = self.graph_top + (self.items_width * point_index) + \ padding + round(float(self.item_width) / 2.0) if row_index == 0: dl.append(DrawableStrokeColor(Color(self.marker_color))) dl.append(DrawableStrokeWidth(1.0)) dl.append(DrawableStrokeOpacity(0.1)) dl.append(DrawableLine(self.graph_left, y_pos, self.graph_left + self.graph_width, y_pos)) dl.append(DrawableFillColor(Color(data_row['color']))) if type(self.transparent) is float: dl.append(DrawableFillOpacity(self.transparent)) elif self.transparent is True: dl.append(DrawableFillOpacity(base.DEFAULT_TRANSPARENCY)) dl.append(DrawableStrokeColor('transparent')) dl.append(DrawableCircle(x_pos, y_pos, x_pos + round(float(self.item_width) / 3.0), y_pos)) # Calculate center based on item_width and current row label_center = self.graph_top + (self.items_width * \ point_index + self.items_width / 2) + padding self.draw_label(label_center, point_index) dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl)
def draw_legend(self): if self.hide_legend: return self.legend_labels = [gdata['label'] for gdata in self.gdata] legend_square_width = self.legend_box_size dl = DrawableList() font = self.font if self.font else DEFAULT_FONT dl.append(DrawablePointSize(self.legend_font_size)) label_widths = [[]] # Used to calculate line wrap for label in self.legend_labels: metrics = TypeMetric() self.base_image.fontTypeMetrics(str(label), metrics) label_width = metrics.textWidth() + legend_square_width * 2.7 label_widths[-1].append(label_width) if sum(label_widths[-1]) > (self.raw_columns * 0.9): label_widths.append([label_widths[-1].pop()]) current_x_offset = self.center(sum(label_widths[0])) if self.hide_title: current_y_offset = self.top_margin + self.title_margin else: current_y_offset = self.top_margin + self.title_margin + self.title_caps_height dl.append(DrawableStrokeColor('transparent')) for index, legend_label in enumerate(self.legend_labels): # Now draw box with color of this dataset dl.append(DrawableFillColor(Color(self.gdata[index]['color']))) dl.append(DrawableRectangle(current_x_offset, current_y_offset - legend_square_width / 2.0, current_x_offset + legend_square_width, current_y_offset + legend_square_width / 2.0)) # Draw label dl.append(DrawableFillColor(Color(self.font_color))) font = self.font if self.font else DEFAULT_FONT dl.append(DrawableFont(font, StyleType.NormalStyle, 400, StretchType.NormalStretch)) dl.append(DrawablePointSize(self.legend_font_size)) dl.append(DrawableGravity(GravityType.NorthWestGravity)) x = current_x_offset + legend_square_width * 1.7 y = current_y_offset + self.legend_caps_height / 3 dl.append(DrawableText(x, y, str(legend_label))) dl.append(DrawablePointSize(self.legend_font_size)) metrics = TypeMetric() self.base_image.fontTypeMetrics(str(legend_label), metrics) current_string_offset = metrics.textWidth() + legend_square_width * 2.7 # Handle wrapping del(label_widths[0][0]) if len(label_widths[0]) == 0: del(label_widths[0]) if len(label_widths) != 0: current_x_offset = self.center(sum(label_widths[0])) line_height = max([self.legend_caps_height, legend_square_width]) + self.legend_margin if len(label_widths) > 0: # Wrap to next line and shrink available graph dimensions current_y_offset += line_height self.graph_top += line_height self.graph_height = self.graph_bottom - self.graph_top else: current_x_offset += current_string_offset if len(dl): dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl) self.color_index = 0
def edgeTest(self): #first build the image, we need to know how big it is with open(self.dataBase + "base.json", "r") as f: base = json.loads(f.read()) self.totalWidth = base['width'] self.totalHeight = base['height'] print ("Creating large base image", int(self.totalWidth), 'x',int(self.totalHeight) ) #im = Image(Geometry(int(self.totalWidth), int(self.totalHeight)), Color("black")) im = Image(Geometry(5000, 5000), Color("black")) allNodes = {} for file in os.listdir(self.dataNodes): if file.endswith('.json'): with open(self.dataNodes + file, "r") as f: nodes = json.loads(f.read()) print ("Storing Nodes data", self.dataNodes + file, len(nodes)) self.buildCounterNodeTotal = len(nodes) self.buildCounterNode = 0 for node in nodes: allNodes[node['id']] = node totalEdges = 0 for file in os.listdir(self.dataEdges): if file.endswith('.json'): with open(self.dataEdges + file, "r") as f: edges = json.loads(f.read()) print ("Building Image Edges", self.dataEdges + file, len(edges)) self.buildCounterNodeTotal = len(edges) self.buildCounterNode = 0 drawlist = DrawableList() for edge in edges: sourcePos = allNodes[edge['source']]['posX'], allNodes[edge['source']]['posY'] targetPos = allNodes[edge['target']]['posX'], allNodes[edge['target']]['posY'] width = abs(sourcePos[0]-targetPos[0]) height = abs(sourcePos[1]-targetPos[1]) dx = targetPos[0] - sourcePos[0] dy = targetPos[1] - sourcePos[1] dxdy = (dx*dx) + (dy*dy) dist = math.sqrt( dxdy ) dxdy = (dx*dx) + (dy*dy) dist = math.sqrt( dxdy ) #midpoint mx = (targetPos[0] + sourcePos[0]) / 2 my = (targetPos[1] + sourcePos[1]) / 2 #print width, height, dist totalEdges+=1 color = (allNodes[edge['source']]['rgb'][0],allNodes[edge['source']]['rgb'][1],allNodes[edge['source']]['rgb'][2]) color = self.rgb_to_hex( color ) drawlist.append(DrawableStrokeColor(color)) drawlist.append(DrawableStrokeOpacity(0.25)) drawlist.append(DrawableLine(0,height,width,0)) #line = Image(Geometry(int(width), int(height)), Color("black")) #line.strokeColor("blue"); #line.draw(drawlist) cords = self.convertCoordinates(int(mx),int(my)) print str(totalEdges), " \r", sys.stdout.flush() #line.write(str(edge['id']) + 'line.png') #im.composite(line, int(cords[0]), int(cords[1]), co.OverCompositeOp) if totalEdges > 1000: im.draw(drawlist) print ("") print ("Writing large file out") im.write('base.png') sys.exit() print totalEdges sys.exit()
def render(self, path, scale=5, width=10000, min_size=10, max_size=200, min_fsize=14, max_fsize=200, bg_color='#003059'): """ Render a PNG from the node coordinates. Args: path (str): The image path. scale (float): Pixels per coordinate unit. width (int): The height/width, in pixels. min_size (int): The min node size. max_size (int): The max node size. min_fsize (int): The min font size. max_fsize (int): The max font size. """ # Initialize the canvas, set font. image = Image(Geometry(width, width), Color(bg_color)) # Set the label font. image.font(config['network']['font']) for cn, n in bar(self.graph.nodes_iter(data=True), expected_size=len(self.graph)): # Get (x,y) / radius. x, y = self.get_xy(cn, scale, width) r = (n['viz']['size']*scale) / 2 # Index the coordinates. self.graph.node[cn]['x'] = x self.graph.node[cn]['y'] = y self.graph.node[cn]['r'] = r # Get the node label. label = ', '.join([ n.get('title', ''), n.get('author', '') ]) # Get the node color. color = '#%02x%02x%02x' % ( n['viz']['color']['r'], n['viz']['color']['g'], n['viz']['color']['b'] ) # Draw the node. dl = DrawableList() dl.append(DrawableFillColor(color)) dl.append(DrawableStrokeColor('black')) dl.append(DrawableStrokeWidth(n['r']/15)) dl.append(DrawableFillOpacity(0.9)) dl.append(DrawableCircle(x, y, x+r, y+r)) image.draw(dl) # Compute the font size. ratio = (n['viz']['size']-min_size) / (max_size-min_size) fsize = min_fsize + (ratio*(max_fsize-min_fsize)) image.fontPointsize(fsize) # Measure the width of the label. tm = TypeMetric() image.fontTypeMetrics(label, tm) tw = tm.textWidth() # Draw the label. dl = DrawableList() dl.append(DrawablePointSize(fsize)) dl.append(DrawableFillColor('white')) dl.append(DrawableText(x-(tw/2), y, label)) image.draw(dl) image.write(os.path.abspath(path))
from pgmagick import Image, Geometry, Color, \ DrawableAffine, DrawableCircle, DrawableCompositeImage, \ DrawableText, DrawableList im = Image(Geometry(300, 300), Color("yellow")) circle = DrawableCircle(100.0, 100.0, 20.0, 20.0) im.fontPointsize(65) im.font("/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType/UnBatang.ttf") text = DrawableText(30, 250, "hello gm") drawlist = DrawableList() drawlist.append(circle) drawlist.append(text) im.draw(drawlist) im.write('non-affine.png') im = Image(Geometry(300, 300), Color("yellow")) circle = DrawableCircle(100.0, 100.0, 20.0, 20.0) im.fontPointsize(65) im.font("/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType/UnBatang.ttf") text = DrawableText(30, 250, "hello gm") drawlist = DrawableList() drawlist.append(DrawableAffine(0.9, 0.9, 0.1, 0.1, 0.5, 0.5)) drawlist.append(circle) drawlist.append(text) im.draw(drawlist) im.write('affine.png') im = Image(Geometry(300, 300), Color("yellow")) d = DrawableCompositeImage(100, 150, im) im.draw(d)
from pgmagick import Image, Geometry, Color, TypeMetric, \ DrawableText, DrawableList, DrawableGravity, GravityType im = Image(Geometry(600, 600), Color("transparent")) im.fontPointsize(30) im.fillColor(Color("#f010f0")) im.strokeColor(Color("transparent")) im.font("Vera.ttf") dl = DrawableList() dl.append(DrawableGravity(GravityType.CenterGravity)) dl.append(DrawableText(0, 0, "center")) tm = TypeMetric() im.fontTypeMetrics("northn", tm) font_height = tm.textHeight() dl.append(DrawableGravity(GravityType.NorthGravity)) dl.append(DrawableText(0, font_height / 2., "north")) dl.append(DrawableGravity(GravityType.WestGravity)) dl.append(DrawableText(0, 0, "west")) dl.append(DrawableGravity(GravityType.EastGravity)) dl.append(DrawableText(0, 0, "east")) dl.append(DrawableText(0, 20, "east-long")) dl.append(DrawableGravity(GravityType.SouthGravity)) dl.append(DrawableText(0, 0, "south")) dl.append(DrawableGravity(GravityType.NorthWestGravity))
def _draw_bezier(self): self.x_increment = self.graph_width / float(self.column_count - 1) dl = DrawableList() for data_row in self.norm_data: poly_points = CoordinateList() dl.append(DrawableFillColor(data_row['color'])) for index, data_point in enumerate(data_row['values']): # Use incremented x and scaled y new_x = self.graph_left + (self.x_increment * index) new_y = self.graph_top + ( self.graph_height - data_point * self.graph_height) if index == 0: poly_points.append(Coordinate(self.graph_left, self.graph_bottom - 1)) poly_points.append(Coordinate(new_x, new_y)) self.draw_label(new_x, index) dl.append(DrawableFillOpacity(0.0)) dl.append(DrawableStrokeColor(data_row['color'])) dl.append(DrawableStrokeWidth(self.clip_value_if_greater_than(self.columns / (len(self.norm_data[0]['values']) * 4), 5.0))) dl.append(DrawableBezier(poly_points)) self.base_image.draw(dl)
def draw_no_data(self): dl = DrawableList() dl.append(DrawableFillColor(Color(self.font_color))) font = self.font if self.font else DEFAULT_FONT dl.append(DrawableGravity(GravityType.CenterGravity)) dl.append(DrawableFillColor(Color(self.font_color))) dl.append(DrawableFont(font, StyleType.NormalStyle, 800, StretchType.NormalStretch)) dl.append(DrawablePointSize(self.scale_fontsize(80))) dl.append(DrawableText(0, 0, self.no_data_message)) dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl)
def draw_axis_labels(self): if self.x_axis_label: dl = DrawableList() # X Axis # Centered vertically and horizontally by setting the # height to 1.0 and the width to the width of the graph. x_axis_label_y_coordinate = self.graph_bottom + \ LABEL_MARGIN * 2 + self.marker_caps_height dl.append(DrawableFillColor(Color(self.font_color))) font = self.font if self.font else DEFAULT_FONT dl.append(DrawableFont(font, StyleType.NormalStyle, 400, StretchType.NormalStretch)) dl.append(DrawableStrokeColor('transparent')) dl.append(DrawablePointSize(self.marker_font_size)) dl.append(DrawableGravity(GravityType.NorthGravity)) # graph center #dl.append(DrawableText(self.graph_left / 2.0, # x_axis_label_y_coordinate, # self.x_axis_label)) dl.append(DrawableText(0.0, x_axis_label_y_coordinate, self.x_axis_label)) dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl) if self.y_axis_label: # Y Axis, rotated vertically dl = DrawableList() dl.append(DrawableFillColor(Color(self.font_color))) font = self.font if self.font else DEFAULT_FONT dl.append(DrawableFont(font, StyleType.NormalStyle, 400, StretchType.NormalStretch)) dl.append(DrawableStrokeColor('transparent')) fontsize = self.marker_font_size dl.append(DrawablePointSize(fontsize)) dl.append(DrawableRotation(90)) dl.append(DrawableGravity(GravityType.WestGravity)) x = -(self.calculate_width(fontsize, self.y_axis_label) / 2.0) y = -(self.left_margin + self.marker_caps_height / 2.0) dl.append(DrawableText(x, y, self.y_axis_label)) dl.append(DrawableScaling(self.scale, self.scale)) dl.append(DrawableRotation(-90)) self.base_image.draw(dl)
def draw_label(self, center_x, center_y, angle, radius, amount): """ Labels are drawn around a slightly wider ellipse to give room for labels on the left and right. """ dl = DrawableList() # TODO Don't use so many hard-coded numbers # The distance out from the center of the pie to get point r_offset = 20.0 # + 15.0 # The label points need to be tweaked slightly x_offset = center_x y_offset = center_y # This one doesn't though radius_offset = (radius + r_offset) ellipse_factor = radius_offset * 0.15 x = x_offset + ((radius_offset + ellipse_factor) * \ math.cos(_deg2rad(angle))) y = y_offset + (radius_offset * math.sin(_deg2rad(angle))) # Draw label dl.append(DrawableFillColor(Color(self.font_color))) font = self.font if self.font else base.DEFAULT_FONT dl.append(DrawableFont(font, StyleType.NormalStyle, 900, StretchType.NormalStretch)) dl.append(DrawablePointSize(self.scale_fontsize( self.marker_font_size))) dl.append(DrawableStrokeColor('transparent')) dl.append(DrawableGravity(GravityType.NorthWestGravity)) dl.append(DrawableText(x, y, amount)) # FIXME: unable scaling dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl)
def draw_title(self): if self.hide_title or self.title is None: return dl = DrawableList() dl.append(DrawableFillColor(Color(self.font_color))) font = self.font if self.font else DEFAULT_FONT dl.append(DrawableGravity(GravityType.NorthGravity)) dl.append(DrawableFont(font, StyleType.NormalStyle, 800, StretchType.NormalStretch)) dl.append(DrawablePointSize(self.title_font_size)) y = self.top_margin + self.title_caps_height / 2.0 dl.append(DrawableText(0, y, self.title)) dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl)
def draw_bars(self): # Setup spacing. # # Columns sit stacked. self.bar_spacing = self.bar_spacing or 0.9 self.bar_width = self.graph_height / float(self.column_count) dl = DrawableList() dl.append(DrawableStrokeOpacity(0.0)) height = [0 for i in range(self.column_count)] length = [self.graph_left for i in range(self.column_count)] padding = (self.bar_width * (1 - self.bar_spacing)) / 2 for row_index, data_row in enumerate(self.norm_data): for point_index, data_point in enumerate(data_row['values']): # using the original calcs from the stacked bar chart to # get the difference between part of the bart chart # we wish to stack. tmp1 = self.graph_left + (self.graph_width - \ data_point * self.graph_width - height[point_index]) + 1 tmp2 = self.graph_left + \ self.graph_width - height[point_index] - 1 difference = tmp2 - tmp1 dl.append(DrawableFillColor(Color(data_row['color']))) if type(self.transparent) is float: dl.append(DrawableFillOpacity(self.transparent)) elif self.transparent is True: dl.append(DrawableFillOpacity(base.DEFAULT_TRANSPARENCY)) left_x = length[point_index] left_y = self.graph_top + \ (self.bar_width * point_index) + padding right_x = left_x + difference right_y = left_y + self.bar_width * self.bar_spacing length[point_index] += difference height[point_index] += (data_point * self.graph_width - 2) dl.append(DrawableRectangle(left_x, left_y, right_x, right_y)) # Calculate center based on bar_width and current row label_center = self.graph_top + \ (self.bar_width * point_index) + \ (self.bar_width * self.bar_spacing / 2.0) self.draw_label(label_center, point_index) dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl)
def draw_line_markers(self): if self.hide_line_markers: return dl = DrawableList() dl.append(DrawableStrokeAntialias(False)) # Draw horizontal line markers and annotate with numbers dl.append(DrawableStrokeColor(Color(self.marker_color))) dl.append(DrawableStrokeWidth(1)) number_of_lines = 5 # TODO Round maximum marker value to a round number like # 100, 0.1, 0.5, etc. increment = self.significant(float(self.maximum_value) / number_of_lines) for index in range(number_of_lines + 1): line_diff = (self.graph_right - self.graph_left) / number_of_lines x = self.graph_right - (line_diff * index) - 1 dl.append(DrawableLine(x, self.graph_bottom, x, self.graph_bottom + 0.5 * base.LABEL_MARGIN)) diff = index - number_of_lines marker_label = abs(diff) * increment if not self.hide_line_numbers: dl.append(DrawableFillColor(Color(self.font_color))) font = self.font if self.font else base.DEFAULT_FONT dl.append(DrawableFont(font, StyleType.NormalStyle, 400, StretchType.NormalStretch)) dl.append(DrawableStrokeColor('transparent')) dl.append(DrawablePointSize(self.marker_font_size)) dl.append(DrawableGravity(GravityType.NorthWestGravity)) font_hight = self.calculate_caps_height(self.marker_font_size) text_width = self.calculate_width(self.marker_font_size, str(marker_label)) x -= text_width / 2.0 y = font_hight / 2.0 + self.graph_bottom + (base.LABEL_MARGIN * 2.0) dl.append(DrawableText(x, y, str(marker_label))) dl.append(DrawableStrokeAntialias(True)) dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl)
def drawTaskPie(self, imgPie, dicTaskTree, globalTimespan=-1, parentTimespan=-1, radiusDelta=10, radiusInner=0, angleStart=0, angleEnd=360): if globalTimespan == -1: globalTimespan = 0 for strBranchName in dicTaskTree: globalTimespan += dicTaskTree[strBranchName]["time"] if parentTimespan == -1: parentTimespan = 0 for strBranchName in dicTaskTree: parentTimespan += dicTaskTree[strBranchName]["time"] if parentTimespan > 0: nSegments = len(dicTaskTree) radiusOuter = radiusInner + radiusDelta nCenterX = imgPie.columns() / 2 nCenterY = imgPie.rows() / 2 nStartXOuter = nCenterX - radiusOuter nStartYOuter = nCenterY - radiusOuter nEndXOuter = nCenterX + radiusOuter nEndYOuter = nCenterY + radiusOuter nStartXInner = nCenterX - radiusInner nStartYInner = nCenterY - radiusInner nEndXInner = nCenterX + radiusInner nEndYInner = nCenterY + radiusInner dAngleOffset = 0 for strBranchName in dicTaskTree: dAngleWidth = float( dicTaskTree[strBranchName]["time"]) / float( parentTimespan) * (angleEnd - angleStart) if dAngleWidth > 0: dStartingAngle = angleStart + dAngleOffset dEndingAngle = dStartingAngle + dAngleWidth dAngleOffset += dAngleWidth if "children" in dicTaskTree[strBranchName]: if len(dicTaskTree[strBranchName]["children"]) > 0: self.drawTaskPie( imgPie, dicTaskTree[strBranchName]["children"], globalTimespan, dicTaskTree[strBranchName]["time"], radiusDelta, radiusOuter, dStartingAngle, dEndingAngle) dTimeSpanDegree = float(dicTaskTree[strBranchName] ["time"]) / float(globalTimespan) imgPie.strokeColor( Color(int(255 * dTimeSpanDegree), 0, int(255 * (1.0 - dTimeSpanDegree)))) lstDrawables = DrawableList() lstDrawables.append( DrawableLine( nCenterX + radiusInner * math.cos(math.radians(dStartingAngle)), nCenterY + radiusInner * math.sin(math.radians(dStartingAngle)), nCenterX + radiusOuter * math.cos(math.radians(dStartingAngle)), nCenterY + radiusOuter * math.sin(math.radians(dStartingAngle)))) lstDrawables.append( DrawableArc(nStartXOuter, nStartYOuter, nEndXOuter, nEndYOuter, dStartingAngle, dEndingAngle)) lstDrawables.append( DrawableLine( nCenterX + radiusInner * math.cos(math.radians(dEndingAngle)), nCenterY + radiusInner * math.sin(math.radians(dEndingAngle)), nCenterX + radiusOuter * math.cos(math.radians(dEndingAngle)), nCenterY + radiusOuter * math.sin(math.radians(dEndingAngle)))) lstDrawables.append( DrawableArc(nStartXInner, nStartYInner, nEndXInner, nEndYInner, dStartingAngle, dEndingAngle)) imgPie.draw(lstDrawables)
def draw(self): """override to draw() method in Base Class.""" Area.__base__.draw(self) if not self.has_gdata: return x_increment = self.graph_width / float(self.column_count - 1) dl = DrawableList() dl.append(DrawableStrokeColor(Color('transparent'))) for data_row in self.norm_data: poly_points = CoordinateList() prev_x = prev_y = 0.0 dl.append(DrawableFillColor(Color(data_row['color']))) if type(self.transparent) is float: dl.append(DrawableFillOpacity(self.transparent)) elif self.transparent is True: dl.append(DrawableFillOpacity(base.DEFAULT_TRANSPARENCY)) for index, data_point in enumerate(data_row['values']): # Use incremented x and scaled y new_x = self.graph_left + (x_increment * index) new_y = self.graph_top + \ (self.graph_height - data_point * self.graph_height) if prev_x > 0 and prev_y > 0: poly_points.append(Coordinate(new_x, new_y)) else: poly_points.append(Coordinate(self.graph_left, self.graph_bottom - 1)) poly_points.append(Coordinate(new_x, new_y)) self.draw_label(new_x, index) prev_x = new_x prev_y = new_y # Add closing points, draw polygon poly_points.append(Coordinate(self.graph_right, self.graph_bottom - 1)) poly_points.append(Coordinate(self.graph_left, self.graph_bottom - 1)) dl.append(DrawablePolyline(poly_points)) dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl)
def _draw_bars(self): self.bar_spacing = self.bar_spacing or 0.9 self.bar_width = self.graph_width / \ float(self.column_count * len(self.gdata)) padding = (self.bar_width * (1 - self.bar_spacing)) / 2 dl = DrawableList() dl.append(DrawableStrokeOpacity(0.0)) conversion = BarConversion() conversion.graph_height = self.graph_height conversion.graph_top = self.graph_top if self.minimum_value >= 0: conversion.mode = 1 else: if self.maximum_value <= 0: conversion.mode = 2 else: conversion.mode = 3 conversion.spread = self.spread conversion.minimum_value = self.minimum_value conversion.zero = -self.minimum_value / self.spread for row_index, data_row in enumerate(self.norm_data): for point_index, data_point in enumerate(data_row['values']): left_x = self.graph_left + (self.bar_width * \ (row_index + point_index + \ ((len(self.gdata) - 1) * point_index))) + padding right_x = left_x + self.bar_width * self.bar_spacing conv = conversion.getLeftYRightYscaled(data_point) dl.append(DrawableFillColor(Color(data_row['color']))) if type(self.transparent) is float: dl.append(DrawableFillOpacity(self.transparent)) elif self.transparent is True: dl.append(DrawableFillOpacity(base.DEFAULT_TRANSPARENCY)) dl.append(DrawableRectangle(left_x, conv[0], right_x, conv[1])) label_center = self.graph_left + \ (len(self.gdata) * self.bar_width * point_index) + \ (len(self.gdata) * self.bar_width / 2.0) if self.center_labels_over_point: tmp = self.bar_width / 2.0 else: tmp = 0.0 self.draw_label(label_center - tmp, point_index) if self.center_labels_over_point: self.draw_label(self.graph_right, self.column_count) dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl)
def draw(self): Line.__base__.draw(self) if not self.has_gdata: return if self.column_count > 1: x_increment = float(self.graph_width / (self.column_count - 1)) else: x_increment = self.graph_width dl = DrawableList() if hasattr(self, "norm_baseline"): level = self.graph_top + (self.graph_height - \ self.norm_baseline * self.graph_height) dl.append(DrawableStrokeColor(Color(self.baseline_color))) dl.append(DrawableFillOpacity(0.0)) dl.append(DrawableDashArray(10, 20)) dl.append(DrawableStrokeWidth(5)) dl.append(DrawableLine(self.graph_left, level, self.graph_left + self.graph_width, level)) self.base_image.draw(dl) #del(dl) for data_row in self.norm_data: prev_x = prev_y = None self.one_point = self.is_contains_one_point_only(data_row) for index, data_point in enumerate(data_row['values']): new_x = self.graph_left + (x_increment * index) if data_point is None: continue self.draw_label(new_x, index) new_y = self.graph_top + (self.graph_height - \ data_point * self.graph_height) # Reset each time to avoid thin-line errors dl.append(DrawableStrokeColor(Color(data_row['color']))) dl.append(DrawableFillColor(Color(data_row['color']))) if type(self.transparent) is float: dl.append(DrawableFillOpacity(self.transparent)) elif self.transparent is True: dl.append(DrawableFillOpacity(base.DEFAULT_TRANSPARENCY)) if type(self.transparent) is float: dl.append(DrawableStrokeOpacity(self.transparent)) elif self.transparent is True: dl.append(DrawableStrokeOpacity(base.DEFAULT_TRANSPARENCY)) dl.append(DrawableStrokeWidth(self.line_width or \ self.clip_value_if_greater_than(self.columns / \ (len(self.norm_data[0]['values']) * 4), 5.0))) circle_radius = self.dot_radius or \ self.clip_value_if_greater_than(self.columns / \ (len(self.norm_data[0]['values']) * 2.5), 5.0) if not self.hide_lines and prev_x and prev_y: dl.append(DrawableLine(prev_x, prev_y, new_x, new_y)) elif self.one_point: dl.append(DrawableCircle(new_x, new_y, new_x - circle_radius, new_y)) if not self.hide_dots: dl.append(DrawableCircle(new_x, new_y, new_x - circle_radius, new_y)) prev_x = new_x prev_y = new_y dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl)
class SideBar(base.Base): """Side Bar Graph Object""" bar_spacing = None def draw(self): self.has_left_labels = True SideBar.__base__.draw(self) if not self.has_gdata: return self.draw_bars() def draw_bars(self): self.dl = DrawableList() self.bar_spacing = self.bar_spacing or 0.9 self.bars_width = self.graph_height / float(self.column_count) self.bar_width = self.bars_width * self.bar_spacing / len(self.norm_data) self.dl.append(DrawableStrokeOpacity(0.0)) height = [0 for i in range(self.column_count)] length = [self.graph_left for i in range(self.column_count)] padding = (self.bar_width * (1 - self.bar_spacing)) / 2 for row_index, data_row in enumerate(self.norm_data): for point_index, data_point in enumerate(data_row['values']): self.dl.append(DrawableFillColor(Color(data_row['color']))) if type(self.transparent) is float: self.dl.append(DrawableFillOpacity(self.transparent)) elif self.transparent is True: self.dl.append(DrawableFillOpacity(base.DEFAULT_TRANSPARENCY)) # Using the original calcs from the stacked bar chart # to get the difference between # part of the bart chart we wish to stack. temp1 = self.graph_left + (self.graph_width - \ data_point * self.graph_width - height[point_index]) temp2 = self.graph_left + self.graph_width - height[point_index] difference = temp2 - temp1 left_x = length[point_index] - 1 left_y = self.graph_top + (self.bars_width * point_index) + \ (self.bar_width * row_index) + padding right_x = left_x + difference right_y = left_y + self.bar_width height[point_index] += (data_point * self.graph_width) self.dl.append(DrawableRectangle(left_x, left_y, right_x, right_y)) # Calculate center based on bar_width and current row label_center = self.graph_top + \ (self.bars_width * point_index + self.bars_width / 2) self.draw_label(label_center, point_index) if self.additional_line_values: _gdata = self.find_label(data_row['label']) self.draw_values(left_y + self.bar_width / 2, _gdata['values'][point_index]) self.dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(self.dl) def find_label(self, label): for i in self.gdata: if i['label'] == label: return copy.copy(i) # Instead of base class version, draws vertical background lines and label def draw_line_markers(self): if self.hide_line_markers: return dl = DrawableList() dl.append(DrawableStrokeAntialias(False)) # Draw horizontal line markers and annotate with numbers dl.append(DrawableFillColor(Color(self.marker_color))) dl.append(DrawableStrokeWidth(1)) number_of_lines = 5 # TODO Round maximum marker value to a round number like 100, 0.1, 0.5, etc. increment = self.significant(float(self.maximum_value) / number_of_lines) for index in range(number_of_lines + 1): line_diff = (self.graph_right - self.graph_left) / number_of_lines x = self.graph_right - (line_diff * index) - 1 dl.append(DrawableLine(x, self.graph_bottom, x, self.graph_top)) diff = index - number_of_lines marker_label = abs(diff) * increment if not self.hide_line_numbers: dl.append(DrawableFillColor(Color(self.font_color))) font = self.font if self.font else base.DEFAULT_FONT dl.append(DrawableFont(font, StyleType.NormalStyle, 400, StretchType.NormalStretch)) dl.append(DrawableStrokeColor(Color('transparent'))) dl.append(DrawablePointSize(self.marker_font_size)) dl.append(DrawableGravity(GravityType.NorthWestGravity)) text_width = self.calculate_width(self.marker_font_size, str(marker_label)) # TODO Center text over line x -= text_width / 2 y = self.graph_bottom + (base.LABEL_MARGIN * 2.0) if type(marker_label) is int: dl.append(DrawableText(x, y, "%d" % marker_label)) else: dl.append(DrawableText(x, y, "%.1f" % marker_label)) dl.append(DrawableStrokeAntialias(True)) dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl) def draw_label(self, y_offset, index): if index in self.labels and index not in self.labels_seen: dl = DrawableList() dl.append(DrawableFillColor(self.font_color)) font = self.font if self.font else base.DEFAULT_FONT dl.append(DrawableGravity(GravityType.NorthEastGravity)) dl.append(DrawableFont(font, StyleType.NormalStyle, 400, StretchType.NormalStretch)) dl.append(DrawableStrokeColor(Color('transparent'))) dl.append(DrawablePointSize(self.marker_font_size)) font_hight = self.calculate_caps_height(self.marker_font_size) #text_width = self.calculate_width(self.marker_font_size, # self.labels[index]) x = self.raw_columns - self.graph_left + base.LABEL_MARGIN y = y_offset + font_hight / 2.0 dl.append(DrawableText(x, y, self.labels[index])) self.labels_seen[index] = 1 dl.append(DrawableScaling(self.scale, self.scale)) self.base_image.draw(dl) def draw_values(self, y_offset, point): self.dl.append(DrawableFillColor(self.font_color)) font = self.font if self.font else base.DEFAULT_FONT self.dl.append(DrawableGravity(GravityType.NorthWestGravity)) self.dl.append(DrawableFont(font, StyleType.ItalicStyle, 400, StretchType.NormalStretch)) self.dl.append(DrawableStrokeColor(Color('transparent'))) marker_font_size = self.marker_font_size * 0.7 self.dl.append(DrawablePointSize(marker_font_size)) font_hight = self.calculate_caps_height(marker_font_size) #text_width = self.calculate_width(self.marker_font_size, # "%.2lf" % point) x = self.graph_left + base.LABEL_MARGIN y = y_offset + font_hight / 2.0 self.dl.append(DrawableText(x, y, "%.2lf" % point))