Repository navigation
Releases
Releases · datavil/ggrust
ggrust 0.9.0
Added
geom_band, as lets-plot: a band across the whole panel betweenxminandxmax(vertical) oryminandymax(horizontal), mapped or constant (geom_band(xmin=1, xmax=2)), with edge lines andalphaon the fill only.geom_bracket_dodge, as lets-plot: brackets between the dodged groupsistartandiendof categoryx(ngroup,dodge_width), same bars, tips and labels asgeom_bracket.residual_plot(bistro), as lets_plot:from ggrust.bistro import residual_plotplots the residuals of a polynomial (method="lm",deg=) or local ("loess", needs statsmodels and scipy) fit of y on x, with a dashed line at zero and marginal densities;as_dict()matches lets_plot's.image_matrix(bistro), as lets_plot: a grid ofgeom_imshowimages from a 2D object array (cmap,norm,vmin,vmax,scale,spacer); the cells areinset_elementfigures, so it returns aPlotSpec. Empty (None) cells stay blank.nudge_unit="size"/"px"ongeom_text,geom_label,geom_text_repel,geom_label_repelandgeom_bracket: the nudge is added in point diameters (2.2 px) or pixels after the coord, as lets-plot.alpha_stroke=Trueongeom_labelandgeom_label_repelfades the text and border byalphatoo.scale_identity(aesthetic, ...), the generic identity scale of lets-plot: a name or a list (scale_identity(['color', 'fill'])). The module of the per-aesthetic identity scales is nowggrust.plot.scale_identity_(lets-plot's name), soggrust.plot.scale_identityis the function.joint_plotandqq_plot(bistro), as lets_plot:from ggrust.bistro.joint import joint_plotdraws points, 2D bins or a 2D density with a dashed regression line and marginal histograms, densities or boxplots;from ggrust.bistro.qq import qq_plotdraws a sample against a theoretical distribution (or two samples against each other) with the fitted line and marginal densities of the quantiles.joint_plot'sas_dict()matches lets_plot's.- Animation, after gganimate:
p + transition_manual("year", cumulative=False)draws one frame per value;animate(plot, nframes=, fps=, duration=, detail=, start_pause=, end_pause=, rewind=, width=, height=, dpi=)plans the frames as gganimate and returns anAnimation(.frame(i),.save(),.to_gif(),.to_apng(),.to_html()).{current_frame},{frame},{nframes}and{progress}in the title, subtitle and caption are filled per frame. Notebooks show an HTML player (play, pause, slider);anim_save("x.gif")andggsave(plot, "x.gif" | "x.png" | "x.html")write a GIF, animated PNG or player page. Scales are trained once, so axes stay fixed; stats and positions run per frame. - Animation states, after gganimate:
p + transition_states("year", transition_length=1, state_length=1, wrap=True)holds each state and moves the marks smoothly into the next (rows matched by group; numbers and sizes eased, colours through CIE Lab, categories switch halfway), andease_aes("cubic-in-out", y="bounce-out")picks tweenr's easing per aesthetic. Labels gain{closest_state},{previous_state},{next_state}and{transitioning}. - Animation over time, after gganimate:
p + transition_time("year", range=None)spaces the frames evenly in time and moves the marks between the observed times (dates and date-times too), andp + transition_reveal("date", range=None, keep_last=True)grows lines, areas and polygons along a column with an interpolated end point while points travel along their group. Labels gain{frame_time}and{frame_along}. - Animation enter/exit effects and shadows, after gganimate:
enter_fade(alpha=0),exit_fade(alpha=0),enter_grow(size=0)andexit_shrink(size=0)let marks without a partner in the next state fade, grow or shrink in and out over the transition (bars from the axis, lines and polygons from their centre; effects added with+apply in order);shadow_wake(wake_length, size=True, alpha=True, colour=None, fill=None, falloff="cubic-in", wrap=True, exclude_layer=None, exclude_phase=("enter", "exit"))trails moving marks with their last frames, andshadow_mark(past=True, future=False, exclude_layer=None, **styles)keeps earlier (or later) states in the background. Work withtransition_statesandtransition_time.
Fixed
- Animated GIFs are 2.5x to 22x smaller and about 3x faster to write: frames that come out pixel-identical are merged into one longer frame, and each later frame holds only the rectangle that changed, with unchanged pixels transparent (as gifski does). Frames of at most 255 colours keep their exact colours.
- Animated lines and polygons whose point count changes between states now morph smoothly: points are inserted along the shape as gganimate (transformr) does, every shape gets at least 50 points, polygons are drawn clockwise and rotated for the least travel. The warning about points matched in order is gone.
- Animation labels pad years to 4 digits (
0001-01-01, as R), and a date-time column uses one label format for the whole animation: the time shows in every frame when any value has one, so midnight no longer prints the date alone next to frames with times (gganimate formats each frame alone; decided by the user). - Animations of a date or date-time column label states as dates (
{current_frame},{closest_state}, ...), not epoch numbers, andtransition_time/transition_revealreject arangeof the wrong kind for the column (numbers for a date column, dates for a numeric one) with aSpecError. ggsave(anim.frame(i), "x.png")writes that one frame as a still PNG (it wrote the whole animation as APNG); SVG, PDF and the notebook display of a frame are still too, and.gifof a frame is anExportError.- A continuous legend over a single value shows one key at that value, as ggplot2, not about five near-identical ones (lets-plot #1267).
- Legend keys with the same label but different values no longer merge (lets-plot #1129):
scale_color_manual(labels=['A', 'A', 'C'])shows three keys, as ggplot2.
ggrust 0.8.0
Added
geom_streamline()/stat_streamline(), as R metR:ggplot(data) + geom_streamline(aes(x=, y=, u=, v=))draws streamlines with one arrowhead half way along each line, per group and facet panel. Rows that form a complete regular grid are used as the field; scattered rows are first averaged onto a grid withvelocity_grid()(gridded=forces either). Lines are integrated withstreamplot()(density,minlength,maxlength,integration_direction,broken_streamlines). New stat-only aestheticsuandv. Not in lets-plot (see deviations.md).velocity_grid(points, vectors, ...): average vectors at scattered points onto a regular grid (Gaussian-weighted nearest neighbours), as scVelo'scompute_velocity_on_grid, without scVelo. Returns aVelocityGrid(x, y, u, v)that feedsstreamplot()directly. Same values as scVelo 0.3.4 on the reference cases; about 7x faster.density_outline(points, level=...): outline a 2D point cloud where its Gaussian kernel density falls toleveltimes its peak, as scipy'sgaussian_kdeplus scikit-image'sfind_contours, without either. Returns an(x, y, path)frame forgeom_path(). Same contours as scipy 1.17 / scikit-image 0.26 on the reference cases; about 10x faster.kernel_density(values, at, bandwidth=...): the Gaussian kernel density of a 1D sample at given points, as scipy's 1Dgaussian_kde(Scott, Silverman or a factor), returned as an(x, density)frame. Within 1e-13 of scipy's values on the reference cases.
ggrust 0.7.1
Added
streamplot(x, y, u, v, density=...): matplotlib's streamlines computed in Rust, no matplotlib needed. Returns aStreamplotSetwithlines(x, y, group) andarrows(x, y, xend, yend, group) polars frames, ready forgeom_path()+geom_segment(arrow=). Lines and arrows match matplotlib 3.10 exactly on the reference cases. Masked arrays and NaN/inf are treated as missing; a density that would need more than 1e8 mask cells raises an error instead of aborting.
ggrust 0.7.0
Changed
- HTML output draws point layers with more than 5,000 markers on a canvas (was 50,000), so mid-sized scatters make much smaller pages. SVG and PNG output are unchanged.
- Smaller interactive HTML: the interactive legend indexes keys per marker instead of wrapping runs of points, and point tooltips on canvas layers reuse the canvas coordinates. Rendering is unchanged.
PlotSpec,FeatureSpecandSupPlotsSpec+returnsNotImplementedfor operands it does not handle, so another object's__radd__(plot)runs: a plain class can extend+without subclassingPlotSpec. Unhandled operands still raiseTypeError(Python's standard message). lets_plot raises in__add__itself.
Added
grid[i] = figureongggridresults replaces a cell in place (int or(row, column), negative from the end,Noneempties it), sogrid[i] += layeradds a layer to one plot of a grid, nested grids included.scale_x_dendro(leaf_levels=)/scale_y_dendro(leaf_levels=): dendrogram leaves that span a run of axis levels,{leaf: [levels]}(for example a tree over clusters beside a heatmap of their cells). The runs are placed end to end in the tree's order, each in its given order, and each leaf is drawn at the centre of its run, on either side, reversed, undercoord_flip()and ingggrid(align=True). Every leaf needs a run, and a level belongs to one run; mistakes raiseSpecErrornaming the leaf.gggrid(axes=, axis_titles=), as patchwork'splot_layout(axes=, axis_titles=):"collect"(or"collect_x"/"collect_y") draws an axis that repeats in neighbouring plots once, on the outer plot of the run, and frees the room of the others; repeated axis titles become one, centred on the run's panels. Axes count as equal when their scales and axis theme match (usesharex/sharey) and, for x, they span the same columns (y: rows). Empty cells, nested grids and faceted plots break runs. A collecting grid keeps its panels equal (relative towidths/heights), as patchwork: the dropped room is shared by all panels. Default"keep".guide_axis_nested()andkey_range_manual(), as R legendry: brackets (or boxes) naming groups of an axis's breaks, past the axis labels or across the panel (side="opposite"). Groups as a mapping{group: [levels]}orkey_range_manual(start, end, name);bracket="line" | "square" | "chevron",type="box",pad_discrete,angle; multi-line names with\n. Theme elementslegendry_bracket,legendry_bracket_size,legendry_box,legendry_guide_spacing. Works on every side,coord_flip(), facets,gggrid(align=True), side band axes and the HTML zoom.- Side band panel theme elements, as R ggside's
ggside.panel.*:theme(ggside_panel_border=, ggside_panel_background=)and theirggside_xside_panel_*/ggside_yside_panel_*forms, falling back to the mainpanel_border/panel_background.ggside_panel_border=element_blank()drops the side bands' frames and keeps the main panel's.
ggrust 0.6.2
Fixed
- Interactive legend: clicking a key on a dense (canvas) point layer no longer blocks the page. The key dims at once and the canvas is redrawn once on the next frame; a double-click redraws one to two times instead of three.
ggrust 0.6.1
Added
- Side band axis theme elements, as R ggside's
ggside.axis.*:theme(ggside_axis_text, ggside_axis_ticks, ggside_axis_ticks_length, ggside_axis_minor_ticks, ggside_axis_minor_ticks_length, ggside_axis_line), each with_x,_x_top,_x_bottom,_y,_y_left,_y_rightvariants. Anything unset falls back to the mainaxis_*theme. guide_axis_mark(): label a subset of an axis's breaks with leader lines (ComplexHeatmap'sanno_markas an axis guide).spread="nearest"or"even",link_width,padding. Works on discrete and continuous axes, every side, side bands, facets andgggrid(align=True).- Several side bands per axis:
side_pos=on a ggside layer overridesggside()for that layer,side_band=names a band (bands on one side stack outward in plot order), andside_size=sets a band's share of the panel.scale_xsidey_*/scale_ysidex_*takeside_pos=andside_band=to set one band's axis. - Docs: the ggrust logo, and a showcase of plots on the README and docs home page.
Fixed
- A y side band's own x axis now reserves room for its ticks and labels (it could overflow the canvas).
- Blank side band axis labels no longer take up room.
ggrust 0.6.0
Highlights
- Side panels and marginal plots: ggside-style side layers and lets-plot's
ggmarginal(). - Plot files:
ggsave(plot, "x.ggrs")writes a self-contained plot file,ggload("x.ggrs")opens it. - Notebook output mode is now chosen with
ggrust.display(mode).
Added
- Side panels (ggside):
geom_xside*/geom_yside*layers for tile, bar, col, histogram, density, point, boxplot, violin, line and text;scale_xsidey_*/scale_ysidex_*;ggside(x_pos=, y_pos=);theme(ggside_panel_scale*, ggside_panel_spacing*). Bands followcoord_flip, axisposition=and HTML zoom. ggmarginal(sides, size, layer), with the same spec as lets_plot..ggrsplot files:ggsave(plot, "x.ggrs")stores the spec, data (Arrow IPC) and registered fonts in one zip;ggload("x.ggrs")restores it (polars, pandas, pyarrow or dict data). Loading runs no code and verifies sizes and hashes.ggrust.display("html" | "svg" | "png")picks what notebooks show: interactive HTML (default), static SVG without JavaScript, or PNG.- Boxplot tooltips show each statistic as a lets-plot style side tooltip.
- Docs: a guide page and gallery section for the built-in ggplot2 extensions, with credits to the R packages.
Changed
ggtb()shows the layers menu by default; passlayers=Falseto remove it.
Breaking
- The
LetsPlotshim is removed. DeleteLetsPlot.setup_html()calls; useggrust.display(mode)to switch output.displayis not in__all__, sofrom ggrust import *does not shadow IPython'sdisplay().
Fixed
- Side band axes: discrete labels are no longer blanked and get room to fit; thin continuous bands keep at least one label.
ggrust 0.5.0
Highlights
- Built-in ggplot2 extensions: ggsci palettes, ggbeeswarm, ggnewscale, ggpointdensity, ggrastr, gghalves/ggdist, ggpubr/ggpmisc statistics, ggforce marks, dendrograms, gghighlight and patchwork extras.
- Secondary axes, axes on top/right, custom fonts, and an interactive legend in HTML output.
- Read-only spec accessors:
layer_data(),build()and plot properties.
Added
- ggsci journal palettes:
scale_color_*/scale_fill_*for npg, aaas, nejm, lancet, jama, jco, d3 and igv. - ggbeeswarm:
geom_beeswarm,geom_quasirandom. - ggnewscale:
new_scale_color(),new_scale_fill(),new_scale(). - ggpointdensity:
geom_pointdensity,stat_pointdensity. - ggrastr:
rasterize(layer, dpi=300)draws a layer as an image in SVG and PDF. - gghalves and ggdist: half geoms, slabs and intervals for raincloud plots.
- ggpubr / ggpmisc:
stat_compare_means,stat_cor,stat_poly_eq. - ggforce:
geom_mark_hull,geom_mark_ellipse,geom_mark_rect. - Dendrograms: hierarchical clustering,
geom_dendrogram,scale_*_dendroandguide_axis_dendro(follow HTML zoom and pan). - gghighlight: grey out non-matching rows, with direct repel labels.
- patchwork extras: tags, design layouts, insets and nested alignment.
geom_col,geom_rugandstat_ellipse(ggplot2 semantics).- Secondary axes:
sec_axis,dup_axis,derive. position=on x and y scales draws the axis on the top/right side, or both.- Custom fonts:
register_font,register_font_dir,registered_fonts. - Spec accessors:
PlotSpec.data,.mapping,.layers,.scales,.themeand more;with_data();layer_data(i)andbuild()return the engine's computed data as polars frames.SupPlotsSpecgetsfigures,grid[i],with_figure(),with_layout()and more. NewPlotIndexError. - Theme geom colors as lets-plot: defaults follow the theme flavor, the color names
"pen","brush","paper"work everywhere, andtheme(geom=element_geom(...))is drawn. - Manual legends:
manual_key=on every geom andlayer_key(...). gggridcaptions vialabs(caption=).geom_boxplot(outlier_jitter=, outlier_seed=).- A style scale with an explicit
na_valuegets an "NA" legend key or colorbar swatch. - Interactive legend in HTML output: click legend keys to hide and show groups.
Fixed
- Notebook HTML works in Google Colab (tooltips, toolbar and canvas layers were static there).
ipykernelis no longer a runtime dependency.
ggrust 0.4.0
Highlights
- Arrow axis lines,
oob=on color scales, and colorbar end labels. - HTML plots shrink to fit their container.
Added
element_line(arrow=, extent=)on axis lines: arrow heads and partial axis lines (for UMAP-style corner axes).oob="censor" | "squish"on continuous color and fill scales.guide_colorbar(label_position="ends"): min and max labels beside the ends of the bar.lineheightongeom_textandgeom_label.
Changed
- A later style scale that sets a mapper (
scale_color_manualafter a default brewer scale, for example) now replaces the earlier one, as in ggplot2. Names, breaks, labels, limits, guide and trans still merge. - HTML plots wider than their notebook cell or docs column shrink to fit, keeping their aspect ratio. Tooltips and zoom keep working.
Fixed
gggrid(guides="collect"): each collected legend keeps its own figure's theme.- Horizontal colorbars reserve room for end labels so they no longer run into the title.
ggrust 0.3.0
Highlights
facet_grid, vector PDF output, andgeom_curve.corr_plotwith a Rust correlation matrix.
Added
facet_grid: panels by columns and rows, row strips, free scales per grid column or row.- Facet label options:
x_order/y_order,x_format/y_format,x_labwidth/y_labwidthonfacet_grid,labwidthonfacet_wrap, multi-line strips. geom_curve(curvature, angle, ncp, spacer, arrow).- Vector PDF output from
ggsave: paths, embedded subset fonts and images. corr_plot(bistro).- Minor ticks and
exponent_format. halo_width/halo_colorongeom_textandgeom_text_repel.- Mapped
hjust/vjustongeom_textandgeom_label.
Changed
- Faster zoom in
ggtbplots: points are drawn on a canvas from 2,000 points, using a sprite atlas.
Fixed
- Box zoom keeps the aspect ratio of
coord_fixedpanels. exponent_formatapplies to HTML zoom labels.