Plotting System
Table of contents
- TOC
All canonical plots are generated through the genecircuitry/plotting/ subpackage. This replaces the legacy inline plotting code that was scattered across preprocessing.py, grn_deep_analysis.py, and hotspot_processing.py.
genecircuitry/plotting/
├── __init__.py # Re-exports all public plot functions
├── qc_plots.py # QC violin and scatter plots
├── grn_plots.py # GRN network graphs, centrality heatmaps, rank plots
├── hotspot_plots.py # Hotspot local correlation heatmaps, module plots
└── utils.py # Shared helpers: save_plot(), plot_exists()
Shared utilities (plotting/utils.py)
save_plot(fig, filepath, plot_type, metadata, skip_existing, save_pdf)
Saves a matplotlib figure to disk in PNG and vector PDF formats, creates parent directories automatically, logs the save event, and returns True on success.
from genecircuitry.plotting.utils import save_plot
saved = save_plot( fig=fig, filepath=”results/figures/grn/my_network.png”, plot_type=”grn”, # label for logging metadata={“cluster”: “0”}, skip_existing=True, # skip if file already exists save_pdf=True, # also save .pdf alongside .png (default: config.SAVE_PDF) )
plot_exists(filepath, skip_existing, check_pdf)
Returns True if the file already exists (including its PDF counterpart when check_pdf=True) and skip_existing=True. Used internally in every plot function to avoid re-generating expensive plots.
from genecircuitry.plotting.utils import plot_exists
if not plot_exists("results/figures/grn/my_plot.png", skip_existing=True):
# generate and save
QC plots (plotting/qc_plots.py)
plot_qc_violin_pre_filter(adata, save_name, figsize, skip_existing)
Three-panel violin plot showing genes per cell, total counts, and mitochondrial % before QC filtering.
from genecircuitry.plotting.qc_plots import plot_qc_violin_pre_filter
plot_qc_violin_pre_filter(
adata,
save_name="run1", # appended to filename: violin_pre_filter_run1.png
figsize=None, # config.PLOT_FIGSIZE_LARGE if None
skip_existing=True,
)
# Saved to: config.FIGURES_DIR_QC/violin_pre_filter_run1.png
plot_qc_violin_post_filter(adata, save_name, figsize, skip_existing)
Same three-panel violin plot after QC filtering — for before/after comparison.
from genecircuitry.plotting.qc_plots import plot_qc_violin_post_filter
plot_qc_violin_post_filter(adata, save_name="run1")
# Saved to: config.FIGURES_DIR_QC/violin_post_filter_run1.png
plot_qc_scatter_pre_filter(adata, save_name, figsize, skip_existing)
Scatter plots: counts vs genes, counts vs MT%, genes vs MT% — useful for spotting doublets and dying cells.
from genecircuitry.plotting.qc_plots import plot_qc_scatter_pre_filter
plot_qc_scatter_pre_filter(adata, save_name="run1")
# Saved to: config.FIGURES_DIR_QC/scatter_pre_filter_run1.png
GRN plots (plotting/grn_plots.py)
generate_all_grn_plots(links, oracle, output_dir, stratification)
Convenience function that generates the full suite of GRN plots for a given Links object:
- Network graphs (one per cluster)
- Centrality score heatmaps
- TF rank plots
- Cross-cluster score comparisons
from genecircuitry.plotting.grn_plots import generate_all_grn_plots
generate_all_grn_plots(
links=links,
oracle=oracle,
output_dir="results/figures/grn/",
stratification="all_cells", # label for filenames
)
plot_network_graph_single(graph, cluster, stratification, ...)
Plots a single cluster’s regulatory network as a directed graph using NetworkX.
from genecircuitry.plotting.grn_plots import plot_network_graph_single
import networkx as nx
g = nx.DiGraph() # your GRN graph
plot_network_graph_single(
graph=g,
cluster="0",
stratification="TypeA",
top_n_nodes=30, # show top N hubs
figsize=None, # config.PLOT_FIGSIZE_SQUARED_LARGE
)
plot_enriched_tf_network(links, cluster, ...)
Network graph where TF nodes are annotated with their top enriched pathway term (requires gseapy).
plot_tf_shared_target_network(links, cluster_a, cluster_b, ...)
Bipartite network showing TFs and targets shared between two clusters — useful for comparing regulatory states.
Hotspot plots (plotting/hotspot_plots.py)
plot_hotspot_local_correlations(hotspot_obj, skip_existing)
Heatmap of pairwise local correlation z-scores between significant genes, with genes ordered by module.
from genecircuitry.plotting.hotspot_plots import plot_hotspot_local_correlations
plot_hotspot_local_correlations(hs, skip_existing=True)
# Saved to: config.FIGURES_DIR_HOTSPOT/hotspot_local_correlations.png
plot_module_scores_violin(hotspot_obj, adata, cluster_key, figsize, skip_existing)
Violin plots of per-module scores split by cell cluster — shows which clusters are enriched for each gene module.
from genecircuitry.plotting.hotspot_plots import plot_module_scores_violin
plot_module_scores_violin(
hotspot_obj=hs,
adata=adata,
cluster_key="leiden",
skip_existing=True,
)
# Saved to: config.FIGURES_DIR_HOTSPOT/module_scores_violin.png
Comparative & aggregation plots (plotting/comparative_plots.py)
Visualizations for cross-cluster and cross-stratification integration:
plot_comparative_module_activity(activity_df, save_name, skip_existing)
Row-standardized Z-score heatmap (cmap="viridis") comparing Hotspot co-expression module activation across clusters or stratifications.
plot_cross_stratification_module_overlap(jaccard_df, alignment_summary_df, save_name, skip_existing)
Heatmap (cmap="viridis") of gene-set Jaccard similarity across modules from different stratifications to align homologous programs and prevent numeric module name collisions.
plot_tf_module_regulatory_matrix(tf_mod_matrix, save_name, skip_existing)
Heatmap (cmap="inferno") showing target gene overlap counts between top transcription factors and co-expression modules.
plot_tf_module_concordance(concordance_df, save_name, skip_existing)
Bubble matrix (cmap="inferno") cross-referencing module expression scores (color) and top driver TF target coverage percentages (bubble size).
plot_gene_selection_sankey(provenance_df, save_name, skip_existing)
4-stage alluvial flow diagram (pastel) tracing genes from Hotspot significance to module assignment, GRN master driver role, cluster specificity, and pathway enrichment.
plot_comparative_tf_centrality(tf_pivot_df, tf_summary_df, save_name, skip_existing)
Heatmap (cmap="inferno") of TF degree centralities across groups with automatic $\bigstar$ Global Master Regulator and $\blacklozenge$ Group-Specific Regulator classifications.
plot_differential_tf_targets(diff_targets_df, save_name, skip_existing)
Stacked horizontal bar chart partitioning TF targets into Conserved (pastel blue) and Condition-Specific / Rewired (pastel coral) sets.
plot_cross_cluster_regulatory_comparison(reg_summary_df, save_name, skip_existing)
2x2 multi-panel comparison of network scale, active TFs/modules, top central TFs, and dominant regulatory circuits per cluster.
plot_integrated_regulatory_dashboard(comparative_results, save_name, skip_existing)
6-panel publication-ready composite dashboard summarizing all comparative metrics.
Figure sizing and DPI
All plot functions accept a figsize parameter; when None, they fall back to a config preset:
| Config key | Default | Use |
|---|---|---|
PLOT_FIGSIZE_SMALL |
(6, 4) |
Inline/thumbnail plots |
PLOT_FIGSIZE_MEDIUM |
(10, 7) |
Standard single plots |
PLOT_FIGSIZE_LARGE |
(20, 15) |
QC panels with many subplots |
PLOT_FIGSIZE_WIDE |
(20, 8) |
Landscape / wide figures |
PLOT_FIGSIZE_SQUARED |
(6, 6) |
Square (network graphs) |
PLOT_FIGSIZE_SQUARED_LARGE |
(10, 10) |
Large square (network graphs) |
PLOT_DPI |
200 |
Screen rendering DPI |
SAVE_DPI |
600 |
File save DPI for publication quality |
PLOT_FORMAT |
'png' |
Output format |
SAVE_PDF |
True |
Automatically save PDF alongside PNG |
Override globally:
from genecircuitry import config config.update_config(SAVE_DPI=300, SAVE_PDF=True, PLOT_FORMAT=”png”)
---
All plot functions accept `skip_existing=True` (default). When a file already exists at the target path, the function returns `False` without regenerating the plot. Set `skip_existing=False` to force regeneration:
```python
plot_qc_violin_pre_filter(adata, skip_existing=False) # always regenerate
This is integrated with the checkpoint system — completed plot steps are not re-run on pipeline resume.
Adding new plots
New plot functions must live in the appropriate genecircuitry/plotting/ module (not in preprocessing.py or other analysis modules). Follow this template:
# In genecircuitry/plotting/qc_plots.py (or grn_plots.py / hotspot_plots.py)
def plot_my_new_figure(adata, save_name="default", figsize=None, skip_existing=True):
from .. import config
from .utils import save_plot, plot_exists
filepath = f"{config.FIGURES_DIR_QC}/my_figure_{save_name}.png"
if plot_exists(filepath, skip_existing):
return False
if figsize is None:
figsize = config.PLOT_FIGSIZE_MEDIUM
fig, ax = plt.subplots(figsize=figsize)
# ... plotting code ...
return save_plot(fig, filepath, plot_type="qc", metadata={"save_name": save_name})
Then export it from genecircuitry/plotting/__init__.py.