From d93f3ad3ea1d25b1296a196504da2bf24f4dc5f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Guignard?= Date: Wed, 17 Jun 2026 11:40:03 +0200 Subject: [PATCH 1/2] README update --- README.md | 215 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 177 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index fa53cae..9600e0c 100644 --- a/README.md +++ b/README.md @@ -1,85 +1,224 @@ # LineageTree -Documentation available at [LineageTree Documentation](https://guignardlab.github.io/LineageTree/) +[![PyPI version](https://badge.fury.io/py/lineagetree.svg)](https://badge.fury.io/py/lineagetree) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) -This library allows to import and work with cell (but not limited to cells) lineage trees. -With LineageTree you can read from: +A Python library for importing, analyzing, and visualizing cell lineage trees. +Built for developmental biology workflows, it supports data from the most common cell-tracking algorithms and provides tools for spatial analysis, tree comparison, and visualization. -- TGMM algorithm outputs described in [Amat et al. 2014](https://www.nature.com/articles/nmeth.3036) -- TrackMate files described in [Tinevez et al. 2017](https://doi.org/10.1016/j.ymeth.2016.09.016) -- MaMuT files described in [Wolff et al. 2018](https://doi.org/10.7554/eLife.34410) -- SVF algorithm outputs described in [McDole, Guignard et al. 2018](https://doi.org/10.1016/j.cell.2018.09.031) -- ASTEC algorithm outputs described in [Guignard, Fiuza et al. 2020](https://doi.org/10.1126/science.aar5663) -- Data from the [Digital development Database](http://digital-development.org/index.html) described in [Du et al. 2014](https://www.cell.com/fulltext/S0092-8674(13)01542-0) and [Du et al. 2015](https://www.sciencedirect.com/science/article/pii/S1534580715004876?via%3Dihub) -- and few others +Full documentation: [guignardlab.github.io/LineageTree](https://guignardlab.github.io/LineageTree/) -## Basic usage +--- -Once installed the library can be called the following way (as an example): +## Features + +- **Multi-format I/O** — read from TGMM, MaMuT/TrackMate, Mastodon, ASTEC, SVF, SWC, BMF, and CSV; export to pickle (`.lT`), SVG, or Tulip (`.tlp`) +- **Tree analysis** — unordered tree edit distance (UTED), dynamic time warping (DTW), chain extraction, depth computation +- **Spatial analysis** — KD-tree indexing, Gabriel graphs, k-nearest neighbours, spatial density +- **Trajectory manipulation** — smooth trajectories, stabilise positions across time points +- **Visualization** — lineage plots, subtree views, DTW heatmaps, chain histograms + +--- + +## Installation + +```shell +pip install lineagetree +``` + +For the development version: + +```shell +pip install git+https://github.com/GuignardLab/LineageTree +``` + +Or from a local clone: + +```shell +pip install . +``` + +--- + +## Quick start + +### Loading a tree ```python from lineagetree import LineageTree + +# From a saved .lT file +lT = LineageTree.load("path/to/file.lT") + +# Inspect basic properties +print(lT.nodes) # frozenset of all node ids +print(lT.roots) # frozenset of root nodes +print(lT.leaves) # frozenset of leaf nodes +print(lT.t_b, lT.t_e) # first and last time points ``` -and one can then load lineage trees the following way: +### Reading from tracking software -For `.lT` files: +```python +from lineagetree import ( + read_from_ASTEC, + read_from_mamut_xml, + read_from_mastodon, + read_from_mastodon_csv, + read_from_tgmm_xml, + read_from_swc, +) + +# ASTEC (Guignard, Fiuza et al. 2020) +lT = read_from_ASTEC("path/to/ASTEC.pkl") + +# MaMuT / TrackMate (Wolff et al. 2018 / Tinevez et al. 2017) +lT = read_from_mamut_xml("path/to/MaMuT.xml") + +# Mastodon — binary format +lT = read_from_mastodon("path/to/file.mastodon") + +# Mastodon — CSV export +lT = read_from_mastodon_csv(["path/to/nodes.csv", "path/to/links.csv"]) + +# TGMM (Amat et al. 2014) — one XML per time point +lT = read_from_tgmm_xml("path/to/single_time_file{t:04d}.xml", tb=0, te=500) + +# SWC morphology files +lT = read_from_swc("path/to/morphology.swc") +``` + +### Building a tree programmatically ```python -lT = LineageTree.load('path/to/file.lT') +from lineagetree import LineageTree + +# From a successor dictionary +lT = LineageTree( + successor={0: [1, 2], 1: [3], 2: [], 3: []}, + time={0: 0, 1: 1, 2: 1, 3: 2}, + pos={0: [0, 0, 0], 1: [1, 0, 0], 2: [-1, 0, 0], 3: [1, 1, 0]}, + name="example", +) ``` -For ASTEC data: +### Tree navigation ```python -from lineagetree import read_from_ASTEC -lT = read_from_ASTEC('path/to/ASTEC.pkl') +# Traverse successors / predecessors +lT.get_successors(node) +lT.get_predecessors(node) + +# All nodes in a subtree rooted at `node` +lT.get_subtree_nodes({node}) + +# Unbroken chains (segments between division events) +lT.all_chains + +# Nodes at a specific time point +lT.nodes_at_t(t) ``` -For MaMuT or TrackMate: +### Saving ```python -from lineagetree import read_from_mamut_xml -lT = read_from_mamut_xml('path/to/MaMuT.xml') +lT.write("output.lT") # pickle +lT.write_to_svg("tree.svg") # SVG visualization +lT.write_to_tlp("tree.tlp") # Tulip graph format ``` -For TGMM: +### Tree comparison ```python -from lineagetree import read_from_tgmm_xml -lT = read_from_tgmm_xml('path/to/single_time_file{t:04d}.xml', tb=0, te=500) +# Unordered tree edit distance between two subtrees +dist = lT.unordered_tree_edit_distance(node_a, node_b) + +# Dynamic time warping on trajectories +score, path = lT.dtw(node_a, node_b) ``` -For Mastodon: +### Spatial analysis ```python -from lineagetree import read_from_mastodon -lT = read_from_mastodon('path/to/Mastodon.mastodon') +# KD-tree index at time t +idx = lT.idx3d(t) + +# k nearest neighbours of a node +neighbours = lT.k_nearest_neighbours(node, t, k=5) + +# Gabriel graph at time t +g = lT.gabriel_graph(t) + +# Local cell density +density = lT.spatial_density(t) ``` -or, for Mastodon csv file: +### Visualization ```python -from lineagetree import read_from_mastodon_csv -lT = read_from_mastodon_csv(['path/to/nodes.csv', 'path/to/links.csv']) +lT.plot_subtree(root_node) +lT.plot_all_lineages() +lT.draw_tree_graph() + +# DTW visualizations +lT.plot_dtw_trajectory(node_a, node_b) +lT.plot_dtw_heatmap(node_a, node_b) ``` -## Quick install +### Multi-tree workflows + +```python +from lineagetree import LineageTreeManager -To quickly install the library together with its dependencies one can run: +manager = LineageTreeManager() +manager["embryo_1"] = lT_1 +manager["embryo_2"] = lT_2 -```shell -pip install LineageTree +# Pairwise UTED across all stored trees +manager.compute_distances() ``` -or, for the latest version if you have cloned the directory: +--- + +## Supported input formats + +| Format | Algorithm / Tool | Reference | +|--------|-----------------|-----------| +| `.xml` (TGMM) | TGMM | [Amat et al. 2014](https://www.nature.com/articles/nmeth.3036) | +| `.xml` (MaMuT/TrackMate) | MaMuT / TrackMate | [Wolff et al. 2018](https://doi.org/10.7554/eLife.34410) / [Tinevez et al. 2017](https://doi.org/10.1016/j.ymeth.2016.09.016) | +| `.mastodon` | Mastodon | — | +| `.pkl` (ASTEC) | ASTEC | [Guignard, Fiuza et al. 2020](https://doi.org/10.1126/science.aar5663) | +| `.lT` | LineageTree native | — | +| `.swc` | SWC morphology | — | +| `.bmf` | Binary mesh format | — | +| `.csv` | Generic / Mastodon CSV | — | +| `.txt` | C. elegans specific | [Du et al. 2014](https://www.cell.com/fulltext/S0092-8674(13)01542-0) | + +--- + +## Development ```shell -pip install . +pip install -e ".[dev]" +pytest ``` -or for the latest version wihtout cloning the directory +To build the documentation: ```shell -pip install git+https://github.com/leoguignard/LineageTree +pip install -e ".[doc]" +cd docs && make html ``` + +--- + +## Citation + +If you use LineageTree in your research, please cite the relevant tracking algorithm paper for the data you loaded, and consider citing this library directly. + +--- + +## License + +MIT — see [LICENSE](LICENSE). From 29671bc0ce895f146a63333b1ee08d4d4eb52e50 Mon Sep 17 00:00:00 2001 From: BadPrograms Date: Wed, 17 Jun 2026 12:53:10 +0200 Subject: [PATCH 2/2] fix manager --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9600e0c..9572f0b 100644 --- a/README.md +++ b/README.md @@ -172,11 +172,11 @@ lT.plot_dtw_heatmap(node_a, node_b) from lineagetree import LineageTreeManager manager = LineageTreeManager() -manager["embryo_1"] = lT_1 -manager["embryo_2"] = lT_2 +manager.add(lT_1) +manager.add(lT_2) -# Pairwise UTED across all stored trees -manager.compute_distances() +# Compare subtrees across lineages +manager.cross_lineage_edit_distance(root_of_lT1, name_of_lT1,root_of_lT2, name_of_lT2) ``` ---