_histograms
Histogram plotting helpers from _plotting/_histograms.py.
Main entry point
adata_histograms
adata_histograms
adata_histograms(...) draws one histogram per selected variable from either an AnnData object or a wide pandas.DataFrame.
It can also draw one histogram per variable metadata group, such as one panel
per gene when multiple variant columns map to the same gene.
By default, histograms are filled density plots with KDE overlays. Subgroup
histograms use palette=palettes.tol_colors unless subset_palette is supplied,
and keep the same subgroup-to-color mapping across every panel.
Panels include a red dotted zero reference line by default, plus dashed mean
lines whose values are added to legends by default.
Full signature
def adata_histograms(
adata: anndata.AnnData | None = None,
*,
df: pd.DataFrame | None = None,
var_df: pd.DataFrame | None = None,
var_names: Sequence[str] | None = None,
var_groupby_key: str | None = None,
collapse_mode: Literal["stack", "aggregate", "all"] = "aggregate",
collapse_func: Literal[
"mean",
"median",
"sum",
"min",
"max",
"count",
"select_max_ref_value",
] = "mean",
ref_values_obsm_key: str = "ref_values",
layer: str | None = None,
use_raw: bool = False,
filter_vars_by_isin_lists: Mapping[str, Sequence[Any]] | None = None,
filter_obs_by_isin_lists: Mapping[str, Sequence[Any]] | None = None,
subset_obs_key: str | None = None,
subset_order: Sequence[Any] | None = None,
palette: Sequence[Any] | str | None = palettes.tol_colors,
subset_palette: Sequence[Any] | str | None = None,
show_all_obs_hist: bool = True,
all_obs_color: Any = "0.7",
all_obs_alpha: float = 0.20,
ncols: int = 3,
figsize: tuple[float, float] | None = None,
sharex: bool = False,
xlims: Sequence[float] | None = None,
add_zero_line: bool = True,
add_mean_line: bool = True,
add_mean_to_legend: bool = True,
highlight_negative_mean_legend: bool = True,
bins: int | str | Sequence[float] = "auto",
binwidth: float | None = None,
binrange: tuple[float, float] | None = None,
stat: Literal["count", "frequency", "probability", "percent", "density"] = "density",
multiple: Literal["layer", "dodge", "stack", "fill"] | None = None,
element: Literal["bars", "step", "poly"] | None = None,
fill: bool | None = True,
kde: bool = True,
common_bins: bool = True,
common_norm: bool = False,
discrete: bool | None = None,
cumulative: bool = False,
alpha: float | None = None,
color: Any | None = None,
xlabel: str | None = None,
ylabel: str | None = None,
title: str | None = None,
subplot_title_var_col: str | None = None,
title_fontsize: int = 14,
axis_label_fontsize: int = 12,
tick_label_fontsize: int | None = None,
legend_fontsize: int | None = None,
legend_loc: str | int | None = None,
legend_bbox_to_anchor: tuple[float, ...] | None = None,
legend: bool = True,
dropna: bool = True,
nas2zeros: bool = False,
dropzeros: bool = False,
show: bool = True,
) -> tuple[plt.Figure, dict[str, plt.Axes]]:
Basic example
import adata_science_tools as adtl
fig, axes = adtl.adata_histograms(
adata=adata,
layer="log1p",
filter_vars_by_isin_lists={"feature_type": ["protein"]},
filter_obs_by_isin_lists={"Treatment": ["drug"]},
subset_obs_key="Batch",
show_all_obs_hist=True,
sharex=True,
xlims=[-2, 2],
bins=30,
show=False,
)
Legend positioning
Use legend_loc and legend_bbox_to_anchor to move per-panel legends.
adtl.adata_histograms(
adata=adata,
var_names=["GENE_A"],
subset_obs_key="Treatment",
legend_loc="upper left",
legend_bbox_to_anchor=(1.02, 1),
show=False,
)
Supported input modes
adata=...uses.X,adata.layers[layer], oradata.raw.Xwhenuse_raw=True.df=...expects rows to be observations and selected feature columns to contain the values to plot. Providevar_namesorvar_df.indexso metadata columns are not guessed as features.var_df=...is feature metadata for DataFrame input. It is used forfilter_vars_by_isin_listsand optional subplot labels, not as the numeric values being plotted.
All-variable stacked histogram
With
var_groupby_key=None,collapse_mode="all"draws one combined panel keyed as"all"by stacking all selected raw variable values.var_names=[...]still selects raw variable names in this mode, andfilter_vars_by_isin_listsis applied before stacking.Observations with more selected measured variables contribute more values to the histogram;
collapse_funcis ignored because no within-observation aggregation is performed.
adtl.adata_histograms(
adata=adata,
var_names=["GENE_A_variant_1", "GENE_A_variant_2"],
collapse_mode="all",
subset_obs_key="Treatment",
sharex=True,
xlims=[-2, 2],
)
Variable-grouped histograms
var_groupby_key="column"groups raw variable columns by a variable metadata column afterfilter_vars_by_isin_listsis applied.In grouped mode,
var_names=[...]selects group names, not raw variable names, and returned axes are keyed by group name strings.collapse_mode="stack"pools all non-missing observation-by-variant values in each group into one variant-level distribution. Observations with more measured variants contribute more values.collapse_mode="aggregate"appliescollapse_funcacross variants within each observation, producing one observation-level value per group before plotting.Grouped mode defaults to
collapse_mode="aggregate"withcollapse_func="mean"so each observation contributes at most one value per group.Missing values are handled after stacking or aggregation.
sumpreserves all-missing observations as missing, whilecountreturns0for observations with no non-missing variants.collapse_func="select_max_ref_value"selects one variant per observation and group using the largest non-missing reference value fromadata.obsm[ref_values_obsm_key], then plots that selected variant’s value from.X,layer, or.raw.X.Reference values may be a DataFrame with observation index and variant columns, or an array-like value with rows aligned to
adata.obs_namesand columns aligned to the active plotting variable axis.Tied maximum reference values are resolved by the first variant in filtered variable order and logged as warnings. Observations with all reference values missing produce missing collapsed values before
nas2zeros,dropna, anddropzerosare applied.DataFrame input with
var_groupby_keyrequiresvar_dfbecause group metadata must come from variable metadata.select_max_ref_valueis only supported for AnnData input.
adtl.adata_histograms(
adata=adata,
var_groupby_key="Gene",
var_names=["GENE_A"],
collapse_mode="stack",
subset_obs_key="Treatment",
sharex=True,
xlims=[-2, 2],
)
post_minus_pre = adtl.ref_vs_target_adata(
adata,
pair_by_key="SubjectID",
opperation_flavor="relative_change_l2fc",
save_source_values_obsm=True,
)
adtl.adata_histograms(
adata=post_minus_pre,
var_groupby_key="Gene",
var_names=["GENE_A"],
collapse_mode="aggregate",
collapse_func="select_max_ref_value",
ref_values_obsm_key="pre_values",
subset_obs_key="Treatment",
sharex=True,
xlims=[-2, 2],
)
adtl.adata_histograms(
adata=adata,
var_groupby_key="Gene",
var_names=["GENE_A"],
collapse_mode="aggregate",
collapse_func="mean",
subset_obs_key="Treatment",
sharex=True,
xlims=[-2, 2],
)
Filtering and Subsets
filter_obs_by_isin_lists={"column": ["allowed"]}filters observations with AND semantics.filter_vars_by_isin_lists={"column": ["allowed"]}filters variables with AND semantics.subset_obs_key="column"draws overlapping histograms by observation metadata group after observation filtering.In subset mode,
show_all_obs_hist=Trueby default adds a neutral non-subsetted all-observation histogram behind the subset histograms for each variable; setshow_all_obs_hist=Falseto opt out.palettecontrols subgroup colors by default;subset_paletteoverrides those colors when provided.add_zero_line=Truedraws a red dotted vertical reference line atx=0.add_mean_line=Truedraws dashed vertical mean lines for the overall histogram, the all-data subset overlay, or each subgroup histogram.add_mean_to_legend=Trueadds mean values to the legend when mean lines are drawn and legends are enabled. In subset mode, the legend starts withAll data (mean=...), computed from all filtered plotted values in the panel after value filtering and before missingsubset_obs_keylabels are ignored for subgroup layers.highlight_negative_mean_legend=Truerenders calculated negative mean legend entries in red bold text by default. This applies to non-subset labels such asMean = -2, all-data labels such asAll data (mean=-1), and subgroup labels such ascase (mean=-3). Sethighlight_negative_mean_legend=Falseto keep Matplotlib’s default legend text styling.Missing
subset_obs_keyvalues are ignored for grouped histogram layers; variables with no plottable subgroup rows get an annotated empty panel instead of stopping the full figure.
Important behavior
AnnData extraction is column-focused for the selected variables and does not densify the full matrix.
The default
stat="density"andkde=Truenormalize distributions for shape comparison; usestat="count"and/orkde=Falsefor raw count histograms.KDE is skipped for panels or grouped layers with fewer than two distinct plottable values so sparse subsets still draw histograms.
sharex=Trueapplies common x-axis limits across selected variable panels;xlims=[lower, upper]sets explicit x-axis limits for every panel.show=Falsecloses the figure before returning, matching the package’s other test-backed plotting APIs.The return value is
(fig, axes)whereaxesis a dict keyed by selected variable name, selected group name, or"all"forcollapse_mode="all".