{ "cells": [ { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "# Visualize antibody mix\n", "We will visualize a hypothetical polyclonal antibody mix same way we'd like to visualize the antibody mixes we deconvolve from deep mutational scanning experiments.\n", "\n", "The hypothetical mix represents antibodies targeting three major neutralizing \"epitopes\" on the SARS-CoV-2 receptor-binding domain (RBD) using the classification scheme of [Barnes et al (2020)](https://www.nature.com/articles/s41586-020-2852-1).\n", "In particular, [Barnes et al (2020)](https://www.nature.com/articles/s41586-020-2852-1) divided anti-RBD antibodies that bind to the receptor-binding motif into three classes (see also [Greaney et al (2021)](https://www.nature.com/articles/s41467-021-24435-8)).\n", "For each class, we will use prior deep mutational scanning on a single well-studied monoclonal of that class to antibody to make plausible choices for how mutations affect that antibody class (of course, in reality as there are many somewhat distinct antibodies in each class).\n", "The antibodies used to represent each class are:\n", "\n", " - *LY-CoV016*: class 1, mutation estimates from [Starr et al (2021), Science](https://science.sciencemag.org/content/371/6531/850)\n", " \n", " - *LY-CoV555*: class 2, mutation estimates from [Starr et al (2021), Cell Reports Medicine](https://doi.org/10.1016/j.xcrm.2021.100255)\n", " \n", " - *REGN10987*: class 3, mutation estimates from [Starr et al (2021), Science](https://science.sciencemag.org/content/371/6531/850)\n", " \n", "Read in the mutation-level escape values $\\beta_{m,e}$ for each mutation against each antibody class for this simulated hypothetical mix:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:07.868012Z", "iopub.status.busy": "2024-01-30T00:27:07.867409Z", "iopub.status.idle": "2024-01-30T00:27:08.693362Z", "shell.execute_reply": "2024-01-30T00:27:08.692655Z", "shell.execute_reply.started": "2024-01-30T00:27:07.867975Z" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
epitopemutationescape
0class 1N331A0.000
1class 1N331D0.000
2class 1N331E0.000
3class 1N331F0.000
4class 1N331G1.701
............
5791class 3T531R0.000
5792class 3T531S0.000
5793class 3T531V0.000
5794class 3T531W0.000
5795class 3T531Y0.000
\n", "

5796 rows × 3 columns

\n", "
" ], "text/plain": [ " epitope mutation escape\n", "0 class 1 N331A 0.000\n", "1 class 1 N331D 0.000\n", "2 class 1 N331E 0.000\n", "3 class 1 N331F 0.000\n", "4 class 1 N331G 1.701\n", "... ... ... ...\n", "5791 class 3 T531R 0.000\n", "5792 class 3 T531S 0.000\n", "5793 class 3 T531V 0.000\n", "5794 class 3 T531W 0.000\n", "5795 class 3 T531Y 0.000\n", "\n", "[5796 rows x 3 columns]" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "\n", "mut_escape_df = pd.read_csv(\"RBD_mut_escape_df.csv\")\n", "\n", "mut_escape_df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the data frame only includes 1932 of the $201 \\times 19 = 3819$ possible amino-acid mutations to the RBD; this is because only about half of the mutations are functionally tolerated.\n", "\n", "We also choose simulated activities $a_{\\rm{wt},e}$ for each epitope $e$.\n", "We will let the activity of the polyclonal antibody mix be highest against the class 2 epitope, then next highest against the class 3 epitope, and lowest against the class 1 epitope ([experiments suggest](https://www.nature.com/articles/s41467-021-24435-8) this roughly corresponds to reality for SARS-CoV-2 polyclonal sera):" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:08.701546Z", "iopub.status.busy": "2024-01-30T00:27:08.701137Z", "iopub.status.idle": "2024-01-30T00:27:08.712414Z", "shell.execute_reply": "2024-01-30T00:27:08.711588Z", "shell.execute_reply.started": "2024-01-30T00:27:08.701513Z" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
epitopeactivity
0class 12.2
1class 23.2
2class 32.4
\n", "
" ], "text/plain": [ " epitope activity\n", "0 class 1 2.2\n", "1 class 2 3.2\n", "2 class 3 2.4" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "activity_wt_df = pd.read_csv(\"RBD_activity_wt_df.csv\")\n", "\n", "activity_wt_df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we will visualize the data using `Polyclonal` class provided by this package to model polyclonal antibody mixes:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:08.716195Z", "iopub.status.busy": "2024-01-30T00:27:08.715796Z", "iopub.status.idle": "2024-01-30T00:27:13.300876Z", "shell.execute_reply": "2024-01-30T00:27:13.300109Z", "shell.execute_reply.started": "2024-01-30T00:27:08.716169Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epitopes: ('class 1', 'class 2', 'class 3')\n", "Number of mutations: 1932\n", "Number of sites: 173\n" ] } ], "source": [ "import polyclonal\n", "\n", "poly_abs = polyclonal.Polyclonal(\n", " activity_wt_df=activity_wt_df, mut_escape_df=mut_escape_df\n", ")\n", "\n", "print(f\"Epitopes: {poly_abs.epitopes}\")\n", "print(f\"Number of mutations: {len(poly_abs.mutations)}\")\n", "print(f\"Number of sites: {len(poly_abs.sites)}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can access the activity values, the mutation escape values, site-level summaries of the mutation escape values.\n", "Note that by default, the Hill curve coefficients initialize to one and the non-neutralized fractions to zero:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:13.304988Z", "iopub.status.busy": "2024-01-30T00:27:13.304772Z", "iopub.status.idle": "2024-01-30T00:27:13.323531Z", "shell.execute_reply": "2024-01-30T00:27:13.322917Z", "shell.execute_reply.started": "2024-01-30T00:27:13.304966Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
epitopeactivityhill_coefficientnon_neutralized_frac
0class 12.21.00.0
1class 23.21.00.0
2class 32.41.00.0
\n", "
" ], "text/plain": [ " epitope activity hill_coefficient non_neutralized_frac\n", "0 class 1 2.2 1.0 0.0\n", "1 class 2 3.2 1.0 0.0\n", "2 class 3 2.4 1.0 0.0" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "poly_abs.curve_specs_df" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:13.329695Z", "iopub.status.busy": "2024-01-30T00:27:13.329065Z", "iopub.status.idle": "2024-01-30T00:27:13.384538Z", "shell.execute_reply": "2024-01-30T00:27:13.383868Z", "shell.execute_reply.started": "2024-01-30T00:27:13.329645Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
epitopesitewildtypemutantmutationescape
0class 1331NAN331A0.000
1class 1331NDN331D0.000
2class 1331NEN331E0.000
3class 1331NFN331F0.000
4class 1331NGN331G1.701
.....................
5791class 3531TRT531R0.000
5792class 3531TST531S0.000
5793class 3531TVT531V0.000
5794class 3531TWT531W0.000
5795class 3531TYT531Y0.000
\n", "

5796 rows × 6 columns

\n", "
" ], "text/plain": [ " epitope site wildtype mutant mutation escape\n", "0 class 1 331 N A N331A 0.000\n", "1 class 1 331 N D N331D 0.000\n", "2 class 1 331 N E N331E 0.000\n", "3 class 1 331 N F N331F 0.000\n", "4 class 1 331 N G N331G 1.701\n", "... ... ... ... ... ... ...\n", "5791 class 3 531 T R T531R 0.000\n", "5792 class 3 531 T S T531S 0.000\n", "5793 class 3 531 T V T531V 0.000\n", "5794 class 3 531 T W T531W 0.000\n", "5795 class 3 531 T Y T531Y 0.000\n", "\n", "[5796 rows x 6 columns]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "poly_abs.mut_escape_df" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:13.388886Z", "iopub.status.busy": "2024-01-30T00:27:13.388513Z", "iopub.status.idle": "2024-01-30T00:27:13.465313Z", "shell.execute_reply": "2024-01-30T00:27:13.464707Z", "shell.execute_reply.started": "2024-01-30T00:27:13.388860Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
epitopesitewildtypemeantotal positivemaxmintotal negativen mutations
0class 1331N0.2700624.3212.6200.00.016
1class 1332I0.78557914.9263.2970.00.019
2class 1333T0.3456676.2222.6030.00.018
3class 1334N0.4887788.7981.8080.00.018
4class 1335L0.2375264.5131.5980.00.019
..............................
514class 3527P0.0000000.0000.0000.00.017
515class 3528K0.0000000.0000.0000.00.018
516class 3529K0.0000000.0000.0000.00.018
517class 3530S0.0000000.0000.0000.00.019
518class 3531T0.0000000.0000.0000.00.019
\n", "

519 rows × 9 columns

\n", "
" ], "text/plain": [ " epitope site wildtype mean total positive max min \\\n", "0 class 1 331 N 0.270062 4.321 2.620 0.0 \n", "1 class 1 332 I 0.785579 14.926 3.297 0.0 \n", "2 class 1 333 T 0.345667 6.222 2.603 0.0 \n", "3 class 1 334 N 0.488778 8.798 1.808 0.0 \n", "4 class 1 335 L 0.237526 4.513 1.598 0.0 \n", ".. ... ... ... ... ... ... ... \n", "514 class 3 527 P 0.000000 0.000 0.000 0.0 \n", "515 class 3 528 K 0.000000 0.000 0.000 0.0 \n", "516 class 3 529 K 0.000000 0.000 0.000 0.0 \n", "517 class 3 530 S 0.000000 0.000 0.000 0.0 \n", "518 class 3 531 T 0.000000 0.000 0.000 0.0 \n", "\n", " total negative n mutations \n", "0 0.0 16 \n", "1 0.0 19 \n", "2 0.0 18 \n", "3 0.0 18 \n", "4 0.0 19 \n", ".. ... ... \n", "514 0.0 17 \n", "515 0.0 18 \n", "516 0.0 18 \n", "517 0.0 19 \n", "518 0.0 19 \n", "\n", "[519 rows x 9 columns]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "poly_abs.mut_escape_site_summary_df()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also view the change in IC90s induced by each mutation:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:13.471834Z", "iopub.status.busy": "2024-01-30T00:27:13.471109Z", "iopub.status.idle": "2024-01-30T00:27:15.245052Z", "shell.execute_reply": "2024-01-30T00:27:15.244472Z", "shell.execute_reply.started": "2024-01-30T00:27:13.471786Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sitewildtypemutantIC90log2_fold_change_IC90
0331NA0.0821190.000000
1331ND0.0821190.000000
2331NE0.0821190.000000
3331NF0.0821190.000000
4331NG0.1126300.455812
..................
2100531TS0.1093090.412627
2101531TT0.0821190.000000
2102531TV0.0821190.000000
2103531TW0.1151730.488016
2104531TY0.0821190.000000
\n", "

2105 rows × 5 columns

\n", "
" ], "text/plain": [ " site wildtype mutant IC90 log2_fold_change_IC90\n", "0 331 N A 0.082119 0.000000\n", "1 331 N D 0.082119 0.000000\n", "2 331 N E 0.082119 0.000000\n", "3 331 N F 0.082119 0.000000\n", "4 331 N G 0.112630 0.455812\n", "... ... ... ... ... ...\n", "2100 531 T S 0.109309 0.412627\n", "2101 531 T T 0.082119 0.000000\n", "2102 531 T V 0.082119 0.000000\n", "2103 531 T W 0.115173 0.488016\n", "2104 531 T Y 0.082119 0.000000\n", "\n", "[2105 rows x 5 columns]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ic90s = poly_abs.mut_icXX_df(\n", " x=0.9,\n", " icXX_col=\"IC90\",\n", " log_fold_change_icXX_col=\"log2_fold_change_IC90\",\n", ")\n", "\n", "ic90s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The fold change in IC90 is correlated with the mutation escape, with the strongest correlation being with the clss 2 epitope (which is the one with highest activity):" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:15.248182Z", "iopub.status.busy": "2024-01-30T00:27:15.247998Z", "iopub.status.idle": "2024-01-30T00:27:15.306231Z", "shell.execute_reply": "2024-01-30T00:27:15.305588Z", "shell.execute_reply.started": "2024-01-30T00:27:15.248163Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
escapelog2_fold_change_IC90
epitope
class 1escape1.000.40
log2_fold_change_IC900.401.00
class 2escape1.000.69
log2_fold_change_IC900.691.00
class 3escape1.000.32
log2_fold_change_IC900.321.00
\n", "
" ], "text/plain": [ " escape log2_fold_change_IC90\n", "epitope \n", "class 1 escape 1.00 0.40\n", " log2_fold_change_IC90 0.40 1.00\n", "class 2 escape 1.00 0.69\n", " log2_fold_change_IC90 0.69 1.00\n", "class 3 escape 1.00 0.32\n", " log2_fold_change_IC90 0.32 1.00" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(\n", " poly_abs.mut_escape_df.merge(ic90s)\n", " .groupby(\"epitope\")[[\"escape\", \"log2_fold_change_IC90\"]]\n", " .corr()\n", " .round(2)\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also **plot** the relevant values characterizing the polyclonal mix.\n", "\n", "Here are the neutralization curves against wildtype for each epitope (these depend on the activity, Hill coefficient, and non-neutralized fraction):" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:15.307689Z", "iopub.status.busy": "2024-01-30T00:27:15.307382Z", "iopub.status.idle": "2024-01-30T00:27:15.552698Z", "shell.execute_reply": "2024-01-30T00:27:15.551946Z", "shell.execute_reply.started": "2024-01-30T00:27:15.307669Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "
\n", "" ], "text/plain": [ "alt.Chart(...)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# NBVAL_IGNORE_OUTPUT\n", "\n", "poly_abs.curves_plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also plot is the mutation escape $\\beta_{m,e}$ for each epitope at each site in a heatmap.\n", "We also include lineplots of the mutation escape at each site summarized by a single number (e.g., as sum of the positive $\\beta_{m,e}$ values for that site).\n", "Note that there is a zoom bar at the top of the plot, and options at the bottom of the plot, including whether or not to floor escape values at zero, which site summary statistic to show, and to select sites with high escape values.\n", "You can also mouse over points for details:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:15.554286Z", "iopub.status.busy": "2024-01-30T00:27:15.553962Z", "iopub.status.idle": "2024-01-30T00:27:19.827384Z", "shell.execute_reply": "2024-01-30T00:27:19.826643Z", "shell.execute_reply.started": "2024-01-30T00:27:15.554264Z" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "
\n", "" ], "text/plain": [ "alt.VConcatChart(...)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# NBVAL_IGNORE_OUTPUT\n", "\n", "poly_abs.mut_escape_plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Additionally, we can just plot how each mutation affects the IC90 (log2 fold change IC90):" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:19.829053Z", "iopub.status.busy": "2024-01-30T00:27:19.828666Z", "iopub.status.idle": "2024-01-30T00:27:23.997242Z", "shell.execute_reply": "2024-01-30T00:27:23.996347Z", "shell.execute_reply.started": "2024-01-30T00:27:19.829030Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "
\n", "" ], "text/plain": [ "alt.VConcatChart(...)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# NBVAL_IGNORE_OUTPUT\n", "\n", "poly_abs.mut_icXX_plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also project the site-level summary metrics of the mutation escape onto the protein structure.\n", "Here we do this using [PDB 6m0j](https://www.rcsb.org/structure/6M0J), which holds the SARS-CoV-2 RBD (chain `E`) in complex with ACE2 (chain `A`).\n", "Specific, the `Polyclonal` object has a method to make versions of the PDB in which the B-factor is re-assigned to one of the site-level summary metrics of escape (such as *mean* or *total positive*):" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:23.999385Z", "iopub.status.busy": "2024-01-30T00:27:23.998926Z", "iopub.status.idle": "2024-01-30T00:27:24.960839Z", "shell.execute_reply": "2024-01-30T00:27:24.960114Z", "shell.execute_reply.started": "2024-01-30T00:27:23.999359Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
epitopePDB file
0class 1RBD_mean_class_1.pdb
1class 2RBD_mean_class_2.pdb
2class 3RBD_mean_class_3.pdb
\n", "
" ], "text/plain": [ " epitope PDB file\n", "0 class 1 RBD_mean_class_1.pdb\n", "1 class 2 RBD_mean_class_2.pdb\n", "2 class 3 RBD_mean_class_3.pdb" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "poly_abs.mut_escape_pdb_b_factor(\n", " input_pdbfile=\"6M0J.pdb\",\n", " chains=\"E\",\n", " metric=\"mean\",\n", " outfile=\"RBD_{metric}_{epitope}.pdb\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These PDB files can then be colored in `pymol` by the escape metric.\n", "If you want the colors to match the same ones used above by the plotting from the `Polyclonal` object, get the colors and convert them to the RGB tuples used by `pymol`:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "execution": { "iopub.execute_input": "2024-01-30T00:27:24.962493Z", "iopub.status.busy": "2024-01-30T00:27:24.962168Z", "iopub.status.idle": "2024-01-30T00:27:24.969123Z", "shell.execute_reply": "2024-01-30T00:27:24.968205Z", "shell.execute_reply.started": "2024-01-30T00:27:24.962463Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "class 1: hex color is #0072B2; RGB tuple is [0.0, 0.447, 0.698]\n", "class 2: hex color is #CC79A7; RGB tuple is [0.8, 0.475, 0.655]\n", "class 3: hex color is #009E73; RGB tuple is [0.0, 0.62, 0.451]\n" ] } ], "source": [ "import matplotlib.colors\n", "\n", "for epitope, hex_color in poly_abs.epitope_colors.items():\n", " rgb = [round(val, 3) for val in matplotlib.colors.to_rgb(hex_color)]\n", " print(f\"{epitope}: hex color is {hex_color}; RGB tuple is {rgb}\")" ] }, { "cell_type": "markdown", "metadata": { "execution": { "iopub.execute_input": "2021-03-14T20:44:30.039666Z", "iopub.status.busy": "2021-03-14T20:44:30.039028Z", "iopub.status.idle": "2021-03-14T20:44:30.045508Z", "shell.execute_reply": "2021-03-14T20:44:30.044631Z", "shell.execute_reply.started": "2021-03-14T20:44:30.039616Z" } }, "source": [ "Then using these colors, we can use the `pymol spectrum` command to re-color by B-factor.\n", "Here is a Python script that can be run within `pymol` (via `run