Skip to content

Commit 16490f1

Browse files
authored
Merge pull request #3 from gletort/epidev
Epidev
2 parents 759ffe6 + 5fa060a commit 16490f1

15 files changed

+1035
-20
lines changed

docs/Output.md

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,35 @@ This option will open an `html` page that contains the table and statistics for
131131
---
132132

133133
## Measure track features
134+
_Select "Measure track features" in Output onglet_
134135

135-
Measures, displays and export track features.
136+
This option allows you to measure and export track related features, as the track length, mean area of the cell along the track...
136137

137-
This option allows you to measure track related features, as the track length, mean area of the cell along the track...
138-
It displays a table of the measured features of each track.
138+
Check the option `Measures in scaled units` to have the results converted in physcial units (µm, min...) or leave it unchecked to have the measures in pixel and frame units.
139+
140+
Select the track that you want to measure with the `Apply on` parameter: only the currently selected cells, all cells or a specific cell group.
141+
142+
Click on `Track features table` to perform the analysis and display a table with the measured features of each track.
143+
144+
![Measure track interface](imgs/output_trackfeature.png)
145+
146+
EpiCure measures standard track/trajectory characteristic and output them in the table, with one row being one track and one column a feature.
147+
Here we list the track features currently proposed in EpiCure.
148+
149+
If you need to measure a feature that is not yet present in this list, you can of course export the raw cell data and measure it in an external program, or add directly the option within EpiCure code and do a pull request to integrate it in the main distribution of EpiCure, or contact us to suggest for us to add it through opening [an issue](https://github.com/gletort/EpiCure/issues), or on the imagesc forum.
150+
151+
???+ example "Track features"
152+
153+
| Name | Description |
154+
| ------------ | ------------------------------------ |
155+
|Label| Label (indentifying number) of the cell/track that is measured in this row |
156+
| TrackDuration|Total duration from the first time point to the last time point of the track|
157+
|TrackStart|Time at which the track starts|
158+
|TrackEnd|Last time point at which the track is present|
159+
|NbGaps|If there are gaps in the track (frames between the first and last one that do not contain the cell), how many are there|
160+
|TotalDisplacement| Total distance travelled by the cell in the whole track|
161+
|NetDisplacement|Distance between the last point and the first point of the track|
162+
|MeanVelocity|Speed of motion of the cell between consecutive frames, averaged over the whole track|
163+
|Straightness|How straight is the trajectory: NetDisplacement/TotalDisplacement. A value of 1 means the track is linear (totally straight) while close to 0 the motion is very tortuous|
164+
|Group|Group in which the cell Label is classified if any|
139165

140-
Options to plot or interact with these measures will be added in the development of EpiCure plugin.

docs/imgs/output_trackfeature.png

184 KB
Loading

mkdocs.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ nav:
1010
- Edit: Edit.md
1111
- Inspect: Inspect.md
1212
- Track: Track.md
13-
- Outputt: Output.md
13+
- Output: Output.md
1414
- Display: Display.md
1515
- Preferences: Preferences.md
1616
- Additionnal options:
@@ -22,8 +22,8 @@ theme:
2222
name: material
2323
features:
2424
- navigation.footer
25-
#- navigation.tabs
26-
#- navigation.tabs.sticky
25+
- navigation.tabs
26+
- navigation.tabs.sticky
2727
- navigation.path
2828
- navigation.top
2929
- navigation.expand
Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "390c70e5-04f0-4d53-818b-a97b37ec2165",
6+
"metadata": {},
7+
"source": [
8+
"# Combine EpiCure and DeXtrusion results\n",
9+
"\n",
10+
"Open an EpiCured movie (treated) and overlay DeXtrusions probibility maps\n",
11+
"\n",
12+
"\n",
13+
"*This notebook is part of EpiCure release, see https://gitlab.pasteur.fr/gletort/epicure for more informations*"
14+
]
15+
},
16+
{
17+
"cell_type": "code",
18+
"execution_count": null,
19+
"id": "d942aae3-8441-4cde-b7b7-621b48b4ee64",
20+
"metadata": {},
21+
"outputs": [],
22+
"source": [
23+
"import epicure.epicuring as epicure\n",
24+
"import os\n",
25+
"import numpy as np\n",
26+
"import napari\n",
27+
"import tifffile as tif"
28+
]
29+
},
30+
{
31+
"cell_type": "code",
32+
"execution_count": null,
33+
"id": "c0b46ed0-a094-41c7-97a0-2b7b157b83a0",
34+
"metadata": {},
35+
"outputs": [],
36+
"source": [
37+
"## path to input data, and names of the movie and EpiCured segmentation\n",
38+
"data_dir = os.path.join(\"..\", \"data\", \"selection\", \"t000-177\")\n",
39+
"filename = \"Ecad\"\n",
40+
"data_img = filename + \".tif\"\n",
41+
"data_seg = filename + \"_labels.tif\"\n",
42+
"\n",
43+
"infile = os.path.join(data_dir, data_img)\n",
44+
"segfile = os.path.join(data_dir, \"epics\", data_seg)"
45+
]
46+
},
47+
{
48+
"cell_type": "code",
49+
"execution_count": null,
50+
"id": "9656fb1e-ee44-4d30-9f00-b9fd7bd0d449",
51+
"metadata": {},
52+
"outputs": [],
53+
"source": [
54+
"## Load the EpiCure files and movies\n",
55+
"epic = epicure.EpiCure()\n",
56+
"napari_viewer = napari.Viewer(show=False)\n",
57+
"epic.viewer = napari_viewer\n",
58+
"epic.load_movie(infile)\n",
59+
"epic.verbose = 0 ## minimal printing of information messages\n",
60+
"epic.go_epicure(\"epics\", segfile)"
61+
]
62+
},
63+
{
64+
"cell_type": "markdown",
65+
"id": "4c15f3dc-a0d4-4862-aa32-6978f4437f61",
66+
"metadata": {},
67+
"source": [
68+
"### Do tracking if it not had been done yet"
69+
]
70+
},
71+
{
72+
"cell_type": "code",
73+
"execution_count": null,
74+
"id": "c58a131b-aaf1-48ee-aae7-1061efc6fc15",
75+
"metadata": {},
76+
"outputs": [],
77+
"source": [
78+
"if epic.tracked == 0:\n",
79+
" epic.tracking.do_tracking() ## Performs tracking with the default parameters. If you have saved preferences, it will use it.\n",
80+
" epic.save_epicures() ## save the results in the ouput \"epics\" folder(s)"
81+
]
82+
},
83+
{
84+
"cell_type": "markdown",
85+
"id": "1de8c8d6-fb14-4837-b8d5-da8c2346a4d9",
86+
"metadata": {},
87+
"source": [
88+
"### Search for extrusions with `Inspect track` option.\n",
89+
"\n",
90+
"It uses all the default parameters except the ones redefined here. So if other inspect options were selected in the preferences, they will also be runned (eg if `flag track apparition` is selected by default, it will be runned here."
91+
]
92+
},
93+
{
94+
"cell_type": "code",
95+
"execution_count": null,
96+
"id": "8996a394-d325-4e38-b773-b60b0a18b556",
97+
"metadata": {},
98+
"outputs": [],
99+
"source": [
100+
"get_extrusions = False ## Whether to inspect tracks now to search for extruions. Put to False if it has already been done\n",
101+
"\n",
102+
"if get_extrusions:\n",
103+
" epic.inspecting.get_extrusions.setChecked( True ) ## Be sure to search for extrusions\n",
104+
" epic.inspecting.threshold_disparition.setText( \"300\" ) ## set the threshold of cell area so that a cell disparition is considered extrusion vs potential error\n",
105+
" epic.inspecting.inspect_tracks( subprogress=False) ## go, look for extrusions (and other suspects if selected in the saved preferences)\n",
106+
" epic.outputing.export_events_type_format( [\"extrusion\"], \"Fiji ROI\" ) ## export extrusion events into Fiji ROIs"
107+
]
108+
},
109+
{
110+
"cell_type": "code",
111+
"execution_count": null,
112+
"id": "67e6781c-bce1-44f6-bbe8-94e1a47e0f44",
113+
"metadata": {},
114+
"outputs": [],
115+
"source": []
116+
},
117+
{
118+
"cell_type": "markdown",
119+
"id": "af698dfb-5df7-48b8-981e-c019e2a612a4",
120+
"metadata": {
121+
"tags": []
122+
},
123+
"source": [
124+
"### Opens up the DeXtrusion probability maps\n",
125+
"\n",
126+
"Add the probability maps from DeXtrusion into the EpiCure viewer so that events of divisions/extrusions are overlayed with the maps"
127+
]
128+
},
129+
{
130+
"cell_type": "code",
131+
"execution_count": null,
132+
"id": "d62f0202-e60e-44ff-9364-7298e438eb10",
133+
"metadata": {},
134+
"outputs": [],
135+
"source": [
136+
"## path to the folder containing the DeXtrusion results probability maps\n",
137+
"dex_data = os.path.join(\"..\", \"data\", \"selection\", \"t000-177\", \"dextrusion-run\", \"results\")\n",
138+
"\n",
139+
"for event, evtcol in zip( [\"death\", \"division\", \"sop\"], [\"magenta\", \"cyan\", \"yellow\"] ):\n",
140+
" evtfile = os.path.join( dex_data, filename + \"_cell_\" + event + \"_proba.tif\" )\n",
141+
" if os.path.exists( evtfile ):\n",
142+
" print( \"Loading \" + evtfile )\n",
143+
" evtraw = tif.TiffFile( evtfile )\n",
144+
" evtmov = evtraw.asarray()\n",
145+
" evtraw.close()\n",
146+
" epic.viewer.add_image( evtmov, name=\"Dext_\"+event, blending=\"additive\", colormap=evtcol, scale=(1, epic.epi_metadata[\"ScaleXY\"],epic.epi_metadata[\"ScaleXY\"]) )"
147+
]
148+
},
149+
{
150+
"cell_type": "markdown",
151+
"id": "a7594dec-869b-4e08-a2dc-c61e0750ddd4",
152+
"metadata": {},
153+
"source": [
154+
"### Detect SOP cells from DeXtrusion probability map with EpiCure intensity group option\n",
155+
"\n",
156+
"Use EpiCure feature to classify cells based on their intensity in the probability map of being a SOP cell estimated by DeXtrusion.\n",
157+
"\n",
158+
"DeXtrusion can outputs probability maps of each events (extrusion, division, SOP). \n",
159+
"For SOP, the probability map will be positive in nearly all the frames within the SOP cell.\n",
160+
"\n",
161+
"EpiCure can automatically classify the cells as SOP based on their intensity along the track with the `Group from track intensity` feature in the interface that calls the `group_positive_cells` function in the API."
162+
]
163+
},
164+
{
165+
"cell_type": "code",
166+
"execution_count": null,
167+
"id": "d425c7e2-cf4b-4fb6-a696-c3fbaaedba12",
168+
"metadata": {},
169+
"outputs": [],
170+
"source": [
171+
"## Set the group name that will be attributted to SOP cells\n",
172+
"classify_SOP = False\n",
173+
"\n",
174+
"if classify_SOP:\n",
175+
" ind = epic.editing.group_choice.findText( \"SOP\" )\n",
176+
" if ind < 0:\n",
177+
" epic.editing.group_choice.addItem( \"SOP\" )\n",
178+
" else:\n",
179+
" epic.editing.group_choice.setCurrentIndex( ind )\n",
180+
"\n",
181+
" ## Measure the intensity in the \"Dext_sop\" layer. Use the sum of all intensity within the cell within the track. \n",
182+
" epic.editing.group_positive_cells( \"Dext_sop\", \"sum\", 0, epic.nframes-1, epic.nframes*200*100 )"
183+
]
184+
},
185+
{
186+
"cell_type": "code",
187+
"execution_count": null,
188+
"id": "678b0162-c91e-403d-b55e-695e68c2e642",
189+
"metadata": {},
190+
"outputs": [],
191+
"source": [
192+
"epic.viewer.show()"
193+
]
194+
},
195+
{
196+
"cell_type": "markdown",
197+
"id": "9388811a-36ff-4cd3-829c-f6807cf475a3",
198+
"metadata": {},
199+
"source": [
200+
"### Check for False positive events of EpiCure\n",
201+
"\n",
202+
"By measuring the mean probability of event from DeXtrusion probability maps for each event detected by EpiCure, we can flag events that have a low probability and thus might be false positive.\n",
203+
"\n",
204+
"Choose the event to check (division or extrusion) by comparing the results.\n",
205+
"You can print all the **indexes** of events in EpiCure that have a low probability to be correct from DeXtrusion results by putting the parameter `show_low_proba_event`. In EpiCure, by going into `Inspect>Events`, set the index of event to the desired value and click on `Go to event`, you can see the corresponding suspicious event and check if it was correct or not. This can be an additionnal way to find segmentation/tracking mistakes that were not detected by the inspection features of EpiCure."
206+
]
207+
},
208+
{
209+
"cell_type": "code",
210+
"execution_count": null,
211+
"id": "cc31e99a-d799-4c78-a793-da7446ce92b0",
212+
"metadata": {},
213+
"outputs": [],
214+
"source": [
215+
"## Compare extrusion or division events\n",
216+
"event = \"division\" ## name of event in EpiCure (division or extrusion)\n",
217+
"evt_name = \"division\" ## name of event in DeXtrusion (to load the proba map, \"death\" or \"division\")\n",
218+
"\n",
219+
"show_low_proba_event = True\n",
220+
"threshold_low_proba = 150\n",
221+
"\n",
222+
"dz = 1\n",
223+
"dxy = 10\n",
224+
"extrusions = epic.inspecting.get_events_from_type( event )\n",
225+
"extr_intensities = []\n",
226+
"for extr in extrusions:\n",
227+
" position, cell = epic.inspecting.get_event_infos( extr )\n",
228+
" minz = max( position[0]-dz, 0 )\n",
229+
" maxz = min( position[0]+dz+1, epic.nframes )\n",
230+
" minx = max( position[1]-dxy, 0 )\n",
231+
" maxx = min( position[1]+dxy+1, epic.imgshape2D[0] )\n",
232+
" miny = max( position[2]-dxy, 0 )\n",
233+
" maxy = min( position[2]+dxy+1, epic.imgshape2D[1] )\n",
234+
" dex_proba = epic.viewer.layers[\"Dext_\"+evt_name].data[minz:maxz, minx:maxx, miny:maxy]\n",
235+
" dex_proba = np.max( dex_proba )\n",
236+
" extr_intensities.append( dex_proba )\n",
237+
" if (show_low_proba_event) and (dex_proba < threshold_low_proba):\n",
238+
" print( epic.inspecting.index_from_id(extr) )"
239+
]
240+
},
241+
{
242+
"cell_type": "markdown",
243+
"id": "1cdea892-54ab-4647-b3ce-5e2921a0e6e4",
244+
"metadata": {},
245+
"source": [
246+
"### Cumulative distribution of DeXtrusion probabilities of EpiCure's events\n",
247+
"\n",
248+
"Plot the distribution of probabilities from DeXtrusion results measured at each event detected in EpiCure.\n",
249+
"If the two pipelines agree, most events should have a near 255 probability."
250+
]
251+
},
252+
{
253+
"cell_type": "code",
254+
"execution_count": null,
255+
"id": "164ba490-5859-4cb4-b55f-7c6a5102ea5f",
256+
"metadata": {},
257+
"outputs": [],
258+
"source": [
259+
"## Cumulative distribution of deXtrusion probabilities of extrusion/division events\n",
260+
"\n",
261+
"extr_intensities = np.array( extr_intensities )\n",
262+
"histo, xhisto = np.histogram( extr_intensities, bins = 100, normed=True )\n",
263+
"dx = xhisto[1] - xhisto[0]\n",
264+
"cdf = np.cumsum( histo ) * dx\n",
265+
"import matplotlib.pyplot as plt\n",
266+
"plt.plot( xhisto[1:], cdf )"
267+
]
268+
},
269+
{
270+
"cell_type": "code",
271+
"execution_count": null,
272+
"id": "552cdcd2-2044-4e77-8e58-170341fd4b1f",
273+
"metadata": {},
274+
"outputs": [],
275+
"source": []
276+
},
277+
{
278+
"cell_type": "code",
279+
"execution_count": null,
280+
"id": "4cd83be6-c17b-488c-9c63-909c3d4510c3",
281+
"metadata": {},
282+
"outputs": [],
283+
"source": []
284+
}
285+
],
286+
"metadata": {
287+
"kernelspec": {
288+
"display_name": "epic",
289+
"language": "python",
290+
"name": "epic"
291+
},
292+
"language_info": {
293+
"codemirror_mode": {
294+
"name": "ipython",
295+
"version": 3
296+
},
297+
"file_extension": ".py",
298+
"mimetype": "text/x-python",
299+
"name": "python",
300+
"nbconvert_exporter": "python",
301+
"pygments_lexer": "ipython3",
302+
"version": "3.10.12"
303+
}
304+
},
305+
"nbformat": 4,
306+
"nbformat_minor": 5
307+
}

0 commit comments

Comments
 (0)