{
"cells": [
{
"cell_type": "markdown",
"id": "03812395",
"metadata": {},
"source": [
"# Experimental data\n",
"\n",
"In contrast to theoretical or computational landscapes, like the Serine codon model shown in previous sections, empirical landscapes are based on experimental data. Such data is typically noisy and incomplete, so we need to apply additional methods to obtain reliable estimates of the phenotype of every possible genotype in order to visualize the genotype-phenotype map. In this section, we will illustrate the two methods available in `gpmap-tools` for inference of complete genotype-phenotype maps $f$ from noisy measurements `y` at a subset of sequences `X`. Optionally, the variance associated to the measurement `y_var` can be provided.\n",
"\n",
"> **Note:** these methods only work for sequences of the same length\n",
"\n",
"- **Minimum epistasis interpolation (MEI)** finds the genotype-phenotype map that minimizes the sum of squared P-th epistatic coefficients $\\bar{\\epsilon_P^2}$ while exactly matching the data `y` at sequences `X` ([read more](https://www.nature.com/articles/s41467-020-15512-5)).\n",
"- **Empirical VC regression** estimates a prior distribution characterized by the variance explained by interactions of every possible order from the empirical distance-correlation function computed from the available data. Then, it uses this prior distribution to perform Gaussian process regression to infer a complete genotype-phenotype map ([read more](https://doi.org/10.1073/pnas.2204233119)).\n",
"\n",
"In this section, we will illustrate how to use these methods using simulated and real data and how to use them to evaluate the evidence supporting specific hypotheses about the genotype-phenotype map."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f34627a2",
"metadata": {},
"outputs": [],
"source": [
"# Import required libraries\n",
"import pandas as pd\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"from itertools import product, combinations\n",
"from scipy.stats import pearsonr, norm\n",
"from gpmap.datasets import DataSet\n",
"from gpmap.inference import VCregression, MinimumEpistasisInterpolator\n",
"from gpmap.plot.mpl import init_fig"
]
},
{
"cell_type": "markdown",
"id": "48dc85f2",
"metadata": {},
"source": [
"## Inference from simulated data\n",
"\n",
"We first illustrate how to use these methods using simulated data. In this case, we know what the true genotype-phenotype map is and can compare the model inferences with the real values. \n",
"\n",
"### How to sample functions from the prior distribution\n",
"\n",
"We will simulate data from the Variance Component regression model. In order to do so, we need to define the configuration of sequence space, the variance associated to interactions of every possible order `lambdas`, standard deviation of the measurement noise `sigma` and the fraction of genotypes that are not measured in the experiment `p_missing`."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "838329b0",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
y
\n",
"
y_var
\n",
"
f
\n",
"
\n",
" \n",
" \n",
"
\n",
"
AAAAAA
\n",
"
0.640632
\n",
"
0.04
\n",
"
0.496707
\n",
"
\n",
"
\n",
"
AAAAAC
\n",
"
-2.314924
\n",
"
0.04
\n",
"
-2.381059
\n",
"
\n",
"
\n",
"
AAAAAG
\n",
"
-2.150190
\n",
"
0.04
\n",
"
-2.072592
\n",
"
\n",
"
\n",
"
AAAAAT
\n",
"
1.466791
\n",
"
0.04
\n",
"
1.143917
\n",
"
\n",
"
\n",
"
AAAACA
\n",
"
3.854757
\n",
"
0.04
\n",
"
4.207335
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
TTTTGG
\n",
"
0.791477
\n",
"
0.04
\n",
"
0.805718
\n",
"
\n",
"
\n",
"
TTTTGT
\n",
"
1.621376
\n",
"
0.04
\n",
"
1.522178
\n",
"
\n",
"
\n",
"
TTTTTA
\n",
"
3.755850
\n",
"
0.04
\n",
"
3.650933
\n",
"
\n",
"
\n",
"
TTTTTC
\n",
"
1.187770
\n",
"
0.04
\n",
"
1.162799
\n",
"
\n",
"
\n",
"
TTTTTG
\n",
"
3.084332
\n",
"
0.04
\n",
"
2.627240
\n",
"
\n",
" \n",
"
\n",
"
3693 rows × 3 columns
\n",
"
"
],
"text/plain": [
" y y_var f\n",
"AAAAAA 0.640632 0.04 0.496707\n",
"AAAAAC -2.314924 0.04 -2.381059\n",
"AAAAAG -2.150190 0.04 -2.072592\n",
"AAAAAT 1.466791 0.04 1.143917\n",
"AAAACA 3.854757 0.04 4.207335\n",
"... ... ... ...\n",
"TTTTGG 0.791477 0.04 0.805718\n",
"TTTTGT 1.621376 0.04 1.522178\n",
"TTTTTA 3.755850 0.04 3.650933\n",
"TTTTTC 1.187770 0.04 1.162799\n",
"TTTTTG 3.084332 0.04 2.627240\n",
"\n",
"[3693 rows x 3 columns]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.random.seed(0)\n",
"lambdas_true = np.array([1e4, 1e3, 2e2, 1e0, 1e-1, 3e-3, 1e-5])\n",
"\n",
"model = VCregression(seq_length=6, alphabet_type='dna', lambdas=lambdas_true)\n",
"f, X, y, y_var = model.simulate(y_var=0.04, p_missing=0.1)\n",
"idx = model.get_obs_idx(X)\n",
"X_test = np.delete(model.genotypes, idx)\n",
"f_test = np.delete(f, idx)\n",
"data = pd.DataFrame({'y': y, 'y_var': y_var, 'f': f[idx]}, index=X)\n",
"data"
]
},
{
"cell_type": "markdown",
"id": "4090bcb3",
"metadata": {},
"source": [
"### How to compute the minimum epistasis interpolation solution\n",
"\n",
"This can be done very simply by defining a `MinimumEpistasisInterpolator` object with the right configuration of sequence space and the order of local epistatic coefficients we aim to penalize. In this case, we set `P=2` to minimize the sum of squared epistatic coefficients."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "dc8c2ad2",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"r2 = pearsonr(mei['f'], f)[0] ** 2\n",
"fig, axes = plt.subplots(1, 1, figsize=(4, 4))\n",
"axes.scatter(x=mei['f'], y=f, c='black', alpha=0.5, s=5, lw=0)\n",
"ticks = np.arange(-10, 9, 2)\n",
"axes.axline((0, 0), (1, 1), lw=0.75, linestyle='--', c='grey')\n",
"axes.set(xlabel=r'$y_{True}$', ylabel=r'$y_{pred}$', aspect='equal', xlim=(-15, 10), ylim=(-15, 10))\n",
"axes.text(0.03, 0.97, r'$R^2$=' + '{:.3f}'.format(r2), transform=axes.transAxes,\n",
" va='top')"
]
},
{
"cell_type": "markdown",
"id": "ce611af4",
"metadata": {},
"source": [
"This comparison shows a very high correlation between the predictions and the real phenotypic values, but the extremely low and high values tend to be over and underestimated, respectively. \n",
"\n",
"### How to estimate Variance Components $\\lambda$'s\n",
"\n",
"We next illustrate how to use Variance Component regression on the same simulated data for comparison. The first step is the estimation of the variance components from the data. The covariance matrix $K$ under the prior is given by\n",
"\n",
"$$K = \\sum_k \\lambda_k K_k$$\n",
"\n",
"We define the $\\lambda_k$ through kernel alignment. This is achieved by finding the non-negative linear combination of the covariance matrices $K_k$ associated to each pure interactions of order $k$ that that minimize the Frobenius norm of the difference with the empirical second moment matrix $(y - \\bar y)^T(y - \\bar y)$ \n",
"\n",
"$$\\hat\\lambda = \\arg \\min_{\\lambda} \\lVert (y - \\bar y)(y - \\bar y)^T - (\\sum_k \\lambda_k K_k)_{xx} \\lVert_F^2$$\n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "5ccde983",
"metadata": {},
"outputs": [],
"source": [
"model = VCregression(seq_length=6, alphabet_type=\"dna\")\n",
"model.fit(X, y, y_var)\n",
"vc = model.lambdas_to_variance(model.lambdas)\n",
"vc_p = vc / vc.sum() * 100"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "c6131627",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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3nzzTcXFxRkbEADQbrfccotuueUW5+P6+nodO3ZMR48e1UcffURRCugm7Ha78vLyFBkZqZ49exodB26AWcQAAG7t3//939XY2KgTJ06osrJSlZWVOnHihOx2u/793//d6HgAgE4QGBioESNG6J577tHTTz9tdBwAHaChoUF5eXmKi4ujIAUnilIuMJvNSkpK0siRI42OAgBeZ+fOnXrhhRd0+eWXO/ddfvnleu6557Rr165LPu9jjz0mk8mkxYsXO/fV19crPT1d4eHh6t27t6ZPn67S0tL2xAcAuMhms+l//ud/tGnTJj388MOaOnWq0ZEAdBCLxaKSkhIlJCTIz48btvB/+DS4ID09Xenp6aqpqVFoaKjRcQDAq8THx6uxsbHFfpvNppiYmEs654EDB/SHP/xBw4YNa7Z/yZIl2rp1q9566y2FhoZqwYIFmjZtmvbs2XNJrwMAOL+vv/5an332mY4dO+bcvvrqKzU2Nsrf319XXnmlhg4danRMAB3gzJkzqq+vV3x8PCvsoQWKUgAAt/bEE09o4cKFMpvNGjFihKRvJz1ftGiRnnzyyYs+X21trWbNmqV169Zp5cqVzv3V1dV6+eWXtXHjRt1www2SpFdeeUVXXnml9u3bp2uuuaZjGgQAXu7uu+/WG2+8IZPJpKCgIFksFt18881atmyZhg4dqsGDB8vX19fomAA6QGlpqfz8/BQdHW10FLgpbt8DALi1n/70p8rJydHo0aMVEBCggIAAjR49WocOHdI999yjvn37OjdXpKen6+abb1ZaWlqz/dnZ2WpsbGy2/4orrlBCQoL27t3boW0CAG+2efNmPfvss6qtrVVRUZEWLFigv/3tbzpw4IASExMpSAHdgMPhUH5+voKCghQeHm50HLgxRkoBANzamjVrOuxcb775pg4dOqQDBw60eK6kpET+/v7OFf7OiYyMVElJSavntFqtslqtzsc1NTUdlhcAuqMlS5Zo9uzZCgwMlCQ988wzmj17tn7+859r8+bNev755/WjH/3I4JQALpXNZlN+fr6io6MVEBBgdBy4OYpSAAC3NmfOnA45T35+vhYtWqS///3vzn8IdYTMzEytWLGiw84HAN1dZmZmi32pqanav3+/nn32Wc2cOVM333yznnnmGfXv39+AhAAuldVqVXFxseLj4xn1CJdw+x4AwK1t2LDhvPub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qampBqUCAHQEVt8D2maz2bRo0SJnQapHjx6KjY1VQUGBmpqaZDKZtHjxYt16663MJwWP1GFzSgEA0BlWrlypl156Sddff71WrFihFStW6Prrr9f69eu1atWqizrXCy+8oGHDhikkJEQhISEaM2aMPvjgA+fz9fX1Sk9PV3h4uHr37q3p06ertLS0o5sEAADgkt27dztv2QsKClJ0dLROnTrlHEXucDiUn5+v3bt3GxkTuGQUpVzAROcAYJxrr71We/fuVXx8vP70pz/pL3/5i773ve/p6NGjGjt27EWdKy4uTo899piys7N18OBB3XDDDbr11lv1P//zP5KkJUuW6C9/+Yveeust7dy5U0VFRQyHB4BOtnv3bt19990aM2aMCgsLJUl//OMf9cknnxicDDBecXGxJCk0NFShoaHKy8s77/yI544DPA2377kgPT1d6enpzom6AABdKyUlRa+//nq7zzN58uRmj3/3u9/phRde0L59+xQXF6eXX35ZGzdu1A033CBJeuWVV3TllVdq3759uuaaa9r9+gCA5t5++2395Cc/0axZs3T48GFZrVZJUnV1tVatWqX333/f4ISAsaKjoxURESG73d5m4Sk6OroLUwEdh6IUAMDt2e12nTx5UmVlZbLb7c2eu/766y/pnDabTW+99ZYsFovGjBmj7OxsNTY2Ki0tzXnMFVdcoYSEBO3du7fVopTVanX+I0r6dqURAIBrVq5cqbVr12r27Nl68803nfuvvfZarVy50sBkgPEcDocGDRqksLAwffXVV+c9xmQyKS4u7qJHjwPugqIUAMCt7du3T3fddZdOnTrVYri6yWSSzWa7qPN99tlnGjNmjOrr69W7d29t2bJFSUlJysnJkb+/v8LCwpodHxkZqZKSklbPl5mZqRUrVlxUBgDAt7744ovzfrkQGhqqqqqqrg8EuAmbzab8/HxFRUUpMzNTM2bMkMlkava30LkVKtesWcMk5/BYzCkFAHBrP//5zzVixAgdO3ZMlZWVOnPmjHOrrKy86PNdfvnlysnJ0aeffqr58+drzpw5On78+CXnW7p0qaqrq51bfn7+JZ8LALxNVFSUTp482WL/J598okGDBhmQCDBeQ0OD8vPzFRcXp8DAQE2bNk2bN29WbGxss+Pi4uK0efNm5r+ER2OkFADArX311VfavHmzvve973XI+fz9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",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"k = np.arange(model.lambdas.shape[0])\n",
"\n",
"fig, subplots = plt.subplots(1, 3, figsize=(12, 3.5))\n",
"\n",
"axes = subplots[0]\n",
"axes.bar(x=k, height=model.lambdas, color='black')\n",
"axes.set(xlabel='k', ylabel=r'$\\lambda_k$', yscale='log',\n",
" xticks=np.arange(7))\n",
"\n",
"axes = subplots[1]\n",
"axes.bar(x=k[1:], height=vc_p, color='black')\n",
"axes.set(xlabel='k', ylabel='% variance explained')\n",
"\n",
"axes = subplots[2]\n",
"axes.scatter(lambdas_true, model.lambdas, c='black')\n",
"lims = (1e-5, 1e6)\n",
"axes.plot(lims, lims, c='grey', lw=0.3, alpha=0.5)\n",
"axes.set(xscale='log', yscale='log',\n",
" xlabel=r'True $\\lambda_k$',\n",
" ylabel=r'Inferred $\\lambda_k$',\n",
" xlim=lims, ylim=lims)\n",
"\n",
"fig.tight_layout()"
]
},
{
"cell_type": "markdown",
"id": "cff9aee0",
"metadata": {},
"source": [
"We can see that the inferred variance components are very similar in log scale to the true data-generating parameters. \n",
"\n",
"However, when data is sparse, kernel alignment is a hard problem and we need to regularize towards simpler solutions. While we could shrink towards additivity, another good general choice that still models high order interactions is towards exponential decay of the variance components. We can do it by setting `cross_validation=True` and penalizing the second order moments of the $\\log \\lambda_k$ as a function of $k$. It will automatically split the data into different folds and perform kernel alignment under different regularization strength to find the penalization constant that best generalizes to the validation set according to a metric. These metrics can be\n",
"the Frobenius of the difference between the prior and second moment matrix, $R^2$ on the or the log-likelihood of the predictions on the validation set. This can be specified through the argument `cv_loss_function='r2'` ,`cv_loss_function='logL'`."
]
},
{
"cell_type": "markdown",
"id": "a9dcb37f",
"metadata": {},
"source": [
"### How to obtain phenotypic predictions under a VC prior\n",
"\n",
"Once we know the parameters of the Variance Component prior, we can compute the posterior distribution for the complete genotype-phenotype map with the method `predict`"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "16df54ca",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"r2 = pearsonr(pred[\"f\"], f)[0] ** 2\n",
"fig, axes = plt.subplots(1, 1, figsize=(4, 4))\n",
"axes.scatter(x=pred[\"f\"], y=f, c=\"black\", alpha=0.5, s=5, lw=0)\n",
"ticks = np.arange(-10, 9, 2)\n",
"axes.axline((0, 0), (1, 1), lw=0.75, linestyle=\"--\", c=\"grey\")\n",
"axes.set(\n",
" xlabel=r\"$y_{True}$\",\n",
" ylabel=r\"$y_{pred}$\",\n",
" aspect=\"equal\",\n",
" xlim=(-15, 10),\n",
" ylim=(-15, 10),\n",
")\n",
"axes.text(\n",
" 0.03,\n",
" 0.97,\n",
" r\"$R^2$=\" + \"{:.3f}\".format(r2),\n",
" transform=axes.transAxes,\n",
" va=\"top\",\n",
")\n"
]
},
{
"cell_type": "markdown",
"id": "78636627",
"metadata": {},
"source": [
"### How to calculate uncertainty of the predictions\n",
"\n",
"In the previous section, we have shown how to compute the posterior mean of the complete genotype-phenotype given the data and the estimated variance components. However, in cases where the ground truth is not known, it can be useful to have an idea about the uncertainty of the phenotypic predictions for new sequences. As we are using Gaussian process models with Gaussian likelihood function, we can compute, not only the posterior mean, but also the posterior variance and 95% probability credible interval for these sequences by setting `calc_variance=True`.\n",
"\n",
"> **Note**: Computing the variance for every possible sequence is usually unfeasible because we need to solve a system of $~\\alpha^\\ell$ equations for computing the variance of each sequence. Thus, in practice, this calculation can only be done for a small subset of sequences of interest.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "1b2ad2fb",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 403/403 [00:16<00:00, 24.33it/s]\n"
]
},
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
f
\n",
"
f_var
\n",
"
f_std
\n",
"
ci_95_lower
\n",
"
ci_95_upper
\n",
"
\n",
" \n",
" \n",
"
\n",
"
AAAACG
\n",
"
-1.661166
\n",
"
0.022802
\n",
"
0.151005
\n",
"
-2.026398
\n",
"
-1.422378
\n",
"
\n",
"
\n",
"
AAAACT
\n",
"
1.739073
\n",
"
0.021753
\n",
"
0.147488
\n",
"
1.361176
\n",
"
1.951128
\n",
"
\n",
"
\n",
"
AAAAGA
\n",
"
1.857192
\n",
"
0.021762
\n",
"
0.147520
\n",
"
1.439720
\n",
"
2.029800
\n",
"
\n",
"
\n",
"
AAACGG
\n",
"
-5.395939
\n",
"
0.020771
\n",
"
0.144121
\n",
"
-5.487868
\n",
"
-4.911382
\n",
"
\n",
"
\n",
"
AAAGAT
\n",
"
1.554774
\n",
"
0.022872
\n",
"
0.151234
\n",
"
1.277205
\n",
"
1.882139
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
TTTGCC
\n",
"
-8.340758
\n",
"
0.021756
\n",
"
0.147500
\n",
"
-8.462849
\n",
"
-7.872850
\n",
"
\n",
"
\n",
"
TTTGCG
\n",
"
-4.501158
\n",
"
0.021703
\n",
"
0.147320
\n",
"
-4.511932
\n",
"
-3.922653
\n",
"
\n",
"
\n",
"
TTTGTA
\n",
"
-3.320864
\n",
"
0.020772
\n",
"
0.144126
\n",
"
-3.539676
\n",
"
-2.963171
\n",
"
\n",
"
\n",
"
TTTTCA
\n",
"
5.393270
\n",
"
0.020795
\n",
"
0.144206
\n",
"
4.917685
\n",
"
5.494508
\n",
"
\n",
"
\n",
"
TTTTTT
\n",
"
4.110144
\n",
"
0.025390
\n",
"
0.159342
\n",
"
3.935240
\n",
"
4.572607
\n",
"
\n",
" \n",
"
\n",
"
403 rows × 5 columns
\n",
"
"
],
"text/plain": [
" f f_var f_std ci_95_lower ci_95_upper\n",
"AAAACG -1.661166 0.022802 0.151005 -2.026398 -1.422378\n",
"AAAACT 1.739073 0.021753 0.147488 1.361176 1.951128\n",
"AAAAGA 1.857192 0.021762 0.147520 1.439720 2.029800\n",
"AAACGG -5.395939 0.020771 0.144121 -5.487868 -4.911382\n",
"AAAGAT 1.554774 0.022872 0.151234 1.277205 1.882139\n",
"... ... ... ... ... ...\n",
"TTTGCC -8.340758 0.021756 0.147500 -8.462849 -7.872850\n",
"TTTGCG -4.501158 0.021703 0.147320 -4.511932 -3.922653\n",
"TTTGTA -3.320864 0.020772 0.144126 -3.539676 -2.963171\n",
"TTTTCA 5.393270 0.020795 0.144206 4.917685 5.494508\n",
"TTTTTT 4.110144 0.025390 0.159342 3.935240 4.572607\n",
"\n",
"[403 rows x 5 columns]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pred = model.predict(X_test, calc_variance=True)\n",
"pred['f'] = f[model.likelihood.idx[X_test]]\n",
"pred"
]
},
{
"cell_type": "markdown",
"id": "7f3de01f",
"metadata": {},
"source": [
"We can now check that predictions are well calibrated, this is, that the true value lies withing the 95% probability predicted interval close to the expected 95% probability; and show the error bars in the scatterplot to visualize if uncertainty is uniformly distributed along the whole range of true phenotypic values."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "f6fdaad7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0.03, 0.97, 'Calibration=92.06%')"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"perc = np.mean((f_test > pred['ci_95_lower']) & (f_test < pred['ci_95_upper'])) * 100\n",
"fig, axes = plt.subplots(1, 1, figsize=(5, 5))\n",
"axes.errorbar(\n",
" x=f_test,\n",
" y=pred[\"f\"],\n",
" yerr=2 * pred[\"f_std\"],\n",
" c=\"black\",\n",
" markersize=3,\n",
" fmt=\"o\",\n",
" alpha=0.2,\n",
")\n",
"axes.axline((0, 0), (1, 1), lw=0.5, c='grey', linestyle='--')\n",
"axes.set(\n",
" xlabel=r\"$y_{True}$\",\n",
" ylabel=r\"$y_{pred}$\",\n",
" aspect=1,\n",
" xlim=(-15, 10),\n",
" ylim=(-15, 10),\n",
")\n",
"axes.text(0.03, 0.97, 'Calibration={:.2f}%'.format(perc), transform=axes.transAxes, va='top')"
]
},
{
"cell_type": "markdown",
"id": "1367584e",
"metadata": {},
"source": [
"### How to estimate mutational effects and epistatic coefficients under the prior\n",
"\n",
"Because the posterior distribution of the sequence function relationship is also a multivariate gaussian, \n",
"\n",
"$$\n",
"f \\sim MvNormal(\\mu, \\Sigma)\n",
"$$\n",
"\n",
"We can easily compute the posterior for any linear combination represented by $B$ of a multivariate normal distribution\n",
"\n",
"$$\n",
"Bf \\sim MvNormal(B\\mu, B\\Sigma B^T)\n",
"$$\n",
"\n",
"Without any prior distribution, we can assume that $\\Sigma=D_{\\sigma^2}$ and $\\mu=y$, and use the following function to compute the posterior distribution for specific linear combinations given by the contrast matrix $B$ \n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "6ffa31e3",
"metadata": {},
"outputs": [],
"source": [
"def make_contrasts(df, contrast_matrix):\n",
" f = df['y']\n",
" Sigma = np.diag(df['y_var'])\n",
" B = contrast_matrix.T.values\n",
" mu = B @ f\n",
" std = np.sqrt(np.diag(B @ Sigma @ B.T))\n",
" posterior = norm(mu, std)\n",
" p = posterior.cdf(0.)\n",
" p = np.max(np.vstack([p, 1-p]), axis=0)\n",
" contrasts = pd.DataFrame({'estimate': mu, 'std': std, \n",
" 'ci_95_lower': mu - 2 * std, \n",
" 'ci_95_upper': mu + 2 * std, \n",
" 'p(|x|>0)': p}, \n",
" index=contrast_matrix.columns)\n",
" return(contrasts)"
]
},
{
"cell_type": "markdown",
"id": "36d4871b",
"metadata": {},
"source": [
"Lets start by estimating mutational effects from`TTTTTT` to `TTTTTC`:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "4cd6a1cb",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"test = pred.loc[X_test, :]\n",
"r2 = pearsonr(test['f'], test['y'])[0] ** 2\n",
"lim = (-9, 3)\n",
"bins = np.linspace(lim[0] + 0.5, lim[1] - 0.5, 100)\n",
"\n",
"fig, subplots = plt.subplots(1, 2, figsize=(8, 4))\n",
"\n",
"axes = subplots[0]\n",
"axes.hist2d(x=test['f'], y=test['y'], cmap='binary', bins=bins)\n",
"axes.axline((0, 0), (1, 1), lw=0.5, linestyle='--', c='grey')\n",
"axes.set(xlabel=r'$y_{pred}$', ylabel=r'$y_{obs}$',\n",
" xlim=(lim[0] + 0.5, lim[1] - 0.5),\n",
" ylim=(lim[0] + 0.5, lim[1] - 0.5))\n",
"axes.text(0.05, 0.95, r'$R^2$=' + '{:.3f}'.format(r2),\n",
" transform=axes.transAxes, color='black', ha='left', va='top')\n",
"\n",
"axes = subplots[1]\n",
"axes.hist(pred.dropna()['f'], label='Observed', alpha=0.3, density=True, bins=bins, color='black')\n",
"axes.hist(pred.loc[np.isnan(pred['y']), 'f'], label='New', alpha=0.3, density=True, bins=bins, color='grey')\n",
"axes.set(xlabel=r'$y_{pred}$', ylabel='% of sequences')\n",
"axes.legend(loc=0)\n",
"\n",
"fig.tight_layout()"
]
},
{
"cell_type": "markdown",
"id": "7010e01d",
"metadata": {},
"source": [
"### Estimating local epistatic coefficients under the prior\n",
"\n",
"As previously shown, we are not only restricted to making calibrated predictions for previously uncharacterized or held out sequences, but we can also get calibrated estimates for linear combinations of them and use them to answer questions about specific mutational effects and how they change as we introduced more mutations.\n",
"\n",
"One of the main interactions in the GB1 dataset is that taking place between positions 41 and 54. In the wild-type sequence VDGV, G41L is highly deleterious, but becomes advantageous in the presence of V54G. Now, we can use our model to compute the posterior distribution for this epistatic coefficient given the whole dataset. \n",
"\n",
"We can select the 4 relevant sequences and show their measurement values"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "9a36fe70",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
y
\n",
"
y_var
\n",
"
\n",
" \n",
" \n",
"
\n",
"
VDGV
\n",
"
0.000000
\n",
"
0.000027
\n",
"
\n",
"
\n",
"
VDGG
\n",
"
0.334153
\n",
"
0.003038
\n",
"
\n",
"
\n",
"
VDLV
\n",
"
-3.512487
\n",
"
0.105615
\n",
"
\n",
"
\n",
"
VDLG
\n",
"
1.140357
\n",
"
0.013197
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" y y_var\n",
"VDGV 0.000000 0.000027\n",
"VDGG 0.334153 0.003038\n",
"VDLV -3.512487 0.105615\n",
"VDLG 1.140357 0.013197"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"seqs = ['VDGV', 'VDGG', 'VDLV', 'VDLG']\n",
"df = data.loc[seqs, :]\n",
"df"
]
},
{
"cell_type": "markdown",
"id": "4b58446b",
"metadata": {},
"source": [
"We then define the contrast matrices for the coefficients of interest: the single point mutational effects as well as the epistatic coefficient between them."
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "7e2f77c2",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 3/3 [01:08<00:00, 23.00s/it]\n"
]
},
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
estimate
\n",
"
std
\n",
"
ci_95_lower
\n",
"
ci_95_upper
\n",
"
p(|x|>0)
\n",
"
\n",
" \n",
" \n",
"
\n",
"
G41L
\n",
"
-3.497472
\n",
"
0.276578
\n",
"
-4.050627
\n",
"
-2.944317
\n",
"
1.000000
\n",
"
\n",
"
\n",
"
V54G
\n",
"
-1.094177
\n",
"
0.515773
\n",
"
-2.125724
\n",
"
-0.062630
\n",
"
0.983057
\n",
"
\n",
"
\n",
"
G41L:V54G
\n",
"
5.739408
\n",
"
0.593206
\n",
"
4.552996
\n",
"
6.925820
\n",
"
1.000000
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" estimate std ci_95_lower ci_95_upper p(|x|>0)\n",
"G41L -3.497472 0.276578 -4.050627 -2.944317 1.000000\n",
"V54G -1.094177 0.515773 -2.125724 -0.062630 0.983057\n",
"G41L:V54G 5.739408 0.593206 4.552996 6.925820 1.000000"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"contrast_matrix = pd.DataFrame({'G41L' : [-1, 0, 1, 0],\n",
" 'V54G' : [-1, 1, 0, 0],\n",
" 'G41L:V54G': [ 1, -1, -1, 1]},\n",
" index=seqs)\n",
"contrast = model.make_contrasts(contrast_matrix)\n",
"contrast"
]
},
{
"cell_type": "markdown",
"id": "93f38a16",
"metadata": {},
"source": [
"We can see that there is strong support in the posterior for the deleterious effect of G41L in the wild-type background, but also that this is strongly reversed in the presence of V54G. Lets now compare these estimates with the naive comparisons using the estimated measurement errors alone"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "69545135",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
estimate
\n",
"
std
\n",
"
ci_95_lower
\n",
"
ci_95_upper
\n",
"
p(|x|>0)
\n",
"
\n",
" \n",
" \n",
"
\n",
"
G41L
\n",
"
-3.512487
\n",
"
0.325026
\n",
"
-4.162539
\n",
"
-2.862435
\n",
"
1.0
\n",
"
\n",
"
\n",
"
V54G
\n",
"
0.334153
\n",
"
0.055370
\n",
"
0.223413
\n",
"
0.444892
\n",
"
1.0
\n",
"
\n",
"
\n",
"
G41L:V54G
\n",
"
4.318691
\n",
"
0.349109
\n",
"
3.620472
\n",
"
5.016910
\n",
"
1.0
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" estimate std ci_95_lower ci_95_upper p(|x|>0)\n",
"G41L -3.512487 0.325026 -4.162539 -2.862435 1.0\n",
"V54G 0.334153 0.055370 0.223413 0.444892 1.0\n",
"G41L:V54G 4.318691 0.349109 3.620472 5.016910 1.0"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"make_contrasts(df, contrast_matrix)"
]
},
{
"cell_type": "markdown",
"id": "cfa8b3bf",
"metadata": {},
"source": [
"We can see how estimates are then shrunk towards 0 and uncertaintly is slightly reduced by using the prior that was estimated across the complete dataset"
]
},
{
"cell_type": "markdown",
"id": "2d87e2c7",
"metadata": {},
"source": [
"## Inference from real data: the Shine-Dalgarno sequence\n",
"\n",
"In this section, we will show how to use `MinimumEpistasisInterpolator` and `VCregression` to infer and analyze the genotype-phenotype map of the Shine-Dalgarno (SD) sequence. We use data from a high-throuhgput experimental Sort-Seq assay in which translational efficiency of a library of about 250,000 9-nucleotide sequences was measured [(Kuo et al. 2020)](https://genome.cshlp.org/content/30/5/711) as in our original gpmap-tools paper [(Martí-Gómez et al. 2025)](https://www.biorxiv.org/content/10.1101/2025.03.09.642267v3). For full reproducibility of the analysis of the Shine-Dalgarno landscape, including processing of the raw data, see the associated [repository](https://github.com/cmarti/shine_dalgarno). \n",
"\n",
"### Loading high-throughput measurements\n",
"\n",
"Here, for simplicity, we use the built-in dataset provided by `gpmap-tools` for the Shine-Dalgarno sequence as over 250,000 measured 9-nucleotide sequences with the associated noise estimates from the replicate experiments. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7517ec25",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
y
\n",
"
y_var
\n",
"
\n",
"
\n",
"
Genotype
\n",
"
\n",
"
\n",
"
\n",
" \n",
" \n",
"
\n",
"
AAAAAAAAA
\n",
"
0.563000
\n",
"
0.017082
\n",
"
\n",
"
\n",
"
AAAAAAAAC
\n",
"
0.664000
\n",
"
0.017082
\n",
"
\n",
"
\n",
"
AAAAAAAAG
\n",
"
0.643000
\n",
"
0.017082
\n",
"
\n",
"
\n",
"
AAAAAAAAU
\n",
"
0.654333
\n",
"
0.017082
\n",
"
\n",
"
\n",
"
AAAAAAACA
\n",
"
0.594667
\n",
"
0.017082
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
UUUUUUUGU
\n",
"
0.705667
\n",
"
0.017082
\n",
"
\n",
"
\n",
"
UUUUUUUUA
\n",
"
0.590667
\n",
"
0.017082
\n",
"
\n",
"
\n",
"
UUUUUUUUC
\n",
"
0.551333
\n",
"
0.017082
\n",
"
\n",
"
\n",
"
UUUUUUUUG
\n",
"
0.523667
\n",
"
0.017082
\n",
"
\n",
"
\n",
"
UUUUUUUUU
\n",
"
0.538333
\n",
"
0.017082
\n",
"
\n",
" \n",
"
\n",
"
257565 rows × 2 columns
\n",
"
"
],
"text/plain": [
" y y_var\n",
"Genotype \n",
"AAAAAAAAA 0.563000 0.017082\n",
"AAAAAAAAC 0.664000 0.017082\n",
"AAAAAAAAG 0.643000 0.017082\n",
"AAAAAAAAU 0.654333 0.017082\n",
"AAAAAAACA 0.594667 0.017082\n",
"... ... ...\n",
"UUUUUUUGU 0.705667 0.017082\n",
"UUUUUUUUA 0.590667 0.017082\n",
"UUUUUUUUC 0.551333 0.017082\n",
"UUUUUUUUG 0.523667 0.017082\n",
"UUUUUUUUU 0.538333 0.017082\n",
"\n",
"[257565 rows x 2 columns]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"dmsc = DataSet('dmsc')\n",
"dmsc.data"
]
},
{
"cell_type": "markdown",
"id": "db68d8c2",
"metadata": {},
"source": [
"First, we split the dataset into training and test sets to evaluate the performance of the different models"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cb85f643",
"metadata": {},
"outputs": [],
"source": [
"np.random.seed(0)\n",
"u = np.random.uniform(size=dmsc.data.shape[0])\n",
"train = dmsc.data.loc[u < 0.999, :]\n",
"test = dmsc.data.loc[u > 0.999, :]\n",
"X_train, y_train, y_var_train = train.index.values, train.y.values, train.y_var.values\n",
"X_test, y_test = test.index.values, test.y.values"
]
},
{
"cell_type": "markdown",
"id": "ee7e8551",
"metadata": {},
"source": [
"### Minimum epistasis interpolation\n",
"\n",
"Now we fit a model using the training data and make predictions for the complete sequence-space"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6918cd73",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
f
\n",
"
\n",
" \n",
" \n",
"
\n",
"
AAAAAAAAA
\n",
"
0.563000
\n",
"
\n",
"
\n",
"
AAAAAAAAC
\n",
"
0.664000
\n",
"
\n",
"
\n",
"
AAAAAAAAG
\n",
"
0.643000
\n",
"
\n",
"
\n",
"
AAAAAAAAU
\n",
"
0.654333
\n",
"
\n",
"
\n",
"
AAAAAAACA
\n",
"
0.594667
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
UUUUUUUGU
\n",
"
0.705667
\n",
"
\n",
"
\n",
"
UUUUUUUUA
\n",
"
0.590667
\n",
"
\n",
"
\n",
"
UUUUUUUUC
\n",
"
0.551333
\n",
"
\n",
"
\n",
"
UUUUUUUUG
\n",
"
0.523667
\n",
"
\n",
"
\n",
"
UUUUUUUUU
\n",
"
0.538333
\n",
"
\n",
" \n",
"
\n",
"
262144 rows × 1 columns
\n",
"
"
],
"text/plain": [
" f\n",
"AAAAAAAAA 0.563000\n",
"AAAAAAAAC 0.664000\n",
"AAAAAAAAG 0.643000\n",
"AAAAAAAAU 0.654333\n",
"AAAAAAACA 0.594667\n",
"... ...\n",
"UUUUUUUGU 0.705667\n",
"UUUUUUUUA 0.590667\n",
"UUUUUUUUC 0.551333\n",
"UUUUUUUUG 0.523667\n",
"UUUUUUUUU 0.538333\n",
"\n",
"[262144 rows x 1 columns]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"model = MinimumEpistasisInterpolator(P=2, seq_length=9, alphabet_type='rna')\n",
"model.fit(X_train, y_train)\n",
"mei = model.predict()\n",
"mei"
]
},
{
"cell_type": "markdown",
"id": "4b8741e0",
"metadata": {},
"source": [
"We can now also compute the predictive uncertainty under the model with the minimum amount of epistasis for a few sequences of interest. Lets try with the test sequences"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "326c8b54",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 274/274 [00:20<00:00, 13.41it/s]\n"
]
}
],
"source": [
"pred = model.predict(X_pred=X_test, calc_variance=True)"
]
},
{
"cell_type": "markdown",
"id": "5ba41d17",
"metadata": {},
"source": [
"Lets now see how similar the predictions are to the measurements in these held-out sequences"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f7c552ff",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0.05, 0.95, '$R^2$=0.86\\nn=274')"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"test_mei = test.join(pred, rsuffix=\"_pred\")\n",
"\n",
"fig, axes = plt.subplots(1, 1, figsize=(4, 4))\n",
"x, xerr = test_mei[\"f\"], 2 * test_mei[\"f_std\"]\n",
"y, yerr = test_mei[\"y\"], 2 * np.sqrt(test_mei[\"y_var\"])\n",
"lims = (-0.5, 3.25)\n",
"r2 = pearsonr(y, x)[0] ** 2\n",
"axes.errorbar(\n",
" x,\n",
" y,\n",
" xerr=xerr,\n",
" yerr=yerr,\n",
" color=\"black\",\n",
" fmt=\"o\",\n",
" alpha=0.2,\n",
" markeredgewidth=0,\n",
" markersize=2.5,\n",
" lw=0.5,\n",
")\n",
"axes.set(\n",
" xlim=lims,\n",
" ylim=lims,\n",
" xticks=np.arange(4),\n",
" xlabel=\"Predicted log(GFP)\",\n",
" ylabel=\"Measured log(GFP)\",\n",
")\n",
"axes.axline((0, 0), (1, 1), lw=0.5, c=\"grey\", linestyle=\"--\")\n",
"axes.text(\n",
" 0.05,\n",
" 0.95,\n",
" \"$R^2$\" + \"={:.2f}\\nn={}\".format(r2, test_mei.shape[0]),\n",
" transform=axes.transAxes,\n",
" va=\"top\",\n",
" ha=\"left\",\n",
")"
]
},
{
"cell_type": "markdown",
"id": "6ae0911e",
"metadata": {},
"source": [
"### Estimating Variance Components\n",
"\n",
"We next use `VCregression` to better understand the complexity of genetic interactions and achieve more accurate and calibrated phenotypic predictions.\n",
"We first estimate the variance components of a prior under which the expected distance-covariance function matches as best as possible the observed one in the empirical data. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ec61f27e",
"metadata": {},
"outputs": [],
"source": [
"model = VCregression(seq_length=4, alphabet_type='protein')\n",
"model.fit(X=X_train, y=y_train, y_var=y_var_train)"
]
},
{
"cell_type": "markdown",
"id": "1bb6389d",
"metadata": {},
"source": [
"We can easily extract the inferred variance components"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "62aa4999",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"test_vc = test.join(pred, rsuffix=\"_pred\")\n",
"\n",
"fig, axes = plt.subplots(1, 1, figsize=(4, 4))\n",
"x, xerr = test_vc[\"f\"], 2 * test_vc[\"f_std\"]\n",
"y, yerr = test_vc[\"y\"], 2 * np.sqrt(test_vc[\"y_var\"])\n",
"lims = (-0.5, 3.25)\n",
"r2 = pearsonr(y, x)[0] ** 2\n",
"axes.errorbar(\n",
" x,\n",
" y,\n",
" xerr=xerr,\n",
" yerr=yerr,\n",
" color=\"black\",\n",
" fmt=\"o\",\n",
" alpha=0.2,\n",
" markeredgewidth=0,\n",
" markersize=2.5,\n",
" lw=0.5,\n",
")\n",
"axes.set(\n",
" xlim=lims,\n",
" ylim=lims,\n",
" xticks=np.arange(4),\n",
" xlabel=\"Predicted log(GFP)\",\n",
" ylabel=\"Measured log(GFP)\",\n",
")\n",
"axes.axline((0, 0), (1, 1), lw=0.5, c=\"grey\", linestyle=\"--\")\n",
"axes.text(\n",
" 0.05,\n",
" 0.95,\n",
" \"$R^2$\" + \"={:.2f}\\nn={}\".format(r2, test_vc.shape[0]),\n",
" transform=axes.transAxes,\n",
" va=\"top\",\n",
" ha=\"left\",\n",
")\n"
]
},
{
"cell_type": "markdown",
"id": "b6642bb4",
"metadata": {},
"source": [
"fitting `VCregression` is substantially slower because of the higher expressivity of the prior distribution. In this particular case, we have measurements over a large fraction of all possible sequences, the performance of both `VCregression` and `MinimumEpistasisInterpolator` are very similar when evaluated on the same test set.\n",
"\n",
"### Estimating context-dependent mutational effects\n",
"\n",
"In addition to computing the posterior distribution for a specific subset of sequences, `gpmap-tools` also enables the computation of the posterior distribution of any possible linear combination of phenotypes. This can be used, for instance, to compute the posterior distribution for the effects of a series of mutations in different genetic backgrounds. In this case, we wanted to test the effects of mutations in two genetic backgrounds `'UUAAGGAGC'` and `'UAAGGAGCA'`, characterized by having an AGGAG motif at adjacent positions in the sequence. \n",
"\n",
"To do this, as in any linear model, we need to define a contrast matrix, with a series of sequences on the rows and the specified contrasts on the columns. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2c2496f0",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, axes = plt.subplots(1, 1, figsize=(4, 1.5))\n",
"\n",
"palette = dict(zip(backgrounds, ['grey', 'black']))\n",
"dx = dict(zip(backgrounds, [-0.125, 0.125]))\n",
"kwargs = {\n",
" \"fmt\": \"o\",\n",
" \"lw\": 0,\n",
" \"elinewidth\": 2,\n",
" \"capsize\": 3,\n",
" \"markersize\": 5,\n",
"}\n",
"\n",
"for background, df in mut_eff_contrasts.groupby('background'):\n",
" df[\"x\"] = np.arange(df.shape[0]) - 0.125\n",
" axes.errorbar(\n",
" df[\"x\"] + dx[background],\n",
" df[\"estimate\"],\n",
" yerr=2 * df[\"std\"],\n",
" color=palette[background],\n",
" label=background,\n",
" **kwargs,\n",
" )\n",
"axes.set(\n",
" xlabel=\"Mutation\",\n",
" ylabel=\"$\\Delta$log(GFP)\",\n",
" xticks=df[\"x\"],\n",
" xticklabels=df[\"mutation\"],\n",
")\n",
"axes.axhline(0, linestyle=\"--\", c=\"grey\", lw=0.75)\n",
"axes.legend(loc=(0.02, 1.025), ncol=2)"
]
},
{
"cell_type": "markdown",
"id": "52cbe16a",
"metadata": {},
"source": [
"### Estimating average phenotype across genetic backgrounds\n",
"\n",
"In some cases, when measurements are not accurate enough, it is hard to draw solid conclusions about the phenotypes or mutational effects at specific sequences. However, we can often reliably estimate the average across a series of genetic backgrounds that we believe behave in the same manner. For instance, in the SD sequence, we hypothesized that we can obtain functional sequences by having at least one of two overlapping AGGAG motifs but that only a partial AGG match would be insufficient to drive high translationa efficiency. \n",
"\n",
"To investigate this question, we define a contrast matrix to compute these average phenotypes across uniformly sampled genetic backgrounds, and compare it with the wild-type sequence `'AAGGAGGUG'` and the average of all possible sequences `'NNNNNNNNN'`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "296f62ff",
"metadata": {},
"outputs": [],
"source": [
"bc1 = np.array([\"\".join(x) for x in product(\"ACGU\", repeat=3)])\n",
"bc2 = np.array([\"\".join(x) for x in product(\"ACGU\", repeat=6)])\n",
"bc3 = np.array([\"\".join(x) for x in product(\"ACGU\", repeat=9)])\n",
"bc4 = np.array([\"\".join(x) for x in product(\"ACGU\", repeat=2)])\n",
"p1, p2, p3 = 1.0 / bc1.shape[0], 1.0 / bc2.shape[0], 1.0 / bc3.shape[0]\n",
"p4 = 1.0 / bc4.shape[0]\n",
"contrasts = {\n",
" \"AGGAGGNNN\": {\"AGGAGG{}\".format(x): p1 for x in bc1},\n",
" \"NGGAGGAGN\": {\"{}GGAGGAG{}\".format(x[0], x[-1]): p4 for x in bc4},\n",
" \"NNNAGGNNN\": {\"{}AGG{}\".format(x[:3], x[3:]): p2 for x in bc2},\n",
" \"NNNAGGAGG\": {\"{}AGGAGG\".format(x): p1 for x in bc1},\n",
" \"AAGGAGGUG\": {\"AAGGAGGUG\": 1.0},\n",
" \"NNNNNNNNN\": {x: p3 for x in bc3},\n",
"}\n",
"contrast_matrix = pd.DataFrame(contrasts).fillna(0)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "70af014e",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 6/6 [00:26<00:00, 4.39s/it]\n"
]
}
],
"source": [
"avg_phenotypes_contrasts = model.make_contrasts(contrast_matrix)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c4872e18",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"