Package: pydove
PyDove: an assortment of graphics utilitiesThis is an assortment of utilities for plotting in Python usingmatplotlibandseaborn. Below are some highlights.FeaturesA figure managerThe defaultmatplotlibfigure uses a box around the figure. For most plots I find this to be both a waste of ink and a bit ugly. It can also make it hard to see points close to the edges of the figure. For these reasons, I usually use thedespinefunction fromseabornto remove the right and upper segments of the figure box, and also to add a bit of an offset between the remaining spines. Like this:To automate this behavior, I createdFigureManager, a context manager that basically callsplt.subplots, but also appliesdespineto the axes upon exit. For instance, the figure above can be obtained using:importnumpyasnpfrompydoveimportFigureManagerwithFigureManager(1,2)as(_,axs):x=np.linspace(0,10,100)fori,axinenumerate(axs):ax.plot(x,np.sin(x),c=f"C{i}")Note that theFigureManageralso scales the figure size when using multiple panels so that each panel is the same size as the default figure. This is in contrast tomatplotlib's default behavior which is to keep the figure size fixed. The behavior of theFigureManageris fully configurable -- see the docstring and the example notebook in thetestfolder for details.A more usefulregplotTheseabornfunctionregplotallows overlaying a fit line and confidence interval on a scatter plot. Unfortunately, it does not either a) provide a mechanism to access the fitting results, or b) allow plotting a user-provided fit line. This package provides a reimplementation [*] ofsns.regplotthat returns theRegressionResultsstructure from astatsmodelslinear fit. The implementation also provides functionsscatter,fitplot, andpolyfit, that are used byregplotto generate the scatter part of the plot, the fit line and confidence interval, and to obtain the fitting results, respectively.[*] Some features ofsns.regplotare not currently implemented. Others may behave slightly differently.Theregplotfunction provided here should function as a drop-in replacement forsns.regplotin most cases. The main disadvantage is that the styling options are slightly different, and so the results might not always match perfectly. In some cases this is by design (because I didn't likeseaborn's choices), but in other cases it's because I haven't yet implemented all the hacks thatseabornemploys to yield good-looking plots.There are some things that thisregplotfunction does better thansns.regplot:consistency:all the fits are calculated usingstatsmodels, even the polynomial ones.speed:confidence intervals are calculated directly usingstatsmodels, removing the need for bootstrapping.flexibility:polynomial fits inlog(x)are not allowed insns.regplotbut work here.configurability:the number of points used for the fit line and confidence interval is configurable;separate keyword options for confidence intervals are supported.The basic usage is identical toseaborn,e.g.:importmatplotlib.pyplotaspltimportpydoveasdvimportnumpyasnp# generate some datarng=np.random.default_rng(0)x=np.linspace(0,1,100)y=3.0*x-0.15+rng.normal(size=len(x))# plot itfig,ax=plt.subplots()res=dv.regplot(x,y,order=2,ax=ax)will make a scatter plot ofyvs.x, fitting a second-order polynomial through the data:Thestatsmodelsresults structure contains a wealth of information:res.summary()More examples can be found in the notebooks in thetestfolder.Colorbar and colormap functionsThe default colorbar function inmatplotlibis not always easy to use and often leads to a colorbar whose height is not matched to the figure. Thecolorbarfunction inpydovemakes this easy (using code inspired fromStackoverflow). Additionaly,plt.colorbardoes not work withscatter, whereasdv.colorbardoes:importnumpyasnpimportpydoveasdvrng=np.random.default_rng(0)withdv.FigureManager()as(_,ax):n=500x=rng.uniform(size=n)y=rng.uniform(size=n)h=ax.scatter(x,y,c=y)dv.colorbar(h)Sometimes it is useful to define a color map that interpolates between two given colors. Matplotlib'sLinearSegmentedColormapdoes this, but in a format that is awkward to use. The functiondv.gradient_cmapmakes it easy:importnumpyasnpimportpydoveasdvrng=np.random.default_rng(0)withdv.FigureManager()as(_,ax):h=ax.imshow(rng.uniform(size=(20,20)),cmap=dv.gradient_cmap("C0_to_C1","C0","C1"))dv.colorbar(h)PlottingSometimes it is useful to generate a line plot with varying colors. This can be done like this:importnumpyasnpimportpydoveasdvcustom_cmap=dv.gradient_cmap("custom_cmap","C0","C1")withdv.FigureManager(1,2)as(_,(ax1,ax2)):x=np.linspace(0,10,100)y=np.sin(x)c=yax1.axhline(0,color="gray",ls=":")dv.color_plot(x,y,c,cmap=custom_cmap,ax=ax1)ax1.autoscale()c=np.linspace(0,6*np.pi,250)r=np.linspace(1,4,len(c))**2x=r*np.cos(c)y=r*np.sin(c)ax2.axhline(0,color="gray",ls=":",lw=0.5)ax2.axvline(0,color="gray",ls=":",lw=0.5)dv.color_plot(x,y,c,ax=ax2)max_r=np.max(r)ax2.set_xlim(-max_r,max_r)ax2.set_ylim(-max_r,max_r)ax2.set_aspect(1)InstallationFrom PyPIThe package is now available on PyPI, so you can simply runpipinstallpydoveFrom sourceAfter cloning the repository or downloading and decompressing, run the following command in the folder containingsetup.py:pipinstall.