def __init__(self, artists, x, y): self.line = artists[0] self.text = artists[1] if len(artists) > 1 else None self.x = x self.y = y Container.__init__(self, artists)
def addCurve(self, x, y, legend, color, symbol, linewidth, linestyle, yaxis, xerror, yerror, z, selectable, fill, alpha): for parameter in (x, y, legend, color, symbol, linewidth, linestyle, yaxis, z, selectable, fill): assert parameter is not None assert yaxis in ('left', 'right') if (len(color) == 4 and type(color[3]) in [type(1), numpy.uint8, numpy.int8]): color = numpy.array(color, dtype=numpy.float) / 255. if yaxis == "right": axes = self.ax2 self._enableAxis("right", True) else: axes = self.ax picker = 3 if selectable else None artists = [] # All the artists composing the curve # First add errorbars if any so they are behind the curve if xerror is not None or yerror is not None: if hasattr(color, 'dtype') and len(color) == len(x): errorbarColor = 'k' else: errorbarColor = color # On Debian 7 at least, Nx1 array yerr does not seems supported if (yerror is not None and yerror.ndim == 2 and yerror.shape[1] == 1 and len(x) != 1): yerror = numpy.ravel(yerror) errorbars = axes.errorbar(x, y, label=legend, xerr=xerror, yerr=yerror, linestyle=' ', color=errorbarColor) artists += list(errorbars.get_children()) if hasattr(color, 'dtype') and len(color) == len(x): # scatter plot if color.dtype not in [numpy.float32, numpy.float]: actualColor = color / 255. else: actualColor = color if linestyle not in ["", " ", None]: # scatter plot with an actual line ... # we need to assign a color ... curveList = axes.plot(x, y, label=legend, linestyle=linestyle, color=actualColor[0], linewidth=linewidth, picker=picker, marker=None) artists += list(curveList) scatter = axes.scatter(x, y, label=legend, color=actualColor, marker=symbol, picker=picker) artists.append(scatter) if fill: artists.append( axes.fill_between(x, 1.0e-8, y, facecolor=actualColor[0], linestyle='')) else: # Curve curveList = axes.plot(x, y, label=legend, linestyle=linestyle, color=color, linewidth=linewidth, marker=symbol, picker=picker) artists += list(curveList) if fill: artists.append(axes.fill_between(x, 1.0e-8, y, facecolor=color)) for artist in artists: artist.set_zorder(z) if alpha < 1: artist.set_alpha(alpha) return Container(artists)
def strain_glyph(x, strain, sigma=None, ext_color=(0.1215, 0.4666, 0.7058), cmp_color=(1.0000, 0.4980, 0.0549), alpha=0.4, linewidth=1.5, vert=500, scale=1.0, snr_mask=True, zorder=None): ''' Returns a container of artists making up a strain glyph. Parameters ---------- x : (2,) array Coordinates of the strain glyph. strain : (3,) array Components of the strain tensor specified as [e_xx,e_yy,_exy]. sigma : (3,) array or (3,3) array, optional Uncertainty on the strain components. This can either be the standard deviation uncertainty on the components specified as a (3,) array or it can be the covariance of the strain components specified as a (3,3) array. ext_color : str, optional Extensional color cmp_color : str, optional Compressional color alpha : float, optional Transparency of the uncertainty field linewidth : float, optional Thickness of the mean lines vert : int, optional Number of vertices used in the strain glyph. Higher values produce a higher resolution glyph at the expense of computational cost. scale : float, optional Scales the strain and uncertainty. snr_mask : bool, optional If True, then the strain glyph transparency will be determined by the signal-to-noise ratio (SNR). In this case, the SNR is the ratio of the strain magnitude to its uncertainty. The strain magnitude is the inner product of the strain matrix with itself. If the SNR is less than 1.0, then nothing will be returned. The glyph will be increasingly opaque for SNR ratios between 1.0 and 2.0. If the SNR is greater than 2.0 then the expected value lines will be opaque and the uncertainty field will be as specified with *alpha*. Returns ------- out : Container instance Contains the artists in the strain glyph. Use the *get_label* method to see which component of the strain glyph each artist describes. Examples -------- Plot a strain glyph which represents extension in the x direction and contraction in the y direction. >>> x = [0.5,0.5] >>> strain = [0.25,-0.25,0.0] >>> uncertainty = [0.1,0.1,0.1] >>> c = strain_glyph(x,strain,uncertainty) >>> fig,ax = plt.subplots() >>> for i in c: ax.add_artist(i) >>> plt.show() ''' x = np.asarray(x, dtype=float) strain = np.asarray(strain, dtype=float) if sigma is None: sigma = np.zeros((3, 3)) else: sigma = np.asarray(sigma, dtype=float) if sigma.shape == (3, 3): # if sigma was specified as a (3,3) covariance matrix then store # sigma as is cov = sigma elif sigma.shape == (3, ): # if sigma was specified as a (3,) standard deviation # uncertainty vector then convert it to a covariance matrix cov = np.diag(sigma**2) else: raise ValueError('*sigma* must be a (3,) or (3,3) array') # if either strain or cov are not finite then silently return an # empty container if ~np.all(np.isfinite(strain)) | ~np.all(np.isfinite(cov)): return Container([]) if snr_mask: min_snr = 1.0 # strain magnitude # (3,) array mag = np.sqrt(strain[0]**2 + strain[1]**2 + 2 * strain[2]**2) # Jacobian of strain magnitude. used for error propagation jac = np.array([strain[0] / mag, strain[1] / mag, 2 * strain[2] / mag]) mag_sigma = np.sqrt(jac.dot(cov).dot(jac)) snr = mag / mag_sigma if snr < min_snr: # return no glyph if snr is less than 1.0 return Container([]) elif (snr >= min_snr) & (snr < (min_snr + 1.0)): # return faded glyph if snr is between 1.0 and 2.0 snr_alpha = snr - min_snr else: # do not fade if snr > 2,0 snr_alpha = 1.0 else: # if snr_mask is False, then dont change glyph transparency snr_alpha = 1.0 # scale the data strain = scale * strain cov = scale**2 * cov # angles for each normal vector theta = np.linspace(0.0, 2 * np.pi, vert) # normal vectors n = np.array([np.cos(theta), np.sin(theta)]).T # This matrix maps the flattened strain tensor to normal strain # along each direction in *n* G = np.array([n[:, 0]**2, n[:, 1]**2, 2 * n[:, 0] * n[:, 1]]).T mean = G.dot(strain) # just compute the diagonals of the covariance matrix sigma = np.sqrt(np.sum(G.dot(cov) * G, axis=1)) artists = [] # make vertices for the line indicating the expected strain mean_vert = n * mean[:, None] # vertices associated with extension mean_vert_ext = mean_vert[mean >= 0.0] # vertices associated with compression mean_vert_cmp = mean_vert[mean < 0.0] # make vertices for the upper bound of strain ub_vert = n * (mean[:, None] + sigma[:, None]) ub_vert_ext = ub_vert[(mean + sigma) >= 0.0] ub_vert_cmp = ub_vert[(mean + sigma) < 0.0] # make vertices for the lower bound of strain lb_vert = n * (mean[:, None] - sigma[:, None]) lb_vert_ext = lb_vert[(mean - sigma) >= 0.0] lb_vert_cmp = lb_vert[(mean - sigma) < 0.0] # make the vertices defining the 1-sigma extension field sigma_vert_ext = np.vstack((ub_vert_ext, lb_vert_ext[::-1])) # make the vertices defining the 1-sigma compression field sigma_vert_cmp = np.vstack((ub_vert_cmp, lb_vert_cmp[::-1])) if mean_vert_ext.shape[0] != 0: artists += [ Polygon(x + mean_vert_ext, edgecolor=ext_color, facecolor='none', linewidth=linewidth, alpha=snr_alpha, zorder=zorder, label='extensional mean') ] if mean_vert_cmp.shape[0] != 0: artists += [ Polygon(x + mean_vert_cmp, edgecolor=cmp_color, facecolor='none', linewidth=linewidth, alpha=snr_alpha, zorder=zorder, label='compressional mean') ] if sigma_vert_ext.shape[0] != 0: artists += [ Polygon(x + sigma_vert_ext, facecolor=ext_color, edgecolor='none', alpha=alpha * snr_alpha, linewidth=linewidth, zorder=zorder, label='extensional confidence interval') ] if sigma_vert_cmp.shape[0] != 0: artists += [ Polygon(x + sigma_vert_cmp, facecolor=cmp_color, edgecolor='none', alpha=alpha * snr_alpha, linewidth=linewidth, zorder=zorder, label='compressional confidence interval') ] out = Container(artists) return out