phylogenie 3.1.2__py3-none-any.whl → 3.1.4__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.
- phylogenie/draw.py +17 -14
- phylogenie/main.py +2 -6
- phylogenie/treesimulator/io/nexus.py +7 -4
- {phylogenie-3.1.2.dist-info → phylogenie-3.1.4.dist-info}/METADATA +12 -17
- {phylogenie-3.1.2.dist-info → phylogenie-3.1.4.dist-info}/RECORD +19 -18
- {phylogenie-3.1.2.dist-info → phylogenie-3.1.4.dist-info}/WHEEL +2 -1
- phylogenie-3.1.4.dist-info/entry_points.txt +2 -0
- phylogenie-3.1.4.dist-info/top_level.txt +1 -0
- phylogenie-3.1.2.dist-info/entry_points.txt +0 -3
- {phylogenie-3.1.2.dist-info → phylogenie-3.1.4.dist-info/licenses}/LICENSE.txt +0 -0
phylogenie/draw.py
CHANGED
|
@@ -5,6 +5,7 @@ import matplotlib.colors as mcolors
|
|
|
5
5
|
import matplotlib.patches as mpatches
|
|
6
6
|
import matplotlib.pyplot as plt
|
|
7
7
|
from matplotlib.axes import Axes
|
|
8
|
+
from matplotlib.colors import Colormap
|
|
8
9
|
from mpl_toolkits.axes_grid1.inset_locator import inset_axes # pyright: ignore
|
|
9
10
|
|
|
10
11
|
from phylogenie.treesimulator import Tree, get_node_depth_levels, get_node_depths
|
|
@@ -48,10 +49,10 @@ def _draw_colored_tree(tree: Tree, ax: Axes, colors: Color | dict[Tree, Color])
|
|
|
48
49
|
def draw_tree(
|
|
49
50
|
tree: Tree,
|
|
50
51
|
ax: Axes | None = None,
|
|
51
|
-
color_by: str | dict[
|
|
52
|
+
color_by: str | dict[str, Any] | None = None,
|
|
52
53
|
coloring: str | Coloring | None = None,
|
|
53
54
|
default_color: Color = "black",
|
|
54
|
-
|
|
55
|
+
colormap: str | Colormap | None = None,
|
|
55
56
|
vmin: float | None = None,
|
|
56
57
|
vmax: float | None = None,
|
|
57
58
|
show_legend: bool = True,
|
|
@@ -67,17 +68,22 @@ def draw_tree(
|
|
|
67
68
|
if color_by is None:
|
|
68
69
|
return _draw_colored_tree(tree, ax, colors=default_color)
|
|
69
70
|
|
|
70
|
-
if isinstance(color_by,
|
|
71
|
-
features = {node: color_by[node] for node in tree if node in color_by}
|
|
72
|
-
else:
|
|
71
|
+
if isinstance(color_by, str):
|
|
73
72
|
features = {node: node[color_by] for node in tree if color_by in node.metadata}
|
|
73
|
+
else:
|
|
74
|
+
features = {node: color_by[node.name] for node in tree if node.name in color_by}
|
|
75
|
+
values = list(features.values())
|
|
74
76
|
|
|
75
77
|
if coloring is None:
|
|
76
78
|
coloring = (
|
|
77
79
|
Coloring.CONTINUOUS
|
|
78
|
-
if any(isinstance(f, float) for f in
|
|
80
|
+
if any(isinstance(f, float) for f in values)
|
|
79
81
|
else Coloring.DISCRETE
|
|
80
82
|
)
|
|
83
|
+
if colormap is None:
|
|
84
|
+
colormap = "tab20" if coloring == Coloring.DISCRETE else "viridis"
|
|
85
|
+
if isinstance(colormap, str):
|
|
86
|
+
colormap = plt.get_cmap(colormap)
|
|
81
87
|
|
|
82
88
|
def _get_colors(feature_map: Callable[[Any], Color]) -> dict[Tree, Color]:
|
|
83
89
|
return {
|
|
@@ -86,14 +92,12 @@ def draw_tree(
|
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
if coloring == Coloring.DISCRETE:
|
|
89
|
-
if any(isinstance(f, float) for f in
|
|
95
|
+
if any(isinstance(f, float) for f in values):
|
|
90
96
|
raise ValueError(
|
|
91
97
|
"Discrete coloring selected but feature values are not all categorical."
|
|
92
98
|
)
|
|
93
|
-
|
|
94
|
-
colormap = plt.get_cmap("tab20" if cmap is None else cmap)
|
|
95
99
|
feature_colors = {
|
|
96
|
-
f: mcolors.to_hex(colormap(i)) for i, f in enumerate(set(
|
|
100
|
+
f: mcolors.to_hex(colormap(i)) for i, f in enumerate(set(values))
|
|
97
101
|
}
|
|
98
102
|
colors = _get_colors(lambda f: feature_colors[f])
|
|
99
103
|
|
|
@@ -114,10 +118,9 @@ def draw_tree(
|
|
|
114
118
|
return _draw_colored_tree(tree, ax, colors)
|
|
115
119
|
|
|
116
120
|
if coloring == Coloring.CONTINUOUS:
|
|
117
|
-
vmin = min(
|
|
118
|
-
vmax = max(
|
|
121
|
+
vmin = min(values) if vmin is None else vmin
|
|
122
|
+
vmax = max(values) if vmax is None else vmax
|
|
119
123
|
norm = mcolors.Normalize(vmin=vmin, vmax=vmax)
|
|
120
|
-
colormap = plt.get_cmap("viridis" if cmap is None else cmap)
|
|
121
124
|
colors = _get_colors(lambda f: colormap(norm(float(f))))
|
|
122
125
|
|
|
123
126
|
if show_hist:
|
|
@@ -127,7 +130,7 @@ def draw_tree(
|
|
|
127
130
|
hist_ax = inset_axes(ax, **default_hist_axes_kwargs) # pyright: ignore
|
|
128
131
|
|
|
129
132
|
hist_kwargs = {} if hist_kwargs is None else hist_kwargs
|
|
130
|
-
_, bins, patches = hist_ax.hist(
|
|
133
|
+
_, bins, patches = hist_ax.hist(values, **hist_kwargs) # pyright: ignore
|
|
131
134
|
|
|
132
135
|
for patch, b0, b1 in zip( # pyright: ignore
|
|
133
136
|
patches, bins[:-1], bins[1:] # pyright: ignore
|
phylogenie/main.py
CHANGED
|
@@ -15,14 +15,10 @@ def run(config_path: str) -> None:
|
|
|
15
15
|
if os.path.isdir(config_path):
|
|
16
16
|
for config_file in glob(os.path.join(config_path, "**/*.yaml"), recursive=True):
|
|
17
17
|
with open(config_file, "r") as f:
|
|
18
|
-
|
|
19
|
-
generator = adapter.validate_python(config)
|
|
20
|
-
generator.generate()
|
|
18
|
+
adapter.validate_python(safe_load(f)).generate()
|
|
21
19
|
else:
|
|
22
20
|
with open(config_path, "r") as f:
|
|
23
|
-
|
|
24
|
-
generator = adapter.validate_python(config)
|
|
25
|
-
generator.generate()
|
|
21
|
+
adapter.validate_python(safe_load(f)).generate()
|
|
26
22
|
|
|
27
23
|
|
|
28
24
|
def main() -> None:
|
|
@@ -15,9 +15,9 @@ def _parse_translate_block(lines: Iterator[str]) -> dict[str, str]:
|
|
|
15
15
|
if ";" in line:
|
|
16
16
|
return translations
|
|
17
17
|
else:
|
|
18
|
-
raise ValueError(f"Invalid translate line
|
|
18
|
+
raise ValueError(f"Invalid translate line. Expected '<num> <name>'.")
|
|
19
19
|
translations[match.group(1)] = match.group(2)
|
|
20
|
-
raise ValueError("Translate block not terminated with ';'")
|
|
20
|
+
raise ValueError("Translate block not terminated with ';'.")
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def _parse_trees_block(lines: Iterator[str]) -> dict[str, Tree]:
|
|
@@ -33,9 +33,12 @@ def _parse_trees_block(lines: Iterator[str]) -> dict[str, Tree]:
|
|
|
33
33
|
match = re.match(r"^TREE\s*\*?\s+(\S+)\s*=\s*(.+)$", line, re.IGNORECASE)
|
|
34
34
|
if match is None:
|
|
35
35
|
raise ValueError(
|
|
36
|
-
f"Invalid tree line. Expected 'TREE <name> = <newick>'"
|
|
36
|
+
f"Invalid tree line. Expected 'TREE <name> = <newick>'."
|
|
37
37
|
)
|
|
38
|
-
|
|
38
|
+
name = match.group(1)
|
|
39
|
+
if name in trees:
|
|
40
|
+
raise ValueError(f"Duplicate tree name found: {name}.")
|
|
41
|
+
trees[name] = parse_newick(match.group(2), translations)
|
|
39
42
|
raise ValueError("Unterminated TREES block.")
|
|
40
43
|
|
|
41
44
|
|
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: phylogenie
|
|
3
|
-
Version: 3.1.
|
|
4
|
-
Summary:
|
|
5
|
-
|
|
6
|
-
Author-email: gabmarino.8601@gmail.com
|
|
7
|
-
Requires-Python: >=3.10,<4.0
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
-
Requires-Dist: joblib (>=1.4.2,<2.0.0)
|
|
13
|
-
Requires-Dist: matplotlib (>=3.10.6,<4.0.0)
|
|
14
|
-
Requires-Dist: pandas (>=2.2.2,<3.0.0)
|
|
15
|
-
Requires-Dist: pydantic (>=2.11.5,<3.0.0)
|
|
16
|
-
Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
|
|
17
|
-
Requires-Dist: tqdm (>=4.66.4,<5.0.0)
|
|
3
|
+
Version: 3.1.4
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Requires-Python: >=3.10
|
|
18
6
|
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE.txt
|
|
8
|
+
Requires-Dist: joblib>=1.5.2
|
|
9
|
+
Requires-Dist: matplotlib>=3.10.7
|
|
10
|
+
Requires-Dist: pandas>=2.3.3
|
|
11
|
+
Requires-Dist: pydantic>=2.12.3
|
|
12
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
13
|
+
Requires-Dist: tqdm>=4.67.1
|
|
14
|
+
Dynamic: license-file
|
|
19
15
|
|
|
20
16
|
<p align="center">
|
|
21
17
|
<img src="https://raw.githubusercontent.com/gabriele-marino/phylogenie/main/logo.png" style="width:100%; height:auto;"/>
|
|
@@ -103,4 +99,3 @@ This project is licensed under [MIT License](https://raw.githubusercontent.com/g
|
|
|
103
99
|
For questions, bug reports, or feature requests, please, consider opening an [issue on GitHub](https://github.com/gabriele-marino/phylogenie/issues), or [contact me directly](mailto:gabmarino.8601@email.com).
|
|
104
100
|
|
|
105
101
|
If you need help with the configuration files, feel free to reach out — I am always very available and happy to assist!
|
|
106
|
-
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
phylogenie/__init__.py,sha256=-4GKO2EKgc2GiOhzVRI0SQk6wQZ4AlP7Ron_Lp-s_r0,2913
|
|
2
|
-
phylogenie/draw.py,sha256=
|
|
2
|
+
phylogenie/draw.py,sha256=nT3FOHSm85G23qz2xxYf2MesEDonWRSxfKGJkVboTKY,5580
|
|
3
|
+
phylogenie/main.py,sha256=DstKWUySyDXdcPN_P8O3Mmoau4IjUxCQ4iLWDVuAcws,1054
|
|
4
|
+
phylogenie/mixins.py,sha256=kwxcHGYSS-Frk-r0nwuyILYS1g6NjSOhbUKEYt2g1B0,1319
|
|
5
|
+
phylogenie/msa.py,sha256=JDGyZUsAq6-m-SQjoCDjAkAZIxfgyl_PDIhdYn5HOow,2064
|
|
6
|
+
phylogenie/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
phylogenie/typeguards.py,sha256=JtqmbEWJZBRHbWgCvcl6nrWm3VcBfzRbklbTBYHItn0,1325
|
|
8
|
+
phylogenie/typings.py,sha256=p694PBe_tk25A6N8vGGWxuqoDtt3nHFUsIYJrwR_76Y,494
|
|
3
9
|
phylogenie/generators/__init__.py,sha256=zsOxy28-9j9alOQLIgrOAFfmM58NNHO_NEtW-KXQXAY,888
|
|
4
10
|
phylogenie/generators/alisim.py,sha256=oizyUz2xNKUdO4HrmZFqtVUfzPBN4BRgxgYczofgeYs,2809
|
|
5
11
|
phylogenie/generators/configs.py,sha256=xDIyDgGxuaqdET9wVkpdrXk02jIbibSp8mgxuIcM5qQ,1489
|
|
@@ -9,32 +15,27 @@ phylogenie/generators/trees.py,sha256=8dO1CkU34E6mmMAHrYqiLV_VA8r54cSEOo-UzoHiN2
|
|
|
9
15
|
phylogenie/generators/typeguards.py,sha256=yj4VkhOaUXJ2OrY-6zhOeY9C4yKIQxjZtk2d-vIxttQ,828
|
|
10
16
|
phylogenie/io/__init__.py,sha256=eWDU6YDqAdx6TZlUMmMbsfO8gP3i5HP_cfUe_-0x2FA,69
|
|
11
17
|
phylogenie/io/fasta.py,sha256=CUFO06m7wClprarsMheZojM4Os2NQf3ALYUXSWzfNL0,869
|
|
12
|
-
phylogenie/main.py,sha256=vtvSpQxBNlYABoFQ25czl-l3fIr4QRo3svWVd-jcArw,1170
|
|
13
|
-
phylogenie/mixins.py,sha256=kwxcHGYSS-Frk-r0nwuyILYS1g6NjSOhbUKEYt2g1B0,1319
|
|
14
|
-
phylogenie/msa.py,sha256=JDGyZUsAq6-m-SQjoCDjAkAZIxfgyl_PDIhdYn5HOow,2064
|
|
15
|
-
phylogenie/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
18
|
phylogenie/skyline/__init__.py,sha256=7pF4CUb4ZCLzNYJNhOjpuTOLTRhlK7L6ugfccNqjIGo,620
|
|
17
19
|
phylogenie/skyline/matrix.py,sha256=v4SitY7VbXprqlqQckjWTzW5hwRmCyIF595R6IJMxWw,9268
|
|
18
20
|
phylogenie/skyline/parameter.py,sha256=TVqkqirGXNN-VP8hnIJACPkOxUan6LkGa5o_JcPfwbY,4834
|
|
19
21
|
phylogenie/skyline/vector.py,sha256=60jtp7PieiEaEH0Tp6zNjNKjyzpN_nT5uwBUXbgeATk,7261
|
|
20
22
|
phylogenie/treesimulator/__init__.py,sha256=Qz__cFookXuEjq8AUp1A6XRON0qQ_xX-q2Q5ixP4XUg,1791
|
|
23
|
+
phylogenie/treesimulator/features.py,sha256=XbuwGw8xjGs2lNhJvvUUvXVtheSTBaSN6qj39tWYEro,1391
|
|
24
|
+
phylogenie/treesimulator/gillespie.py,sha256=ey2hdpJOSpNW88duwK7wTAdYSTnSuTSZ_yhZv9MlNHo,5323
|
|
25
|
+
phylogenie/treesimulator/model.py,sha256=L0RsL6H1ynFDPecULniSs4Cs8dvz87ovviQOXFy5Qt0,4580
|
|
26
|
+
phylogenie/treesimulator/tree.py,sha256=-yMW14018x9dw45TonS6nRlzWcwXcaHv3Jn5HYriLQQ,6009
|
|
27
|
+
phylogenie/treesimulator/utils.py,sha256=OxZwVHxN004Jf-kYZ_GfJgIY0beo-0tYq80CuFGQt-M,3416
|
|
21
28
|
phylogenie/treesimulator/events/__init__.py,sha256=w2tJ0D2WB5AiCbr3CsKN6vdADueiAEMzd_ve0rpa4zg,939
|
|
22
29
|
phylogenie/treesimulator/events/base.py,sha256=JQKYUZmhB2Q-WQOy2ULGKQiabsMz-JvwMVfDoa3ZKyo,1170
|
|
23
30
|
phylogenie/treesimulator/events/contact_tracing.py,sha256=t64omKEO2d-DfN_dhDJlXp_Kg9egy2ZE346yWjV3ZrA,5148
|
|
24
31
|
phylogenie/treesimulator/events/core.py,sha256=bhgQgi5L-oaHsoWJmUOsTTzWxi0POYxVLoF-KrC8AGQ,8179
|
|
25
32
|
phylogenie/treesimulator/events/mutations.py,sha256=8Nqa2fg7fwaVNe5XSkGDSwp9pIKQ7XaBQCCj-LYlfzA,3666
|
|
26
|
-
phylogenie/treesimulator/features.py,sha256=XbuwGw8xjGs2lNhJvvUUvXVtheSTBaSN6qj39tWYEro,1391
|
|
27
|
-
phylogenie/treesimulator/gillespie.py,sha256=ey2hdpJOSpNW88duwK7wTAdYSTnSuTSZ_yhZv9MlNHo,5323
|
|
28
33
|
phylogenie/treesimulator/io/__init__.py,sha256=rfP-zp8SP8baq5_4dPAr10WH0W6KfoMCxdTZDCSXtzE,185
|
|
29
34
|
phylogenie/treesimulator/io/newick.py,sha256=8Pr_jixByPOaVch18w-rFt62HYy0U97YMu0H-QSwIy0,3449
|
|
30
|
-
phylogenie/treesimulator/io/nexus.py,sha256=
|
|
31
|
-
phylogenie/
|
|
32
|
-
phylogenie/
|
|
33
|
-
phylogenie/
|
|
34
|
-
phylogenie/
|
|
35
|
-
phylogenie/
|
|
36
|
-
phylogenie-3.1.
|
|
37
|
-
phylogenie-3.1.2.dist-info/METADATA,sha256=8bNrxXaHWW1N1nWmjDwf8CV9306fDaxguE2xoWmPufU,5476
|
|
38
|
-
phylogenie-3.1.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
39
|
-
phylogenie-3.1.2.dist-info/entry_points.txt,sha256=Rt6_usN0FkBX1ZfiqCirjMN9FKOgFLG8rydcQ8kugeE,51
|
|
40
|
-
phylogenie-3.1.2.dist-info/RECORD,,
|
|
35
|
+
phylogenie/treesimulator/io/nexus.py,sha256=tPZRPejnG0OEE7YTorwvyZe2vnZHv4KiC9f-N7Kx6qg,1849
|
|
36
|
+
phylogenie-3.1.4.dist-info/licenses/LICENSE.txt,sha256=NUrDqElK-eD3I0WqC004CJsy6cs0JgsAoebDv_42-pw,1071
|
|
37
|
+
phylogenie-3.1.4.dist-info/METADATA,sha256=en3CvCPhiUbQPZTAUYWpx8nQze6oqS-KQJJa3xGdvbI,5163
|
|
38
|
+
phylogenie-3.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
39
|
+
phylogenie-3.1.4.dist-info/entry_points.txt,sha256=BBH8LoReHnNFnvq4sROEsVFegfkKJ6c_oHZ7bgK7Jl4,52
|
|
40
|
+
phylogenie-3.1.4.dist-info/top_level.txt,sha256=1YGZJhKA9tN9qI0Hcj6Cn_sOoDpba0HQlNcgQTjMD-8,11
|
|
41
|
+
phylogenie-3.1.4.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
phylogenie
|
|
File without changes
|