splotch
Advanced tools
+1
-1
| Metadata-Version: 2.1 | ||
| Name: splotch | ||
| Version: 0.6.2.1 | ||
| Version: 0.6.5.2 | ||
| Summary: Simple PLOTs, Contours and Histograms is a small package with wrapper functions designed to simplify plotting calls from matplotlib. | ||
@@ -5,0 +5,0 @@ Home-page: https://github.com/MBravoS/splot |
+1
-1
@@ -6,3 +6,3 @@ import atexit | ||
| setup(name='splotch', | ||
| version='0.6.2.1', | ||
| version='0.6.5.2', | ||
| description='Simple PLOTs, Contours and Histograms is a small package with wrapper functions designed to simplify plotting calls from matplotlib.', | ||
@@ -9,0 +9,0 @@ url='https://github.com/MBravoS/splot', |
| Metadata-Version: 2.1 | ||
| Name: splotch | ||
| Version: 0.6.2.1 | ||
| Version: 0.6.5.2 | ||
| Summary: Simple PLOTs, Contours and Histograms is a small package with wrapper functions designed to simplify plotting calls from matplotlib. | ||
@@ -5,0 +5,0 @@ Home-page: https://github.com/MBravoS/splot |
+185
-12
| ######################################################################## | ||
| ######### Base functions for axis_funcs, plots_1d and plots_2d ######### | ||
| ######################################################################## | ||
| from collections.abc import Iterable | ||
| from warnings import warn | ||
| from numbers import Number | ||
@@ -11,6 +14,8 @@ from math import ceil, floor | ||
| from matplotlib import rcParams | ||
| from matplotlib.pyplot import fill_between, fill_betweenx, gca, grid, sca, title as plt_title | ||
| from matplotlib.pyplot import fill_between, fill_betweenx, gca, gcf, grid, sca, title as plt_title | ||
| from matplotlib.pyplot import xlabel as plt_xlabel, xlim as plt_xlim, xscale | ||
| from matplotlib.pyplot import ylabel as plt_ylabel, ylim as plt_ylim, yscale | ||
| from .defaults import Params | ||
| #################################### | ||
@@ -47,2 +52,100 @@ # Boolean, unsigned integer, signed integer, float, complex. | ||
| ######################################### | ||
| # Handle various inputs to grid parameter | ||
| ######################################### | ||
| def grid_handler(grid, ax=None): | ||
| """ Handles grid behaviour | ||
| Base-level function to handle the behaviour of inputs to the grid parameter. If grid is a boolean, then | ||
| nothing is changed, however, if grid is None, first check whether this is the first plot call to this | ||
| axis, if so, use rcParams, otherwise do nothing. | ||
| Parameters | ||
| ---------- | ||
| grid : boolean, dict or None | ||
| The requested grid settings. | ||
| * If boolean, then the grid is set on (True) or off (False). | ||
| * If dict, then parameters in grid will be parsed into the plt.grid() function. | ||
| * If None and this is the initial plotting call, set to rcParams, else do nothing. | ||
| ax : Axes object or None | ||
| The axis in which to check the current grid settings. | ||
| Returns | ||
| ------- | ||
| gridpar : boolean | ||
| Returns the modified grid parameters as a dictionary. | ||
| """ | ||
| if ax is None: | ||
| ax = gca() | ||
| if grid is None: | ||
| if ax.has_data(): | ||
| return None # i.e. do nothing | ||
| else: | ||
| grid = rcParams['axes.grid'] | ||
| if isinstance(grid, bool): | ||
| if grid is True: # only set additional grid properties if grid=True, otherwise warnings given. | ||
| return dict(visible=grid, which=rcParams['axes.grid.which'], axis=rcParams['axes.grid.axis'], | ||
| color=Params.grid_color, alpha=Params.grid_alpha, | ||
| linestyle=Params.grid_ls, linewidth=Params.grid_lw) | ||
| else: | ||
| return dict(visible=grid, which=rcParams['axes.grid.which'], axis=rcParams['axes.grid.axis']) | ||
| elif isinstance(grid, dict): | ||
| return grid | ||
| else: | ||
| warn(f"grid must be given as either boolean, dict or None. Instead got {type(grid)}.") | ||
| return None | ||
| ############################################### | ||
| # Handle various inputs to xlim/ylim parameters | ||
| ############################################### | ||
| def lims_handler(lims, ax=None): | ||
| """ Handles xlim/ylim behaviour | ||
| Base-level function to handle the behaviour of inputs to the xlim/ylim parameters. If xlim/ylim is a valid tuple, | ||
| then set these as the limits. However, if xlim/ylim is None, first check whether this is the first plot call to this | ||
| axis, if so, set to 'auto' (i.e. autoscale), otherwise do nothing. | ||
| Parameters | ||
| ---------- | ||
| lims : tuple, str or None | ||
| The requested values for xlim/ylim. | ||
| * If tuple, then return these values (if valid). | ||
| * If None and this is the initial plotting call, set to 'auto', else set to None | ||
| * If str, must be of the value 'auto' return. | ||
| ax : Axes object or None | ||
| The axis in which to check the current grid settings. | ||
| Returns | ||
| ------- | ||
| limspar : boolean | ||
| Returns the modified grid parameters as a dictionary. | ||
| """ | ||
| if ax is None: | ||
| ax = gca() | ||
| if lims is None: | ||
| if ax.has_data(): | ||
| return None # i.e. do nothing | ||
| else: | ||
| return 'auto' | ||
| elif isinstance(lims, Iterable): | ||
| if isinstance(lims, str): | ||
| if lims != 'auto': | ||
| warn(f"Only 'auto' is accepted when giving lims as a str. Instead got {type(lims)}.") | ||
| return None | ||
| else: | ||
| return 'auto' | ||
| else: | ||
| return lims # should we validate limits here? | ||
| else: | ||
| warn(f"lims must be given as either list-like, str or None. Instead got {type(lims)}.") | ||
| return None | ||
| #################################### | ||
@@ -256,12 +359,3 @@ # Base function for 2D histograms | ||
| #################################### | ||
| # Density/scaled counts for hexbin | ||
| #################################### | ||
| #def hexarea(value,norm): | ||
| # return(value/norm) | ||
| # | ||
| #def hexscaled(value,scale): | ||
| # return(1.0*value/scale) | ||
| #################################### | ||
@@ -317,3 +411,2 @@ # General check for numeric values | ||
| """ | ||
| from numbers import Number | ||
@@ -467,3 +560,3 @@ return isinstance(var, Number) | ||
| if grid_control is not None: | ||
| if isinstance(grid_control, bool): | ||
| grid(b=grid_control, which=rcParams['axes.grid.which'], axis=rcParams['axes.grid.axis']) | ||
@@ -475,2 +568,82 @@ else: | ||
| #################################### | ||
| # Set labels, limits and more | ||
| #################################### | ||
| def _plot_finalizer(xlog, ylog, xlim, ylim, title, xlabel, ylabel, xinvert, yinvert, gridpar, ax=None): | ||
| """New axis handler | ||
| This function is a base-level function used by most other plotting functions to set the current | ||
| Axes instance to ax and returns the old Axes instance to be later reverted. | ||
| Parameters | ||
| ---------- | ||
| xlog : None or bool | ||
| If True, the x-axis scale is set to 'log'. | ||
| ylog : None or bool | ||
| If True, the y-axis scale is set to 'log'. | ||
| xlim : None or array-like | ||
| If given, defines the low and high limits for the x-axis. The first two elements must be int | ||
| and/or float. | ||
| ylim : None or array-like | ||
| If given, defines the low and high limits for the y-axis. The first two elements must be int | ||
| and/or float. | ||
| title : None or str | ||
| If given, defines the title of the figure. | ||
| xlabel : None or str | ||
| If given, defines the label of the x-axis. | ||
| ylabel : None or str | ||
| If given, defines the label of the y-axis. | ||
| xinvert : None or bool | ||
| If True, ensures the x-axis is inverted. If False, ensures the x-axis is not inverted. | ||
| yinvert : None or bool | ||
| If True, ensures the y-axis is inverted. If False, ensures the y-axis is not inverted. | ||
| gridpar : None or dict | ||
| The parameters to be given to matplotlib's grid function. | ||
| ax : Axes object or None | ||
| The axis for which to apply the plot parameters. | ||
| Returns | ||
| ------- | ||
| None | ||
| """ | ||
| ax = gca() if ax is None else ax | ||
| if xlog: | ||
| ax.set_xscale('log') | ||
| if ylog: | ||
| ax.set_yscale('log') | ||
| if xlim == 'auto': | ||
| ax.autoscale(axis='x') | ||
| else: | ||
| ax.set_xlim(xlim) | ||
| if ylim == 'auto': | ||
| ax.autoscale(axis='y') | ||
| else: | ||
| ax.set_ylim(ylim) | ||
| if title is not None: | ||
| ax.set_title(title) | ||
| if xlabel is not None: | ||
| ax.set_xlabel(xlabel) | ||
| if ylabel is not None: | ||
| ax.set_ylabel(ylabel) | ||
| if xinvert: | ||
| if not ax.xaxis_inverted(): | ||
| ax.invert_xaxis() | ||
| if yinvert: | ||
| if not ax.yaxis_inverted(): | ||
| ax.invert_yaxis() | ||
| if gridpar is not None: | ||
| ax.grid(**gridpar) | ||
| #################################### | ||
| # Modified fill_between for hist | ||
@@ -477,0 +650,0 @@ #################################### |
@@ -21,3 +21,3 @@ ######################################################################## | ||
| hist1D_yaxis_log = False | ||
| hist2D_output = False | ||
| hist2D_output = True | ||
| hist2D_caxis_log = False | ||
@@ -30,5 +30,5 @@ | ||
| # Grids | ||
| grid_color = 'white' | ||
| grid_color = 'grey' | ||
| grid_alpha = 1.0 | ||
| grid_ls = '--' | ||
| grid_ls = '-' | ||
| grid_lw = 1.0 | ||
@@ -35,0 +35,0 @@ |
+319
-250
@@ -12,3 +12,3 @@ ######################################################################## | ||
| from matplotlib.legend_handler import HandlerLine2D, HandlerPathCollection, HandlerTuple | ||
| from matplotlib.pyplot import bar, barh, fill_between, fill_betweenx, gca, legend, plot as plt_plot, sca, stairs # step | ||
| from matplotlib.pyplot import bar, barh, fill_between, fill_betweenx, gcf, gca, legend, plot as plt_plot, sca, stairs # step | ||
| from matplotlib.transforms import Bbox | ||
@@ -20,5 +20,6 @@ from matplotlib.colors import to_rgba_array | ||
| from .base_func import axes_handler, bin_axis, dict_splicer, is_numeric, is_number, plot_finalizer, simpler_dict_splicer | ||
| from .base_func import axes_handler, grid_handler, lims_handler, bin_axis, dict_splicer, is_numeric, is_number, plot_finalizer, _plot_finalizer, simpler_dict_splicer | ||
| from .defaults import Params | ||
| #################################### | ||
@@ -65,4 +66,7 @@ # Generalized lines | ||
| Sets the legend for the plot. | ||
| grid : boolean, optional | ||
| If not given defaults to the value defined in splotch.Params. | ||
| grid : boolean, dict or None | ||
| The grid behaviour, acts according to: | ||
| * If boolean, the grid is set on (True) or off (False). | ||
| * If dict, allows specific `.Line2D` properties of the grid to be set. | ||
| * If None, use default grid parameters if this is the initial plotting call, otherwise do nothing. | ||
| ax : pyplot.Axes or list-like, optional | ||
@@ -85,3 +89,3 @@ Specifies the axes on which to plot the lines, defaults to the current axes. | ||
| # Set the current axis | ||
| # Get the relevant axis | ||
| if ax is not None: | ||
@@ -91,9 +95,8 @@ if isinstance(ax, (list, tuple, ndarray)): | ||
| ax = array(ax).flatten() | ||
| old_ax = axes_handler(ax[0]) | ||
| else: | ||
| ax = [ax] # Axis must be a list to be enumerated over | ||
| old_ax = axes_handler(ax[0]) | ||
| ax = [ax] # Axis must be a list-like object | ||
| else: | ||
| ax = [gca()] | ||
| old_ax = ax[0] | ||
| old_ax = axes_handler(ax[0]) # sets the current axis and returns old axis | ||
@@ -150,5 +153,3 @@ # Validate input parameters | ||
| # Combine the `explicit` plot_kw dictionary with the `implicit` **kwargs dictionary | ||
| # plot_par={**plot_kw, **kwargs} # For Python > 3.5 | ||
| plot_par = plot_kw.copy() | ||
| plot_par.update(kwargs) | ||
| plot_par = {**plot_kw, **kwargs} | ||
@@ -158,5 +159,9 @@ # Create 'L' number of plot kwarg dictionaries to parse into each plot call | ||
| lines = [[] for kk in range(len(ax))] # Initialise list which contains each Line2D object | ||
| lines = [[]] * len(ax) # Initialise list which contains each Line2D object | ||
| for jj, axis in enumerate(ax): # Loop over all axes | ||
| sca(axis) | ||
| gridpar = grid_handler(grid, axis) | ||
| ax_xlim = axis.get_xlim() if lims_handler(xlim, axis) is None else xlim | ||
| ax_ylim = axis.get_ylim() if lims_handler(ylim, axis) is None else ylim | ||
| if (x is not None): | ||
@@ -169,18 +174,9 @@ for ii, xx in enumerate(x): | ||
| if (a is not None): | ||
| for ii, (aa, bb) in enumerate(zip(a, b)): | ||
| xLims = axis.get_xlim() if xlim is None else xlim | ||
| yLims = axis.get_ylim() if ylim is None else ylim | ||
| for ii, (aa, bb) in enumerate(zip(a, b)): # Loop over all lines | ||
| lines[jj].append(axis.axline(xy1=(0, bb), slope=aa, label=label[ii], **plot_par[ii])) | ||
| lines[jj].append(axis.plot([xLims[0], xLims[1]], [aa * xLims[0] + bb, aa * xLims[1] + bb], label=label[ii], **plot_par[ii])[0]) | ||
| axis.set_xlim(xLims) | ||
| axis.set_ylim(yLims) | ||
| _plot_finalizer(xlog, ylog, ax_xlim, ax_ylim, title, xlabel, ylabel, xinvert, yinvert, gridpar, axis) | ||
| plot_finalizer(xlog, ylog, xlim, ylim, title, xlabel, ylabel, xinvert, yinvert, grid) | ||
| # Autoscale the axes if needed | ||
| if xlim is None: axis.autoscale(axis='x') | ||
| if ylim is None: axis.autoscale(axis='y') | ||
| if old_ax is not None: # Reset the previously set axis | ||
| old_ax = axes_handler(old_ax) | ||
| sca(old_ax) | ||
@@ -193,6 +189,5 @@ return squeeze(lines).tolist() # Reduce the dimensionality of the lines, if needed | ||
| #################################### | ||
| def brokenplot(x,y=None,xbreak=None,ybreak=None,xlim=None,ylim=None,sep=0.05, | ||
| xinvert=False,yinvert=False,xlog=False,ylog=False,title=None, | ||
| xlabel=None,ylabel=None,label=None,lab_loc=0,ax=None,grid=None,plot_kw={},**kwargs): | ||
| def brokenplot(x, y=None, xbreak=None, ybreak=None, xlim=None, ylim=None, sep=0.05, overflow=0.05, | ||
| xinvert=False, yinvert=False, xlog=False, ylog=False, title=None, | ||
| xlabel=None, ylabel=None, label=None, lab_loc=0, ax=None, grid=None, plot_kw={}, **kwargs): | ||
| """Broken Axis Plot Function | ||
@@ -218,4 +213,7 @@ | ||
| Defines the limits of the y-axis, it must contain two elements (lower and higer limits). | ||
| sep : float, optional, default: 0.05 | ||
| sep : float, optional (default: 0.05) | ||
| The separation size of the axis break, given as a fraction of the axis dimensions. | ||
| overflow : float, optional (default: 0.05) | ||
| The fractional overflow of the axes beyond the break values. Often good to keep this non-zero as | ||
| breaking the axis exactly at the break point leaves the final gridlines and ticks out of view. | ||
| xinvert : bool or list, optional | ||
@@ -247,3 +245,3 @@ If true inverts the x-axis. | ||
| kwargs are used to specify matplotlib specific properties such as linecolor, linewidth, | ||
| antialiasing, etc. A list of available `Line2D` properties can be found here: | ||
| antialiasing, etc. A list of available `Line2D` properties can be found here: | ||
| https://matplotlib.org/3.1.0/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D | ||
@@ -253,122 +251,188 @@ | ||
| ------- | ||
| lines | ||
| lines : list of Line2D | ||
| A list of Line2D objects (paired as tuples) representing the plotted data. | ||
| The lines are given as pairs to correspond to the separate lines either side of the x/ybreak. | ||
| ax2 : pyplot.Axes, optional | ||
| The additional axis object created. | ||
| """ | ||
| if ax is not None: | ||
| old_axes=axes_handler(ax) | ||
| else: | ||
| ax=gca() | ||
| old_axes=ax | ||
| # Get the relevant axis | ||
| ax1 = gca() if ax is None else ax | ||
| old_ax = axes_handler(ax1) | ||
| if type(x) is not list or len(shape(x))==1: | ||
| x=[x] | ||
| L=len(x) | ||
| gridpar = grid_handler(grid, ax1) | ||
| if not isinstance(x, (list, tuple, ndarray)) or len(shape(x)) == 1: | ||
| x = [x] | ||
| L = len(x) | ||
| if y is None: | ||
| y=x | ||
| x=[arange(len(x[i])) for i in range(L)] | ||
| y = x | ||
| x = [arange(len(x[i])) for i in range(L)] | ||
| else: | ||
| if type(y) is not list or len(shape(y))==1: | ||
| y=[y] | ||
| if type(label) is not list: | ||
| label=[label for i in range(L)] | ||
| if not isinstance(y, (list, tuple, ndarray)) or len(shape(y)) == 1: | ||
| y = [y] | ||
| if not isinstance(label, (list, tuple, ndarray)) or len(shape(label)) == 1: | ||
| label = [label] * L | ||
| # Combine the `explicit` plot_kw dictionary with the `implicit` **kwargs dictionary | ||
| plot_par = {**plot_kw, **kwargs} | ||
| # Validate x/ybreak | ||
| if (xbreak == None): | ||
| # Create 'L' number of plot kwarg dictionaries to parse into each plot call | ||
| plot_par = dict_splicer(plot_par, L, [1] * L) | ||
| # Get the original axis position | ||
| pos0 = ax.get_position(original=True) | ||
| width0, height0 = pos0.x1 - pos0.x0, pos0.y1 - pos0.y0 | ||
| # Perform first plot call to original axis | ||
| lines = [] | ||
| for i in range(L): | ||
| lines += ax1.plot(x[i], y[i], label=label[i], **plot_par[i]) | ||
| # Get the axis limits if not already specified | ||
| xlims = ax1.get_xlim() if xlim in [None, 'auto'] else xlim | ||
| ylims = ax1.get_ylim() if ylim in [None, 'auto'] else ylim | ||
| # Validate xbreak/ybreak | ||
| if (xbreak is None and ybreak is None): | ||
| raise ValueError("Require either xbreak/ybreak to be specified.") | ||
| if (ybreak != None): | ||
| raise NotImplementedError("ybreak not yet implemented.") | ||
| if (ybreak is not None and xbreak is not None): | ||
| raise ValueError("Cannot specify both xbreak and ybreak.") | ||
| breaks = xbreak if xbreak else ybreak | ||
| if not isinstance(breaks, (list, tuple, ndarray)): | ||
| breaks = (breaks,) * 2 | ||
| else: | ||
| if len(breaks) == 1: | ||
| breaks = (breaks[0],) * 2 | ||
| elif len(breaks) == 2: | ||
| if breaks[0] > breaks[1]: | ||
| raise ValueError("First value in xbreak/ybreak must not be greater than the second value.") | ||
| else: | ||
| raise ValueError("xbreak/ybreak must be a single value or a list-like object with two elements.") | ||
| if type(xbreak) not in [list,tuple,ndarray]: | ||
| xbreak=(xbreak, xbreak) | ||
| else: | ||
| if (len(xbreak) != 2): | ||
| raise ValueError("xbreak must be a single value of a tuple-like list of two elements.") | ||
| if xbreak and (breaks[0] < xlims[0] or breaks[1] > xlims[1]): | ||
| raise ValueError(f"xbreak given ({xbreak}) must be within the xlim ({xlims}).") | ||
| if ybreak and (breaks[0] < ylims[0] or breaks[1] > ylims[1]): | ||
| raise ValueError(f"ybreak given ({ybreak}) must be within the ylim ({ylims}).") | ||
| # Define the positions of the two separated axes | ||
| pos1 = Bbox(list(pos0.get_points())) | ||
| if xbreak: | ||
| pos1.x1 = pos1.x0 + (pos1.x1 - pos1.x0) * (sum(breaks) / 2 - xlims[0]) / (xlims[1] - xlims[0]) - sep * (pos1.x1 - pos1.x0) / 2 | ||
| if ybreak: | ||
| pos1.y1 = pos1.y0 + (pos1.y1 - pos1.y0) * (sum(breaks) / 2 - ylims[0]) / (ylims[1] - ylims[0]) - sep * (pos1.y1 - pos1.y0) / 2 | ||
| pos2 = Bbox(list(pos0.get_points())) | ||
| if xbreak: | ||
| pos2.x0 = pos2.x0 + (pos2.x1 - pos2.x0) * (sum(breaks) / 2 - xlims[0]) / (xlims[1] - xlims[0]) + sep * (pos2.x1 - pos2.x0) / 2 | ||
| if ybreak: | ||
| pos2.y0 = pos2.y0 + (pos2.y1 - pos2.y0) * (sum(breaks) / 2 - ylims[0]) / (ylims[1] - ylims[0]) + sep * (pos2.y1 - pos2.y0) / 2 | ||
| ax1.set_position(pos1) # Resize the first axis | ||
| ax2 = ax1.figure.add_axes(pos2) # Add and duplicate the plotting in the second axis | ||
| # Combine the `explicit` plot_kw dictionary with the `implicit` **kwargs dictionary | ||
| #plot_par={**plot_kw, **kwargs} # For Python > 3.5 | ||
| plot_par=plot_kw.copy() | ||
| plot_par.update(kwargs) | ||
| # Perform first plot call to original axis | ||
| lines = [] | ||
| for i in range(L): | ||
| lines += ax2.plot(x[i], y[i], label=label[i], **plot_par[i]) | ||
| # Create 'L' number of plot kwarg dictionaries to parse into each plot call | ||
| plot_par=dict_splicer(plot_par,L,[1]*L) | ||
| width1, height1 = pos1.x1 - pos1.x0, pos1.y1 - pos1.y0 | ||
| width2, height2 = pos2.x1 - pos2.x0, pos2.y1 - pos2.y0 | ||
| # Adjust x/y limits for both axes | ||
| xlim1 = (xlims[0], breaks[0] + overflow * (width1 + sep) / width0) if xbreak else xlims | ||
| xlim2 = (breaks[1] - overflow * (width2 + sep) / width0, xlims[1]) if xbreak else xlims | ||
| # Get the original axis position | ||
| pos0=ax.get_position(original=True) | ||
| width0, height0=pos0.x1 - pos0.x0, pos0.y1 - pos0.y0 | ||
| ylim1 = (ylims[0], breaks[0]) if ybreak else ylims | ||
| ylim2 = (breaks[1], ylims[1]) if ybreak else ylims | ||
| lines=[] # Initialising list which contains each line | ||
| for i in range(L): | ||
| # First side plot call | ||
| l1=ax.plot(x[i],y[i],label=label[i],**plot_par[i]) | ||
| if xbreak: | ||
| dx1, dy1 = 0.01 * width0 / (width0 - width2 - sep / 2), height1 * 0.025 | ||
| dx2, dy2 = 0.01 * width0 / (width0 - width1 - sep / 2), height2 * 0.025 | ||
| # Get the axis limits if not already specified | ||
| xlims=ax.get_xlim() if xlim == None else xlim | ||
| ylims=ax.get_ylim() if ylim == None else ylim | ||
| # Define the positions of the two separated axes | ||
| if (i == 0): | ||
| pos1=Bbox(list(pos0.get_points())) | ||
| pos1.x1=pos1.x0 + (pos1.x1-pos1.x0)*(sum(xbreak)/2-xlims[0])/(xlims[1]-xlims[0]) - sep*(pos1.x1-pos1.x0)/2 | ||
| pos2=Bbox(list(pos0.get_points())) | ||
| pos2.x0=pos2.x0 + (pos2.x1-pos2.x0)*(sum(xbreak)/2-xlims[0])/(xlims[1]-xlims[0]) + sep*(pos2.x1-pos2.x0)/2 | ||
| ax.set_position(pos1) # Resize the first axis | ||
| ax2=ax.figure.add_axes(pos2) # Add and duplicate the plotting in the second axis | ||
| # Set the new axis limits at the break point | ||
| ax.set_xlim(xlims[0],xbreak[0]) | ||
| ax2.set_xlim(xbreak[1],xlims[1]) | ||
| dash_kw = dict(transform=ax1.transAxes, color='black', linestyle='-', marker='', clip_on=False) | ||
| temp1 = (breaks[0] - xlim1[0]) / (breaks[0] - xlim1[0] + overflow * (width1 + sep) / width0) | ||
| ax1.plot((temp1 - dx1, temp1 + dx1), (0 - dy1, 0 + dy1), **dash_kw) # bottom-left | ||
| ax1.plot((temp1 - dx1, temp1 + dx1), (1 - dy1, 1 + dy1), **dash_kw) # top-left | ||
| # Second side plot call | ||
| l2=ax2.plot(x[i],y[i],label=None,**plot_par[i]) | ||
| dash_kw.update(transform=ax2.transAxes) # switch to the left axes | ||
| temp2 = 1 - (xlim2[1] - breaks[1]) / (xlim2[1] - breaks[1] + overflow * (width2 + sep) / width0) | ||
| ax2.plot((temp2 - dx2, temp2 + dx2), (0 - dy2, 0 + dy2), **dash_kw) # bottom-right | ||
| ax2.plot((temp2 - dx2, temp2 + dx2), (1 - dy2, 1 + dy2), **dash_kw) # top-right | ||
| lines.append((*l1,*l2)) # Add line as tuple of both axes. | ||
| # Fix axes labels and splines | ||
| ax1.spines['right'].set_visible(False) | ||
| ax1.tick_params(labelright=False, which='both') | ||
| ax1.yaxis.tick_left() | ||
| ax2.spines['left'].set_visible(False) | ||
| ax2.tick_params(labelleft=False, which='both') | ||
| ax2.yaxis.tick_right() | ||
| if (ax1.get_xticks()[-1] == ax2.get_xticks()[0]): | ||
| if (breaks[0] >= (xlims[0] + xlims[1]) * 0.5): | ||
| ax1.set_xticks(ax1.get_xticks()[:-1]) # Remove duplicate tick on left side | ||
| else: | ||
| ax2.set_xticks(ax2.get_xticks()[1:]) # Remove duplicate tick on right side | ||
| ax1.axes.spines[['top', 'bottom']].set_bounds((xlim1[0], breaks[0])) | ||
| ax2.axes.spines[['top', 'bottom']].set_bounds((breaks[1], xlim2[-1])) | ||
| width1, height1=pos1.x1 - pos1.x0, pos1.y1 - pos1.y0 | ||
| width2, height2=pos2.x1 - pos2.x0, pos2.y1 - pos2.y0 | ||
| ax1.xaxis.set_label_coords(0.5 * (width0 / width1), -0.125, transform=ax1.axes.transAxes) | ||
| if ybreak: | ||
| dx1, dy1 = width1 * 0.0125, 0.02 * height0 / (height0 - height2 - sep / 2) | ||
| dx2, dy2 = width2 * 0.0125, 0.02 * height0 / (height0 - height1 - sep / 2) | ||
| dx1, dy1=0.01 * width0/(width0-width1-sep/2), height1*0.025 | ||
| dash_kw = dict(transform=ax1.transAxes, color='black', linestyle='-', marker='', clip_on=False) | ||
| temp1 = (breaks[0] - ylim1[0]) / (breaks[0] - ylim1[0] + overflow * (height1 + sep) / height0) | ||
| ax1.plot((0 - dx1, 0 + dx1), (temp1 - dy1, temp1 + dy1), **dash_kw) # bottom-left | ||
| ax1.plot((1 - dx1, 1 + dx1), (temp1 - dy1, temp1 + dy1), **dash_kw) # bottom-right | ||
| dash_kw=dict(transform=ax2.transAxes, color='black', linestyle='-', marker='', clip_on=False) | ||
| ax2.plot((0 - dx1, 0 + dx1), (0 - dy1, 0 + dy1), **dash_kw) # bottom-right diagonal | ||
| ax2.plot((0 - dx1, 0 + dx1), (1 - dy1, 1 + dy1), **dash_kw) # top-right diagonal | ||
| dx2, dy2=0.01 * width0/(width0-width2-sep/2), height2*0.025 | ||
| dash_kw.update(transform=ax.transAxes) # switch to the left axes | ||
| ax.plot((1 - dx2, 1 + dx2), (0 - dy2, 0 + dy2), **dash_kw) # bottom-left sep/5iagonal | ||
| ax.plot((1 - dx2, 1 + dx2), (1 - dy2, 1 + dy2), **dash_kw) # top-left sep/5iagonal | ||
| ax.spines['right'].set_visible(False) | ||
| ax.tick_params(labelright=False,which='both') # don't put tick labels at the top | ||
| ax.yaxis.tick_left() | ||
| ax2.spines['left'].set_visible(False) | ||
| ax2.tick_params(labelleft=False,which='both') # don't put tick labels at the top | ||
| ax2.yaxis.tick_right() | ||
| dash_kw.update(transform=ax2.transAxes) # switch to the left axes | ||
| temp2 = 1 - (ylim2[1] - breaks[1]) / (ylim2[1] - breaks[1] + overflow * (height2 + sep) / height0) | ||
| ax2.plot((0 - dx2, 0 + dx2), (temp2 - dy2, temp2 + dy2), **dash_kw) # top-left | ||
| ax2.plot((1 - dx2, 1 + dx2), (temp2 - dy2, temp2 + dy2), **dash_kw) # top-right | ||
| # Check that there is no duplicate ticks over both axes | ||
| if (xbreak): | ||
| if (ax.get_xticks()[-1] == ax2.get_xticks()[0]): | ||
| if (xbreak[0] >= (xlims[0] + xlims[1])*0.5): | ||
| ax.set_xticks(ax.get_xticks()[:-1]) # Remove duplicate tick on left side | ||
| # Fix axes labels and splines | ||
| ax1.spines['top'].set_visible(False) | ||
| ax1.tick_params(labeltop=False, which='both') | ||
| ax1.xaxis.tick_bottom() | ||
| ax2.spines['bottom'].set_visible(False) | ||
| ax2.tick_params(labelbottom=False, which='both') | ||
| ax2.xaxis.tick_top() | ||
| if (ax1.get_yticks()[-1] == ax2.get_yticks()[0]): | ||
| if (breaks[0] >= (ylims[0] + ylims[1]) * 0.5): | ||
| ax1.set_yticks(ax1.get_yticks()[:-1]) # Remove duplicate tick on top | ||
| else: | ||
| ax2.set_xticks(ax2.get_xticks()[1:]) # Remove duplicate tick on right side | ||
| sca(ax) | ||
| ax2.set_yticks(ax2.get_yticks()[1:]) # Remove duplicate tick on bottom | ||
| ax1.axes.spines[['left', 'right']].set_bounds((ylim1[0], breaks[0])) | ||
| ax2.axes.spines[['left', 'right']].set_bounds((breaks[1], ylim2[-1])) | ||
| ax1.yaxis.set_label_coords(-0.125, 0.5 * (height0 / height1), transform=ax1.axes.transAxes) | ||
| if any(label): | ||
| ax.legend(loc=lab_loc) | ||
| ax2.legend(loc=lab_loc) | ||
| plot_finalizer(xlog,ylog,xlim,ylim,title,xlabel,ylabel,xinvert,yinvert,grid) | ||
| _plot_finalizer(xlog, ylog, xlim1, ylim1, title, xlabel, ylabel, xinvert, yinvert, gridpar, ax=ax1) | ||
| _plot_finalizer(xlog, ylog, xlim2, ylim2, None, None, None, xinvert, yinvert, gridpar, ax=ax2) | ||
| if old_axes is not ax: | ||
| old_axes=axes_handler(old_axes) | ||
| # Share axes | ||
| if xbreak: | ||
| ax1.get_shared_y_axes().join(ax, ax2) | ||
| if ybreak: | ||
| ax1.get_shared_x_axes().join(ax, ax2) | ||
| if old_ax is not None: | ||
| sca(old_ax) | ||
| return (lines[0] if len(lines) == 1 else lines) | ||
| return (lines[0] if len(lines) == 1 else lines, ax2) | ||
@@ -427,4 +491,7 @@ | ||
| If True the scale of the x-axis is logarithmic. | ||
| grid : boolean, optional | ||
| If not given defaults to the value defined in splotch.Params. | ||
| grid : boolean, dict or None | ||
| The grid behaviour, acts according to: | ||
| * If boolean, the grid is set on (True) or off (False). | ||
| * If dict, allows specific `.Line2D` properties of the grid to be set. | ||
| * If None, use default grid parameters if this is the initial plotting call, otherwise do nothing. | ||
| title : str, optional | ||
@@ -472,14 +539,16 @@ Sets the title of the plot | ||
| if ax is not None: | ||
| old_axes = axes_handler(ax) | ||
| else: | ||
| ax = gca() | ||
| old_axes = ax | ||
| # Get the relevant axis | ||
| if ax is None: ax = gca() | ||
| old_ax = axes_handler(ax) | ||
| gridpar = grid_handler(grid, ax) | ||
| xlim = lims_handler(xlim, ax) | ||
| ylim = lims_handler(ylim, ax) | ||
| # Assign bounds if none given | ||
| if (bounds is None): | ||
| if orientation == 'horizontal': | ||
| bounds = xlim if xlim is not None else ax.get_xlim() | ||
| bounds = xlim if xlim not in [None, 'auto'] else ax.get_xlim() | ||
| else: | ||
| bounds = ylim if ylim is not None else ax.get_ylim() | ||
| bounds = ylim if ylim not in [None, 'auto'] else ax.get_ylim() | ||
@@ -589,11 +658,7 @@ # Parse expression | ||
| plot_finalizer(xlog, ylog, xlim, ylim, title, xlabel, ylabel, xinvert, yinvert, grid) | ||
| _plot_finalizer(xlog, ylog, xlim, ylim, title, xlabel, ylabel, xinvert, yinvert, gridpar, ax) | ||
| # Autoscale the axes if needed | ||
| if xlim is None: ax.autoscale(axis='x') | ||
| if ylim is None: ax.autoscale(axis='y') | ||
| if old_ax is not None: | ||
| sca(old_ax) | ||
| if old_axes is not ax: | ||
| old_axes = axes_handler(old_axes) | ||
| return(curves[0] if len(curves) == 1 else curves, expr) | ||
@@ -611,3 +676,3 @@ | ||
| Plot the curve(s) corresponding to mathematical expressions over a given range across the independent variable. | ||
| Expressions can be given with multiple variables, whereby one is taken to be the independent variable and all | ||
| Expressions can be given with multiple variables, whereby one is taken to be the independent variable and all | ||
| others are substitution variables. This function can only accept one value per substitution variable. | ||
@@ -619,3 +684,3 @@ | ||
| An expression parsed either as a string, sympy expression or callable (function or lambda) | ||
| which will be evaluated by the function in the range of `bounds`. A piece-wise function is defined | ||
| which will be evaluated by the function in the range of `bounds`. A piece-wise function is defined | ||
| by parsing a list of expressions. The piece-wise functionality must also be reflected in `bounds`. | ||
@@ -631,5 +696,5 @@ var : str or sympy symbol, required. | ||
| the x-axis ('horizontal') or the y-axis ('vertical') of the plot. | ||
| splotch.curve('a*x') is notationally the same as splotch.curve('1/a*y',var='y',orientation='vertical'). | ||
| splotch.curve('a*x') is notationally the same as splotch.curve('1/a*y',var='y',orientation='vertical'). | ||
| bounds : list-like, optional | ||
| The range over which the function will be plotted. If not given, these default to the current bounds | ||
| The range over which the function will be plotted. If not given, these default to the current bounds | ||
| of the axes being plotted onto, given by `ax`. | ||
@@ -653,4 +718,7 @@ intervals : list-like, required | ||
| If True the scale of the x-axis is logarithmic. | ||
| grid : boolean, optional | ||
| If not given defaults to the value defined in splotch.Params. | ||
| grid : boolean, dict or None | ||
| The grid behaviour, acts according to: | ||
| * If boolean, the grid is set on (True) or off (False). | ||
| * If dict, allows specific `.Line2D` properties of the grid to be set. | ||
| * If None, use default grid parameters if this is the initial plotting call, otherwise do nothing. | ||
| title : str, optional | ||
@@ -684,6 +752,6 @@ Sets the title of the plot | ||
| **kwargs: Line2D properties, optional | ||
| kwargs are used to specify matplotlib specific properties such as linecolor, linewidth, | ||
| antialiasing, etc. A list of available `Line2D` properties can be found here: | ||
| kwargs are used to specify matplotlib specific properties such as linecolor, linewidth, | ||
| antialiasing, etc. A list of available `Line2D` properties can be found here: | ||
| https://matplotlib.org/3.1.0/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D | ||
| Returns | ||
@@ -696,13 +764,14 @@ ------- | ||
| Otherwise, simply returns the `expr` that was given. | ||
| """ | ||
| # Get the relevant axis | ||
| if ax is None: ax = gca() | ||
| old_ax = axes_handler(ax) | ||
| gridpar = grid_handler(grid, ax) | ||
| xlim = lims_handler(xlim, ax) | ||
| ylim = lims_handler(ylim, ax) | ||
| if ax is not None: | ||
| old_axes=axes_handler(ax) | ||
| else: | ||
| ax=gca() | ||
| old_axes=ax | ||
| # Assign bounds if none given | ||
| if (bounds == None): | ||
| # Assign bounds if none given | ||
| if (bounds is None): | ||
| if orientation == 'horizontal': | ||
@@ -714,5 +783,5 @@ bounds = xlim if xlim is not None else ax.get_xlim() | ||
| # Check if iterable | ||
| try: # duck-type check | ||
| try: # duck-type check | ||
| _ = (k for k in expr) | ||
| if isinstance(expr,str): | ||
| if isinstance(expr, str): | ||
| expr = [expr] | ||
@@ -725,6 +794,6 @@ elif isinstance(expr, tuple): | ||
| # Parse expressions | ||
| isfunc=[False]*len(expr) | ||
| isfunc = [False] * len(expr) | ||
| for ii in range(len(expr)): | ||
| if (isinstance(expr[ii], str)): | ||
| expr[ii]=sympify(expr[ii]) | ||
| expr[ii] = sympify(expr[ii]) | ||
| elif (callable(expr[ii])): | ||
@@ -737,3 +806,3 @@ isfunc[ii] = True | ||
| if not (all(isfunc) or all([not b for b in isfunc])): # Must either be all expressions or all callables | ||
| if not (all(isfunc) or all([not b for b in isfunc])): # Must either be all expressions or all callables | ||
| raise TypeError("`expr` cannot mix callable functions with expressions.") | ||
@@ -747,3 +816,3 @@ | ||
| intervals = list(intervals) | ||
| if len(intervals) == 0: # if no intervals are given, set the interval to be the ending bound as a placeholder | ||
| if len(intervals) == 0: # if no intervals are given, set the interval to be the ending bound as a placeholder | ||
| if len(expr) == 1: | ||
@@ -753,5 +822,5 @@ intervals = [bounds[-1]] | ||
| raise ValueError(f"No intervals given for {len(expr)} expressions.") | ||
| elif len(intervals) != len(expr) - 1: | ||
| elif len(intervals) != len(expr) - 1: | ||
| raise ValueError(f"There should be N-1 intervals for N expressions, instead received {len(intervals)} intervals for {len(expr)} expressions.") | ||
| else: # If intervals are given, ensure they are within the bounds given. | ||
| else: # If intervals are given, ensure they are within the bounds given. | ||
| if min(intervals) <= bounds[0]: | ||
@@ -763,3 +832,2 @@ raise ValueError(f"The minimum interval value should be within the current bounds ({bounds[0]}, {bounds[1]}).") | ||
| intervals = [intervals] | ||
@@ -772,16 +840,16 @@ # Validate the substitution variable names | ||
| if subs is None: subs = dict() | ||
| if not any(isfunc): # expr contains Sympy expressions | ||
| if not any(isfunc): # expr contains Sympy expressions | ||
| symbols = expr[0].free_symbols | ||
| for ii in range(len(expr)): | ||
| symbols=expr[ii].free_symbols # Get expression Symbols | ||
| symbolkeys=[str(symb) for symb in symbols] # convert these to strings, instead of sympy.Symbols | ||
| symbols = expr[ii].free_symbols # Get expression Symbols | ||
| symbolkeys = [str(symb) for symb in symbols] # convert these to strings, instead of sympy.Symbols | ||
| if var is None: # Assume independent variable is 'x', otherwise, assume the first symbol. | ||
| if var is None: # Assume independent variable is 'x', otherwise, assume the first symbol. | ||
| if orientation == 'horizontal': | ||
| var = 'x' #if 'x' in symbolkeys or len(symbolkeys)==0 else None | ||
| else: # first test for 'y' as an independent variable, then default to x. | ||
| var = 'x' # if 'x' in symbolkeys or len(symbolkeys)==0 else None | ||
| else: # first test for 'y' as an independent variable, then default to x. | ||
| if 'y' in symbolkeys: | ||
| var = 'y' | ||
| else: | ||
| var = 'x' #if 'x' in symbolkeys or len(symbolkeys)==0 else symbolkeys[0] | ||
| var = 'x' # if 'x' in symbolkeys or len(symbolkeys)==0 else symbolkeys[0] | ||
@@ -797,3 +865,3 @@ # remove the independent variable from the symbols and append to list | ||
| # Check for any substitution variables that are not in any expressions | ||
| for key in list(subs): | ||
| for key in list(subs): | ||
| if not any([key in symb for symb in symbolkeysArr]): | ||
@@ -803,25 +871,25 @@ raise KeyError(f"Substitution variable '{key}' does not exist in any 'expr'") | ||
| # The lengths of each substitute value list, len=1 if just a single value | ||
| lens = [len(subs[key]) if (isinstance(subs[key], Iterable) and type(subs[key])!=str) else 1 for key in list(subs)] | ||
| if (permute == True): | ||
| lens = [len(subs[key]) if (isinstance(subs[key], Iterable) and not isinstance(subs[key], str)) else 1 for key in list(subs)] | ||
| if (permute is True): | ||
| L = prod(lens) | ||
| perms=array(meshgrid(*subs.values())).reshape(len(subs),-1) | ||
| permsubs={} | ||
| perms = array(meshgrid(*subs.values())).reshape(len(subs), -1) | ||
| permsubs = {} | ||
| for ii, key in enumerate(list(subs)): | ||
| permsubs[key]=perms[ii] | ||
| subsarr=simpler_dict_splicer(permsubs,L,[1]*L) | ||
| permsubs[key] = perms[ii] | ||
| subsarr = simpler_dict_splicer(permsubs, L, [1] * L) | ||
| else: | ||
| L=max(lens) if len(lens) > 0 else 1 | ||
| subsarr=simpler_dict_splicer(subs,L,[1]*L) | ||
| L = max(lens) if len(lens) > 0 else 1 | ||
| subsarr = simpler_dict_splicer(subs, L, [1] * L) | ||
| # Combine the `explicit` plot_kw dictionary with the `implicit` **kwargs dictionary | ||
| plot_par={**plot_kw, **kwargs} | ||
| plot_par = {**plot_kw, **kwargs} | ||
| # Create 'L' number of plot kwarg dictionaries to parse into each plot call | ||
| plot_par=dict_splicer(plot_par,L,[1]*L) | ||
| plot_par = dict_splicer(plot_par, L, [1] * L) | ||
| # Create the legend object | ||
| if bool(label) == False: # label was `None` or `False` | ||
| labellist = None | ||
| if bool(label) is False: # label was `None` or `False` | ||
| labellist = [None] * L | ||
| elif label == True: # Auto-generate labels | ||
| elif label is True: # Auto-generate labels | ||
| if subsarr == [{}]: | ||
@@ -832,15 +900,15 @@ labellist = [f"${latex(expr)}$" if uselatex else str(expr)] | ||
| exprstr = f"${latex(expr)}$" if uselatex else str(expr) | ||
| for ii in range(L): # Make a label for each of sub values | ||
| for ii in range(L): # Make a label for each of sub values | ||
| if uselatex: | ||
| labellist.append(f"{exprstr} (" + "; ".join( [f"${key}$={subsarr[ii][key]}" for jj, key in enumerate(list(subsarr[ii])) ] ) +")" ) # join substitute strings together | ||
| labellist.append(f"{exprstr} (" + "; ".join([f"${key}$={subsarr[ii][key]}" for jj, key in enumerate(list(subsarr[ii]))]) + ")") | ||
| else: | ||
| labellist.append(f"{exprstr} (" + "; ".join( [f"{key}={subsarr[ii][key]}" for jj, key in enumerate(list(subsarr[ii])) ] ) +")" ) # join substitute strings together | ||
| labellist.append(f"{exprstr} (" + "; ".join([f"{key}={subsarr[ii][key]}" for jj, key in enumerate(list(subsarr[ii]))]) + ")") | ||
| elif isinstance(label,str): # A single string | ||
| labellist = [label]*L | ||
| elif isinstance(label, str): # A single string | ||
| labellist = [label] * L | ||
| else: | ||
| try: # Test whether the parameter is iterable | ||
| try: # Test whether the parameter is iterable | ||
| _ = (k for k in label) | ||
| except TypeError: # was not an iterable | ||
| except TypeError: # was not an iterable | ||
| raise TypeError(f"`label` of type {type(label)} is not recognised.") | ||
@@ -853,6 +921,6 @@ | ||
| vararr = logspace(*log10(bounds),num=num) if xlog else linspace(*bounds,num=num) | ||
| vararr = logspace(*log10(bounds), num=num) if xlog else linspace(*bounds, num=num) | ||
| intervals.append(vararr[-1]) | ||
| curves=[None]*L | ||
| for ii in range(L): | ||
| curves = [None] * L | ||
| for ii in range(L): | ||
| lines = [] | ||
@@ -863,3 +931,3 @@ start = 0 | ||
| if any(isfunc): | ||
| lines.append( list( zip(vararr[start:end+1],expr[jj](vararr[start:end+1],**subsarr[ii])) ) ) | ||
| lines.append(zip(vararr[start: end + 1], expr[jj](vararr[start: end + 1], **subsarr[ii]))) | ||
| else: | ||
@@ -873,7 +941,7 @@ lamb = lambdify(var, expr[jj].subs(subsarr[ii]), modules='numpy') | ||
| if orientation == 'horizontal': | ||
| lines.append( list( zip(vararr[start:end+1],func(vararr[start:end+1])) ) ) | ||
| lines.append(list(zip(vararr[start: end + 1], func(vararr[start: end + 1])))) | ||
| else: | ||
| lines.append( list( zip(func(vararr[start:end+1]),vararr[start:end+1]) ) ) | ||
| lines.append(list(zip(func(vararr[start: end + 1]), vararr[start: end + 1]))) | ||
| start = end # move to next interval | ||
| start = end # move to next interval | ||
@@ -883,11 +951,8 @@ curves[ii] = LineCollection(lines, label=labellist[ii], **plot_par[ii]) | ||
| plot_finalizer(xlog,ylog,xlim,ylim,title,xlabel,ylabel,xinvert,yinvert,grid) | ||
| _plot_finalizer(xlog, ylog, xlim, ylim, title, xlabel, ylabel, xinvert, yinvert, gridpar, ax) | ||
| if xlim is None: ax.autoscale(axis='x') | ||
| if ylim is None: ax.autoscale(axis='y') | ||
| if old_ax is not None: | ||
| sca(old_ax) | ||
| if old_axes is not ax: | ||
| old_axes=axes_handler(old_axes) | ||
| return(curves[0] if len(curves)==1 else curves) | ||
| return(curves[0] if len(curves) == 1 else curves) | ||
@@ -898,10 +963,2 @@ | ||
| #################################### | ||
| ######################################################################## | ||
| ############## Definition of all wrappers for 1D plotting ############## | ||
| ######################################################################## | ||
| #################################### | ||
| # 1D histogram and binned statistics | ||
| #################################### | ||
| def hist(data, bin_type=None, bins=None, dens=True, cumul=None, scale=None, weights=None, hist_type=None, orientation='vertical', | ||
@@ -986,4 +1043,7 @@ v=None, vstat=None, nmin=0, color=None, xlim=None, ylim=None, xinvert=False, yinvert=False, xlog=False, ylog=None, title=None, | ||
| Use the given axes to make the plot, defaults to the current axes. | ||
| grid : boolean, optional | ||
| If not given defaults to the value defined in splotch.Params. | ||
| grid : boolean, dict or None | ||
| The grid behaviour, acts according to: | ||
| * If boolean, the grid is set on (True) or off (False). | ||
| * If dict, allows specific `.Line2D` properties of the grid to be set. | ||
| * If None, use default grid parameters if this is the initial plotting call, otherwise do nothing. | ||
| plot_par : dict, optional | ||
@@ -1004,11 +1064,14 @@ Passes the given dictionary as a kwarg to the plotting function. | ||
| # Set the current axis | ||
| if ax is not None: | ||
| old_axes = axes_handler(ax) | ||
| else: | ||
| ax = gca() | ||
| old_axes = ax | ||
| # Get the relevant axis | ||
| if ax is None: ax = gca() | ||
| old_ax = axes_handler(ax) | ||
| if not isinstance(data, (list, tuple, ndarray)) or (len(shape(data)) == 1 and array(data).dtype is not dtype('O')): | ||
| gridpar = grid_handler(grid, ax) | ||
| if not isinstance(data, (list, tuple, ndarray)): | ||
| data = [data] | ||
| elif isinstance(data, ndarray): | ||
| if (len(shape(data)) == 1 and data.dtype is not dtype('O')): | ||
| data = [data] | ||
| L = len(data) | ||
@@ -1041,3 +1104,2 @@ | ||
| xlim = [nanmean(data) - xlim * nanstd(data), nanmean(data) + xlim * nanstd(data)] | ||
| if ylog is None: | ||
@@ -1053,6 +1115,7 @@ ylog = Params.hist1D_yaxis_log | ||
| xlim = lims_handler(xlim, ax) | ||
| ylim = lims_handler(ylim, ax) | ||
| # Combine the `explicit` plot_kw dictionary with the `implicit` **kwargs dictionary | ||
| # plot_par={**plot_kw, **kwargs} # For Python > 3.5 | ||
| plot_par = plot_kw.copy() | ||
| plot_par.update(kwargs) | ||
| plot_par = {**plot_kw, **kwargs} | ||
@@ -1158,18 +1221,21 @@ # Check if width is given as a kwarg | ||
| if ylim is None and orientation == 'vertical': # Adjust ylims if None given. | ||
| if ylim == 'auto' and orientation == 'vertical': # Adjust ylims if None given. | ||
| if not ylog and all([val is None for val in v]): # These automatic limits do not apply when ylog=True or statistics are used. | ||
| ylim = [0, max(nanmax(y) * (1 + rcParams['axes.ymargin']), gca().get_ylim()[1])] | ||
| if xlim is None and orientation == 'horizontal': # Adjust xlims if None given. | ||
| if xlim == 'auto' and orientation == 'horizontal': # Adjust xlims if 'auto'. | ||
| if not xlog and all([val is None for val in v]): # These automatic limits do not apply when ylog=True or statistics are used. | ||
| xlim = [0, max(nanmax(y) * (1 + rcParams['axes.xmargin']), gca().get_xlim()[1])] | ||
| plot_finalizer(xlog, ylog, xlim, ylim, title, xlabel, ylabel, xinvert, yinvert, grid) | ||
| _plot_finalizer(xlog, ylog, xlim, ylim, title, xlabel, ylabel, xinvert, yinvert, gridpar, ax) | ||
| if old_axes is not ax: | ||
| old_axes = axes_handler(old_axes) | ||
| if old_ax is not ax: | ||
| sca(old_ax) | ||
| if len(n_return) == 1: | ||
| n_return = n_return[0] | ||
| if len(bin_edges) == 1: | ||
| bin_edges = bin_edges[0] | ||
| if output: | ||
@@ -1219,4 +1285,7 @@ return(n_return, bin_edges) | ||
| Use the given axes to make the plot, defaults to the current axes. | ||
| grid : boolean, optional | ||
| If not given defaults to the value defined in splotch.Params. | ||
| grid : boolean, dict or None | ||
| The grid behaviour, acts according to: | ||
| * If boolean, the grid is set on (True) or off (False). | ||
| * If dict, allows specific `.Line2D` properties of the grid to be set. | ||
| * If None, use default grid parameters if this is the initial plotting call, otherwise do nothing. | ||
| plot_kw : dict, optional | ||
@@ -1236,8 +1305,10 @@ Passes the given dictionary as a kwarg to the plotting function. Valid kwargs are | ||
| if ax is not None: | ||
| old_axes = axes_handler(ax) # Set current axis to ax and return the previous axis to old_axes. | ||
| else: | ||
| ax = gca() | ||
| old_axes = ax | ||
| # Get the relevant axis | ||
| if ax is None: ax = gca() | ||
| old_ax = axes_handler(ax) | ||
| gridpar = grid_handler(grid, ax) | ||
| xlim = lims_handler(xlim, ax) | ||
| ylim = lims_handler(ylim, ax) | ||
| if not isinstance(x, list) or len(shape(x)) == 1: | ||
@@ -1256,5 +1327,3 @@ x = [x] | ||
| # Combine the `explicit` plot_kw dictionary with the `implicit` **kwargs dictionary | ||
| # plot_par={**plot_kw, **kwargs} # For Python > 3.5 | ||
| plot_par = plot_kw.copy() | ||
| plot_par.update(kwargs) | ||
| plot_par = {**plot_kw, **kwargs} | ||
@@ -1266,11 +1335,11 @@ # Create 'L' number of plot kwarg dictionaries to parse into each plot call | ||
| for i in range(L): | ||
| lines += plt_plot(x[i], y[i], label=label[i], **plot_par[i]) | ||
| lines += ax.plot(x[i], y[i], label=label[i], **plot_par[i]) | ||
| if any(label): | ||
| legend(loc=lab_loc) | ||
| plot_finalizer(xlog, ylog, xlim, ylim, title, xlabel, ylabel, xinvert, yinvert, grid) | ||
| _plot_finalizer(xlog, ylog, xlim, ylim, title, xlabel, ylabel, xinvert, yinvert, gridpar, ax) | ||
| if old_axes is not ax: | ||
| old_axes = axes_handler(old_axes) | ||
| if old_ax is not ax: | ||
| sca(old_ax) | ||
| return (lines[0] if len(lines) == 1 else lines) |
Sorry, the diff of this file is too big to display
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
217557
6.09%4127
5.33%