2D complementarity maps#

Project the TCR-peptide-MHC interface (CDR1-3, peptide, MHC groove helices/floor) onto the canonical groove plane, build the two canonical polars tables (residue markup + contacts), and render a metadata-rich SVG complementarity map.

[1]:
# Environment versions (reproducibility)
import sys, polars as pl, tcren
print('python', sys.version.split()[0], '| polars', pl.__version__, '| tcren', tcren.__version__)
python 3.11.15 | polars 1.41.2 | tcren 0.1.0
[2]:
# Load a native complex, type chains (arda) and annotate the MHC groove
from tcren.structure import parse_structure
from tcren.annotation import classify_chains
from tcren.mhc import annotate_mhc

structure = parse_structure('data/Native2026/1ao7.pdb.gz', pdb_id='1ao7')
classify_chains(structure, organism='human')
annotate_mhc(structure)
[(c.chain_id, c.chain_type) for c in structure.chains]
[2]:
[('A', 'TRA'), ('B', 'TRB'), ('C', 'PEPTIDE'), ('D', 'MHCa'), ('E', 'B2M')]
[3]:
# Project onto the canonical groove plane and build the canonical tables
from tcren.project2d import (project_structure, residue_markup_table,
                             contacts_table, ca_contacts_table, pocket_markers)

projection = project_structure(structure)
markup = residue_markup_table(structure, projection)
contacts = contacts_table(structure, threshold=5.0)
ca_contacts = ca_contacts_table(structure, threshold=8.0)
pockets = pocket_markers(markup)
markup.head()
[3]:
shape: (5, 14)
structure_idstructure_chaincomplex_chaincomplex_regionresidue_indexaa_indexaa_lenaaxyzuvheight
strstrstrstri64i64i64strf64f64f64f64f64f64
"1ao7""A""tra""fr1"10110"K"nullnullnullnullnullnull
"1ao7""A""tra""fr1"21110"E"nullnullnullnullnullnull
"1ao7""A""tra""fr1"32110"V"nullnullnullnullnullnull
"1ao7""A""tra""fr1"43110"E"nullnullnullnullnullnull
"1ao7""A""tra""fr1"54110"Q"nullnullnullnullnullnull
[4]:
# Contacts table is compatible with the original TCRen 5 A calculation
contacts.head()
[4]:
shape: (5, 11)
structure_idstructure_chain_1structure_chain_2residue_index_1residue_index_2aa_index_1aa_index_2min_distcontact_typebackbone_1backbone_2
strstrstri64i64i64i64f64strboolbool
"1ao7""D""E"2351023492.447153"hydrogen_bond"truefalse
"1ao7""A""C"3153042.54217"hydrogen_bond"falsefalse
"1ao7""C""D"117101702.631378"hydrogen_bond"truefalse
"1ao7""A""B"50105491002.63158"hydrogen_bond"falsefalse
"1ao7""A""B"35106341012.647912"hydrogen_bond"falsetrue
[5]:
# Render the SVG complementarity map (squares=residues, bold=Ca-Ca, dashed=inter-residue)
from tcren.viz import render_complementarity_map
from IPython.display import SVG

svg = render_complementarity_map(markup, contacts=contacts, ca_contacts=ca_contacts, pockets=pockets)
SVG(svg)
[5]:
../_images/notebooks_complementarity_map_2d_5_0.svg

Multiple views of the same complex#

The full map above shows the whole interface. Below are focused complementarity-map views (chain subsets — the TCR↔peptide footprint, and the peptide sitting in the MHC groove) followed by three orthogonal structural views of the oriented complex. Contacts in every view are the same closest-atom edges read off the contact table.

[6]:
# Different complementarity-map VIEWS via chain subsets (edges = contacts read off the map).
from IPython.display import display
map_views = {'TCR (CDR1-3) ↔ peptide': ['tra', 'trb', 'peptide'],
             'peptide in the MHC groove': ['peptide', 'mhca', 'mhcb']}
for title, chains in map_views.items():
    print(title)
    display(SVG(render_complementarity_map(
        markup, contacts=contacts, ca_contacts=ca_contacts, pockets=pockets, show_chains=chains)))
TCR (CDR1-3) ↔ peptide
../_images/notebooks_complementarity_map_2d_7_1.svg
peptide in the MHC groove
../_images/notebooks_complementarity_map_2d_7_3.svg
[7]:
# Different STRUCTURAL views: the oriented interface in 3 orthogonal planes.
# u = along the groove (peptide N->C), v = across the groove, height = MHC->TCR normal.
# The canonical frame puts the TCR on top (+height) of the peptide/MHC.
import matplotlib.pyplot as plt
m = markup.filter(pl.col('u').is_not_null())
chain_col = {'mhca': '#999999', 'mhcb': '#777777', 'peptide': '#E69F00',
             'tra': '#0072B2', 'trb': '#D55E00'}
planes = [('u', 'v', 'top — groove plane'),
          ('u', 'height', 'side — along groove'),
          ('v', 'height', 'side — across groove')]
fig, axes = plt.subplots(1, 3, figsize=(13, 3.8))
for ax, (a1, a2, ttl) in zip(axes, planes):
    for ch, col in chain_col.items():
        sub = m.filter(pl.col('complex_chain') == ch)
        if sub.height:
            ax.scatter(sub[a1], sub[a2], s=16, c=col, label=ch, edgecolor='none')
    ax.set_xlabel(a1); ax.set_ylabel(a2); ax.set_title(ttl); ax.set_aspect('equal', 'datalim')
axes[0].legend(fontsize=7, ncol=2, loc='best')
fig.suptitle('1ao7 — oriented interface, three views'); plt.tight_layout(); plt.show()
../_images/notebooks_complementarity_map_2d_8_0.png
[8]:
# Polars summarize: contact-type breakdown of the TCR (CDR) -> peptide interface
tcr_pep = (contacts
    .join(markup.select('structure_chain', 'aa_index', 'complex_chain', 'complex_region'),
          left_on=['structure_chain_1', 'aa_index_1'],
          right_on=['structure_chain', 'aa_index'])
    .filter(pl.col('complex_chain').is_in(['tra', 'trb'])
            & pl.col('structure_chain_2').is_in([c.chain_id for c in structure.chains if c.chain_type=='PEPTIDE'])))
tcr_pep.group_by('complex_region', 'contact_type').agg(
    pl.len().alias('n'), pl.col('min_dist').min().round(2).alias('closest')
).sort('complex_region', 'n', descending=[False, True])
[8]:
shape: (6, 4)
complex_regioncontact_typenclosest
strstru32f64
"cdr1""hydrogen_bond"42.54
"cdr1""polar"33.66
"cdr1""hydrophobic"14.93
"cdr3""polar"133.32
"cdr3""hydrophobic"43.66
"cdr3""hydrogen_bond"42.89