def draw_protein_main_sequence(self, current_position): next_row = current_position + self.row_width i = -1 offset = current_position + 1 digits = ndigits(offset) i -= (digits - 1) * 0.5 text_path = TextPath( (self.protein_pad + i, self.layer_height + .2 + self.cur_y), str(current_position + 1), size=self.sequence_font_size / 7.5, prop=font_options) patch = mpatches.PathPatch(text_path, facecolor='grey', edgecolor='grey', lw=0.04) self.ax.add_patch(patch) i = self.row_width text_path = TextPath( (self.protein_pad + i, self.layer_height + .2 + self.cur_y), str(next_row), size=self.sequence_font_size / 7.5, prop=font_options) patch = mpatches.PathPatch(text_path, facecolor='grey', edgecolor='grey', lw=0.04) self.ax.add_patch(patch) self._draw_main_sequence(current_position, next_row)
def _add_single_block(x, y, name, ax): """ Add a single block of two gates. Args: *x (float)*: Layer position. *y (float)*: Qubit 1 position. *name (str)*: Gate name. *ax (pyplot.Axes)*: Axes for the figure. Returns (inplace): None """ ax.add_patch( patches.Rectangle((x, y), 0.5, 0.5, facecolor='white', edgecolor='black')) tp = TextPath((x, y + 0.16), name, size=0.25) center = (tp.get_extents().xmax - tp.get_extents().xmin) / 2 tp = TextPath((x + 0.24 - center, y + 0.16), name, size=0.25) ax.add_patch(patches.PathPatch(tp, color="black"))
def preliminize(text="Preliminary", ax=None, **kwargs): """A very simple code for adding words to a figure. Parameters ---------- text : str, default "Preliminary" Text we add to figure. ax : matplotlib axis What axis? kwargs : goes into the text Returns ------- axis that is preliminized """ # get axis if no ax is provided if type(ax) == type(None): ax = plt.gca() fontdict = { 'horizontalalignment': 'center', 'verticalalignment': 'center', 'fontname': 'Arial', 'alpha': 0.2 } # get rotation from axis to display x0, y0 = ax.transAxes.transform((0, 0)) x1, y1 = ax.transAxes.transform((1, 1)) dy = y0 - y1 dx = x1 - x0 rotation = 180 / pi * atan2(dy, dx) # get fontsize from display extent bb0 = TextPath((0, 0), text, size=50, props=fontdict).get_extents() bb1 = TextPath((0, 0), text, size=51, props=fontdict).get_extents() dw = bb1.width - bb0.width # display / size dh = bb1.height - bb0.height # display / size # get the hypotenuse: through a little math in the display system, we # realize that hypot = h tan theta + w, where h and w are the height and # width of the text tan theta = dy / dx from earlier. we multiply by 0.75 # because this didn't actually work perfectly. size = int(sqrt(dy**2 + dx**2) / (dh * abs(dy / dx) + dw) * 0.75) fontdict['size'] = size # update with any kwargs fontdict.update(kwargs) # set the text ax.text(0.5, 0.5, text, fontdict=fontdict, rotation=rotation, transform=ax.transAxes)
def _add_double_block(x, y, name, ax): ax.add_patch( patches.Rectangle((x, y), 0.5, 1.5, facecolor='white', edgecolor='black')) tp = TextPath((x, y + 0.66), name, size=0.25) center = (tp.get_extents().xmax - tp.get_extents().xmin) / 2 tp = TextPath((x + 0.24 - center, y + 0.66), name, size=0.25) ax.add_patch(patches.PathPatch(tp, color="black"))
def text_banner(axes, text, facecolor="red", edgecolor="darkred", linewidth=1, alpha=0.3, angleadjust=True, zorder=0): """ Paint text across a hole axes. For height > width, angleadjust should be False. """ # draw the text into a patch textpath = TextPath((0, 0), text, size=20, transform=axes.transAxes) tp_bbox = textpath.get_extents() patch = PathPatch(textpath, fc=facecolor, ec=edgecolor, lw=linewidth, alpha=alpha, transform=IdentityTransform(), zorder=11) # get angle and scale to transform text to axes coordinates ax_bbox = axes.get_window_extent() angle = math.atan2(ax_bbox.height, ax_bbox.width) * \ (ax_bbox.height/ax_bbox.width if angleadjust else 1) scale = min(*rotated_scale(tp_bbox.width, tp_bbox.height, angle, ax_bbox.width, ax_bbox.height))*0.95 # paint the patch into the axes offsetbox = AuxTransformBox(Affine2D().rotate(angle).scale(scale)) offsetbox.add_artist(patch) artist = AnnotationBbox(offsetbox, (0.5, 0.5), xycoords='axes fraction', frameon=False) artist.set_zorder(zorder) axes.add_artist(artist)
def _set_mathtext_path(self): """ Draw mathtext markers '$...$' using TextPath object. Submitted by tcb """ from matplotlib.textpath import TextPath # again, the properties could be initialised just once outside # this function text = TextPath(xy=(0, 0), s=self.get_marker(), usetex=rcParams['text.usetex']) if len(text.vertices) == 0: return xmin, ymin = text.vertices.min(axis=0) xmax, ymax = text.vertices.max(axis=0) width = xmax - xmin height = ymax - ymin max_dim = max(width, height) self._transform = Affine2D() \ .translate(-xmin + 0.5 * -width, -ymin + 0.5 * -height) \ .scale(1.0 / max_dim) self._path = text self._snap = False
def get_text_path(text: str, font: FontProperties, size=1) -> TextPath: """Returns a matplotlib :class:`TextPath` object.""" return TextPath((0, 0), text.replace("$", "\\$"), size=size, prop=font, usetex=False)
def text_v2(self, point: tuple, text: str, col: tuple = render_settings.BLACK, size: float = SIZE, vertical_alignment: str = DEFAULT_VERTICAL_ALIGNMENT, border_col: tuple = None): """ Plot text string s at point p in monospace font """ if text is not None: if vertical_alignment == CENTER: point = (point[0], point[1] - size * render_settings.CENTER_CONSTANT) mono_property = font_manager.FontProperties(family='monospace') tp = TextPath(point, text, size=size, prop=mono_property) path_patch = PathPatch(tp, color=col, linewidth=TEXTWIDTH, zorder=TEXT_Z_ORDER) if border_col: path_patch.set_path_effects([ PathEffects.withStroke(linewidth=BORDER_WIDTH, foreground=border_col) ]) self.fig.gca().add_patch(path_patch)
def render_text(text, size=None, position=(0, 0), font_prop=None, tolerance=0.1): tol = 0.1 * tolerance path = TextPath(position, text, size=size, prop=font_prop) polys = [] xmax = position[0] for points, code in path.iter_segments(): if code == path.MOVETO: c = gdstk.Curve(points, tolerance=tolerance) elif code == path.LINETO: c.segment(points.reshape(points.size // 2, 2)) elif code == path.CURVE3: c.quadratic(points.reshape(points.size // 2, 2)) elif code == path.CURVE4: c.cubic(points.reshape(points.size // 2, 2)) elif code == path.CLOSEPOLY: poly = c.points() if poly.size > 0: if poly[:, 0].min() < xmax: i = len(polys) - 1 while i >= 0: if gdstk.inside(poly[:1], [polys[i]], precision=tol)[0]: p = polys.pop(i) b = gdstk.boolean([p], [poly], "xor", tol) poly = b[0].points break elif gdstk.inside(polys[i][:1], [poly], precision=tol)[0]: p = polys.pop(i) b = gdstk.boolean([p], [poly], "xor", tol) poly = b[0].points i -= 1 xmax = max(xmax, poly[:, 0].max()) polys.append(poly) return polys
def make_cities_marker(length, flip_y=True): from matplotlib.path import Path from matplotlib.textpath import TextPath from matplotlib.font_manager import FontProperties circle = Path.unit_circle() scale = math.sqrt(length * 0.8) / 4.0 + (0.4 if length > 1 else 0) circle = circle.transformed(mpl.transforms.Affine2D().scale(scale, scale)) if length <= 1: verts = circle.vertices codes = circle.codes else: text = str(length) fp = FontProperties(family="DejaVu Sans", style="oblique") textPath = TextPath((0, 0), text, size=1 if length <= 9 else 1.2, prop=fp) textPath = textPath.transformed(mpl.transforms.Affine2D().scale( 1, -1 if flip_y else 1).translate( -len(text) / 2.5 if len(text) > 1 else -0.2, 0.3)) verts = np.concatenate([circle.vertices, textPath.vertices]) codes = np.concatenate([circle.codes, textPath.codes]) combined_marker = Path(verts, codes) return combined_marker
def ylabel_tweaks(g, amounts, labels, distance, scale): assert len(amounts) == len(labels) g.set_ylabel("") position = -distance ticklength = 25 text_size = 10 total = sum(amounts) cum_amounts = [0] for a in amounts: cum_amounts.append(cum_amounts[-1] + a) yticks = [a / total for a in cum_amounts] ylocators = [(a + b) / 2 for a, b in zip(yticks, yticks[1:])] for i, l in enumerate(labels): box = TextPath((0, 0), l, size=text_size).get_extents() ylocators[i] += ((box.x1 - box.x0) / 2) * scale ax2 = g.twinx() ax2.spines['right'].set_position(('axes', position)) ax2.spines['right'].set_visible(True) ax2.yaxis.set_major_formatter(ticker.NullFormatter()) ax2.yaxis.set_minor_locator(ticker.FixedLocator(ylocators)) ax2.yaxis.set_minor_formatter(ticker.FixedFormatter(labels)) ax2.tick_params(axis='y', which='minor', width=0, length=0, rotation=90, pad=-(text_size + 3)) ax2.tick_params(axis='y', which='major', width=1, length=ticklength, labelsize=text_size, direction='out') ax2.set_yticks(yticks)
def letter_to_polygon(letter, **kwargs): ''' Construct a Polygon from a letter. Arguments: letter: the letter to be converted to a polygon Keyword arguments: anchor: scale: font_properties: font properties ''' # parse kwargs anchor = kwargs.get('anchor', (0, 0)) scale = kwargs.get('scale', (1, 1)) fp = kwargs.get('font_properties', FontProperties(family='DejaVu Sans', weight='bold')) # create TextPath, and convert to Polygon let = TextPath(anchor, letter, size=1, prop=fp) polygons = [sgeom.Polygon(pol) for pol in let.to_polygons()] geometry = sgeom.Polygon(polygons[0].boundary.coords, holes=[pol.boundary.coords for pol in polygons[1:]]) geometry = affinity.scale(geometry, xfact=scale[0], yfact=scale[1]) return geometry
def draw_protein_main_sequence(self, current_position): next_row = current_position + self.row_width transform = self._make_text_scaler() for i, aa in enumerate( self.protein.protein_sequence[current_position:next_row]): color = self.n_glycosite_bar_color if (i + current_position) in self.glycosites\ else self.default_protein_bar_color rect = mpatches.Rectangle( (self.protein_pad + i, self.layer_height + .05 + self.cur_y), width=self.sequence_font_size / 4.5, height=self.sequence_font_size / 30., facecolor=color) self.ax.add_patch(rect) if i % 100 == 0 and i != 0: xy = np.array((self.protein_pad + i, self.layer_height + .35 + self.cur_y)) text_path = TextPath(xy, str(current_position + i), size=self.sequence_font_size / 7.5, prop=font_options) text_path = text_path.transformed(transform) new_center = transform.transform(xy) delta = xy - new_center - (1, 0) text_path = text_path.transformed(Affine2D().translate(*delta)) patch = mpatches.PathPatch(text_path, facecolor='grey', lw=0.04) self.ax.add_patch(patch)
def _draw_text(ax, x, y, text, size, zorder=2, horizontalalignment='left', verticalalignment='bottom'): if not text: return text_path = TextPath((0, 0), text, size=size) if horizontalalignment == 'right': h_align = np.ptp(text_path.vertices, axis=0)[0] elif horizontalalignment == 'center': h_align = np.ptp(text_path.vertices, axis=0)[0] / 2 elif horizontalalignment == 'left': h_align = 0 else: raise ValueError("{} is not an appropriate horizontalalignment value".format(horizontalalignment)) if verticalalignment == 'top': v_align = np.ptp(text_path.vertices, axis=0)[1] elif verticalalignment == 'center': v_align = np.ptp(text_path.vertices, axis=0)[1] / 2 elif verticalalignment == 'bottom': v_align = 0 else: raise ValueError("{} is not an appropriate verticalalignment value".format(verticalalignment)) translation = matplotlib.transforms.Affine2D().translate(x - h_align, y - v_align) trans_path = text_path.transformed(translation) patch = patches.PathPatch(trans_path, facecolor='black', zorder=zorder, edgecolor=None, linewidth=0) ax.add_patch(patch) return
def polar_text(text, angle, radius=1, scale=0.005, family="sans"): prop = FontProperties(family=family, weight="regular") path = TextPath((0, 0), text, size=1, prop=prop) V = path.vertices xmin, xmax = V[:, 0].min(), V[:, 0].max() V[:, 0] = angle - (V[:, 0] - (xmin + xmax) / 2) * scale V[:, 1] = radius + V[:, 1] * scale patch = PathPatch(path, facecolor="black", linewidth=0, clip_on=False) ax.add_artist(patch)
def plt_draw_text(node: minidom.Element, trans: mtransforms.Transform, style: dict, ids: dict, no_draw: bool = False): """ draw a svg text node as a text patch element into the figure (with the given transformation and style) """ trans = parseTransformation(node.getAttribute("transform")) + trans + plt.gca().transData trans = mtransforms.Affine2D([[1, 0, 0], [0, -1, 0], [0, 0, 1]]) + trans if node.getAttribute("x") != "": pos = np.array([svgUnitToMpl(node.getAttribute("x")), -svgUnitToMpl(node.getAttribute("y"))]) else: pos = np.array([0, 0]) style = get_inline_style(node, get_css_style(node, ids["css"], style)) dx = node.getAttribute("dx") or "0" dy = node.getAttribute("dy") or "0" text_content = "" patch_list = [] for child in node.childNodes: if not isinstance(child, minidom.Element): partial_content = child.data pos_child = pos.copy() pos_child[0] += svgUnitToMpl(dx) pos_child[1] -= svgUnitToMpl(dy) style_child = style part_id = "" else: part_id = node.getAttribute("id") if child.firstChild is None: continue partial_content = child.firstChild.nodeValue style_child = get_inline_style(child, get_css_style(child, ids["css"], style)) pos_child = pos.copy() if child.getAttribute("x") != "": pos_child = np.array([svgUnitToMpl(child.getAttribute("x")), -svgUnitToMpl(child.getAttribute("y"))]) if child.getAttribute("dx") != "": pos_child[0] += svgUnitToMpl(child.getAttribute("dx")) if child.getAttribute("dy") != "": pos_child[1] -= svgUnitToMpl(child.getAttribute("dy")) text_content += partial_content path1 = TextPath(pos_child, partial_content, prop=font_properties_from_style(style_child)) patch = mpatches.PathPatch(path1, transform=trans) apply_style(style_child, patch) if not no_draw and not styleNoDisplay(style_child): plt.gca().add_patch(patch) if part_id != "": ids[part_id] = patch patch_list.append(patch) if node.getAttribute("id") != "": ids[node.getAttribute("id")] = patch_list
def make_text_elements(text, x=0.0, y=0.0, width=1.0, height=1.0, color='blue', edgecolor="black", font = FontProperties(family='monospace')): tp = TextPath((0.0, 0.0), text, size=1, prop=font) bbox = tp.get_extents() bwidth = bbox.x1 - bbox.x0 bheight = bbox.y1 - bbox.y0 trafo = Affine2D() trafo.translate(-bbox.x0, -bbox.y0) trafo.scale(1 / bwidth * width, 1 / bheight * height) trafo.translate(x,y) tp = tp.transformed(trafo) return patches.PathPatch(tp, facecolor=color, edgecolor=edgecolor)
def get_text_path(self, text: str, font: FontProperties) -> TextPath: # None is the default font cache = self._text_path_cache[hash(font)] # defaultdict(dict) path = cache.get(text, None) if path is None: if font is None: font = self._default_font # must replace $ with \$ to avoid matplotlib interpreting it as math text path = TextPath((0, 0), text.replace('$', '\\$'), size=1, prop=font, usetex=False) if self._use_cache: cache[text] = path return path
def plt_draw_text(node, trans, style, ids, no_draw=False): from matplotlib.textpath import TextPath trans = parseTransformation( node.getAttribute("transform")) + trans + plt.gca().transData trans = mtransforms.Affine2D([[1, 0, 0], [0, -1, 0], [0, 0, 1]]) + trans pos = np.array([ svgUnitToMpl(node.getAttribute("x")), -svgUnitToMpl(node.getAttribute("y")) ]) style = get_inline_style(node, get_css_style(node, ids["css"], style)) text_content = "" patch_list = [] for child in node.childNodes: text_content += child.firstChild.nodeValue if 1: style_child = get_inline_style( child, get_css_style(child, ids["css"], style)) pos_child = pos.copy() if child.getAttribute("x") != "": pos_child = np.array([ svgUnitToMpl(child.getAttribute("x")), -svgUnitToMpl(child.getAttribute("y")) ]) if child.getAttribute("dx") != "": pos_child[0] += svgUnitToMpl(child.getAttribute("dx")) if child.getAttribute("dy") != "": pos_child[1] -= svgUnitToMpl(child.getAttribute("dy")) path1 = TextPath(pos_child, child.firstChild.nodeValue, prop=font_properties_from_style(style_child)) patch = mpatches.PathPatch(path1, transform=trans) apply_style(style_child, patch) if not no_draw and not styleNoDisplay(style_child): plt.gca().add_patch(patch) if child.getAttribute("id") != "": ids[child.getAttribute("id")] = patch patch_list.append(patch) else: text = plt.text(float(child.getAttribute("x")), float(child.getAttribute("y")), child.firstChild.nodeValue, transform=trans) apply_style(style, text) if node.getAttribute("id") != "": ids[node.getAttribute("id")] = patch_list
def label(text, angle, radius=1, scale=0.005): path = TextPath((0, 0), text, size=10) path.vertices.flags.writeable = True V = path.vertices xmin, xmax = V[:, 0].min(), V[:, 0].max() ymin, ymax = V[:, 1].min(), V[:, 1].max() V -= (xmin + xmax) / 2, (ymin + ymax) / 2 V *= scale for i in range(len(V)): a = angle - V[i, 0] V[i, 0] = (radius + V[i, 1]) * np.cos(a) V[i, 1] = (radius + V[i, 1]) * np.sin(a) patch = PathPatch(path, facecolor="k", linewidth=0) ax.add_artist(patch)
def contour(X, Y, text, offset=0): # Interpolate text along curve # X0,Y0 for position + X1,Y1 for normal vectors path = TextPath((0, -0.75), text, prop=FontProperties(size=2, family="Roboto", weight="bold")) V = path.vertices X0, Y0, D = interpolate(X, Y, offset + V[:, 0]) X1, Y1, _ = interpolate(X, Y, offset + V[:, 0] + 0.1) # Here we interpolate the original path to get the "remainder" # (path minus text) X, Y, _ = interpolate(X, Y, np.linspace(V[:, 0].max() + 1, D - 1, 200)) plt.plot(X, Y, color="black", linewidth=0.5, markersize=1, marker="o", markevery=[0, -1]) # Transform text vertices dX, dY = X1 - X0, Y1 - Y0 norm = np.sqrt(dX**2 + dY**2) dX, dY = dX / norm, dY / norm X0 += -V[:, 1] * dY Y0 += +V[:, 1] * dX V[:, 0], V[:, 1] = X0, Y0 # Faint outline patch = PathPatch( path, facecolor="white", zorder=10, alpha=0.25, edgecolor="white", linewidth=1.25, ) ax.add_artist(patch) # Actual text patch = PathPatch(path, facecolor="black", zorder=30, edgecolor="black", linewidth=0.0) ax.add_artist(patch)
def _render_text(text, size=None, position=(0, 0), font_prop=None, tolerance=0.1): """This function is copied from https://gdspy.readthedocs.io/en/stable/gettingstarted.html#using-system-fonts""" path = TextPath(position, text, size=size, prop=font_prop) polys = [] xmax = position[0] for points, code in path.iter_segments(): if code == path.MOVETO: c = gdspy.Curve(*points, tolerance=tolerance) elif code == path.LINETO: c.L(*points) elif code == path.CURVE3: c.Q(*points) elif code == path.CURVE4: c.C(*points) elif code == path.CLOSEPOLY: poly = c.get_points() if poly.size > 0: if poly[:, 0].min() < xmax: i = len(polys) - 1 while i >= 0: if gdspy.inside(poly[:1], [polys[i]], precision=0.1 * tolerance)[0]: p = polys.pop(i) poly = gdspy.boolean( [p], [poly], "xor", precision=0.1 * tolerance, max_points=0, ).polygons[0] break elif gdspy.inside(polys[i][:1], [poly], precision=0.1 * tolerance)[0]: p = polys.pop(i) poly = gdspy.boolean( [p], [poly], "xor", precision=0.1 * tolerance, max_points=0, ).polygons[0] i -= 1 xmax = max(xmax, poly[:, 0].max()) polys.append(poly) return polys
def create_text_axes(fig, height_px): """Create an axes in *fig* that contains 'matplotlib' as Text.""" ax = fig.add_axes((0, 0, 1, 1)) ax.set_aspect("equal") ax.set_axis_off() path = TextPath((0, 0), "matplotlib", size=height_px * 0.8, prop=get_font_properties()) fp = get_font_properties() fp.set_weight('light') path1 = TextPath((80, -13), 'Cheat sheet', size=height_px * 0.12, prop=fp) path2 = TextPath((310, -13), f'Version {matplotlib. __version__}', size=height_px * 0.12, prop=fp) angle = 4.25 # degrees trans = mtrans.Affine2D().skew_deg(angle, 0) patch = PathPatch(path, transform=trans + ax.transData, color=MPL_BLUE, lw=0) patch1 = PathPatch(path1, transform=trans + ax.transData, color=MPL_BLUE, lw=0) patch2 = PathPatch(path2, color=MPL_BLUE, lw=0) ax.add_patch(patch) ax.add_patch(patch1) ax.add_patch(patch2) ax.autoscale()
def draw_protein_main_sequence(self, current_position): next_row = current_position + self.row_width i = -1 offset = current_position + 1 digits = ndigits(offset) i -= (digits - 1) * 0.5 text_path = TextPath( (self.protein_pad + i, self.layer_height + .2 + self.cur_y), str(current_position + 1), size=self.sequence_font_size / 7.5, prop=font_options) patch = mpatches.PathPatch(text_path, facecolor='grey', lw=0.04) self.ax.add_patch(patch) i = self.row_width text_path = TextPath( (self.protein_pad + i, self.layer_height + .2 + self.cur_y), str(next_row), size=self.sequence_font_size / 7.5, prop=font_options) patch = mpatches.PathPatch(text_path, facecolor='grey', lw=0.04) self.ax.add_patch(patch) for i, aa in enumerate( self.protein.protein_sequence[current_position:next_row]): text_path = TextPath( (self.protein_pad + i, self.layer_height + .2 + self.cur_y), aa, size=self.sequence_font_size / 7.5, prop=font_options) color = 'red' if any( (((i + current_position) in self.glycosites), ((i + current_position - 1) in self.glycosites), ((i + current_position - 2) in self.glycosites))) else 'black' patch = mpatches.PathPatch(text_path, facecolor=color, lw=0.04) self.ax.add_patch(patch)
def render_text(text, size=None, position=(0, 0), font_prop=None, tolerance=0.1): path = TextPath(position, text, size=size, prop=font_prop) polys = [] xmax = position[0] for points, code in path.iter_segments(): if code == path.MOVETO: c = gdspy.Curve(*points, tolerance=tolerance) elif code == path.LINETO: c.L(*points) elif code == path.CURVE3: c.Q(*points) elif code == path.CURVE4: c.C(*points) elif code == path.CLOSEPOLY: poly = c.get_points() if poly.size > 0: if poly[:, 0].min() < xmax: i = len(polys) - 1 while i >= 0: if gdspy.inside(poly[:1], [polys[i]], precision=0.1 * tolerance)[0]: p = polys.pop(i) poly = gdspy.boolean( [p], [poly], "xor", precision=0.1 * tolerance, max_points=0, ).polygons[0] break elif gdspy.inside(polys[i][:1], [poly], precision=0.1 * tolerance)[0]: p = polys.pop(i) poly = gdspy.boolean( [p], [poly], "xor", precision=0.1 * tolerance, max_points=0, ).polygons[0] i -= 1 xmax = max(xmax, poly[:, 0].max()) polys.append(poly) return polys
def create_text_axes(fig, height_px): """Create an axes in *fig* that contains 'matplotlib' as Text.""" ax = fig.add_axes((0, 0, 1, 1)) ax.set_aspect("equal") ax.set_axis_off() path = TextPath((0, 0), "matplotlib", size=height_px * 0.8, prop=get_font_properties()) angle = 4.25 # degrees trans = mtrans.Affine2D().skew_deg(angle, 0) patch = PathPatch(path, transform=trans + ax.transData, color=MPL_BLUE, lw=0) ax.add_patch(patch) ax.autoscale()
def _draw_main_sequence(self, start, end): for i, aa in enumerate(self.protein.protein_sequence[start:end]): text_path = TextPath( (self.protein_pad + i, self.layer_height + .2 + self.cur_y), aa, size=self.sequence_font_size / 7.5, prop=font_options) color = 'red' if any( (((i + start) in self.glycosites), ((i + start - 1) in self.glycosites), ((i + start - 2) in self.glycosites))) else 'black' patch = mpatches.PathPatch(text_path, facecolor=color, edgecolor=color, lw=0.04) self.ax.add_patch(patch)
def _plot_label(self, ax, x, y, text, color): """ Plot a text label :param ax: matplotlib axis / subplot :param x: x position :param y: y position :param text: text :param color: color of text :return: """ x = self._map_size_x - x - 1 prop = FontProperties(family='monospace', weight='black') tp = TextPath((y, x), text, prop=prop, size=1) polygon = tp.to_polygons() for a in polygon: patch = patches.Polygon(a, facecolor=color, edgecolor='black', linewidth=1, zorder=10) ax.add_patch(patch)
def draw_modification_chips(self, gpm, current_position): start_index, end_index = self._compute_sequence_indices( gpm, current_position) # Extract PTMs from the peptide sequence to draw over the # peptide rectangle seq = self._get_sequence(gpm) for i, pos in enumerate(seq[start_index:end_index]): if len(pos[1]) > 0: modification = pos[1][0] color = self._compute_modification_color(gpm, modification) facecolor, edgecolor = lighten(color), darken(color, 0.6) mod_patch = mpatches.Rectangle( (gpm.start_position - current_position + i - self.mod_x_offset + 0.3 + start_index, self.cur_y), width=self.mod_width, height=self.layer_height, alpha=0.4, facecolor=facecolor, edgecolor=edgecolor, linewidth=0.5, ) self.id_mapper.add("modification-%d", mod_patch, { "modification-type": str(modification), "parent": gpm.id }) self.ax.add_patch(mod_patch) modification_string = str(modification) modification_symbol = modification_string[0] if modification_symbol == '@': modification_symbol = modification_string[1] text_path = TextPath( (gpm.start_position - current_position + i - self.mod_text_x_offset + 0.3 + start_index, self.cur_y + self.mod_text_y_offset), modification_symbol, size=self.mod_font_size / 4.5, prop=font_options) patch = mpatches.PathPatch(text_path, facecolor='black', lw=0.04) self.ax.add_patch(patch)
def text_to_polygons(text, prop=None, subdivision=None): from matplotlib.textpath import TextPath # from matplotlib.font_manager import FontProperties # prop = FontProperties(family='Times New Roman',size=10) text_path = TextPath([0, 0], text, prop=prop) subdivision = subdivision or 10 codes = text_path.codes vertices = text_path.vertices polygons = [] polygon = [] ii = 0 done = False while not done: if codes[ii] == text_path.MOVETO: if len(polygon) > 0: polygons.append(fix_poly(polygon)) polygon = [vertices[ii]] ii += 1 elif codes[ii] == text_path.LINETO: polygon.append(vertices[ii]) ii += 1 elif codes[ii] == text_path.CURVE3: curve_points = vertices[(ii - 1, ii, ii + 1), :] polygon.extend(interp_2d(quadratic, curve_points, subdivision)) ii += 2 elif codes[ii] == text_path.CURVE4: curve_points = vertices[(ii - 1, ii, ii + 1, ii + 2), :] polygon.extend(interp_2d(cubic, curve_points, subdivision)) ii += 3 elif codes[ii] == text_path.CLOSEPOLY: polygons.append(fix_poly(polygon)) polygon = [] ii += 1 else: raise (Exception('unknown')) done = ii >= len(codes) if len(polygon) > 0: polygons.append(fix_poly(polygon)) return polygons