Correlation-scatter and rank-comparison plotting helpers from _plotting/_corr_dotplots.py.
This is the most test-backed plotting module in the package. Direct regression tests live in tests/test_corr_dotplots.py.
corr_dotplotcorr_dotplot_dev(deprecated compatibility wrapper)spearman_cor_dotplotspearman_cor_dotplot_2plot_rank_scatterplot_rank_heatmapplot_rank_scatter_densitypairwise_spearman_corr_matrixcompare_ranked_listsplot_heatmap
corr_dotplot(...) is the primary public API for correlation scatter plots, subgroup fit lines, and optional x/y marginal histograms.
def corr_dotplot(
df: pd.DataFrame | None = None,
*,
adata: anndata.AnnData | None = None,
layer: str | None = None,
x_df: Any | None = None,
var_df: pd.DataFrame | None = None,
obs_df: pd.DataFrame | None = None,
column_key_x: str | None = None,
column_key_y: str | None = None,
hue: str | None = None,
subset_key: str | None = None,
figsize: tuple[float, float] = (20, 10),
xlabel: str | None = None,
ylabel: str | None = None,
axes_title: str | None = None,
axes_lines: bool = True,
show_y_intercept: bool = True,
palette: Sequence[Any] | str | None = palettes.godsnot_102,
subset_palette: Sequence[Any] | str | None = None,
dot_size: float = 200,
title_fontsize: int = 20,
stats_fontsize: int | None = None,
axes_title_y: float | None = None,
axis_label_fontsize: int = 20,
tick_label_fontsize: int | None = None,
legend_fontsize: int | None = None,
fit_legend_bbox_to_anchor: Sequence[float] | None = None,
hue_legend_bbox_to_anchor: Sequence[float] | None = None,
show_all_obs_fit: bool = False,
show_fit: bool = True,
show_fit_legend: bool = True,
show_hue_legend: bool = True,
show_stats_text: bool = True,
show_identity_line: bool = False,
identity_line_label: str | None = "Identity",
identity_line_style: Mapping[str, Any] | None = None,
identity_limits: Literal["shared_axes", "data"] = "shared_axes",
nas2zeros: bool = False,
dropna: bool = False,
dropzeros: bool = False,
method: Literal["spearman", "pearson"] = "pearson",
show_x_marginal_hist: bool = False,
show_y_marginal_hist: bool = False,
x_marginal_hist_bins: int | Sequence[float] = 20,
y_marginal_hist_bins: int | Sequence[float] = 20,
x_marginal_hist_fill: bool = True,
x_marginal_hist_KDE: bool = True,
y_marginal_hist_fill: bool = True,
y_marginal_hist_KDE: bool = True,
show_all_obs_x_hist: bool = False,
show_all_obs_y_hist: bool = False,
x_marginal_hist_height_ratio: float = 0.18,
y_marginal_hist_width_ratio: float = 0.18,
xscale: str = "linear",
yscale: str = "linear",
xlims: Sequence[float] | None = None,
ylims: Sequence[float] | None = None,
xlim_padding_fraction: float | None = None,
ylim_padding_fraction: float | None = None,
x_reference_lines: Sequence[Mapping[str, Any]] | None = None,
y_reference_lines: Sequence[Mapping[str, Any]] | None = None,
show: bool = True,
) -> tuple[
plt.Figure,
plt.Axes | dict[str, plt.Axes | None],
Any,
float,
float,
]:import adata_science_tools as adtl
fig, axes, fit, corr_value, corr_pvalue = adtl.corr_dotplot(
adata=adata,
layer="log1p",
column_key_x="geneA",
column_key_y="geneB",
hue="Treatment",
subset_key="Batch",
method="spearman",
show_x_marginal_hist=True,
show_y_marginal_hist=True,
show=False,
)
main_ax = axes["main"]
top_hist_ax = axes["x_marginal"]
right_hist_ax = axes["y_marginal"]subgroup_marginals — Correlation with subgroup fits and marginals. Data and analysis provenance.
log1p_identity — Correlation on synchronized log1p axes. Data and analysis provenance.
df=...with preassembled plotting columnsadata=...with an optionallayerx_dfplusobs_df, with optionalvar_dfwhen feature columns need names
When df is provided, the AnnData-derived path is ignored. column_key_x and column_key_y are required and must resolve to numeric columns after the final plotting table is assembled.
corr_dotplot(...) always returns (fig, axes, fit, corr_value, corr_pvalue).
- With both marginal flags disabled,
axesis the single scatterAxes, preserving the original public contract. - With either marginal enabled,
axesis a dictionary containing"main","x_marginal", and"y_marginal"; a disabled marginal entry isNone. fit,corr_value, andcorr_pvaluealways describe the overall filtered observations, including when subgroup fits are drawn.
methodmust be"pearson"or"spearman".nas2zeros,dropna, anddropzeroscontrol x/y cleanup before statistics.palettecolorshue-driven scatter points, whilesubset_palettecolorssubset_key-driven fit and marginal layers.subset_keydraws one fit line per subgroup when fitting succeeds.- Subgroup order follows categorical order for categorical columns, ascending order for non-categorical numeric columns, and first-seen order for other columns.
show_all_obs_fit=Trueadds the overall fit line in subset mode.show_fit=Falsehides fit artists without changing returned fit or correlation statistics.show_identity_line=Truedraws y=x over the shared visible interval or combined finite data range.xscaleandyscaleaccept"linear","log","log2", and"log1p"; enabled marginals use the same scale and limits as the main axes."log"uses Matplotlib's default logarithmic base, while"log2"uses a base-2 logarithmic scale."log1p"useslog1p/expm1function scaling, accepts finite values strictly greater than -1, and keeps the legacy origin line valid.- On nonlinear axes, fit and identity artists sample their raw-coordinate linear relation densely; correlation and regression statistics still use the untransformed values.
- Automatic and fractionally padded
"log1p"ranges include the data plus active fit endpoints and axis-reference values, including a legacy origin line, before applying transformed-space padding that stays above -1. - Explicit limits still win; an explicit reference sequence replaces the legacy origin on that axis, and an empty sequence draws none. Reference specifications other than
Nonemust be sequences of mappings. - Explicit limits take precedence over padding; padding is calculated in the configured transformed space for all three logarithmic modes.
- Data, limits, references, fit endpoints, and identity coordinates must satisfy each configured scale's domain.
- When identity coordinates span two transformed axes, the stricter lower domain bound applies.
- Reference entries are drawn in caller order and accept
value,label,color,linestyle,linewidth,alpha, andzorder. show_fit_legend,show_hue_legend, andshow_stats_textare independent display controls.fit_legend_bbox_to_anchorandhue_legend_bbox_to_anchoraccept 2-item or 4-item sequences.- If no valid subgroup values remain,
corr_dotplot(...)falls back to the all-data fit and statistics; enabled marginals also show the all-data distributions. show=Falsecloses the figure before returning so notebook backends do not auto-render it.
- The supported layouts are no marginals, x-only above the scatter, y-only to the right, and both marginals.
- Marginals always use the same filtered observations as the scatter and returned statistics.
- Without
subset_key, each enabled marginal draws one overall histogram. - With
subset_key, marginal grouping followssubset_key, nothue, and usessubset_palette. show_all_obs_x_histandshow_all_obs_y_histadd muted all-observation overlays in subset mode.- Bin arguments accept an integer count or explicit one-dimensional edge sequences. Explicit edges for an enabled marginal must contain at least two finite, strictly increasing values within the configured scale's domain.
- Fill and KDE overlays can be controlled independently for x and y.
x_marginal_hist_height_ratioandy_marginal_hist_width_ratiocontrol marginal panel size relative to the main panel.- When an x marginal is enabled,
axes_titlebelongs toaxes["x_marginal"]; otherwise it belongs to the main axes. - Default legends move beyond the right marginal when one is present; explicit legend anchors still win.
Regression tests cover observation/feature name collisions, generic and sparse matrix extraction, full matrix-shape validation, styling controls, optional footer text, subgroup fit failures, independent legends, separate palettes, numeric subgroup ordering, all four layouts, grouped and all-observation marginals, filtering parity, integer and explicit bins, fill/KDE controls, subplot ratios, title ownership, footer spacing, legend placement, main-limit preservation, the empty-subset fallback, Spearman forwarding, early scale validation, and synchronized log, log2, and log1p axes.
The config-driven example uses corr_dotplot(...) with both marginals enabled:
example_simulated_data/config/config.yamlcontains the marginal controls.example_simulated_data/scripts/plot_dotplot_simulate_1_var_covar_age.pyloads the simulated AnnData and creates the plot.- The generated figure is available at
baseline.png.
corr_dotplot_dev(...) is deprecated. It emits DeprecationWarning and forwards all arguments to corr_dotplot(...).
For compatibility, its second return value is always the three-key axes dictionary, including when both marginals are disabled. New code should use corr_dotplot(...) and follow the conditional return contract above.
replacement_smoke — Deprecated correlation wrapper. Data and analysis provenance. Deprecated: use corr_dotplot instead.
spearman_cor_dotplot(...) is a backward-compatible wrapper around corr_dotplot(...).
def spearman_cor_dotplot(*args, **kwargs):fig, ax, fit, corr_value, corr_pvalue = adtl.spearman_cor_dotplot(
df,
"x",
"y",
"group",
show=False,
)spearman_fit — Spearman correlation compatibility API. Data and analysis provenance. Compatibility API: prefer corr_dotplot for new code.
Important behavior:
- It forces
method="spearman"even if a different method is passed. - It still supports the older positional calling style
df, column_key_x, column_key_y, hue, ....
Creates a two-panel scatter plot of the same x/y pair with two different hue columns. It returns (figure, axes).
def spearman_cor_dotplot_2(df, column_key_x, column_key_y, hue, hue_right, figsize=(20, 10)):dual_hue — Correlation under two categorical encodings. Data and analysis provenance.
plot_rank_scatter,plot_rank_heatmap, andplot_rank_scatter_densitycompare two ranked lists using the ranks of shared elements.- They return
(correlation, p_value). - If the lists share no common elements, they return
(None, None).
rank_agreement — Rank agreement. Data and analysis provenance.
rank_hexbin — Rank agreement density. Data and analysis provenance.
rank_density — Rank agreement with local density. Data and analysis provenance.
Builds a pairwise Spearman correlation matrix across a dictionary of ranked lists.
Computes the Spearman correlation between two ranked lists without plotting and returns (correlation, p_value), or (None, None) when there is no overlap.
Heatmap helper for numeric matrices or DataFrame input. This function is documented from code rather than regression tests; use it as a convenience helper rather than a heavily stabilized API.
clustered — Clustered rank-correlation heatmap. Data and analysis provenance.
fixed_order — Fixed-order rank-correlation heatmap. Data and analysis provenance.
fig, ax, fit, corr_value, corr_pvalue = adtl.corr_dotplot(
df=df,
column_key_x="Age",
column_key_y="CRP",
hue="Outcome",
show=False,
)
fig.savefig("results/age_crp_corr.png", dpi=300, bbox_inches="tight")








