def make_arrow(self, color): key = color if key in self.arrows: return self.arrows[key] arrow = draw.Marker(-0.1, -0.5, 1.1, 0.5, scale=4) arrow.append(draw.Lines(1, -0.5, 1, 0.5, 0, 0, fill=color, close=True)) self.arrows[key] = arrow return arrow
def __init__(self, is_gem_sbml=False, pathway_id='rp_pathway', central_species_group_id='central_species', sink_species_group_id='rp_sink_species', model_name=None, document=None, path=None, rpcache=None): """Class constructor .. document private functions .. automethod:: hierarchyPos """ super().__init__(is_gem_sbml, pathway_id, central_species_group_id, sink_species_group_id, model_name, document, path, rpcache) #self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(os.path.basename(__file__)) self.mnx_cofactors = json.load(open('data/mnx_cofactors.json', 'r')) #some drawing constants self.arrowhead = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=4, orient='auto', id='normal_arrow') self.arrowhead.append(draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill='black', close=True)) self.arrowhead_flat = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=4, orient=0, id='flat_arrow') self.arrowhead_flat.append(draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill='black', close=True)) self.rev_arrowhead_flat = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=4, orient=180, id='rev_flat_arrow') self.rev_arrowhead_flat.append(draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill='black', close=True)) ''' self.rev_arrowhead = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=4, orient=0, id='rev_flat_arrow') self.rev_arrowhead.append(draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill='black', close=True)) ''' self.arrowhead_comp_x = 7.0 self.arrowhead_comp_y = 7.0
def drawSigil(points, canvas, color='white'): # draw sigil from coordinate list # setup sigil dash = svg.Marker(-0.5, -0.5, 0.5, 0.5, scale=5, orient='auto') # define line to terminate the sigil dash.append(svg.Line(-0., -0.5, 0., 0.5, stroke_width=0.2, stroke=color)) dot = svg.Marker(-0.8, -0.5, 0.5, 0.5, scale=5, orient='auto') # define circle to start the sigil dot.append(svg.Circle(-0.3, 0.0, 0.3, stroke_width=0.2, stroke=color, fill='none')) p = svg.Path(stroke_width=7, stroke=color, fill='none', marker_start=dot, marker_end=dash) # draw sigil for point in points: if points.index(point) == 0: originX = point[0] originY = point[1] p.M(originX, originY) else: x = point[0] - originX # abs. to rel. coords y = point[1] - originY # abs. to rel. coords p.l(x, y) # draw originX = point[0] originY = point[1] # add to canvas canvas.append(p)
def draw_constraint(self, url, dn, rc, stroke="red", stroke_width=1): d = self.d arrow = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=stroke_width * 1.5, orient='auto') arrow.append( draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill=stroke, close=True)) p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none', stroke_dasharray="4", marker_end=arrow) t = self.tree bdn = t & dn p_bdn = bdn.up brc = t & rc p_brc = brc.up if bdn.x_coor > brc.x_coor: p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none', marker_end=arrow) p.M(bdn.x_coor, bdn.y_coor).L(brc.x_coor, brc.y_coor) d.append(p) else: p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none', marker_end=arrow) p.M(bdn.x_coor, bdn.y_coor).L(brc.x_coor, brc.y_coor) d.append(p) ''' spacing = self.width / (self.n_leaves + 1) total_time = self.total_time width = self.width height = self.height d = self.d stroke_a = stroke_width / 2.0 for n in self.tree.traverse(): # Inner tree, vertical lines x_0, y_0, y_1 = n.x_coor, n.y_coor, self._y_scaling(n.dist) p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none') p.M(x_0, y_0).l(0, y_1) d.append(p) if not n.is_leaf(): c1, c2 = n.get_children() # Horizontal lines # Inner Tree p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none') p.M(c1.x_coor - stroke_a, n.y_coor).L(c2.x_coor + stroke_a, n.y_coor) d.append(p) d.setRenderSize(h=self.height) d.saveSvg(url) return(d) if node2events[n.name] == "T": p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none', stroke_dasharray="4", marker_end=arrow) if c1.x_coor > c2.x_coor: p.M(c1.x_coor, n.y_coor).L(c2.x_coor + radius, n.y_coor) else: p.M(c1.x_coor, n.y_coor).L(c2.x_coor - radius, n.y_coor) ''' d.saveSvg(url) return (d)
def DrawGeneTree(self, url, genetreefile, eventsgenetreefile, stroke="red", stroke_width=2, displacement=2, r_displacement=0, symbol_scaling=1.5): spacing = self.width / (self.n_leaves + 1) total_time = self.total_time width = self.width height = self.height d = self.d radius = 0.1 genetree_svg = list() r_displacement = random.uniform(-r_displacement, r_displacement) node2events = dict() node2displacement = dict() gtree = self._read_treefile(genetreefile) #################### This a patch to correct a bug in Zombi ################ with open(eventsgenetreefile) as f: f.readline() o, e, nodes = f.readline().strip().split("\t") o_time = float(o) while e != "S" and e != "E" and e != "F" and e != "L" and e != "T" and e != "D": t, e, nodes = f.readline().strip().split("\t") gtree.dist = float(t) - float(o) ############################################################################# # We add the coordinates for n in gtree.traverse(): dist_to_origin = n.get_distance(gtree) + gtree.dist + o_time x_coor, _ = self.node2coor[n.name.split("_")[0]] y_coor = round( self._y_scaling(total_time) - self._y_scaling(dist_to_origin), 2) n.add_feature("displacement", 0) n.add_feature("x_coor", x_coor) n.add_feature("y_coor", y_coor) # We add the displacement gtree.displacement = r_displacement gtree.x_coor += r_displacement for n in gtree.iter_descendants(): parent_d = (n.up).displacement n.displacement = parent_d if n.name in node2displacement: n.displacement += node2displacement[n.name] n.x_coor += (n.displacement * displacement) + r_displacement #n.y_coor += (n.displacement*4) # We get a dict with the new coordinates in the gene tree gnode2x_coor = {n.name: n.x_coor for n in gtree.traverse()} ###### EVENT SYMBOLS ############ arrow = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=stroke_width * 1.5, orient='auto') arrow.append( draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill=stroke, close=True)) ################################## # We add the symbols symbols = list() with open(eventsgenetreefile) as f: f.readline() for l in f: t, e, nodes = l.strip().split("\t") if nodes == "Root": x_coor = gnode2x_coor["Root_1"] else: x_coor = gnode2x_coor["_".join(nodes.split(";")[:2])] if e == "O": o_time = float(t) y_coor = self._y_scaling(total_time) - self._y_scaling( float(t)) symbols.append(("O", x_coor, y_coor)) if e == "D": _, _, node1, num1, node2, num2 = nodes.split(";") n1 = node1 + "_" + num1 n2 = node2 + "_" + num2 node2displacement[n1] = 1 node2displacement[n2] = -1 y_coor = self._y_scaling(total_time) - self._y_scaling( float(t)) symbols.append(("D", x_coor, y_coor)) if e == "L": y_coor = self._y_scaling(total_time) - self._y_scaling( float(t)) symbols.append(("L", x_coor, y_coor)) if e == "T": _, _, node1, num1, node2, num2 = nodes.split(";") n1 = node1 + "_" + num1 n2 = node2 + "_" + num2 node2events["_".join(nodes.split(";")[0:2])] = "T" node2displacement[n2] = 1 #x_coor, _ = self.node2coor[nodes.split(";")[4]] #y_coor = self._y_scaling(float(t)) for n in gtree.traverse(): # Need to check 2 things: is leaf? and has_events? if n.is_leaf() and n.name in node2events: # Vertical line if node2events[n.name] == "L": x_0, y_0, y_1 = n.x_coor, n.y_coor, self._y_scaling(n.dist) p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none', marker_end=cross) p.M(x_0, y_0).l(0, y_1) else: x_0, y_0, y_1 = n.x_coor, n.y_coor, self._y_scaling(n.dist) p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none') p.M(x_0, y_0).l(0, y_1) genetree_svg.append(p) elif not n.is_leaf() and n.name in node2events: # Vertical line x_0, y_0, y_1 = n.x_coor, n.y_coor, self._y_scaling(n.dist) p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none') p.M(x_0, y_0).l(0, y_1) genetree_svg.append(p) # Horizontal line c1, c2 = n.get_children() if node2events[n.name] == "T": p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none', stroke_dasharray="4", marker_end=arrow) if c1.x_coor > c2.x_coor: p.M(c1.x_coor, n.y_coor).L(c2.x_coor + radius, n.y_coor) else: p.M(c1.x_coor, n.y_coor).L(c2.x_coor - radius, n.y_coor) genetree_svg.append(p) elif n.is_leaf() and n.name not in node2events: # Vertical line x_0, y_0, y_1 = n.x_coor, n.y_coor, self._y_scaling(n.dist) p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none') p.M(x_0, y_0).l(0, y_1) genetree_svg.append(p) elif not n.is_leaf() and n.name not in node2events: # Vertical line x_0, y_0, y_1 = n.x_coor, n.y_coor, self._y_scaling(n.dist) p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none') p.M(x_0, y_0).l(0, y_1) genetree_svg.append(p) # Horizontal line c1, c2 = n.get_children() p = draw.Path(stroke=stroke, stroke_width=stroke_width, fill='none') p.M(c1.x_coor - (stroke_width / 2.0), n.y_coor).L(c2.x_coor + (stroke_width / 2.0), n.y_coor) genetree_svg.append(p) # We add the symbols for e, x_coor, y_coor in symbols: if e == "O": p = draw.Circle(cx=x_coor, cy=y_coor, r=stroke_width * symbol_scaling, stroke=stroke, stroke_width=0, fill='green') genetree_svg.append(p) if e == "D": p = draw.Circle(cx=x_coor, cy=y_coor, r=stroke_width * symbol_scaling, stroke=stroke, stroke_width=0, fill='yellow') genetree_svg.append(p) if e == "L": p = draw.Circle(cx=x_coor, cy=y_coor, r=stroke_width * symbol_scaling, stroke=stroke, stroke_width=0, fill='red') genetree_svg.append(p) for element in genetree_svg: d.append(element) d.setRenderSize(h=self.height) d.saveSvg(url) return (d)
stroke_width=3, fill='none')) d.append( draw.Arc(60, -20, 20, 270, 60, cw=True, stroke='blue', stroke_width=1, fill='black', fill_opacity=0.3)) # Draw arrows arrow = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=4, orient='auto') arrow.append(draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill='red', close=True)) p = draw.Path(stroke='red', stroke_width=2, fill='none', marker_end=arrow) # Add an arrow to the end of a path p.M(20, -40).L(20, -27).L(0, -20) # Chain multiple path operations d.append(p) d.append( draw.Line(30, -20, 0, -10, stroke='red', stroke_width=2, fill='none', marker_end=arrow)) # Add an arrow to the end of a line
def arrow(scale, color): marker = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=scale, orient='auto') marker.append( draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill=color, close=True)) return marker
def draw_genes(annotations, scale, color_table): '''Draw the genes in annotations. ''' # Define the coordinate system to draw on. # x length is fixed, y depends on how many species/strains are in the # annotations (how many gff's were given to the script) y_len = 25*len(annotations) + 50 # Add 50 for the scale bar d = draw.Drawing(500, y_len, origin = (0,0), displayInline=False) for idx, (k, v) in enumerate(annotations.items()): genes, min, max = v[0], v[1], v[2] contig_length = (max - min)*scale offset = 35 row = y_len-25*(idx+1) # Draw a line for each gff file and it's name d.append(draw.Line(offset, row, contig_length+offset, row, stroke='black', stroke_width=2, fill='none')) d.append(draw.Text(k[:10],6, 2, row-1, text_anchor="left", fill='black')) for gene in genes: color = color_table[gene[4]] arrow = draw.Marker(0, -0.5, 1, 0.5, scale=2, orient='auto') arrow.append(draw.Lines(0, -0.5, 0, 0.5, 1, 0, fill=color, close=True)) # Draw genes gene_coords = ((gene[1] - min)*scale+offset, \ (gene[2] - min)*scale+offset) midpoint = int(gene_coords[0] + (gene_coords[1] - gene_coords[0]) / 2) arrow_positions = [] # Shit code but extend the arrows from the midpoint in both # directions i = midpoint while i < int(gene_coords[1])-1: arrow_positions.append(i) i += int(600*scale) i = midpoint - int(600*scale) while i > int(gene_coords[0])+1: arrow_positions.append(i) i -= int(600*scale) # To draw arrows in correct orientation k = -1 if gene[3] == "+" else 1 # Draw a line for each gene d.append(draw.Line(gene_coords[0], row, gene_coords[1], row, \ stroke=color, stroke_width=6, fill='none')) # Draw arrows on the gene, depending on orientation for a in arrow_positions: d.append(draw.Lines(a+k, row+2, a-k, row, a+k, row-2, \ stroke_width=0.2, stroke = "black",fill="none")) ## Draw labels # Gene name, skip hypothetical proteins if gene[4] != "hypothetical_protein": text_pos = gene_coords[0] + (gene_coords[1]-gene_coords[0])/2 d.append(draw.Text(gene[4],5, text_pos,row-10, center=0.6, text_anchor="middle", fill='black')) # Draw a scale bar longest = int(450 / scale) row = 25 d.append(draw.Line(offset, row, longest, row, stroke='black', stroke_width=1, fill='none')) for num in range(0,longest, 1000): scaled_num = num*scale + offset d.append(draw.Line(scaled_num, row+1.5, scaled_num, row-1.5, stroke='black', stroke_width=0.5, fill='none')) d.append(draw.Text(str(num), 3, scaled_num, row-5, center=True, fill='black')) d.setPixelScale(2) d.saveSvg('test.svg')
def draw_bloch_sphere(d, inner_proj=euclid3d.identity(3), label='', axis=None, rot_proj=None, rot_deg=180, outer_labels=(), inner_labels=(), extra_opacity=1, inner_opacity=1, background='white'): spin = euclid3d.rotation(3, 0, 2, 2 * np.pi / 16 / 2 * 1.001) tilt = euclid3d.rotation(3, 1, 2, np.pi / 8) trans = tilt @ spin @ euclid3d.axis_swap((1, 2, 0)) proj = euclid3d.perspective3d(np.pi / 8, view_size=4) @ trans zx = euclid3d.axis_swap((2, 0, 1)) xy = euclid3d.identity(3) yz = euclid3d.axis_swap((1, 2, 0)) proj_zx = proj @ zx proj_xy = proj @ xy proj_yz = proj @ yz if background: d.append(draw.Rectangle(-100, -100, 200, 200, fill=background)) def draw_band(proj, trans, r_outer=1, r_inner=0.9, color='black', z_mul=1, opacity=1, divs=4, d=d, **kwargs): color = (color * divs)[:divs] if isinstance(color, list) else [color] * divs points = np.array([[-1, -1, 1, 1], [-1, 1, 1, -1]]).T sqr12 = 0.5**0.5 overlap = np.pi / 500 * (divs != 4) start_end_points = [ np.array([[ np.cos(pr - 2 * np.pi / divs - overlap), np.sin(pr - 2 * np.pi / divs - overlap) ], [np.cos(pr + overlap), np.sin(pr + overlap)], [np.cos(pr - np.pi / divs), np.sin(pr - np.pi / divs)]]) for pr in np.linspace(0, 2 * np.pi, num=divs, endpoint=False) ] for i in range(divs): p = draw.Path(fill=color[i], stroke='none', stroke_width=0.002, **kwargs, opacity=opacity) z = trans.project_point( (r_inner + r_outer) / 2 * start_end_points[i][2])[2] e = shapes.EllipseArc.fromBoundingQuad( *proj.project_list(points * r_outer)[:, :2].flatten(), *proj.project_list(start_end_points[i] * r_outer)[:, :2].flatten(), ) if e: e.drawToPath(p) if r_inner > 0: e = shapes.EllipseArc.fromBoundingQuad( *proj.project_list(points * r_inner)[:, :2].flatten(), *proj.project_list(start_end_points[i] * r_inner)[:, :2].flatten(), ) if e: e.reversed().drawToPath(p, includeL=True) p.Z() d.append(p, z=z * z_mul) if False: d.draw(shapes.EllipseArc.fromBoundingQuad( *proj.project_list( (r_outer + r_inner) / 2 * points)[:, :2].flatten(), *proj.project_list((r_outer + r_inner) / 2 * start_end_points[i])[:, :2].flatten(), ), fill='none', stroke_width=0.02, stroke=color[i], **kwargs, z=z * z_mul) xycolors = ['#56e', '#239', '#56e', '#56e'] yzcolors = ['#e1e144', '#909022', '#e1e144', '#e1e144'] zxcolors = ['#9e2', '#6a1', '#9e2', '#9e2'] draw_band(proj_xy, trans @ xy, 1, 0.925, z_mul=10, color=xycolors) draw_band(proj_yz, trans @ yz, 1, 0.925, z_mul=10, color=yzcolors) draw_band(proj_zx, trans @ zx, 1, 0.925, z_mul=10, color=zxcolors) # Inner g = draw.Group(opacity=inner_opacity) z_center = trans.project_point((0, 0, 0))[2] d.append(g, z=z_center) inner_xy = proj @ inner_proj @ xy # Darker colors: #34b, #a8a833, #7b2 draw_band(proj @ inner_proj @ xy, trans @ inner_proj @ xy, 0.8, 0.7, color=xycolors, d=g) draw_band(proj @ inner_proj @ yz, trans @ inner_proj @ yz, 0.8, 0.7, color=yzcolors, divs=4, d=g) draw_band(proj @ inner_proj @ zx, trans @ inner_proj @ zx, 0.8, 0.7, color=zxcolors, divs=8 // 2, d=g) elevation_lines = False if elevation_lines: for elevation in (*np.linspace(0, np.pi / 2, 4, True)[1:-1], *np.linspace(-np.pi / 2, 0, 3, False)[1:]): y = 0.75 * np.sin(elevation) r = 0.75 * np.cos(elevation) draw_band(proj @ inner_proj @ xy @ euclid3d.translation((0, 0, y)), trans @ inner_proj @ xy @ euclid3d.translation( (0, 0, y)), r_outer=r - 0.01, r_inner=r + 0.01, color='#bbb', opacity=1, d=g) arrow = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=4, orient='auto') arrow.append( draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill='black', close=True)) g.append(draw.Line(*inner_xy.p2(-0.65, 0, 0), *inner_xy.p2(0.6, 0, 0), stroke='black', stroke_width=0.015, marker_end=arrow), z=z_center) g.append(draw.Line(*inner_xy.p2(0, -0.65, 0), *inner_xy.p2(0, 0.6, 0), stroke='black', stroke_width=0.015, marker_end=arrow), z=z_center) g.append(draw.Line(*inner_xy.p2(0, 0, -0.65), *inner_xy.p2(0, 0, 0.6), stroke='black', stroke_width=0.015, marker_end=arrow), z=z_center) for pt, (x_off, y_off), elem in inner_labels: x, y = (proj @ inner_proj).p2(*pt) g.append(draw.Use(elem, x + x_off, y + y_off), z=10000) # Outer arrows and text arrow = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=4, orient='auto') arrow.append( draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill='black', close=True)) d.append(draw.Line(*proj_xy.p2(1, 0, 0), *proj_xy.p2(1.2, 0, 0), stroke='black', stroke_width=0.02, marker_end=arrow), z=100) d.append(draw.Line(*proj_xy.p2(0, 1, 0), *proj_xy.p2(0, 1.2, 0), stroke='black', stroke_width=0.02, marker_end=arrow), z=100) d.append(draw.Line(*proj_xy.p2(0, 0, 1), *proj_xy.p2(0, 0, 1.2), stroke='black', stroke_width=0.02, marker_end=arrow), z=100) d.append( draw.Line(*proj_xy.p2(-1, 0, 0), *proj_xy.p2(-1.2, 0, 0), stroke='black', stroke_width=0.02)) d.append( draw.Line(*proj_xy.p2(0, -1, 0), *proj_xy.p2(0, -1.2, 0), stroke='black', stroke_width=0.02)) d.append( draw.Line(*proj_xy.p2(0, 0, -1), *proj_xy.p2(0, 0, -1.2), stroke='black', stroke_width=0.02)) d.append(draw.Text(['X'], 0.2, *proj_xy.p2(1.7, 0, 0), center=True, fill='black'), z=100) d.append(draw.Text(['Y'], 0.2, *proj_xy.p2(0, 1.35, 0), center=True, fill='black'), z=100) d.append(draw.Text(['Z'], 0.2, *proj_xy.p2(0, 0, 1.4), center=True, fill='black'), z=100) for pt, (x_off, y_off), elem in outer_labels: x, y = proj.p2(*pt) d.append(draw.Use(elem, x + x_off, y + y_off), z=10000) # Extra annotations #label='', axis=None, rot_proj=None if label: d.append( draw.Text([label], 0.4, -0.6, 1.2, center=True, fill='#c00', text_anchor='end', opacity=extra_opacity)) if axis: g = draw.Group(opacity=extra_opacity) axis = np.array(axis, dtype=float) axis_len = 1.18 axis /= np.linalg.norm(axis) arrow = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=3, orient='auto') arrow.append( draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill='#e00', close=True)) z = 100 #10 * proj_xy.project_point(axis*1)[2] g.append( draw.Line(*proj_xy.p2(0, 0, 0), *proj_xy.p2(*axis * axis_len), stroke='#e00', stroke_width=0.04, marker_end=arrow)) d.append(g, z=z) if rot_proj is not None: rot_proj = inner_proj @ rot_proj r_inner, r_outer = 0.1, 0.16 points = np.array([[-1, -1, 1, 1], [-1, 1, 1, -1]]).T start_end_points = np.array([[1, 0], [-1, 0], [0, 1]]) p = draw.Path(fill='orange', fill_rule='nonzero', opacity=extra_opacity) z = 9 * (trans @ rot_proj).project_point(start_end_points[2])[2] e = shapes.EllipseArc.fromBoundingQuad( *(proj @ rot_proj).project_list(points * r_outer)[:, :2].flatten(), *(proj @ rot_proj).project_list(start_end_points * r_outer)[:, :2].flatten(), ) if e: e.reversed().drawToPath(p) e = shapes.EllipseArc.fromBoundingQuad( *(proj @ rot_proj).project_list(points * r_inner)[:, :2].flatten(), *(proj @ rot_proj).project_list(start_end_points * r_inner)[:, :2].flatten(), ) if e: e.drawToPath(p, includeL=True) sa = 2.5 * (r_outer - r_inner) xa = -(r_inner + r_outer) / 2 p.L(*(proj @ rot_proj).p2(xa, 0.3 * sa)) p.L(*(proj @ rot_proj).p2(xa + 0.5 * sa, 0.3 * sa)) p.L(*(proj @ rot_proj).p2(xa, -0.7 * sa)) p.L(*(proj @ rot_proj).p2(xa - 0.5 * sa, 0.3 * sa)) p.L(*(proj @ rot_proj).p2(xa, 0.3 * sa)) p.Z() d.append(p, z=z) return d
def draw_share_progress(): goal = int(getattr(settings, "SHARE_PROGRESS_GOAL", "10") or "10") offset = int(getattr(settings, "SHARE_PROGRESS_OFFSET", "0") or "0") baseline = int(getattr(settings, "SHARE_PROGRESS_BASELINE", "0") or "0") baseline_progress = baseline / goal ordered = Share.objects.filter( cancelled_date__isnull=True).count() + offset ordered_progress = ordered / goal paid = Share.objects.filter(cancelled_date__isnull=True, paid_date__isnull=False).count() + offset paid_progress = paid / goal d = draw.Drawing(1.8, 1.6, origin='center') arrow = draw.Marker(-0.2, -0.5, 0.9, 0.5, scale=20, orient='auto') arrow.append( draw.Lines(-0.2, -0.5, 0, 0, -0.2, 0.5, 0.9, 0, fill='black', close=True)) arc = draw.Path(stroke='black', stroke_width=0.002, fill_opacity=0, marker_end=arrow) arc.arc(0, 0, 0.6, 89, 94, cw=True) d.append(arc) d.append(draw.Text(f'{goal}', **on_arc(0.63, 0.99))) d.append(progress_arc(ordered_progress, fill_opacity=0.5)) d.append(progress_arc(paid_progress)) if baseline > 0: d.append(progress_arc(baseline_progress, fill='#083c00')) # text center if goal > ordered: d.append(draw.Text('Noch', 0.1, 0, 0.3, center=True)) d.append( draw.Text(str(goal - ordered), 0.3, 0, 0.12, center=True, font_weight='bold')) d.append(draw.Text('Anteilscheine', 0.09, 0, -0.1, center=True)) # labels d.append( draw.Text(f'{ordered-baseline} neue\nbestellt', **on_arc(0.7, ordered_progress))) d.append( draw.Text(f'{paid-baseline} neue\nbezahlt', **on_arc(0.5, paid_progress, 'inner'))) if baseline > 0: d.append( draw.Text(f'{baseline}\nbisher', fill='white', **on_arc(0.5, baseline_progress - 0.025))) else: d.append(draw.Text('Wir haben es', 0.09, 0, 0.14, center=True)) d.append( draw.Text('Geschafft!', 0.18, 0, 0, center=True, font_weight='bold')) # Display d.setRenderSize(w='100%', h='100%') svg = d.asSvg() return svg[:-6] + """<style type="text/css">