def _draw(self, renderer, bboxes, ticklabels_bbox): renderer.open_group('coordinate_axis') self._update_ticks(renderer) self.ticks.draw(renderer) self.ticklabels.draw(renderer, bboxes=bboxes, ticklabels_bbox=ticklabels_bbox) if self.grid_lines_kwargs['visible']: if self._grid_type == 'lines': self._update_grid_lines() else: self._update_grid_contour() if self._grid_type == 'lines': frame_patch = self.frame.patch for path in self.grid_lines: p = PathPatch(path, **self.grid_lines_kwargs) p.set_clip_path(frame_patch) p.draw(renderer) elif self._grid is not None: for line in self._grid.collections: line.set(**self.grid_lines_kwargs) line.draw(renderer) renderer.close_group('coordinate_axis')
def draw_box_with_text(ax, x, y, width, height, text, color='black', zorder=3, text_fontsize=15, text_color="black", edgecolor='black', linewidth=4, linestyle=None): alignment = {'horizontalalignment': 'center', 'verticalalignment': 'center'} font_1 = font_0.copy() font_1.set_size(text_fontsize) font_1.set_weight('bold') codes = [Path.MOVETO] + [Path.LINETO] * 3 + [Path.CLOSEPOLY] vertices = [(x, y), (x + width, y), (x + width, y - height), (x, y - height), (0, 0)] vertices = np.array(vertices, float) path = Path(vertices, codes) pathpatch = PathPatch( path, #facecolor='None', edgecolor=edgecolor, zorder=zorder,# lw=linewidth, linewidth=linewidth, linestyle=linestyle ) pathpatch.set_fill(False) ax.text(x + width / 2.0, y - height / 2.0, text, color=text_color, fontproperties=font_1, **alignment) ax.add_patch(pathpatch)
def join_lines(ax, min_idx, max_idx, y, color='black'): codes = [Path.MOVETO] + [Path.LINETO] vertices = [(min_idx, y), (max_idx, y)] vertices = np.array(vertices, float) path = Path(vertices, codes) pathpatch = PathPatch(path, facecolor='None', edgecolor=color, zorder=3, lw=4) pathpatch.set_fill(False) ax.add_patch(pathpatch)
def draw_line_1(ax, idx, y_min, y_max, color='black', zorder=3): codes = [Path.MOVETO] + [Path.LINETO] vertices = [(idx, y_max), (idx, y_min)] vertices = np.array(vertices, float) path = Path(vertices, codes) pathpatch = PathPatch(path, facecolor='None', edgecolor=color, zorder=zorder, lw=4) pathpatch.set_fill(False) ax.add_patch(pathpatch)
def hash_fill_between(ax, x, y1, y2=0, **kargs): ''' For x, hash region between y1 and y2. Equivalent of ax.fill_between ''' p = ax.fill_between(x, y1, y2, **kargs) p.set_facecolors("none") p.set_edgecolors("none") for path in p.get_paths(): p1 = PathPatch(path, fc="none", hatch="//", alpha=1) ax.add_patch(p1) p1.set_zorder(p.get_zorder() - 0.1)
def make_path(d, style): items = [] for c in d.split(): if c.upper() in codemap: items.append(c) else: x, y = (float(v) for v in c.split(",")) items.append((x, y)) codes = [] vertices = [] i = 0 lx, ly = 0, 0 last_code = "M" while i < len(items): code = items[i] if not isinstance(code, str): code = last_code else: i += 1 ucode = code.upper() if code.isupper(): relative = False else: relative = True if ucode in ("M", "L"): x, y = items[i] i += 1 if relative: x += lx y += ly codes.append(codemap[ucode]) vertices.append((x, y)) lx, ly = x, y if ucode == "C": if not relative: points = items[i:i+3] else: points = [(_x + lx, _y + ly) for _x, _y in items[i:i+3]] codes.extend([codemap[ucode]]*3) vertices.extend(points) lx, ly = points[-1] i += 3 if ucode == "Z": break last_code = code codes[0] = Path.MOVETO patch = PathPatch( Path(vertices, codes) ) patch.set_linewidth( get_number(style.get("stroke-width", "1px") ) ) fill = style.get("fill", "none") if fill == "none": patch.set_fill( None ) else: patch.set_facecolor( fill ) edge = style.get("stroke", "none") patch.set_edgecolor(edge) return patch
def draw(fig, h, heid, row): ax = plt.subplot2grid(shape=(2,5), loc=(row,0), colspan=2) lbls = labels_count if row==1 else [_] ax.set_xticklabels(lbls) for t in ax.xaxis.get_major_ticks(): t.label.set_rotation(30) rplt.hist(h, axes=ax) npass = sum(list(h)[2:]) p = plt.fill_between([1.5,4.5],[npass,npass], [0.01,0.01]) p.set_facecolors('none') for path in p.get_paths(): p1 = PathPatch(path, fc='none', hatch='\\\\\\', color='blue') ax.add_patch(p1) p1.set_zorder(p.get_zorder()-0.1) ax.set_yscale('log') ylim((0.01,3*h.GetMaximum())) text(0.9, 0.75,'charge skim', fontsize=12, color='blue', transform=ax.transAxes, horizontalalignment='right', verticalalignment='bottom') text(0.9, 0.68, '%.1f'%(100*npass)+'$\%$', fontsize=14, color='blue', transform=ax.transAxes, horizontalalignment='right', verticalalignment='top') ax = plt.subplot2grid(shape=(2,5), loc=(row,2), colspan=3) lbls = labels_eid if row==1 else [_] ax.set_xticklabels(lbls) for t in ax.xaxis.get_major_ticks(): t.label.set_rotation(30) rplt.hist(heid, axes=ax) X = [0.5,6.5] Y1 = [npass,npass] Y2 = [heid.GetMinimum(), heid.GetMinimum()] # plot(X, Y2, 'r-.') p = plt.fill_between([0.5,1.5],[npass,npass]) p.set_facecolors('none') for path in p.get_paths(): p1 = PathPatch(path, fc='none', hatch='\\\\\\', color='blue') ax.add_patch(p1) p1.set_zorder(p.get_zorder()-0.1) p = plt.fill_between([5.5,6.5],Y2) p.set_facecolors('none') for path in p.get_paths(): p1 = PathPatch(path, fc='none', hatch='xxx', color='green') ax.add_patch(p1) p1.set_zorder(p.get_zorder()-0.1) ylim((0.5*heid.GetMinimum(),1.1*heid.GetMaximum())) text(0.95, 0.75, 'refined electron\nidentification', fontsize=12, color='green', transform=ax.transAxes, horizontalalignment='right', verticalalignment='bottom') text(0.95, 0.68, '%.1f'%(100*heid.GetMinimum())+'$\%$', fontsize=14, color='green', transform=ax.transAxes, horizontalalignment='right', verticalalignment='top') # subplots_adjust(bottom=0.5, wspace=0.6, hspace=0.1) subplots_adjust(left=0.1, bottom=0.15, wspace=0.6, hspace=0.1) if row==1: # text(0,-0.0025,'selection criteria', fontsize=12) text(0.5,0,'selection criteria', fontsize=12, transform=fig.transFigure, horizontalalignment='center') text(0, 0.5, 'events per trigger', fontsize=12, transform=fig.transFigure, verticalalignment='center', rotation=90)
def _initPatch(self): """ get pathPatches for plotting res for CRS of dedicate port :return: """ codes = [] vertices = [] for re in self.res: codes += re().codes vertices += re().vertices path = Path(vertices, codes) patch = PathPatch(path, facecolor='white', edgecolor='black', linewidth=0.2, fill='none') patch.set_zorder(90) return patch, codes, vertices
def getResPatchInPrb(self, n__PRB:int): """ get pathPatches for plot res in dedicate Prb :return: """ codes = [] vertices = [] for re in self.prb(n__PRB)().res: codes += re().codes vertices += re().vertices path = Path(vertices, codes) pathPatch = PathPatch(path, facecolor='white', edgecolor='black', linewidth=0.2, linestyle='dotted', fill='none') pathPatch.set_zorder(9) return pathPatch
def getResPatchInReg(self, k___singleQuote:int, l___singleQuote:int): """ get pathPatches for plot res in dedicate Prb :return: """ codes = [] vertices = [] for re in self.reg(k___singleQuote,l___singleQuote).res: codes += re().codes vertices += re().vertices path = Path(vertices, codes) patch = PathPatch(path, facecolor='white', edgecolor='black', linewidth=0.2, linestyle='dotted', fill='none') patch.set_zorder(90) return patch
def create_24_tachogram(gs1, row_number, timing, des1, start_hour=None, stop_hour=None, slice_color="black"): max_timing = np.max(timing) ax_24_tachogram = plt.subplot(gs1[row_number, :]) ax_24_tachogram.set_color_cycle(['blue']) ax_24_tachogram.plot(timing, des1) ax_24_tachogram.ticklabel_format(style='sci', axis='x', scilimits=(0, max_timing)) ax_24_tachogram.xaxis.set_ticks(np.arange(0, int(max_timing) + 1, 1)) ax_24_tachogram.set_xlim(0, max_timing) font_1 = font_0.copy() font_1.set_size('11') font_1.set_weight('bold') y_lim = ax_24_tachogram.get_ylim()[1] if not start_hour == None: codes = [Path.MOVETO] + [Path.LINETO] * 3 + [Path.CLOSEPOLY] vertices = [(start_hour, y_lim - 20), (stop_hour, y_lim - 20), (stop_hour, 0), (start_hour, 0), (0, 0)] vertices = np.array(vertices, float) path = Path(vertices, codes) pathpatch = PathPatch(path, facecolor='None', edgecolor=slice_color, zorder=3, lw=3) pathpatch.set_fill(False) ax_24_tachogram.add_patch(pathpatch) leg = ax_24_tachogram.legend(['$\mathbf{%s}$' % ("RR")], loc='upper left') #change legend font properties plt.setp(leg.get_texts(), fontsize='large') plt.setp(leg.get_texts(), fontweight='bold') ax_24_tachogram.set_xlabel(u"Czas [godziny]", fontproperties = font_1) ax_24_tachogram.set_ylabel(u"RR [ms]", fontproperties = font_1) tachogram_label_pos = 18 font_1 = font_0.copy() font_1.set_size('18') font_1.set_weight('bold') ax_24_tachogram.text(tachogram_label_pos, y_lim - 200, u"Tachogram - 24 godziny", fontproperties = font_1) bold_ticks_labels(ax_24_tachogram) return row_number + 1
def _initPatch(self, n__s:int, subFrameTypeName:str): """ generate path patch for this PRB :param n__s: :param subFrameTypeName: :return: """ vertices = [] codes = [] bottom = 0 left = 0 width = 0 height = 0 if subFrameTypeName == 'D': bottom = self.n__PRB * conf.N__sc___RB_DL left = 0 width = conf.N__symb___DL height = conf.N__sc___RB_DL if subFrameTypeName == 'U': bottom = self.n__PRB * conf.N__sc___RB_UL left = 0 width = conf.N__symb___UL height = conf.N__sc___RB_UL if subFrameTypeName == 'S': if n__s %1 == 0: bottom = self.n__PRB * conf.N__sc___RB_DL left = 0 width = conf.N__symb___DwPTS height = conf.N__sc___RB_DL if n__s %1 == 1: bottom = self.n__PRB * conf.N__sc___RB_UL left = conf.N__symb___UpPTS width = conf.N__symb___UL - conf.N__symb___DwPTS height = conf.N__sc___RB_UL codes = [Path.MOVETO] + [Path.LINETO]*3 + [Path.CLOSEPOLY] vertices = [(left,bottom), (left,bottom+height), (left+width,bottom+height), (left+width,bottom), (0,0)] path = Path(vertices, codes) patch = PathPatch(path, facecolor='white', edgecolor='black', linewidth=2.0, fill='none' ) patch.set_zorder(80) return patch, codes, vertices
def _draw(self, renderer, bboxes): renderer.open_group('coordinate_axis') self._update_ticks(renderer) self._update_grid() self.ticks.draw(renderer) self.ticklabels.draw(renderer, bboxes=bboxes) if self.grid_lines_kwargs['visible']: for path in self.grid_lines: p = PathPatch(path, **self.grid_lines_kwargs) p.set_clip_path(self.frame.path, Affine2D()) p.draw(renderer) renderer.close_group('coordinate_axis')
def __init__(self, canvas, color, x, y0=None, y1=None, line_width=1.0, picker_width=5, line_style='-'): """ Init the marker. :param canvas: A MPL canvas. :param color: An MPL colour value :param x: The x coordinate (data) of the marker. :param y0: The y coordinate (data) of the bottom end of the marker. Default is None which means dynamically set it to the current lowest y value displayed. :param y1: The y coordinate (data) of the top end of the marker. Default is None which means dynamically set it to the current highest y value displayed. :param line_width: The line width (pixels). :param picker_width: The picker sensitivity (pixels). :param line_style: An MPL line style value. """ super(VerticalMarker, self).__init__() self.ax = canvas.figure.get_axes()[0] self.x = x self.y0 = y0 self.y1 = y1 y0, y1 = self._get_y0_y1() path = Path([(x, y0), (x, y1)], [Path.MOVETO, Path.LINETO]) self.patch = PathPatch(path, facecolor='None', edgecolor=color, picker=picker_width, linewidth=line_width, linestyle=line_style, animated=True) self.ax.add_patch(self.patch) self.is_moving = False
def initPatch(self): """ plot based on matplotlib :return: """ vertices = [] codes = [] codes = [Path.MOVETO] + [Path.LINETO]*3 + [Path.CLOSEPOLY] vertices = [(self.l,self.k), ((self.l),(self.k+1)), ((self.l+1),(self.k+1)), ((self.l+1),(self.k)), (0,0)] path = Path(vertices, codes) patch = PathPatch(path, facecolor='white', edgecolor='black') patch.set_zorder(100) return patch, codes,vertices
def _initPatch(self): """ generate path patch for this SLOT :param n: :param subFrameTypeName: :return: """ vertices = [] codes = [] vertices += self.slots[0].vertices codes += self.slots[0].codes vertices += self.slots[1].vertices codes += self.slots[1].codes path = Path(vertices, codes) patch = PathPatch(path, facecolor='white', edgecolor='black', linewidth=2.0, fill='none' ) patch.set_zorder(60) return patch, codes, vertices
def _add_ends(self): """ Create patches from extended ends and add them to the axes. """ del self.extension_patch1 del self.extension_patch2 path1, path2 = self.ax.get_axes_locator().get_path_ends() fc = mpl.rcParams["axes.facecolor"] ec = mpl.rcParams["axes.edgecolor"] linewidths = 0.5 * mpl.rcParams["axes.linewidth"] self.extension_patch1 = PathPatch( path1, fc=fc, ec=ec, lw=linewidths, zorder=2.0, transform=self.ax.transAxes, clip_on=False ) self.extension_patch2 = PathPatch( path2, fc=fc, ec=ec, lw=linewidths, zorder=2.0, transform=self.ax.transAxes, clip_on=False ) self.ax.add_artist(self.extension_patch1) self.ax.add_artist(self.extension_patch2)
def _sync_patch(self): if self._patch is not None: self._patch.remove() self._patch = None if self._roi.defined(): x, y = self._roi.to_polygon() p = MplPath(np.column_stack((x, y))) self._patch = PathPatch(p) self._patch.set_visible(True) self._patch.set(**self.plot_opts)
class MplPathROI(MplPolygonalROI): def roi_factory(self): return Path() def _setup_patch(self): self._patch = None def _sync_patch(self): if self._patch is not None: self._patch.remove() self._patch = None # Update geometry if not self._roi.defined(): return else: x, y = self._roi.to_polygon() p = MplPath(np.column_stack((x, y))) self._patch = PathPatch(p) self._patch.set_visible(True) # Update appearance self._patch.set(**self.plot_opts) # Refresh self._axes.figure.canvas.draw() def finalize_selection(self, event): self._mid_selection = False if self._patch is not None: self._patch.set_visible(False) self._axes.figure.canvas.draw()
def BezierHitTest(path, x0, y0): from matplotlib.patches import PathPatch import ifigure.widgets.canvas.custom_picker as cpicker segpath = BezierSplit(path) i = 0 for seg in segpath: p = [(item[0], item[1]) for item in seg] codes, verts = zip(*p) obj = matplotlib.path.Path(verts, codes) a = PathPatch(obj) xy= a.get_verts() if len(xy) == 0: ## this case happens when verts has only two points in mpl1.5 x = [v[0] for v in verts] y = [v[1] for v in verts] else: x = np.transpose(xy)[0] y = np.transpose(xy)[1] hit, idx = cpicker.CheckLineHit(x, y, x0, y0) if hit: return True, i i = i+1 return False, -1
def scatter(self, x, y, s, ax=None, fancy=False, **kwargs): """ takes data coordinate x, y and plot them to a data coordinate axes, s is the radius in data units. When fancy is True, apply a radient filter so that the edge is blent into the background; better with marker='o' or marker='+'. """ X, Y, S = numpy.asarray([x, y, s]) if ax is None: ax=self.default_axes def filter(image, dpi): # this is problematic if the marker is clipped. if image.shape[0] <=1 and image.shape[1] <=1: return image xgrad = 1.0 \ - numpy.fabs(numpy.linspace(0, 2, image.shape[0], endpoint=True) - 1.0) ygrad = 1.0 \ - numpy.fabs(numpy.linspace(0, 2, image.shape[1], endpoint=True) - 1.0) image[..., 3] *= xgrad[:, None] ** 0.5 image[..., 3] *= ygrad[None, :] ** 0.5 return image, 0, 0 marker = kwargs.pop('marker', 'x') verts = kwargs.pop('verts', None) # to be API compatible if marker is None and not (verts is None): marker = (verts, 0) verts = None objs = [] color = kwargs.pop('color', None) edgecolor = kwargs.pop('edgecolor', None) linewidth = kwargs.pop('linewidth', kwargs.pop('lw', None)) marker_obj = MarkerStyle(marker) if not marker_obj.is_filled(): edgecolor = color for x,y,r in numpy.nditer([X, Y, S], flags=['zerosize_ok']): path = marker_obj.get_path().transformed( marker_obj.get_transform().scale(r).translate(x, y)) obj = PathPatch( path, facecolor = color, edgecolor = edgecolor, linewidth = linewidth, transform = ax.transData, ) obj.set_alpha(1.0) if fancy: obj.set_agg_filter(filter) obj.rasterized = True objs += [obj] ax.add_artist(obj) ax.autoscale_view() return objs
def _sync_patch(self): if self._patch is not None: self._patch.remove() self._patch = None # Update geometry if not self._roi.defined(): return else: x, y = self._roi.to_polygon() p = MplPath(np.column_stack((x, y))) self._patch = PathPatch(p) self._patch.set_visible(True) # Update appearance self._patch.set(**self.plot_opts) # Refresh self._axes.figure.canvas.draw()
def profiles_rigid_vs_el_mtrx(): r = 0.003 tau = 0.3 V_f = 0.11 E_f = 200e3 E_m = 25e10 Ll = 35. Lr = 35. Xxi = RV('weibull_min', shape=5., scale=.02) Xr = RV('uniform', loc=.002, scale=.002) Xtau = RV('uniform', loc=.02, scale=.98) reinf2 = Reinforcement(r=Xr, tau=Xtau, V_f=V_f, E_f=E_f, xi=Xxi, n_int=15) model2 = CompositeCrackBridge(E_m=E_m, reinforcement_lst=[reinf2], Ll=Ll, Lr=Lr) ccb_view2 = CompositeCrackBridgeView(model=model2) ccb_view2.sigma_c_max x2 = np.hstack((-Ll, ccb_view2.x_arr, Lr)) mu_epsf2 = np.hstack((ccb_view2.mu_epsf_arr[0], ccb_view2.mu_epsf_arr, ccb_view2.mu_epsf_arr[-1])) epsm2 = np.hstack((ccb_view2.epsm_arr[0], ccb_view2.epsm_arr, ccb_view2.epsm_arr[-1])) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(x2, mu_epsf2, lw=2, color='black') ax.plot(x2, epsm2, lw=2, color='black') p = ax.fill_between(x2, epsm2, mu_epsf2, facecolor='none') from matplotlib.patches import PathPatch path = p.get_paths()[0] p1 = PathPatch(path, fc="none", hatch="/") ax.add_patch(p1) p1.set_zorder(p.get_zorder()-0.1) p = ax.fill_between(x2, mu_epsf2, facecolor='none') path = p.get_paths()[0] p1 = PathPatch(path, fc="none", hatch="\\") ax.add_patch(p1) p1.set_zorder(p.get_zorder()-0.1) reinf1 = Reinforcement(r=r, tau=tau, V_f=V_f, E_f=E_f, xi=Xxi, n_int=15) model1 = CompositeCrackBridge(E_m=E_m, reinforcement_lst=[reinf1], Ll=Ll, Lr=Lr) ccb_view1 = CompositeCrackBridgeView(model=model1) ccb_view1.sigma_c_max x1 = np.hstack((-Ll, ccb_view1.x_arr, Lr)) mu_epsf1 = np.hstack((ccb_view1.mu_epsf_arr[0], ccb_view1.mu_epsf_arr, ccb_view1.mu_epsf_arr[-1])) epsm1 = np.hstack((ccb_view1.epsm_arr[0], ccb_view1.epsm_arr, ccb_view1.epsm_arr[-1])) ax.plot(x1, mu_epsf1, lw=2, color='black') ax.plot(x1, epsm1, lw=2, color='black') plt.xlabel('z [mm]') plt.xlim(-35, 35) plt.ylim(0) plt.ylabel('$\epsilon$ [-]')
def create_zoom_plot(gs1, row_number, timing, start_hour=None, stop_hour=None, slice_color="black"): max_timing = np.max(timing) ax_zoom = plt.subplot(gs1[row_number, :]) ax_zoom.set_axis_off() ax_zoom.set_frame_on(False) ax_zoom.set_xlim(0, max_timing) alignment = {'horizontalalignment': 'center', 'verticalalignment': 'center'} text_fontsize = 18 font_1 = font_0.copy() font_1.set_size(text_fontsize) font_1.set_weight('bold') codes = [Path.MOVETO] + [Path.LINETO] vertices = [(start_hour, 1.0), (0, 0)] vertices = np.array(vertices, float) path = Path(vertices, codes) pathpatch = PathPatch(path, facecolor='None', edgecolor=slice_color, zorder=3, lw=3) pathpatch.set_fill(False) ax_zoom.add_patch(pathpatch) codes = [Path.MOVETO] + [Path.LINETO] vertices = [(stop_hour, 1.0), (max_timing, 0)] vertices = np.array(vertices, float) path = Path(vertices, codes) pathpatch = PathPatch(path, facecolor='None', edgecolor=slice_color, zorder=3, lw=3) pathpatch.set_fill(False) ax_zoom.add_patch(pathpatch) # ax_zoom.text(stop_hour-1, 0.3, u"2-godzinny wycinek tachogramu", # fontproperties=font_1, # **alignment # #size=20 # ) return row_number + 1
class MplPathROI(MplPolygonalROI): """ Matplotlib ROI for path selections Parameters ---------- axes : `~matplotlib.axes.Axes` The Matplotlib axes to draw to. """ _roi_cls = Path def __init__(self, axes, roi=None): super(MplPolygonalROI, self).__init__(axes) self.plot_opts = {'edgecolor': PATCH_COLOR, 'facecolor': PATCH_COLOR, 'alpha': 0.3} self._patch = None def _sync_patch(self): if self._patch is not None: self._patch.remove() self._patch = None if self._roi.defined(): x, y = self._roi.to_polygon() p = MplPath(np.column_stack((x, y))) self._patch = PathPatch(p) self._patch.set_visible(True) self._patch.set(**self.plot_opts) def finalize_selection(self, event): self._mid_selection = False if self._patch is not None: self._patch.set_visible(False) self._draw()
def create_24_tachogram(gs1, row_number, timing, des1, slice_color="black"): max_timing = np.max(timing) ax_24_tachogram = plt.subplot(gs1[row_number, :]) ax_24_tachogram.set_color_cycle(['blue']) ax_24_tachogram.plot(timing, des1) ax_24_tachogram.ticklabel_format(style='sci', axis='x', scilimits=(0, max_timing)) ax_24_tachogram.xaxis.set_ticks(np.arange(0, int(max_timing) + 1, 1)) ax_24_tachogram.set_xlim(0, max_timing) font_1 = font_0.copy() font_1.set_size('13') font_1.set_weight('bold') alignment = {'horizontalalignment': 'center', 'verticalalignment': 'center'} y_lim_min = ax_24_tachogram.get_ylim()[0] y_lim_max = ax_24_tachogram.get_ylim()[1] shift = 50 for position in positions: codes = [Path.MOVETO] + [Path.LINETO] * 3 + [Path.CLOSEPOLY] start_pos = position - 0.5 stop_pos = position + 0.5 vertices = [(start_pos, y_lim_max - shift), (stop_pos, y_lim_max - shift), (stop_pos, y_lim_min + shift), (start_pos, y_lim_min + shift), (0, 0)] vertices = np.array(vertices, float) path = Path(vertices, codes) pathpatch = PathPatch(path, facecolor='None', edgecolor=slice_color, zorder=3, lw=3) pathpatch.set_fill(False) ax_24_tachogram.add_patch(pathpatch) ax_24_tachogram.text(position, y_lim_min + 2 * shift, u"5 min.", fontproperties=font_1, **alignment) # size=15) leg = ax_24_tachogram.legend(['$\mathbf{%s}$' % ("RR")], loc='upper left') # change legend font properties plt.setp(leg.get_texts(), fontsize='large') plt.setp(leg.get_texts(), fontweight='bold') ax_24_tachogram.set_xlabel(u"Czas [godziny]", fontproperties=font_1) ax_24_tachogram.set_ylabel(u"RR [ms]", fontproperties=font_1) tachogram_label_pos = 18 font_1 = font_0.copy() font_1.set_size('18') font_1.set_weight('bold') ax_24_tachogram.text(0.85, 0.9, u"Tachogram - 24 godziny", fontproperties=font_1, transform=ax_24_tachogram.transAxes) # size=15) arrow_size = 4.5 head_width = 45 tail_width = 25 head_length = 40 arrow_shift = 100 pos_start = positions[2] + 0.75 pos_stop = positions[3] - 0.75 draw_simple_arrow(ax_24_tachogram, # posA=(pos_x - arrow_size / 2.0, y_lim_max - head_width - arrow_shift), # posB=(pos_x + arrow_size / 2.0, y_lim_max - head_width - arrow_shift), posA=(pos_start, y_lim_max - head_width - arrow_shift), posB=(pos_stop, y_lim_max - head_width - arrow_shift), tail_width=tail_width, head_width=head_width, head_length=head_length, color="red", text=u"Kierunek przesuwania okna", text_fontsize=12, lw=2.0, ) # ax_24_tachogram.text(tachogram_label_pos, y_lim - 200, # u"Tachogram - 24 godziny", fontproperties = font_1) bold_ticks_labels(ax_24_tachogram, fontsize=13) return row_number + 1
def plot_density_single(settings, sample_label, tx_start, tx_end, gene_obj, mRNAs, strand, graphcoords, graphToGene, bam_group, axvar, chrom, paired_end=False, intron_scale=30, exon_scale=4, color='r', ymax=None, logged=False, coverage=1, number_junctions=True, resolution=.5, showXaxis=True, showYaxis=True, nyticks=3, nxticks=4, show_ylabel=True, show_xlabel=True, font_size=6, junction_log_base=10, plot_title=None, plot_label=None): """ Plot MISO events using BAM files and posterior distribution files. TODO: If comparison files are available, plot Bayes factors too. """ wiggle = zeros((tx_end - tx_start + 1), dtype='f') jxns = {} bamfile_num = len(bam_group) all_c = [] for i in range(bamfile_num): file_name = os.path.expanduser(bam_group[i]) bamfile = pysam.Samfile(file_name, 'rb') try: subset_reads = bamfile.fetch(reference=chrom, start=tx_start,end=tx_end) except ValueError as e: print "Error retrieving files from %s: %s" %(chrom, str(e)) print "Are you sure %s appears in your BAM file?" %(chrom) print "Aborting plot..." return axvar # wiggle, jxns = readsToWiggle_pysam(subset_reads, tx_start, tx_end) # p1 = subprocess.Popen(["samtools", "view", "-F", "0x4", file_name,], stdout=subprocess.PIPE) # p2 = subprocess.Popen(["cut", "-f", "1",], stdin=p1.stdout, stdout=subprocess.PIPE) # p3 = subprocess.Popen(["sort",], stdin=p2.stdout, stdout=subprocess.PIPE) # p4 = subprocess.Popen(["uniq",], stdin=p3.stdout, stdout=subprocess.PIPE) # p5 = subprocess.Popen(["wc", "-l",], stdin=p4.stdout, stdout=subprocess.PIPE) # p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. # p2.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. # p3.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. # p4.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. # output,err = p5.communicate() p1 = subprocess.Popen(["samtools", "idxstats", file_name,], stdout=subprocess.PIPE) p2 = subprocess.Popen(["awk", "{s+=$3} END {print s}",], stdin=p1.stdout, stdout=subprocess.PIPE) p1.stdout.close() output,err = p2.communicate() if err: print err print 'Setting the number of mapped read to 1.' cover = 1 else: cover = int(output) / 1e6 all_c.append(cover) readsToWiggle_pysam(subset_reads, tx_start, tx_end, wiggle, jxns) coverage = np.mean(all_c) wiggle = 1e3 * wiggle / coverage / bamfile_num # junction_width_scale = settings["junction_width_scale"] for j_key in jxns.keys(): jxns[j_key] = int(round(1.0 * jxns[j_key] / bamfile_num, 0)) # gene_reads = sam_utils.fetch_bam_reads_in_gene(bamfile, gene_obj.chrom,\ # tx_start, tx_end, gene_obj) # reads, num_raw_reads = sam_utils.sam_parse_reads(gene_reads,\ # paired_end=paired_end) # wiggle, jxns = readsToWiggle(reads, tx_start, tx_end) #wiggle = 1e3 * wiggle / coverage if logged: wiggle = log10(wiggle + 1) maxheight = max(wiggle) if ymax is None: ymax = 1.1 * maxheight else: ymax = ymax ymin = -.5 * ymax # Reduce memory footprint by using incremented graphcoords. compressed_x = [] compressed_wiggle = [] prevx = graphcoords[0] tmpval = [] for i in range(len(graphcoords)): tmpval.append(wiggle[i]) if abs(graphcoords[i] - prevx) > resolution: compressed_wiggle.append(mean(tmpval)) compressed_x.append(prevx) prevx = graphcoords[i] tmpval = [] fill_between(compressed_x, compressed_wiggle,\ y2=0, color=color, lw=0) sslists = [] for mRNA in mRNAs: tmp = [] for s, e in mRNA: tmp.extend([s, e]) sslists.append(tmp) min_counts = settings["min_counts"] # if the jxn is smaller than it, then omit the text plotting show_text_background = settings["text_background"] maxy = 0 for jxn in jxns: leftss, rightss = map(int, jxn.split(":")) ss1, ss2 = [graphcoords[leftss - tx_start - 1],\ graphcoords[rightss - tx_start]] mid = (ss1 + ss2) / 2 h = -3 * ymin / 4 numisoforms = 0 for i in range(len(mRNAs)): if leftss in sslists[i] and \ rightss in sslists[i]: numisoforms += 1 if numisoforms > 0: if numisoforms % 2 == 0: # put on bottom pts = [(ss1, 0), (ss1, -h), (ss2, -h), (ss2, 0)] midpt = cubic_bezier(pts, .5) else: # put on top leftdens = wiggle[leftss - tx_start - 1] rightdens = wiggle[rightss - tx_start] pts = [(ss1, leftdens), (ss1, leftdens + h), (ss2, rightdens + h), (ss2, rightdens)] midpt = cubic_bezier(pts, .5) if min_counts == 0 or jxns[jxn] >= min_counts: if number_junctions: if show_text_background: txt = text(midpt[0], midpt[1], '%s'%(jxns[jxn]), fontsize=font_size-2, ha='center', va='center', backgroundcolor='w') else: txt = text(midpt[0], midpt[1], '%s' % (jxns[jxn]), fontsize=font_size-2, ha='center', va='center') interval = axvar.get_ylim()[1]*0.05 y = interval + midpt[1] maxy = max(maxy, y) a = Path(pts, [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4]) p = PathPatch(a, ec=color, lw=log(jxns[jxn] + 1) /\ log(junction_log_base) * (jxns[jxn] + 1)**0.33 * 0.1, fc='none', clip_on=False) axvar.add_patch(p) # Format plot # ylim(ymin, ymax) # axvar.spines['left'].set_bounds(0, ymax) axvar.spines['right'].set_color('none') axvar.spines['top'].set_color('none') if showXaxis: axvar.xaxis.set_ticks_position('bottom') xlabel('Genomic coordinate (%s), "%s" strand'%(gene_obj.chrom, strand), fontsize=font_size) max_graphcoords = max(graphcoords) - 1 coords_fontsize = font_size - (font_size * 0.2) xticks(linspace(0, max_graphcoords, nxticks), [graphToGene[int(x)] for x in \ linspace(0, max_graphcoords, nxticks)], fontsize=coords_fontsize) else: axvar.spines['bottom'].set_color('none') xticks([]) # if showYaxis: # axvar.yaxis.set_ticks_position('left') # yticks(linspace(0, ymax, nyticks), ['%d'%(x) for x in \ # linspace(0, ymax, nyticks)], # fontsize=font_size) # else: # axvar.spines['left'].set_color('none') # yticks([]) xlim(0, max(graphcoords)) # Return modified axis return axvar, maxy
def add(self, patchlabel='', flows=None, orientations=None, labels='', trunklength=1.0, pathlengths=0.25, prior=None, connect=(0, 0), rotation=0, **kwargs): """ Add a simple Sankey diagram with flows at the same hierarchical level. Parameters ---------- patchlabel : str Label to be placed at the center of the diagram. Note that *label* (not *patchlabel*) can be passed as keyword argument to create an entry in the legend. flows : list of float Array of flow values. By convention, inputs are positive and outputs are negative. Flows are placed along the top of the diagram from the inside out in order of their index within *flows*. They are placed along the sides of the diagram from the top down and along the bottom from the outside in. If the sum of the inputs and outputs is nonzero, the discrepancy will appear as a cubic Bezier curve along the top and bottom edges of the trunk. orientations : list of {-1, 0, 1} List of orientations of the flows (or a single orientation to be used for all flows). Valid values are 0 (inputs from the left, outputs to the right), 1 (from and to the top) or -1 (from and to the bottom). labels : list of (str or None) List of labels for the flows (or a single label to be used for all flows). Each label may be *None* (no label), or a labeling string. If an entry is a (possibly empty) string, then the quantity for the corresponding flow will be shown below the string. However, if the *unit* of the main diagram is None, then quantities are never shown, regardless of the value of this argument. trunklength : float Length between the bases of the input and output groups (in data-space units). pathlengths : list of float List of lengths of the vertical arrows before break-in or after break-away. If a single value is given, then it will be applied to the first (inside) paths on the top and bottom, and the length of all other arrows will be justified accordingly. The *pathlengths* are not applied to the horizontal inputs and outputs. prior : int Index of the prior diagram to which this diagram should be connected. connect : (int, int) A (prior, this) tuple indexing the flow of the prior diagram and the flow of this diagram which should be connected. If this is the first diagram or *prior* is *None*, *connect* will be ignored. rotation : float Angle of rotation of the diagram in degrees. The interpretation of the *orientations* argument will be rotated accordingly (e.g., if *rotation* == 90, an *orientations* entry of 1 means to/from the left). *rotation* is ignored if this diagram is connected to an existing one (using *prior* and *connect*). Returns ------- Sankey The current `.Sankey` instance. Other Parameters ---------------- **kwargs Additional keyword arguments set `matplotlib.patches.PathPatch` properties, listed below. For example, one may want to use ``fill=False`` or ``label="A legend entry"``. %(Patch)s See Also -------- Sankey.finish """ # Check and preprocess the arguments. if flows is None: flows = np.array([1.0, -1.0]) else: flows = np.array(flows) n = flows.shape[0] # Number of flows if rotation is None: rotation = 0 else: # In the code below, angles are expressed in deg/90. rotation /= 90.0 if orientations is None: orientations = 0 try: orientations = np.broadcast_to(orientations, n) except ValueError: raise ValueError( f"The shapes of 'flows' {np.shape(flows)} and 'orientations' " f"{np.shape(orientations)} are incompatible") from None try: labels = np.broadcast_to(labels, n) except ValueError: raise ValueError( f"The shapes of 'flows' {np.shape(flows)} and 'labels' " f"{np.shape(labels)} are incompatible") from None if trunklength < 0: raise ValueError( "'trunklength' is negative, which is not allowed because it " "would cause poor layout") if np.abs(np.sum(flows)) > self.tolerance: _log.info( "The sum of the flows is nonzero (%f; patchlabel=%r); " "is the system not at steady state?", np.sum(flows), patchlabel) scaled_flows = self.scale * flows gain = sum(max(flow, 0) for flow in scaled_flows) loss = sum(min(flow, 0) for flow in scaled_flows) if prior is not None: if prior < 0: raise ValueError("The index of the prior diagram is negative") if min(connect) < 0: raise ValueError( "At least one of the connection indices is negative") if prior >= len(self.diagrams): raise ValueError( f"The index of the prior diagram is {prior}, but there " f"are only {len(self.diagrams)} other diagrams") if connect[0] >= len(self.diagrams[prior].flows): raise ValueError( "The connection index to the source diagram is {}, but " "that diagram has only {} flows".format( connect[0], len(self.diagrams[prior].flows))) if connect[1] >= n: raise ValueError( f"The connection index to this diagram is {connect[1]}, " f"but this diagram has only {n} flows") if self.diagrams[prior].angles[connect[0]] is None: raise ValueError( f"The connection cannot be made, which may occur if the " f"magnitude of flow {connect[0]} of diagram {prior} is " f"less than the specified tolerance") flow_error = (self.diagrams[prior].flows[connect[0]] + flows[connect[1]]) if abs(flow_error) >= self.tolerance: raise ValueError( f"The scaled sum of the connected flows is {flow_error}, " f"which is not within the tolerance ({self.tolerance})") # Determine if the flows are inputs. are_inputs = [None] * n for i, flow in enumerate(flows): if flow >= self.tolerance: are_inputs[i] = True elif flow <= -self.tolerance: are_inputs[i] = False else: _log.info( "The magnitude of flow %d (%f) is below the tolerance " "(%f).\nIt will not be shown, and it cannot be used in a " "connection.", i, flow, self.tolerance) # Determine the angles of the arrows (before rotation). angles = [None] * n for i, (orient, is_input) in enumerate(zip(orientations, are_inputs)): if orient == 1: if is_input: angles[i] = DOWN elif not is_input: # Be specific since is_input can be None. angles[i] = UP elif orient == 0: if is_input is not None: angles[i] = RIGHT else: if orient != -1: raise ValueError( f"The value of orientations[{i}] is {orient}, " f"but it must be -1, 0, or 1") if is_input: angles[i] = UP elif not is_input: angles[i] = DOWN # Justify the lengths of the paths. if np.iterable(pathlengths): if len(pathlengths) != n: raise ValueError( f"The lengths of 'flows' ({n}) and 'pathlengths' " f"({len(pathlengths)}) are incompatible") else: # Make pathlengths into a list. urlength = pathlengths ullength = pathlengths lrlength = pathlengths lllength = pathlengths d = dict(RIGHT=pathlengths) pathlengths = [d.get(angle, 0) for angle in angles] # Determine the lengths of the top-side arrows # from the middle outwards. for i, (angle, is_input, flow) in enumerate(zip(angles, are_inputs, scaled_flows)): if angle == DOWN and is_input: pathlengths[i] = ullength ullength += flow elif angle == UP and not is_input: pathlengths[i] = urlength urlength -= flow # Flow is negative for outputs. # Determine the lengths of the bottom-side arrows # from the middle outwards. for i, (angle, is_input, flow) in enumerate( reversed(list(zip(angles, are_inputs, scaled_flows)))): if angle == UP and is_input: pathlengths[n - i - 1] = lllength lllength += flow elif angle == DOWN and not is_input: pathlengths[n - i - 1] = lrlength lrlength -= flow # Determine the lengths of the left-side arrows # from the bottom upwards. has_left_input = False for i, (angle, is_input, spec) in enumerate( reversed( list( zip(angles, are_inputs, zip(scaled_flows, pathlengths))))): if angle == RIGHT: if is_input: if has_left_input: pathlengths[n - i - 1] = 0 else: has_left_input = True # Determine the lengths of the right-side arrows # from the top downwards. has_right_output = False for i, (angle, is_input, spec) in enumerate( zip(angles, are_inputs, list(zip(scaled_flows, pathlengths)))): if angle == RIGHT: if not is_input: if has_right_output: pathlengths[i] = 0 else: has_right_output = True # Begin the subpaths, and smooth the transition if the sum of the flows # is nonzero. urpath = [ ( Path.MOVETO, [ (self.gap - trunklength / 2.0), # Upper right gain / 2.0 ]), (Path.LINETO, [(self.gap - trunklength / 2.0) / 2.0, gain / 2.0]), (Path.CURVE4, [(self.gap - trunklength / 2.0) / 8.0, gain / 2.0]), (Path.CURVE4, [(trunklength / 2.0 - self.gap) / 8.0, -loss / 2.0]), (Path.LINETO, [(trunklength / 2.0 - self.gap) / 2.0, -loss / 2.0]), (Path.LINETO, [(trunklength / 2.0 - self.gap), -loss / 2.0]) ] llpath = [ ( Path.LINETO, [ (trunklength / 2.0 - self.gap), # Lower left loss / 2.0 ]), (Path.LINETO, [(trunklength / 2.0 - self.gap) / 2.0, loss / 2.0]), (Path.CURVE4, [(trunklength / 2.0 - self.gap) / 8.0, loss / 2.0]), (Path.CURVE4, [(self.gap - trunklength / 2.0) / 8.0, -gain / 2.0]), (Path.LINETO, [(self.gap - trunklength / 2.0) / 2.0, -gain / 2.0]), (Path.LINETO, [(self.gap - trunklength / 2.0), -gain / 2.0]) ] lrpath = [( Path.LINETO, [ (trunklength / 2.0 - self.gap), # Lower right loss / 2.0 ])] ulpath = [( Path.LINETO, [ self.gap - trunklength / 2.0, # Upper left gain / 2.0 ])] # Add the subpaths and assign the locations of the tips and labels. tips = np.zeros((n, 2)) label_locations = np.zeros((n, 2)) # Add the top-side inputs and outputs from the middle outwards. for i, (angle, is_input, spec) in enumerate( zip(angles, are_inputs, list(zip(scaled_flows, pathlengths)))): if angle == DOWN and is_input: tips[i, :], label_locations[i, :] = self._add_input( ulpath, angle, *spec) elif angle == UP and not is_input: tips[i, :], label_locations[i, :] = self._add_output( urpath, angle, *spec) # Add the bottom-side inputs and outputs from the middle outwards. for i, (angle, is_input, spec) in enumerate( reversed( list( zip(angles, are_inputs, list(zip(scaled_flows, pathlengths)))))): if angle == UP and is_input: tip, label_location = self._add_input(llpath, angle, *spec) tips[n - i - 1, :] = tip label_locations[n - i - 1, :] = label_location elif angle == DOWN and not is_input: tip, label_location = self._add_output(lrpath, angle, *spec) tips[n - i - 1, :] = tip label_locations[n - i - 1, :] = label_location # Add the left-side inputs from the bottom upwards. has_left_input = False for i, (angle, is_input, spec) in enumerate( reversed( list( zip(angles, are_inputs, list(zip(scaled_flows, pathlengths)))))): if angle == RIGHT and is_input: if not has_left_input: # Make sure the lower path extends # at least as far as the upper one. if llpath[-1][1][0] > ulpath[-1][1][0]: llpath.append( (Path.LINETO, [ulpath[-1][1][0], llpath[-1][1][1]])) has_left_input = True tip, label_location = self._add_input(llpath, angle, *spec) tips[n - i - 1, :] = tip label_locations[n - i - 1, :] = label_location # Add the right-side outputs from the top downwards. has_right_output = False for i, (angle, is_input, spec) in enumerate( zip(angles, are_inputs, list(zip(scaled_flows, pathlengths)))): if angle == RIGHT and not is_input: if not has_right_output: # Make sure the upper path extends # at least as far as the lower one. if urpath[-1][1][0] < lrpath[-1][1][0]: urpath.append( (Path.LINETO, [lrpath[-1][1][0], urpath[-1][1][1]])) has_right_output = True tips[i, :], label_locations[i, :] = self._add_output( urpath, angle, *spec) # Trim any hanging vertices. if not has_left_input: ulpath.pop() llpath.pop() if not has_right_output: lrpath.pop() urpath.pop() # Concatenate the subpaths in the correct order (clockwise from top). path = (urpath + self._revert(lrpath) + llpath + self._revert(ulpath) + [(Path.CLOSEPOLY, urpath[0][1])]) # Create a patch with the Sankey outline. codes, vertices = zip(*path) vertices = np.array(vertices) def _get_angle(a, r): if a is None: return None else: return a + r if prior is None: if rotation != 0: # By default, none of this is needed. angles = [_get_angle(angle, rotation) for angle in angles] rotate = Affine2D().rotate_deg(rotation * 90).transform_affine tips = rotate(tips) label_locations = rotate(label_locations) vertices = rotate(vertices) text = self.ax.text(0, 0, s=patchlabel, ha='center', va='center') else: rotation = (self.diagrams[prior].angles[connect[0]] - angles[connect[1]]) angles = [_get_angle(angle, rotation) for angle in angles] rotate = Affine2D().rotate_deg(rotation * 90).transform_affine tips = rotate(tips) offset = self.diagrams[prior].tips[connect[0]] - tips[connect[1]] translate = Affine2D().translate(*offset).transform_affine tips = translate(tips) label_locations = translate(rotate(label_locations)) vertices = translate(rotate(vertices)) kwds = dict(s=patchlabel, ha='center', va='center') text = self.ax.text(*offset, **kwds) if rcParams['_internal.classic_mode']: fc = kwargs.pop('fc', kwargs.pop('facecolor', '#bfd1d4')) lw = kwargs.pop('lw', kwargs.pop('linewidth', 0.5)) else: fc = kwargs.pop('fc', kwargs.pop('facecolor', None)) lw = kwargs.pop('lw', kwargs.pop('linewidth', None)) if fc is None: fc = next(self.ax._get_patches_for_fill.prop_cycler)['color'] patch = PathPatch(Path(vertices, codes), fc=fc, lw=lw, **kwargs) self.ax.add_patch(patch) # Add the path labels. texts = [] for number, angle, label, location in zip(flows, angles, labels, label_locations): if label is None or angle is None: label = '' elif self.unit is not None: quantity = self.format % abs(number) + self.unit if label != '': label += "\n" label += quantity texts.append( self.ax.text(x=location[0], y=location[1], s=label, ha='center', va='center')) # Text objects are placed even they are empty (as long as the magnitude # of the corresponding flow is larger than the tolerance) in case the # user wants to provide labels later. # Expand the size of the diagram if necessary. self.extent = (min(np.min(vertices[:, 0]), np.min(label_locations[:, 0]), self.extent[0]), max(np.max(vertices[:, 0]), np.max(label_locations[:, 0]), self.extent[1]), min(np.min(vertices[:, 1]), np.min(label_locations[:, 1]), self.extent[2]), max(np.max(vertices[:, 1]), np.max(label_locations[:, 1]), self.extent[3])) # Include both vertices _and_ label locations in the extents; there are # where either could determine the margins (e.g., arrow shoulders). # Add this diagram as a subdiagram. self.diagrams.append( SimpleNamespace(patch=patch, flows=flows, angles=angles, tips=tips, text=text, texts=texts)) # Allow a daisy-chained call structure (see docstring for the class). return self
def create_windowed_tachogram(gs1, row_number, timing, des1, max_idx, start_hour=None, stop_hour=None): # RIGHT TACHOGRAM START ax_windowed_tachogram = plt.subplot(gs1[row_number, 0]) ax_windowed_tachogram.set_color_cycle(['blue', 'red']) max_timing = np.max(timing) des1_max = np.max(des1) des1_min = np.min(des1) only_2_hours = is_only_2_hours(start_hour, stop_hour) ax_windowed_tachogram.plot(timing, des1) ax_windowed_tachogram.ticklabel_format(style='sci', axis='x', scilimits=(0, max_timing)) ax_windowed_tachogram.xaxis.set_ticks(np.arange(0, int(max_timing)+1, 1)) ax_windowed_tachogram.set_xlim(0, max_timing) font_1 = font_0.copy() font_1.set_size('11') font_1.set_weight('bold') if start_hour == None: x_label = u"Czas [godziny]" else: x_label = u"Czas [minuty]" ax_windowed_tachogram.set_xlabel(x_label, fontproperties=font_1) ax_windowed_tachogram.set_ylabel(u"Wartość [ms]", fontproperties=font_1) font_1 = font_0.copy() font_1.set_size('18') font_1.set_weight('bold') y_lim = ax_windowed_tachogram.get_ylim()[1] if start_hour == None: tachogram_label_pos = 19 tach_label = u"Tachogram - 24 godziny" else: tachogram_label_pos = 17 tach_label = u"Tachogram - fragment 2 godziny" ax_windowed_tachogram.text(tachogram_label_pos, y_lim - 100, tach_label, fontproperties=font_1 # size=20 ) first_lw = 0.5 lws = np.linspace(first_lw, 4, max_idx + 1 + first_lw)[::-1] for idx, lw in zip(range(max_idx - 1, -1, -1), lws): if not (idx % window_step == 0): continue codes = [Path.MOVETO] + [Path.LINETO] * 3 + [Path.CLOSEPOLY] vertices = [(idx, des1_max - des1_max / 10), (idx + window_step, des1_max - des1_max / 10), (idx + window_step, des1_min + des1_max / 10), (idx, des1_min + des1_max / 10), (0, 0)] vertices = np.array(vertices, float) path = Path(vertices, codes) pathpatch = PathPatch(path, facecolor='None', edgecolor='red', zorder=3, lw=lw) pathpatch.set_fill(False) ax_windowed_tachogram.add_patch(pathpatch) leg = ax_windowed_tachogram.legend(['$\mathbf{%s}$' % ("RR"), "Okno danych - 5 minut"], loc='upper left', numpoints=5) # change legend font properties plt.setp(leg.get_texts(), fontsize='large') plt.setp(leg.get_texts(), fontweight='bold') arrow_size = 4.5 head_width = 45 tail_width = 25 head_length = 40 arrow_shift = 100 if start_hour == None else 40 draw_simple_arrow(ax_windowed_tachogram, posA=(max_idx / 2.0 - arrow_size / 2.0, y_lim - head_width - arrow_shift), posB=(max_idx / 2.0 + arrow_size / 2.0, y_lim - head_width - arrow_shift), tail_width=tail_width, head_width=head_width, head_length=head_length, color="red", text=u"Kierunek przesuwania okna", text_fontsize=12, lw=2.0, ) if not start_hour == None: change_ticks_for_5_minutes(ax_windowed_tachogram) bold_ticks_labels(ax_windowed_tachogram) if only_2_hours == True: change_xtickslabels_2_hours(ax_windowed_tachogram) return row_number + 1
'C': Path.CURVE4, 'L': Path.LINETO, } while i < len(parts): path_code = code_map[parts[i]] npoints = Path.NUM_VERTICES_FOR_CODE[path_code] codes.extend([path_code] * npoints) vertices.extend([[*map(float, y.split(','))] for y in parts[i + 1:][:npoints]]) i += npoints + 1 vertices = np.array(vertices) vertices[:, 1] -= 160 dolphin_path = Path(vertices, codes) dolphin_patch = PathPatch(dolphin_path, facecolor=(0.6, 0.6, 0.6), edgecolor=(0.0, 0.0, 0.0)) ax.add_patch(dolphin_patch) vertices = Affine2D().rotate_deg(60).transform(vertices) dolphin_path2 = Path(vertices, codes) dolphin_patch2 = PathPatch(dolphin_path2, facecolor=(0.5, 0.5, 0.5), edgecolor=(0.0, 0.0, 0.0)) ax.add_patch(dolphin_patch2) plt.show() ############################################################################# # # ------------ # # References
def add(self, patchlabel='', flows=None, orientations=None, labels='', trunklength=1.0, pathlengths=0.25, prior=None, connect=(0, 0), rotation=0, **kwargs): """ Add a simple Sankey diagram with flows at the same hierarchical level. Return value is the instance of :class:`Sankey`. Optional keyword arguments: =============== =================================================== Keyword Description =============== =================================================== *patchlabel* label to be placed at the center of the diagram Note: *label* (not *patchlabel*) will be passed to the patch through ``**kwargs`` and can be used to create an entry in the legend. *flows* array of flow values By convention, inputs are positive and outputs are negative. *orientations* list of orientations of the paths Valid values are 1 (from/to the top), 0 (from/to the left or right), or -1 (from/to the bottom). If *orientations* == 0, inputs will break in from the left and outputs will break away to the right. *labels* list of specifications of the labels for the flows Each value may be *None* (no labels), '' (just label the quantities), or a labeling string. If a single value is provided, it will be applied to all flows. If an entry is a non-empty string, then the quantity for the corresponding flow will be shown below the string. However, if the *unit* of the main diagram is None, then quantities are never shown, regardless of the value of this argument. *trunklength* length between the bases of the input and output groups *pathlengths* list of lengths of the arrows before break-in or after break-away If a single value is given, then it will be applied to the first (inside) paths on the top and bottom, and the length of all other arrows will be justified accordingly. The *pathlengths* are not applied to the horizontal inputs and outputs. *prior* index of the prior diagram to which this diagram should be connected *connect* a (prior, this) tuple indexing the flow of the prior diagram and the flow of this diagram which should be connected If this is the first diagram or *prior* is *None*, *connect* will be ignored. *rotation* angle of rotation of the diagram [deg] *rotation* is ignored if this diagram is connected to an existing one (using *prior* and *connect*). The interpretation of the *orientations* argument will be rotated accordingly (e.g., if *rotation* == 90, an *orientations* entry of 1 means to/from the left). =============== =================================================== Valid kwargs are :meth:`matplotlib.patches.PathPatch` arguments: %(Patch)s As examples, ``fill=False`` and ``label='A legend entry'``. By default, ``facecolor='#bfd1d4'`` (light blue) and ``linewidth=0.5``. The indexing parameters (*prior* and *connect*) are zero-based. The flows are placed along the top of the diagram from the inside out in order of their index within the *flows* list or array. They are placed along the sides of the diagram from the top down and along the bottom from the outside in. If the sum of the inputs and outputs is nonzero, the discrepancy will appear as a cubic Bezier curve along the top and bottom edges of the trunk. .. seealso:: :meth:`finish` """ # Check and preprocess the arguments. if flows is None: flows = np.array([1.0, -1.0]) else: flows = np.array(flows) n = flows.shape[0] # Number of flows if rotation is None: rotation = 0 else: # In the code below, angles are expressed in deg/90. rotation /= 90.0 if orientations is None: orientations = [0, 0] if len(orientations) != n: raise ValueError( "orientations and flows must have the same length.\n" "orientations has length %d, but flows has length %d." % (len(orientations), n)) if labels != '' and getattr(labels, '__iter__', False): # iterable() isn't used because it would give True if labels is a # string if len(labels) != n: raise ValueError( "If labels is a list, then labels and flows must have the " "same length.\nlabels has length %d, but flows has length %d." % (len(labels), n)) else: labels = [labels] * n if trunklength < 0: raise ValueError( "trunklength is negative.\nThis isn't allowed, because it would " "cause poor layout.") if np.abs(np.sum(flows)) > self.tolerance: verbose.report( "The sum of the flows is nonzero (%f).\nIs the " "system not at steady state?" % np.sum(flows), 'helpful') scaled_flows = self.scale * flows gain = sum(max(flow, 0) for flow in scaled_flows) loss = sum(min(flow, 0) for flow in scaled_flows) if not (0.5 <= gain <= 2.0): verbose.report( "The scaled sum of the inputs is %f.\nThis may " "cause poor layout.\nConsider changing the scale so" " that the scaled sum is approximately 1.0." % gain, 'helpful') if not (-2.0 <= loss <= -0.5): verbose.report( "The scaled sum of the outputs is %f.\nThis may " "cause poor layout.\nConsider changing the scale so" " that the scaled sum is approximately 1.0." % gain, 'helpful') if prior is not None: if prior < 0: raise ValueError("The index of the prior diagram is negative.") if min(connect) < 0: raise ValueError( "At least one of the connection indices is negative.") if prior >= len(self.diagrams): raise ValueError( "The index of the prior diagram is %d, but there are " "only %d other diagrams.\nThe index is zero-based." % (prior, len(self.diagrams))) if connect[0] >= len(self.diagrams[prior].flows): raise ValueError( "The connection index to the source diagram is %d, but " "that diagram has only %d flows.\nThe index is zero-based." % (connect[0], len(self.diagrams[prior].flows))) if connect[1] >= n: raise ValueError( "The connection index to this diagram is %d, but this diagram" "has only %d flows.\n The index is zero-based." % (connect[1], n)) if self.diagrams[prior].angles[connect[0]] is None: raise ValueError( "The connection cannot be made. Check that the magnitude " "of flow %d of diagram %d is greater than or equal to the " "specified tolerance." % (connect[0], prior)) flow_error = (self.diagrams[prior].flows[connect[0]] + flows[connect[1]]) if abs(flow_error) >= self.tolerance: raise ValueError( "The scaled sum of the connected flows is %f, which is not " "within the tolerance (%f)." % (flow_error, self.tolerance)) # Determine if the flows are inputs. are_inputs = [None] * n for i, flow in enumerate(flows): if flow >= self.tolerance: are_inputs[i] = True elif flow <= -self.tolerance: are_inputs[i] = False else: verbose.report( "The magnitude of flow %d (%f) is below the " "tolerance (%f).\nIt will not be shown, and it " "cannot be used in a connection." % (i, flow, self.tolerance), 'helpful') # Determine the angles of the arrows (before rotation). angles = [None] * n for i, (orient, is_input) in enumerate(zip(orientations, are_inputs)): if orient == 1: if is_input: angles[i] = DOWN elif not is_input: # Be specific since is_input can be None. angles[i] = UP elif orient == 0: if is_input is not None: angles[i] = RIGHT else: if orient != -1: raise ValueError( "The value of orientations[%d] is %d, " "but it must be [ -1 | 0 | 1 ]." % (i, orient)) if is_input: angles[i] = UP elif not is_input: angles[i] = DOWN # Justify the lengths of the paths. if iterable(pathlengths): if len(pathlengths) != n: raise ValueError( "If pathlengths is a list, then pathlengths and flows must " "have the same length.\npathlengths has length %d, but flows " "has length %d." % (len(pathlengths), n)) else: # Make pathlengths into a list. urlength = pathlengths ullength = pathlengths lrlength = pathlengths lllength = pathlengths d = dict(RIGHT=pathlengths) pathlengths = [d.get(angle, 0) for angle in angles] # Determine the lengths of the top-side arrows # from the middle outwards. for i, (angle, is_input, flow) in enumerate(zip(angles, are_inputs, scaled_flows)): if angle == DOWN and is_input: pathlengths[i] = ullength ullength += flow elif angle == UP and not is_input: pathlengths[i] = urlength urlength -= flow # Flow is negative for outputs. # Determine the lengths of the bottom-side arrows # from the middle outwards. for i, (angle, is_input, flow) in enumerate(reversed(list(zip( angles, are_inputs, scaled_flows)))): if angle == UP and is_input: pathlengths[n - i - 1] = lllength lllength += flow elif angle == DOWN and not is_input: pathlengths[n - i - 1] = lrlength lrlength -= flow # Determine the lengths of the left-side arrows # from the bottom upwards. has_left_input = False for i, (angle, is_input, spec) in enumerate(reversed(list(zip( angles, are_inputs, zip(scaled_flows, pathlengths))))): if angle == RIGHT: if is_input: if has_left_input: pathlengths[n - i - 1] = 0 else: has_left_input = True # Determine the lengths of the right-side arrows # from the top downwards. has_right_output = False for i, (angle, is_input, spec) in enumerate(zip( angles, are_inputs, list(zip(scaled_flows, pathlengths)))): if angle == RIGHT: if not is_input: if has_right_output: pathlengths[i] = 0 else: has_right_output = True # Begin the subpaths, and smooth the transition if the sum of the flows # is nonzero. urpath = [(Path.MOVETO, [(self.gap - trunklength / 2.0), # Upper right gain / 2.0]), (Path.LINETO, [(self.gap - trunklength / 2.0) / 2.0, gain / 2.0]), (Path.CURVE4, [(self.gap - trunklength / 2.0) / 8.0, gain / 2.0]), (Path.CURVE4, [(trunklength / 2.0 - self.gap) / 8.0, -loss / 2.0]), (Path.LINETO, [(trunklength / 2.0 - self.gap) / 2.0, -loss / 2.0]), (Path.LINETO, [(trunklength / 2.0 - self.gap), -loss / 2.0])] llpath = [(Path.LINETO, [(trunklength / 2.0 - self.gap), # Lower left loss / 2.0]), (Path.LINETO, [(trunklength / 2.0 - self.gap) / 2.0, loss / 2.0]), (Path.CURVE4, [(trunklength / 2.0 - self.gap) / 8.0, loss / 2.0]), (Path.CURVE4, [(self.gap - trunklength / 2.0) / 8.0, -gain / 2.0]), (Path.LINETO, [(self.gap - trunklength / 2.0) / 2.0, -gain / 2.0]), (Path.LINETO, [(self.gap - trunklength / 2.0), -gain / 2.0])] lrpath = [(Path.LINETO, [(trunklength / 2.0 - self.gap), # Lower right loss / 2.0])] ulpath = [(Path.LINETO, [self.gap - trunklength / 2.0, # Upper left gain / 2.0])] # Add the subpaths and assign the locations of the tips and labels. tips = np.zeros((n, 2)) label_locations = np.zeros((n, 2)) # Add the top-side inputs and outputs from the middle outwards. for i, (angle, is_input, spec) in enumerate(zip( angles, are_inputs, list(zip(scaled_flows, pathlengths)))): if angle == DOWN and is_input: tips[i, :], label_locations[i, :] = self._add_input( ulpath, angle, *spec) elif angle == UP and not is_input: tips[i, :], label_locations[i, :] = self._add_output( urpath, angle, *spec) # Add the bottom-side inputs and outputs from the middle outwards. for i, (angle, is_input, spec) in enumerate(reversed(list(zip( angles, are_inputs, list(zip(scaled_flows, pathlengths)))))): if angle == UP and is_input: tip, label_location = self._add_input(llpath, angle, *spec) tips[n - i - 1, :] = tip label_locations[n - i - 1, :] = label_location elif angle == DOWN and not is_input: tip, label_location = self._add_output(lrpath, angle, *spec) tips[n - i - 1, :] = tip label_locations[n - i - 1, :] = label_location # Add the left-side inputs from the bottom upwards. has_left_input = False for i, (angle, is_input, spec) in enumerate(reversed(list(zip( angles, are_inputs, list(zip(scaled_flows, pathlengths)))))): if angle == RIGHT and is_input: if not has_left_input: # Make sure the lower path extends # at least as far as the upper one. if llpath[-1][1][0] > ulpath[-1][1][0]: llpath.append((Path.LINETO, [ulpath[-1][1][0], llpath[-1][1][1]])) has_left_input = True tip, label_location = self._add_input(llpath, angle, *spec) tips[n - i - 1, :] = tip label_locations[n - i - 1, :] = label_location # Add the right-side outputs from the top downwards. has_right_output = False for i, (angle, is_input, spec) in enumerate(zip( angles, are_inputs, list(zip(scaled_flows, pathlengths)))): if angle == RIGHT and not is_input: if not has_right_output: # Make sure the upper path extends # at least as far as the lower one. if urpath[-1][1][0] < lrpath[-1][1][0]: urpath.append((Path.LINETO, [lrpath[-1][1][0], urpath[-1][1][1]])) has_right_output = True tips[i, :], label_locations[i, :] = self._add_output( urpath, angle, *spec) # Trim any hanging vertices. if not has_left_input: ulpath.pop() llpath.pop() if not has_right_output: lrpath.pop() urpath.pop() # Concatenate the subpaths in the correct order (clockwise from top). path = (urpath + self._revert(lrpath) + llpath + self._revert(ulpath) + [(Path.CLOSEPOLY, urpath[0][1])]) # Create a patch with the Sankey outline. codes, vertices = list(zip(*path)) vertices = np.array(vertices) def _get_angle(a, r): if a is None: return None else: return a + r if prior is None: if rotation != 0: # By default, none of this is needed. angles = [_get_angle(angle, rotation) for angle in angles] rotate = Affine2D().rotate_deg(rotation * 90).transform_affine tips = rotate(tips) label_locations = rotate(label_locations) vertices = rotate(vertices) text = self.ax.text(0, 0, s=patchlabel, ha='center', va='center') else: rotation = (self.diagrams[prior].angles[connect[0]] - angles[connect[1]]) angles = [_get_angle(angle, rotation) for angle in angles] rotate = Affine2D().rotate_deg(rotation * 90).transform_affine tips = rotate(tips) offset = self.diagrams[prior].tips[connect[0]] - tips[connect[1]] translate = Affine2D().translate(*offset).transform_affine tips = translate(tips) label_locations = translate(rotate(label_locations)) vertices = translate(rotate(vertices)) kwds = dict(s=patchlabel, ha='center', va='center') text = self.ax.text(*offset, **kwds) if False: # Debug print("llpath\n", llpath) print("ulpath\n", self._revert(ulpath)) print("urpath\n", urpath) print("lrpath\n", self._revert(lrpath)) xs, ys = list(zip(*vertices)) self.ax.plot(xs, ys, 'go-') if rcParams['_internal.classic_mode']: fc = kwargs.pop('fc', kwargs.pop('facecolor', '#bfd1d4')) lw = kwargs.pop('lw', kwargs.pop('linewidth', 0.5)) else: fc = kwargs.pop('fc', kwargs.pop('facecolor', None)) lw = kwargs.pop('lw', kwargs.pop('linewidth', None)) if fc is None: fc = six.next(self.ax._get_patches_for_fill.prop_cycler)['color'] patch = PathPatch(Path(vertices, codes), fc=fc, lw=lw, **kwargs) self.ax.add_patch(patch) # Add the path labels. texts = [] for number, angle, label, location in zip(flows, angles, labels, label_locations): if label is None or angle is None: label = '' elif self.unit is not None: quantity = self.format % abs(number) + self.unit if label != '': label += "\n" label += quantity texts.append(self.ax.text(x=location[0], y=location[1], s=label, ha='center', va='center')) # Text objects are placed even they are empty (as long as the magnitude # of the corresponding flow is larger than the tolerance) in case the # user wants to provide labels later. # Expand the size of the diagram if necessary. self.extent = (min(np.min(vertices[:, 0]), np.min(label_locations[:, 0]), self.extent[0]), max(np.max(vertices[:, 0]), np.max(label_locations[:, 0]), self.extent[1]), min(np.min(vertices[:, 1]), np.min(label_locations[:, 1]), self.extent[2]), max(np.max(vertices[:, 1]), np.max(label_locations[:, 1]), self.extent[3])) # Include both vertices _and_ label locations in the extents; there are # where either could determine the margins (e.g., arrow shoulders). # Add this diagram as a subdiagram. self.diagrams.append(Bunch(patch=patch, flows=flows, angles=angles, tips=tips, text=text, texts=texts)) # Allow a daisy-chained call structure (see docstring for the class). return self
def _render_on_subplot(self, subplot): """ Render this Bezier path in a subplot. This is the key function that defines how this Bezier path graphics primitive is rendered in matplotlib's library. TESTS:: sage: bezier_path([[(0,1),(.5,0),(1,1)]]) :: sage: bezier_path([[(0,1),(.5,0),(1,1),(-3,5)]]) """ from matplotlib.patches import PathPatch from matplotlib.path import Path options = dict(self.options()) del options['alpha'] del options['thickness'] del options['rgbcolor'] del options['zorder'] del options['fill'] del options['linestyle'] bpath = Path(self.vertices, self.codes) bpatch = PathPatch(bpath, **options) options = self.options() bpatch.set_linewidth(float(options['thickness'])) bpatch.set_fill(options['fill']) bpatch.set_zorder(options['zorder']) a = float(options['alpha']) bpatch.set_alpha(a) c = to_mpl_color(options['rgbcolor']) bpatch.set_edgecolor(c) bpatch.set_facecolor(c) bpatch.set_linestyle(options['linestyle']) subplot.add_patch(bpatch)
import numpy as np import matplotlib.cm as cm import matplotlib.mlab as mlab import matplotlib.pyplot as plt from matplotlib.path import Path from matplotlib.patches import PathPatch delta = 0.025 x = y = np.arange(-3.0, 3.0, delta) X, Y = np.meshgrid(x, y) Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) Z = Z2-Z1 # difference of Gaussians path = Path([[0, 1], [1, 0], [0, -1], [-1, 0], [0, 1]]) patch = PathPatch(path, facecolor='none') plt.gca().add_patch(patch) im = plt.imshow(Z, interpolation='bilinear', cmap=cm.gray, origin='lower', extent=[-3,3,-3,3], clip_path=patch, clip_on=True) im.set_clip_path(patch)
def kdp_objects(kdpc,KDPmasked,ax,f,time_start,month,d_beg,h_beg,min_beg,sec_beg,d_end,h_end,min_end,sec_end,rlons,rlats,max_lons_c,max_lats_c,kdplev,proj): kdp_areas = [] kdp_centroid_lon = [] kdp_centroid_lat = [] kdp_max = [] kdp_storm_lon = [] kdp_storm_lat = [] if np.max(KDPmasked) > kdplev: for level in kdpc.collections: for contour_poly in level.get_paths(): for n_contour,contour in enumerate(contour_poly.to_polygons()): contour_a = np.asarray(contour[:]) xa = contour_a[:,0] ya = contour_a[:,1] polygon_new = geometry.Polygon([(i[0], i[1]) for i in zip(xa,ya)]) if n_contour == 0: polygon = polygon_new else: polygon = polygon.difference(polygon_new) try: pr_area = (transform(proj, polygon).area * units('m^2')).to('km^2') except: continue boundary = np.asarray(polygon.boundary.xy) polypath = Path(boundary.transpose()) coord_map = np.vstack((rlons[0,:,:].flatten(), rlats[0,:,:].flatten())).T # create an Mx2 array listing all the coordinates in field mask_kdp = polypath.contains_points(coord_map).reshape(rlons[0,:,:].shape) if pr_area > 2 * units('km^2'): g = Geod(ellps='sphere') dist_kdp = np.zeros((np.asarray(max_lons_c).shape[0])) for i in range(dist_kdp.shape[0]): distance_kdp = g.inv(polygon.centroid.x, polygon.centroid.y, max_lons_c[i], max_lats_c[i]) dist_kdp[i] = distance_kdp[2]/1000. try: if np.min(np.asarray(dist_kdp)) < 15.0 and np.max((np.max(KDPmasked[mask_kdp])) > 1.5): kdp_path = polypath kdp_areas.append((pr_area)) kdp_centroid_lon.append((polygon.centroid.x)) kdp_centroid_lat.append((polygon.centroid.y)) kdp_storm_lon.append((max_lons_c[np.where(dist_kdp == np.min(dist_kdp))[0][0]])) kdp_storm_lat.append((max_lats_c[np.where(dist_kdp == np.min(dist_kdp))[0][0]])) kdp_max.append((np.max(KDPmasked[mask_kdp]))) patch = PathPatch(polypath, facecolor='green', alpha=.5, edgecolor = 'green', linewidth = 3) ax.add_patch(patch) #Add polygon to placefile f.write('TimeRange: '+str(time_start.year)+'-'+str(month)+'-'+str(d_beg)+'T'+str(h_beg)+':'+str(min_beg)+':'+str(sec_beg)+'Z '+str(time_start.year)+'-'+str(month)+'-'+str(d_end)+'T'+str(h_end)+':'+str(min_end)+':'+str(sec_end)+'Z') f.write('\n') f.write("Color: 000 139 000 \n") f.write('Line: 3, 0, "KDP Foot Outline" \n') for i in range(len(kdp_path.vertices)): f.write("%.5f" %(kdp_path.vertices[i][1])) f.write(", ") f.write("%.5f" %(kdp_path.vertices[i][0])) f.write('\n') f.write("End: \n \n") f.flush() except: print('kdp fail') return kdp_areas,kdp_centroid_lon,kdp_centroid_lat,kdp_storm_lon,kdp_storm_lat,kdp_max,ax,f
def __init__(self, transform, label_x, label_y, length=0.15, fontsize=0.08, loc=2, angle=0, aspect_ratio=1, pad=0.4, borderpad=0.4, frameon=False, color='w', alpha=1, sep_x=0.01, sep_y=0, fontproperties=None, back_length=0.15, head_width=10, head_length=15, tail_width=2, text_props=None, arrow_props=None, **kwargs): """ Draw two perpendicular arrows to indicate directions. Parameters ---------- transform : `matplotlib.transforms.Transform` The transformation object for the coordinate system in use, i.e., :attr:`matplotlib.axes.Axes.transAxes`. label_x, label_y : str Label text for the x and y arrows length : float, default: 0.15 Length of the arrow, given in coordinates of *transform*. fontsize : float, default: 0.08 Size of label strings, given in coordinates of *transform*. loc : int, default: 2 Location of the direction arrows. Valid location codes are:: 'upper right' : 1, 'upper left' : 2, 'lower left' : 3, 'lower right' : 4, 'right' : 5, 'center left' : 6, 'center right' : 7, 'lower center' : 8, 'upper center' : 9, 'center' : 10 angle : float, default: 0 The angle of the arrows in degrees. aspect_ratio : float, default: 1 The ratio of the length of arrow_x and arrow_y. Negative numbers can be used to change the direction. pad : float, default: 0.4 Padding around the labels and arrows, in fraction of the font size. borderpad : float, default: 0.4 Border padding, in fraction of the font size. frameon : bool, default: False If True, draw a box around the arrows and labels. color : str, default: 'white' Color for the arrows and labels. alpha : float, default: 1 Alpha values of the arrows and labels sep_x, sep_y : float, default: 0.01 and 0 respectively Separation between the arrows and labels in coordinates of *transform*. fontproperties : `matplotlib.font_manager.FontProperties`, optional Font properties for the label text. back_length : float, default: 0.15 Fraction of the arrow behind the arrow crossing. head_width : float, default: 10 Width of arrow head, sent to ArrowStyle. head_length : float, default: 15 Length of arrow head, sent to ArrowStyle. tail_width : float, default: 2 Width of arrow tail, sent to ArrowStyle. text_props, arrow_props : dict Properties of the text and arrows, passed to `.textpath.TextPath` and `.patches.FancyArrowPatch`. **kwargs Keyworded arguments to pass to :class:`matplotlib.offsetbox.AnchoredOffsetbox`. Attributes ---------- arrow_x, arrow_y : `matplotlib.patches.FancyArrowPatch` Arrow x and y text_path_x, text_path_y : `matplotlib.textpath.TextPath` Path for arrow labels p_x, p_y : `matplotlib.patches.PathPatch` Patch for arrow labels box : `matplotlib.offsetbox.AuxTransformBox` Container for the arrows and labels. Notes ----- If *prop* is passed as a keyword argument, but *fontproperties* is not, then *prop* is be assumed to be the intended *fontproperties*. Using both *prop* and *fontproperties* is not supported. Examples -------- >>> import matplotlib.pyplot as plt >>> import numpy as np >>> from mpl_toolkits.axes_grid1.anchored_artists import ( ... AnchoredDirectionArrows) >>> fig, ax = plt.subplots() >>> ax.imshow(np.random.random((10, 10))) >>> arrows = AnchoredDirectionArrows(ax.transAxes, '111', '110') >>> ax.add_artist(arrows) >>> fig.show() Using several of the optional parameters, creating downward pointing arrow and high contrast text labels. >>> import matplotlib.font_manager as fm >>> fontprops = fm.FontProperties(family='monospace') >>> arrows = AnchoredDirectionArrows(ax.transAxes, 'East', 'South', ... loc='lower left', color='k', ... aspect_ratio=-1, sep_x=0.02, ... sep_y=-0.01, ... text_props={'ec':'w', 'fc':'k'}, ... fontproperties=fontprops) """ if arrow_props is None: arrow_props = {} if text_props is None: text_props = {} arrowstyle = ArrowStyle("Simple", head_width=head_width, head_length=head_length, tail_width=tail_width) if fontproperties is None and 'prop' in kwargs: fontproperties = kwargs.pop('prop') if 'color' not in arrow_props: arrow_props['color'] = color if 'alpha' not in arrow_props: arrow_props['alpha'] = alpha if 'color' not in text_props: text_props['color'] = color if 'alpha' not in text_props: text_props['alpha'] = alpha t_start = transform t_end = t_start + transforms.Affine2D().rotate_deg(angle) self.box = AuxTransformBox(t_end) length_x = length length_y = length * aspect_ratio self.arrow_x = FancyArrowPatch((0, back_length * length_y), (length_x, back_length * length_y), arrowstyle=arrowstyle, shrinkA=0.0, shrinkB=0.0, **arrow_props) self.arrow_y = FancyArrowPatch((back_length * length_x, 0), (back_length * length_x, length_y), arrowstyle=arrowstyle, shrinkA=0.0, shrinkB=0.0, **arrow_props) self.box.add_artist(self.arrow_x) self.box.add_artist(self.arrow_y) text_path_x = TextPath( (length_x + sep_x, back_length * length_y + sep_y), label_x, size=fontsize, prop=fontproperties) self.p_x = PathPatch(text_path_x, transform=t_start, **text_props) self.box.add_artist(self.p_x) text_path_y = TextPath((length_x * back_length + sep_x, length_y * (1 - back_length) + sep_y), label_y, size=fontsize, prop=fontproperties) self.p_y = PathPatch(text_path_y, **text_props) self.box.add_artist(self.p_y) super().__init__(loc, pad=pad, borderpad=borderpad, child=self.box, frameon=frameon, **kwargs)
def triplot(ax, *args, **kwargs): """ Draw a unstructured triangular grid as lines and/or markers. The triangulation to plot can be specified in one of two ways; either:: triplot(triangulation, ...) where triangulation is a :class:`~matplotlib.tri.Triangulation` object, or :: triplot(x, y, ...) triplot(x, y, triangles, ...) triplot(x, y, triangles=triangles, ...) triplot(x, y, mask=mask, ...) triplot(x, y, triangles, mask=mask, ...) in which case a Triangulation object will be created. See :class:`~matplotlib.tri.Triangulation` for a explanation of these possibilities. The remaining args and kwargs are the same as for :meth:`~matplotlib.axes.Axes.plot`. **Example:** .. plot:: mpl_examples/pylab_examples/triplot_demo.py """ import matplotlib.axes tri, args, kwargs = Triangulation.get_from_args_and_kwargs(*args, **kwargs) x = tri.x y = tri.y edges = tri.edges # If draw both lines and markers at the same time, e.g. # ax.plot(x[edges].T, y[edges].T, *args, **kwargs) # then the markers are drawn more than once which is incorrect if alpha<1. # Hence draw lines and markers separately. # Decode plot format string, e.g. 'ro-' fmt = '' if len(args) > 0: fmt = args[0] linestyle, marker, color = matplotlib.axes._process_plot_format(fmt) # Draw lines without markers, if lines are required. if linestyle is not None and linestyle is not 'None': kw = kwargs.copy() kw.pop('marker', None) # Ignore marker if set. kw['linestyle'] = ls_mapper[linestyle] kw['edgecolor'] = color kw['facecolor'] = None vertices = np.column_stack((x[edges].flatten(), y[edges].flatten())) codes = ([Path.MOVETO] + [Path.LINETO]) * len(edges) path = Path(vertices, codes) pathpatch = PathPatch(path, **kw) ax.add_patch(pathpatch) # Draw markers without lines. # Should avoid drawing markers for points that are not in any triangle? kwargs['linestyle'] = '' ax.plot(x, y, *args, **kwargs)
def plot_mesh_mpl(nodes, elements, polygons=None, polynomial_orders=None, edges_only=False): from matplotlib import pyplot from matplotlib.path import Path from matplotlib.patches import PathPatch from matplotlib.patches import Rectangle colors_old = { 1: '#000684', 2: '#3250fc', 3: '#36c4ee', 4: '#04eabc', 5: '#62ff2a', 6: '#fdff07', 7: '#ffa044', 8: '#ff1111', 9: '#b02c2c', 10: '#820f97', } colors = { 0: '#7f7f7f', 1: '#7f2aff', 2: '#2a2aff', 3: '#2a7fff', 4: '#00d4aa', 5: '#00aa44', 6: '#abc837', 7: '#ffd42a', 8: '#c87137', 9: '#c83737', 10: '#ff0000', } fig = pyplot.figure() sp = fig.add_subplot(111) for el_id in polygons: x = list(polygons[el_id][:, 0]) y = list(polygons[el_id][:, 1]) x.append(x[0]) y.append(y[0]) vertices = zip(x, y) codes = [Path.MOVETO] + [Path.LINETO]*(len(vertices)-2) + \ [Path.CLOSEPOLY] p = Path(vertices, codes) if edges_only: color = "white" linewidth = 2 else: if polynomial_orders is None: color = colors[0] else: color = colors[polynomial_orders[el_id]] linewidth = 1 patch = PathPatch(p, facecolor=color, lw=linewidth, edgecolor='#000000') sp.add_patch(patch) show_legend = polynomial_orders is not None if show_legend: # Create legend def split_nodes(): x = [] y = [] if isinstance(nodes, dict): _nodes = nodes.items() else: _nodes = enumerate(nodes) for k, pnt in _nodes: x.append(pnt[0]) y.append(pnt[1]) return (x, y) def get_max(what='x'): x, y = split_nodes() if what == 'x': return max(x) else: return max(y) def get_min(what='x'): x, y = split_nodes() if what == 'x': return min(x) else: return min(y) maxX = get_max('x') maxY = get_max('y') minX = get_min('x') minY = get_min('y') dy = (maxY - minY) / 20 dx = (maxX - minX) / 20 y = minY + dy x = maxX + dx ord = polynomial_orders.items() order_list = [] for k,v in ord: order_list.append(v) m = max(order_list) for k,c in colors.items(): if k <= m : p = Rectangle(xy=(x,y), width=dx, height=dy, fill=True, facecolor=c) sp.add_patch(p) sp.text(x + dx + (dx/2), y + (dy/4), str(k)) y += dy else: break sp.text(x, y + (dy/2), str('Orders')) sp.set_title("Mesh") sp.set_aspect("equal") sp.autoscale_view() return sp.figure
def main(butler, visits, fields, fieldRadius, showCCDs=False, aitoff=False, alpha=0.2, byFilter=False, byVisit=False, title="", verbose=False): ra, dec = [], [] filters = {} _visits, visits = visits, [] for v in _visits: try: exp = butler.get("raw", visit=v, ccd=49) except RuntimeError as e: if verbose: print(e, file=sys.stderr) continue ccd = exp.getDetector() xy = ccd.getPixelFromPosition(afwCG.FpPoint(0, 0)) sky = exp.getWcs().pixelToSky(xy) visits.append(v) ra.append(sky[0].asDegrees()) dec.append(sky[1].asDegrees()) filters[v] = exp.getFilter().getName() plt.clf() if aitoff: axes = plt.gcf().add_axes((0.1, 0.1, 0.85, 0.80), projection="aitoff") axes.grid(1) else: axes = plt.gca() axes.set_aspect('equal') ctypes = dict( BIAS="orange", DARK="cyan", ) if byFilter: ctypeFilters = dict( g="green", r="red", r1="orange", i="magenta", z="brown", y="black", nb0921='darkgray', ) else: ctypeKeys = {} colors = list("rgbcmyk") + ["orange", "brown", "orchid" ] # colours for ctypeKeys if aitoff: fieldRadius = np.radians(fieldRadius) dec = np.radians(dec) ra = np.array(ra) ra = np.radians(np.where(ra > 180, ra - 360, ra)) plots, labels = [], [] for v, r, d in zip(visits, ra, dec): field = fields.get(v) if verbose: print("Drawing %s %s \r" % (v, field), end=' ', flush=True) if byFilter: facecolor = ctypes.get(field, ctypeFilters.get(filters[v], "gray")) else: key = v if byVisit else field if key not in ctypeKeys: ctypeKeys[key] = colors[len(ctypeKeys) % len(colors)] facecolor = ctypeKeys[key] circ = Circle(xy=(r, d), radius=fieldRadius, fill=False if showCCDs else True, facecolor=facecolor, alpha=alpha) axes.add_artist(circ) if showCCDs: pathCodes = [ Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY, ] for ccd in butler.queryMetadata("raw", "visit", ["ccd"], visit=v): try: md = butler.get("raw_md", visit=v, ccd=ccd) except RuntimeError as e: if verbose: print(e, file=sys.stderr) continue width, height = md.getScalar("NAXIS1"), md.getScalar("NAXIS2") wcs = afwGeom.makeSkyWcs(md) verts = [] for p in [(0, 0), (width, 0), (width, height), (0, height)]: sky = wcs.pixelToSky(afwGeom.PointD(*p)) verts.append([sky[0].asDegrees(), sky[1].asDegrees()]) verts.append((0, 0)) # dummy axes.add_patch( PathPatch(Path(verts, pathCodes), alpha=alpha, facecolor=facecolor)) if byFilter: key = filters[v] else: key = v if byVisit else field if not labels.count(key): plots.append(Circle((0, 0), facecolor=facecolor)) labels.append(key) plt.legend(plots, labels, loc='best', bbox_to_anchor=(0, 1.02, 1, 0.102)).draggable() if not aitoff: raRange = np.max(ra) - np.min(ra) + 1.2 * fieldRadius decRange = np.max(dec) - np.min(dec) + 1.2 * fieldRadius raRange *= np.cos(np.radians(np.mean(dec))) plt.xlim(0.5 * (np.max(ra) + np.min(ra)) + raRange * np.array((1, -1))) plt.ylim(0.5 * (np.max(dec) + np.min(dec)) + decRange * np.array((-1, 1))) plt.xlabel("ra") plt.ylabel("dec") return plt
def visualize_walks(self, node_idx, edge_index, walks, edge_mask, y=None, threshold=None, **kwargs) -> Tuple[Axes, nx.DiGraph]: r"""Visualizes the subgraph around :attr:`node_idx` given an edge mask :attr:`edge_mask`. Args: node_idx (int): The node id to explain. edge_index (LongTensor): The edge indices. edge_mask (Tensor): The edge mask. y (Tensor, optional): The ground-truth node-prediction labels used as node colorings. (default: :obj:`None`) threshold (float, optional): Sets a threshold for visualizing important edges. If set to :obj:`None`, will visualize all edges with transparancy indicating the importance of edges. (default: :obj:`None`) **kwargs (optional): Additional arguments passed to :func:`nx.draw`. :rtype: :class:`matplotlib.axes.Axes`, :class:`networkx.DiGraph` """ self_loop_edge_index, _ = add_self_loops(edge_index, num_nodes=kwargs.get('num_nodes')) assert edge_mask.size(0) == self_loop_edge_index.size(1) if self.molecule: atomic_num = torch.clone(y) # Only operate on a k-hop subgraph around `node_idx`. subset, edge_index, _, hard_edge_mask = subgraph( node_idx, self.__num_hops__, self_loop_edge_index, relabel_nodes=True, num_nodes=None, flow=self.__flow__()) edge_mask = edge_mask[hard_edge_mask] # --- temp --- edge_mask[edge_mask == float('inf')] = 1 edge_mask[edge_mask == - float('inf')] = 0 # --- if threshold is not None: edge_mask = (edge_mask >= threshold).to(torch.float) if data_args.dataset_name == 'ba_lrp': y = torch.zeros(edge_index.max().item() + 1, device=edge_index.device) if y is None: y = torch.zeros(edge_index.max().item() + 1, device=edge_index.device) else: y = y[subset] if self.molecule: atom_colors = {6: '#8c69c5', 7: '#71bcf0', 8: '#aef5f1', 9: '#bdc499', 15: '#c22f72', 16: '#f3ea19', 17: '#bdc499', 35: '#cc7161'} node_colors = [None for _ in range(y.shape[0])] for y_idx in range(y.shape[0]): node_colors[y_idx] = atom_colors[y[y_idx].int().tolist()] else: atom_colors = {0: '#8c69c5', 1: '#c56973', 2: '#a1c569', 3: '#69c5ba'} node_colors = [None for _ in range(y.shape[0])] for y_idx in range(y.shape[0]): node_colors[y_idx] = atom_colors[y[y_idx].int().tolist()] data = Data(edge_index=edge_index, att=edge_mask, y=y, num_nodes=y.size(0)).to('cpu') G = to_networkx(data, node_attrs=['y'], edge_attrs=['att']) mapping = {k: i for k, i in enumerate(subset.tolist())} G = nx.relabel_nodes(G, mapping) kwargs['with_labels'] = kwargs.get('with_labels') or True kwargs['font_size'] = kwargs.get('font_size') or 8 kwargs['node_size'] = kwargs.get('node_size') or 200 kwargs['cmap'] = kwargs.get('cmap') or 'cool' # calculate Graph positions pos = nx.kamada_kawai_layout(G) ax = plt.gca() for source, target, data in G.edges(data=True): ax.annotate( '', xy=pos[target], xycoords='data', xytext=pos[source], textcoords='data', arrowprops=dict( arrowstyle="-", lw=1.5, alpha=0.5, # alpha control transparency color='grey', # color control color shrinkA=sqrt(kwargs['node_size']) / 2.0, shrinkB=sqrt(kwargs['node_size']) / 2.0, connectionstyle="arc3,rad=0", # rad control angle )) # --- try to draw a walk --- walks_ids = walks['ids'] walks_score = walks['score'] walks_node_list = [] for i in range(walks_ids.shape[1]): if i == 0: walks_node_list.append(self_loop_edge_index[:, walks_ids[:, i].view(-1)].view(2, -1)) else: walks_node_list.append(self_loop_edge_index[1, walks_ids[:, i].view(-1)].view(1, -1)) walks_node_ids = torch.cat(walks_node_list, dim=0).T walks_mask = torch.zeros(walks_node_ids.shape, dtype=bool, device=self.device) for n in G.nodes(): walks_mask = walks_mask | (walks_node_ids == n) walks_mask = walks_mask.sum(1) == walks_node_ids.shape[1] sub_walks_node_ids = walks_node_ids[walks_mask] sub_walks_score = walks_score[walks_mask] for i, walk in enumerate(sub_walks_node_ids): verts = [pos[n.item()] for n in walk] if walk.shape[0] == 3: codes = [Path.MOVETO, Path.CURVE3, Path.CURVE3] else: codes = [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4] path = Path(verts, codes) if sub_walks_score[i] > 0: patch = PathPatch(path, facecolor='none', edgecolor='red', lw=1.5,#e1442a alpha=(sub_walks_score[i] / (sub_walks_score.max() * 2)).item()) else: patch = PathPatch(path, facecolor='none', edgecolor='blue', lw=1.5,#18d66b alpha=(sub_walks_score[i] / (sub_walks_score.min() * 2)).item()) ax.add_patch(patch) nx.draw_networkx_nodes(G, pos, node_color=node_colors, **kwargs) # define node labels if self.molecule: if x_args.nolabel: node_labels = {n: f'{self.table(atomic_num[n].int().item())}' for n in G.nodes()} nx.draw_networkx_labels(G, pos, labels=node_labels, **kwargs) else: node_labels = {n: f'{n}:{self.table(atomic_num[n].int().item())}' for n in G.nodes()} nx.draw_networkx_labels(G, pos, labels=node_labels, **kwargs) else: if not x_args.nolabel: nx.draw_networkx_labels(G, pos, **kwargs) return ax, G
frameon=True, borderpad=0.2) ax.add_artist(ao) # another text from matplotlib.patches import PathPatch if usetex: r = r"\mbox{textpath supports mathtext \& \TeX}" else: r = r"textpath supports mathtext & TeX" text_path = TextPath((0, 0), r, size=20, usetex=usetex) p1 = PathPatch(text_path, ec="w", lw=3, fc="w", alpha=0.9, transform=IdentityTransform()) p2 = PathPatch(text_path, ec="none", fc="k", transform=IdentityTransform()) offsetbox2 = AuxTransformBox(IdentityTransform()) offsetbox2.add_artist(p1) offsetbox2.add_artist(p2) ab = AnnotationBbox(offsetbox2, (0.95, 0.05), xycoords='axes fraction', boxcoords="offset points", box_alignment=(1., 0.), frameon=False) ax.add_artist(ab)
def plot_mapping_data(xv, yv, data, **kwargs): """ xv and yv should have shape [nj,ni,nv], where nv is the number of vertices, and nj and ni are indices to coordinates. If unstructured, nj or ni is probably 1, but if a lat-lon grid nj and ni are probably both > 0. Data should have dimensions nj and ni. NOTE: To avoid artifacts due to antialiasing, you should probably pass antialiaseds=False to **kwargs. Should this be the default? TODO: it would be better to generalize this by collapsing nj and ni. """ from matplotlib import pyplot from matplotlib.path import Path from matplotlib.patches import PathPatch from matplotlib.collections import PatchCollection from cartopy import crs import numpy ax = pyplot.gca() patches = [] colors = [] for i in range(xv.shape[1]): for j in range(xv.shape[0]): # Find vertices for this cell corners = [] xvals = xv.values[j, i, :] yvals = yv.values[j, i, :] # Fix stuff that wraps around; I should NOT have to do this # if I'm using cartopy! if any(xvals < 90) and any(xvals > 270): xvals = numpy.where(xvals < 90, xvals + 360, xvals) if any(yvals < -45) and any(yvals > 45): yvals = numpy.where(yvals < -45, yvals + 90, yvals) for iv in range(xv.shape[-1]): corners.append([xvals[iv], yvals[iv]]) # Add PathPatch for this cell path = Path(corners, closed=False) patch = PathPatch(path, edgecolor='black', facecolor='none') patches.append(patch) # Get data values for this point so we can color later colors.append(data[j, i]) # Create a PatchCollection from our aggregated list of PathPatches p = PatchCollection(patches, facecolor='white', **kwargs) # Color the patches in the collection according to the data values #colors = data.squeeze() p.set_array(colors) #numpy.array(colors)) # Add the collection to the axes ax.add_collection(p) # Set sane axes limits ax.set_xlim([xv.min(), xv.max()]) ax.set_ylim([yv.min(), yv.max()]) # Return collection of patches return p
ax.set_xlim((0, 1)) trans = (fig.dpi_scale_trans + transforms.ScaledTranslation(xdata[0], ydata[0], ax.transData)) # plot an ellipse around the point that is 150 x 130 points in diameter... circle = mpatches.Ellipse((0, 0), 20 / 72, 10 / 72, angle=0, fill=None, transform=trans) ax.add_patch(circle) size = 9 / 72 # ox = self._x # oy = self._y ox = 0 oy = 0 # vertices = [] # codes = [] codes = [Path.MOVETO] + [Path.LINETO] * 2 + [Path.CLOSEPOLY] vertices = [(ox, oy), (ox + size / 2, oy - size * 1.73 / 2), (ox - size / 2, oy - size * 1.73 / 2), (0, 0)] vertices = np.array(vertices, float) path = Path(vertices, codes) trans = (fig.dpi_scale_trans + transforms.ScaledTranslation(xdata[1], ydata[1], ax.transData)) pathpatch = PathPatch(path, facecolor='None', edgecolor='k', transform=trans) ax.add_patch(pathpatch) plt.show()
def draw_labels(fig, ax, out_value, features, feature_type, offset_text, total_effect=0, min_perc=0.05, text_rotation=0): start_text = out_value pre_val = out_value # Define variables specific to positive and negative effect features if feature_type == 'positive': colors = ['#FF0D57', '#FFC3D5'] alignement = 'right' sign = 1 else: colors = ['#1E88E5', '#D1E6FA'] alignement = 'left' sign = -1 # Draw initial line if feature_type == 'positive': x, y = np.array([[pre_val, pre_val], [0, -0.18]]) line = lines.Line2D(x, y, lw=1., alpha=0.5, color=colors[0]) line.set_clip_on(False) ax.add_line(line) start_text = pre_val box_end = out_value val = out_value for feature in features: # Exclude all labels that do not contribute at least 10% to the total feature_contribution = np.abs(float(feature[0]) - pre_val) / np.abs(total_effect) if feature_contribution < min_perc: break # Compute value for current feature val = float(feature[0]) # Draw labels. if feature[1] == "": text = feature[2] else: text = feature[2] + ' = ' + np.round(feature[1], 3) if text_rotation is not 0: va_alignment = 'top' else: va_alignment = 'baseline' text_out_val = plt.text(start_text - sign * offset_text, -0.15, text, fontsize=12, color=colors[0], horizontalalignment=alignement, va=va_alignment, rotation=text_rotation) text_out_val.set_bbox(dict(facecolor='none', edgecolor='none')) # We need to draw the plot to be able to get the size of the # text box fig.canvas.draw() box_size = text_out_val.get_bbox_patch().get_extents()\ .transformed(ax.transData.inverted()) if feature_type == 'positive': box_end_ = box_size.get_points()[0][0] else: box_end_ = box_size.get_points()[1][0] # If the feature goes over the side of the plot, we remove that label # and stop drawing labels if box_end_ > ax.get_xlim()[1]: text_out_val.remove() break # Create end line if (sign * box_end_) > (sign * val): x, y = np.array([[val, val], [0, -0.18]]) line = lines.Line2D(x, y, lw=1., alpha=0.5, color=colors[0]) line.set_clip_on(False) ax.add_line(line) start_text = val box_end = val else: box_end = box_end_ - sign * offset_text x, y = np.array([[val, box_end, box_end], [0, -0.08, -0.18]]) line = lines.Line2D(x, y, lw=1., alpha=0.5, color=colors[0]) line.set_clip_on(False) ax.add_line(line) start_text = box_end # Update previous value pre_val = float(feature[0]) # Create line for labels extent_shading = [out_value, box_end, 0, -0.31] path = [[out_value, 0], [pre_val, 0], [box_end, -0.08], [box_end, -0.2], [out_value, -0.2], [out_value, 0]] path = Path(path) patch = PathPatch(path, facecolor='none', edgecolor='none') ax.add_patch(patch) # Extend axis if needed lower_lim, upper_lim = ax.get_xlim() if (box_end < lower_lim): ax.set_xlim(box_end, upper_lim) if (box_end > upper_lim): ax.set_xlim(lower_lim, box_end) # Create shading if feature_type == 'positive': colors = np.array([(255, 13, 87), (255, 255, 255)]) / 255. else: colors = np.array([(30, 136, 229), (255, 255, 255)]) / 255. cm = matplotlib.colors.LinearSegmentedColormap.from_list('cm', colors) _, Z2 = np.meshgrid(np.linspace(0, 10), np.linspace(-10, 10)) im = plt.imshow(Z2, interpolation='quadric', cmap=cm, vmax=0.01, alpha=0.3, origin='lower', extent=extent_shading, clip_path=patch, clip_on=True, aspect='auto') im.set_clip_path(patch) return fig, ax
ax_d = draw_significance(intra_class_inter_cell_conductance, inter_class_inter_cell_conductance, p_less_inter / num_comparisons, ax_d, height_offset=.05) ax_d.grid(False) sns.despine(ax=ax_d) fig_d.savefig('figures/%s_dist_comp.pdf' % line, bbox_inches='tight') plt.close(fig_d) ax.add_patch( PathPatch(Path([[current_idx, current_idx], [current_idx + line_hof_models, current_idx], [ current_idx + line_hof_models, current_idx + line_hof_models ], [current_idx, current_idx]]), facecolor="none", edgecolor='k', linewidth=2)) current_idx += line_hof_models line_idx += num_line_cells current_idx = 0 for _ in range(num_all_cells): ax.add_patch( PathPatch(Path([[current_idx, current_idx], [current_idx + hof_num, current_idx], [current_idx + hof_num, current_idx + hof_num], [current_idx, current_idx]]), facecolor="none",
def partimatrix(alignment, display=False, samples=0, s_limit=0, title="", include_incomplete=False, print_stats=True, max_site_labels=50): if print_stats: print "%s sequences in %s bp alignment" % ( alignment.getNumSeqs(), len(alignment)) (sites, columns, partitions) = binary_partitions(alignment) if print_stats: print "%s unique binary partitions from %s informative sites" % ( len(partitions), len(sites)) partpart = min_edges(partitions) # [partition,partition] partimatrix = partpart[columns,:] # [site, partition] sitematrix = partimatrix[:,columns] # [site, site] # RETICULATE, JE 1996 compatiblity = sitematrix <= 2 if print_stats: print "Overall compatibility %.6f" % intra_region_average(compatiblity) if samples == 0: print "Neighbour similarity score = %.6f" % \ neighbour_similarity_score(compatiblity) else: print "Neighbour similarity = %.6f, avg random = %.6f, p < %s" % \ nss_significance(compatiblity, samples=samples) # PARTIMATRIX, JWE 1997 # Remove the incomplete partitions with gaps or other ambiguities mask = 2**alignment.getNumSeqs()-1 complete = [i for (i,(x, xz)) in enumerate(partitions) if xz==mask] if not include_incomplete: partimatrix = partimatrix[:,complete] partitions = [partitions[i] for i in complete] # For scoring/ordering purposes, also remove the incomplete sequences complete_columns = [i for (i,c) in enumerate(columns) if c in complete] scoreable_partimatrix = partimatrix[complete_columns, :] # Order partitions by increasing conflict score conflict = (scoreable_partimatrix > 2).sum(axis=0) conflict_order = numpy.argsort(conflict) partimatrix = partimatrix[:, conflict_order] partitions = [partitions[i] for i in conflict_order] scoreable_partimatrix = partimatrix[complete_columns, :] support = (scoreable_partimatrix == 0).sum(axis=0) consist = (scoreable_partimatrix <= 2).sum(axis=0) conflict = (scoreable_partimatrix > 2).sum(axis=0) # Similarity measure between partitions O = boolean_similarity(scoreable_partimatrix <= 2) s = 1.0*len(complete_columns) O = O.astype(float) / s p,q = consist/s, conflict/s E = numpy.outer(p,p) + numpy.outer(q,q) S = (O-E)/numpy.sqrt(E*(1-E)/s) # Order partitions for better visual grouping if "order_by_conflict": order = order_tied_to_cluster_similar(S, conflict) else: order = order_to_cluster_similar(S) half = len(order) // 2 if sum(conflict[order[:half]]) > sum(conflict[order[half:]]): order.reverse() partimatrix = partimatrix[:, order] conflict = conflict[order] support = support[order] partitions = [partitions[i] for i in order] if display: figwidth = 8.0 (c_size, p_size) = partimatrix.shape s_size = num_seqs = alignment.getNumSeqs() # Layout (including figure height) chosen to get aspect ratio of # 1.0 for the compatibility matrix, and if possible the other # matrices. if s_size > s_limit: # too many species to show s_size = 0 else: # distort squares to give enough space for species names extra = max(1.0, (12/80)/(figwidth/(c_size + p_size))) p_size *= numpy.sqrt(extra) s_size *= extra genemap = Display(alignment, recursive=s_size>0, colour_sequences=False, draw_bases=False) annot_width = max(genemap.height / 80, 0.1) figwidth = max(figwidth, figwidth/2 + annot_width) bar_height = 0.5 link_width = 0.3 x_margin = 0.60 y_margin = 0.35 xpad = 0.05 ypad = 0.2 (x, y) = (c_size + p_size, c_size + s_size) x_scale = y_scale = (figwidth-2*x_margin-xpad-link_width-annot_width)/x figheight = y_scale * y + 2*y_margin + 2*ypad + bar_height x_scale /= figwidth y_scale /= figheight x_margin /= figwidth y_margin /= figheight xpad /= figwidth ypad /= figheight bar_height /= figheight link_width /= figwidth annot_width /= figwidth (c_width, c_height) = (c_size*x_scale, c_size*y_scale) (p_width, s_height) = (p_size*x_scale, s_size*y_scale) vert = (x_margin + xpad + c_width) top = (y_margin + c_height + ypad) fig = plt.figure(figsize=(figwidth,figheight)) kw = dict(axisbg=fig.get_facecolor()) axC = fig.add_axes([x_margin, y_margin, c_width, c_height], **kw) axP = fig.add_axes([vert, y_margin, p_width, c_height], sharey=axC, **kw) axS = fig.add_axes([vert, top, p_width, s_height or .001], sharex=axP, **kw) axB = fig.add_axes([vert, top+ypad+s_height, p_width, bar_height], sharex=axP, **kw) axZ = fig.add_axes([vert+p_width, y_margin, link_width, c_height], frameon=False) axA = genemap.asAxes( fig, [vert+p_width+link_width, y_margin, annot_width, c_height], vertical=True, labeled=True) axP.yaxis.set_visible(False) #for ax in [axC, axP, axS]: #ax.set_aspect(adjustable='box', aspect='equal') fig.text(x_margin+c_width/2, .995, title, ha='center', va='top') if not s_size: axS.set_visible(False) # No ticks for these non-float dimensions for axes in [axB, axC, axS, axP]: for axis in [axes.xaxis, axes.yaxis]: for tick in axis.get_major_ticks(): tick.gridOn = False tick.tick1On = False tick.tick2On = False tick.label1.set_size(8) tick.label2.set_size(8) if axis is axes.xaxis: tick.label1.set_rotation('vertical') # Partition dimension for axis in [axS.xaxis, axP.xaxis, axB.xaxis, axB.yaxis]: axis.set_major_formatter(matplotlib.ticker.NullFormatter()) axis.set_minor_formatter(matplotlib.ticker.NullFormatter()) # Site dimension if c_size > max_site_labels: for axis in [axC.yaxis, axC.xaxis]: axis.set_visible(False) else: isl = integer_tick_label(sites) for axis in [axC.yaxis, axC.xaxis]: axis.set_minor_locator(matplotlib.ticker.IndexLocator(1,0)) axis.set_minor_formatter(matplotlib.ticker.NullFormatter()) axis.set_major_locator(matplotlib.ticker.IndexLocator(1,0.5)) axis.set_major_formatter(matplotlib.ticker.FuncFormatter(isl)) # Species dimension if s_size: seq_names = [name.split(' ')[0] for name in alignment.getSeqNames()] axS.yaxis.set_minor_locator(matplotlib.ticker.IndexLocator(1,0)) axS.yaxis.set_minor_formatter(matplotlib.ticker.NullFormatter()) axS.yaxis.set_major_locator(matplotlib.ticker.IndexLocator(1,0.5)) axS.yaxis.set_major_formatter(matplotlib.ticker.FixedFormatter(seq_names)) #axS.yaxis.grid(False) #, 'minor') # Display the main matrices: compatibility and partimatrix axC.pcolorfast(compatiblity, cmap=plt.cm.gray) partishow = partimatrix <= 2 axP.pcolorfast(partishow, cmap=plt.cm.gray) axP.set_autoscale_on(False) axC.plot([0,c_size], [0, c_size], color='lightgreen') (sx, sy) = numpy.nonzero(partimatrix.T==0) axP.scatter(sx+0.5, sy+0.5, color='lightgreen', marker='^', s=15) # Make [partition, sequence] matrix # Not a good idea with too many sequences if s_size: partseq1 = numpy.empty([len(partitions), num_seqs], bool) partseq2 = numpy.empty([len(partitions), num_seqs], bool) for (i, (x, xz)) in enumerate(partitions): partseq1[i] = bit_decode(x, num_seqs) partseq2[i] = bit_decode(xz^x, num_seqs) # Order sequqnces so as to place similar sequences adjacent O = boolean_similarity(partseq1) order = order_to_cluster_similar(O) partseq1 = partseq1[:,order] partseq2 = partseq2[:,order] seq_names = [seq_names[i] for i in order] axS.set_ylim(0, len(seq_names)) axS.set_autoscale_on(False) for (halfpart,color) in [(partseq1, 'red'),(partseq2, 'blue')]: (sx, sy) = numpy.nonzero(halfpart) axS.scatter(sx+0.5, sy+0.5, color=color, marker='o') axS.grid(False) #axS.yaxis.tick_right() #axS.yaxis.set_label_position('right') # Bar chart of partition support and conflict scores #axB.set_autoscalex_on(False) if conflict.sum(): axB.bar(numpy.arange(len(partitions)), -conflict/conflict.sum(), 1.0, color='black', align='edge') if support.sum(): axB.bar(numpy.arange(len(partitions)), +support/support.sum(), 1.0, color='lightgreen', align='edge') axB.set_xlim(0.0, len(partitions)) # Alignment features axA.set_ylim(0, len(alignment)) axA.set_autoscale_on(False) axA.yaxis.set_major_formatter( matplotlib.ticker.FuncFormatter(lambda y,pos:str(int(y)))) axA.yaxis.tick_right() axA.yaxis.set_label_position('right') axA.xaxis.tick_top() axA.xaxis.set_label_position('top') #axA.xaxis.set_visible(False) # "Zoom lines" linking informative-site coords to alignment coords from matplotlib.patches import PathPatch from matplotlib.path import Path axZ.set_xlim(0.0,1.0) axZ.set_xticks([]) axZ.set_ylim(0, len(alignment)) axZ.set_yticks([]) zoom = len(alignment) / len(sites) vertices = [] for (i,p) in enumerate(sites): vertices.extend([(.1, (i+0.5)*zoom), (.9,p+0.5)]) axA.axhspan(p, p+1, facecolor='green', edgecolor='green', alpha=0.3) ops = [Path.MOVETO, Path.LINETO] * (len(vertices)//2) path = Path(vertices, ops) axZ.add_patch(PathPatch(path, fill=False, linewidth=0.25)) # interactive navigation messes up axZ. Could use callbacks but # probably not worth the extra complexity. for ax in [axC, axP, axS, axB, axZ, axA]: ax.set_navigate(False) return fig
def contour_shp_clip(originfig, ax, m=None, shpfile=None, region_index=3, region_name=None): """ Mask out the unnecessary data outside the interest region on a Matplotlib-plotted output instance. http://bbs.06climate.com/forum.php?mod=viewthread&tid=42437&extra=page%3D1 :param originfig: the Matplotlib contour plot instance :param ax: the Axes instance :param m: basemap instance, m=Basemap(...) :param shpfile: the shape file used for basemap :param region_index: the record index of region name. If don't know the region index, can explore with: sf = shapefile.Reader(shpfile) print(sf.shapeRecords()[0].record) :param region_name: the name of a region of on the basemap, outside the region the data is to be maskout :return: clip, the the masked-out or clipped matplotlib instance """ # get shape file if shpfile is None: shpfile = pkg_resources.resource_filename( 'nmc_met_graphics', "resources\\maps\\country1.shp") # get region name if region_name is None: region_name = ["China"] # check shape file if not os.path.isfile(shpfile): return None # read shape file data sf = shapefile.Reader(shpfile) # define vertices and codes vertices = [] codes = [] # loop every records for shape_rec in sf.shapeRecords(): if shape_rec.record[region_index] in region_name: pts = shape_rec.shape.points prt = list(shape_rec.shape.parts) + [len(pts)] for i in range(len(prt) - 1): for j in range(prt[i], prt[i + 1]): if m is not None: vertices.append(m(pts[j][0], pts[j][1])) else: vertices.append((pts[j][0], pts[j][1])) codes += [Path.MOVETO] codes += [Path.LINETO] * (prt[i + 1] - prt[i] - 2) codes += [Path.CLOSEPOLY] clip = Path(vertices, codes) clip = PathPatch(clip, transform=ax.transData) # clip contour for contour in originfig.collections: contour.set_clip_path(clip) return clip
cMap.to_rgba(i))) else: plt.gca().add_patch(getPositions(poses[index, :], linkLength)) return ln, def makeMovie(fname, env, poses, linkLength): ani = animation.FuncAnimation(plt.gcf(), drawPose, \ fargs=(env, poses, linkLength), frames=poses.shape[0], \ blit=True) ani.save(fname, bitrate=300, fps=20) if __name__ == '__main__': if len(argv) < 2: print('Usage: %s num_links [movie]' % argv[0]) exit(1) dims = int(argv[1]) coords = np.loadtxt('environment_%d.dat' % dims) env = PathPatch(Path(coords), facecolor='none', edgecolor='black') poses = np.loadtxt('kinematic_path_%d.dat' % dims) linkLength = 1. / dims if len(argv) > 2: makeMovie('kinematic_%d.mp4' % dims, env, poses, linkLength) else: drawPose(-1, env, poses, linkLength) fig = plt.gcf() fig.savefig('kinematic_%d.pdf' % dims)
def _protein_letter_at(letter, x, y, yscale=1, ax=None, color='black', alpha=1.0): #fp = FontProperties(family="Arial", weight="bold") #fp = FontProperties(family="Ubuntu", weight="bold") fp = FontProperties(family="DejaVu Sans", weight="bold") globscale = 1.35 LETTERS = {"T" : TextPath((-0.305, 0), "T", size=1, prop=fp), "G" : TextPath((-0.384, 0), "G", size=1, prop=fp), "A" : TextPath((-0.35, 0), "A", size=1, prop=fp), "C" : TextPath((-0.366, 0), "C", size=1, prop=fp), "L" : TextPath((-0.35, 0), "L", size=1, prop=fp), "M" : TextPath((-0.35, 0), "M", size=1, prop=fp), "F" : TextPath((-0.35, 0), "F", size=1, prop=fp), "W" : TextPath((-0.35, 0), "W", size=1, prop=fp), "K" : TextPath((-0.35, 0), "K", size=1, prop=fp), "Q" : TextPath((-0.35, 0), "Q", size=1, prop=fp), "E" : TextPath((-0.35, 0), "E", size=1, prop=fp), "S" : TextPath((-0.35, 0), "S", size=1, prop=fp), "P" : TextPath((-0.35, 0), "P", size=1, prop=fp), "V" : TextPath((-0.35, 0), "V", size=1, prop=fp), "I" : TextPath((-0.35, 0), "I", size=1, prop=fp), "Y" : TextPath((-0.35, 0), "Y", size=1, prop=fp), "H" : TextPath((-0.35, 0), "H", size=1, prop=fp), "R" : TextPath((-0.35, 0), "R", size=1, prop=fp), "N" : TextPath((-0.35, 0), "N", size=1, prop=fp), "D" : TextPath((-0.35, 0), "D", size=1, prop=fp), "U" : TextPath((-0.35, 0), "U", size=1, prop=fp), "!" : TextPath((-0.35, 0), "!", size=1, prop=fp), "UP" : TextPath((-0.488, 0), '$\\Uparrow$', size=1, prop=fp), "DN" : TextPath((-0.488, 0), '$\\Downarrow$', size=1, prop=fp), "(" : TextPath((-0.25, 0), "(", size=1, prop=fp), "." : TextPath((-0.125, 0), "-", size=1, prop=fp), ")" : TextPath((-0.1, 0), ")", size=1, prop=fp)} if letter in LETTERS : text = LETTERS[letter] else : text = TextPath((-0.35, 0), letter, size=1, prop=fp) chosen_color = color if chosen_color is None : chosen_color = 'black' if letter in ['A', 'I', 'L', 'M', 'F', 'W', 'V'] : #Hydrophobic chosen_color = 'blue' elif letter in ['K' ,'R'] : #Positive charge chosen_color = 'red' elif letter in ['E', 'D'] : #Negative charge chosen_color = 'magenta' elif letter in ['N', 'Q', 'S', 'T'] : #Polar chosen_color = 'green' elif letter in ['C'] : #Cysteines chosen_color = 'pink' elif letter in ['G'] : #Glycines chosen_color = 'orange' elif letter in ['P'] : #Prolines chosen_color = 'yellow' elif letter in ['H', 'Y'] : #Aromatic chosen_color = 'cyan' t = mpl.transforms.Affine2D().scale(1*globscale, yscale*globscale) + \ mpl.transforms.Affine2D().translate(x,y) + ax.transData p = PathPatch(text, lw=0, fc=chosen_color, alpha=alpha, transform=t) if ax != None: ax.add_artist(p) return p
plons.append(plons[0]) plats = list(latInt.ev(x1, y1)) plats.append(plats[0]) ax.plot(plons, plats, marker="X", color=colors[-7]) #anim = FuncAnimation(fig, animate, circle.advect(0, tend, .3), save_count=24*5, fargs=(ax, lonrs, latrs, u[1], v[1], lonInt, latInt)) #anim.save("5dcontourPatchG.gif", PillowWriter(10)) circle.advect(0, tend, .3) pxl = [p.trajx[-1] for p in circle.particles] pyl = [p.trajy[-1] for p in circle.particles] plons = lonInt.ev(pxl, pyl) plats = latInt.ev(pxl, pyl) pathVs = np.asarray([plons, plats]) pathVs = pathVs.T pp = Path(pathVs, closed=True) patch = PathPatch(pp, color=colors[0], edgecolor=None) ax.add_artist(patch) contourDS = xr.Dataset(data_vars={ "T0": (["var", "p0"], [x1, y1]), "TF": (["var", "pf"], [pxl, pyl]) }, coords={"var": ["x", "y"]}) contourDS.to_netcdf( "geostrophic_contour.nc", format="NETCDF4") #save 1 contour for later calculations mprof.add("contours") mprof.show()
def create_windowed_descriptors_tachogram(gs1, row_number, timing, des1, max_idx, sym_indexes, start_hour=None, stop_hour=None, sym_color="brown", asym_color="green"): first_lw = 0.5 lws = np.linspace(first_lw, 4, max_idx + 1 + first_lw)[::-1] max_lws = max(lws) lws = [max_lws] * len(lws) only_2_hours = is_only_2_hours(start_hour, stop_hour) asym_indexes = [idx for idx in range(max_idx) if idx not in sym_indexes] max_timing = np.max(timing) des1_max = np.max(des1) des1_min = np.min(des1) # RIGHT TACHOGRAM START ax_windowed_desc = plt.subplot(gs1[row_number, 0]) ax_windowed_desc.set_color_cycle(['blue', 'red']) ax_windowed_desc.plot(timing, des1) ax_windowed_desc.ticklabel_format(style='sci', axis='x', scilimits=(0, max_timing)) ax_windowed_desc.xaxis.set_ticks(np.arange(0, int(max_timing)+1, 1)) ax_windowed_desc.xaxis.set_ticks_position('top') ax_windowed_desc.xaxis.set_label_position('top') ax_windowed_desc.set_xlim(0, max_timing) font_1 = font_0.copy() font_1.set_size('11') font_1.set_weight('bold') if start_hour == None: x_label = u"Czas [godziny]" else: x_label = u"Czas [minuty]" ax_windowed_desc.set_xlabel(x_label, fontproperties=font_1) ax_windowed_desc.set_ylabel(u"Wartość [ms]", fontproperties=font_1) font_1 = font_0.copy() font_1.set_size('18') font_1.set_weight('bold') if start_hour == None: tach_label = u"Tachogram - 24 godziny" tachogram_label_pos = 19 else: tach_label = u"Tachogram - fragment 2 godziny" tachogram_label_pos = 17 y_lim = ax_windowed_desc.get_ylim()[1] ax_windowed_desc.text(tachogram_label_pos, y_lim - 100, tach_label, fontproperties=font_1) for idx, lw in zip(range(max_idx - 1, -1, -1), lws): # if idx % window_step == 1: if not (idx % window_step == 0): continue vertices = [] codes = [] codes = [Path.MOVETO] + [Path.LINETO] * 3 + [Path.CLOSEPOLY] vertices = [(idx, des1_max - des1_max / 10), (idx + window_step, des1_max - des1_max / 10), (idx + window_step, des1_min + des1_max / 10), (idx, des1_min + des1_max / 10), (0, 0)] vertices = np.array(vertices, float) path = Path(vertices, codes) pathpatch = PathPatch(path, facecolor='None', edgecolor='red', zorder=3, lw=lw) pathpatch.set_fill(False) ax_windowed_desc.add_patch(pathpatch) min_y = 50 max_y = 400 zero_ones = [("0" if idx in sym_indexes else "A") for idx in range(max_idx)] zero_one_y = des1_min - 50 alignment = {'horizontalalignment': 'center', 'verticalalignment': 'center'} # zero_one_font_size = 20 font_1 = font_0.copy() font_1.set_size('20') font_1.set_weight('bold') for idx, lw in zip(range(max_idx - 1, -1, -1), lws): if not (idx % window_step == 0): continue codes = [Path.MOVETO] + [Path.LINETO] * 3 + [Path.CLOSEPOLY] vertices = [(idx, max_y), (idx + window_step, max_y), (idx + window_step, min_y), (idx, min_y), (0, 0)] vertices = np.array(vertices, float) path = Path(vertices, codes) pathpatch = PathPatch(path, facecolor='None', edgecolor='black', zorder=3, lw=0) pathpatch.set_fill(False) ax_windowed_desc.text(idx+window_step/2.0, zero_one_y, u"%s" % (zero_ones[idx]), # size=zero_one_font_size, color=asym_color if idx in asym_indexes else sym_color, fontproperties=font_1, **alignment) ax_windowed_desc.add_patch(pathpatch) leg = ax_windowed_desc.legend(['$\mathbf{%s}$' % ("RR"), "Okno danych - 5 minut"], loc='upper left', numpoints=5) ax_windowed_desc.add_artist(leg) # change legend font properties plt.setp(leg.get_texts(), fontsize='large') plt.setp(leg.get_texts(), fontweight='bold') lines = [3] * Line2D(range(1), range(1), linestyle='None', marker='None', color="blue") labels = ['G: - godzina', 'M: - minuta', 'S: - sekunda'] leg = ax_windowed_desc.legend([lines], [labels], loc='upper right') plt.setp(leg.get_texts(), fontsize='large') plt.setp(leg.get_texts(), fontweight='bold') ax_windowed_desc.add_artist(leg) if not start_hour == None: change_ticks_for_5_minutes(ax_windowed_desc) bold_ticks_labels(ax_windowed_desc) if only_2_hours == True: change_xtickslabels_2_hours(ax_windowed_desc) return row_number + 1
def plot_tree(self, root, **kwargs): pyplot.ioff() self.root = root self.leaves = root.leaves() self.nleaves = len(self.leaves) self.leaf_hsep = 1.0/float(self.nleaves) if "branchlabels" in kwargs: self.branchlabels = kwargs["branchlabels"] if "leaflabels" in kwargs: self.leaflabels = kwargs["leaflabels"] for n in root.descendants(): if n.length is None: self.scaled=False; break n2c = layout.cartesian(root, scaled=self.scaled) self.n2c = n2c sv = sorted([ [c.y, c.x, n] for n, c in n2c.items() ]) self.coords = sv#numpy.array(sv) self.yaxis.set_visible(False) M = Path.MOVETO; L = Path.LINETO; S = Path.STOP verts = [] codes = [] self.node2label = {} for node, coords in n2c.items(): x = coords.x; y = coords.y if node.parent: pcoords = n2c[node.parent] px = pcoords.x; py = pcoords.y verts.append((x, y)); codes.append(M) verts.append((px, y)); codes.append(L) verts.append((px, py)); codes.append(L) if node.isleaf and node.label and self.leaflabels: txt = self.annotate( node.label, xy=(x, y), xytext=(self.leaf_offset, 0), textcoords="offset points", verticalalignment=self.leaf_valign, horizontalalignment=self.leaf_halign, fontsize=self.leaf_fontsize, clip_on=True, picker=True ) txt.set_visible(False) self.node2label[node] = txt if (not node.isleaf) and node.label and self.branchlabels: txt = self.annotate( node.label, xy=(x, y), xytext=(self.branch_offset,0), textcoords="offset points", verticalalignment=self.branch_valign, horizontalalignment=self.branch_halign, fontsize=self.branch_fontsize, bbox=dict(fc="lightyellow", ec="none", alpha=0.8), clip_on=True, picker=True ) ## txt.set_visible(False) self.node2label[node] = txt px, py = verts[-1] verts.append((px, py)); codes.append(M) verts.append((px, py)); codes.append(S) self.branchpath = Path(verts, codes) self.branchpatch = PathPatch(self.branchpath, fill=False) self.add_patch(self.branchpatch) self.highlight_support() self.mark_named() self.home() self.set_name(self.name) pyplot.ion() return self
def make_patch_list(writer): try: from matplotlib.path import Path except ImportError: Path = None from matplotlib.patches import Circle, Polygon, Wedge else: from matplotlib.patches import Circle, PathPatch, Wedge indices = writer.positions[:, 2].argsort() patch_list = [] for a in indices: xy = writer.positions[a, :2] if a < writer.natoms: r = writer.d[a] / 2 if writer.frac_occ: site_occ = writer.occs[writer.tags[a]] # first an empty circle if a site is not fully occupied if (np.sum([v for v in site_occ.values()])) < 1.0: # fill with white fill = '#ffffff' patch = Circle(xy, r, facecolor=fill, edgecolor='black') patch_list.append(patch) start = 0 # start with the dominant species for sym, occ in sorted(site_occ.items(), key=lambda x: x[1], reverse=True): if np.round(occ, decimals=4) == 1.0: patch = Circle(xy, r, facecolor=writer.colors[a], edgecolor='black') patch_list.append(patch) else: # jmol colors for the moment extent = 360. * occ patch = Wedge( xy, r, start, start + extent, facecolor=jmol_colors[atomic_numbers[sym]], edgecolor='black') patch_list.append(patch) start += extent else: if ((xy[1] + r > 0) and (xy[1] - r < writer.h) and (xy[0] + r > 0) and (xy[0] - r < writer.w)): patch = Circle(xy, r, facecolor=writer.colors[a], edgecolor='black') patch_list.append(patch) else: a -= writer.natoms c = writer.T[a] if c != -1: hxy = writer.D[c] if Path is None: patch = Polygon((xy + hxy, xy - hxy)) else: patch = PathPatch(Path((xy + hxy, xy - hxy))) patch_list.append(patch) return patch_list
fig2 = plt.figure("ring_patch()") axre = fig2.add_subplot(111) axre.set_xlim(-1, 1) axre.set_ylim(-1, 1) # plot random grid of background points to highlight alpha xx = np.random.random(100) yy = np.random.random(100) plt.scatter(xx, yy) for r in np.arange(0, 1, 0.1): path = ring_patch(r, r + 0.1, i_test, phi_test) newp = PathPatch(path, color='red', alpha=r, ec='none') axre.add_patch(newp) # test converting ring angles to ring tilt print ring_tilt(i_test, phi_test) # test fig = plt.figure("make_star_limbd()") import matplotlib.gridspec as gridspec gs = gridspec.GridSpec(2, 2) (ax) = plt.subplot(gs[0, 0]) ax2 = plt.subplot(gs[1, 0]) ax3 = plt.subplot(gs[0, 1]) ax4 = plt.subplot(gs[1, 1]) fig.add_subplot(ax) fig.add_subplot(ax2)
def plot_unstructured(xv, yv, data, antialiased=False, **kwargs): """ Plot unstructured data. xv and yv specify the x and y coordinates of the vertices of each cell and should have shape [ni,nv] where ni is the size of the grid (number of cells) and nv is the number of vertices for each cell. Data contains the values of the data you want to plot, and should have dimension [ni,]. The intent with this function is that you will need to read in an auxillary SCRIP-format file that describes the grid (unless this information is present in the same file that contains the data; unlikely) as well as the file that contains the data, and grab the cell corner information from the SCRIP file and the data from the data file. This function will then plot the data on the native grid by looping over each cell and drawing patches for each. Note that this will probably be really slow for big grids! Seems to work alright up to about ne120 or so, but really some more clever techniques should probably be used here (parallelism?). NOTE: To avoid artifacts due to antialiasing, you should probably pass antialiaseds=False to **kwargs. """ patches = [] colors = [] for i in range(xv.shape[0]): # Find vertices for this cell (as [x, y] pairs) corners = [] xvals = xv.values[i, :] yvals = yv.values[i, :] # Fix stuff that wraps around; I should NOT have to do this # if I'm using cartopy! if any(xvals < 90) and any(xvals > 270): xvals = numpy.where(xvals < 90, xvals + 360, xvals) if any(yvals < -45) and any(yvals > 45): yvals = numpy.where(yvals < -45, yvals + 90, yvals) # Loop over corners for iv in range(xv.shape[1]): corners.append([xvals[iv], yvals[iv]]) # Add PathPatch for this cell path = Path(corners, closed=False) patch = PathPatch(path) patches.append(patch) colors.append(data.values[i]) # Create a PatchCollection from our aggregated list of PathPatches p = PatchCollection(patches, antialiaseds=antialiased, **kwargs) # Color the patches in the collection according to the data values #colors = data.squeeze() p.set_array(numpy.array(colors)) # Add the collection to the axes ax = pyplot.gca() ax.add_collection(p) # Set sane axes limits ax.set_xlim([xv.min(), xv.max()]) ax.set_ylim([yv.min(), yv.max()]) # Return collection of patches return p
class AxisArtist(martist.Artist): """ An artist which draws axis (a line along which the n-th axes coord is constant) line, ticks, ticklabels, and axis label. """ ZORDER = 2.5 @property def LABELPAD(self): return self.label.get_pad() @LABELPAD.setter def LABELPAD(self, v): self.label.set_pad(v) def __init__(self, axes, helper, offset=None, axis_direction="bottom", **kwargs): """ Parameters ---------- axes : `mpl_toolkits.axisartist.axislines.Axes` helper : `~mpl_toolkits.axisartist.axislines.AxisArtistHelper` """ #axes is also used to follow the axis attribute (tick color, etc). super().__init__(**kwargs) self.axes = axes self._axis_artist_helper = helper if offset is None: offset = (0, 0) self.offset_transform = ScaledTranslation( *offset, Affine2D().scale(1 / 72) # points to inches. + self.axes.figure.dpi_scale_trans) if axis_direction in ["left", "right"]: axis_name = "ytick" self.axis = axes.yaxis else: axis_name = "xtick" self.axis = axes.xaxis self._axisline_style = None self._axis_direction = axis_direction self._init_line() self._init_ticks(axis_name, **kwargs) self._init_offsetText(axis_direction) self._init_label() self.set_zorder(self.ZORDER) self._rotate_label_along_line = False # axis direction self._tick_add_angle = 180. self._ticklabel_add_angle = 0. self._axislabel_add_angle = 0. self.set_axis_direction(axis_direction) @cbook.deprecated("3.3") @property def dpi_transform(self): return Affine2D().scale(1 / 72) + self.axes.figure.dpi_scale_trans # axis direction def set_axis_direction(self, axis_direction): """ Adjust the direction, text angle, text alignment of ticklabels, labels following the matplotlib convention for the rectangle axes. The *axis_direction* must be one of [left, right, bottom, top]. ===================== ========== ========= ========== ========== property left bottom right top ===================== ========== ========= ========== ========== ticklabels location "-" "+" "+" "-" axislabel location "-" "+" "+" "-" ticklabels angle 90 0 -90 180 ticklabel va center baseline center baseline ticklabel ha right center right center axislabel angle 180 0 0 180 axislabel va center top center bottom axislabel ha right center right center ===================== ========== ========= ========== ========== Note that the direction "+" and "-" are relative to the direction of the increasing coordinate. Also, the text angles are actually relative to (90 + angle of the direction to the ticklabel), which gives 0 for bottom axis. """ self.major_ticklabels.set_axis_direction(axis_direction) self.label.set_axis_direction(axis_direction) self._axis_direction = axis_direction if axis_direction in ["left", "top"]: self.set_ticklabel_direction("-") self.set_axislabel_direction("-") else: self.set_ticklabel_direction("+") self.set_axislabel_direction("+") def set_ticklabel_direction(self, tick_direction): r""" Adjust the direction of the ticklabel. Note that the *label_direction*\s '+' and '-' are relative to the direction of the increasing coordinate. Parameters ---------- tick_direction : {"+", "-"} """ self._ticklabel_add_angle = cbook._check_getitem( { "+": 0, "-": 180 }, tick_direction=tick_direction) def invert_ticklabel_direction(self): self._ticklabel_add_angle = (self._ticklabel_add_angle + 180) % 360 self.major_ticklabels.invert_axis_direction() self.minor_ticklabels.invert_axis_direction() def set_axislabel_direction(self, label_direction): r""" Adjust the direction of the axislabel. Note that the *label_direction*\s '+' and '-' are relative to the direction of the increasing coordinate. Parameters ---------- tick_direction : {"+", "-"} """ self._axislabel_add_angle = cbook._check_getitem( { "+": 0, "-": 180 }, label_direction=label_direction) def get_transform(self): return self.axes.transAxes + self.offset_transform def get_helper(self): """ Return axis artist helper instance. """ return self._axis_artist_helper def set_axisline_style(self, axisline_style=None, **kwargs): """ Set the axisline style. The new style is completely defined by the passed attributes. Existing style attributes are forgotten. Parameters ---------- axisline_style : str or None The line style, e.g. '->', optionally followed by a comma-separated list of attributes. Alternatively, the attributes can be provided as keywords. If *None* this returns a string containing the available styles. Examples -------- The following two commands are equal: >>> set_axisline_style("->,size=1.5") >>> set_axisline_style("->", size=1.5) """ if axisline_style is None: return AxislineStyle.pprint_styles() if isinstance(axisline_style, AxislineStyle._Base): self._axisline_style = axisline_style else: self._axisline_style = AxislineStyle(axisline_style, **kwargs) self._init_line() def get_axisline_style(self): """Return the current axisline style.""" return self._axisline_style def _init_line(self): """ Initialize the *line* artist that is responsible to draw the axis line. """ tran = (self._axis_artist_helper.get_line_transform(self.axes) + self.offset_transform) axisline_style = self.get_axisline_style() if axisline_style is None: self.line = PathPatch(self._axis_artist_helper.get_line(self.axes), color=rcParams['axes.edgecolor'], fill=False, linewidth=rcParams['axes.linewidth'], capstyle=rcParams['lines.solid_capstyle'], joinstyle=rcParams['lines.solid_joinstyle'], transform=tran) else: self.line = axisline_style(self, transform=tran) def _draw_line(self, renderer): self.line.set_path(self._axis_artist_helper.get_line(self.axes)) if self.get_axisline_style() is not None: self.line.set_line_mutation_scale(self.major_ticklabels.get_size()) self.line.draw(renderer) def _init_ticks(self, axis_name, **kwargs): trans = (self._axis_artist_helper.get_tick_transform(self.axes) + self.offset_transform) major_tick_size = kwargs.get("major_tick_size", rcParams[f'{axis_name}.major.size']) major_tick_pad = kwargs.get("major_tick_pad", rcParams[f'{axis_name}.major.pad']) minor_tick_size = kwargs.get("minor_tick_size", rcParams[f'{axis_name}.minor.size']) minor_tick_pad = kwargs.get("minor_tick_pad", rcParams[f'{axis_name}.minor.pad']) self.major_ticks = Ticks(major_tick_size, axis=self.axis, transform=trans) self.minor_ticks = Ticks(minor_tick_size, axis=self.axis, transform=trans) if axis_name == "xaxis": size = rcParams['xtick.labelsize'] else: size = rcParams['ytick.labelsize'] self.major_ticklabels = TickLabels(size=size, axis=self.axis, axis_direction=self._axis_direction) self.minor_ticklabels = TickLabels(size=size, axis=self.axis, axis_direction=self._axis_direction) self.major_ticklabels.set(figure=self.axes.figure, transform=trans, fontsize=size) self.major_ticklabels.set_pad(major_tick_pad) self.minor_ticklabels.set(figure=self.axes.figure, transform=trans, fontsize=size) self.minor_ticklabels.set_pad(minor_tick_pad) def _get_tick_info(self, tick_iter): """ Return a pair of: - list of locs and angles for ticks - list of locs, angles and labels for ticklabels. """ ticks_loc_angle = [] ticklabels_loc_angle_label = [] ticklabel_add_angle = self._ticklabel_add_angle for loc, angle_normal, angle_tangent, label in tick_iter: angle_label = angle_tangent - 90 + ticklabel_add_angle angle_tick = (angle_normal if 90 <= (angle_label - angle_normal) % 360 <= 270 else angle_normal + 180) ticks_loc_angle.append([loc, angle_tick]) ticklabels_loc_angle_label.append([loc, angle_label, label]) return ticks_loc_angle, ticklabels_loc_angle_label def _update_ticks(self, renderer): # set extra pad for major and minor ticklabels: use ticksize of # majorticks even for minor ticks. not clear what is best. dpi_cor = renderer.points_to_pixels(1.) if self.major_ticks.get_visible() and self.major_ticks.get_tick_out(): self.major_ticklabels._set_external_pad( self.major_ticks._ticksize * dpi_cor) self.minor_ticklabels._set_external_pad( self.major_ticks._ticksize * dpi_cor) else: self.major_ticklabels._set_external_pad(0) self.minor_ticklabels._set_external_pad(0) majortick_iter, minortick_iter = \ self._axis_artist_helper.get_tick_iterators(self.axes) tick_loc_angle, ticklabel_loc_angle_label = \ self._get_tick_info(majortick_iter) self.major_ticks.set_locs_angles(tick_loc_angle) self.major_ticklabels.set_locs_angles_labels(ticklabel_loc_angle_label) # minor ticks tick_loc_angle, ticklabel_loc_angle_label = \ self._get_tick_info(minortick_iter) self.minor_ticks.set_locs_angles(tick_loc_angle) self.minor_ticklabels.set_locs_angles_labels(ticklabel_loc_angle_label) return self.major_ticklabels.get_window_extents(renderer) def _draw_ticks(self, renderer): extents = self._update_ticks(renderer) self.major_ticks.draw(renderer) self.major_ticklabels.draw(renderer) self.minor_ticks.draw(renderer) self.minor_ticklabels.draw(renderer) if (self.major_ticklabels.get_visible() or self.minor_ticklabels.get_visible()): self._draw_offsetText(renderer) return extents def _draw_ticks2(self, renderer): # set extra pad for major and minor ticklabels: use ticksize of # majorticks even for minor ticks. not clear what is best. dpi_cor = renderer.points_to_pixels(1.) if self.major_ticks.get_visible() and self.major_ticks.get_tick_out(): self.major_ticklabels._set_external_pad( self.major_ticks._ticksize * dpi_cor) self.minor_ticklabels._set_external_pad( self.major_ticks._ticksize * dpi_cor) else: self.major_ticklabels._set_external_pad(0) self.minor_ticklabels._set_external_pad(0) majortick_iter, minortick_iter = \ self._axis_artist_helper.get_tick_iterators(self.axes) tick_loc_angle, ticklabel_loc_angle_label = \ self._get_tick_info(majortick_iter) self.major_ticks.set_locs_angles(tick_loc_angle) self.major_ticklabels.set_locs_angles_labels(ticklabel_loc_angle_label) self.major_ticks.draw(renderer) self.major_ticklabels.draw(renderer) # minor ticks tick_loc_angle, ticklabel_loc_angle_label = \ self._get_tick_info(minortick_iter) self.minor_ticks.set_locs_angles(tick_loc_angle) self.minor_ticklabels.set_locs_angles_labels(ticklabel_loc_angle_label) self.minor_ticks.draw(renderer) self.minor_ticklabels.draw(renderer) if (self.major_ticklabels.get_visible() or self.minor_ticklabels.get_visible()): self._draw_offsetText(renderer) return self.major_ticklabels.get_window_extents(renderer) _offsetText_pos = dict(left=(0, 1, "bottom", "right"), right=(1, 1, "bottom", "left"), bottom=(1, 0, "top", "right"), top=(1, 1, "bottom", "right")) def _init_offsetText(self, direction): x, y, va, ha = self._offsetText_pos[direction] self.offsetText = mtext.Annotation( "", xy=(x, y), xycoords="axes fraction", xytext=(0, 0), textcoords="offset points", color=rcParams['xtick.color'], horizontalalignment=ha, verticalalignment=va, ) self.offsetText.set_transform(IdentityTransform()) self.axes._set_artist_props(self.offsetText) def _update_offsetText(self): self.offsetText.set_text(self.axis.major.formatter.get_offset()) self.offsetText.set_size(self.major_ticklabels.get_size()) offset = (self.major_ticklabels.get_pad() + self.major_ticklabels.get_size() + 2) self.offsetText.xyann = (0, offset) def _draw_offsetText(self, renderer): self._update_offsetText() self.offsetText.draw(renderer) def _init_label(self, **kwargs): tr = (self._axis_artist_helper.get_axislabel_transform(self.axes) + self.offset_transform) self.label = AxisLabel( 0, 0, "__from_axes__", color="auto", fontsize=kwargs.get("labelsize", rcParams['axes.labelsize']), fontweight=rcParams['axes.labelweight'], axis=self.axis, transform=tr, axis_direction=self._axis_direction, ) self.label.set_figure(self.axes.figure) labelpad = kwargs.get("labelpad", 5) self.label.set_pad(labelpad) def _update_label(self, renderer): if not self.label.get_visible(): return if self._ticklabel_add_angle != self._axislabel_add_angle: if ((self.major_ticks.get_visible() and not self.major_ticks.get_tick_out()) or (self.minor_ticks.get_visible() and not self.major_ticks.get_tick_out())): axislabel_pad = self.major_ticks._ticksize else: axislabel_pad = 0 else: axislabel_pad = max(self.major_ticklabels._axislabel_pad, self.minor_ticklabels._axislabel_pad) self.label._set_external_pad(axislabel_pad) xy, angle_tangent = \ self._axis_artist_helper.get_axislabel_pos_angle(self.axes) if xy is None: return angle_label = angle_tangent - 90 x, y = xy self.label._set_ref_angle(angle_label + self._axislabel_add_angle) self.label.set(x=x, y=y) def _draw_label(self, renderer): self._update_label(renderer) self.label.draw(renderer) def _draw_label2(self, renderer): if not self.label.get_visible(): return if self._ticklabel_add_angle != self._axislabel_add_angle: if ((self.major_ticks.get_visible() and not self.major_ticks.get_tick_out()) or (self.minor_ticks.get_visible() and not self.major_ticks.get_tick_out())): axislabel_pad = self.major_ticks._ticksize else: axislabel_pad = 0 else: axislabel_pad = max(self.major_ticklabels._axislabel_pad, self.minor_ticklabels._axislabel_pad) self.label._set_external_pad(axislabel_pad) xy, angle_tangent = \ self._axis_artist_helper.get_axislabel_pos_angle(self.axes) if xy is None: return angle_label = angle_tangent - 90 x, y = xy self.label._set_ref_angle(angle_label + self._axislabel_add_angle) self.label.set(x=x, y=y) self.label.draw(renderer) def set_label(self, s): self.label.set_text(s) def get_tightbbox(self, renderer): if not self.get_visible(): return self._axis_artist_helper.update_lim(self.axes) self._update_ticks(renderer) self._update_label(renderer) bb = [ *self.major_ticklabels.get_window_extents(renderer), *self.minor_ticklabels.get_window_extents(renderer), self.label.get_window_extent(renderer), self.offsetText.get_window_extent(renderer), ] bb = [b for b in bb if b and (b.width != 0 or b.height != 0)] if bb: _bbox = Bbox.union(bb) return _bbox else: return None @martist.allow_rasterization def draw(self, renderer): # docstring inherited if not self.get_visible(): return renderer.open_group(__name__, gid=self.get_gid()) self._axis_artist_helper.update_lim(self.axes) self._draw_ticks(renderer) self._draw_line(renderer) self._draw_label(renderer) renderer.close_group(__name__) def toggle(self, all=None, ticks=None, ticklabels=None, label=None): """ Toggle visibility of ticks, ticklabels, and (axis) label. To turn all off, :: axis.toggle(all=False) To turn all off but ticks on :: axis.toggle(all=False, ticks=True) To turn all on but (axis) label off :: axis.toggle(all=True, label=False)) """ if all: _ticks, _ticklabels, _label = True, True, True elif all is not None: _ticks, _ticklabels, _label = False, False, False else: _ticks, _ticklabels, _label = None, None, None if ticks is not None: _ticks = ticks if ticklabels is not None: _ticklabels = ticklabels if label is not None: _label = label if _ticks is not None: self.major_ticks.set_visible(_ticks) self.minor_ticks.set_visible(_ticks) if _ticklabels is not None: self.major_ticklabels.set_visible(_ticklabels) self.minor_ticklabels.set_visible(_ticklabels) if _label is not None: self.label.set_visible(_label)
x=np.linspace((xcoord-length/2),(xcoord+length/2),length+1,dtype=int) y=np.linspace((ycoord+width/2),(ycoord-width/2),width+1,dtype=int) x_1,y_1=np.meshgrid(x,y, indexing='xy') points = np.array(list(zip(x_1.flatten(),y_1.flatten()))) vertices = [((xcoord-length/2), (ycoord-width/2)), ((xcoord-length/2), (ycoord+width/2)), ((xcoord+length/2), (ycoord+width/2)), ((xcoord+length/2), (ycoord-width/2)), (0, 0)] return points, vertices #################### ROBOT COORDINATE robot_x_coord=30 #LOCATION OF THE EQUIPMENT ENTRY DOOR WHERE ROBOT WILL START robot_y_coord=30 #LOCATION OF THE EQUIPMENT ENTRY DOOR WHERE ROBOT WILL START robot_height=6 robot_breadth=6 Robot_points,rvertices=makeRect(robot_x_coord,robot_y_coord,robot_breadth,robot_height) ########### PLOTTING THE ROBOT ################ rcodes = [Path.MOVETO] + [Path.LINETO]*3 + [Path.CLOSEPOLY] robot = Path(rvertices,rcodes) robotpatch = PathPatch(robot, facecolor='green', edgecolor='green') #################### PLOTTING SOURCE 1 circle=Path.circle(Source1_location, radius=1) source1patch=PathPatch(circle, facecolor='red', edgecolor='red') #################### PLOTTING SOURCE 2 circle=Path.circle(Source2_location, radius=1) source2patch=PathPatch(circle, facecolor='red', edgecolor='red') #################### PLOTTING SOURCE 3 circle=Path.circle(Source3_location, radius=1) source3patch=PathPatch(circle, facecolor='red', edgecolor='red') #################### PLOTTING DRY STORAGE CASK 1 circle=Path.circle(Cask1_location, radius=Cask_rad) sourcedrycast1=PathPatch(circle, facecolor='white', edgecolor='none') #################### PLOTTING DRY STORAGE CASK 2 circle=Path.circle(Cask2_location, radius=Cask_rad)
# Plot the MOC using matplotlib import matplotlib.pyplot as plt fig = plt.figure(111, figsize=(10, 10)) # Define a astropy WCS easily with World2ScreenMPL( fig, fov=20 * u.deg, center=SkyCoord(10, 5, unit='deg', frame='icrs'), coordsys="icrs", rotation=Angle(0, u.degree), # The gnomonic projection transforms great circles into straight lines. projection="TAN") as wcs: ax = fig.add_subplot(1, 1, 1, projection=wcs) # Call fill with a matplotlib axe and the `~astropy.wcs.WCS` wcs object. moc.fill(ax=ax, wcs=wcs, alpha=0.5, fill=True, color="red", linewidth=1) moc.border(ax=ax, wcs=wcs, alpha=1, color="red") # Plot the border from astropy.wcs.utils import skycoord_to_pixel x, y = skycoord_to_pixel(skycoords[0], wcs) p = Path(np.vstack((x, y)).T) patch = PathPatch(p, color="black", fill=False, alpha=0.75, lw=2) ax.add_patch(patch) plt.xlabel('ra') plt.ylabel('dec') plt.title('Get the border(s) of a MOC') plt.grid(color="black", linestyle="dotted") plt.show()
class ColorbarBase(cm.ScalarMappable): ''' Draw a colorbar in an existing axes. This is a base class for the :class:`Colorbar` class, which is the basis for the :func:`~matplotlib.pyplot.colorbar` method and pylab function. It is also useful by itself for showing a colormap. If the *cmap* kwarg is given but *boundaries* and *values* are left as None, then the colormap will be displayed on a 0-1 scale. To show the under- and over-value colors, specify the *norm* as:: colors.Normalize(clip=False) To show the colors versus index instead of on the 0-1 scale, use:: norm=colors.NoNorm. Useful attributes: :attr:`ax` the Axes instance in which the colorbar is drawn :attr:`lines` a LineCollection if lines were drawn, otherwise None :attr:`dividers` a LineCollection if *drawedges* is True, otherwise None Useful public methods are :meth:`set_label` and :meth:`add_lines`. ''' def __init__(self, ax, cmap=None, norm=None, alpha=1.0, values=None, boundaries=None, orientation='vertical', extend='neither', spacing='uniform', # uniform or proportional ticks=None, format=None, drawedges=False, filled=True, ): self.ax = ax if cmap is None: cmap = cm.get_cmap() if norm is None: norm = colors.Normalize() self.alpha = alpha cm.ScalarMappable.__init__(self, cmap=cmap, norm=norm) self.values = values self.boundaries = boundaries self.extend = extend self.spacing = spacing self.orientation = orientation self.drawedges = drawedges self.filled = filled # artists self.solids = None self.lines = None self.dividers = None self.extension_patch1 = None self.extension_patch2 = None if orientation == "vertical": self.cbar_axis = self.ax.yaxis else: self.cbar_axis = self.ax.xaxis if format is None: if isinstance(self.norm, colors.LogNorm): # change both axis for proper aspect self.ax.set_xscale("log") self.ax.set_yscale("log") self.cbar_axis.set_minor_locator(ticker.NullLocator()) formatter = ticker.LogFormatter() else: formatter = None elif isinstance(format, six.string_types): formatter = ticker.FormatStrFormatter(format) else: formatter = format # Assume it is a Formatter if formatter is None: formatter = self.cbar_axis.get_major_formatter() else: self.cbar_axis.set_major_formatter(formatter) if cbook.iterable(ticks): self.cbar_axis.set_ticks(ticks) elif ticks is not None: self.cbar_axis.set_major_locator(ticks) else: self._select_locator(formatter) self._config_axes() self.update_artists() self.set_label_text('') def _get_colorbar_limits(self): """ initial limits for colorbar range. The returned min, max values will be used to create colorbar solid(?) and etc. """ if self.boundaries is not None: C = self.boundaries if self.extend in ["min", "both"]: C = C[1:] if self.extend in ["max", "both"]: C = C[:-1] return min(C), max(C) else: return self.get_clim() def _config_axes(self): ''' Adjust the properties of the axes to be adequate for colorbar display. ''' ax = self.ax axes_locator = CbarAxesLocator(ax.get_axes_locator(), extend=self.extend, orientation=self.orientation) ax.set_axes_locator(axes_locator) # override the get_data_ratio for the aspect works. def _f(): return 1. ax.get_data_ratio = _f ax.get_data_ratio_log = _f ax.set_frame_on(True) ax.set_navigate(False) self.ax.set_autoscalex_on(False) self.ax.set_autoscaley_on(False) if self.orientation == 'horizontal': ax.xaxis.set_label_position('bottom') ax.set_yticks([]) else: ax.set_xticks([]) ax.yaxis.set_label_position('right') ax.yaxis.set_ticks_position('right') def update_artists(self): """ Update the colorbar associated artists, *filled* and *ends*. Note that *lines* are not updated. This needs to be called whenever clim of associated image changes. """ self._process_values() self._add_ends() X, Y = self._mesh() if self.filled: C = self._values[:,np.newaxis] self._add_solids(X, Y, C) ax = self.ax vmin, vmax = self._get_colorbar_limits() if self.orientation == 'horizontal': ax.set_ylim(1, 2) ax.set_xlim(vmin, vmax) else: ax.set_xlim(1, 2) ax.set_ylim(vmin, vmax) def _add_ends(self): """ Create patches from extended ends and add them to the axes. """ del self.extension_patch1 del self.extension_patch2 path1, path2 = self.ax.get_axes_locator().get_path_ends() fc=mpl.rcParams['axes.facecolor'] ec=mpl.rcParams['axes.edgecolor'] linewidths=0.5*mpl.rcParams['axes.linewidth'] self.extension_patch1 = PathPatch(path1, fc=fc, ec=ec, lw=linewidths, zorder=2., transform=self.ax.transAxes, clip_on=False) self.extension_patch2 = PathPatch(path2, fc=fc, ec=ec, lw=linewidths, zorder=2., transform=self.ax.transAxes, clip_on=False) self.ax.add_artist(self.extension_patch1) self.ax.add_artist(self.extension_patch2) def _set_label_text(self): """ set label. """ self.cbar_axis.set_label_text(self._label, **self._labelkw) def set_label_text(self, label, **kw): ''' Label the long axis of the colorbar ''' self._label = label self._labelkw = kw self._set_label_text() def _edges(self, X, Y): ''' Return the separator line segments; helper for _add_solids. ''' N = X.shape[0] # Using the non-array form of these line segments is much # simpler than making them into arrays. if self.orientation == 'vertical': return [list(zip(X[i], Y[i])) for i in xrange(1, N-1)] else: return [list(zip(Y[i], X[i])) for i in xrange(1, N-1)] def _add_solids(self, X, Y, C): ''' Draw the colors using :meth:`~matplotlib.axes.Axes.pcolormesh`; optionally add separators. ''' ## Change to pcolorfast after fixing bugs in some backends... if self.extend in ["min", "both"]: cc = self.to_rgba([C[0][0]]) self.extension_patch1.set_fc(cc[0]) X, Y, C = X[1:], Y[1:], C[1:] if self.extend in ["max", "both"]: cc = self.to_rgba([C[-1][0]]) self.extension_patch2.set_fc(cc[0]) X, Y, C = X[:-1], Y[:-1], C[:-1] if self.orientation == 'vertical': args = (X, Y, C) else: args = (np.transpose(Y), np.transpose(X), np.transpose(C)) kw = {'cmap':self.cmap, 'norm':self.norm, 'shading':'flat', 'alpha':self.alpha, } del self.solids del self.dividers col = self.ax.pcolormesh(*args, **kw) self.solids = col if self.drawedges: self.dividers = collections.LineCollection(self._edges(X,Y), colors=(mpl.rcParams['axes.edgecolor'],), linewidths=(0.5*mpl.rcParams['axes.linewidth'],), ) self.ax.add_collection(self.dividers) else: self.dividers = None def add_lines(self, levels, colors, linewidths): ''' Draw lines on the colorbar. It deletes preexisting lines. ''' del self.lines N = len(levels) x = np.array([1.0, 2.0]) X, Y = np.meshgrid(x,levels) if self.orientation == 'vertical': xy = [list(zip(X[i], Y[i])) for i in xrange(N)] else: xy = [list(zip(Y[i], X[i])) for i in xrange(N)] col = collections.LineCollection(xy, linewidths=linewidths, ) self.lines = col col.set_color(colors) self.ax.add_collection(col) def _select_locator(self, formatter): ''' select a suitable locator ''' if self.boundaries is None: if isinstance(self.norm, colors.NoNorm): nv = len(self._values) base = 1 + int(nv/10) locator = ticker.IndexLocator(base=base, offset=0) elif isinstance(self.norm, colors.BoundaryNorm): b = self.norm.boundaries locator = ticker.FixedLocator(b, nbins=10) elif isinstance(self.norm, colors.LogNorm): locator = ticker.LogLocator() else: locator = ticker.MaxNLocator(nbins=5) else: b = self._boundaries[self._inside] locator = ticker.FixedLocator(b) #, nbins=10) self.cbar_axis.set_major_locator(locator) def _process_values(self, b=None): ''' Set the :attr:`_boundaries` and :attr:`_values` attributes based on the input boundaries and values. Input boundaries can be *self.boundaries* or the argument *b*. ''' if b is None: b = self.boundaries if b is not None: self._boundaries = np.asarray(b, dtype=float) if self.values is None: self._values = 0.5*(self._boundaries[:-1] + self._boundaries[1:]) if isinstance(self.norm, colors.NoNorm): self._values = (self._values + 0.00001).astype(np.int16) return self._values = np.array(self.values) return if self.values is not None: self._values = np.array(self.values) if self.boundaries is None: b = np.zeros(len(self.values)+1, 'd') b[1:-1] = 0.5*(self._values[:-1] - self._values[1:]) b[0] = 2.0*b[1] - b[2] b[-1] = 2.0*b[-2] - b[-3] self._boundaries = b return self._boundaries = np.array(self.boundaries) return # Neither boundaries nor values are specified; # make reasonable ones based on cmap and norm. if isinstance(self.norm, colors.NoNorm): b = self._uniform_y(self.cmap.N+1) * self.cmap.N - 0.5 v = np.zeros((len(b)-1,), dtype=np.int16) v = np.arange(self.cmap.N, dtype=np.int16) self._boundaries = b self._values = v return elif isinstance(self.norm, colors.BoundaryNorm): b = np.array(self.norm.boundaries) v = np.zeros((len(b)-1,), dtype=float) bi = self.norm.boundaries v = 0.5*(bi[:-1] + bi[1:]) self._boundaries = b self._values = v return else: b = self._uniform_y(self.cmap.N+1) self._process_values(b) def _uniform_y(self, N): ''' Return colorbar data coordinates for *N* uniformly spaced boundaries. ''' vmin, vmax = self._get_colorbar_limits() if isinstance(self.norm, colors.LogNorm): y = np.logspace(np.log10(vmin), np.log10(vmax), N) else: y = np.linspace(vmin, vmax, N) return y def _mesh(self): ''' Return X,Y, the coordinate arrays for the colorbar pcolormesh. These are suitable for a vertical colorbar; swapping and transposition for a horizontal colorbar are done outside this function. ''' x = np.array([1.0, 2.0]) if self.spacing == 'uniform': y = self._uniform_y(len(self._boundaries)) else: y = self._boundaries self._y = y X, Y = np.meshgrid(x,y) return X, Y def set_alpha(self, alpha): """ set alpha value. """ self.alpha = alpha
class ColorbarBase(cm.ScalarMappable): ''' Draw a colorbar in an existing axes. This is a base class for the :class:`Colorbar` class, which is the basis for the :func:`~matplotlib.pyplot.colorbar` method and pylab function. It is also useful by itself for showing a colormap. If the *cmap* kwarg is given but *boundaries* and *values* are left as None, then the colormap will be displayed on a 0-1 scale. To show the under- and over-value colors, specify the *norm* as:: colors.Normalize(clip=False) To show the colors versus index instead of on the 0-1 scale, use:: norm=colors.NoNorm. Useful attributes: :attr:`ax` the Axes instance in which the colorbar is drawn :attr:`lines` a LineCollection if lines were drawn, otherwise None :attr:`dividers` a LineCollection if *drawedges* is True, otherwise None Useful public methods are :meth:`set_label` and :meth:`add_lines`. ''' def __init__(self, ax, cmap=None, norm=None, alpha=1.0, values=None, boundaries=None, orientation='vertical', extend='neither', spacing='uniform', # uniform or proportional ticks=None, format=None, drawedges=False, filled=True, ): self.ax = ax if cmap is None: cmap = cm.get_cmap() if norm is None: norm = colors.Normalize() self.alpha = alpha cm.ScalarMappable.__init__(self, cmap=cmap, norm=norm) self.values = values self.boundaries = boundaries self.extend = extend self.spacing = spacing self.orientation = orientation self.drawedges = drawedges self.filled = filled # artists self.solids = None self.lines = None self.dividers = None self.extension_patch1 = None self.extension_patch2 = None if orientation == "vertical": self.cbar_axis = self.ax.yaxis else: self.cbar_axis = self.ax.xaxis if format is None: if isinstance(self.norm, colors.LogNorm): # change both axis for proper aspect self.ax.xaxis.set_scale("log") self.ax.yaxis.set_scale("log") self.ax._update_transScale() self.cbar_axis.set_minor_locator(ticker.NullLocator()) formatter = ticker.LogFormatter() else: formatter = None elif cbook.is_string_like(format): formatter = ticker.FormatStrFormatter(format) else: formatter = format # Assume it is a Formatter if formatter is None: formatter = self.cbar_axis.get_major_formatter() else: self.cbar_axis.set_major_formatter(formatter) if cbook.iterable(ticks): self.cbar_axis.set_ticks(ticks) elif ticks is not None: self.cbar_axis.set_major_locator(ticks) else: self._select_locator(formatter) self._config_axes() self.update_artists() self.set_label_text('') def _get_colorbar_limits(self): """ initial limits for colorbar range. The returned min, max values will be used to create colorbar solid(?) and etc. """ if self.boundaries is not None: C = self.boundaries if self.extend in ["min", "both"]: C = C[1:] if self.extend in ["max", "both"]: C = C[:-1] return min(C), max(C) else: return self.get_clim() def _config_axes(self): ''' Adjust the properties of the axes to be adequate for colorbar display. ''' ax = self.ax axes_locator = CbarAxesLocator(ax.get_axes_locator(), extend=self.extend, orientation=self.orientation) ax.set_axes_locator(axes_locator) # override the get_data_ratio for the aspect works. def _f(): return 1. ax.get_data_ratio = _f ax.get_data_ratio_log = _f ax.set_frame_on(True) ax.set_navigate(False) self.ax.set_autoscalex_on(False) self.ax.set_autoscaley_on(False) if self.orientation == 'horizontal': ax.xaxis.set_label_position('bottom') ax.set_yticks([]) else: ax.set_xticks([]) ax.yaxis.set_label_position('right') ax.yaxis.set_ticks_position('right') def update_artists(self): """ Update the colorbar associated artists, *filled* and *ends*. Note that *lines* are not updated. This needs to be called whenever clim of associated image changes. """ self._process_values() self._add_ends() X, Y = self._mesh() if self.filled: C = self._values[:,np.newaxis] self._add_solids(X, Y, C) ax = self.ax vmin, vmax = self._get_colorbar_limits() if self.orientation == 'horizontal': ax.set_ylim(1, 2) ax.set_xlim(vmin, vmax) else: ax.set_xlim(1, 2) ax.set_ylim(vmin, vmax) def _add_ends(self): """ Create patches from extended ends and add them to the axes. """ del self.extension_patch1 del self.extension_patch2 path1, path2 = self.ax.get_axes_locator().get_path_ends() fc=mpl.rcParams['axes.facecolor'] ec=mpl.rcParams['axes.edgecolor'] linewidths=0.5*mpl.rcParams['axes.linewidth'] self.extension_patch1 = PathPatch(path1, fc=fc, ec=ec, lw=linewidths, zorder=2., transform=self.ax.transAxes, clip_on=False) self.extension_patch2 = PathPatch(path2, fc=fc, ec=ec, lw=linewidths, zorder=2., transform=self.ax.transAxes, clip_on=False) self.ax.add_artist(self.extension_patch1) self.ax.add_artist(self.extension_patch2) def _set_label_text(self): """ set label. """ self.cbar_axis.set_label_text(self._label, **self._labelkw) def set_label_text(self, label, **kw): ''' Label the long axis of the colorbar ''' self._label = label self._labelkw = kw self._set_label_text() def _edges(self, X, Y): ''' Return the separator line segments; helper for _add_solids. ''' N = X.shape[0] # Using the non-array form of these line segments is much # simpler than making them into arrays. if self.orientation == 'vertical': return [zip(X[i], Y[i]) for i in range(1, N-1)] else: return [zip(Y[i], X[i]) for i in range(1, N-1)] def _add_solids(self, X, Y, C): ''' Draw the colors using :meth:`~matplotlib.axes.Axes.pcolor`; optionally add separators. ''' ## Change to pcolorfast after fixing bugs in some backends... if self.extend in ["min", "both"]: cc = self.to_rgba([C[0][0]]) self.extension_patch1.set_fc(cc[0]) X, Y, C = X[1:], Y[1:], C[1:] if self.extend in ["max", "both"]: cc = self.to_rgba([C[-1][0]]) self.extension_patch2.set_fc(cc[0]) X, Y, C = X[:-1], Y[:-1], C[:-1] if self.orientation == 'vertical': args = (X, Y, C) else: args = (np.transpose(Y), np.transpose(X), np.transpose(C)) kw = {'cmap':self.cmap, 'norm':self.norm, 'shading':'flat', 'alpha':self.alpha, } del self.solids del self.dividers col = self.ax.pcolor(*args, **kw) self.solids = col if self.drawedges: self.dividers = collections.LineCollection(self._edges(X,Y), colors=(mpl.rcParams['axes.edgecolor'],), linewidths=(0.5*mpl.rcParams['axes.linewidth'],), ) self.ax.add_collection(self.dividers) else: self.dividers = None def add_lines(self, levels, colors, linewidths): ''' Draw lines on the colorbar. It deletes preexisting lines. ''' del self.lines N = len(levels) x = np.array([1.0, 2.0]) X, Y = np.meshgrid(x,levels) if self.orientation == 'vertical': xy = [zip(X[i], Y[i]) for i in range(N)] else: xy = [zip(Y[i], X[i]) for i in range(N)] col = collections.LineCollection(xy, linewidths=linewidths, ) self.lines = col col.set_color(colors) self.ax.add_collection(col) def _select_locator(self, formatter): ''' select a suitable locator ''' if self.boundaries is None: if isinstance(self.norm, colors.NoNorm): nv = len(self._values) base = 1 + int(nv/10) locator = ticker.IndexLocator(base=base, offset=0) elif isinstance(self.norm, colors.BoundaryNorm): b = self.norm.boundaries locator = ticker.FixedLocator(b, nbins=10) elif isinstance(self.norm, colors.LogNorm): locator = ticker.LogLocator() else: locator = ticker.MaxNLocator(nbins=5) else: b = self._boundaries[self._inside] locator = ticker.FixedLocator(b) #, nbins=10) self.cbar_axis.set_major_locator(locator) def _process_values(self, b=None): ''' Set the :attr:`_boundaries` and :attr:`_values` attributes based on the input boundaries and values. Input boundaries can be *self.boundaries* or the argument *b*. ''' if b is None: b = self.boundaries if b is not None: self._boundaries = np.asarray(b, dtype=float) if self.values is None: self._values = 0.5*(self._boundaries[:-1] + self._boundaries[1:]) if isinstance(self.norm, colors.NoNorm): self._values = (self._values + 0.00001).astype(np.int16) return self._values = np.array(self.values) return if self.values is not None: self._values = np.array(self.values) if self.boundaries is None: b = np.zeros(len(self.values)+1, 'd') b[1:-1] = 0.5*(self._values[:-1] - self._values[1:]) b[0] = 2.0*b[1] - b[2] b[-1] = 2.0*b[-2] - b[-3] self._boundaries = b return self._boundaries = np.array(self.boundaries) return # Neither boundaries nor values are specified; # make reasonable ones based on cmap and norm. if isinstance(self.norm, colors.NoNorm): b = self._uniform_y(self.cmap.N+1) * self.cmap.N - 0.5 v = np.zeros((len(b)-1,), dtype=np.int16) v = np.arange(self.cmap.N, dtype=np.int16) self._boundaries = b self._values = v return elif isinstance(self.norm, colors.BoundaryNorm): b = np.array(self.norm.boundaries) v = np.zeros((len(b)-1,), dtype=float) bi = self.norm.boundaries v = 0.5*(bi[:-1] + bi[1:]) self._boundaries = b self._values = v return else: b = self._uniform_y(self.cmap.N+1) self._process_values(b) def _uniform_y(self, N): ''' Return colorbar data coordinates for *N* uniformly spaced boundaries. ''' vmin, vmax = self._get_colorbar_limits() if isinstance(self.norm, colors.LogNorm): y = np.logspace(np.log10(vmin), np.log10(vmax), N) else: y = np.linspace(vmin, vmax, N) return y def _mesh(self): ''' Return X,Y, the coordinate arrays for the colorbar pcolormesh. These are suitable for a vertical colorbar; swapping and transposition for a horizontal colorbar are done outside this function. ''' x = np.array([1.0, 2.0]) if self.spacing == 'uniform': y = self._uniform_y(len(self._boundaries)) else: y = self._boundaries self._y = y X, Y = np.meshgrid(x,y) return X, Y def set_alpha(self, alpha): """ set alpha value. """ self.alpha = alpha