{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "colab": {}, "colab_type": "code", "id": "feb7MpFF4hKl", "pycharm": {} }, "outputs": [], "source": [ "import wot" ] }, { "cell_type": "markdown", "metadata": { "colab": {}, "colab_type": "code", "id": "JvT_bLlR4hKq", "pycharm": {} }, "source": [ "# Notebook 3: Computing long-range couplings\n", "\n", "In Notebook 2 we saw how to compute transport matrices $\\pi_{t_i,t_{i+1}}$ connecting adjacent time-points $(t_i,t_{i+1})$. Over short time-scales, this OT matrix is a good approximation to the true temporal coupling:\n", "\n", "$$ \\pi_{t_i,t_{i+1}} \\approx \\gamma_{t_i,t_{i+1}}. $$\n", "\n", "In this notebook we show how to infer transitions over a longer time interval $(t_i,t_j)$.\n", "To do this, we assume the developmental stochastic process ${\\mathbb{P}}_t$ is Markov. This means that the couplings $\\gamma_{s,t}$ satisfy the following algebraic relationship:\n", "\n", "$$ \\gamma_{t_1,t_3}(x,z) = \\iint \\gamma_{t_1,t_2}(x,y) \\gamma_{t_2,t_3}(y,z) dy$$\n", "\n", "for any $t_1 < t_2 < t_3$. The integral on the right hand side becomes a finite sum when we have a finite sample of cells. In fact, it's a matrix multiplication! \n", "\n", "Therefore we can infer long-range transitions by composing transport maps as follows:\n", "\n", "$$\\gamma_{t_i,t_j} = \\gamma_{t_i,t_{i+1}} \\circ \\gamma_{t_{i+1},t_{i+2}} \\circ \\cdots \\circ \\gamma_{t_{j-1},t_{j}} \n", "\\approx \\pi_{t_i,t_{i+1}} \\circ \\pi_{t_{i+1},t_{i+2}} \\circ \\cdots \\circ \\pi_{t_{j-1},t_{j}}.$$\n", "\n", "Here $\\circ$ denotes matrix multiplication. This is of course different than directly computing OT over longer time-intervals:\n", "\n", "$$ \\pi_{t_1,t_2} \\circ \\pi_{t_2,t_3} \\ne \\pi_{t_1,t_3}.$$\n", "\n", "In the following code block we construct a TransportMapModel from a directory of pre-computed transport matrices. " ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 34 }, "colab_type": "code", "id": "5lFF4FfhAexV", "outputId": "e5befe29-2896-45a2-ddc2-f37458648d5c", "pycharm": {} }, "outputs": [], "source": [ "tmap_model = wot.tmap.TransportMapModel.from_directory('tmaps/serum')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Composing couplings\n", "\n", "We can now easily compute the coupling between any pair of time-points as follows:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "AnnData object with n_obs × n_vars = 3815 × 2051 \n", " obs: 'g0', 'g1', 'g2', 'g3'" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gamma_8_10 = tmap_model.get_coupling(8, 10)\n", "gamma_8_10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The resulting temporal coupling $\\gamma_{t_i,t_j}$ has a row for each cell at time $t_i$ and a column for each cell at time $t_j$. \n", "Just like for a short-range coupling, the units are \"transported mass\". So a value of $\\gamma_{t_i,t_j}(x,y) = 0.2$ means that cell $x$ will have on average $0.2$ descendants with expression profile similar to $y$ at time $t_j$.\n", "Note that the sum of a row shows the total number of descendants that a cell will have at time $t_j$." ] } ], "metadata": { "colab": { "name": "wot-3.ipynb", "provenance": [], "version": "0.3.2" }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" }, "pycharm": { "stem_cell": { "cell_type": "raw", "source": [], "metadata": { "collapsed": false } } } }, "nbformat": 4, "nbformat_minor": 2 }