def _find_best_position(self, width, height, renderer, consider=None): """ Determine the best location to place the legend. `consider` is a list of (x, y) pairs to consider as a potential lower-left corner of the legend. All are display coords. """ # should always hold because function is only called internally assert self.isaxes verts, bboxes, lines, offsets = self._auto_legend_data() bbox = Bbox.from_bounds(0, 0, width, height) if consider is None: consider = [self._get_anchored_bbox(x, bbox, self.get_bbox_to_anchor(), renderer) for x in range(1, len(self.codes))] # tx, ty = self.legendPatch.get_x(), self.legendPatch.get_y() candidates = [] for l, b in consider: legendBox = Bbox.from_bounds(l, b, width, height) badness = 0 # XXX TODO: If markers are present, it would be good to # take their into account when checking vertex overlaps in # the next line. badness = legendBox.count_contains(verts) badness += legendBox.count_contains(offsets) badness += legendBox.count_overlaps(bboxes) for line in lines: # FIXME: the following line is ill-suited for lines # that 'spiral' around the center, because the bbox # may intersect with the legend even if the line # itself doesn't. One solution would be to break up # the line into its straight-segment components, but # this may (or may not) result in a significant # slowdown if lines with many vertices are present. if line.intersects_bbox(legendBox): badness += 1 ox, oy = l, b if badness == 0: return ox, oy candidates.append((badness, (l, b))) # rather than use min() or list.sort(), do this so that we are assured # that in the case of two equal badnesses, the one first considered is # returned. # NOTE: list.sort() is stable.But leave as it is for now. -JJL minCandidate = candidates[0] for candidate in candidates: if candidate[0] < minCandidate[0]: minCandidate = candidate ox, oy = minCandidate[1] return ox, oy
def adjust_bbox_pdf(fig, bbox_inches): """ adjust_bbox for pdf & eps format """ if fig._cachedRenderer.__class__.__name__ == "RendererPgf": tr = Affine2D().scale(fig.dpi) f = 1. else: tr = Affine2D().scale(72) f = 72. / fig.dpi _bbox = TransformedBbox(bbox_inches, tr) fig.bbox_inches = Bbox.from_bounds(0, 0, bbox_inches.width, bbox_inches.height) x0, y0 = _bbox.x0, _bbox.y0 w1, h1 = fig.bbox.width * f, fig.bbox.height * f fig.transFigure._boxout = Bbox.from_bounds(-x0, -y0, w1, h1) fig.transFigure.invalidate() fig.bbox = TransformedBbox(fig.bbox_inches, tr) fig.patch.set_bounds(x0 / w1, y0 / h1, fig.bbox.width / w1, fig.bbox.height / h1)
def _find_best_position(self, width, height, renderer, consider=None): """ Determine the best location to place the legend. `consider` is a list of (x, y) pairs to consider as a potential lower-left corner of the legend. All are display coords. """ assert self.isaxes # should always hold because function is only called internally verts, bboxes, lines = self._auto_legend_data() bbox = Bbox.from_bounds(0, 0, width, height) consider = [self._get_anchored_bbox(x, bbox, self.get_bbox_to_anchor(), renderer) for x in range(1, len(self.codes))] candidates = [] for l, b in consider: legendBox = Bbox.from_bounds(l, b, width, height) badness = 0 badness = legendBox.count_contains(verts) badness += legendBox.count_overlaps(bboxes) for line in lines: if line.intersects_bbox(legendBox): badness += 1 ox, oy = l, b if badness == 0: return ox, oy candidates.append((badness, (l, b))) minCandidate = candidates[0] for candidate in candidates: if candidate[0] < minCandidate[0]: minCandidate = candidate ox, oy = minCandidate[1] return ox, oy
def get_tight_bbox(fig, bbox_extra_artists=[], pad=None): """ Compute a tight bounding box around all the artists in the figure. """ renderer = fig.canvas.get_renderer() bbox_inches = fig.get_tightbbox(renderer) bbox_artists = bbox_extra_artists[:] bbox_artists += fig.get_default_bbox_extra_artists() bbox_filtered = [] for a in bbox_artists: bbox = a.get_window_extent(renderer) if isinstance(bbox, tuple): continue if a.get_clip_on(): clip_box = a.get_clip_box() if clip_box is not None: bbox = Bbox.intersection(bbox, clip_box) clip_path = a.get_clip_path() if clip_path is not None and bbox is not None: clip_path = clip_path.get_fully_transformed_path() bbox = Bbox.intersection(bbox, clip_path.get_extents()) if bbox is not None and (bbox.width != 0 or bbox.height != 0): bbox_filtered.append(bbox) if bbox_filtered: _bbox = Bbox.union(bbox_filtered) trans = Affine2D().scale(1.0 / fig.dpi) bbox_extra = TransformedBbox(_bbox, trans) bbox_inches = Bbox.union([bbox_inches, bbox_extra]) return bbox_inches.padded(pad) if pad else bbox_inches
def draw_plot(self): if self._doRePlot: self._resizeCreateContent() if self.background is None: self.background = self.canvas.copy_from_bbox(self.ax.bbox) self.foo += 1 #self.y = numpy.cos(numpy.arange(0.0,1.0,0.1)+self.foo*0.1) # Optimization on the blitting: we compute the box where the changes happen changes_box = None for i in range(len(self.lines)): data=self.channels[i].getNext() if len(data[1])>0: if self.autolim: print self.autolim[0], data[1], self.autolim[1] self.autolim = [ min(self.autolim[0], min(data[1])), \ max(self.autolim[1], max(data[1])) ] else: self.autolim = [ min(data[1]), min(data[1]) ] if changes_box is None: changes_box = Bbox.unit() print '>>>>>>>>' print data[0], data[1] changes_box.update_from_data(numpy.array(data[0]), \ numpy.array(data[1]), ignore=changes_box.is_unit()) if not self._doRePlot and len(data[0]) > 0 : end = data[0][-1] if end > self.begin+self.span: self.begin += self.span self._doRePlot = True print 'do replot' self.lines[i].set_data(data[0], data[1]) else: self.lines[i].set_data([], []) if not changes_box: return #self.canvas.restore_region(self.background) for line in self.lines: self.ax.draw_artist(line) #print line.get_transform() tr = line.get_transform() changes_box_inframe = changes_box.transformed(tr) box_padding = 5 (x,y,l,w) = changes_box_inframe.bounds changes_box_inframe = Bbox.from_bounds(x-box_padding, \ y-box_padding, l+2*box_padding, w+2*box_padding) #print t0 = time.time() self.canvas.blit(None) #self.canvas.blit(changes_box_inframe) self.blit_time += time.time() - t0
def _calculate_bbox(self): r = self.renderer bboxes = self.xaxis.get_window_extent(r), self.yaxis.get_window_extent(r), self.subplot.bbox all_bbox = Bbox.union(bboxes) (x0, y0), (x1, y1) = all_bbox.get_points() w = x1 - x0 h = y1 - y0 all_bbox = Bbox.from_bounds(x0, y0, w * 1.02, h * 1.02) return all_bbox
def plotIToEBrokenAxis(sp, gIdx, neuronIdx, trialNum=0, axBoundaries=None, axesProportions=(0.5, 0.5), bottomLimits=None, topLimits=None, **kw): if axBoundaries is None: axBoundaries = [0, 0, 1, 1] left, bottom, right, top = axBoundaries title = kw.pop('title', 'E cell') fig = kw.pop('fig', plt.gcf()) h = top - bottom w = right - left hBottom = h*axesProportions[0] hTop = h*axesProportions[1] axBottom = fig.add_axes(Bbox.from_extents(left, bottom, right, bottom + hBottom)) axTop = fig.add_axes(Bbox.from_extents(left, top - hTop, right, top), sharex=axBottom) _, gI = aggr.computeYX(sp, iterList) M = sp[0][gIdx][trialNum].data['g_EI'] conns = M[neuronIdx, :] pconn.plotConnHistogram(conns, title=title, ax=axBottom, **kw) kw['ylabel'] = '' pconn.plotConnHistogram(conns, title=title, ax=axTop, **kw) annG = gI[0, gIdx] if annG - int(annG) == 0: annG = int(annG) #ann = '$g_I$ = {0} nS'.format(annG) #fig.text(left+0.95*w, bottom+0.9*h, ann, ha='right', va='bottom', # fontsize='x-small') axBottom.set_xlim([0, annG]) axBottom.set_xticks([0, annG]) axBottom.xaxis.set_ticklabels([0, '$g_I$']) axBottom.set_ylim(bottomLimits) axBottom.set_yticks(bottomLimits) axBottom.yaxis.set_minor_locator(ti.NullLocator()) axTop.set_ylim(topLimits) axTop.set_yticks([topLimits[1]]) axTop.xaxis.set_visible(False) axTop.spines['bottom'].set_visible(False) divLen = 0.07 d = .015 kwargs = dict(transform=fig.transFigure, color='k', clip_on=False) axBottom.plot((left-divLen*w, left+divLen*w), (bottom+hBottom + d, bottom+hBottom - d), **kwargs) axTop.plot((left-divLen*w, left+divLen*w), (top-hTop + d, top-hTop - d), **kwargs) return axBottom, axTop
def zoom_effect(ax_zoomed, ax_origin, xlims = None, orientation='below', **kwargs): """ ax_zoomed : zoomed axes ax_origin: the main axes (xmin,xmax) : the limits of the colored area in both plot axes. connect ax1 & ax2. The x-range of (xmin, xmax) in both axes will be marked. The keywords parameters will be used ti create patches. """ if xlims is None: tt = ax_zoomed.transScale + (ax_zoomed.transLimits + ax_origin.transAxes) transform = blended_transform_factory(ax_origin.transData, tt) bbox_zoomed=ax_zoomed.bbox bbox_origin=TransformedBbox(ax_zoomed.viewLim, transform) else: transform_zoomed=blended_transform_factory(ax_zoomed.transData, ax_zoomed.transAxes) transform_origin=blended_transform_factory(ax_origin.transData, ax_origin.transAxes) bbox_zoomed=TransformedBbox(Bbox.from_extents(xlims[0], 0, xlims[1], 1), transform_zoomed) bbox_origin=TransformedBbox(Bbox.from_extents(xlims[0], 0, xlims[1], 1), transform_origin) prop_patches = kwargs.copy() prop_patches["ec"] = "none" prop_patches["alpha"] = 0.2 if orientation=='below': loc1a=2 loc2a=3 loc1b=1 loc2b=4 elif orientation=='above': loc1a=3 loc2a=2 loc1b=4 loc2b=1 else: raise Exception("orientation '%s' not recognized" % orientation) c1, c2, bbox_zoomed_patch, bbox_origin_patch, p = \ connect_bbox(bbox_zoomed, bbox_origin, loc1a=loc1a, loc2a=loc2a, loc1b=loc1b, loc2b=loc2b, prop_lines=kwargs, prop_patches=prop_patches) ax_zoomed.add_patch(bbox_zoomed_patch) ax_origin.add_patch(bbox_origin_patch) ax_origin.add_patch(c1) ax_origin.add_patch(c2) ax_origin.add_patch(p) return c1, c2, bbox_zoomed_patch, bbox_origin_patch, p
def connect_bbox(bbox1, bbox2, loc1, loc2=None): """ Helper function to obtain a Path from one bbox to another. Parameters ---------- bbox1, bbox2 : `matplotlib.transforms.Bbox` Bounding boxes to connect. loc1 : {1, 2, 3, 4} Corner of *bbox1* to use. Valid values are:: 'upper right' : 1, 'upper left' : 2, 'lower left' : 3, 'lower right' : 4 loc2 : {1, 2, 3, 4}, optional Corner of *bbox2* to use. If None, defaults to *loc1*. Valid values are:: 'upper right' : 1, 'upper left' : 2, 'lower left' : 3, 'lower right' : 4 Returns ------- path : `matplotlib.path.Path` A line segment from the *loc1* corner of *bbox1* to the *loc2* corner of *bbox2*. """ if isinstance(bbox1, Rectangle): transform = bbox1.get_transform() bbox1 = Bbox.from_bounds(0, 0, 1, 1) bbox1 = TransformedBbox(bbox1, transform) if isinstance(bbox2, Rectangle): transform = bbox2.get_transform() bbox2 = Bbox.from_bounds(0, 0, 1, 1) bbox2 = TransformedBbox(bbox2, transform) if loc2 is None: loc2 = loc1 x1, y1 = BboxConnector.get_bbox_edge_pos(bbox1, loc1) x2, y2 = BboxConnector.get_bbox_edge_pos(bbox2, loc2) verts = [[x1, y1], [x2, y2]] codes = [Path.MOVETO, Path.LINETO] return Path(verts, codes)
def plot(self, *args, **kwargs): ps = self.env.ps output_dir = self.config['output_dir'] rateLeft = rasterLeft rateBottom = 0.2 rateRight = rasterRight rateTop = self.myc['rateTop'] for idx, noise_sigma in enumerate(ps.noise_sigmas): # E cells fig = self._get_final_fig(self.myc['fig_size']) ax = fig.add_axes(Bbox.from_extents(rateLeft, rateBottom, rateRight, rateTop)) kw = {} if (idx != 0): kw['ylabel'] = '' rasters.plotAvgFiringRate(ps.bumpGamma[idx], spaceType='bump', noise_sigma=ps.noise_sigmas[idx], popType='E', r=rasterRC[idx][0], c=rasterRC[idx][1], ylabelPos=self.myc['ylabelPos'], color='red', tLimits=tLimits, ax=ax, **kw) fname = output_dir + "/bumps_rate_e{0}.pdf".format(noise_sigma) fig.savefig(fname, dpi=300, transparent=transparent) plt.close() # I cells fig = self._get_final_fig(self.myc['fig_size']) ax = fig.add_axes(Bbox.from_extents(rateLeft, rateBottom, rateRight, rateTop)) kw = {} if (idx != 0): kw['ylabel'] = '' rasters.plotAvgFiringRate(ps.bumpGamma[idx], spaceType='bump', noise_sigma=ps.noise_sigmas[idx], popType='I', r=rasterRC[idx][0], c=rasterRC[idx][1], ylabelPos=self.myc['ylabelPos'], color='blue', tLimits=tLimits, ax=ax, **kw) fname = output_dir + "/bumps_rate_i{0}.pdf".format(noise_sigma) fig.savefig(fname, dpi=300, transparent=transparent) plt.close()
def plot(self, *args, **kwargs): ps = self.env.ps output_dir = self.config['output_dir'] transparent = self.myc['transparent'] for idx, noise_sigma in enumerate(ps.noise_sigmas): # E cells fig = self._get_final_fig(self.myc['fig_size']) l, b, r, t = self.myc['bbox'] ax = fig.add_axes(Bbox.from_extents(l, b, r, t)) kw = {} if (idx != 0): kw['ylabel'] = '' rasters.plotAvgFiringRate(ps.v[idx], spaceType='velocity', noise_sigma=noise_sigma, popType='E', r=rasterRC[idx][0], c=rasterRC[idx][1], color='red', ylabelPos=self.config['vel_rasters']['ylabelPos'], tLimits=self.config['vel_rasters']['tLimits'], trialNum=self.config['vel_rasters']['trialNum'], sigmaTitle=False, ax=ax, **kw) fname = output_dir + "/velocity_rate_e{0}.pdf".format(noise_sigma) fig.savefig(fname, dpi=300, transparent=transparent) plt.close() # I cells fig = self._get_final_fig(self.myc['fig_size']) ax = fig.add_axes(Bbox.from_extents(l, b, r, t)) kw = {} if (idx != 0): kw['ylabel'] = '' rasters.plotAvgFiringRate(ps.v[idx], spaceType='velocity', noise_sigma=noise_sigma, popType='I', r=rasterRC[idx][0], c=rasterRC[idx][1], color='blue', ylabelPos=self.config['vel_rasters']['ylabelPos'], tLimits=self.config['vel_rasters']['tLimits'], trialNum=self.config['vel_rasters']['trialNum'], sigmaTitle=False, ax=ax, **kw) fname = output_dir + "/velocity_rate_i{0}.pdf".format(noise_sigma) fig.savefig(fname, dpi=300, transparent=transparent) plt.close()
def _find_best_position(self, width, height, renderer, consider=None): """ Determine the best location to place the legend. `consider` is a list of (x, y) pairs to consider as a potential lower-left corner of the legend. All are display coords. """ # should always hold because function is only called internally assert self.isaxes verts, bboxes, lines = self._auto_legend_data() bbox = Bbox.from_bounds(0, 0, width, height) consider = [self._get_anchored_bbox(x, bbox, self.get_bbox_to_anchor(), renderer) for x in range(1, len(self.codes))] #tx, ty = self.legendPatch.get_x(), self.legendPatch.get_y() candidates = [] for l, b in consider: legendBox = Bbox.from_bounds(l, b, width, height) badness = 0 badness = legendBox.count_contains(verts) badness += legendBox.count_overlaps(bboxes) for line in lines: if line.intersects_bbox(legendBox): badness += 1 ox, oy = l, b if badness == 0: return ox, oy candidates.append((badness, (l, b))) # rather than use min() or list.sort(), do this so that we are assured # that in the case of two equal badnesses, the one first considered is # returned. # NOTE: list.sort() is stable.But leave as it is for now. -JJL minCandidate = candidates[0] for candidate in candidates: if candidate[0] < minCandidate[0]: minCandidate = candidate ox, oy = minCandidate[1] return ox, oy
def _compute_bbox(self, fig, kw): """ Compute the tight bounding box for each figure once, reducing number of required canvas draw calls from N*2 to N+1 as a function of the number of frames. Tight bounding box computing code here mirrors: matplotlib.backend_bases.FigureCanvasBase.print_figure as it hasn't been factored out as a function. """ fig_id = id(fig) if kw['bbox_inches'] == 'tight': if not fig_id in MPLRenderer.drawn: fig.set_dpi(self.dpi) fig.canvas.draw() renderer = fig._cachedRenderer bbox_inches = fig.get_tightbbox(renderer) bbox_artists = kw.pop("bbox_extra_artists", []) bbox_artists += fig.get_default_bbox_extra_artists() bbox_filtered = [] for a in bbox_artists: bbox = a.get_window_extent(renderer) if isinstance(bbox, tuple): continue if a.get_clip_on(): clip_box = a.get_clip_box() if clip_box is not None: bbox = Bbox.intersection(bbox, clip_box) clip_path = a.get_clip_path() if clip_path is not None and bbox is not None: clip_path = clip_path.get_fully_transformed_path() bbox = Bbox.intersection(bbox, clip_path.get_extents()) if bbox is not None and (bbox.width != 0 or bbox.height != 0): bbox_filtered.append(bbox) if bbox_filtered: _bbox = Bbox.union(bbox_filtered) trans = Affine2D().scale(1.0 / self.dpi) bbox_extra = TransformedBbox(_bbox, trans) bbox_inches = Bbox.union([bbox_inches, bbox_extra]) pad = plt.rcParams['savefig.pad_inches'] bbox_inches = bbox_inches.padded(pad) MPLRenderer.drawn[fig_id] = bbox_inches kw['bbox_inches'] = bbox_inches else: kw['bbox_inches'] = MPLRenderer.drawn[fig_id] return kw
def set_bbox_to_anchor(self, bbox, transform=None): """ set the bbox that the legend will be anchored. *bbox* can be a BboxBase instance, a tuple of [left, bottom, width, height] in the given transform (normalized axes coordinate if None), or a tuple of [left, bottom] where the width and height will be assumed to be zero. """ if bbox is None: self._bbox_to_anchor = None return elif isinstance(bbox, BboxBase): self._bbox_to_anchor = bbox else: try: l = len(bbox) except TypeError: raise ValueError("Invalid argument for bbox : %s" % str(bbox)) if l == 2: bbox = [bbox[0], bbox[1], 0, 0] self._bbox_to_anchor = Bbox.from_bounds(*bbox) if transform is None: transform = BboxTransformTo(self.parent.bbox) self._bbox_to_anchor = TransformedBbox(self._bbox_to_anchor, transform)
def get_tightbbox(self, renderer): if not self.get_visible(): return self._axis_artist_helper.update_lim(self.axes) dpi_cor = renderer.points_to_pixels(1.) self.dpi_transform.clear().scale(dpi_cor, dpi_cor) bb = [] self._update_ticks(renderer) bb.extend(self.major_ticklabels.get_window_extents(renderer)) bb.extend(self.minor_ticklabels.get_window_extents(renderer)) self._update_label(renderer) bb.append(self.label.get_window_extent(renderer)) bb.append(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
def get_tightbbox(self, renderer, call_axes_locator=True): bb0 = super(Axes, self).get_tightbbox(renderer, call_axes_locator) if not self._axisline_on: return bb0 bb = [bb0] for axisline in self._axislines.values(): if not axisline.get_visible(): continue bb.append(axisline.get_tightbbox(renderer)) # if axisline.label.get_visible(): # bb.append(axisline.label.get_window_extent(renderer)) # if axisline.major_ticklabels.get_visible(): # bb.extend(axisline.major_ticklabels.get_window_extents(renderer)) # if axisline.minor_ticklabels.get_visible(): # bb.extend(axisline.minor_ticklabels.get_window_extents(renderer)) # if axisline.major_ticklabels.get_visible() or \ # axisline.minor_ticklabels.get_visible(): # bb.append(axisline.offsetText.get_window_extent(renderer)) #bb.extend([c.get_window_extent(renderer) for c in artists \ # if c.get_visible()]) _bbox = Bbox.union([b for b in bb if b and (b.width!=0 or b.height!=0)]) return _bbox
def _set_lim_and_transforms(self): PolarAxes._set_lim_and_transforms(self) self.transProjection = self.NorthPolarTransform() self.axisProjection = self.NorthPolarAxisTransform() self.transData = ( Affine2D().scale(numpy.pi/180.0, 1.0/90.0) + self.transScale + self.transProjection + (self.transProjectionAffine + self.transAxes)) self._xaxis_pretransform = ( Affine2D().scale(1.0, 1.0) ) self._xaxis_transform = ( self._xaxis_pretransform + self.axisProjection + self.PolarAffine(IdentityTransform(), Bbox.unit()) + self.transAxes) self._xaxis_text1_transform = ( self._theta_label1_position + self._xaxis_transform) self._yaxis_transform = ( Affine2D().scale(numpy.pi*2.0, 1.0) + self.transScale + self.axisProjection + (self.transProjectionAffine + self.transAxes)) self._yaxis_text1_transform = ( self._r_label1_position + Affine2D().translate(0.0, -0.051) + self._yaxis_transform)
def zoom_nodes(self, nodes, border=1.2): y0, y1 = self.get_ylim(); x0, x1 = self.get_xlim() y0 = max(0, y0); y1 = min(1, y1) n2c = self.n2c v = [ n2c[n] for n in nodes ] ymin = min([ c.y for c in v ]) ymax = max([ c.y for c in v ]) xmin = min([ c.x for c in v ]) xmax = max([ c.x for c in v ]) bb = Bbox(((xmin,ymin), (xmax, ymax))) # convert data coordinates to display coordinates transform = self.transData.transform disp_bb = [Bbox(transform(bb))] disp_bb = Bbox.union(disp_bb).expanded(border, border) # convert back to data coordinates points = self.transData.inverted().transform(disp_bb) x0, x1 = points[:,0] y0, y1 = points[:,1] self.set_xlim(x0, x1) self.set_ylim(y0, y1) self.draw_labels()
def _set_lim_and_transforms(self): self.transAxes = BboxTransformTo(self.bbox) self.transScale = TransformWrapper(IdentityTransform()) self.transProjection = self.PolarTransform() self.transProjectionAffine = self.PolarAffine(self.transScale, self.viewLim) self.transData = self.transScale + self.transProjection + \ (self.transProjectionAffine + self.transAxes) self._xaxis_transform = ( self.transProjection + self.PolarAffine(IdentityTransform(), Bbox.unit()) + self.transAxes) self._theta_label1_position = Affine2D().translate(0.0, 1.1) self._xaxis_text1_transform = ( self._theta_label1_position + self._xaxis_transform) self._theta_label2_position = Affine2D().translate(0.0, 1.0 / 1.1) self._xaxis_text2_transform = ( self._theta_label2_position + self._xaxis_transform) self._yaxis_transform = ( Affine2D().scale(npy.pi * 2.0, 1.0) + self.transData) self._r_label1_position = Affine2D().translate(22.5, self._rpad) self._yaxis_text1_transform = ( self._r_label1_position + Affine2D().scale(1.0 / 360.0, 1.0) + self._yaxis_transform ) self._r_label2_position = Affine2D().translate(22.5, self._rpad) self._yaxis_text2_transform = ( self._r_label2_position + Affine2D().scale(1.0 / 360.0, 1.0) + self._yaxis_transform )
def zoom_nodes(self, nodes, border=1.2): y0, y1 = self.get_ylim(); x0, x1 = self.get_xlim() y0 = max(0, y0); y1 = min(1, y1) n2c = self.n2c v = [ n2c[n] for n in nodes ] ymin = min([ c.y for c in v ]) ymax = max([ c.y for c in v ]) xmin = min([ c.x for c in v ]) xmax = max([ c.x for c in v ]) bb = Bbox(((xmin,ymin), (xmax, ymax))) # convert data coordinates to display coordinates transform = self.transData.transform disp_bb = [Bbox(transform(bb))] for n in nodes: if n.isleaf: txt = self.node2label[n] if txt.get_visible(): disp_bb.append(txt.get_window_extent()) disp_bb = Bbox.union(disp_bb).expanded(border, border) # convert back to data coordinates points = self.transData.inverted().transform(disp_bb) x0, x1 = points[:,0] y0, y1 = points[:,1] self.set_xlim(x0, x1) self.set_ylim(y0, y1)
def _set_lim_and_transforms(self): PolarAxes._set_lim_and_transforms(self) try: theta_position = self._theta_label1_position except AttributeError: theta_position = self.get_theta_offset() self.transProjection = self.GlobeCrossSectionTransform() self.transData = ( self.transScale + self.transProjection + (self.transProjectionAffine + self.transAxes)) self._xaxis_transform = ( self.transProjection + self.PolarAffine(IdentityTransform(), Bbox.unit()) + self.transAxes) self._xaxis_text1_transform = ( theta_position + self._xaxis_transform) self._yaxis_transform = ( Affine2D().scale(num.pi * 2.0, 1.0) + self.transData) try: rlp = getattr(self, '_r_label1_position') except AttributeError: rlp = getattr(self, '_r_label_position') self._yaxis_text1_transform = ( rlp + Affine2D().scale(1.0 / 360.0, 1.0) + self._yaxis_transform)
def _offset(w, h, xd, yd, renderer, fontsize=fontsize, self=self): bbox = Bbox.from_bounds(0, 0, w, h) borderpad = self.borderpad * fontsize bbox_to_anchor = self.get_bbox_to_anchor() x0, y0 = self._get_anchored_bbox(self.loc, bbox, bbox_to_anchor, borderpad) return x0 + xd, y0 + yd
def zoom_effect01(ax1, ax2, xmin, xmax, **kwargs): u""" ax1 : the main axes ax1 : the zoomed axes (xmin,xmax) : the limits of the colored area in both plot axes. connect ax1 & ax2. The x-range of (xmin, xmax) in both axes will be marked. The keywords parameters will be used ti create patches. """ trans1 = blended_transform_factory(ax1.transData, ax1.transAxes) trans2 = blended_transform_factory(ax2.transData, ax2.transAxes) bbox = Bbox.from_extents(xmin, 0, xmax, 1) mybbox1 = TransformedBbox(bbox, trans1) mybbox2 = TransformedBbox(bbox, trans2) prop_patches=kwargs.copy() prop_patches["ec"]="none" prop_patches["alpha"]=0.2 c1, c2, bbox_patch1, bbox_patch2, p = \ connect_bbox(mybbox1, mybbox2, loc1a=3, loc2a=2, loc1b=4, loc2b=1, prop_lines=kwargs, prop_patches=prop_patches) ax1.add_patch(bbox_patch1) ax2.add_patch(bbox_patch2) ax2.add_patch(c1) ax2.add_patch(c2) ax2.add_patch(p) return c1, c2, bbox_patch1, bbox_patch2, p
def test_text_with_arrow_annotation_get_window_extent(): headwidth = 21 fig, ax = plt.subplots(dpi=100) txt = ax.text(s='test', x=0, y=0) ann = ax.annotate( 'test', xy=(0.0, 50.0), xytext=(50.0, 50.0), xycoords='figure pixels', arrowprops={ 'facecolor': 'black', 'width': 2, 'headwidth': headwidth, 'shrink': 0.0}) plt.draw() renderer = fig.canvas.renderer # bounding box of text text_bbox = txt.get_window_extent(renderer=renderer) # bounding box of annotation (text + arrow) bbox = ann.get_window_extent(renderer=renderer) # bounding box of arrow arrow_bbox = ann.arrow.get_window_extent(renderer) # bounding box of annotation text ann_txt_bbox = Text.get_window_extent(ann) # make sure annotation with in 50 px wider than # just the text eq_(bbox.width, text_bbox.width + 50.0) # make sure the annotation text bounding box is same size # as the bounding box of the same string as a Text object eq_(ann_txt_bbox.height, text_bbox.height) eq_(ann_txt_bbox.width, text_bbox.width) # compute the expected bounding box of arrow + text expected_bbox = Bbox.union([ann_txt_bbox, arrow_bbox]) assert_almost_equal(bbox.height, expected_bbox.height)
def connect_bbox(bbox1, bbox2, loc1, loc2=None): if isinstance(bbox1, Rectangle): transform = bbox1.get_transfrom() bbox1 = Bbox.from_bounds(0, 0, 1, 1) bbox1 = TransformedBbox(bbox1, transform) if isinstance(bbox2, Rectangle): transform = bbox2.get_transform() bbox2 = Bbox.from_bounds(0, 0, 1, 1) bbox2 = TransformedBbox(bbox2, transform) if loc2 is None: loc2 = loc1 x1, y1 = BboxConnector.get_bbox_edge_pos(bbox1, loc1) x2, y2 = BboxConnector.get_bbox_edge_pos(bbox2, loc2) verts = [[x1, y1], [x2,y2]] codes = [Path.MOVETO, Path.LINETO] return Path(verts, codes)
def plot(self, *args, **kwargs): ps = self.env.ps output_dir = self.config['output_dir'] l, b, r, t = self.myc['bbox'] transparent = self.myc['transparent'] tLimits = [2.75e3, 2.875e3] # ms trialNum = 0 for idx, noise_sigma in enumerate(ps.noise_sigmas): fig = self._get_final_fig(self.myc['fig_size']) ax = fig.add_axes(Bbox.from_extents(l, b, r, t)) kw = dict(scaleBar=None) if idx == 2: kw['scaleBar'] = 25 rasters.EIRaster(ps.v[idx], noise_sigma=noise_sigma, spaceType='velocity', r=rasterRC[idx][0], c=rasterRC[idx][1], ylabelPos=self.myc['ylabelPos'], tLimits=tLimits, trialNum=trialNum, sigmaTitle=False, ann_EI=True, scaleX=0.75, scaleY=-0.15, ylabel='', yticks=False, **kw) fname = output_dir + "/velocity_raster_zooms{0}.png" fig.savefig(fname.format(int(noise_sigma)), dpi=300, transparent=transparent) plt.close()
def plot(self, *args, **kwargs): ps = self.env.ps output_dir = self.config['output_dir'] logger.info("Plotting rasters") for idx, noise_sigma in enumerate(ps.noise_sigmas): logger.info(" Rasters: %d pA", noise_sigma) fig = self._get_final_fig(self.myc['fig_size']) l, b, r, t = self.myc['bbox'] ax = fig.add_axes(Bbox.from_extents(l, b, r, t)) kw = dict(scaleBar=None) if (idx != 0): kw['ylabel'] = '' kw['yticks'] = False if idx == 2: kw['scaleBar'] = 125 rasters.EIRaster(ps.v[idx], noise_sigma=noise_sigma, spaceType='velocity', r=rasterRC[idx][0], c=rasterRC[idx][1], ylabelPos=self.config['vel_rasters']['ylabelPos'], tLimits=self.config['vel_rasters']['tLimits'], trialNum=self.config['vel_rasters']['trialNum'], ann_EI=True, scaleX=0.85, scaleY=-0.15, **kw) fname = output_dir + "/velocity_raster{0}.png" fig.savefig(fname.format(int(noise_sigma)), dpi=300, transparent=self.myc['transparent']) plt.close()
def __init__(self, width, height, dpi): if __debug__: verbose.report('RendererAgg.__init__', 'debug-annoying') RendererBase.__init__(self) self.texd = maxdict(50) # a cache of tex image rasters self._fontd = maxdict(50) self.dpi = dpi self.width = width self.height = height if __debug__: verbose.report('RendererAgg.__init__ width=%s, height=%s'%(width, height), 'debug-annoying') self._renderer = _RendererAgg(int(width), int(height), dpi, debug=False) if __debug__: verbose.report('RendererAgg.__init__ _RendererAgg done', 'debug-annoying') #self.draw_path = self._renderer.draw_path # see below self.draw_markers = self._renderer.draw_markers self.draw_path_collection = self._renderer.draw_path_collection self.draw_quad_mesh = self._renderer.draw_quad_mesh self.draw_image = self._renderer.draw_image self.copy_from_bbox = self._renderer.copy_from_bbox self.tostring_rgba_minimized = self._renderer.tostring_rgba_minimized self.mathtext_parser = MathTextParser('Agg') self.bbox = Bbox.from_bounds(0, 0, self.width, self.height) if __debug__: verbose.report('RendererAgg.__init__ done', 'debug-annoying')
def plot(self, *args, **kwargs): ps = self.env.ps output_dir = self.config['output_dir'] iter_list = self.config['iter_list'] l, b, r, t = self.myc['bbox_rect'] for ns_idx, noise_sigma in enumerate(ps.noise_sigmas): fig = self._get_final_fig(self.myc['fig_size']) ax = fig.add_axes(Bbox.from_extents(l, b, r, t)) kwargs = dict() if ns_idx != 1: kwargs['xlabel'] = '' if ns_idx != 0: kwargs['ylabel'] = '' self.plotSlopes( ax, ps.v[ns_idx], self.myc['positions'][ns_idx], noise_sigma=noise_sigma, iterList=iter_list, color='blue', ivel_range=self.myc.get('ivel_range', None), g_ann=self.myc.get('g_ann', True), **kwargs) fname = (self.config['output_dir'] + "/velocity_slope_examples_{0}.pdf".format(int(noise_sigma))) plt.savefig(fname, dpi=300, transparent=True)
def setDirectory(self, rootPath, shape): super(BumpSweepWidget, self).setDirectory(rootPath, shape) sigmaBumpText = '$\sigma_{bump}^{-1}\ (neurons^{-1})$' self.cbar_kw.update(dict( label = sigmaBumpText, ticks = ti.MultipleLocator(0.1))) self.canvas.fig.clear() self.ax = self.canvas.fig.add_axes( Bbox.from_extents(self.sweepLeft, self.sweepBottom, self.sweepRight, self.sweepTop)) self.aggrData = aggr.AggregateBumpReciprocal(self.dataSpace, self.iterList, self.NTrials, tStart=self.bumpTStart) sweeps.plotSweep(self.aggrData, self.noise_sigma, sigmaTitle=False, cbar=True, cbar_kw=self.cbar_kw, ax=self.ax, picker=True) c = self.ax.collections if (len(c) != 1): raise RuntimeError("Something went wrong! len(c) != 1") self.dataCollection = c[0] self.canvas.draw() self.dataRenewed.emit(self.dataSpace)
# Timing tests -- print time per plot TIME_PY = 1 TIME_EXT = 1 ################# # Test Parameters ################# # Bounding box to use in testing ll_x = 320 ll_y = 240 ur_x = 640 ur_y = 480 BBOX = Bbox(Point(Value(ll_x), Value(ll_y)), Point(Value(ur_x), Value(ur_y))) # Number of iterations for timing NITERS = 25 ############################################################################### # # Testing framework # def time_loop(function, args): i = 0 start = time.time()
def FindMasks(flat_path,root_flat,flat_thres,SAVEPATH,binnx,binny): width=200./binnx masks=np.empty([4,2*ypixels/binny+ygap,xpixels/binnx])*0.0 y_arr=np.linspace(0,2*ypixels/binny+ygap,2*ypixels/binny+ygap) x_arr=np.linspace(0,xpixels/binnx,xpixels/binnx) X,Y=np.meshgrid(x_arr,y_arr) BOXES=np.array([]) print ' CHIP ALIGNMENT:' print '---------------------------------' print '| 6 | 5 | 8 | 7 |' print '---------------------------------' print '| 1 | 2 | 3 | 4 |' print '---------------------------------' for c in range(0,len(top_chip)): print ' ' print '------------------------------' print ' Working on chips', top_chip[c], '&', bot_chip[c] print '------------------------------' data_t=np.fliplr(((fits.open(flat_path+root_flat+str(int(top_chip[c]))+'.fits.gz'))[0].data) [0:ypixels/binny,0:xpixels/binnx]) data_b=np.flipud(((fits.open(flat_path+root_flat+str(int(bot_chip[c]))+'.fits.gz'))[0].data) [0:ypixels/binny,0:xpixels/binnx]) data=np.empty([2*ypixels/binny+ygap,xpixels/binnx])*np.nan data[0:ypixels/binny,:]=data_t data[ypixels/binny+ygap:,:]=data_b print ' -->> DATA STITCHED' fig,ax=plt.subplots(1,2,figsize=(6.,6.)) #plt.title('CHIPS'+str(int(top_chip[c]))+'&'+str(int(bot_chip[c]))) im=ax[0].imshow(np.log10(data),cmap=plt.cm.Greys_r) #im=ax[0].colorbar() cs=ax[0].contour(X,Y,data,levels=[flat_thres],color='yellow',linewidth=2.0) ax[0].set_title('FLATS DATA') paths=cs.collections[0].get_paths() for i in range(0,len(paths)): p0=(paths[i]) bbox=p0.get_extents() if np.abs((bbox.get_points()[0,0])-(bbox.get_points()[1,0]))> 190./binnx: middle_of_box=(bbox.get_points()[0,0]+bbox.get_points()[1,0])/2. #print 'BOX #',i #print ' ----> MIDDLE OF BOX:', middle_of_box #print ' ----> WIDTH actual:', np.abs(bbox.get_points()[0,0]-bbox.get_points()[1,0]) #print ' ----> LEFT OF BOX (actual, estimated)', bbox.get_points()[0,0],middle_of_box-width/2. #print ' ----> RIGHT OF BOX (actual, estimated)', bbox.get_points()[1,0],middle_of_box+width/2. #ax.add_patch(patches.PathPatch(p0, facecolor='none', ec='yellow', linewidth=2, zorder=50)) #plt.show(block=False) #bbox.get_points[0,0]=MIN_x, [0,1]=MIN_y, [1,0]=MAX_x, [1,1]=MAX_y x0,y0,x1,y1=middle_of_box-width/(2.),bbox.get_points()[0,1],middle_of_box+width/(2.),bbox.get_points()[1,1] if top_chip[c]==6: x0=x0 x1=x1 if top_chip[c]==5: x0=x0+(xpixels/binnx+xgap) x1=x1+(xpixels/binnx+xgap) if top_chip[c]==8: x0=x0+2.*(xpixels/binnx+xgap) x1=x1+2.*(xpixels/binnx+xgap) if top_chip[c]==7: x0=x0+3.*(xpixels/binnx+xgap) x1=x1+3.*(xpixels/binnx+xgap) BOXES_item=Bbox(np.array([[x0,y0],[x1,y1]])) BOXES=np.append(BOXES,BOXES_item) for y in range(0,2*ypixels/binny+ygap): if y>bbox.get_points()[0,1] and y<bbox.get_points()[1,1]: for x in range(0,xpixels/binnx): #if x>bbox.get_points()[0,0] and x<bbox.get_points()[1,0]: if x>middle_of_box-width/(2.) and x<middle_of_box+width/(2.): masks[c,y,x]=1.0 ax[1].imshow(masks[c,:,:], cmap=plt.cm.Greys_r, interpolation='none') ax[1].set_title('Generated Masks') plt.show(block=False) for x in range(ypixels/binny,ypixels/binny+ygap): masks[:,y,:]=np.nan #print BOXES BOXES=np.reshape(BOXES,(len(BOXES)/4,4)) #print mask_edges np.savez_compressed(SAVEPATH+'Masks.npz',Masks=masks,paths=paths,boxes=BOXES) return masks
def test_fill_facecolor(): fig, ax = plt.subplots(1, 5) fig.set_size_inches(5, 5) for i in range(1, 4): ax[i].yaxis.set_visible(False) ax[4].yaxis.tick_right() bbox = Bbox.from_extents(0, 0.4, 1, 0.6) # fill with blue by setting 'fc' field bbox1 = TransformedBbox(bbox, ax[0].transData) bbox2 = TransformedBbox(bbox, ax[1].transData) # set color to BboxConnectorPatch p = BboxConnectorPatch(bbox1, bbox2, loc1a=1, loc2a=2, loc1b=4, loc2b=3, ec="r", fc="b") p.set_clip_on(False) ax[0].add_patch(p) # set color to marked area axins = zoomed_inset_axes(ax[0], 1, loc='upper right') axins.set_xlim(0, 0.2) axins.set_ylim(0, 0.2) plt.gca().axes.get_xaxis().set_ticks([]) plt.gca().axes.get_yaxis().set_ticks([]) mark_inset(ax[0], axins, loc1=2, loc2=4, fc="b", ec="0.5") # fill with yellow by setting 'facecolor' field bbox3 = TransformedBbox(bbox, ax[1].transData) bbox4 = TransformedBbox(bbox, ax[2].transData) # set color to BboxConnectorPatch p = BboxConnectorPatch(bbox3, bbox4, loc1a=1, loc2a=2, loc1b=4, loc2b=3, ec="r", facecolor="y") p.set_clip_on(False) ax[1].add_patch(p) # set color to marked area axins = zoomed_inset_axes(ax[1], 1, loc='upper right') axins.set_xlim(0, 0.2) axins.set_ylim(0, 0.2) plt.gca().axes.get_xaxis().set_ticks([]) plt.gca().axes.get_yaxis().set_ticks([]) mark_inset(ax[1], axins, loc1=2, loc2=4, facecolor="y", ec="0.5") # fill with green by setting 'color' field bbox5 = TransformedBbox(bbox, ax[2].transData) bbox6 = TransformedBbox(bbox, ax[3].transData) # set color to BboxConnectorPatch p = BboxConnectorPatch(bbox5, bbox6, loc1a=1, loc2a=2, loc1b=4, loc2b=3, ec="r", color="g") p.set_clip_on(False) ax[2].add_patch(p) # set color to marked area axins = zoomed_inset_axes(ax[2], 1, loc='upper right') axins.set_xlim(0, 0.2) axins.set_ylim(0, 0.2) plt.gca().axes.get_xaxis().set_ticks([]) plt.gca().axes.get_yaxis().set_ticks([]) mark_inset(ax[2], axins, loc1=2, loc2=4, color="g", ec="0.5") # fill with green but color won't show if set fill to False bbox7 = TransformedBbox(bbox, ax[3].transData) bbox8 = TransformedBbox(bbox, ax[4].transData) # BboxConnectorPatch won't show green p = BboxConnectorPatch(bbox7, bbox8, loc1a=1, loc2a=2, loc1b=4, loc2b=3, ec="r", fc="g", fill=False) p.set_clip_on(False) ax[3].add_patch(p) # marked area won't show green axins = zoomed_inset_axes(ax[3], 1, loc='upper right') axins.set_xlim(0, 0.2) axins.set_ylim(0, 0.2) axins.get_xaxis().set_ticks([]) axins.get_yaxis().set_ticks([]) mark_inset(ax[3], axins, loc1=2, loc2=4, fc="g", ec="0.5", fill=False)
def draw_grid(*, max_row: int, max_column: int, clued_locations: Set[Location], location_to_entry: Dict[Location, str], location_to_clue_numbers: Dict[Location, Sequence[str]], top_bars: Set[Location], left_bars: Set[Location], shading: Dict[Location, str] = {}, rotation: Dict[Location, str] = {}, circles: Set[Location] = set(), **args: Any) -> None: _axes = args.get('axes') if _axes: axes = cast(Axes, _axes) else: _, axes = plt.subplots(1, 1, figsize=(8, 11), dpi=100) # Set (1,1) as the top-left corner, and (max_column, max_row) as the bottom right. axes.axis([1, max_column, max_row, 1]) axes.axis('equal') axes.axis('off') # Fill in the shaded squares for row, column in itertools.product(range(1, max_row), range(1, max_column)): if (row, column) in shading: color = shading[row, column] axes.add_patch( patches.Rectangle((column, row), 1, 1, facecolor=color, linewidth=0)) # elif (row, column) not in clued_locations: # axes.add_patch(patches.Rectangle((column, row), 1, 1, facecolor='black', linewidth=0)) for row, column in itertools.product(range(1, max_row + 1), range(1, max_column + 1)): this_exists = (row, column) in clued_locations left_exists = (row, column - 1) in clued_locations above_exists = (row - 1, column) in clued_locations if this_exists or left_exists: width = 5 if this_exists != left_exists or ( row, column) in left_bars else None axes.plot([column, column], [row, row + 1], 'black', linewidth=width) if this_exists or above_exists: width = 5 if this_exists != above_exists or ( row, column) in top_bars else None axes.plot([column, column + 1], [row, row], 'black', linewidth=width) if (row, column) in shading: color = shading[row, column] axes.add_patch( patches.Rectangle((column, row), 1, 1, facecolor=color, linewidth=0)) for row, column in circles: circle = plt.Circle((column + .5, row + .5), radius=.4, linewidth=2, fill=False, facecolor='black') axes.add_patch(circle) scaled_box = Bbox.unit().transformed(axes.transData - axes.figure.dpi_scale_trans) inches_per_data = min(abs(scaled_box.width), abs(scaled_box.height)) points_per_data = 72 * inches_per_data # Fill in the values for (row, column), entry in location_to_entry.items(): axes.text(column + 1 / 2, row + 1 / 2, entry, fontsize=points_per_data / 2, fontweight='bold', fontfamily="sans-serif", verticalalignment='center', horizontalalignment='center', rotation=rotation.get((row, column), 0)) # Fill in the clue numbers for (row, column), clue_numbers in location_to_clue_numbers.items(): font_info = dict(fontsize=points_per_data / 4, fontfamily="sans-serif") for index, text in enumerate(clue_numbers): if index == 0: axes.text(column + .05, row + .05, text, verticalalignment='top', horizontalalignment='left', **font_info) elif index == 1: axes.text(column + .95, row + .05, text, verticalalignment='top', horizontalalignment='right', **font_info) elif index == 2: axes.text(column + .05, row + .95, text, verticalalignment='bottom', horizontalalignment='left', **font_info) elif index == 3: axes.text(column + .95, row + .95, text, verticalalignment='bottom', horizontalalignment='right', **font_info) if not _axes: plt.show()
def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, unsampled=False, round_to_pixel_border=True): """ Normalize, rescale and color the image `A` from the given in_bbox (in data space), to the given out_bbox (in pixel space) clipped to the given clip_bbox (also in pixel space), and magnified by the magnification factor. `A` may be a greyscale image (MxN) with a dtype of `float32`, `float64`, `uint16` or `uint8`, or an RGBA image (MxNx4) with a dtype of `float32`, `float64`, or `uint8`. If `unsampled` is True, the image will not be scaled, but an appropriate affine transformation will be returned instead. If `round_to_pixel_border` is True, the output image size will be rounded to the nearest pixel boundary. This makes the images align correctly with the axes. It should not be used in cases where you want exact scaling, however, such as FigureImage. Returns the resulting (image, x, y, trans), where (x, y) is the upper left corner of the result in pixel space, and `trans` is the affine transformation from the image to pixel space. """ if A is None: raise RuntimeError('You must first set the image' ' array or the image attribute') clipped_bbox = Bbox.intersection(out_bbox, clip_bbox) if clipped_bbox is None: return None, 0, 0, None out_width_base = clipped_bbox.width * magnification out_height_base = clipped_bbox.height * magnification if out_width_base == 0 or out_height_base == 0: return None, 0, 0, None if self.origin == 'upper': # Flip the input image using a transform. This avoids the # problem with flipping the array, which results in a copy # when it is converted to contiguous in the C wrapper t0 = Affine2D().translate(0, -A.shape[0]).scale(1, -1) else: t0 = IdentityTransform() t0 += (Affine2D().scale(in_bbox.width / A.shape[1], in_bbox.height / A.shape[0]).translate(in_bbox.x0, in_bbox.y0) + self.get_transform()) t = (t0 + Affine2D().translate(-clipped_bbox.x0, -clipped_bbox.y0).scale( magnification, magnification)) # So that the image is aligned with the edge of the axes, we want # to round up the output width to the next integer. This also # means scaling the transform just slightly to account for the # extra subpixel. if (t.is_affine and round_to_pixel_border and (out_width_base % 1.0 != 0.0 or out_height_base % 1.0 != 0.0)): out_width = int(ceil(out_width_base) + 1) out_height = int(ceil(out_height_base) + 1) extra_width = (out_width - out_width_base) / out_width_base extra_height = (out_height - out_height_base) / out_height_base t += Affine2D().scale(1.0 + extra_width, 1.0 + extra_height) else: out_width = int(out_width_base) out_height = int(out_height_base) if not unsampled: created_rgba_mask = False if A.ndim == 2: A = self.norm(A) # If the image is greyscale, convert to RGBA with the # correct alpha channel for resizing rgba = np.empty((A.shape[0], A.shape[1], 4), dtype=A.dtype) rgba[..., 0:3] = np.expand_dims(A, 2) if A.dtype.kind == 'f': rgba[..., 3] = ~A.mask else: rgba[..., 3] = np.where(A.mask, 0, np.iinfo(A.dtype).max) A = rgba output = np.zeros((out_height, out_width, 4), dtype=A.dtype) alpha = 1.0 created_rgba_mask = True elif A.ndim == 3: # Always convert to RGBA, even if only RGB input if A.shape[2] == 3: A = _rgb_to_rgba(A) elif A.shape[2] != 4: raise ValueError("Invalid dimensions, got %s" % (A.shape, )) output = np.zeros((out_height, out_width, 4), dtype=A.dtype) alpha = self.get_alpha() if alpha is None: alpha = 1.0 else: raise ValueError("Invalid dimensions, got %s" % (A.shape, )) _image.resample(A, output, t, _interpd_[self.get_interpolation()], self.get_resample(), alpha, self.get_filternorm() or 0.0, self.get_filterrad() or 0.0) if created_rgba_mask: # Convert back to a masked greyscale array so # colormapping works correctly output = np.ma.masked_array(output[..., 0], output[..., 3] < 0.5) output = self.to_rgba(output, bytes=True, norm=False) # Apply alpha *after* if the input was greyscale without a mask if A.ndim == 2 or created_rgba_mask: alpha = self.get_alpha() if alpha is not None and alpha != 1.0: alpha_channel = output[:, :, 3] alpha_channel[:] = np.asarray( np.asarray(alpha_channel, np.float32) * alpha, np.uint8) else: if self._imcache is None: self._imcache = self.to_rgba(A, bytes=True, norm=(A.ndim == 2)) output = self._imcache # Subset the input image to only the part that will be # displayed subset = TransformedBbox(clip_bbox, t0.frozen().inverted()).frozen() output = output[int(max(subset.ymin, 0) ):int(min(subset.ymax + 1, output.shape[0])), int(max(subset.xmin, 0) ):int(min(subset.xmax + 1, output.shape[1]))] t = Affine2D().translate(int(max(subset.xmin, 0)), int(max(subset.ymin, 0))) + t return output, clipped_bbox.x0, clipped_bbox.y0, t
axis2.contour(X2,Y2,Z2, zdir='z', offset=-1, cmap='inferno') axis2.set_title('Non-convex function') for axis in [axis1, axis2]: axis.set_proj_type('ortho') axis.xaxis.pane.fill = False axis.yaxis.pane.fill = False axis.zaxis.pane.fill = False axis.grid(False) axis.set_xticklabels([]) axis.set_yticklabels([]) axis.set_zticklabels([]) axis.yaxis._axinfo['label']['space_factor'] = 1.0 axis.view_init(20, 30) fig.tight_layout(pad=0) fig.savefig('/home/abdeljalil/Workspace/MasterThesis/figures/gradient_descent.pdf', bbox_inches=Bbox([[0, .15], [6, 2.6]])) plt.show() #%% Plot [French] fig = plt.figure(figsize=(6,2.5)) axis1 = fig.add_subplot(1,2,1, projection='3d') axis1.plot_surface(X1,Y1,Z1, cmap='inferno') axis1.contour(X1,Y1,Z1, zdir='z', offset=0, cmap='inferno') axis1.set_title('Fonction convexe') axis2 = fig.add_subplot(1,2,2, projection='3d') axis2.plot_surface(X2,Y2,Z2, cmap='inferno') axis2.contour(X2,Y2,Z2, zdir='z', offset=-1, cmap='inferno') axis2.set_title('Fonction non convexe') for axis in [axis1, axis2]:
import numpy as np import matplotlib.pyplot as plt from matplotlib.transforms import Bbox from matplotlib.path import Path # Fixing random state for reproducibility np.random.seed(19680801) left, bottom, width, height = (-1, -1, 2, 2) rect = plt.Rectangle((left, bottom), width, height, facecolor="#aaaaaa") fig, ax = plt.subplots() ax.add_patch(rect) bbox = Bbox.from_bounds(left, bottom, width, height) for i in range(12): vertices = (np.random.random((2, 2)) - 0.5) * 6.0 path = Path(vertices) if path.intersects_bbox(bbox): color = 'r' else: color = 'b' ax.plot(vertices[:, 0], vertices[:, 1], color=color) plt.show()
def highlight_artist(self, val, artist=None): from ifigure.matplotlib_mod.art3d_gl import Poly3DCollectionGL from ifigure.matplotlib_mod.art3d_gl import Line3DCollectionGL figure = self.get_figpage()._artists[0] ax = self.get_figaxes() if artist is None: alist = self._artists else: alist = artist if val == True: if self._parent is None: return container = self.get_container() if container is None: return if isinstance(alist[0], Poly3DCollectionGL): hl = alist[0].add_hl_mask() for item in hl: alist[0].figobj_hl.append(item) else: de = self.get_data_extent() x = (de[0], de[1], de[1], de[0], de[0]) y = (de[2], de[2], de[3], de[3], de[2]) facecolor = 'k' if isinstance(alist[0], Poly3DCollectionGL): hl = alist[0].make_hl_artist(container) facecolor = 'none' self._hit_path = None elif isinstance(alist[0], Line3DCollectionGL): hl = alist[0].make_hl_artist(container) facecolor = 'none' self._hit_path = None else: hl = container.plot(x, y, marker='s', color='k', linestyle='None', markerfacecolor='None', markeredgewidth=0.5, scalex=False, scaley=False) for item in hl: alist[0].figobj_hl.append(item) if self._hit_path is not None: v = self._hit_path.vertices hl = container.plot(v[:, 0], v[:, 1], marker='s', color='k', linestyle='None', markerfacecolor='None', markeredgewidth=0.5, scalex=False, scaley=False) for item in hl: alist[0].figobj_hl.append(item) hlp = Rectangle((de[0], de[2]), de[1]-de[0], de[3]-de[2], alpha=0.3, facecolor=facecolor, figure=figure, transform=container.transData) if ax is not None: x0, y0 = ax._artists[0].transAxes.transform((0, 0)) x1, y1 = ax._artists[0].transAxes.transform((1, 1)) bbox = Bbox([[x0, y0], [x1, y1]]) hlp.set_clip_box(bbox) hlp.set_clip_on(True) figure.patches.append(hlp) alist[0].figobj_hl.append(hlp) else: for a in alist: if len(a.figobj_hl) == 0: continue for hl in a.figobj_hl[:-1]: hl.remove() if isinstance(alist[0], Poly3DCollectionGL): a.figobj_hl[-1].remove() else: figure.patches.remove(a.figobj_hl[-1]) a.figobj_hl = []
class GlassMapFigure(Figure): """Matplotlib implementation of an optical glass map. Attributes: glass_db: an instance of :class:`~.GlassMapDB` db_display: list of boolean flags to control catalog display hover_glass_names: if True display glass name list under cursor plot_display_type: controls the type of data display. Supported types are: - "Refractive Index" - "Partial Dispersion" - "Buchdahl Coefficients" - "Buchdahl Dispersion Coefficients" refresh_gui: an optional function called when a glass is picked pick_list: list of glasses selected by a mouse click. The on_pick fct accumulates the pick_list. Filled with: catalog_name, glass_name, nd, vd, PCd """ dsc = [ (56 / 255, 142 / 255, 142 / 255), # sgi teal (133 / 255, 133 / 255, 133 / 255), # grey 52 (113 / 255, 113 / 255, 198 / 255), # sgi slateblue (102 / 255, 205 / 255, 0), # chartreuse 3 (255 / 255, 114 / 255, 86 / 255), # coral 1 (255 / 255, 165 / 255, 0 / 255), # orange 1 (139 / 255, 139 / 255, 131 / 255), # ivory 4 ] mkr = ['^', 'x', '2', 's', 'v', '+', '*', 'D', 'o'] home_bbox = Bbox(np.array([[95., 1.45], [20., 2.05]])) def __init__(self, glass_db, db_display=None, hover_glass_names=True, plot_display_type="Refractive Index", refresh_gui=None, **kwargs): """GlassMap figure initialization. """ super().__init__(**kwargs) self.refresh_gui = refresh_gui self.glass_db = glass_db num_catalogs = len(glass_db.catalogs) self.db_display = db_display if db_display else [True] * num_catalogs self.plot_display_type = plot_display_type self.partials = ('F', 'd') self.hover_glass_names = hover_glass_names self.needsClear = True self.pick_list = [] self.event_dict = {} self.update_data() def connect_events(self, action_dict=None): 'connect to all the events we need' if action_dict is None: action_dict = { 'motion_notify_event': self.on_hover, # 'button_press_event': self.on_press, 'pick_event': self.on_pick, } self.callback_ids = [] for event, action in action_dict.items(): self.event_dict[event] = action cid = self.canvas.mpl_connect(event, action) self.callback_ids.append(cid) def disconnect_events(self): 'disconnect all the stored connection ids' for clbk in self.callback_ids: self.canvas.mpl_disconnect(clbk) self.callback_ids = None event_dict, self.event_dict = self.event_dict, {} return event_dict def get_display_label(self): return self.plot_display_type def refresh(self, **kwargs): """Call update_data() followed by plot(), return self. Args: kwargs: keyword arguments are passed to update_data Returns: self (class Figure) so scripting envs will auto display results """ self.update_data(**kwargs) self.plot() return self def update_data(self, **kwargs): """Fill in raw_data array. The raw_data attribute is a list over catalogs. Each catalog has an item consisting of the catalog name and a tuple of vectors: n, v, p, coefs0, coefs1, glass_names """ self.rawData = [] ctyp = ("disp_coefs" if self.plot_display_type == "Buchdahl Dispersion Coefficients" else None) for i, display in enumerate(self.db_display): gmap_data = self.glass_db.get_data_at(i, ctype=ctyp, partials=self.partials) n, v, p, coefs0, coefs1, glass_names = gmap_data catalog_name = self.glass_db.get_data_set_label_at(i) self.rawData.append( [catalog_name, (n, v, p, coefs0, coefs1, glass_names)]) return self def update_axis_limits(self, bbox): self.ax.set_xlim(bbox[0][0], bbox[1][0]) self.ax.set_ylim(bbox[0][1], bbox[1][1]) def draw_axes(self): self.ax.grid(True) if hasattr(self, 'header'): self.ax.set_title(self.header, pad=10.0, fontsize=18) if hasattr(self, 'x_label'): self.ax.set_xlabel(self.x_label) if hasattr(self, 'y_label'): self.ax.set_ylabel(self.y_label) def plot(self): try: self.ax.cla() except AttributeError: self.ax = self.add_subplot(1, 1, 1) if self.plot_display_type == "Refractive Index": self.x_label = r'$\mathrm{V_d}$' self.y_label = r'$\mathrm{n_d}$' xi = 1 yi = 0 self.draw_glass_polygons() elif self.plot_display_type == "Partial Dispersion": self.x_label = r'$\mathrm{V_d}$' self.y_label = r'$\mathrm{P_{%s-%s}}$' % self.partials xi = 1 yi = 2 elif self.plot_display_type == "Buchdahl Coefficients": self.x_label = r'$\mathrm{\nu_2}$' self.y_label = r'$\mathrm{\nu_1}$' xi = 4 yi = 3 elif self.plot_display_type == "Buchdahl Dispersion Coefficients": self.x_label = r'$\mathrm{\eta_2}$' self.y_label = r'$\mathrm{\eta_1}$' xi = 4 yi = 3 self.ax.set_title(self.get_display_label()) for i, display in enumerate(self.db_display): line = self.ax.plot( self.rawData[i][1][xi], self.rawData[i][1][yi], linestyle='None', marker='o', markersize=5, # linestyle='None', markersize=7, alpha=0.75, gid=i, picker=True, pickradius=5, color=self.dsc[i], # marker=self.mkr[i], fillstyle='none', label=self.rawData[i][0], visible=display) # set pickradius here because of a bug. Fixed in 3.3 line[0].set_pickradius(5.) if self.plot_display_type == "Refractive Index": # provide a default minimum area, and update view limits # accordingly viewLim = Bbox.union([self.home_bbox, self.ax.viewLim]) self.update_axis_limits(viewLim.get_points()) # set up interactive event handling # The pick events, one per artist, are sent before the sole button # press event actions = { 'button_press_event': self.on_press, 'pick_event': self.on_pick, } if self.hover_glass_names: actions['motion_notify_event'] = self.on_hover self.connect_events(action_dict=actions) # set up hover annotation if self.hover_glass_names: self.hover_list = self.ax.annotate( "", xy=(0, 0), xytext=(20, 20), textcoords="offset points", bbox=dict(boxstyle="round", fc="w"), arrowprops=dict(arrowstyle="->")) self.hover_list.set_visible(False) # draw remaining stuff, axes, legend... if xi == 1: self.ax.invert_xaxis() self.draw_axes() self.ax.legend() self.canvas.draw() return self def draw_glass_polygons(self): for glass, poly in gp.polygons.items(): rgb = gp.rgb[glass] p = Polygon(poly, closed=True, fc=util.rgb2mpl(rgb), ec='black', linewidth=1.0) self.ax.add_artist(p) def clear_pick_table(self): self.pick_list = [] self.needsClear = False # --- interactive actions def find_artists_at_location(self, event): """Returns a list of shapes in zorder at the event location.""" artists = [] for artist in self.ax.get_children(): inside, info = artist.contains(event) if inside: id = artist.get_gid() if id is not None: artists.append((artist, info, id)) return sorted(artists, key=lambda a: a[0].get_zorder(), reverse=True) def on_hover(self, event): vis = self.hover_list.get_visible() artists = self.find_artists_at_location(event) info_text = [] if len(artists) > 0: for a in artists: artist, info, cat = a if self.db_display[cat]: ind = info['ind'] cat_name = self.rawData[cat][0] n, v, p, coef0, coef1, glass_name = self.rawData[cat][1] for k in ind: text = glass_name[k] + ', ' + cat_name info_text.append(text) # Update annotation with glass list info_text = '\n'.join(info_text) self.hover_list.set_text(info_text) pos = event.xdata, event.ydata self.hover_list.xy = pos self.hover_list.get_bbox_patch().set_alpha(0.8) self.hover_list.set_visible(True) self.canvas.draw_idle() else: if vis: self.hover_list.set_visible(False) self.canvas.draw_idle() def on_pick(self, event): """ handle picking glasses under the cursor. One pick event for each catalog, extract selected glasses and add to pick_list """ logging.debug("on_pick: needsClear={}".format(self.needsClear)) if self.needsClear: self.clear_pick_table() line = event.artist cat = line.get_gid() if self.db_display[cat]: ind = event.ind cat_name = self.rawData[cat][0] n, v, p, coef0, coef1, glass_name = self.rawData[cat][1] for k in ind: glass = (cat_name, glass_name[k], n[k], v[k], p[k]) self.pick_list.append(glass) def on_press(self, event): """ handle mouse clicks within the diagram. The button press event is sent after the pick events; it will be sent in cases with no pick events, e.g. clicking in an empty area of the axes. The two cases are: - if there were pick events, needsClear will be False so that items from different artists can be accumulated in the pick_list. The press event signals no further item accumulation. Flip needsClear to True so the next pick or press event will clear the pick_list. - if there were no pick events, needsClear will be True. Call clear_pick_table to empty pick_list and reset needsClear to False. """ logging.debug("on_press: needsClear={}".format(self.needsClear)) if self.needsClear: # If needsClear is still set, there have been no pick events so # this is a click in an empty region of the plot. # Clear the pick table self.clear_pick_table() else: # on_press event happens after on_pick events. Set needsClear for # next on_pick, i.e. a new selection, to handle self.needsClear = True if self.refresh_gui is not None: self.refresh_gui() def updateVisibility(self, indx, state): self.ax.lines[indx].set_visible(state) self.canvas.draw()
def plot_map(ds, buffer=None, background='_default', imscale=6, gridlines=True, coastlines=True, scalebar=True, gridlines_kwargs={}): """ Show the boundary of the dataset on a visually appealing map. Parameters ---------- ds : xr.Dataset or xr.DataArray The dataset whose bounds to plot on the map. buffer : float, optional Margin around the bounds polygon to plot, relative to the polygon dimension. By default, add around 20% on each side. background : :class:`cartopy.io.img_tiles` image tiles, optional The basemap to plot in the background (default: Stamen terrain). If None, do not plot a background map. imscale : int, optional The zoom level of the background image (default: 6). gridlines : bool, optional Whether to plot gridlines (default: True). coastlines : bool, optional Whether to plot coastlines (default: True). scalebar : bool, optional Whether to add a scale bar (default: True). gridlines_kwargs : dict, optional Additional keyword arguments for gridlines_with_labels(). Returns ------- :class:`cartopy.mpl.geoaxes.GeoAxes` The corresponding GeoAxes object. """ if background == '_default': try: background = cimgt.Stamen('terrain-background') except AttributeError: # cartopy < 0.17.0 background = cimgt.StamenTerrain() # Get polygon shape # ----------------- geometry_data = shapely.geometry.box(*ds.nd.bounds) if buffer is None: buffer = 1.2 else: buffer += 1.0 buffered = shapely.affinity.scale(geometry_data, xfact=buffer, yfact=buffer) project = pyproj.Transformer.from_crs(ds.nd.crs, 'epsg:4326') b = shapely.ops.transform(project.transform, buffered).bounds extent = [b[0], b[2], b[1], b[3]] bb = Bbox.from_extents(extent) # Define Orthographic map projection # (centered at the polygon) # ---------------------------------- map_crs = _get_orthographic_projection(ds) proj4_params = map_crs.proj4_params if 'a' in proj4_params: # Some version of cartopy add the parameter 'a'. # For some reason, the CRS cannot be parsed by rasterio with # this parameter present. del proj4_params['a'] # Create figure # ------------- ax = plt.axes(xlim=(b[0], b[2]), ylim=(b[1], b[3]), projection=map_crs, aspect='equal', clip_box=bb) ax.set_global() ax.set_extent(extent, crs=ccrs.PlateCarree()) ax.apply_aspect() # Add additional map features # --------------------------- if background is not None: ax.add_image(background, imscale) if coastlines: color = 'black' if background is None else 'white' ax.coastlines(resolution='10m', color=color) if scalebar: # Determine optimal length scale = _get_scalebar_length(ax) scale_bar(ax, (0.05, 0.05), scale, linewidth=5, ha='center') # Add polygon # ----------- geometry_map = warp.get_geometry(ds, crs=proj4_params) ax.add_geometries([geometry_map], crs=map_crs, facecolor=(1, 0, 0, 0.2), edgecolor=(0, 0, 0, 1)) if gridlines: color = '0.5' if background is None else 'white' gridlines_with_labels(ax, color=color, **gridlines_kwargs) return ax
def event_plot(events, rowHeight=100): genes = numpy.unique( numpy.char.partition(events.rownames.astype(str), "_")[:, 0]) x = pandas.DataFrame(numpy.zeros((len(genes), events.shape[1]), dtype=int), index=numpy.array(genes), columns=events.colnames) fig = plt.gcf() bbox = Bbox([[0.8 * fig.dpi, 0.5 * fig.dpi], [(fig.get_figwidth() - 0.5) * fig.dpi, 0.3 * len(x) * fig.dpi]]) plt.axes(bbox.transformed(plt.gcf().transFigure.inverted()).bounds) for feature in events.rownames: gene, eventType = feature.split("_", 1) i = genes.searchsorted(gene) if eventType == "mut": shift = 0 elif eventType == "gain": shift = 1 elif eventType == "loss": shift = 2 x.values[i] |= events[[feature]].events[0].astype(int) << shift geneOrder = (x.values > 0).sum(1).argsort() sampleOrder = numpy.lexsort(x.values[geneOrder])[::-1] colours = matplotlib.colors.ListedColormap( ["#dddddd", "#377eb8", "#2ca25f", "#756bb1", "#de2d26", "#ff7f00"]) plt.imshow(x.values[geneOrder][:, sampleOrder], aspect="auto", interpolation="none", cmap=colours, origin="lower", vmin=0, vmax=5) plt.grid(ls="-", c="white", axis="x") plt.setp(plt.gca().spines.values(), color="#888888", alpha=0) for tic in plt.gca().xaxis.get_major_ticks(): tic.tick1On = tic.tick2On = False for tic in plt.gca().yaxis.get_major_ticks(): tic.tick1On = tic.tick2On = False try: plt.yticks(numpy.arange(len(x)), x.index[geneOrder]) except AttributeError: pass plt.gca().yaxis.set_minor_locator( matplotlib.ticker.FixedLocator( numpy.linspace(-0.5, len(x) - 0.5, x.shape[0] + 1))) plt.grid(ls="-", c="white", axis="y", lw=4, alpha=1, which="minor") plt.grid(ls="None", axis="y", which="major") for tic in plt.gca().yaxis.get_minor_ticks(): tic.tick1On = tic.tick2On = False plt.gcf().patch.set_facecolor("white") plt.xlim(0, x.ix[genes].any(0).sum())
def plotNSigmaNormals(mu=0, sigma=1, shift=1.5, SL=6, save=False, fs=(11.5, 4.5), resi=512, file_out='NsigmaNormal.png'): """ # mu = 0; sigma = 1 : mean and standard deviation # shift = 1.5 : for the plotting of the shifted distributions # SL=6 : |special limit point|; used to calculate the cdf at lsl and usl """ N = 100 x_majloc = 0.5 * sigma # :: base for the x-axis MultipleLocator # Compute the past-extreme location for arrow placement: lsl, usl = mu - SL * sigma, mu + SL * sigma # :: the '6-sigma' extremes beg = lsl - 0.75 # :: for x-axis range resizing end = usl + 0.75 # the last index of the dict value is used for extreme (SL=special limit) points labeling shift1 = '+{:.1f}\sigma'.format(shift) shift2 = '-{:.1f}\sigma'.format(shift) switch = { -1: ['b', '\mu-\sigma=', shift2], 0: ['g', '\mu=', 'unshifted'], 1: ['r', '\mu+\sigma=', shift1] } limits_col = 'purple' fill_transpcy = 0.15 line_transpcy = 0.40 fig = plt.figure(1, figsize=fs) plt.title('Normal distribution pdf (' + '$\mu$={:.2f}, $\sigma$={:.2f}, shift={:.1f}, |SL|={:.0f})\n'. format(mu, sigma, shift, SL)) axes = plt.subplot(111) x1 = sp.linspace(start=beg, stop=end, num=N) def formannotate(sf='', v1='x', v2=0, x=0, y=0, xytxt=(1, 1), colr='k', hal='left', multialign='right', a=1): # sf: format_str with 2 placholders s = sf.format(v1, v2) # value1, value2 axes.annotate(s, xy=(x, y), xycoords='data', xytext=xytxt, textcoords='data', color=colr, ha=hal, multialignment=multialign, alpha=a) for k in switch.keys(): mean = mu + k * shift * sigma col = switch[k][0] y0 = stats.norm(loc=mean, scale=sigma) y = y0.pdf(x1) plt.plot(x1, y, color=col, alpha=line_transpcy, label=switch[k][2]) plt.gca().fill_between(x1, y, facecolor=col, alpha=fill_transpcy) # dashed vline at mu plt.plot([mean, mean], [0, max(y)], ls='--', color=col, linewidth=2.2, alpha=line_transpcy, zorder=2) # label @ mu formannotate(sf='${:s}{:.2f}$', v1=switch[k][1], v2=mean, x=mean, y=0.065, xytxt=(mean, 0.065), hal='center', colr=col) # dotted vline at mu+sigma mu_plus = mean + sigma y_plus = y0.pdf(mu_plus) plt.plot([mu_plus, mu_plus], [0.0, y_plus], ls=':', color=col, linewidth=2, alpha=line_transpcy, zorder=2) # label @ mu_plus formannotate(sf='${:s}{:.2f}$', v1=switch[1][1], v2=mu_plus, x=mu_plus, y=0.04, xytxt=(mu_plus, 0.04), hal='center', colr=col) # dotted vline at mu-sigma mu_minus = mean - sigma y_minus = y0.pdf(mu_minus) plt.plot([mu_minus, mu_minus], [0.0, y_minus], ls=':', color=col, linewidth=2, alpha=line_transpcy, zorder=2) # label @ mu_minus formannotate(sf='${:s}{:.2f}$', v1=switch[-1][1], v2=mu_minus, x=mu_minus, y=0.02, xytxt=(mu_minus, 0.02), hal='center', colr=col) # Calc SL values to build the stacked text above each extreme pt: if k == -1: cdf1 = stats.norm(loc=-shift, scale=sigma).cdf(x=lsl) cdf4 = 1 - stats.norm(loc=-shift, scale=sigma).cdf(x=usl) elif k == 0: cdf2 = stats.norm(loc=0, scale=sigma).cdf(x=lsl) cdf5 = 1 - stats.norm(loc=0, scale=sigma).cdf(x=usl) else: cdf3 = stats.norm(loc=shift, scale=sigma).cdf(x=lsl) cdf6 = 1 - stats.norm(loc=shift, scale=sigma).cdf(x=usl) top0 = 0.38 # left-side annotations: axes.annotate('Area left of LSL:', xy=(beg * 0.95, 0.0), xycoords='data', xytext=(beg * 0.95, top0), textcoords='data', ha='left', color=limits_col, alpha=0.9) formannotate('${:s}$ shift: {:.3e}', switch[-1][2], cdf1, x=beg * 0.95, y=0.0, xytxt=(beg * 0.95, top0 - 0.03), colr=switch[-1][0], a=0.7) formannotate(' {:s}: {:.3e}', switch[0][2], cdf2, x=beg * 0.95, y=0.0, xytxt=(beg * 0.95, top0 - 0.05), colr=switch[0][0], a=0.7) formannotate('${:s}$ shift: {:.3e}', switch[1][2], cdf3, x=beg * 0.95, y=0.0, xytxt=(beg * 0.95, top0 - 0.07), colr=switch[1][0], a=0.7) # place arrows axes.annotate('', xy=(beg * 0.95, 0.0), xycoords='data', xytext=(beg * 0.95, top0 - 0.09), textcoords='data', weight='bold', ha='center', color=limits_col, arrowprops=dict(arrowstyle='->', connectionstyle='arc3', color=limits_col, alpha=line_transpcy, linewidth=1.8)) axes.annotate('LSL', xy=(lsl, 0.0), xycoords='data', xytext=(lsl, 0.08), textcoords='data', weight='bold', ha='center', color=limits_col, arrowprops=dict(arrowstyle='-', connectionstyle="arc3", color=limits_col)) axes.annotate('USL', xy=(usl, 0.0), xycoords='data', xytext=(usl, 0.08), textcoords='data', weight='bold', ha='center', color=limits_col, arrowprops=dict(arrowstyle='-', connectionstyle="arc3", color=limits_col)) # right-side annotations: axes.annotate('Area right of USL:', xy=(end * 0.95, 0.0), xycoords='data', xytext=(end * 0.95, top0), textcoords='data', ha='right', color=limits_col, alpha=0.9) formannotate('${:s}$ shift: {:.3e}', switch[-1][2], cdf4, x=end * 0.95, y=0.0, xytxt=(end * 0.95, top0 - 0.03), colr=switch[-1][0], a=0.7, hal='right') formannotate('${:s}$ shift: {:.3e}', switch[0][2], cdf5, x=end * 0.95, y=0.0, xytxt=(end * 0.95, top0 - 0.05), colr=switch[0][0], a=0.7, hal='right') formannotate('${:s}$ shift: {:.3e}', switch[1][2], cdf6, x=end * 0.95, y=0.0, xytxt=(end * 0.95, top0 - 0.07), colr=switch[1][0], a=0.7, hal='right') # place arrow axes.annotate('', xy=(end * 0.95, 0.0), xycoords='data', xytext=(end * 0.95, top0 - 0.09), textcoords='data', weight='bold', ha='center', color=limits_col, arrowprops=dict(arrowstyle='->', connectionstyle='arc3', color=limits_col, alpha=line_transpcy, linewidth=1.8)) # create the borded box: #................................................................... l0 = stats.norm(loc=shift * sigma + 0.5, scale=sigma).ppf(0.85) l1 = l0 + 2.6 h0 = 0.15 h1 = h0 + 0.1 # If fig_size width too small (w<11), the text will not fit in box # => draw box w/o edge color if fs[0] < 11: edge_col = 'none' else: edge_col = limits_col bb = Bbox([[l0, h0], [l1, h1]]) fbx = FancyBboxPatch((bb.xmin, bb.ymin), abs(bb.width), abs(bb.height), boxstyle='round, pad=0.01, rounding_size=0.05', linewidth=1, alpha=line_transpcy, zorder=1, ec=edge_col, fc='none') axes.add_patch(fbx) # Create text (to overlap the box): dx = l0 + 0.1 dy = bb.ymax - 0.02 axes.annotate('Total area beyond SL:', xy=(dx, dy), xycoords='data', xytext=(dx, dy), textcoords='data', ha='left', color=limits_col, alpha=0.9) formannotate('${:s}$ shift: {:.3e}', switch[-1][2], cdf1 + cdf4, x=dx, y=dy, xytxt=(dx, dy - 0.03), colr=switch[-1][0], a=0.7) formannotate(' {:s}: {:.3e}', switch[0][2], cdf2 + cdf5, x=dx, y=dy, xytxt=(dx, dy - 0.05), colr=switch[0][0], a=0.7) formannotate('${:s}$ shift: {:.3e}', switch[1][2], cdf3 + cdf6, x=dx, y=dy, xytxt=(dx, dy - 0.07), colr=switch[1][0], a=0.7) # place y-axis at x=mu axes.spines['left'].set_position(('data', mu)) # change transp. of both axes axes.spines['left'].set(alpha=0.3) axes.spines['bottom'].set(alpha=0.3) axes.set_xlim(beg, end) Ylim = max(y) axes.set_ylim(0, Ylim + 0.05) # whole_xtick and whole_ytick: label the axes with a 'ruler style' # x-axis manips def whole_xtick(x, pos): if not (x % 1.0): return '{:.0f}'.format(x) return '' # y-axis manips def whole_ytick(x, pos): # The rounded expression in use here is a workaround a numpy(scipy).mod bug: # <n,s>p.<mod,remainder>( 0.5, 0.1) == sp.mod( 0.9, 0.1) == 0.099999999999999978 # Note: only works bc range < 0.5. # Excludes 0 for vertical axis since already displayed on x-axis if not (x == 0): if not round(sp.mod(x, 0.1), 3): return '{:.2f}'.format(x) return '' return '' axes.xaxis.set_major_locator(MultipleLocator(base=x_majloc)) axes.xaxis.set_major_formatter(FuncFormatter(whole_xtick)) axes.xaxis.set_minor_locator(AutoMinorLocator(4)) axes.yaxis.set_major_locator(MultipleLocator(base=0.05)) axes.yaxis.set_major_formatter(FuncFormatter(whole_ytick)) axes.yaxis.set_minor_locator(AutoMinorLocator(4)) # To annotate the last labeled pt on major x-tick: axes.text(end * 0.95, -0.03, 'x ', fontsize=10, horizontalalignment='center', verticalalignment='bottom', bbox=dict(fc='w', ec='none', pad=0.0)) # To annotate the second to last labeled pt on major y-tick: axes.text(mu - 0.5 * x_majloc, axes.yaxis.get_ticklocs()[-1], '$\phi(x)$', weight='bold', fontsize=16, ha='right', horizontalalignment='right', verticalalignment='center') # remove top/right spines axes.spines['top'].set_visible(False) axes.spines['right'].set_visible(False) # set ticks off plt.tick_params(top='off', right='off', which='both') plt.tick_params('x', which='both', direction='out') plt.show() if save: fig.savefig(filename=file_out, dpi=resi, orientation='landscape', transparent=True, frameon=None, bbox_inches='tight')
def CombineMasks(mask_full,SAVEPATH,binnx,binny): # import matplotlib.patches as patches y_arr_f=np.linspace(0,2*ypixels/binny+ygap,2*ypixels/binny+ygap) x_arr_f=np.linspace(0,4*xpixels/binnx+3*xgap,4*xpixels/binnx+3*xgap) X,Y=np.meshgrid(x_arr_f,y_arr_f) fig0,ax0=plt.subplots(1,figsize=(8,8)) cs=ax0.contourf(X,Y,mask_full[0,:,:],cmap=plt.cm.Greys_r) fig0.colorbar(cs,cmap=plt.cm.Greys_r) cs=ax0.contour(X,Y,mask_full[0,:,:],levels=[0.99],color='red',linewidth=2.0) ax0.set_ylim(2*ypixels/binny+ygap,0) #### chip edges.... plt.axhline(y=ypixels/binny,color='yellow') plt.axhline(y=ypixels/binny+ygap,color='yellow') plt.axvline(x=xpixels/binnx,color='yellow') plt.axvline(x=xpixels/binnx+xgap,color='yellow') plt.axvline(x=2*xpixels/binnx+xgap,color='yellow') plt.axvline(x=2*xpixels/binnx+2*xgap,color='yellow') plt.axvline(x=3*xpixels/binnx+2*xgap,color='yellow') plt.axvline(x=3*xpixels/binnx+3*xgap,color='yellow') #### paths=np.load(SAVEPATH+'Masks.npz')['boxes']#cs.collections[0].get_paths() for i in range(0,len(paths)): p0=paths[i] #print p0 bbox=Bbox(np.array([[p0[0],p0[1]],[p0[2],p0[3]]])) #print bbox #print bbox.get_points if np.abs((bbox.get_points()[0,0])-(bbox.get_points()[1,0]))> 190.: ax0.add_patch(patches.Rectangle((p0[0],p0[1]),p0[2]-p0[0],p0[3]-p0[1], facecolor='none', ec='green', linewidth=2, zorder=50)) ax0.set_title('Un-Combined Masks, Full Frame') plt.show(block=False) ##merging masks from split chips boxes=np.array([]) skip_arr=np.array([]) for i in range(0,len(paths)): if i in skip_arr: continue #print '----->', len(boxes)/4. p0=paths[i] bbbox=Bbox(np.array([[p0[0],p0[1]],[p0[2],p0[3]]])) #bbbox=p0.get_extents() #print i, bbox x0,y0,x1,y1=p0[0],p0[1],p0[2],p0[3] #test_point=x0+100 #if np.abs(y1-ypixels)<20: # test_point=[x0+100,y1+2*ygap] #print test_point for j in range(0,len(paths)): if j==i and j<len(paths)-1: j+=1 if j==i and j==len(paths): continue p1=paths[j] x01,y01,x11,y11=p1[0],p1[1],p1[2],p1[3] #if p1.contains_point(test_point): #if test_point[0]>x01 and test_point[0]<x11: if (x0>x01 and x0<x11) or (x1>x01 and x1<x11): if np.abs(y1-y01)<2*ygap: #print i,j skip_arr=np.append(skip_arr,j) #bbox1=p1.get_extents() #x01,y01,x11,y11=bbox1.get_points()[0,0],bbox1.get_points()[0,1],bbox1.get_points()[1,0],bbox1.get_points()[1,1] x0n=np.nanmin([x0,x01]) #print 'Bottom',y01,y11, 'TOP',y0,y1 #print x0,x01,x0n y0n=y0 x1n=np.nanmax([x1,x11]) #print x1,x11,x1n #print '----' y1n=y11 bbbox=Bbox(np.array([[x0n,y0n],[x1n,y1n]])) #elif not p1.contains_point(test_point): # bbox_new=bbbox #else: # bbox_new=bbbox boxes=np.append(boxes,bbbox) mask_edges=np.reshape(boxes,(len(boxes)/4,4))#np.empty([4,len(boxes/4.)]) #p=0 #for b in range(0,len(boxes)): # x=b%4 # mask_edges[x,int(p)]=boxes[b] # p+=(1./4.) ## plotting newly merged boxes fig1,ax1=plt.subplots(1,figsize=(8,8)) cs=ax1.contourf(X,Y,mask_full[0,:,:],cmap=plt.cm.Greys_r) fig1.colorbar(cs,cmap=plt.cm.Greys_r) cs=ax1.contour(X,Y,mask_full[0,:,:],levels=[0.99],color='red',linewidth=2.0) ax1.set_ylim(2*ypixels/binny+ygap,0) #### chip edges.... plt.axhline(y=ypixels/binny,color='yellow') plt.axhline(y=ypixels/binny+ygap,color='yellow') plt.axvline(x=xpixels/binnx,color='yellow') plt.axvline(x=xpixels/binnx+xgap,color='yellow') plt.axvline(x=2*xpixels/binnx+xgap,color='yellow') plt.axvline(x=2*xpixels/binnx+2*xgap,color='yellow') plt.axvline(x=3*xpixels/binnx+2*xgap,color='yellow') plt.axvline(x=3*xpixels/binnx+3*xgap,color='yellow') #### #paths=cs.collections[0].get_paths() for i in range(0,len(boxes)/4): x0,y0,x1,y1=mask_edges[i,0],mask_edges[i,1],mask_edges[i,2],mask_edges[i,3] ax1.add_patch(patches.Rectangle((x0,y0),np.abs(x0-x1),np.abs(y0-y1), facecolor='none', ec='cyan', linewidth=2, zorder=50)) ax1.annotate(i,xy=(x0+100/binnx,y1-500/binny),ha='center',va='center',fontsize=8,color='red',zorder=51) ax1.set_title('Combined Masks, Full Frame') plt.show(block=False) np.savez_compressed(SAVEPATH+'CombinedMasks.npz',mask_edges=mask_edges,boxes=boxes) return(mask_edges)
def graph(self): fig, ax = plt.subplots() plt.subplots_adjust(left=0.03, right=0.97, top=0.99, bottom=0.1) renderer = fig.canvas.get_renderer() fig.set_size_inches( GanttChart.WIDTH_PX / 100, self.height / 100, ) plt.grid( axis='x', which='major', visible=True, color='0.8', ) plt.grid( axis='x', which='minor', visible=True, color='0.9', linestyle='--', ) plt.tick_params( axis='y', which='both', left=False, right=False, labelleft=False, ) # X Axes ax2 = ax.twiny() for x in [ax, ax2]: x.xaxis.set_major_locator( GanttChart.TICK_PARAMS[self.years]['major_locator']) x.xaxis.set_minor_locator( GanttChart.TICK_PARAMS[self.years]['minor_locator']) x.xaxis.set_major_formatter( GanttChart.TICK_PARAMS[self.years]['format']) x.set_xlim(self.start_date, self.end_date) # Y Axis ax.set_ylim(0, self.height) for i, d in enumerate(self.data, 1): top = self.height - (i * GanttChart.STUDY_HEIGHT_PX) left = max(d['start_date'], self.start_date) t = plt.text( 0, 0, d['name'], ha="left", va="bottom", ) bbox = Bbox(ax.transData.inverted().transform( t.get_window_extent(renderer=renderer))) if (left + relativedelta(days=bbox.width)) > self.end_date: t._x = self.end_date - relativedelta(days=bbox.width) else: t._x = left t._y = top + GanttChart.STUDY_BAR_HEIGHT ax.broken_barh( [(d['start_date'], d['duration'])], (top, GanttChart.STUDY_BAR_HEIGHT), # facecolors =('tab:orange'), ) return plt
def get_window_extent(self, renderer=None): x0, x1, y0, y1 = self._extent bbox = Bbox.from_extents([x0, y0, x1, y1]) return bbox.transformed(self.axes.transData)
def __call__(self, ax, renderer): bbox_parent = self.parent.get_position(original=False) trans = BboxTransformTo(bbox_parent) bbox_inset = Bbox.from_bounds(*self.lbwh) bb = TransformedBbox(bbox_inset, trans) return bb
ax2.set_ylabel('normalised flux') ax2.scatter(x_coord, f, color='k') ax1.text(0.98, 0.95, runtime, ha='right', va='bottom', transform=ax1.transAxes, **tyb) ([x0a0, y0a0], [x1a0, y1a0]) = ax1.get_position().get_points() ([x0a1, y0a1], [x1a1, y1a1]) = ax2.get_position().get_points() from matplotlib.transforms import Bbox ax2.set_position(Bbox.from_extents([x0a0, y0a1], [x1a0, y1a1])) plt.draw() ###plt.savefig('simdisk_a.pdf') def disk_mass(r_disk, tau, mean_a=0.5 * u.micron, mean_rho=2.5 * u.g / (u.cm * u.cm * u.cm)): 'simple mass for a face-on circular optically thin disk' # cadged from Mellon's derivation in thesis - p.44, eq. 4.9 Mdisk = (4 * np.pi * mean_a * mean_rho * tau * r_disk * r_disk) / 3. return Mdisk.to(u.g)
def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, unsampled=False, round_to_pixel_border=True): """ Normalize, rescale and color the image `A` from the given in_bbox (in data space), to the given out_bbox (in pixel space) clipped to the given clip_bbox (also in pixel space), and magnified by the magnification factor. `A` may be a greyscale image (MxN) with a dtype of `float32`, `float64`, `uint16` or `uint8`, or an RGBA image (MxNx4) with a dtype of `float32`, `float64`, or `uint8`. If `unsampled` is True, the image will not be scaled, but an appropriate affine transformation will be returned instead. If `round_to_pixel_border` is True, the output image size will be rounded to the nearest pixel boundary. This makes the images align correctly with the axes. It should not be used in cases where you want exact scaling, however, such as FigureImage. Returns the resulting (image, x, y, trans), where (x, y) is the upper left corner of the result in pixel space, and `trans` is the affine transformation from the image to pixel space. """ if A is None: raise RuntimeError('You must first set the image' ' array or the image attribute') clipped_bbox = Bbox.intersection(out_bbox, clip_bbox) if clipped_bbox is None: return None, 0, 0, None out_width_base = clipped_bbox.width * magnification out_height_base = clipped_bbox.height * magnification if out_width_base == 0 or out_height_base == 0: return None, 0, 0, None if self.origin == 'upper': # Flip the input image using a transform. This avoids the # problem with flipping the array, which results in a copy # when it is converted to contiguous in the C wrapper t0 = Affine2D().translate(0, -A.shape[0]).scale(1, -1) else: t0 = IdentityTransform() t0 += ( Affine2D() .scale( in_bbox.width / A.shape[1], in_bbox.height / A.shape[0]) .translate(in_bbox.x0, in_bbox.y0) + self.get_transform()) t = (t0 + Affine2D().translate( -clipped_bbox.x0, -clipped_bbox.y0) .scale(magnification, magnification)) # So that the image is aligned with the edge of the axes, we want # to round up the output width to the next integer. This also # means scaling the transform just slightly to account for the # extra subpixel. if (t.is_affine and round_to_pixel_border and (out_width_base % 1.0 != 0.0 or out_height_base % 1.0 != 0.0)): out_width = int(ceil(out_width_base)) out_height = int(ceil(out_height_base)) extra_width = (out_width - out_width_base) / out_width_base extra_height = (out_height - out_height_base) / out_height_base t += Affine2D().scale( 1.0 + extra_width, 1.0 + extra_height) else: out_width = int(out_width_base) out_height = int(out_height_base) if not unsampled: created_rgba_mask = False if A.ndim not in (2, 3): raise ValueError("Invalid dimensions, got %s" % (A.shape,)) if A.ndim == 2: A = self.norm(A) if A.dtype.kind == 'f': # If the image is greyscale, convert to RGBA and # use the extra channels for resizing the over, # under, and bad pixels. This is needed because # Agg's resampler is very aggressive about # clipping to [0, 1] and we use out-of-bounds # values to carry the over/under/bad information rgba = np.empty((A.shape[0], A.shape[1], 4), dtype=A.dtype) rgba[..., 0] = A # normalized data # this is to work around spurious warnings coming # out of masked arrays. with np.errstate(invalid='ignore'): rgba[..., 1] = A < 0 # under data rgba[..., 2] = A > 1 # over data rgba[..., 3] = ~A.mask # bad data A = rgba output = np.zeros((out_height, out_width, 4), dtype=A.dtype) alpha = 1.0 created_rgba_mask = True else: # colormap norms that output integers (ex NoNorm # and BoundaryNorm) to RGBA space before # interpolating. This is needed due to the # Agg resampler only working on floats in the # range [0, 1] and because interpolating indexes # into an arbitrary LUT may be problematic. # # This falls back to interpolating in RGBA space which # can produce it's own artifacts of colors not in the map # showing up in the final image. A = self.cmap(A, alpha=self.get_alpha(), bytes=True) if not created_rgba_mask: # Always convert to RGBA, even if only RGB input if A.shape[2] == 3: A = _rgb_to_rgba(A) elif A.shape[2] != 4: raise ValueError("Invalid dimensions, got %s" % (A.shape,)) output = np.zeros((out_height, out_width, 4), dtype=A.dtype) alpha = self.get_alpha() if alpha is None: alpha = 1.0 _image.resample( A, output, t, _interpd_[self.get_interpolation()], self.get_resample(), alpha, self.get_filternorm() or 0.0, self.get_filterrad() or 0.0) if created_rgba_mask: # Convert back to a masked greyscale array so # colormapping works correctly hid_output = output output = np.ma.masked_array( hid_output[..., 0], hid_output[..., 3] < 0.5) # relabel under data output[hid_output[..., 1] > .5] = -1 # relabel over data output[hid_output[..., 2] > .5] = 2 output = self.to_rgba(output, bytes=True, norm=False) # Apply alpha *after* if the input was greyscale without a mask if A.ndim == 2 or created_rgba_mask: alpha = self.get_alpha() if alpha is not None and alpha != 1.0: alpha_channel = output[:, :, 3] alpha_channel[:] = np.asarray( np.asarray(alpha_channel, np.float32) * alpha, np.uint8) else: if self._imcache is None: self._imcache = self.to_rgba(A, bytes=True, norm=(A.ndim == 2)) output = self._imcache # Subset the input image to only the part that will be # displayed subset = TransformedBbox( clip_bbox, t0.frozen().inverted()).frozen() output = output[ int(max(subset.ymin, 0)): int(min(subset.ymax + 1, output.shape[0])), int(max(subset.xmin, 0)): int(min(subset.xmax + 1, output.shape[1]))] t = Affine2D().translate( int(max(subset.xmin, 0)), int(max(subset.ymin, 0))) + t return output, clipped_bbox.x0, clipped_bbox.y0, t
c_top = [((x, y), (90 - a)%180+180) for (y, x, a) in c_top_ \ if bbox.containsx(x)] return list(zip(lx4, ly4)), [c_left, c_bottom, c_right, c_top] if __name__ == "__main__": import matplotlib.pyplot as plt x = np.array([-3, -2, -1, 0., 1, 2, 3, 2, 1, 0, -1, -2, -3, 5]) #x = np.array([-3, -2, -1, 0., 1, 2, 3]) y = np.arange(len(x)) #x0 = 2 plt.plot(x, y, lw=1) from matplotlib.transforms import Bbox bb = Bbox.from_extents(-2, 3, 2, 12.5) lxy, ticks = clip_line_to_rect(x, y, bb) for xx, yy in lxy: plt.plot(xx, yy, lw=1, color="g") ccc = iter(["ro", "go", "rx", "bx"]) for ttt in ticks: cc = six.next(ccc) for (xx, yy), aa in ttt: plt.plot([xx], [yy], cc) #xlim(
import numpy as np import matplotlib.pyplot as plt import copy from matplotlib.transforms import Bbox fig = plt.figure() ax1 = fig.add_subplot(111) xs = [1, 2, 3] box = Bbox([[0, 0], [1, 1]]) # ax1.fill([0, 1, 1, 0], [0, 0, 1, 1], hatch='x') ax1.fill([0, 1, 1, 0], [0, 0, 1, 1], hatch=None) ax1.tick_params(direction='in') xaxis = ax1.get_xaxis() xtick_labels = xaxis.get_ticklabels() # print(xtick_labels) ax1.text(0.5, -0.1, 'wo', fontsize=12, ha='center') # print(xtick_labels[0].get_position()[0]) # ax1.set_xlim(1, 10) xtick_lines = ax1.get_xticklines() # fig.canvas.draw() # for tl in xtick_lines: # # print(tl) # tl.set_visible(False) xtick_labels = ax1.get_xlabel() line = xtick_lines[0]
def _make_patch(self): """ Returns an appropriately scaled patch object corresponding to the Glyph. """ # Set height height = self.ceiling - self.floor # If height is zero, set patch to None and return None if height == 0.0: self.patch = None return None # Set bounding box for character, # leaving requested amount of padding above and below the character char_xmin = self.p - self.width / 2.0 char_ymin = self.floor + self.vpad * height / 2.0 char_width = self.width char_height = height - self.vpad * height bbox = Bbox.from_bounds(char_xmin, char_ymin, char_width, char_height) # Set font properties of Glyph font_properties = FontProperties(family=self.font_name, weight=self.font_weight) # Create a path for Glyph that does not yet have the correct # position or scaling tmp_path = TextPath((0, 0), self.c, size=1, prop=font_properties) # Create create a corresponding path for a glyph representing # the max stretched character msc_path = TextPath((0, 0), self.dont_stretch_more_than, size=1, prop=font_properties) # If need to flip char, do it within tmp_path if self.flip: transformation = Affine2D().scale(sx=1, sy=-1) tmp_path = transformation.transform_path(tmp_path) # If need to mirror char, do it within tmp_path if self.mirror: transformation = Affine2D().scale(sx=-1, sy=1) tmp_path = transformation.transform_path(tmp_path) # Get bounding box for temporary character and max_stretched_character tmp_bbox = tmp_path.get_extents() msc_bbox = msc_path.get_extents() # Compute horizontal stretch factor needed for tmp_path hstretch_tmp = bbox.width / tmp_bbox.width # Compute horizontal stretch factor needed for msc_path hstretch_msc = bbox.width / msc_bbox.width # Choose the MINIMUM of these two horizontal stretch factors. # This prevents very narrow characters, such as 'I', from being # stretched too much. hstretch = min(hstretch_tmp, hstretch_msc) # Compute the new character width, accounting for the # limit placed on the stretching factor char_width = hstretch * tmp_bbox.width # Compute how much to horizontally shift the character path char_shift = (bbox.width - char_width) / 2.0 # Compute vertical stetch factor needed for tmp_path vstretch = bbox.height / tmp_bbox.height # THESE ARE THE ESSENTIAL TRANSFORMATIONS # 1. First, translate char path so that lower left corner is at origin # 2. Then scale char path to desired width and height # 3. Finally, translate char path to desired position # char_path is the resulting path used for the Glyph transformation = Affine2D() \ .translate(tx=-tmp_bbox.xmin, ty=-tmp_bbox.ymin) \ .scale(sx=hstretch, sy=vstretch) \ .translate(tx=bbox.xmin + char_shift, ty=bbox.ymin) char_path = transformation.transform_path(tmp_path) # Convert char_path to a patch, which can now be drawn on demand self.patch = PathPatch(char_path, facecolor=self.color, zorder=self.zorder, alpha=self.alpha, edgecolor=self.edgecolor, linewidth=self.edgewidth) # add patch to axes self.ax.add_patch(self.patch)
def _find_best_position(self, width, height, renderer, consider=None): """ Determine the best location to place the legend. `consider` is a list of (x, y) pairs to consider as a potential lower-left corner of the legend. All are display coords. """ # should always hold because function is only called internally assert self.isaxes verts, bboxes, lines, offsets = self._auto_legend_data() bbox = Bbox.from_bounds(0, 0, width, height) if consider is None: consider = [ self._get_anchored_bbox(x, bbox, self.get_bbox_to_anchor(), renderer) for x in range(1, len(self.codes)) ] # tx, ty = self.legendPatch.get_x(), self.legendPatch.get_y() candidates = [] for l, b in consider: legendBox = Bbox.from_bounds(l, b, width, height) badness = 0 # XXX TODO: If markers are present, it would be good to # take their into account when checking vertex overlaps in # the next line. badness = legendBox.count_contains(verts) badness += legendBox.count_contains(offsets) badness += legendBox.count_overlaps(bboxes) for line in lines: # FIXME: the following line is ill-suited for lines # that 'spiral' around the center, because the bbox # may intersect with the legend even if the line # itself doesn't. One solution would be to break up # the line into its straight-segment components, but # this may (or may not) result in a significant # slowdown if lines with many vertices are present. if line.intersects_bbox(legendBox): badness += 1 ox, oy = l, b if badness == 0: return ox, oy candidates.append((badness, (l, b))) # rather than use min() or list.sort(), do this so that we are assured # that in the case of two equal badnesses, the one first considered is # returned. # NOTE: list.sort() is stable.But leave as it is for now. -JJL minCandidate = candidates[0] for candidate in candidates: if candidate[0] < minCandidate[0]: minCandidate = candidate ox, oy = minCandidate[1] return ox, oy
def as_mpl_artists(shape_list, properties_func=None, text_offset=5.0, origin=1): """ Converts a region list to a list of patches and a list of artists. Optional Keywords: [ text_offset ] - If there is text associated with the regions, add some vertical offset (in pixels) to the text so that it doesn't overlap with the regions. Often, the regions files implicitly assume the lower-left corner of the image as a coordinate (1,1). However, the python convetion is that the array index starts from 0. By default (origin = 1), coordinates of the returned mpl artists have coordinate shifted by (1, 1). If you do not want this shift, set origin=0. """ patch_list = [] artist_list = [] if properties_func is None: properties_func = properties_func_default # properties for continued(? multiline?) regions saved_attrs = None for shape in shape_list: patches = [] if saved_attrs is None: _attrs = [], {} else: _attrs = copy.copy(saved_attrs[0]), copy.copy(saved_attrs[1]) kwargs = properties_func(shape, _attrs) if shape.name == "composite": saved_attrs = shape.attr continue if saved_attrs is None and shape.continued: saved_attrs = shape.attr # elif (shape.name in shape.attr[1]): # if (shape.attr[1][shape.name] != "ignore"): # saved_attrs = shape.attr if not shape.continued: saved_attrs = None # text associated with the shape txt = shape.attr[1].get("text") if shape.name == "polygon": xy = np.array(shape.coord_list) xy.shape = -1,2 # -1 for change origin to 0,0 patches=[mpatches.Polygon(xy-origin, closed=True, **kwargs)] elif shape.name == "rotbox" or shape.name == "box": xc, yc, w, h, rot = shape.coord_list # -1 for change origin to 0,0 xc, yc = xc-origin, yc-origin _box = np.array([[-w/2., -h/2.], [-w/2., h/2.], [w/2., h/2.], [w/2., -h/2.]]) box = _box + [xc, yc] rotbox = rotated_polygon(box, xc, yc, rot) patches = [mpatches.Polygon(rotbox, closed=True, **kwargs)] elif shape.name == "ellipse": xc, yc = shape.coord_list[:2] # -1 for change origin to 0,0 xc, yc = xc-origin, yc-origin angle = shape.coord_list[-1] maj_list, min_list = shape.coord_list[2:-1:2], shape.coord_list[3:-1:2] patches = [mpatches.Ellipse((xc, yc), 2*maj, 2*min, angle=angle, **kwargs) for maj, min in zip(maj_list, min_list)] elif shape.name == "annulus": xc, yc = shape.coord_list[:2] # -1 for change origin to 0,0 xc, yc = xc-origin, yc-origin r_list = shape.coord_list[2:] patches = [mpatches.Ellipse((xc, yc), 2*r, 2*r, **kwargs) for r in r_list] elif shape.name == "circle": xc, yc, major = shape.coord_list # -1 for change origin to 0,0 xc, yc = xc-origin, yc-origin patches = [mpatches.Ellipse((xc, yc), 2*major, 2*major, angle=0, **kwargs)] elif shape.name == "panda": xc, yc, a1, a2, an, r1, r2, rn = shape.coord_list # -1 for change origin to 0,0 xc, yc = xc-origin, yc-origin patches = [mpatches.Arc((xc, yc), rr*2, rr*2, angle=0, theta1=a1, theta2=a2, **kwargs) for rr in np.linspace(r1, r2, rn+1)] for aa in np.linspace(a1, a2, an+1): xx = np.array([r1, r2]) * np.cos(aa/180.*np.pi) + xc yy = np.array([r1, r2]) * np.sin(aa/180.*np.pi) + yc p = Path(np.transpose([xx, yy])) patches.append(mpatches.PathPatch(p, **kwargs)) elif shape.name == "pie": xc, yc, r1, r2, a1, a2 = shape.coord_list # -1 for change origin to 0,0 xc, yc = xc-origin, yc-origin patches = [mpatches.Arc((xc, yc), rr*2, rr*2, angle=0, theta1=a1, theta2=a2, **kwargs) for rr in [r1, r2]] for aa in [a1, a2]: xx = np.array([r1, r2]) * np.cos(aa/180.*np.pi) + xc yy = np.array([r1, r2]) * np.sin(aa/180.*np.pi) + yc p = Path(np.transpose([xx, yy])) patches.append(mpatches.PathPatch(p, **kwargs)) elif shape.name == "epanda": xc, yc, a1, a2, an, r11, r12, r21, r22, rn, angle = shape.coord_list # -1 for change origin to 0,0 xc, yc = xc-origin, yc-origin # mpl takes angle a1, a2 as angle as in circle before # transformation to ellipse. x1, y1 = cos(a1/180.*pi), sin(a1/180.*pi)*r11/r12 x2, y2 = cos(a2/180.*pi), sin(a2/180.*pi)*r11/r12 a1, a2 = atan2(y1, x1)/pi*180., atan2(y2, x2)/pi*180. patches = [mpatches.Arc((xc, yc), rr1*2, rr2*2, angle=angle, theta1=a1, theta2=a2, **kwargs) for rr1, rr2 in zip(np.linspace(r11, r21, rn+1), np.linspace(r12, r22, rn+1))] for aa in np.linspace(a1, a2, an+1): xx = np.array([r11, r21]) * np.cos(aa/180.*np.pi) yy = np.array([r11, r21]) * np.sin(aa/180.*np.pi) p = Path(np.transpose([xx, yy])) tr = Affine2D().scale(1, r12/r11).rotate_deg(angle).translate(xc, yc) p2 = tr.transform_path(p) patches.append(mpatches.PathPatch(p2, **kwargs)) elif shape.name == "text": xc, yc = shape.coord_list[:2] # -1 for change origin to 0,0 xc, yc = xc-origin, yc-origin if txt: _t = _get_text(txt, xc, yc, 0, 0, **kwargs) artist_list.append(_t) elif shape.name == "point": xc, yc = shape.coord_list[:2] # -1 for change origin to 0,0 xc, yc = xc-origin, yc-origin artist_list.append(Line2D([xc], [yc], **kwargs)) if txt: textshape = copy.copy(shape) textshape.name = "text" textkwargs = properties_func(textshape, _attrs) _t = _get_text(txt, xc, yc, 0, text_offset, va="bottom", **textkwargs) artist_list.append(_t) elif shape.name in ["line", "vector"]: if shape.name == "line": x1, y1, x2, y2 = shape.coord_list[:4] # -1 for change origin to 0,0 x1, y1, x2, y2 = x1-origin, y1-origin, x2-origin, y2-origin a1, a2 = shape.attr[1].get("line", "0 0").strip().split()[:2] arrowstyle = "-" if int(a1): arrowstyle = "<" + arrowstyle if int(a2): arrowstyle = arrowstyle + ">" else: # shape.name == "vector" x1, y1, l, a = shape.coord_list[:4] # -1 for change origin to 0,0 x1, y1 = x1-origin, y1-origin x2, y2 = x1 + l * np.cos(a/180.*np.pi), y1 + l * np.sin(a/180.*np.pi) v1 = int(shape.attr[1].get("vector", "0").strip()) if v1: arrowstyle = "->" else: arrowstyle = "-" patches = [mpatches.FancyArrowPatch(posA=(x1, y1), posB=(x2, y2), arrowstyle=arrowstyle, arrow_transmuter=None, connectionstyle="arc3", patchA=None, patchB=None, shrinkA=0, shrinkB=0, connector=None, **kwargs)] else: warnings.warn("'as_mpl_artists' does not know how to convert {0} " "to mpl artist".format(shape.name)) patch_list.extend(patches) if txt and patches: # the text associated with a shape uses different # matplotlib keywords than the shape itself for, e.g., # color textshape = copy.copy(shape) textshape.name = "text" textkwargs = properties_func(textshape, _attrs) # calculate the text position _bb = [p.get_window_extent() for p in patches] # this is to work around backward-incompatible change made # in matplotlib 1.2. This change is later reverted so only # some versions are affected. With affected version of # matplotlib, get_window_extent method calls get_transform # method which sets the _transformSet to True, which is # not desired. for p in patches: p._transformSet = False _bbox = Bbox.union(_bb) x0, y0, x1, y1 = _bbox.extents xc = .5*(x0+x1) _t = _get_text(txt, xc, y1, 0, text_offset, va="bottom", **textkwargs) artist_list.append(_t) return patch_list, artist_list
def test_degenerate_polygon(): point = [0, 0] correct_extents = Bbox([point, point]).extents assert np.all(Polygon([point]).get_extents().extents == correct_extents)
def test_nan_overlap(): a = Bbox([[0, 0], [1, 1]]) b = Bbox([[0, 0], [1, np.nan]]) assert not a.overlaps(b)
set(gca(), 'xticks', [-1, -.5, 0, .5, 1]) set(gca(), 'yticks', []) xlabel('intensity') ylabel('MRI density') if 1: # plot the EEG # load the data numSamples, numRows = 800,4 data = fromstring(file('data/eeg.dat', 'rb').read(), Float) data.shape = numSamples, numRows t = arange(numSamples)/float(numSamples)*10.0 ticklocs = [] ax = subplot(212) boxin = Bbox( Point(ax.viewLim.ll().x(), Value(-20)), Point(ax.viewLim.ur().x(), Value(20))) height = ax.bbox.ur().y() - ax.bbox.ll().y() boxout = Bbox( Point(ax.bbox.ll().x(), Value(-1)*height), Point(ax.bbox.ur().x(), Value(1) * height)) transOffset = get_bbox_transform( unit_bbox(), Bbox( Point( Value(0), ax.bbox.ll().y()), Point( Value(1), ax.bbox.ur().y()) ))
def auto_adjust_subplotpars(fig, renderer, nrows_ncols, num1num2_list, subplot_list, ax_bbox_list=None, pad=1.08, h_pad=None, w_pad=None, rect=None): """ Return a dict of subplot parameters to adjust spacing between subplots or ``None`` if resulting axes would have zero height or width. Note that this function ignores geometry information of subplot itself, but uses what is given by the *nrows_ncols* and *num1num2_list* parameters. Also, the results could be incorrect if some subplots have ``adjustable=datalim``. Parameters ---------- nrows_ncols : Tuple[int, int] Number of rows and number of columns of the grid. num1num2_list : List[int] List of numbers specifying the area occupied by the subplot subplot_list : list of subplots List of subplots that will be used to calculate optimal subplot_params. pad : float Padding between the figure edge and the edges of subplots, as a fraction of the font size. h_pad, w_pad : float Padding (height/width) between edges of adjacent subplots, as a fraction of the font size. Defaults to *pad*. rect : Tuple[float, float, float, float] [left, bottom, right, top] in normalized (0, 1) figure coordinates. """ rows, cols = nrows_ncols font_size_inches = ( FontProperties(size=rcParams["font.size"]).get_size_in_points() / 72) pad_inches = pad * font_size_inches vpad_inches = h_pad * font_size_inches if h_pad is not None else pad_inches hpad_inches = w_pad * font_size_inches if w_pad is not None else pad_inches if len(num1num2_list) != len(subplot_list) or len(subplot_list) == 0: raise ValueError if rect is None: margin_left = margin_bottom = margin_right = margin_top = None else: margin_left, margin_bottom, _right, _top = rect margin_right = 1 - _right if _right else None margin_top = 1 - _top if _top else None vspaces = np.zeros((rows + 1, cols)) hspaces = np.zeros((rows, cols + 1)) if ax_bbox_list is None: ax_bbox_list = [ Bbox.union([ax.get_position(original=True) for ax in subplots]) for subplots in subplot_list ] for subplots, ax_bbox, (num1, num2) in zip(subplot_list, ax_bbox_list, num1num2_list): if all(not ax.get_visible() for ax in subplots): continue tight_bbox_raw = Bbox.union([ ax.get_tightbbox(renderer) for ax in subplots if ax.get_visible() ]) tight_bbox = TransformedBbox(tight_bbox_raw, fig.transFigure.inverted()) row1, col1 = divmod(num1, cols) if num2 is None: num2 = num1 row2, col2 = divmod(num2, cols) for row_i in range(row1, row2 + 1): hspaces[row_i, col1] += ax_bbox.xmin - tight_bbox.xmin # left hspaces[row_i, col2 + 1] += tight_bbox.xmax - ax_bbox.xmax # right for col_i in range(col1, col2 + 1): vspaces[row1, col_i] += tight_bbox.ymax - ax_bbox.ymax # top vspaces[row2 + 1, col_i] += ax_bbox.ymin - tight_bbox.ymin # bot. fig_width_inch, fig_height_inch = fig.get_size_inches() # margins can be negative for axes with aspect applied, so use max(, 0) to # make them nonnegative. if not margin_left: margin_left = (max(hspaces[:, 0].max(), 0) + pad_inches / fig_width_inch) if not margin_right: margin_right = (max(hspaces[:, -1].max(), 0) + pad_inches / fig_width_inch) if not margin_top: margin_top = (max(vspaces[0, :].max(), 0) + pad_inches / fig_height_inch) if not margin_bottom: margin_bottom = (max(vspaces[-1, :].max(), 0) + pad_inches / fig_height_inch) if margin_left + margin_right >= 1: cbook._warn_external('Tight layout not applied. The left and right ' 'margins cannot be made large enough to ' 'accommodate all axes decorations. ') return None if margin_bottom + margin_top >= 1: cbook._warn_external('Tight layout not applied. The bottom and top ' 'margins cannot be made large enough to ' 'accommodate all axes decorations. ') return None kwargs = dict(left=margin_left, right=1 - margin_right, bottom=margin_bottom, top=1 - margin_top) if cols > 1: hspace = hspaces[:, 1:-1].max() + hpad_inches / fig_width_inch # axes widths: h_axes = (1 - margin_right - margin_left - hspace * (cols - 1)) / cols if h_axes < 0: cbook._warn_external('Tight layout not applied. tight_layout ' 'cannot make axes width small enough to ' 'accommodate all axes decorations') return None else: kwargs["wspace"] = hspace / h_axes if rows > 1: vspace = vspaces[1:-1, :].max() + vpad_inches / fig_height_inch v_axes = (1 - margin_top - margin_bottom - vspace * (rows - 1)) / rows if v_axes < 0: cbook._warn_external('Tight layout not applied. tight_layout ' 'cannot make axes height small enough to ' 'accommodate all axes decorations') return None else: kwargs["hspace"] = vspace / v_axes return kwargs
############################################################################### # If you want an inset axes in data-space, you need to manually execute the # layout using ``fig.execute_constrained_layout()`` call. The inset figure # will then be properly positioned. However, it will not be properly # positioned if the size of the figure is subsequently changed. Similarly, # if the figure is printed to another backend, there may be slight changes # of location due to small differences in how the backends render fonts. from matplotlib.transforms import Bbox fig, axs = plt.subplots(1, 2) example_plot(axs[0], fontsize=12) fig.execute_constrained_layout() # put into data-space: bb_data_ax2 = Bbox.from_bounds(0.5, 1., 0.2, 0.4) disp_coords = axs[0].transData.transform(bb_data_ax2) fig_coords_ax2 = fig.transFigure.inverted().transform(disp_coords) bb_ax2 = Bbox(fig_coords_ax2) ax2 = fig.add_axes(bb_ax2) ############################################################################### # Manually turning off ``constrained_layout`` # =========================================== # # ``constrained_layout`` usually adjusts the axes positions on each draw # of the figure. If you want to get the spacing provided by # ``constrained_layout`` but not have it update, then do the initial # draw and then call ``fig.set_constrained_layout(False)``. # This is potentially useful for animations where the tick labels may # change length.
def plot(self): try: self.ax.cla() except AttributeError: self.ax = self.add_subplot(1, 1, 1) if self.plot_display_type == "Refractive Index": self.x_label = r'$\mathrm{V_d}$' self.y_label = r'$\mathrm{n_d}$' xi = 1 yi = 0 self.draw_glass_polygons() elif self.plot_display_type == "Partial Dispersion": self.x_label = r'$\mathrm{V_d}$' self.y_label = r'$\mathrm{P_{%s-%s}}$' % self.partials xi = 1 yi = 2 elif self.plot_display_type == "Buchdahl Coefficients": self.x_label = r'$\mathrm{\nu_2}$' self.y_label = r'$\mathrm{\nu_1}$' xi = 4 yi = 3 elif self.plot_display_type == "Buchdahl Dispersion Coefficients": self.x_label = r'$\mathrm{\eta_2}$' self.y_label = r'$\mathrm{\eta_1}$' xi = 4 yi = 3 self.ax.set_title(self.get_display_label()) for i, display in enumerate(self.db_display): line = self.ax.plot( self.rawData[i][1][xi], self.rawData[i][1][yi], linestyle='None', marker='o', markersize=5, # linestyle='None', markersize=7, alpha=0.75, gid=i, picker=True, pickradius=5, color=self.dsc[i], # marker=self.mkr[i], fillstyle='none', label=self.rawData[i][0], visible=display) # set pickradius here because of a bug. Fixed in 3.3 line[0].set_pickradius(5.) if self.plot_display_type == "Refractive Index": # provide a default minimum area, and update view limits # accordingly viewLim = Bbox.union([self.home_bbox, self.ax.viewLim]) self.update_axis_limits(viewLim.get_points()) # set up interactive event handling # The pick events, one per artist, are sent before the sole button # press event actions = { 'button_press_event': self.on_press, 'pick_event': self.on_pick, } if self.hover_glass_names: actions['motion_notify_event'] = self.on_hover self.connect_events(action_dict=actions) # set up hover annotation if self.hover_glass_names: self.hover_list = self.ax.annotate( "", xy=(0, 0), xytext=(20, 20), textcoords="offset points", bbox=dict(boxstyle="round", fc="w"), arrowprops=dict(arrowstyle="->")) self.hover_list.set_visible(False) # draw remaining stuff, axes, legend... if xi == 1: self.ax.invert_xaxis() self.draw_axes() self.ax.legend() self.canvas.draw() return self
def _plot(array_samples_data, fig, ax1, ax2, interactive=False): colorbar = None colorbar_2 = None plt.gca() # plt.cla() # plt.clf() fig.clear() fig.add_axes(ax1) fig.add_axes(ax2) plt.cla() xlim = (-5., 5.) ylim = (-5., 5.) xlist = np.linspace(*xlim, 100) ylist = np.linspace(*ylim, 100) X_, Y_ = np.meshgrid(xlist, ylist) Z = np.dstack((X_, Y_)) Z = Z.reshape(-1, 2) predictions = get_predictions(Z, array_samples_theta) if np.size(predictions): predictions = predictions.reshape(100, 100) else: return False # print("finished") ax1.clear() if np.size(predictions): CS = ax1.contourf(X_, Y_, predictions, cmap="cividis") ax1.scatter(X_1[:, 0], X_1[:, 1]) ax1.scatter(X_2[:, 0], X_2[:, 1]) ax1.set_xlim(*xlim) ax1.set_ylim(*ylim) ax1.set_title("Predicted probability of belonging to C_1") ax3 = fig.add_axes(Bbox([[0.43, 0.11], [0.453, 0.88]])) if np.size(predictions): colorbar = fig.colorbar( CS, cax=ax3, ) ax1.set_position(Bbox([[0.125, 0.11], [0.39, 0.88]])) if np.size(array_samples_theta): colors = np.arange(1, array_samples_theta.shape[0] + 1) CS_2 = ax2.scatter(array_samples_theta[:, 0], array_samples_theta[:, 1], c=colors) colorbar_2 = plt.colorbar(CS_2, ax=ax2) x_prior = np.linspace(-3, 3, 100) y_prior = np.linspace(-3, 3, 100) X_prior, Y_prior = np.meshgrid(x_prior, y_prior) Z = np.dstack((X_prior, Y_prior)) Z = Z.reshape(-1, 2) prior_values = multivariate_normal.pdf(Z, np.zeros(2), np.identity(2)) prior_values = prior_values.reshape(100, 100) ax2.contour(X_, Y_, prior_values, cmap="inferno") ax2.set_title("Samples from the posterior distribution\n" "The contour plot shows the prior distribution.") plt.pause(0.001) if interactive: if np.size(predictions): colorbar.remove() colorbar_2.remove() return True