Cell Lineage in the adult mouse corpus callosum
Summary
This notebook demonstrates how to recreate lineages published in the paper Live imaging of remyelination in the adult mouse corpus callosum and available at idr0113-bottes-opcclones .
The lineage is created from the metadata associated to the specified image.
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.
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.
The majority of the clones remained quiescent or divided only few times. Some OPCs were highly proliferative. Large clones showed longer times between consecutive divisions compared to low proliferating clones.
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.
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.
Cell death was associated with distinct cell division histories of different clones, with higher probability of death when generated at later divisions.
Migratory behaviour was restricted to progenitors. Successfully differentiating progenitors moved shorter distances per day compared to dying cells.
Code Snippets
2 3 | # Parameters: imageId = 13425213 |
7 8 9 10 11 12 13 14 | import graphviz import math import requests import pandas as pd from os.path import expanduser from idr import connection |
18 | conn = connection('idr.openmicroscopy.org') |
22 23 24 25 26 27 28 29 | times = {} image = conn.getObject("Image", imageId) pixels_id = image.getPrimaryPixels().getId() query = "from PlaneInfo as Info where pixels.id='" + str(pixels_id) + "'" infos = conn.getQueryService().findAllByQuery(query, None) for i in infos: times.update({i.theT.getValue(): int(i.deltaT.getValue())}) |
33 34 35 | INDEX_PAGE = "https://idr.openmicroscopy.org/webclient/?experimenter=-1" ROI_URL = "https://idr.openmicroscopy.org/api/v0/m/images/{key}/rois/?limit=500" TABLE_URL = "https://idr.openmicroscopy.org/webgateway/table/Image/{key}/query/?query=*" |
39 40 41 42 43 44 45 | # create http session
with requests.Session() as session:
request = requests.Request('GET', INDEX_PAGE)
prepped = session.prepare_request(request)
response = session.send(prepped)
if response.status_code != 200:
response.raise_for_status()
|
49 50 51 52 53 54 55 56 57 58 | qs = {'key': imageId} url = ROI_URL.format(**qs) json_data = session.get(url).json() roi_time_map = {} # parse the json for d in json_data['data']: roi_id = d['@id'] for s in d["shapes"]: roi_time_map.update({str(roi_id): times.get(int(s['TheT']))}) |
62 63 | url = TABLE_URL.format(**qs) json_data = session.get(url).json() |
67 68 69 | df = pd.DataFrame(columns=json_data['data']['columns']) for r in json_data['data']['rows']: df.loc[len(df)] = r |
77 78 79 80 81 82 | def is_valid(row): mother = row["Mother Roi"] sister = row["Sister Roi"] if mother == "" and sister == "": return False return True |
86 87 88 89 90 91 92 93 94 95 | def find_mothers(): ids = [] for index, row in df.iterrows(): mother = row["Mother Roi"] if mother == "": continue v = str(mother) if v not in ids: ids.append(v) return ids |
99 100 101 | f = graphviz.Digraph(comment='Lineage', format='pdf') f.attr(rank='sink') f.attr('node', shape='circle') |
105 106 107 108 109 110 111 112 113 | # Set various parametes used in the graph COLOR_OPC = "red" COLOR_PM = "orange" COLOR_M = "cyan" COLOR_DEAD = "purple" COLOR_UNCERTAIN = "black" COLOR_EDGE = "black" STYLE_CERTAIN = "solid" STYLE_UNCERTAIN = "dotted" |
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | ids = [] # determine the mothers rois mothers = find_mothers() for index, row in df.iterrows(): id = str(row["Roi"]) if is_valid(row) is False and id not in mothers: continue type = str(row["Cell Type"]) ids.append(id) dead = "no" dead_value = str(row["Cell Death"]) uncertainty = str(row["Cell Uncertainty"]) value = "Type: %s\nCertainty: %s\nDays After Induction: %s\nROI ID: %s" % (type, uncertainty, roi_time_map.get(id), id) color = COLOR_OPC width = "0.1" if type == "PM": color = COLOR_PM elif type == "M": color = COLOR_M if uncertainty == "uncertain": color = "%s:%s" % (COLOR_UNCERTAIN, color) width = "0.2" f.node(id, "", URL='https://idr.openmicroscopy.org/iviewer/?roi=%s' % id, style="radial", color=color, fixedsize='true', width=width, tooltip=value) # Create a node indicating that the cell is dead if dead_value != "": nv = "dead_%s" % id f.node(nv, "", style='filled', color=COLOR_DEAD, fixedsize='true', width='0.1') |
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | edges = [] for index, row in df.iterrows(): if is_valid(row) is False: continue id = str(row["Roi"]) color = COLOR_EDGE lineage = row["Lineage Roi"] if lineage != "": f.edge(str(int(lineage)), id, label='', color=color, arrowhead="none") value = row["Mother Roi"] if value != "" and lineage == "": certainty = row["Mother Uncertainty"] style = STYLE_CERTAIN if certainty != "certain": style = STYLE_UNCERTAIN f.edge(str(int(value)), id, label='', color=color, style=style, arrowhead="none") dead_value = str(row["Cell Death"]) if dead_value != "": nv = "dead_%s" % id f.edge(id, nv, label='', color=color, arrowhead="none", tooltip="Cell is dead") |
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | with f.subgraph(name='legend') as c: c.attr('node', shape='plaintext', fontsize='8') c.node("key1", label='''<<table border="0" cellpadding="2" cellspacing="0" cellborder="0"> <tr><td align="left" port="i1">certain</td></tr> <tr><td align="left" port="i2">uncertain</td></tr> </table>>''') c.node("key2", label='''<<table border="0" cellpadding="2" cellspacing="0" cellborder="0"> <tr><td align="right" port="i1"> </td></tr> <tr><td align="right" port="i2"> </td></tr> </table>>''') c.edge("key1:i1", "key2:i1", label='', color=COLOR_EDGE, style=STYLE_CERTAIN, arrowhead="none") c.edge("key1:i2", "key2:i2", label='', color=COLOR_EDGE, style=STYLE_UNCERTAIN, arrowhead="none") c.node("OPC") c.node("PM") c.node("M") c.node("Cell Death") c.node("Uncertain Cell Type") c.attr('node', shape='circle', fontsize='6') c.node("opc1", "", style='filled', color=COLOR_OPC, fixedsize='true', width='0.1') c.node("pm1", "", style='filled', color=COLOR_PM, fixedsize='true', width='0.1') c.node("m1", "", style='filled', color=COLOR_M, fixedsize='true', width='0.1') c.node("death1", "", style='filled', color=COLOR_DEAD, fixedsize='true', width='0.1') c.node("type1", "", style='filled', color=COLOR_UNCERTAIN, fixedsize='true', width='0.1') c.edge("OPC", "opc1", label='', style="invis") c.edge("PM", "pm1", label='', style="invis") c.edge("M", "m1", label='', style="invis") c.edge("Cell Death", "death1", label='', style="invis") c.edge("Uncertain Cell Type", "type1", label='', style="invis") |
205 206 | home = expanduser("~") f.view(home+"/lineage_%s" % imageId) |
Support
- Future updates
Related Workflows





