{
"cells": [
{
"cell_type": "markdown",
"id": "6b25ab6a-6e72-499b-8e1c-596a1acf326e",
"metadata": {},
"source": [
"# Innere und \u00e4u\u00dfere Zellgrenzen\n",
"Bei der Untersuchung von Geweben, Organismen und Organoiden ist oft die Position und Orientierung der Zelle und ihrer Membranen innerhalb des Gewebes relevant. Zum Beispiel unterscheiden wir zwischen apikalen (an einer Spitze, am Ende, \u00e4u\u00dferen) und basalen (an der Basis, inneren) Seiten von Zellen innerhalb des Gewebes. Ausgehend von einem Zellsegmentierungs-Labelbild k\u00f6nnen wir Pixel identifizieren, die au\u00dferhalb oder innerhalb einer aus Zellen bestehenden Struktur liegen. Im folgenden Beispiel arbeiten wir mit einem synthetischen zweidimensionalen Bild einiger Zellen, die ein Organoid bilden. Die gleichen Funktionen funktionieren auch in 3D."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "626f5f39-5098-4073-85ad-dba507e02258",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pyclesperanto_prototype as cle"
]
},
{
"cell_type": "markdown",
"id": "d90dcfb3-062f-47f1-8bf7-f9d33778e364",
"metadata": {},
"source": [
"Zuerst erstellen wir unseren synthetischen Datensatz. Er besteht aus 6 Zellzentren, die wir zu einem Organoid erweitert haben."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "451f06eb-7ed0-444f-8ff7-bb8978993b00",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(100, 100)"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"points = np.asarray([\n",
" [50, 50],\n",
" [60, 60],\n",
" [25, 40],\n",
" [70, 30],\n",
" [35, 65],\n",
" [50, 25]\n",
"]).T\n",
"image = np.zeros((100, 100))\n",
"spots = cle.pointlist_to_labelled_spots(points, image)\n",
"cells = cle.dilate_labels(spots, radius=15)\n",
"spots.shape"
]
},
{
"cell_type": "markdown",
"id": "09eabbdf-6694-4708-b79d-5c20f554c481",
"metadata": {},
"source": [
"Dies sind unsere Zellen:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "4118d3d7-a155-482b-bf7f-c2c4d877b099",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (100, 100) | \n",
"dtype | uint32 | \n",
"size | 39.1 kB | \n",
"min | 0.0 | max | 6.0 | \n",
" \n",
"\n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" ...,\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0]], dtype=uint32)"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cells"
]
},
{
"cell_type": "markdown",
"id": "a6a69fe3-ccf7-4bfc-b768-d7465cec1f3c",
"metadata": {},
"source": [
"Und das ist das Organoid:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "430c2545-b765-427e-a001-6af31c372547",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (100, 100) | \n",
"dtype | uint8 | \n",
"size | 9.8 kB | \n",
"min | 0.0 | max | 1.0 | \n",
" \n",
" \n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" ...,\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0]], dtype=uint8)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"organoid = cells > 0\n",
"organoid"
]
},
{
"cell_type": "markdown",
"id": "0772ee71-ff4e-4581-a111-d146c6c119dd",
"metadata": {},
"source": [
"Wir identifizieren nun die Pixel, die sich an den Grenzen der Zellen befinden."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "50881a14-b5a2-4855-943c-949fcb631b6a",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (100, 100) | \n",
"dtype | uint32 | \n",
"size | 39.1 kB | \n",
"min | 0.0 | max | 6.0 | \n",
" \n",
"\n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" ...,\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0]], dtype=uint32)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cell_borders = cle.reduce_labels_to_label_edges(cells)\n",
"cell_borders"
]
},
{
"cell_type": "markdown",
"id": "16f151e4-f006-459b-bce7-23b05b571f25",
"metadata": {},
"source": [
"Wir k\u00f6nnen genau dasselbe mit dem Organoid machen, um die Pixel auf seiner Oberfl\u00e4che zu identifizieren."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "0e02357b-f746-4867-b881-e9c962b653d3",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (100, 100) | \n",
"dtype | uint32 | \n",
"size | 39.1 kB | \n",
"min | 0.0 | max | 1.0 | \n",
" \n",
"\n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" ...,\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0]], dtype=uint32)"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"organoid_border = cle.reduce_labels_to_label_edges(organoid)\n",
"organoid_border"
]
},
{
"cell_type": "markdown",
"id": "d9d1ec4e-8f1f-4e45-b12a-ad37c18b020d",
"metadata": {},
"source": [
"Indem wir die Zellgrenzen mit der Organoidgrenze maskieren - technisch gesehen ist das eine pixelweise Multiplikation - k\u00f6nnen wir die \u00e4u\u00dferen Grenzen identifizieren."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "aa965a78-ef82-4e60-8909-eed3d68c0cd2",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (100, 100) | \n",
"dtype | uint32 | \n",
"size | 39.1 kB | \n",
"min | 0.0 | max | 6.0 | \n",
" \n",
"\n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" ...,\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0]], dtype=uint32)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"outer_borders = cle.mask(cell_borders, organoid_border).astype(np.uint32)\n",
"outer_borders"
]
},
{
"cell_type": "markdown",
"id": "11ef81d3-49ef-4bee-9bb6-2b491ec9d6ef",
"metadata": {},
"source": [
"Wenn wir die \u00e4u\u00dferen Grenzen von allen Zellgrenzen abziehen, erhalten wir die inneren Grenzen"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "452340c1-987d-41b1-8431-f9882cad6e10",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (100, 100) | \n",
"dtype | uint32 | \n",
"size | 39.1 kB | \n",
"min | 0.0 | max | 6.0 | \n",
" \n",
"\n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" ...,\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0]], dtype=uint32)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"inner_borders = (cell_borders - outer_borders).astype(np.uint32)\n",
"inner_borders"
]
},
{
"cell_type": "markdown",
"id": "afc73d32-96d9-4b23-b712-8fadde7a8edc",
"metadata": {},
"source": [
"Bei der Nachbearbeitung dieser Labelbilder sollten Sie etwas vorsichtig sein, da diese Bilder m\u00f6glicherweise nicht sequenziell beschriftet sind. Es gibt Bibliotheken und Funktionen, die m\u00f6glicherweise Probleme mit solchen Labelbildern haben (z.B. `cle.statistics_of_labelled_pixels()`). Sie k\u00f6nnen die vorhandenen Labels in einem Labelbild mit `np.unique()` ausgeben und die Labelbilder mit `cle.relabel_sequential()` sequenziell machen."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "a40a6826-5f21-4ba4-aafa-a2992a6332e1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0, 2, 3, 4, 5, 6], dtype=uint32)"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.unique(outer_borders)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "7da3ec85-4bd0-4433-aa73-46641e24dbcf",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0, 1, 2, 3, 4, 5, 6], dtype=uint32)"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.unique(inner_borders)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "32e866b1-b41b-4965-a717-9c57d190fa73",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.9.15"
}
},
"nbformat": 4,
"nbformat_minor": 5
}