CPPStructurePlot.explore

CPPStructurePlot.explore(df_feat, sequence, pdb=None, uniprot=None, df_seq=None, labels=None, model='rf', predictor=None, output='widget', path=None, col_imp='feat_impact', col_val='mean_dif', shap_plot=True, tmd_len=20, init_site=None, sites=None, label_target_class=1, mode='impact', focus='fade', focus_region=None, size_by_impact=True, normalize_by_span=False, chain=None, random_state=None, n_jobs=None, debounce_ms=250)[source]

Predict per site and paint the structure, with a selectable output type.

The integrated explorer ([pro]): given a feature set df_feat plus a labeled training population (df_seq + labels) and a model, it builds a per-site predictor that, for a P1 site, computes the query window’s feature values for the fixed feature set (never a CPP.run() rediscovery), predicts its probability, and attaches the per-site SHAP impact (a default ShapModel refit, fuzzy interpolate). It then dispatches to one of the render paths by output:

  • 'widget' -> interactive() (a live ipywidgets explorer; the P1 slider re-predicts and repaints per site; needs a kernel + ipywidgets).

  • 'html' -> a self-contained linked HTML, written to path if given. Baked for the single init_site by default; pass sites=[...] to bake a multi-site live page whose JS slider switches the pre-computed per-site prediction client-side (no kernel).

  • 'static' -> plot_combined() (the structure beside the feature map, baked for init_site). With path given, the feature-map panel is saved (CombinedView.savefig, format from the extension, e.g. PNG/PDF); the 3D structure stays interactive.

The site geometry follows the package convention: p1 is the first TMD residue, so the TMD spans [p1, p1 + tmd_len - 1] and start = p1 - jmd_n_len (the construction jmd_n_len / jmd_c_len). Pass predictor to override the built-in with a custom (sequence, p1) -> df_feat callable, in which case df_seq / labels / model are ignored.

Added in version 1.1.0.

Parameters:
  • df_feat (pd.DataFrame, shape (n_features, n_feature_info)) – Feature DataFrame with a feature column (the fixed feature set) and the scale-information columns the feature map needs. The per-site impact is computed and written to col_imp; an existing col_imp is overwritten per site.

  • sequence (str) – Full protein sequence of the query protein the P1 site ranges over.

  • pdb (str, optional) – Path to a .pdb / .cif structure file. Exactly one of pdb or uniprot must be given.

  • uniprot (str, optional) – UniProt accession; the AlphaFold model is fetched. Exactly one of pdb or uniprot must be given.

  • df_seq (pd.DataFrame, shape (n_samples, n_seq_info), optional) – DataFrame containing an entry column with a unique protein identifier per row, the labeled training population row-aligned to labels. Required for the built-in predictor (predictor=None); the training feature matrix is built from it via SequenceFeature.get_df_parts().

  • labels (array-like, shape (n_samples,), optional) – Class labels for df_seq (typically 1=positive, 0=negative). Required for the built-in predictor.

  • model (str, estimator, or list, default='rf') – Prediction model for the per-site probability: a name ('rf', 'svm', 'log_reg', 'extra_trees'), a scikit-learn estimator, or a list of those (probabilities averaged). The ShapModel that computes the impact always uses its own defaults (TreeExplainer + RandomForest / ExtraTrees), so the prediction model and the explanation model may differ.

  • predictor (callable, optional) – Escape hatch: a custom (sequence, p1) -> df_feat callable. When given, the built-in predictor is not built and df_seq / labels / model are ignored.

  • output ({'widget', 'html', 'static'}, default='widget') – Which output to produce (see the method summary).

  • path (str, optional) – Output file path. For output='html' writes the self-contained page; for output='static' saves the feature-map panel as an image (PNG/PDF/…, format from the extension). Ignored for output='widget'.

  • col_imp (str, default='feat_impact') – Column the per-site signed impact is written to (and painted from). With shap_plot=True it must be 'feat_impact' or follow 'feat_impact_<name>' (the SHAP feature map’s requirement).

  • col_val (str, default='mean_dif') – Column shown in the feature-map heatmap cells.

  • shap_plot (bool, default=True) – Passed to CPPPlot.feature_map().

  • tmd_len (int, default=20) – TMD length of the predicted window (>=1).

  • init_site (int, optional) – The P1 site to bake for output in {'html', 'static'} and the initial slider site for 'widget' (default near the middle of sequence).

  • sites (list of int, optional) – Only for output='html': a list of P1 positions to bake into one multi-site live HTML. The page gets a client-side JS site slider that switches the pre-computed prediction per site (feature map + structure restyle) with no kernel, keeping the column-residue linking. None (default) bakes only the single init_site. Each site embeds a feature-map image and runs one predictor refit, so a warning is emitted past 40 sites and a hard cap applies at 200.

  • label_target_class (int, default=1) – Class whose probability is predicted and explained.

  • mode ({'impact', 'plddt'}, default='impact') – Initial structure colouring.

  • focus ({'whole', 'fade', 'zoom'}, default='fade') – Structure framing.

  • focus_region (tuple or list of tuples, optional) – Fixed (start, stop) focus window; default from the window’s positions.

  • size_by_impact (bool, default=True) – Scale each impact residue’s stick by |impact| (impact mode only).

  • normalize_by_span (bool, default=False) – Per-residue aggregation for the structure colouring; see map_structure().

  • chain (str, optional) – Chain id to render; default selects the best-matching / first amino-acid chain.

  • random_state (int, optional) – Seed for the prediction estimator and the SHAP estimation (reproducibility).

  • n_jobs (int, optional) – Cores for building the training feature matrix.

  • debounce_ms (int, default=250) – For output='widget', coalesce slider changes within this many milliseconds.

Returns:

view – For output='widget' an ipywidgets panel; for 'html' a LinkedView; for 'static' a CombinedView. All render inline in Jupyter.

Return type:

object

Raises:
  • ValueError – On invalid arguments (e.g. an unknown output, neither or both of pdb / uniprot, predictor=None without df_seq / labels, or an unknown model name).

  • RuntimeError – If a required optional package (py3Dmol, or ipywidgets for the widget) is missing, or an AlphaFold model cannot be fetched.

Notes

  • Per-site cost. The built-in predictor refits a ShapModel per site (the predicted probability is fit once; only the SHAP impact refits). For output='html' with sites=[...] every site additionally embeds a feature-map image, so file size and build time scale linearly with len(sites) — a warning is emitted past 40 sites and a hard cap applies at 200.

  • Static capture. output='static' with path saves the feature-map panel only (CombinedView.savefig); the 3D structure is interactive and has no headless image.

See also

Examples

The integrated explorer: instead of writing the predictor(sequence, p1) callable yourself, pass a feature set df_feat, a labeled training population (df_seq + labels), and a model. explore builds a built-in per-site predictor that, for each P1 site, computes the query window’s feature values for the fixed feature set (no CPP.run rediscovery), predicts its probability, and attaches the per-site SHAP impact (a default ShapModel refit), then renders it. One output= argument selects the form:

  • output='widget' → a live ipywidgets explorer (the P1 slider re-predicts per site).

  • output='html' → a self-contained linked HTML page (write it with path=).

  • output='static' → the structure beside the feature map (a CombinedView).

This is a pro feature (needs biopython + py3Dmol + shap; the widget also needs ipywidgets).

import numpy as np
import pandas as pd
import aaanalysis as aa
import aaanalysis.utils as ut

aa.options["verbose"] = False

df_feat fixes which features are computed per site (the PART-SPLIT-SCALE ids plus the scale-info columns the feature map needs). df_seq + labels are the labeled windows the predictor learns from; the geometry (tmd_len, and the construction jmd_n_len / jmd_c_len) must match how the features were generated. sequence is the query protein the P1 site ranges over.

# A complete CPP-style feature set over real scales / categories
df_scales = aa.load_scales(name="scales")
df_cat = aa.load_scales(name="scales_cat")
df_cat = df_cat[df_cat[ut.COL_SCALE_ID].isin(df_scales.columns)].head(4).reset_index(drop=True)
splits = ["Segment(1,2)", "Segment(2,2)", "Segment(1,1)", "Pattern(C,1)"]
parts = ["TMD", "TMD", "JMD_N", "TMD"]
df_feat = pd.DataFrame({
    ut.COL_FEATURE: [f"{parts[i]}-{splits[i]}-{df_cat[ut.COL_SCALE_ID][i]}" for i in range(4)],
    "category": df_cat[ut.COL_CAT], "subcategory": df_cat[ut.COL_SUBCAT],
    "scale_name": df_cat[ut.COL_SCALE_NAME],
    "abs_auc": [0.2, 0.15, 0.3, 0.1], "abs_mean_dif": [0.3, 0.2, 0.5, 0.4],
    "mean_dif": [0.3, -0.2, 0.5, -0.4], "std_test": 0.1, "std_ref": 0.1})

# A small labeled training population (position-based df_seq: 1-based tmd_start / tmd_stop)
rng = np.random.default_rng(0)
AAs = list("ACDEFGHIKLMNPQRSTVWY")
df_seq = pd.DataFrame([{ut.COL_ENTRY: f"P{i:03d}",
                        ut.COL_SEQ: "".join(rng.choice(AAs, size=40)),
                        ut.COL_TMD_START: 11, ut.COL_TMD_STOP: 20} for i in range(16)])
labels = [1, 0] * 8

# The query protein (human lysozyme C, UniProt P61626) the P1 site slides over
sequence = ("MKALIVLGLVLLSVTVQGKVFERCELARTLKRLGMDGYRGISLANWMCLAKWESGYNTRATNYNAGDRSTDYGIFQINS"
            "RYWCNDGKTPGAVNACHLSCSALLQDNIADAVACAKRVVRDPQGIRAWVAWRNRCQNRDVRQYVQGCGV")
aa.display_df(df_feat, n_rows=10, show_shape=True)
DataFrame shape: (4, 9)
  feature category subcategory scale_name abs_auc abs_mean_dif mean_dif std_test std_ref
1 TMD-Segment(1,2)-LINS030110 ASA/Volume Accessible surface area (ASA) ASA (folded coil/turn) 0.200000 0.300000 0.300000 0.100000 0.100000
2 TMD-Segment(2,2)-LINS030113 ASA/Volume Accessible surface area (ASA) ASA (folded coil/turn) 0.150000 0.200000 -0.200000 0.100000 0.100000
3 JMD_N-Segment(1,1)-JANJ780101 ASA/Volume Accessible surface area (ASA) ASA (folded protein) 0.300000 0.500000 0.500000 0.100000 0.100000
4 TMD-Pattern(C,1)-JANJ780103 ASA/Volume Accessible surface area (ASA) ASA (folded protein) 0.100000 0.400000 -0.400000 0.100000 0.100000

The built-in predictor runs once for the chosen init_site (a P1 site; p1 is the first TMD residue, so the window’s TMD spans [p1, p1 + tmd_len - 1]). model accepts a name ('rf', 'svm', 'log_reg'), a scikit-learn estimator, or a list; the ShapModel that computes the impact always uses its own defaults. mode (impact/plddt), focus (whole/fade/zoom), size_by_impact, and normalize_by_span style the structure.

csp = aa.CPPStructurePlot(jmd_n_len=10, jmd_c_len=10, verbose=False)
view = csp.explore(df_feat=df_feat, sequence=sequence, uniprot="P61626",
                   df_seq=df_seq, labels=labels, model="rf", output="static",
                   tmd_len=10, init_site=25, mode="impact", focus="zoom",
                   size_by_impact=True, random_state=42)
view

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Writes one standalone .html (feature map ↔ structure hover-linked) to path — the paper-figure / sharing artifact. Baked for the single init_site (no live kernel).

view_html = csp.explore(df_feat=df_feat, sequence=sequence, uniprot="P61626",
                        df_seq=df_seq, labels=labels, model="rf", output="html",
                        path="explore_lysozyme.html", tmd_len=10, init_site=25,
                        random_state=42)
view_html

Pass a list of P1 sites to bake them all into one standalone HTML with a client-side site slider: moving it switches the pre-computed prediction per site (feature map + structure restyle) with no kernel, keeping the column↔residue linking. Each site embeds a feature-map image and costs one predictor refit (a warning fires past 40 sites; a hard cap at 200).

live = csp.explore(df_feat=df_feat, sequence=sequence, uniprot="P61626",
                   df_seq=df_seq, labels=labels, model="rf", output="html",
                   sites=[40, 55, 70, 85], path="explore_lysozyme_live.html",
                   tmd_len=10, random_state=42)
live

Drag the site (P1) slider to re-predict and repaint both views on a live kernel; the colour / focus dropdowns restyle the structure, and debounce_ms coalesces rapid moves. init_site sets the initial slider site (default near the middle of sequence).

panel = csp.explore(df_feat=df_feat, sequence=sequence, uniprot="P61626",
                    df_seq=df_seq, labels=labels, model="rf", output="widget",
                    tmd_len=10, init_site=25, mode="impact", focus="fade",
                    debounce_ms=250, random_state=42)
panel
VBox(children=(HBox(children=(IntSlider(value=25, continuous_update=False, description='site (P1)', max=148, m…

Pass your own predictor=(sequence, p1) -> df_feat to bypass the built-in (then df_seq / labels / model are ignored) — for a bespoke windowing or model. The lower-level CPPStructurePlot.interactive, plot_linked, and plot_combined remain available when you already hold a df_feat.

# A custom predictor is any (sequence, p1) -> df_feat callable; here a stand-in for YOUR model.
# With predictor= given, df_seq / labels / model are ignored.
def my_predictor(sequence, p1):
    out = df_feat.copy()
    out['feat_impact'] = np.random.default_rng(p1).normal(size=len(out))  # replace with your model
    return out

csp.explore(df_feat=df_feat, sequence=sequence, uniprot='P61626', predictor=my_predictor,
            output='static', tmd_len=10, init_site=40, label_target_class=1)

3Dmol.js failed to load for some reason. Please check your browser console for error messages.