LineageTree 1.8.0__py3-none-any.whl → 2.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- LineageTree/__init__.py +27 -2
- LineageTree/legacy/export_csv.py +70 -0
- LineageTree/legacy/to_lineajea.py +30 -0
- LineageTree/legacy/to_motile.py +36 -0
- LineageTree/lineageTree.py +2298 -1471
- LineageTree/lineageTreeManager.py +767 -79
- LineageTree/loaders.py +942 -864
- LineageTree/test/test_lineageTree.py +634 -0
- LineageTree/test/test_uted.py +233 -0
- LineageTree/tree_approximation.py +488 -0
- LineageTree/utils.py +103 -103
- lineagetree-2.0.3.dist-info/METADATA +130 -0
- lineagetree-2.0.3.dist-info/RECORD +16 -0
- {LineageTree-1.8.0.dist-info → lineagetree-2.0.3.dist-info}/WHEEL +1 -1
- LineageTree/tree_styles.py +0 -334
- LineageTree-1.8.0.dist-info/METADATA +0 -156
- LineageTree-1.8.0.dist-info/RECORD +0 -11
- {LineageTree-1.8.0.dist-info → lineagetree-2.0.3.dist-info/licenses}/LICENSE +0 -0
- {LineageTree-1.8.0.dist-info → lineagetree-2.0.3.dist-info}/top_level.txt +0 -0
LineageTree/utils.py
CHANGED
@@ -1,122 +1,88 @@
|
|
1
|
-
import
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
pos=lT.pos[time_node],
|
32
|
-
score=1,
|
33
|
-
)
|
34
|
-
|
35
|
-
motile.add_cand_edges(fmt, max_dist, max_skip_frames=max_skip_frames)
|
36
|
-
|
37
|
-
return fmt
|
38
|
-
|
39
|
-
|
40
|
-
def write_csv_from_lT_to_lineaja(
|
41
|
-
lT, path_to, start: int = 0, finish: int = 300
|
42
|
-
):
|
43
|
-
csv_dict = {}
|
44
|
-
for time in range(start, finish):
|
45
|
-
for node in lT.time_nodes[time]:
|
46
|
-
csv_dict[node] = {"pos": lT.pos[node], "t": time}
|
47
|
-
with open(path_to, "w", newline="\n") as file:
|
48
|
-
fieldnames = [
|
49
|
-
"time",
|
50
|
-
"positions_x",
|
51
|
-
"positions_y",
|
52
|
-
"positions_z",
|
53
|
-
"id",
|
54
|
-
]
|
55
|
-
writer = csv.DictWriter(file, fieldnames=fieldnames)
|
56
|
-
writer.writeheader()
|
57
|
-
for node in csv_dict:
|
58
|
-
writer.writerow(
|
59
|
-
{
|
60
|
-
"time": csv_dict[node]["t"],
|
61
|
-
"positions_z": csv_dict[node]["pos"][0],
|
62
|
-
"positions_y": csv_dict[node]["pos"][1],
|
63
|
-
"positions_x": csv_dict[node]["pos"][2],
|
64
|
-
"id": node,
|
65
|
-
}
|
66
|
-
)
|
67
|
-
|
68
|
-
|
69
|
-
def create_links_and_cycles(lT: lineageTree, roots=None):
|
70
|
-
"""Generates a dictionary containing the links and the lengths of each branch.
|
71
|
-
Similar to simple tree, mainly used for tree manip app.
|
72
|
-
|
73
|
-
Args:
|
74
|
-
roots (Union[list,set,int]): The roots from which the tree will be generated.
|
75
|
-
|
76
|
-
Returns:
|
77
|
-
dict: A dictionary with keys "links" and "times" which contains the connections all cells and their branch
|
78
|
-
length.
|
1
|
+
from collections.abc import Iterable
|
2
|
+
|
3
|
+
from LineageTree import lineageTree, tree_approximation
|
4
|
+
|
5
|
+
|
6
|
+
def create_links_and_chains(
|
7
|
+
lT: lineageTree,
|
8
|
+
roots: int | Iterable | None = None,
|
9
|
+
end_time: int | None = None,
|
10
|
+
) -> dict[str, dict]:
|
11
|
+
"""Generates a dictionary containing all the edges (from start of lifetime to end not the intermediate timepoints)
|
12
|
+
of a subtree spawned by node/s and their duration
|
13
|
+
|
14
|
+
|
15
|
+
Parameters
|
16
|
+
----------
|
17
|
+
lT : lineageTree
|
18
|
+
The lineagetree that the user is working on
|
19
|
+
roots : int or Iterable, optional
|
20
|
+
The root/s from which the tree/s will be generated, if 'None' all the roots will be selected.
|
21
|
+
end_time : int, optional
|
22
|
+
The last timepoint to be considered, if 'None' the last timepoint of the dataset (t_e) is considered, by default None.
|
23
|
+
|
24
|
+
Returns
|
25
|
+
-------
|
26
|
+
dict mapping str to set or dict mapping int to list or int
|
27
|
+
A dictionary that contains:
|
28
|
+
- "links": The dictionary that contains the hierarchy of the nodes (only start and end of each chain)
|
29
|
+
- "times": The time distance between the start and the end of a chain
|
30
|
+
- "roots": The roots used
|
79
31
|
"""
|
80
32
|
if roots is None:
|
81
33
|
to_do = set(lT.roots)
|
82
|
-
elif isinstance(roots,
|
34
|
+
elif isinstance(roots, Iterable):
|
83
35
|
to_do = set(roots)
|
84
36
|
else:
|
85
37
|
to_do = {int(roots)}
|
38
|
+
if end_time is None:
|
39
|
+
end_time = lT.t_e
|
86
40
|
times = {}
|
87
41
|
links = {}
|
88
42
|
while to_do:
|
89
43
|
curr = to_do.pop()
|
90
|
-
cyc = lT.get_successors(curr)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
44
|
+
cyc = lT.get_successors(curr, end_time=end_time)
|
45
|
+
if cyc[-1] != curr or lT.time[cyc[-1]] <= end_time:
|
46
|
+
last = cyc[-1]
|
47
|
+
times[curr] = len(cyc)
|
48
|
+
if last != curr:
|
49
|
+
links[curr] = [last]
|
50
|
+
else:
|
51
|
+
links[curr] = []
|
52
|
+
succ = lT._successor.get(last)
|
53
|
+
if succ:
|
54
|
+
times[cyc[-1]] = 0
|
55
|
+
to_do.update(succ)
|
101
56
|
links[last] = succ
|
102
57
|
return {"links": links, "times": times, "root": roots}
|
103
58
|
|
104
59
|
|
105
60
|
def hierarchical_pos(
|
106
61
|
lnks_tms: dict, root, width=1000, vert_gap=2, xcenter=0, ycenter=0
|
107
|
-
):
|
108
|
-
"""Calculates the position of each node on
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
62
|
+
) -> dict[int, list[float]] | None:
|
63
|
+
"""Calculates the position of each node on the tree graph.
|
64
|
+
|
65
|
+
Parameters
|
66
|
+
----------
|
67
|
+
lnks_tms : dict
|
68
|
+
a dictionary created by create_links_and_chains.
|
69
|
+
root : _type_
|
70
|
+
The id of the node, usually it exists inside lnks_tms dictionary, however you may use your own root.
|
71
|
+
width : int, optional
|
72
|
+
Max width, will not change the graph but interacting with the graph takes this distance into account, by default 1000
|
73
|
+
vert_gap : int, optional
|
74
|
+
How far downwards each timepoint will go, by default 2
|
75
|
+
xcenter : int, optional
|
76
|
+
Where the root will be placed on the x axis, by default 0
|
77
|
+
ycenter : int, optional
|
78
|
+
Where the root will be placed on the y axis, by default 0
|
79
|
+
|
80
|
+
Returns
|
81
|
+
-------
|
82
|
+
dict mapping int to list of float
|
83
|
+
Provides a dictionary that contains the id of each node as keys and its 2-d position on the
|
84
|
+
tree graph as values.
|
85
|
+
If the root requested does not exists, None is then returned
|
120
86
|
"""
|
121
87
|
to_do = [root]
|
122
88
|
if root not in lnks_tms["times"]:
|
@@ -152,3 +118,37 @@ def hierarchical_pos(
|
|
152
118
|
prev_width[curr] / 2,
|
153
119
|
)
|
154
120
|
return pos_node
|
121
|
+
|
122
|
+
|
123
|
+
def convert_style_to_number(
|
124
|
+
style: str | tree_approximation.TreeApproximationTemplate,
|
125
|
+
downsample: int | None,
|
126
|
+
) -> int:
|
127
|
+
"""Converts tree_style and downsampling to a single number.
|
128
|
+
|
129
|
+
Parameters
|
130
|
+
----------
|
131
|
+
style : str
|
132
|
+
the tree style
|
133
|
+
downsample : int
|
134
|
+
the downsampling factor
|
135
|
+
|
136
|
+
Returns
|
137
|
+
-------
|
138
|
+
int
|
139
|
+
A number which serves as ID if the tree style and downsampling used.
|
140
|
+
"""
|
141
|
+
style_dict = {
|
142
|
+
"full": 0,
|
143
|
+
"simple": -1,
|
144
|
+
"normalized_simple": -2,
|
145
|
+
"mini": -1000,
|
146
|
+
}
|
147
|
+
if style == "downsampled" and downsample is not None:
|
148
|
+
return downsample
|
149
|
+
elif not isinstance(style, str) and issubclass(
|
150
|
+
style, tree_approximation.TreeApproximationTemplate
|
151
|
+
):
|
152
|
+
return hash(style.__name__)
|
153
|
+
else:
|
154
|
+
return style_dict[style]
|
@@ -0,0 +1,130 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: LineageTree
|
3
|
+
Version: 2.0.3
|
4
|
+
Summary: Structure for Lineage Trees
|
5
|
+
Author: Giannis Liaskas, Christopher Mazzerbo
|
6
|
+
Author-email: Léo Guignard <leo.guignard@univ-amu.fr>
|
7
|
+
Maintainer-email: Léo Guignard <leo.guignard@univ-amu.fr>
|
8
|
+
License-Expression: MIT
|
9
|
+
Project-URL: Bug Tracker, https://github.com/GuignardLab/LineageTree/issues
|
10
|
+
Project-URL: Documentation, https://github.com/GuignardLab/LineageTree#README.md
|
11
|
+
Project-URL: Source Code, https://github.com/GuignardLab/LineageTree
|
12
|
+
Project-URL: User Support, https://github.com/GuignardLab/LineageTree/issues
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
14
|
+
Classifier: Intended Audience :: Developers
|
15
|
+
Classifier: Operating System :: OS Independent
|
16
|
+
Classifier: Programming Language :: Python
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
23
|
+
Requires-Python: >=3.10
|
24
|
+
Description-Content-Type: text/markdown
|
25
|
+
License-File: LICENSE
|
26
|
+
Requires-Dist: scipy>=1.9
|
27
|
+
Requires-Dist: numpy>=1.23
|
28
|
+
Requires-Dist: mastodon-reader
|
29
|
+
Requires-Dist: matplotlib
|
30
|
+
Requires-Dist: edist
|
31
|
+
Requires-Dist: svgwrite
|
32
|
+
Provides-Extra: dev
|
33
|
+
Requires-Dist: pytest; extra == "dev"
|
34
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
35
|
+
Requires-Dist: tox; extra == "dev"
|
36
|
+
Requires-Dist: black; extra == "dev"
|
37
|
+
Requires-Dist: ruff; extra == "dev"
|
38
|
+
Requires-Dist: bumpver; extra == "dev"
|
39
|
+
Provides-Extra: doc
|
40
|
+
Requires-Dist: sphinx-rtd-theme; extra == "doc"
|
41
|
+
Requires-Dist: myst-parser; extra == "doc"
|
42
|
+
Requires-Dist: sphinx_book_theme; extra == "doc"
|
43
|
+
Provides-Extra: test
|
44
|
+
Requires-Dist: pytest; extra == "test"
|
45
|
+
Requires-Dist: pytest-cov; extra == "test"
|
46
|
+
Dynamic: license-file
|
47
|
+
|
48
|
+
# LineageTree
|
49
|
+
|
50
|
+
This library allows to import and work with cell (but not limited to cells) lineage trees.
|
51
|
+
With LineageTree you can read from:
|
52
|
+
|
53
|
+
- TGMM algorithm outputs described in [Amat et al. 2014](https://www.nature.com/articles/nmeth.3036)
|
54
|
+
- TrackMate files described in [Tinevez et al. 2017](https://doi.org/10.1016/j.ymeth.2016.09.016)
|
55
|
+
- MaMuT files described in [Wolff et al. 2018](https://doi.org/10.7554/eLife.34410)
|
56
|
+
- SVF algorithm outputs described in [McDole, Guignard et al. 2018](https://doi.org/10.1016/j.cell.2018.09.031)
|
57
|
+
- ASTEC algorithm outputs described in [Guignard, Fiuza et al. 2020](https://doi.org/10.1126/science.aar5663)
|
58
|
+
- 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)
|
59
|
+
- and few others
|
60
|
+
|
61
|
+
## Basic usage
|
62
|
+
|
63
|
+
Once installed the library can be called the following way (as an example):
|
64
|
+
|
65
|
+
```python
|
66
|
+
from LineageTree import lineageTree
|
67
|
+
```
|
68
|
+
|
69
|
+
and one can then load lineage trees the following way:
|
70
|
+
|
71
|
+
For `.lT` files:
|
72
|
+
|
73
|
+
```python
|
74
|
+
lT = lineageTree.load('path/to/file.lT')
|
75
|
+
```
|
76
|
+
|
77
|
+
For ASTEC data:
|
78
|
+
|
79
|
+
```python
|
80
|
+
from LineageTree import read_from_ASTEC
|
81
|
+
lT = read_from_ASTEC('path/to/ASTEC.pkl')
|
82
|
+
```
|
83
|
+
|
84
|
+
For MaMuT or TrackMate:
|
85
|
+
|
86
|
+
```python
|
87
|
+
from LineageTree import read_from_mamut_xml
|
88
|
+
lT = read_from_mamut_xml('path/to/MaMuT.xml')
|
89
|
+
```
|
90
|
+
|
91
|
+
For TGMM:
|
92
|
+
|
93
|
+
```python
|
94
|
+
from LineageTree import read_from_tgmm_xml
|
95
|
+
lT = read_from_tgmm_xml('path/to/single_time_file{t:04d}.xml', tb=0, te=500)
|
96
|
+
```
|
97
|
+
|
98
|
+
For Mastodon:
|
99
|
+
|
100
|
+
```python
|
101
|
+
from LineageTree import read_from_mastodon
|
102
|
+
lT = read_from_mastodon('path/to/Mastodon.mastodon')
|
103
|
+
```
|
104
|
+
|
105
|
+
or, for Mastodon csv file:
|
106
|
+
|
107
|
+
```python
|
108
|
+
from LineageTree import read_from_mastodon_csv
|
109
|
+
lT = read_from_mastodon_csv(['path/to/nodes.csv', 'path/to/links.csv'])
|
110
|
+
```
|
111
|
+
|
112
|
+
## Quick install
|
113
|
+
|
114
|
+
To quickly install the library together with its dependencies one can run:
|
115
|
+
|
116
|
+
```shell
|
117
|
+
pip install LineageTree
|
118
|
+
```
|
119
|
+
|
120
|
+
or, for the latest version if you have cloned the directory:
|
121
|
+
|
122
|
+
```shell
|
123
|
+
pip install .
|
124
|
+
```
|
125
|
+
|
126
|
+
or for the latest version wihtout cloning the directory
|
127
|
+
|
128
|
+
```shell
|
129
|
+
pip install git+https://github.com/leoguignard/LineageTree
|
130
|
+
```
|
@@ -0,0 +1,16 @@
|
|
1
|
+
LineageTree/__init__.py,sha256=DBw4aJTm7ttYYm6FuL9b_Q1108W9YU_dox0oIoDiLUU,749
|
2
|
+
LineageTree/lineageTree.py,sha256=3es3wPN9O0Eaqw-YC-uMq4tukpQPkW7DbTl9ujvZkXs,125993
|
3
|
+
LineageTree/lineageTreeManager.py,sha256=kyHeoQ3EKMNnlSJG-v0K67j8RHECNIk-dUzdP0za3as,32406
|
4
|
+
LineageTree/loaders.py,sha256=lcLEvLGA4Jn0QwBId__kHpQ3i4axDT5VEyACGnDNrBg,30255
|
5
|
+
LineageTree/tree_approximation.py,sha256=61Omn0gUaRiNTDcIucDM4DUPBW5voXRxCZQ0uYGRDSg,16170
|
6
|
+
LineageTree/utils.py,sha256=EOH2MGlBH3cFs8DVOX-3fJRwoj0ZmiE_nPkAjzWXK48,5124
|
7
|
+
LineageTree/legacy/export_csv.py,sha256=cJ1R3GCGEy9Oey73jbFhoKRGTonNbqg229fVnGm_FuU,2009
|
8
|
+
LineageTree/legacy/to_lineajea.py,sha256=iZyZTsrvWYHkGJ8npf91lQPrXPgKouiy7Zrywx5Lkkw,926
|
9
|
+
LineageTree/legacy/to_motile.py,sha256=4AC9BmGa-hpqt8_x6HTR_XqCrTERlKo9WwYHUFtheM0,860
|
10
|
+
LineageTree/test/test_lineageTree.py,sha256=d5uucokzE7OWQirsW7XxaGEgeRszQ5KICbAYhriXEQo,16492
|
11
|
+
LineageTree/test/test_uted.py,sha256=Vl7uNGZp57XUD3v3SHRJtXhb0Lte8mDjpOtEKp_dxt0,6496
|
12
|
+
lineagetree-2.0.3.dist-info/licenses/LICENSE,sha256=IKncNCNpq93Kq7Ywg1V4I9Bu_99VMK-mX1EJyjTKLyc,1068
|
13
|
+
lineagetree-2.0.3.dist-info/METADATA,sha256=GOrhmJPx3qWTCqszjsjHQ2vS-43DZ0gDurjfpUZ8US8,4081
|
14
|
+
lineagetree-2.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
15
|
+
lineagetree-2.0.3.dist-info/top_level.txt,sha256=CCqPCTX76zPTEUagUgTWbLaZun8752n59iOOwfUlvxs,12
|
16
|
+
lineagetree-2.0.3.dist-info/RECORD,,
|