def plot_image_scatter(data: DataFrame, ax_in: Axes, img: Image) -> list: """Creates a scatter plot using the images instead of points on ax_in. Arguments: data {DataFrame} -- Provides xCoordinate and yCoordinate ax_in {Axes} -- Target axes for the plot. img {Image} -- PIL Image already sized to be placed on plot. Returns: list -- List of created AnnotationBbox objects """ img_boxes = [] for _, row in data.iterrows(): imagebox = OffsetImage(img) imagebox.image.axes = ax_in pos = (row['xCoordinate'], row['yCoordinate']) ab = AnnotationBbox(imagebox, pos, xycoords='data', boxcoords="offset points", box_alignment=(0.5, 0.5), pad=0, frameon=False) ax_in.add_artist(ab) ab.set_zorder(2) img_boxes.append(ab) return img_boxes
def plot_2d(self, ax_2d: Axes, **kwargs) -> None: """ Plot the circle in 2D. Parameters ---------- ax_2d : Axes Instance of :class:`~matplotlib.axes.Axes`. kwargs : dict, optional Additional keywords passed to :Class:`matplotlib.patches.Circle`. Examples -------- .. plot:: :include-source: >>> import matplotlib.pyplot as plt >>> from skspatial.objects import Circle >>> circle = Circle([-2, 3], 3) >>> fig, ax = plt.subplots() >>> circle.plot_2d(ax, fill=False) >>> circle.point.plot_2d(ax) >>> limits = plt.axis([-10, 10, -10, 10]) """ circle = plt.Circle(self.point, self.radius, **kwargs) ax_2d.add_artist(circle)
def __init__(self, ax: Axes, numpages = 10, valinit=0, valfmt='%1d', **kwargs ): self.facecolor=kwargs.get('facecolor',"yellow") self.activecolor = kwargs.pop('activecolor',"blue" ) self.stepcolor = kwargs.pop('stepcolor', "#ff6f6f" ) self.on_animcolor = kwargs.pop('on-animcolor', "#006622") self.fontsize = kwargs.pop('fontsize', 10) self.maxIndexedPages = 24 self.numpages = numpages self.axes = ax super(PageSlider, self).__init__(ax, "", 0, numpages, valinit=valinit, valfmt=valfmt, **kwargs) self.poly.set_visible(False) self.vline.set_visible(False) self.pageRects = [] indexMod = math.ceil( self.numpages / self.maxIndexedPages ) for i in range(numpages): facecolor = self.activecolor if i==valinit else self.facecolor r = matplotlib.patches.Rectangle((float(i)/numpages, 0), 1./numpages, 1, transform=ax.transAxes, facecolor=facecolor) ax.add_artist(r) self.pageRects.append(r) if i % indexMod == 0: ax.text(float(i)/numpages+0.5/numpages, 0.5, str(i+1), ha="center", va="center", transform=ax.transAxes, fontsize=self.fontsize) self.valtext.set_visible(False) divider = make_axes_locatable(ax) bax = divider.append_axes("right", size="5%", pad=0.05) fax = divider.append_axes("right", size="5%", pad=0.05) self.button_back = matplotlib.widgets.Button(bax, label='$\u25C1$', color=self.stepcolor, hovercolor=self.activecolor) self.button_forward = matplotlib.widgets.Button(fax, label='$\u25B7$', color=self.stepcolor, hovercolor=self.activecolor) self.button_back.label.set_fontsize(self.fontsize) self.button_forward.label.set_fontsize(self.fontsize) self.button_back.on_clicked(self.backward) self.button_forward.on_clicked(self. forward)
def __init__(self, ax: Axes, numpages = 10, valinit=0, valfmt='%1d', **kwargs ): self.facecolor=kwargs.get('facecolor',"yellow") self.activecolor = kwargs.pop('activecolor',"blue" ) self.stepcolor = kwargs.pop('stepcolor', "#ff6f6f" ) self.animcolor = kwargs.pop('animcolor', "#6fff6f" ) self.on_animcolor = kwargs.pop('on-animcolor', "#006622") self.fontsize = kwargs.pop('fontsize', 10) self.animation_controls = kwargs.pop('dynamic', True ) self.maxIndexedPages = 24 self.numpages = numpages self.init_anim_delay: float = 0.5 # time between timer events in seconds self.anim_delay: float = self.init_anim_delay self.anim_delay_multiplier = 1.5 self.anim_state = ADirection.STOP self.axes = ax self.event_source = EventSource( self.step, delay = self.init_anim_delay ) super(PageSlider, self).__init__(ax, "", 0, numpages, valinit=valinit, valfmt=valfmt, **kwargs) self.poly.set_visible(False) self.vline.set_visible(False) self.pageRects = [] indexMod = math.ceil( self.numpages / self.maxIndexedPages ) for i in range(numpages): facecolor = self.activecolor if i==valinit else self.facecolor r = matplotlib.patches.Rectangle((float(i)/numpages, 0), 1./numpages, 1, transform=ax.transAxes, facecolor=facecolor) ax.add_artist(r) self.pageRects.append(r) if i % indexMod == 0: ax.text(float(i)/numpages+0.5/numpages, 0.5, str(i+1), ha="center", va="center", transform=ax.transAxes, fontsize=self.fontsize) self.valtext.set_visible(False) divider = make_axes_locatable(ax) bax = divider.append_axes("right", size="5%", pad=0.05) fax = divider.append_axes("right", size="5%", pad=0.05) self.button_back = matplotlib.widgets.Button(bax, label='$\u25C1$', color=self.stepcolor, hovercolor=self.activecolor) self.button_forward = matplotlib.widgets.Button(fax, label='$\u25B7$', color=self.stepcolor, hovercolor=self.activecolor) self.button_back.label.set_fontsize(self.fontsize) self.button_forward.label.set_fontsize(self.fontsize) self.button_back.on_clicked(self.step_backward) self.button_forward.on_clicked(self.step_forward) if self.animation_controls: afax = divider.append_axes("left", size="5%", pad=0.05) asax = divider.append_axes("left", size="5%", pad=0.05) abax = divider.append_axes("left", size="5%", pad=0.05) self.button_aback = matplotlib.widgets.Button( abax, label='$\u25C0$', color=self.animcolor, hovercolor=self.activecolor) self.button_astop = matplotlib.widgets.Button( asax, label='$\u25FE$', color=self.animcolor, hovercolor=self.activecolor) self.button_aforward = matplotlib.widgets.Button( afax, label='$\u25B6$', color=self.animcolor, hovercolor=self.activecolor) self.button_aback.label.set_fontsize(self.fontsize) self.button_astop.label.set_fontsize(self.fontsize) self.button_aforward.label.set_fontsize(self.fontsize) self.button_aback.on_clicked(self.anim_backward) self.button_astop.on_clicked(self.anim_stop) self.button_aforward.on_clicked(self.anim_forward)
def _plot_color_wheel(ax: Axes, font_size: int, use_degrees: Optional[bool] = False) -> None: """Plots a color wheel on the given Axes object.""" try: import seaborn as sns except ImportError: raise ImportError( 'Must have seaborn installed to use plot_state_pixel or' ' plot_state_qpshere. To install, run "pip install seaborn".') n = 64 theta = np.ones(n) ax.pie(theta, colors=sns.color_palette("hls", n), radius=0.75) ax.add_artist(Circle((0, 0), 0.5, color='white', zorder=1)) offset = 0.95 # since radius of sphere is one. if use_degrees: labels = ['Phase\n(Deg)', '0', '90', '180 ', '270'] else: labels = ['Phase', '$0$', '$\\pi/2$', '$\\pi$', '$3\\pi/2$'] ax.text(0, 0, labels[0], horizontalalignment='center', verticalalignment='center', fontsize=font_size) ax.text(offset, 0, labels[1], horizontalalignment='center', verticalalignment='center', fontsize=font_size) ax.text(0, offset, labels[2], horizontalalignment='center', verticalalignment='center', fontsize=font_size) ax.text(-offset, 0, labels[3], horizontalalignment='center', verticalalignment='center', fontsize=font_size) ax.text(0, -offset, labels[4], horizontalalignment='center', verticalalignment='center', fontsize=font_size)
def plot_cross_cut(): #plot cut plane with crossection of cut fibers fig55 = figure(55) title('Cut fibers area (ellipses)') ax55 = Axes(fig55, [.1, .1, .8, .8]) fig55.add_axes(ax55) for i in range(0, len(phi_x_cut)): sy_c = sy_cut[i] + (sec - sx_cut[i]) / cos(phi_x_cut[i]) * sin(phi_x_cut[i]) * cos(theta_cut[i]) sz_c = sz_cut[i] + (sec - sx_cut[i]) / cos(phi_x_cut[i]) * sin(phi_x_cut[i]) * sin(theta_cut[i]) if (0 < phi_x_cut[i] < arctan((fib.lf) / fib.df)) and (sx_cut[i] - fib.lf / 2. * cos(phi_x_cut[i]) + fib.df / 2. * sin(phi_x_cut[i]) < sec < sx_cut[i] + fib.lf / 2. * cos(phi_x_cut[i]) - fib.df / 2. * sin(phi_x_cut[i])): patch = Ellipse([ sy_c, sz_c ] , fib.df, fib.df / cos(phi_x_cut[i]), theta_cut[i] * 180 / pi , color = 'black') ax55.add_artist(patch) ax55.set_xlim(-spec.l_y / 2., spec.l_y / 2.) ax55.set_ylim(-spec.l_z / 2., spec.l_z / 2.)
def preview(path, ext=0, width=None, minwidth=256, maxwidth=1024): """ Preview FITS image as PNG """ base = stdconf.get('basepath', '.') fullpath = os.path.join(base, path) # Optional parameters fmt = request.args.get('format', 'jpeg') quality = int(request.args.get('quality', 80)) width = request.args.get('width', width) if width is not None: width = int(width) data = fits.getdata(fullpath, ext) figsize = [data.shape[1], data.shape[0]] if width is None: if figsize[0] < minwidth: width = minwidth elif figsize[0] > maxwidth: width = maxwidth if width is not None and figsize[0] != width: figsize[1] = width*figsize[1]/figsize[0] figsize[0] = width fig = Figure(facecolor='white', dpi=72, figsize=(figsize[0]/72, figsize[1]/72)) ax = Axes(fig, [0., 0., 1., 1.]) # ax.set_axis_off() fig.add_axes(ax) plots.imshow(data, ax=ax, show_axis=False, show_colorbar=False, cmap=request.args.get('cmap', 'Blues_r'), stretch=request.args.get('stretch', 'linear'), qq=[float(request.args.get('qmin', 0.5)), float(request.args.get('qmax', 99.5))]) if request.args.get('ra', None) is not None and request.args.get('dec', None) is not None: # Show the position of the object header = fits.getheader(fullpath, ext) wcs = WCS(header) x,y = wcs.all_world2pix(float(request.args.get('ra')), float(request.args.get('dec')), 0) ax.add_artist(Circle((x, y), 5.0, edgecolor='red', facecolor='none', ls='-', lw=2)) buf = io.BytesIO() fig.savefig(buf, format=fmt, quality=quality) return Response(buf.getvalue(), mimetype='image/%s' % fmt)
def kpiPlot(title: str, info: Union[int, str], color: str, ax: Axes): ax.pie([1], colors=[color], labels=[""]) centre_circle = plt.Circle((0, 0), 0.78, fc='white') ax.add_artist(centre_circle) ax.text(0, 1.45, title, va='top', ha='center', fontsize=18, weight='bold') ax.text(0, 0, prettyNumber(info), va='top', ha='center', fontsize=16, weight='bold') return ax
def add_mae_r2_box( xs: NDArray[np.float64], ys: NDArray[np.float64], ax: Axes = None, loc: str = "lower right", prefix: str = "", suffix: str = "", prec: int = 3, **kwargs: Any, ) -> AnchoredText: """Provide a set of x and y values of equal length and an optional Axes object on which to print the values' mean absolute error and R^2 coefficient of determination. Args: xs (array, optional): x values. ys (array, optional): y values. ax (Axes, optional): matplotlib Axes on which to add the box. Defaults to None. loc (str, optional): Where on the plot to place the AnchoredText object. Defaults to "lower right". prec (int, optional): # of decimal places in printed metrics. Defaults to 3. prefix (str, optional): Title or other string to prepend to metrics. Defaults to "". suffix (str, optional): Text to append after metrics. Defaults to "". Returns: AnchoredText: Instance containing the metrics. """ if ax is None: ax = plt.gca() mask = ~np.isnan(xs) & ~np.isnan(ys) xs, ys = xs[mask], ys[mask] text = f"{prefix}$\\mathrm{{MAE}} = {np.abs(xs - ys).mean():.{prec}f}$" text += f"\n$R^2 = {r2_score(xs, ys):.{prec}f}${suffix}" frameon: bool = kwargs.pop("frameon", False) text_box = AnchoredText(text, loc=loc, frameon=frameon, **kwargs) ax.add_artist(text_box) return text_box
def plot_ellipses(subplot: Axes, x_avg: float, y_avg: float, x_std: float, y_std: float, ellipse_color: str = 'b') -> None: std_ellipse = Ellipse(xy=(x_avg, y_avg), width=x_std * 2, height=y_std * 2, fill=False, edgecolor=ellipse_color, linestyle='dashed') double_std_ellipse = Ellipse(xy=(x_avg, y_avg), width=x_std * 4, height=y_std * 4, fill=False, edgecolor=ellipse_color) subplot.add_artist(std_ellipse) subplot.add_artist(double_std_ellipse)
def _plot(self, ax: Axes, position_kwargs: dict, heading_kwargs: dict): """ adds a representation of this critter to matplotlib axis object position_kwargs should likely have keys [radius, zorder, facecolor, edgecolor] heading_kwargs should likely have keys [color, linewidth, zorder] """ # position p0 = self.location.position patch = CirclePolygon(p0, **position_kwargs) ax.add_artist(patch) # heading indicator if "hlen" not in heading_kwargs.keys(): hlen = 0.08 else: hlen = heading_kwargs["hlen"] p1 = (cos(self.location.heading) * hlen + p0[0], sin(self.location.heading) * hlen + p0[1]) line = Line2D(p0, p1, **heading_kwargs) ax.add_line(line) return ax
def add_artist(self, a, path_interpolation=None): ''' Modified :meth:`matplotlib.axes.Axes.add_artist`. Enables the interpolation of a given artist, e.g. a line or rectangle Keyword arguments: *a*: Artist to be added Accepts: :class:`matplotlib.artist.Artist` instance *path_interpolation`: if set, the path of the artist will be interpolated with the given value. If set to 0, bezier arcs are used to connect. ''' if path_interpolation is not None: if hasattr(a, "get_path"): a.get_path()._interpolation_steps = path_interpolation else: raise AttributeError("Artist has no Path") return Axes.add_artist(self, a)
def imscatter( x: np.ndarray, y: np.ndarray, ax: Axes, imageData: torch.Tensor, unnormalize_fn: Optional[Callable] = None, zoom: int = 1, ) -> NoReturn: """Scatter plot with images instead of points on ax.""" images = [] for i in range(len(x)): x0, y0 = x[i], y[i] # Convert to image img = imageData[i] if unnormalize_fn is not None: img = unnormalize_fn(img) img *= 255.0 img = img.permute([1, 2, 0]).numpy().astype(np.uint8) image = OffsetImage(img, zoom=zoom) ab = AnnotationBbox(image, (x0, y0), xycoords="data", frameon=False) images.append(ax.add_artist(ab)) ax.update_datalim(np.column_stack([x, y])) ax.autoscale()
def plot_station_positions(directions_file_path: Path, stations: list, ax: Axes, grid_config: GridConfig=default_domains.bc_mh_044, save_upstream_boundaries_to_shp=False): with Dataset(str(directions_file_path)) as ds: flow_dirs = ds.variables["flow_direction_value"][:] flow_acc_area = ds.variables["accumulation_area"][:] lons_2d, lats_2d = [ds.variables[k][:] for k in ["lon", "lat"]] basemap, reg_of_interest = grid_config.get_basemap_using_shape_with_polygons_of_interest(lons_2d, lats_2d, shp_path=default_domains.MH_BASINS_PATH, resolution="i") cell_manager = CellManager(flow_dirs, lons2d=lons_2d, lats2d=lats_2d, accumulation_area_km2=flow_acc_area) station_to_model_point = cell_manager.get_model_points_for_stations(station_list=stations, nneighbours=8) ##### xx, yy = basemap(lons_2d, lats_2d) upstream_edges = cell_manager.get_upstream_polygons_for_points( model_point_list=list(station_to_model_point.values()), xx=xx, yy=yy) upstream_edges_latlon = cell_manager.get_upstream_polygons_for_points( model_point_list=list(station_to_model_point.values()), xx=lons_2d, yy=lats_2d) plot_utils.draw_upstream_area_bounds(ax, upstream_edges=upstream_edges, color="r", linewidth=0.6) if save_upstream_boundaries_to_shp: plot_utils.save_to_shape_file(upstream_edges_latlon, folder_path="mh/engage_report/upstream_stations_areas/mh_{}".format(grid_config.dx), in_proj=None) basemap.drawrivers(linewidth=0.2) basemap.drawstates(linewidth=0.1) basemap.drawcountries(linewidth=0.1) basemap.drawcoastlines(linewidth=0.2) pos_ids, lons_pos, lats_pos = [], [], [] pos_labels = [] legend_lines = [] for i, (s, mp) in enumerate(sorted(station_to_model_point.items(), key=lambda p: p[0].latitude, reverse=True), start=1): pos_ids.append(s.id) pos_labels.append(i) lons_pos.append(mp.longitude) lats_pos.append(mp.latitude) legend_lines.append("{}: {}".format(i, s.id)) xm, ym = basemap(lons_pos, lats_pos) ax.scatter(xm, ym, c="g", s=20) for txt, x1, y1, pos_label in zip(pos_ids, xm, ym, pos_labels): ax.annotate(pos_label, xy=(x1, y1)) at = AnchoredText("\n".join(legend_lines), prop=dict(size=8), frameon=True, loc=1) at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2") ax.add_artist(at)
def plot(self, ax: Axes = None, show_image=True, labels=None, objects=None, alpha=0.6, ls='-'): # Reuse the current axis if none was passed in ax = ax or plt.gca() # I am now using this same class for the ENTIRE image as well # as for sub images of facades. if show_image: if self.extent: ax.imshow(self.image, zorder=-1, extent=self.extent) else: ax.imshow(self.image, zorder=-1) if self.extent: ax.set_xbound(self.extent[0], self.extent[1]) ax.set_ybound(self.extent[2], self.extent[3]) # If this is a subimage of a facade, use the JSON file to # determine the actual facade polygon if self.dat is not None and self.annotation is None: pts = array(self.dat.polygon) p = Polygon(pts, color=[0, 0, 0], zorder=self.z_orders['facade'], fill=False, alpha=alpha, hatch='/') ax.add_patch(p) return if objects is None: objects = self.iter_objects(labels) else: objects = objects for o in objects: n = o.name z = self.z_orders[n] c = self.colors[z] / 255. pts = self.unrectified(o.polygon.pt) # Just in case -- I think I have pruned out deleted records but if # any remain, render them with a black crosshatch overlaid. if o.deleted: ax.add_patch( Polygon(pts, color='k', hatch='+', fill=False, zorder=50)) else: ax.add_patch( Polygon(pts, color=c, edgecolor=None, zorder=z, linestyle=ls, alpha=alpha)) ax.add_patch( Polygon(pts, color=c, lw=2, linestyle=ls, fill=False, zorder=50)) ax.add_artist(Text(*pts.mean(0), o.name, zorder=55))
def plot_z_trend_histogram(self, axis: Axes = None, polar: bool = True, normed: bool = True) -> None: if axis is None: axis = self.figure.add_subplot(111) cluster = Cluster(simulation_name=self.simulation.simulation_name, clusterID=0, redshift='z000p000') aperture_float = self.get_apertures(cluster)[ self.aperture_id] / cluster.r200 if not os.path.isfile( os.path.join( self.path, f'redshift_rot0rot4_histogram_aperture_{self.aperture_id}.npy' )): warnings.warn( f"File redshift_rot0rot4_histogram_aperture_{self.aperture_id}.npy not found." ) print("self.make_simhist() activated.") self.make_simhist() print( f"Retrieving npy files: redshift_rot0rot4_histogram_aperture_{self.aperture_id}.npy" ) sim_hist = np.load(os.path.join( self.path, f'redshift_rot0rot4_histogram_aperture_{self.aperture_id}.npy'), allow_pickle=True) sim_hist = np.asarray(sim_hist) if normed: norm_factor = np.sum(self.simulation.sample_completeness) sim_hist[2] /= norm_factor sim_hist[3] /= norm_factor y_label = r"Sample fraction" else: y_label = r"Number of samples" items_labels = f""" REDSHIFT TRENDS - HISTOGRAM Number of clusters: {self.simulation.totalClusters:d} $z$ = 0.0 - 1.8 Total samples: {np.sum(self.simulation.sample_completeness):d} $\equiv N_\mathrm{{clusters}} \cdot N_\mathrm{{redshifts}}$ Aperture radius = {aperture_float:.2f} $R_{{200\ true}}$""" print(items_labels) sim_colors = { 'ceagle': 'pink', 'celr_e': 'lime', 'celr_b': 'orange', 'macsis': 'aqua', } axis.axvline(90, linestyle='--', color='k', alpha=0.5, linewidth=2) axis.step(sim_hist[0], sim_hist[2], color=sim_colors[self.simulation.simulation_name], where='mid') axis.fill_between(sim_hist[0], sim_hist[2] + sim_hist[3], sim_hist[2] - sim_hist[3], step='mid', color=sim_colors[self.simulation.simulation_name], alpha=0.2, edgecolor='none', linewidth=0) axis.set_ylabel(y_label, size=25) axis.set_xlabel( r"$\Delta \theta \equiv (\mathbf{L}_\mathrm{gas},\mathrm{\widehat{CoP}},\mathbf{L}_\mathrm{stars})$\quad[degrees]", size=25) axis.set_xlim(0, 180) axis.set_ylim(0, 0.1) axis.text(0.03, 0.97, items_labels, horizontalalignment='left', verticalalignment='top', transform=axis.transAxes, size=15) if polar: inset_axis = self.figure.add_axes([0.75, 0.65, 0.25, 0.25], projection='polar') inset_axis.patch.set_alpha(0) # Transparent background inset_axis.set_theta_zero_location('N') inset_axis.set_thetamin(0) inset_axis.set_thetamax(180) inset_axis.set_xticks(np.pi / 180. * np.linspace(0, 180, 5, endpoint=True)) inset_axis.set_yticks([]) inset_axis.step(sim_hist[0] / 180 * np.pi, sim_hist[2], color=sim_colors[self.simulation.simulation_name], where='mid') inset_axis.fill_between( sim_hist[0] / 180 * np.pi, sim_hist[2] + sim_hist[3], sim_hist[2] - sim_hist[3], step='mid', color=sim_colors[self.simulation.simulation_name], alpha=0.2, edgecolor='none', linewidth=0) patch_ceagle = Patch(facecolor=sim_colors['ceagle'], label='C-EAGLE', edgecolor='k', linewidth=1) patch_celre = Patch(facecolor=sim_colors['celr_e'], label='CELR-E', edgecolor='k', linewidth=1) patch_celrb = Patch(facecolor=sim_colors['celr_b'], label='CELR-B', edgecolor='k', linewidth=1) patch_macsis = Patch(facecolor=sim_colors['macsis'], label='MACSIS', edgecolor='k', linewidth=1) leg2 = axis.legend( handles=[patch_ceagle, patch_celre, patch_celrb, patch_macsis], loc='lower center', handlelength=1, fontsize=20) axis.add_artist(leg2)
def qq_gaussian( y_true: NumArray, y_pred: NumArray, y_std: NumArray | dict[str, NumArray], ax: Axes = None, ) -> Axes: """Plot the Gaussian quantile-quantile (Q-Q) plot of one (passed as array) or multiple (passed as dict) sets of uncertainty estimates for a single pair of ground truth targets `y_true` and model predictions `y_pred`. Overconfidence relative to a Gaussian distribution is visualized as shaded areas below the parity line, underconfidence (oversized uncertainties) as shaded areas above the parity line. The measure of calibration is how well the uncertainty percentiles conform to those of a normal distribution. Inspired by https://git.io/JufOz. Info on Q-Q plots: https://wikipedia.org/wiki/Q-Q_plot Args: y_true (array): ground truth targets y_pred (array): model predictions y_std (array | dict[str, array]): model uncertainties ax (Axes): matplotlib Axes on which to plot. Defaults to None. Returns: ax: The plot's matplotlib Axes. """ if ax is None: ax = plt.gca() if isinstance(y_std, np.ndarray): y_std = {"std": y_std} res = np.abs(y_pred - y_true) resolution = 100 lines = [] # collect plotted lines to show second legend with miscalibration areas for key, std in y_std.items(): z_scored = (np.array(res) / std).reshape(-1, 1) exp_proportions = np.linspace(0, 1, resolution) gaussian_upper_bound = norm.ppf(0.5 + exp_proportions / 2) obs_proportions = np.mean(z_scored <= gaussian_upper_bound, axis=0) [line] = ax.plot( exp_proportions, obs_proportions, linewidth=2, alpha=0.8, label=key ) ax.fill_between( exp_proportions, y1=obs_proportions, y2=exp_proportions, alpha=0.2 ) miscal_area = np.trapz( np.abs(obs_proportions - exp_proportions), dx=1 / resolution ) lines.append([line, miscal_area]) # identity line ax.axline((0, 0), (1, 1), alpha=0.5, zorder=0, linestyle="dashed", color="black") ax.set(xlim=(0, 1), ylim=(0, 1)) ax.set(xlabel="Theoretical Quantile", ylabel="Observed Quantile") legend1 = ax.legend(loc="upper left", frameon=False) # Multiple legends on the same axes: # https://matplotlib.org/3.3.3/tutorials/intermediate/legend_guide.html#multiple-legends-on-the-same-axes ax.add_artist(legend1) lines, areas = zip(*lines) if len(lines) > 1: legend2 = ax.legend( lines, [f"{area:.2f}" for area in areas], title="Miscalibration areas", loc="lower right", ncol=2, frameon=False, ) legend2._legend_box.align = "left" # https://stackoverflow.com/a/44620643 else: ax.legend( lines, [f"Miscalibration area: {areas[0]:.2f}"], loc="lower right", frameon=False, ) return ax
def plot_z_trends(self, axis: Axes = None) -> None: if axis is None: axis = self.figure.add_subplot(111) cluster = Cluster(simulation_name=self.simulation.simulation_name, clusterID=0, redshift='z000p000') aperture_float = self.get_apertures(cluster)[ self.aperture_id] / cluster.r200 if not os.path.isfile( os.path.join( self.path, f'redshift_rot0rot4_bootstrap_aperture_{self.aperture_id}.npy' )): warnings.warn( f"File redshift_rot0rot4_bootstrap_aperture_{self.aperture_id}.npy not found." ) print("self.make_simbootstrap() activated.") self.make_simbootstrap() print( f"Retrieving npy files: redshift_rot0rot4_bootstrap_aperture_{self.aperture_id}.npy" ) sim_bootstrap = np.load(os.path.join( self.path, f'redshift_rot0rot4_bootstrap_aperture_' f'{self.aperture_id}.npy'), allow_pickle=True) sim_bootstrap = np.asarray(sim_bootstrap) items_labels = f""" REDSHIFT TRENDS Number of clusters: {self.simulation.totalClusters:d} $z$ = 0.0 - 1.8 Aperture radius = {aperture_float:.2f} $R_{{200\ true}}$""" print(items_labels) sim_colors = { 'ceagle': 'pink', 'celr_e': 'lime', 'celr_b': 'orange', 'macsis': 'aqua', } axis.axhline(90, linestyle='--', color='k', alpha=0.5, linewidth=2) axis.plot(sim_bootstrap[0, 0], sim_bootstrap[3, 0], color=sim_colors[self.simulation.simulation_name], alpha=1, linestyle='none', marker='^', markersize=10) axis.plot(sim_bootstrap[0, 0], sim_bootstrap[2, 0], color=sim_colors[self.simulation.simulation_name], alpha=1, linestyle='none', marker='o', markersize=10) axis.plot(sim_bootstrap[0, 0], sim_bootstrap[1, 0], color=sim_colors[self.simulation.simulation_name], alpha=1, linestyle='none', marker='v', markersize=10) for marker_index in range(len(sim_bootstrap[0, 0])): if marker_index is 0: align_toggle = 'edge' x_edge_left = sim_bootstrap[0, 0][marker_index] x_edge_right = sim_bootstrap[ 0, 0][marker_index] + sim_bootstrap[0, 1][marker_index] else: align_toggle = 'center' x_edge_left = sim_bootstrap[ 0, 0][marker_index] - sim_bootstrap[0, 1][marker_index] / 2 x_edge_right = sim_bootstrap[ 0, 0][marker_index] + sim_bootstrap[0, 1][marker_index] / 2 axis.plot([x_edge_left, x_edge_right], [ sim_bootstrap[3, 0][marker_index], sim_bootstrap[3, 0][marker_index] ], color=sim_colors[self.simulation.simulation_name], alpha=0.8, linestyle='--', lw=1.5) axis.plot([x_edge_left, x_edge_right], [ sim_bootstrap[2, 0][marker_index], sim_bootstrap[2, 0][marker_index] ], color=sim_colors[self.simulation.simulation_name], alpha=0.8, linestyle='-', lw=1.5) axis.plot([x_edge_left, x_edge_right], [ sim_bootstrap[1, 0][marker_index], sim_bootstrap[1, 0][marker_index] ], color=sim_colors[self.simulation.simulation_name], alpha=0.8, linestyle='-.', lw=1.5) axis.bar(sim_bootstrap[0, 0][marker_index], 2 * sim_bootstrap[3, 1][marker_index], bottom=sim_bootstrap[3, 0][marker_index] - sim_bootstrap[3, 1][marker_index], width=sim_bootstrap[0, 1][marker_index], align=align_toggle, color=sim_colors[self.simulation.simulation_name], alpha=0.2, edgecolor='none', linewidth=0) axis.bar(sim_bootstrap[0, 0][marker_index], 2 * sim_bootstrap[2, 1][marker_index], bottom=sim_bootstrap[2, 0][marker_index] - sim_bootstrap[2, 1][marker_index], width=sim_bootstrap[0, 1][marker_index], align=align_toggle, color=sim_colors[self.simulation.simulation_name], alpha=0.2, edgecolor='none', linewidth=0) axis.bar(sim_bootstrap[0, 0][marker_index], 2 * sim_bootstrap[1, 1][marker_index], bottom=sim_bootstrap[1, 0][marker_index] - sim_bootstrap[1, 1][marker_index], width=sim_bootstrap[0, 1][marker_index], align=align_toggle, color=sim_colors[self.simulation.simulation_name], alpha=0.2, edgecolor='none', linewidth=0) perc84 = Line2D([], [], color='k', marker='^', linestyle='--', markersize=10, label=r'$84^{th}$ percentile') perc50 = Line2D([], [], color='k', marker='o', linestyle='-', markersize=10, label=r'median') perc16 = Line2D([], [], color='k', marker='v', linestyle='-.', markersize=10, label=r'$16^{th}$ percentile') patch_ceagle = Patch(facecolor=sim_colors['ceagle'], label='C-EAGLE', edgecolor='k', linewidth=1) patch_celre = Patch(facecolor=sim_colors['celr_e'], label='CELR-E', edgecolor='k', linewidth=1) patch_celrb = Patch(facecolor=sim_colors['celr_b'], label='CELR-B', edgecolor='k', linewidth=1) patch_macsis = Patch(facecolor=sim_colors['macsis'], label='MACSIS', edgecolor='k', linewidth=1) leg1 = axis.legend(handles=[perc84, perc50, perc16], loc='lower right', handlelength=3, fontsize=20) leg2 = axis.legend( handles=[patch_ceagle, patch_celre, patch_celrb, patch_macsis], loc='lower left', handlelength=1, fontsize=20) axis.add_artist(leg1) axis.add_artist(leg2) axis.text(0.03, 0.97, items_labels, horizontalalignment='left', verticalalignment='top', transform=axis.transAxes, size=15) axis.set_xlabel(r"$z$", size=25) axis.set_ylabel( r"$\Delta \theta \equiv (\mathbf{L},\mathrm{\widehat{CoP}},\mathbf{v_{pec}})$\quad[degrees]", size=25) axis.set_ylim(0, 180)
def _draw_grid_world(self, axis: Axes) -> None: draw_kwargs: Dict[str, Any] = dict(linestyle="-", color="k", alpha=0.5) col: int for col in range(self.width): axis.plot((col - 0.5) * np.ones(2), [-0.5, self.height - 0.5], **draw_kwargs) axis.plot((self.width - 0.5) * np.ones(2), [-0.5, self.height - 0.5], **draw_kwargs) row: int for row in range(self.height): axis.plot([-0.5, self.width - 0.5], (row - 0.5) * np.ones(2), **draw_kwargs) axis.plot([-0.5, self.width - 0.5], (self.height - 0.5) * np.ones(2), **draw_kwargs) axis.add_artist( plt.Circle( self.get_start_state(), radius=GridWorld.ARROW_LENGTH * 0.5 * 1.1, color="b", fill=False, )) for terminal_state in self.get_terminal_states(): axis.add_artist( plt.Circle( terminal_state, radius=GridWorld.ARROW_LENGTH * 0.5 * 1.1, color="k", fill=True, )) xlim: Tuple[int, int] = [-1.0, self.width] ylim: Tuple[int, int] = [-1.0, self.height] # TODO adding typing from here if self.upward_wind_list: for col in range(self.width): axis.text( col, -1.0, f"{self.upward_wind_list[col]:.1f}", ha="center", va="top", ) ylim[0] = -1.5 if self.rightward_wind_list: for row in range(self.height): axis.text(-1.0, row, f"{self.rightward_wind_list[row]:.1f}") xlim[0] = -1.5 axis.set_xlim(xlim) axis.set_ylim(ylim) axis.axis("equal") axis.axis("off")
def draw_regions1d(regions: RegionSet, plot: Axes, **kwargs): """ Draws the Regions on a 1D plot, to visualize the overlapping or intersecting Regions (or intervals). Args: regions: The set of 1D Regions to draw. plot: The matplotlib plot to draw on. kwargs: Additional arguments and options. Keyword Args: colored: Boolean flag for colored output or greyscale. If True, color codes the Regions based on the Region's stored 'color' data property. Otherwise, all Regions have black edges with transparent faces. communities: Boolean flag for whether or not to show the connected communities (or Regions with same color). Requires colored to be True. tightbounds: Boolean flag for whether or not to reduce the bounding size to the minimum bounding Region, instead of the defined bounds. """ assert regions.dimension == 1 black = (0, 0, 0) groups = {} colored = kwargs.get('colored', False) communities = kwargs.get('communities', False) tightbounds = kwargs.get('tightbounds', False) bbox = regions.bbox if tightbounds else regions.minbounds spacing = max(bbox[0].length / len(regions), 10) if colored and communities: for region in regions: color = region.getdata('color') if color is not None: group = groups.setdefault(tuple(color), RegionSet(dimension=1)) group.add(region) for color, group in groups.items(): gbbox = group.bbox[0] lows = (gbbox.lower, 0) w, h = (gbbox.length, spacing * (len(regions) + 2)) rectangle = Rectangle(lows, w, h, facecolor=(*color, 0.05), edgecolor='none') rectangle.set_clip_box(plot) plot.add_artist(rectangle) for i, region in enumerate(regions): color = region.getdata('color', black) if colored else black plot.plot(list(astuple(region[0])), [spacing * (i + 1)] * 2, color=color) plot.set_xlim(astuple(bbox[0])) plot.yaxis.set_visible(False)
def draw_regions2d(regions: RegionSet, plot: Axes, **kwargs): """ Draws the Regions on a 2D plot, to visualize the overlapping or intersecting Regions (or rectangles). Args: regions: The set of 2D Regions to draw. plot: The matplotlib plot to draw on. kwargs: Additional arguments and options. Keyword Args: colored: Boolean flag for colored output or greyscale. If True, color codes the Regions based on the Region's stored 'color' data property. Otherwise, all Regions have black edges with transparent faces. communities: Boolean flag for whether or not to show the connected communities (or Regions with same color). Requires colored to be True. tightbounds: Boolean flag for whether or not to reduce the bounding size to the minimum bounding Region, instead of the defined bounds. """ assert regions.dimension == 2 black = (0, 0, 0) groups = {} colored = kwargs.get('colored', False) communities = kwargs.get('communities', False) tightbounds = kwargs.get('tightbounds', False) bbox = regions.bbox if tightbounds else regions.minbounds def mkrectangle(region: Region): lower = tuple(region[d].lower for d in range(2)) w, h = tuple(region[d].length for d in range(2)) return lower, w, h if colored and communities: for region in regions: color = region.getdata('color') if color is not None: group = groups.setdefault(tuple(color), RegionSet(dimension=2)) group.add(region) for color, group in groups.items(): rectangle = Rectangle(*mkrectangle(group.bbox), facecolor=(*color, 0.05), edgecolor='none') rectangle.set_clip_box(plot) plot.add_artist(rectangle) for region in regions: color = region.getdata('color', black) if colored else black rectangle = Rectangle(*mkrectangle(region), facecolor=(*color, 0.1), edgecolor=color) rectangle.set_clip_box(plot) plot.add_artist(rectangle) plot.set_xlim(astuple(bbox[0])) plot.set_ylim(astuple(bbox[1]))