Skip to content

Commit a2c45b0

Browse files
authored
Merge pull request #45 from Image-Analysis-Hub/api/time-key
Api/time key update notebooks
2 parents 92e0936 + 4d6e6f3 commit a2c45b0

7 files changed

Lines changed: 1057 additions & 1024 deletions

File tree

notebooks/Custom properties.ipynb

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
},
2525
{
2626
"cell_type": "code",
27-
"execution_count": 1,
27+
"execution_count": 19,
2828
"metadata": {},
2929
"outputs": [],
3030
"source": [
@@ -42,7 +42,7 @@
4242
},
4343
{
4444
"cell_type": "code",
45-
"execution_count": 2,
45+
"execution_count": 20,
4646
"metadata": {},
4747
"outputs": [
4848
{
@@ -118,14 +118,14 @@
118118
},
119119
{
120120
"cell_type": "code",
121-
"execution_count": 3,
121+
"execution_count": 21,
122122
"metadata": {},
123123
"outputs": [],
124124
"source": [
125125
"age_prop = pc.Property(\n",
126126
" identifier=\"age\",\n",
127127
" name=\"age\",\n",
128-
" description=\"Age of the cell since the beginning of the lineage\",\n",
128+
" description=\"Age of the cell since the start of the lineage\",\n",
129129
" provenance=\"custom\",\n",
130130
" prop_type=\"node\",\n",
131131
" lin_type=\"CellLineage\",\n",
@@ -143,14 +143,14 @@
143143
},
144144
{
145145
"cell_type": "code",
146-
"execution_count": 4,
146+
"execution_count": 22,
147147
"metadata": {},
148148
"outputs": [
149149
{
150150
"name": "stdout",
151151
"output_type": "stream",
152152
"text": [
153-
"age: Age of the cell since the beginning of the lineage in frame(s)\n"
153+
"age: Age of the cell since the start of the lineage in frame(s)\n"
154154
]
155155
}
156156
],
@@ -192,7 +192,7 @@
192192
},
193193
{
194194
"cell_type": "code",
195-
"execution_count": 5,
195+
"execution_count": 23,
196196
"metadata": {},
197197
"outputs": [],
198198
"source": [
@@ -267,7 +267,7 @@
267267
},
268268
{
269269
"cell_type": "code",
270-
"execution_count": 6,
270+
"execution_count": 24,
271271
"metadata": {},
272272
"outputs": [],
273273
"source": [
@@ -304,7 +304,7 @@
304304
},
305305
{
306306
"cell_type": "code",
307-
"execution_count": 7,
307+
"execution_count": 25,
308308
"metadata": {},
309309
"outputs": [],
310310
"source": [
@@ -322,7 +322,7 @@
322322
},
323323
{
324324
"cell_type": "code",
325-
"execution_count": 8,
325+
"execution_count": 26,
326326
"metadata": {},
327327
"outputs": [
328328
{
@@ -2507,7 +2507,7 @@
25072507
"autorange": "reversed",
25082508
"showgrid": true,
25092509
"title": {
2510-
"text": "Time (frames)"
2510+
"text": "Time (timepoints)"
25112511
},
25122512
"zeroline": true
25132513
}
@@ -2539,7 +2539,7 @@
25392539
},
25402540
{
25412541
"cell_type": "code",
2542-
"execution_count": 9,
2542+
"execution_count": 27,
25432543
"metadata": {},
25442544
"outputs": [],
25452545
"source": [
@@ -2577,7 +2577,7 @@
25772577
},
25782578
{
25792579
"cell_type": "code",
2580-
"execution_count": 10,
2580+
"execution_count": 28,
25812581
"metadata": {},
25822582
"outputs": [],
25832583
"source": [
@@ -2602,7 +2602,7 @@
26022602
},
26032603
{
26042604
"cell_type": "code",
2605-
"execution_count": 11,
2605+
"execution_count": 29,
26062606
"metadata": {
26072607
"tags": [
26082608
"raises-exception"
@@ -2616,9 +2616,9 @@
26162616
"traceback": [
26172617
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
26182618
"\u001b[31mTypeError\u001b[39m Traceback (most recent call last)",
2619-
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[11]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m 1\u001b[39m calc = ParityCalculator_incorrect(prop_incorrect)\n\u001b[32m 2\u001b[39m model.add_custom_property(calc)\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[43mmodel\u001b[49m\u001b[43m.\u001b[49m\u001b[43mupdate\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
2620-
"\u001b[36mFile \u001b[39m\u001b[32m/media/lxenard/data/Code/pycellin/pycellin/pycellin/classes/model.py:575\u001b[39m, in \u001b[36mModel.update\u001b[39m\u001b[34m(self, props_to_update)\u001b[39m\n\u001b[32m 567\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m\n\u001b[32m 569\u001b[39m \u001b[38;5;66;03m# self.data._freeze_lineage_data()\u001b[39;00m\n\u001b[32m 570\u001b[39m \n\u001b[32m 571\u001b[39m \u001b[38;5;66;03m# TODO: need to handle all the errors that can be raised\u001b[39;00m\n\u001b[32m 572\u001b[39m \u001b[38;5;66;03m# by the updater methods to avoid incoherent states.\u001b[39;00m\n\u001b[32m 573\u001b[39m \u001b[38;5;66;03m# => saving a copy of the model before the update so we can roll back?\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m575\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_updater\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_update\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprops_to_update\u001b[49m\u001b[43m)\u001b[49m\n",
2621-
"\u001b[36mFile \u001b[39m\u001b[32m/media/lxenard/data/Code/pycellin/pycellin/pycellin/classes/updater.py:194\u001b[39m, in \u001b[36mModelUpdater._update\u001b[39m\u001b[34m(self, data, props_to_update)\u001b[39m\n\u001b[32m 190\u001b[39m \u001b[38;5;66;03m# Recompute the properties as needed.\u001b[39;00m\n\u001b[32m 191\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m calc \u001b[38;5;129;01min\u001b[39;00m cell_calculators:\n\u001b[32m 192\u001b[39m \u001b[38;5;66;03m# Depending on the class of the calculator, a different version of\u001b[39;00m\n\u001b[32m 193\u001b[39m \u001b[38;5;66;03m# the enrich() method is called.\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m194\u001b[39m \u001b[43mcalc\u001b[49m\u001b[43m.\u001b[49m\u001b[43menrich\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 195\u001b[39m \u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 196\u001b[39m \u001b[43m \u001b[49m\u001b[43mnodes_to_enrich\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_added_cells\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 197\u001b[39m \u001b[43m \u001b[49m\u001b[43medges_to_enrich\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_added_links\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 198\u001b[39m \u001b[43m \u001b[49m\u001b[43mlineages_to_enrich\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_added_lineages\u001b[49m\u001b[43m \u001b[49m\u001b[43m|\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_modified_lineages\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 199\u001b[39m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 201\u001b[39m \u001b[38;5;66;03m# In case of modifications in the structure of some cell lineages,\u001b[39;00m\n\u001b[32m 202\u001b[39m \u001b[38;5;66;03m# we need to recompute the cycle lineages and their properties.\u001b[39;00m\n\u001b[32m 203\u001b[39m \u001b[38;5;66;03m# TODO: optimize so we don't have to recompute EVERYTHING for cycle lineages?\u001b[39;00m\n\u001b[32m 204\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m lin_ID \u001b[38;5;129;01min\u001b[39;00m (\u001b[38;5;28mself\u001b[39m._modified_lineages | \u001b[38;5;28mself\u001b[39m._added_lineages) - \u001b[38;5;28mself\u001b[39m._removed_lineages:\n",
2619+
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[29]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m 1\u001b[39m calc = ParityCalculator_incorrect(prop_incorrect)\n\u001b[32m 2\u001b[39m model.add_custom_property(calc)\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[43mmodel\u001b[49m\u001b[43m.\u001b[49m\u001b[43mupdate\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
2620+
"\u001b[36mFile \u001b[39m\u001b[32m/media/lxenard/data/Code/pycellin/pycellin/pycellin/classes/model.py:910\u001b[39m, in \u001b[36mModel.update\u001b[39m\u001b[34m(self, props_to_update)\u001b[39m\n\u001b[32m 903\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m time_step \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m 904\u001b[39m \u001b[38;5;66;03m# TODO: add \"see documentation\" to the error message or explain\u001b[39;00m\n\u001b[32m 905\u001b[39m \u001b[38;5;66;03m# directly how to set it?\u001b[39;00m\n\u001b[32m 906\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[32m 907\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mThe time step of the model is currently not defined \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 908\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mbut is required for cycle lineage computation.\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 909\u001b[39m )\n\u001b[32m--> \u001b[39m\u001b[32m910\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_updater\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_update\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 911\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 912\u001b[39m \u001b[43m \u001b[49m\u001b[43mtime_prop\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mmodel_metadata\u001b[49m\u001b[43m.\u001b[49m\u001b[43mreference_time_property\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 913\u001b[39m \u001b[43m \u001b[49m\u001b[43mtime_step\u001b[49m\u001b[43m=\u001b[49m\u001b[43mtime_step\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 914\u001b[39m \u001b[43m \u001b[49m\u001b[43mprops_to_update\u001b[49m\u001b[43m=\u001b[49m\u001b[43mprops_to_update\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 915\u001b[39m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n",
2621+
"\u001b[36mFile \u001b[39m\u001b[32m/media/lxenard/data/Code/pycellin/pycellin/pycellin/classes/updater.py:280\u001b[39m, in \u001b[36mModelUpdater._update\u001b[39m\u001b[34m(self, data, time_prop, time_step, props_to_update)\u001b[39m\n\u001b[32m 276\u001b[39m \u001b[38;5;66;03m# Recompute the properties as needed.\u001b[39;00m\n\u001b[32m 277\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m calc \u001b[38;5;129;01min\u001b[39;00m cell_calculators:\n\u001b[32m 278\u001b[39m \u001b[38;5;66;03m# Depending on the class of the calculator, a different version of\u001b[39;00m\n\u001b[32m 279\u001b[39m \u001b[38;5;66;03m# the enrich() method is called.\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m280\u001b[39m \u001b[43mcalc\u001b[49m\u001b[43m.\u001b[49m\u001b[43menrich\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 281\u001b[39m \u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 282\u001b[39m \u001b[43m \u001b[49m\u001b[43mnodes_to_enrich\u001b[49m\u001b[43m=\u001b[49m\u001b[43mnodes_to_process\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# self._added_cells,\u001b[39;49;00m\n\u001b[32m 283\u001b[39m \u001b[43m \u001b[49m\u001b[43medges_to_enrich\u001b[49m\u001b[43m=\u001b[49m\u001b[43medges_to_process\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# self._added_links,\u001b[39;49;00m\n\u001b[32m 284\u001b[39m \u001b[43m \u001b[49m\u001b[43mlineages_to_enrich\u001b[49m\u001b[43m=\u001b[49m\u001b[43mlins_to_process\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# self._added_lineages | self._modified_lineages\u001b[39;49;00m\n\u001b[32m 285\u001b[39m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 287\u001b[39m \u001b[38;5;66;03m# In case of modifications in the structure of some cell lineages,\u001b[39;00m\n\u001b[32m 288\u001b[39m \u001b[38;5;66;03m# we need to recompute the cycle lineages and their properties.\u001b[39;00m\n\u001b[32m 289\u001b[39m \u001b[38;5;66;03m# TODO: optimize so we don't have to recompute EVERYTHING for cycle lineages?\u001b[39;00m\n\u001b[32m 290\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m lin_ID \u001b[38;5;129;01min\u001b[39;00m lins_to_process:\n",
26222622
"\u001b[36mFile \u001b[39m\u001b[32m/media/lxenard/data/Code/pycellin/pycellin/pycellin/classes/property_calculator.py:181\u001b[39m, in \u001b[36mNodeLocalPropCalculator.enrich\u001b[39m\u001b[34m(self, data, nodes_to_enrich, **kwargs)\u001b[39m\n\u001b[32m 179\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m nid, lin_ID \u001b[38;5;129;01min\u001b[39;00m nodes_to_enrich:\n\u001b[32m 180\u001b[39m lin = lineages[lin_ID]\n\u001b[32m--> \u001b[39m\u001b[32m181\u001b[39m lin.nodes[nid][\u001b[38;5;28mself\u001b[39m.prop.identifier] = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mcompute\u001b[49m\u001b[43m(\u001b[49m\u001b[43mlin\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnid\u001b[49m\u001b[43m)\u001b[49m\n",
26232623
"\u001b[31mTypeError\u001b[39m: ParityCalculator_incorrect.compute() takes 2 positional arguments but 3 were given"
26242624
]
@@ -2646,7 +2646,7 @@
26462646
},
26472647
{
26482648
"cell_type": "code",
2649-
"execution_count": 12,
2649+
"execution_count": 30,
26502650
"metadata": {},
26512651
"outputs": [],
26522652
"source": [
@@ -2672,7 +2672,7 @@
26722672
},
26732673
{
26742674
"cell_type": "code",
2675-
"execution_count": 13,
2675+
"execution_count": 31,
26762676
"metadata": {},
26772677
"outputs": [
26782678
{
@@ -2735,14 +2735,14 @@
27352735
},
27362736
{
27372737
"cell_type": "code",
2738-
"execution_count": 14,
2738+
"execution_count": 32,
27392739
"metadata": {},
27402740
"outputs": [],
27412741
"source": [
27422742
"age_prop2 = pc.Property(\n",
27432743
" identifier=\"relative_age\",\n",
27442744
" name=\"relative age\",\n",
2745-
" description=\"Age of the cell since the beginning of the current cell cycle\",\n",
2745+
" description=\"Age of the cell since the start of the current cell cycle\",\n",
27462746
" provenance=\"custom\",\n",
27472747
" prop_type=\"node\",\n",
27482748
" lin_type=\"CellLineage\",\n",
@@ -2751,7 +2751,7 @@
27512751
")\n",
27522752
"\n",
27532753
"\n",
2754-
"class RelativeAgeCalculator(pc.NodeGlobalPropCalculator):\n",
2754+
"class MyRelativeAgeCalculator(pc.NodeGlobalPropCalculator):\n",
27552755
" def __init__(self, property: pc.Property, time_step: float):\n",
27562756
" # Call the parent __init__ method.\n",
27572757
" super().__init__(property)\n",
@@ -2781,17 +2781,17 @@
27812781
},
27822782
{
27832783
"cell_type": "code",
2784-
"execution_count": 15,
2784+
"execution_count": 33,
27852785
"metadata": {},
27862786
"outputs": [],
27872787
"source": [
2788-
"calc = RelativeAgeCalculator(age_prop2, model.get_time_step())\n",
2788+
"calc = MyRelativeAgeCalculator(age_prop2, model.get_time_step())\n",
27892789
"model.add_custom_property(calc)"
27902790
]
27912791
},
27922792
{
27932793
"cell_type": "code",
2794-
"execution_count": 16,
2794+
"execution_count": 34,
27952795
"metadata": {},
27962796
"outputs": [
27972797
{
@@ -4976,7 +4976,7 @@
49764976
"autorange": "reversed",
49774977
"showgrid": true,
49784978
"title": {
4979-
"text": "Time (frames)"
4979+
"text": "Time (timepoints)"
49804980
},
49814981
"zeroline": true
49824982
}
@@ -5001,7 +5001,7 @@
50015001
},
50025002
{
50035003
"cell_type": "code",
5004-
"execution_count": 17,
5004+
"execution_count": 35,
50055005
"metadata": {},
50065006
"outputs": [],
50075007
"source": [
@@ -5036,7 +5036,7 @@
50365036
},
50375037
{
50385038
"cell_type": "code",
5039-
"execution_count": 18,
5039+
"execution_count": 36,
50405040
"metadata": {},
50415041
"outputs": [
50425042
{
@@ -6199,8 +6199,9 @@
61996199
],
62006200
"source": [
62016201
"model.add_cycle_data()\n",
6202-
"# Division time is a Pycellin property, and it is needed to compute the growth rate.\n",
6203-
"model.add_division_time(in_time_unit=True)\n",
6202+
"# Division time is a Pycellin property, and it is needed to compute the growth rate,\n",
6203+
"# see line 23 in the code above.\n",
6204+
"model.add_division_time()\n",
62046205
"model.add_custom_property(GrowthRateCalculator(gr_prop))\n",
62056206
"model.update()\n",
62066207
"model.data.cycle_data[0].plot(node_hover_props=[\"cycle_ID\", \"growth_rate\"])"

0 commit comments

Comments
 (0)