Visualise#
Block 6 — charts. See the guide. Requires
pip install chem-tactics[viz].
Benchmark comparison (Altair)#
- class TACTICS.library_analysis.visualization.TS_Benchmarks(no_of_cycles, methods_list, TS_runs_data, reference_data=None, top_n=100, sort_type='minimize', top_ns=None)[source]#
A class to generate visualizations of TS results. The goal here is to compare different cycles of TS runs with the same search strategy. This is mainly used to compare different search strategies to ground truth values. Each search strategy is used a no of times equal to the number of cycles. It is recommended that random baseline data and brute-force (exhaustive search) data be included for comparison. Reference data is optional, but is required for generating the barplots. A strip plot can be generated without reference data for comparison of methods.
All required data (TS runs data, bar plot data, line plot data, and grouped statistics) is automatically generated during initialization. After creating an instance, you can directly call the plotting methods without additional data generation steps.
- gen_TS_runs_data(top_n=100, sort_type='minimize')[source]#
Generates a single dataframe with all the TS runs data. This is a concatenated polars dataframe for each method
Parameters:#
- top_n: int
Number of top products to consider for each method
- sort_type: str
Type of sorting to perform on the data “minimize” - sorts the data in ascending order “maximize” - sorts the data in descending order
- stripplot_TS_results(width=None, height=None, save_path=None, show_plot=True, legend_position='right')[source]#
Generate a stripplot for TS results using altair. This visualizes the distribution of scores across cycles and methods. Data is automatically generated during class initialization.
Parameters:#
- width: Optional[int]
Width of the plot
- height: Optional[int]
Height of the plot
- save_path: Optional[str]
Path to save the plot
- show_plot: bool
If True, shows the plot in Jupyter
- legend_position: str
Position of the legend. “right” (default) or “bottom” for horizontal legend below plot.
Returns:#
- altair.Chart or None
The altair chart if show_plot is True, None otherwise
- get_barplot_TS_results_data(top_n=100)[source]#
Generate data for bar plot, for checking the number of hits recovered by each search strategy. To use this plot, you must have the reference compounds that serve as the ground truth. This shows what fraction of the top N reference compounds each method finds.
- Parameters:
top_n (int) – Number of top reference products to count as hits. Use the same
top_nfor every method.- Returns:
Hits found by each method in each cycle against the reference set.
- Return type:
polars.DataFrame
- plot_barplot_TS_results(width=None, height=None, save_path=None, show_plot=True, legend_position='right', dark_mode=False)[source]#
Generate a barplot for TS results using altair. This visualizes the number of reference hits recovered by each search strategy. Data is automatically generated during class initialization.
Parameters:#
- widthOptional[int]
Width of the plot in pixels
- heightOptional[int]
Height of the plot in pixels
- save_pathOptional[str]
Path to save the plot
- show_plotbool
If True, shows the plot in Jupyter
- legend_positionstr
Position of the legend. “right” (default) or “bottom” for horizontal legend below plot.
- dark_modebool
If True, uses white text for bar labels (for dark backgrounds). Default is False (black text).
Returns:#
- altair.Chart or None
The altair chart if show_plot is True, None otherwise
- gen_line_plot_performance_data(top_ns=None)[source]#
Generate data for line plot, for checking the performance of each method. The plot looks at how the performance of the methods changes with comparison to the top N compounds found by the reference method. Efficiently calculates fraction of hits found for each top_n cutoff.
Parameters:#
- top_nsList[int], optional
List of top N values to test (e.g., [50, 100, 200, 300, 400, 500]) If None, defaults to [50, 100, 200, 300, 400, 500]
Returns:#
- line_plot_dfpolars DataFrame
DataFrame with columns: [‘cycle’, ‘top_n’, ‘method’, ‘frac_top_n’]
- plot_line_performance_with_error_bars(width=None, height=None, save_path=None, show_plot=True, legend_position='right')[source]#
Generate a line plot with error bars for method performance using altair. Shows mean fraction of reference compounds found across cycles with standard deviation error bars. Data and grouped statistics are automatically generated during class initialization.
Parameters:#
- widthOptional[int]
Width of the plot in pixels
- heightOptional[int]
Height of the plot in pixels
- save_pathOptional[str]
Path to save the plot
- show_plotbool
If True, shows the plot in Jupyter
- legend_positionstr
Position of the legend. “right” (default) or “bottom” for horizontal legend below plot.
Returns:#
- altair.Chart or None
The altair chart if show_plot is True, None otherwise
Diagnostic plots (matplotlib)#
Matplotlib plotting functions for CATS diagnostics.
All functions accept Polars DataFrames and return matplotlib.figure.Figure
objects so callers can save, show, or compose them freely.
- TACTICS.library_analysis.diagnostic_plots.plot_criticality_trajectory(diagnostics_df, figsize=(10, 4))[source]#
Plot per-component criticality over cycles.
A horizontal band at criticality <= 0.3 is shaded as the “diffuse” zone.
- Parameters:
diagnostics_df (pl.DataFrame) – DataFrame from
sampler.get_diagnostics().figsize (tuple) – Figure size.
- Returns:
Matplotlib Figure.
- Return type:
Figure
- TACTICS.library_analysis.diagnostic_plots.plot_snr_trajectory(diagnostics_df, figsize=(10, 4))[source]#
Plot SNR evolution with a threshold line at SNR = 1.
Requires enhanced diagnostics (
snrcolumn).- Parameters:
diagnostics_df (pl.DataFrame) – Enhanced diagnostics DataFrame.
figsize (tuple) – Figure size.
- Returns:
Matplotlib Figure.
- Return type:
Figure
- TACTICS.library_analysis.diagnostic_plots.plot_temperature_decomposition(diagnostics_df, component_idx, figsize=(10, 6))[source]#
Plot full temperature pipeline decomposition for one component.
Shows base_temp, cats_multiplier, criticality_weight, effective_multiplier, and final_temperature on separate subplots.
Requires enhanced diagnostics.
- TACTICS.library_analysis.diagnostic_plots.plot_rws_diagnostic(diagnostics_df, title='', figsize=(12, 5))[source]#
RWS diagnostic: GMIC + CATS multiplier + divergence gate.
Dual y-axis plot averaged across replicates with 95 % confidence interval bands. Vertical background shading indicates batches where the divergence gate blocks GMIC modulation (diversity mode).
Left y-axis: GMIC per component (solid lines with CI bands).
Right y-axis: CATS multiplier per component (dashed lines). Shows the GMIC-driven temperature modulation directly, without the noisy heated/cooled oscillation that
final_temperaturehas. Values > 1 amplify exploration, < 1 amplify exploitation, = 1 is the base temperature.Background: light pink shading with red boundary lines when any component is in diversity mode in > 30 % of replicates.
- TACTICS.library_analysis.diagnostic_plots.plot_ttts_diagnostic(diagnostics_df, title='', figsize=(12, 5))[source]#
TT-TS diagnostic: disagreement EMA + heated_scale.
Dual y-axis plot averaged across replicates with 95 % confidence interval bands.
Left y-axis: disagreement EMA per component (solid lines). Right y-axis: heated_scale per component (dashed lines). Horizontal bands mark the adaptive thresholds (0.3 and 0.8).
Works with any number of components.
- TACTICS.library_analysis.diagnostic_plots.plot_reagent_usage_action_panel(search_df, diag_df, reagent_files, batch_size=100, replicate=None, aggregate_window=1, normalize='library', auto_trim=True, max_batches=None, component_names=None, title='', figsize=(14, 5.5), heated_label='Heated')[source]#
Two-panel reagent usage diagnostic: heating timeline + new-reagent lines.
Top panel (action strip). A thin categorical timeline showing which component was marked
is_heatedat each batch — one coloured block per batch, coloured by the component’s palette entry. Reads left-to-right like a sequence diagram. Batches with no heated record appear white. The strip’s y-label is set byheated_labelso the figure can use method-appropriate terminology (e.g."Heated"for RWS,"Explore"for TT-TS).Bottom panel (lines). Per-component lines showing the fraction of that component’s reagents first-seen in this batch (
new_count / n_reagents_per_component) — always library-normalized so the scree-plot decay reads the same across components. Uses the same component palette as the heating strip, so the reader can match each line to the heated-block colours in the strip above. Interpretation: the decay rate summarizes when the algorithm has exhausted the informative reagents per component.Note: the
normalizeparameter is retained for API compatibility but no longer affects the plot (the bar panel it controlled has been replaced by the heating strip). The value is still validated so stale callers passing unknown strings still raise.- Parameters:
search_df (pl.DataFrame) – Search-phase rows for a single trial (library, query, method, replicate), in evaluation order. Must have
Name(underscore-joined reagent IDs) andphasecolumns. Ifreplicateis None the DataFrame must already be filtered to a single replicate.diag_df (pl.DataFrame) – Per-cycle diagnostics for the same trial. Must have
component_idx,current_cycle,is_heated.reagent_files (list[Path]) – Ordered list of
.smifile paths, one per component. Used to count total reagents (forlibrarynormalization) and to correctly parse product names where reagent IDs themselves may contain underscores (e.g. adenine’sisocyanide_db_511).batch_size (int) – Evaluations per batch (default 100).
replicate (Optional[int]) – If provided, filter both DataFrames to this replicate.
aggregate_window (int) – If >1, bin every
aggregate_windowbatches into a single bar. Useful for long searches (e.g., 1000+ batches on docking libraries). Diversity is averaged across batches in the bin; new is recomputed against all prior bins; heated component is the majority within the bin.auto_trim (bool) – If True (default), automatically crop to the active region of the search — batches where the mechanism is still switching heated components or discovering new reagents. Trailing exploitation-only batches (same component heated for many batches with no new reagents) are dropped and a note is annotated on the figure.
max_batches (Optional[int]) – Hard upper limit on the number of batches shown. Takes precedence over
auto_trimif smaller.component_names (Optional[list[str]]) – Optional list of display names (one per component) to use in the legend instead of “Component N”. If
None, names are inferred from the common prefix of each component’s reagent IDs (e.g., adenine automatically becomes [“Amidine”, “Isocyanide”, “Aldehyde”]). Components with purely numeric reagent IDs fall back to “Component N”.normalize (str) –
"library"(default) normalizes by total reagents in each component — interpretation: fraction of the library sampled this batch."batch"normalizes bymin(batch_size, n_reagents)— interpretation: fraction of the maximum achievable diversity."share"normalizes each batch’s per-component count by the batch’s total unique-reagent count across components, producing a stacked-to-1 view. Use"share"on imbalanced libraries where components differ in size by many-fold, so small components don’t disappear visually when heated.title (str) – Plot title.
figsize (tuple) – Figure size.
heated_label (str) – Y-axis label for the action strip. Use
"Heated"for RWS-family methods (default) and"Explore"for TT-TS, where the strip marks the exploring component each batch (cooled / exploit components are the unfilled cells).
- Returns:
Matplotlib Figure.
- Return type:
Figure
- TACTICS.library_analysis.diagnostic_plots.plot_gmic_directed_exploration(search_df, diag_df, reagent_files, methods, *, method_labels=None, replicate=None, batch_size=100, component_names=None, component_colors=None, gmic_ref=1.0, title=None, figsize=None)[source]#
Layer 1: how GMIC directs WHICH component to explore (signal -> decision -> result).
One column per method; three stacked rows sharing the search-cycle x-axis:
- SIGNAL – per-component GMIC (criticality). High = the component’s reagent
means are well separated relative to noise (resolved -> exploit); low = unresolved (explore).
- DECISION – the per-component “explored” strip (
is_heated): which component the GMIC-weighted rotation sends exploration to each cycle.
- RESULT – cumulative per-component reagent coverage (fraction of that
component’s reagents discovered), each normalised to its own size.
On an imbalanced library (thrombin: 130 acids x 3844 dipeptides) the small component resolves immediately (high GMIC -> exploited -> coverage saturates to 100%) while the large one stays unresolved (low GMIC -> explored -> coverage climbs), making the GMIC-directed explore/exploit reallocation visible end to end.
- Parameters:
search_df (DataFrame) – Per-evaluation search log (
Name,method,replicate,phase); onlyphase == "search"rows are used.diag_df (DataFrame) – Per-cycle diagnostics (
method,replicate,current_cycle,component_idx,gmic,is_heated).reagent_files (list[Path]) – One
.smiper component (defines each component’s reagent IDs).methods (list[str]) – Method names to show as columns (e.g. the RWS and TT-TS labels).
method_labels – Optional
{method: display label}for the column titles.replicate – Replicate to plot; defaults to the smallest in
diag_df.batch_size (int) – Evaluations per cycle/batch (default 100).
component_names – Display names per component; inferred from reagent-ID prefixes when
None.component_colors – Line colours per component.
gmic_ref (float) – Reference line on the GMIC row (default 1.0 = critical/flexible boundary).
title – Figure suptitle.
figsize – Defaults to
(7.5 * n_methods, 9.2).
- Returns:
Matplotlib Figure.
- TACTICS.library_analysis.diagnostic_plots.plot_adaptive_intensity(search_df, diag_df, reagent_files, methods, *, method_labels=None, replicate=None, batch_size=100, component_names=None, component_colors=None, smooth_window=9, show_decision=True, result='new', title=None, figsize=None)[source]#
Layer 2: how each method tunes exploration within a component.
Where
plot_gmic_directed_exploration()(layer 1) shows WHICH component GMIC sends exploration to, this shows HOW HARD each method explores the chosen component, and what that yields in reagent discovery. One column per method; rows share the search-cycle x-axis:- INTENSITY – the per-component within-component knob, smoothed. Both knobs
are reported as dimensionless multipliers centred on 1.0 (1.0 = no adjustment; >1 = amplify exploration), so the two methods read on a common interpretation: RWS modulates the CATS temperature multiplier (
cats_multiplier, ×base temperature – the GMIC-driven factor); TT-TS modulates the σ-inflation multiplier (heated_scale, ×posterior σ – the disagreement-driven factor). Note the asymmetry the knobs reveal: RWS’s multiplier is GMIC-driven, so it amplifies above 1.0 on the unresolved (low-GMIC) component; TT-TS’s heated_scale is disagreement-driven, and because two-sample disagreement saturates (>0.8) on both components of a large library it decays toward 1.0 – most on the highest-disagreement (unresolved) component – i.e. the TT-TS adaptation is largely one-directional and cannot manufacture exploration beyond what the raw posteriors already provide.- DECISION – per-component heating probability (rolling fraction of
cycles in which the component was the explored/heated one). Omitted when
show_decision=False(leaving INTENSITY + RESULT, i.e. “just the temperature”).- RESULT – per-component within-component discovery.
result="new" (default) plots new reagents discovered per batch (the per-batch rate – the discrete increment of coverage);
result="coverage"plots cumulative coverage (% of the component’s reagents seen at least once – the running total, identical to the layer-1 RESULT row). New-per-batch is the derivative of coverage: it falls toward zero as the reagent pool is exhausted even while coverage is still rising.
On thrombin (130 acids × 3844 dipeptides) both methods keep discovering new dipeptides long after the small acid component is exhausted – the same reallocation, reached through two different within-component mechanisms.
- Parameters:
search_df (DataFrame) – Per-evaluation search log (
Name,method,replicate,phase); onlyphase == "search"rows are used.diag_df (DataFrame) – Per-cycle diagnostics (
method,replicate,current_cycle,component_idx,is_heatedplus the method-specific intensity columncats_multiplierfor RWS orheated_scalefor TT-TS).reagent_files (list[Path]) – One
.smiper component (defines each component’s reagent IDs).method_labels – Optional
{method: display label}for column titles.replicate – Replicate to plot; defaults to the smallest in
diag_df.batch_size (int) – Evaluations per cycle/batch (default 100).
component_names – Display names per component; inferred from reagent-ID prefixes when
None.component_colors – Line colours per component.
smooth_window (int) – Centred (edge-shrinking) rolling-mean window (cycles) applied to every row so the per-cycle heated/cooled square-wave reads as an effective average (default 9).
show_decision (bool) – Include the heating-probability row (default True).
result (str) –
"new"(new reagents per batch, default) or"coverage"(cumulative % coverage, as in layer 1).title – Figure suptitle.
figsize – Defaults to
(7.5 * n_methods, 9.2 or 7.0).
- Returns:
Matplotlib Figure.