Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b62ec95
Add geff files to gitignore
lxenard Jul 25, 2025
e409be5
Add folder structure for geff io
lxenard Jul 25, 2025
341f1ef
Put explicit units in TM XML files
lxenard Jul 25, 2025
37e0030
Move check_fusions() to utils.py
lxenard Jul 25, 2025
99632df
Add pytest.ini_options
lxenard Jul 26, 2025
558df05
Rename and move common functions in loaders and tests
lxenard Jul 26, 2025
6428ecd
Extract update feature names related functions from TM loader, rename…
lxenard Jul 26, 2025
947a568
Improve _update_node_feature_key()
lxenard Jul 26, 2025
373c37d
Reimplement _update_lineage_ID_key() into _update_lineages_IDs_key()
lxenard Jul 26, 2025
1fcd697
WIP geff loader main
lxenard Jul 29, 2025
60c352b
WIP GEFF loader
lxenard Aug 6, 2025
30cbd00
Merge branch 'main' into feature/geff_io
lxenard Sep 11, 2025
075c271
Replace features by properties
lxenard Sep 11, 2025
3eda3b4
WIP extraction of lineage props metadata
lxenard Sep 11, 2025
3ef02e5
Finalize extraction of properties metadata
lxenard Sep 12, 2025
8025f0a
Add missing docstrings
lxenard Sep 12, 2025
87ba1f8
Raise Error when geff graph is undirected
lxenard Sep 12, 2025
c55fd89
WIP GEFF exporter
lxenard Sep 15, 2025
e3c4da1
Update pyproject.toml with geff
lxenard Sep 16, 2025
ae71656
Add Model.has_cycle_data() method
lxenard Sep 16, 2025
28b9925
Working GEFF exporter
lxenard Sep 16, 2025
8c80a1e
Add missing info in __init__.py files
lxenard Sep 16, 2025
d91f806
Ugly WIP on GEFF loader
lxenard Sep 16, 2025
dcf29a5
Less wonky GEFF loader
lxenard Sep 17, 2025
5058277
Fix incorrect typing
lxenard Sep 17, 2025
0e884d8
Fix incorrect docstrings and imports order
lxenard Sep 17, 2025
c05e31e
Small improvments on GEFF exporter
lxenard Sep 17, 2025
d4b2738
Add parameter to control validation of GEFF schema
lxenard Sep 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ cov.xml

# Data
sample_data/FakeTracks.tif
sample_data/**.geff
16 changes: 8 additions & 8 deletions notebooks/Custom properties.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -2614,13 +2614,13 @@
"evalue": "ParityCalculator_incorrect.compute() takes 2 positional arguments but 3 were given",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[1;32mIn[11], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m calc \u001b[38;5;241m=\u001b[39m ParityCalculator_incorrect(prop_incorrect)\n\u001b[0;32m 2\u001b[0m model\u001b[38;5;241m.\u001b[39madd_custom_property(calc)\n\u001b[1;32m----> 3\u001b[0m \u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mupdate\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[1;32mE:\\Code\\pycellin\\pycellin\\pycellin\\classes\\model.py:533\u001b[0m, in \u001b[0;36mModel.update\u001b[1;34m(self, props_to_update)\u001b[0m\n\u001b[0;32m 525\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m\n\u001b[0;32m 527\u001b[0m \u001b[38;5;66;03m# self.data._freeze_lineage_data()\u001b[39;00m\n\u001b[0;32m 528\u001b[0m \n\u001b[0;32m 529\u001b[0m \u001b[38;5;66;03m# TODO: need to handle all the errors that can be raised\u001b[39;00m\n\u001b[0;32m 530\u001b[0m \u001b[38;5;66;03m# by the updater methods to avoid incoherent states.\u001b[39;00m\n\u001b[0;32m 531\u001b[0m \u001b[38;5;66;03m# => saving a copy of the model before the update so we can roll back?\u001b[39;00m\n\u001b[1;32m--> 533\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_updater\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_update\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprops_to_update\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[1;32mE:\\Code\\pycellin\\pycellin\\pycellin\\classes\\updater.py:194\u001b[0m, in \u001b[0;36mModelUpdater._update\u001b[1;34m(self, data, props_to_update)\u001b[0m\n\u001b[0;32m 190\u001b[0m \u001b[38;5;66;03m# Recompute the properties as needed.\u001b[39;00m\n\u001b[0;32m 191\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m calc \u001b[38;5;129;01min\u001b[39;00m cell_calculators:\n\u001b[0;32m 192\u001b[0m \u001b[38;5;66;03m# Depending on the class of the calculator, a different version of\u001b[39;00m\n\u001b[0;32m 193\u001b[0m \u001b[38;5;66;03m# the enrich() method is called.\u001b[39;00m\n\u001b[1;32m--> 194\u001b[0m \u001b[43mcalc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43menrich\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 195\u001b[0m \u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 196\u001b[0m \u001b[43m \u001b[49m\u001b[43mnodes_to_enrich\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_added_cells\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 197\u001b[0m \u001b[43m \u001b[49m\u001b[43medges_to_enrich\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_added_links\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 198\u001b[0m \u001b[43m \u001b[49m\u001b[43mlineages_to_enrich\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_added_lineages\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m|\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_modified_lineages\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 199\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 201\u001b[0m \u001b[38;5;66;03m# In case of modifications in the structure of some cell lineages,\u001b[39;00m\n\u001b[0;32m 202\u001b[0m \u001b[38;5;66;03m# we need to recompute the cycle lineages and their properties.\u001b[39;00m\n\u001b[0;32m 203\u001b[0m \u001b[38;5;66;03m# TODO: optimize so we don't have to recompute EVERYTHING for cycle lineages?\u001b[39;00m\n\u001b[0;32m 204\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m lin_ID \u001b[38;5;129;01min\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_modified_lineages \u001b[38;5;241m|\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_added_lineages) \u001b[38;5;241m-\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_removed_lineages:\n",
"File \u001b[1;32mE:\\Code\\pycellin\\pycellin\\pycellin\\classes\\property_calculator.py:181\u001b[0m, in \u001b[0;36mNodeLocalPropCalculator.enrich\u001b[1;34m(self, data, nodes_to_enrich, **kwargs)\u001b[0m\n\u001b[0;32m 179\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m nid, lin_ID \u001b[38;5;129;01min\u001b[39;00m nodes_to_enrich:\n\u001b[0;32m 180\u001b[0m lin \u001b[38;5;241m=\u001b[39m lineages[lin_ID]\n\u001b[1;32m--> 181\u001b[0m lin\u001b[38;5;241m.\u001b[39mnodes[nid][\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprop\u001b[38;5;241m.\u001b[39midentifier] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;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",
"\u001b[1;31mTypeError\u001b[0m: ParityCalculator_incorrect.compute() takes 2 positional arguments but 3 were given"
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
"\u001b[31mTypeError\u001b[39m Traceback (most recent call last)",
"\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",
"\u001b[36mFile \u001b[39m\u001b[32m/media/lxenard/data/Code/pycellin/pycellin/pycellin/classes/model.py:533\u001b[39m, in \u001b[36mModel.update\u001b[39m\u001b[34m(self, props_to_update)\u001b[39m\n\u001b[32m 525\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m\n\u001b[32m 527\u001b[39m \u001b[38;5;66;03m# self.data._freeze_lineage_data()\u001b[39;00m\n\u001b[32m 528\u001b[39m \n\u001b[32m 529\u001b[39m \u001b[38;5;66;03m# TODO: need to handle all the errors that can be raised\u001b[39;00m\n\u001b[32m 530\u001b[39m \u001b[38;5;66;03m# by the updater methods to avoid incoherent states.\u001b[39;00m\n\u001b[32m 531\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[32m533\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",
"\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",
"\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",
"\u001b[31mTypeError\u001b[39m: ParityCalculator_incorrect.compute() takes 2 positional arguments but 3 were given"
]
}
],
Expand Down Expand Up @@ -6223,7 +6223,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.18"
"version": "3.11.13"
}
},
"nbformat": 4,
Expand Down
Loading
Loading