{ "cells": [ { "cell_type": "markdown", "id": "favorite-helping", "metadata": {}, "source": [ "## Lineage\n", "\n", "This notebook demonstrates how to recreate lineages published in the paper [Live imaging of remyelination in the adult mouse corpus callosum](https://www.pnas.org/content/118/28/e2025795118) and available at [idr0113-bottes-opcclones](https://idr.openmicroscopy.org/search/?query=Name:idr0113).\n", "\n", "The lineage is created from the metadata associated to the specified image.\n", "\n", "To load the data from the Image Data Resource, we use:\n", "* the [Python API](https://docs.openmicroscopy.org/omero/latest/developers/Python.html)\n", "* the [JSON API](https://docs.openmicroscopy.org/omero/latest/developers/json-api.html)" ] }, { "cell_type": "markdown", "id": "parallel-kennedy", "metadata": {}, "source": [ "LPC-induced focal demyelination and in vivo imaging of genetically targeted OPCs and their progeny to describe the cellular dynamics of OPC-mediated remyelination in the CC.\n", "\n", "Longitudinal observation of OPCs and their progeny for up to two months reveals functional inter- and intraclonal heterogeneity and provides insights into the cell division capacity and the migration/differentiation dynamics of OPCs and their daughter cells in vivo.\n", "\n", "The majority of the clones remained quiescent or divided only few times. Some OPCs were highly proliferative. \n", "Large clones showed longer times between consecutive divisions compared to low proliferating clones.\n", "\n", "OPCs show distinct modes of cell division: from symmetric proliferative, to symmetric differentiating and also asymmetric cell division, where the OPC is self-renewed while the other daughter cell differentiates.\n", "\n", "Only 16.46% of OPC-derived cells differentiated into mature, remyelinating oligodendrocytes, with OPCs born at early divisions showing a higher probability to survive and to terminally differentiate.\n", "\n", "Cell death was associated with distinct cell division histories of different clones, with higher probability of death when generated at later divisions.\n", "\n", "Migratory behaviour was restricted to progenitors. Successfully differentiating progenitors moved shorter distances per day compared to dying cells." ] }, { "cell_type": "markdown", "id": "grand-trick", "metadata": {}, "source": [ "## Settings\n", "\n", "### Auxiliar libraries used\n", "* [nb_conda_kernels](https://github.com/Anaconda-Platform/nb_conda_kernels): Enables a Jupyter Notebook or JupyterLab application in one conda environment to access kernels for Python, R, and other languages found in other environments.\n", "* [jupyter_contrib_nbextensions](https://jupyter-contrib-nbextensions.readthedocs.io/en/latest/index.html): Package containing a collection of community-contributed unofficial extensions that add functionality to the Jupyter notebook\n", "* [jupyter-notebookparams](https://pypi.org/project/jupyter-notebookparams/): Takes query parameters from a url to update a parameter cell of a jupyter notebook.\n", "\n", "## Launch\n", "\n", "### binder\n", "\n", "If not already running, you can launch by clicking on the logo [![Binder <](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/IDR/idr0113-bottes-opcclones/main?urlpath=notebooks%2Fnotebooks%2Fidr0113_lineage.ipynb%3FimageId%3D13425213)\n", "\n", "### run locally using repo2docker\n", "\n", "With ``jupyter-repo2docker`` installed, run:\n", "```\n", "git clone https://github.com/IDR/idr0113-bottes-opcclones.git\n", "cd idr0113-bottes-opcclones\n", "repo2docker .\n", "```" ] }, { "cell_type": "markdown", "id": "patent-gateway", "metadata": {}, "source": [ "## Collect the parameter " ] }, { "cell_type": "code", "execution_count": 1, "id": "amazing-belief", "metadata": {}, "outputs": [], "source": [ "# Parameters:\n", "imageId = 13425213" ] }, { "cell_type": "markdown", "id": "worst-anniversary", "metadata": {}, "source": [ "## Load the libraries " ] }, { "cell_type": "code", "execution_count": 2, "id": "micro-gilbert", "metadata": {}, "outputs": [], "source": [ "import graphviz\n", "import math\n", "import requests\n", "import pandas as pd\n", "\n", "from os.path import expanduser\n", "\n", "from idr import connection" ] }, { "cell_type": "markdown", "id": "foreign-archives", "metadata": {}, "source": [ "# Load data " ] }, { "cell_type": "markdown", "id": "located-chest", "metadata": {}, "source": [ "## Connect to IDR" ] }, { "cell_type": "code", "execution_count": 3, "id": "signal-arrow", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Connected to IDR ...\n" ] } ], "source": [ "conn = connection('idr.openmicroscopy.org')" ] }, { "cell_type": "markdown", "id": "approximate-vault", "metadata": {}, "source": [ "## Load the plane information\n", "First load information about the image so we can identify the number of days after induction." ] }, { "cell_type": "code", "execution_count": 4, "id": "african-building", "metadata": {}, "outputs": [], "source": [ "times = {}\n", "\n", "image = conn.getObject(\"Image\", imageId)\n", "pixels_id = image.getPrimaryPixels().getId()\n", "query = \"from PlaneInfo as Info where pixels.id='\" + str(pixels_id) + \"'\"\n", "infos = conn.getQueryService().findAllByQuery(query, None)\n", "for i in infos:\n", " times.update({i.theT.getValue(): int(i.deltaT.getValue())})" ] }, { "cell_type": "markdown", "id": "moving-position", "metadata": {}, "source": [ "## URL used to load data\n", "We now use the JSON API to load the Regions of Interest (ROI) and the table with the lineage information" ] }, { "cell_type": "code", "execution_count": 5, "id": "automotive-sunday", "metadata": {}, "outputs": [], "source": [ "INDEX_PAGE = \"https://idr.openmicroscopy.org/webclient/?experimenter=-1\"\n", "ROI_URL = \"https://idr.openmicroscopy.org/api/v0/m/images/{key}/rois/?limit=500\"\n", "TABLE_URL = \"https://idr.openmicroscopy.org/webgateway/table/Image/{key}/query/?query=*\"" ] }, { "cell_type": "code", "execution_count": 6, "id": "overall-grenada", "metadata": {}, "outputs": [], "source": [ "# create http session\n", "with requests.Session() as session:\n", " request = requests.Request('GET', INDEX_PAGE)\n", " prepped = session.prepare_request(request)\n", " response = session.send(prepped)\n", " if response.status_code != 200:\n", " response.raise_for_status()" ] }, { "cell_type": "markdown", "id": "fifteen-episode", "metadata": {}, "source": [ "## Load the Regions of Interest linked to the image\n", "Each ROI has only one shape so we map the timepoint the shape is to the value in days." ] }, { "cell_type": "code", "execution_count": 7, "id": "transparent-conviction", "metadata": {}, "outputs": [], "source": [ "qs = {'key': imageId}\n", "url = ROI_URL.format(**qs)\n", "json_data = session.get(url).json()\n", "\n", "roi_time_map = {}\n", "# parse the json\n", "for d in json_data['data']:\n", " roi_id = d['@id']\n", " for s in d[\"shapes\"]:\n", " roi_time_map.update({str(roi_id): times.get(int(s['TheT']))}) " ] }, { "cell_type": "markdown", "id": "curious-philosophy", "metadata": {}, "source": [ "## Load the lineage table\n", "Each image with ROIs has a table linked to it capturing the lineage.\n", "We load the table and convert it into a Pandas dataframe." ] }, { "cell_type": "code", "execution_count": 8, "id": "minus-oxford", "metadata": {}, "outputs": [], "source": [ "url = TABLE_URL.format(**qs)\n", "json_data = session.get(url).json()" ] }, { "cell_type": "code", "execution_count": 9, "id": "hundred-latex", "metadata": {}, "outputs": [], "source": [ "df = pd.DataFrame(columns=json_data['data']['columns'])\n", "for r in json_data['data']['rows']:\n", " df.loc[len(df)] = r" ] }, { "cell_type": "code", "execution_count": 10, "id": "studied-season", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | Roi | \n", "Cell Type | \n", "Cell Uncertainty | \n", "Lineage Roi | \n", "Mother Roi | \n", "Mother Uncertainty | \n", "Sister Roi | \n", "Sister Uncertainty | \n", "Cell Death | \n", "Roi Name | \n", "
---|---|---|---|---|---|---|---|---|---|---|
0 | \n", "2359678 | \n", "PM | \n", "certain | \n", "\n", " | \n", " | certain | \n", "\n", " | certain | \n", "\n", " | 1-1_2_6_na_1_1_na_1 | \n", "
1 | \n", "2359679 | \n", "PM | \n", "certain | \n", "2359678 | \n", "\n", " | certain | \n", "\n", " | certain | \n", "\n", " | 1-1_2_6_na_1_1_na_1 | \n", "
2 | \n", "2359680 | \n", "PM | \n", "certain | \n", "2359679 | \n", "\n", " | certain | \n", "\n", " | certain | \n", "\n", " | 1-1_2_6_na_1_1_na_1 | \n", "
3 | \n", "2359681 | \n", "PM | \n", "certain | \n", "2359680 | \n", "\n", " | certain | \n", "\n", " | certain | \n", "\n", " | 1-1_2_6_na_1_1_na_1 | \n", "
4 | \n", "2359682 | \n", "PM | \n", "certain | \n", "2359681 | \n", "\n", " | certain | \n", "\n", " | certain | \n", "\n", " | 1-1_2_6_na_1_1_na_1 | \n", "
... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
325 | \n", "2360003 | \n", "OPC | \n", "certain | \n", "2360002 | \n", "2359948 | \n", "certain | \n", "\n", " | certain | \n", "yes | \n", "6-6_1_18_5-1_1_1_6-5_1_0 | \n", "
326 | \n", "2360004 | \n", "OPC | \n", "certain | \n", "\n", " | 2359972 | \n", "uncertain | \n", "2360007 | \n", "uncertain | \n", "\n", " | 6-7_1_18_5-4_1_0_6-8_0_0 | \n", "
327 | \n", "2360005 | \n", "OPC | \n", "certain | \n", "2360004 | \n", "2359972 | \n", "uncertain | \n", "\n", " | uncertain | \n", "yes | \n", "6-7_1_18_5-4_1_0_6-8_0_0 | \n", "
328 | \n", "2360006 | \n", "OPC | \n", "certain | \n", "\n", " | 2359972 | \n", "uncertain | \n", "2360005 | \n", "uncertain | \n", "\n", " | 6-8_1_18_5-4_1_0_6-7_0_0 | \n", "
329 | \n", "2360007 | \n", "OPC | \n", "certain | \n", "2360006 | \n", "2359972 | \n", "uncertain | \n", "\n", " | uncertain | \n", "yes | \n", "6-8_1_18_5-4_1_0_6-7_0_0 | \n", "
330 rows × 10 columns
\n", "certain |
uncertain |