def polar_map(hist: Histogram2D, ax: Axes, *, show_zero: bool = True, show_colorbar: bool = True, **kwargs): """Polar map of polar histograms. Similar to map, but supports less parameters.""" data = get_data(hist, cumulative=False, flatten=True, density=kwargs.pop("density", False)) cmap = _get_cmap(kwargs) norm, cmap_data = _get_cmap_data(data, kwargs) colors = cmap(cmap_data) rpos, phipos = (arr.flatten() for arr in hist.get_bin_left_edges()) dr, dphi = (arr.flatten() for arr in hist.get_bin_widths()) rmax, _ = (arr.flatten() for arr in hist.get_bin_right_edges()) bar_args = {} if "zorder" in kwargs: bar_args["zorder"] = kwargs.pop("zorder") alphas = _get_alpha_data(cmap_data, kwargs) if np.isscalar(alphas): alphas = np.ones_like(data) * alphas for i in range(len(rpos)): if data[i] > 0 or show_zero: bin_color = colors[i] # TODO: align = "edge" bars = ax.bar(phipos[i], dr[i], width=dphi[i], bottom=rpos[i], align='edge', color=bin_color, edgecolor=kwargs.get("grid_color", cmap(0.5)), lw=kwargs.get("lw", 0.5), alpha=alphas[i], **bar_args) ax.set_rmax(rmax.max()) if show_colorbar: _add_colorbar(ax, cmap, cmap_data, norm)
def test_wrong_arguments(self): freqs = [[1, 0], [1, 2]] h = Histogram2D(binnings=(range(3), range(3)), frequencies=freqs) with pytest.raises(RuntimeError): h0 = h.partial_normalize(2) with pytest.raises(RuntimeError): h0 = h.partial_normalize(-2)
def test_with_zeros(self): freqs = [ [0, 0], [0, 2] ] h = Histogram2D(binnings=(range(3), range(3)), frequencies=freqs) h1 = h.partial_normalize(1) assert np.allclose(h1.frequencies, [[0, 0], [0, 1.0]])
def test_inplace(self): freqs = [[1, 0], [1, 2]] h = Histogram2D(binnings=(range(3), range(3)), frequencies=freqs) h1 = h.partial_normalize(0, inplace=False) assert np.allclose(h.frequencies, freqs) assert not np.allclose(h1.frequencies, h.frequencies) h.partial_normalize(0, inplace=True) assert h1 == h
def test_values(self): freqs = [[1, 0], [1, 2]] h = Histogram2D(binnings=(range(3), range(3)), frequencies=freqs) h0 = h.partial_normalize(0) h1 = h.partial_normalize(1) assert np.allclose(h0.frequencies, [[.5, 0], [.5, 1.0]]) assert np.allclose(h1.frequencies, [[1, 0], [.333333333333, .6666666666]])
def test_axis_names(self): freqs = [ [1, 0], [1, 2] ] h = Histogram2D(binnings=(range(3), range(3)), frequencies=freqs, axis_names=["first_axis", "second_axis"]) h1 = h.partial_normalize("second_axis") assert np.allclose(h1.frequencies, [[1, 0], [.333333333333, .6666666666]]) with pytest.raises(ValueError): h0 = h.partial_normalize("third_axis")
def bar3d(h2: Histogram2D, ax: Axes3D, **kwargs): """Plot of 2D histograms as 3D boxes.""" density = kwargs.pop("density", False) data = get_data(h2, cumulative=False, flatten=True, density=density) if "cmap" in kwargs: cmap = _get_cmap(kwargs) _, cmap_data = _get_cmap_data(data, kwargs) colors = cmap(cmap_data) else: colors = kwargs.pop("color", kwargs.pop("c", "blue")) xpos, ypos = (arr.flatten() for arr in h2.get_bin_centers()) zpos = np.zeros_like(ypos) dx, dy = (arr.flatten() for arr in h2.get_bin_widths()) _add_labels(ax, h2, kwargs) ax.bar3d(xpos, ypos, zpos, dx, dy, data, color=colors, **kwargs) ax.set_zlabel("density" if density else "frequency")
def map(h2: Histogram2D, *, show_zero: bool = True, show_values: bool = False, **kwargs) -> dict: """Heat-map of two-dimensional histogram.""" vega = _create_figure(kwargs) values_arr = get_data(h2, kwargs.pop("density", None), kwargs.pop("cumulative", None)) values = values_arr.tolist() value_format = get_value_format(kwargs.pop("value_format", None)) _add_title(h2, vega, kwargs) _create_scales(h2, vega, kwargs) _create_axes(h2, vega, kwargs) _create_cmap_scale(values_arr, vega, kwargs) _create_colorbar(vega, kwargs) x = h2.get_bin_centers(0) y = h2.get_bin_centers(1) x1 = h2.get_bin_left_edges(0) x2 = h2.get_bin_right_edges(0) y1 = h2.get_bin_left_edges(1) y2 = h2.get_bin_right_edges(1) data = [] for i in range(h2.shape[0]): for j in range(h2.shape[1]): if not show_zero and values[i][j] == 0: continue item = { "x": float(x[i]), "x1": float(x1[i]), "x2": float(x2[i]), "y": float(y[j]), "y1": float(y1[j]), "y2": float(y2[j]), "c": float(values[i][j]) } if show_values: item["label"] = value_format(values[i][j]) data.append(item) vega["data"] = [{ "name": "table", "values": data }] vega["marks"] = [ { "type": "rect", "from": {"data": "table"}, "encode": { "enter": { "x": {"scale": "xscale", "field": "x1"}, "x2": {"scale": "xscale", "field": "x2"}, "y": {"scale": "yscale", "field": "y1"}, "y2": {"scale": "yscale", "field": "y2"}, "fill": {"scale": "color", "field": "c"}, "stroke": {"value": 0}, # "strokeWidth": {"value": 0}, # "fillColor": {"value": "#ffff00"} }, "update": { "fillOpacity": {"value": kwargs.pop("alpha", 1)} }, # "hover": { # "fillOpacity": {"value": 0.5} # } } } ] if show_values: vega["marks"].append( { "type": "text", "from": {"data": "table"}, "encode": { "enter": { "align": {"value": "center"}, "baseline": {"value": "middle"}, "fontSize": {"value": 13}, "fontWeight": {"value": "bold"}, "text": {"field": "label"}, "x": {"scale": "xscale", "field": "x"}, "y": {"scale": "yscale", "field": "y"}, } } } ) return vega
def map(h2: Histogram2D, ax: Axes, *, show_zero: bool = True, show_values: bool = False, show_colorbar: bool = True, x=None, y=None, **kwargs): """Coloured-rectangle plot of 2D histogram. Parameters ---------- show_zero : Whether to show coloured box for bins with 0 frequency (otherwise background). show_values : Whether to show labels with frequencies/densities in the middle of the bin text_color : Optional Colour of text descriptions text_alpha : Optional[float] Alpha for the text labels only x : Optional[Callable] Transformation of x bin coordinates y : Optional[Callable] Transformation of y bin coordinates zorder : float z-order in the axis (higher number above lower) See Also -------- image, polar_map, surface_map Notes ----- If you transform axes using x or y parameters, the deduction of axis limits does not work well automatically. Please, make sure to attend to it yourself. The densities in transformed maps are calculated from original bins. """ # Detect transformation transformed = False if x is not None or y is not None: if not x: x = lambda x, y: x if not y: y = lambda x, y: y transformed = True value_format = kwargs.pop("value_format", lambda x: str(x)) # TODO: Implement correctly the text_kwargs if isinstance(value_format, str): format_str = "{0:" + value_format + "}" value_format = lambda x: format_str.format(x) rect_args = {} if "zorder" in kwargs: rect_args["zorder"] = kwargs.pop("zorder") data = get_data(h2, cumulative=False, flatten=True, density=kwargs.pop("density", False)) cmap = _get_cmap(kwargs) norm, cmap_data = _get_cmap_data(data, kwargs) colors = cmap(cmap_data) xpos, ypos = (arr.flatten() for arr in h2.get_bin_left_edges()) dx, dy = (arr.flatten() for arr in h2.get_bin_widths()) text_x, text_y = (arr.flatten() for arr in h2.get_bin_centers()) _apply_xy_lims(ax, h2, data=data, kwargs=kwargs) _add_labels(ax, h2, kwargs) ax.autoscale_view() alphas = _get_alpha_data(cmap_data, kwargs) if np.isscalar(alphas): alphas = np.ones_like(data) * alphas for i in range(len(xpos)): bin_color = colors[i] alpha = alphas[i] if data[i] != 0 or show_zero: if not transformed: rect = plt.Rectangle([xpos[i], ypos[i]], dx[i], dy[i], facecolor=bin_color, edgecolor=kwargs.get( "grid_color", cmap(0.5)), lw=kwargs.get("lw", 0.5), alpha=alpha, **rect_args) tx, ty = text_x[i], text_y[i] else: # See http://matplotlib.org/users/path_tutorial.html points = ((xpos[i], ypos[i]), (xpos[i] + dx[i], ypos[i]), (xpos[i] + dx[i], ypos[i] + dy[i]), (xpos[i], ypos[i] + dy[i]), (xpos[i], ypos[i])) verts = [(x(*p), y(*p)) for p in points] codes = [ path.Path.MOVETO, path.Path.LINETO, path.Path.LINETO, path.Path.LINETO, path.Path.CLOSEPOLY, ] rect_path = path.Path(verts, codes) rect = patches.PathPatch(rect_path, facecolor=bin_color, edgecolor=kwargs.get( "grid_color", cmap(0.5)), lw=kwargs.get("lw", 0.5), alpha=alpha, **rect_args) tx = x(text_x[i], text_y[i]) ty = y(text_x[i], text_y[i]) ax.add_patch(rect) if show_values: text = value_format(data[i]) yiq_y = np.dot(bin_color[:3], [0.299, 0.587, 0.114]) text_color = kwargs.get("text_color", None) if not text_color: if yiq_y > 0.5: text_color = (0.0, 0.0, 0.0, kwargs.get("text_alpha", alpha)) else: text_color = (1.0, 1.0, 1.0, kwargs.get("text_alpha", alpha)) ax.text(tx, ty, text, horizontalalignment='center', verticalalignment='center', color=text_color, clip_on=True, **rect_args) if show_colorbar: _add_colorbar(ax, cmap, cmap_data, norm)