phylogenie 3.1.1__py3-none-any.whl → 3.1.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.

Potentially problematic release.


This version of phylogenie might be problematic. Click here for more details.

phylogenie/draw.py CHANGED
@@ -48,7 +48,7 @@ def _draw_colored_tree(tree: Tree, ax: Axes, colors: Color | dict[Tree, Color])
48
48
  def draw_tree(
49
49
  tree: Tree,
50
50
  ax: Axes | None = None,
51
- color_by: str | dict[Tree, Any] | None = None,
51
+ color_by: str | dict[str, Any] | None = None,
52
52
  coloring: str | Coloring | None = None,
53
53
  default_color: Color = "black",
54
54
  cmap: str | None = None,
@@ -67,15 +67,16 @@ def draw_tree(
67
67
  if color_by is None:
68
68
  return _draw_colored_tree(tree, ax, colors=default_color)
69
69
 
70
- if isinstance(color_by, dict):
71
- features = {node: color_by[node] for node in tree if node in color_by}
72
- else:
70
+ if isinstance(color_by, str):
73
71
  features = {node: node[color_by] for node in tree if color_by in node.metadata}
72
+ else:
73
+ features = {node: color_by[node.name] for node in tree if node.name in color_by}
74
+ values = list(features.values())
74
75
 
75
76
  if coloring is None:
76
77
  coloring = (
77
78
  Coloring.CONTINUOUS
78
- if any(isinstance(f, float) for f in features.values())
79
+ if any(isinstance(f, float) for f in values)
79
80
  else Coloring.DISCRETE
80
81
  )
81
82
 
@@ -86,14 +87,14 @@ def draw_tree(
86
87
  }
87
88
 
88
89
  if coloring == Coloring.DISCRETE:
89
- if any(isinstance(f, float) for f in features.values()):
90
+ if any(isinstance(f, float) for f in values):
90
91
  raise ValueError(
91
92
  "Discrete coloring selected but feature values are not all categorical."
92
93
  )
93
94
 
94
95
  colormap = plt.get_cmap("tab20" if cmap is None else cmap)
95
96
  feature_colors = {
96
- f: mcolors.to_hex(colormap(i)) for i, f in enumerate(set(features.values()))
97
+ f: mcolors.to_hex(colormap(i)) for i, f in enumerate(set(values))
97
98
  }
98
99
  colors = _get_colors(lambda f: feature_colors[f])
99
100
 
@@ -114,8 +115,8 @@ def draw_tree(
114
115
  return _draw_colored_tree(tree, ax, colors)
115
116
 
116
117
  if coloring == Coloring.CONTINUOUS:
117
- vmin = min(features.values()) if vmin is None else vmin
118
- vmax = max(features.values()) if vmax is None else vmax
118
+ vmin = min(values) if vmin is None else vmin
119
+ vmax = max(values) if vmax is None else vmax
119
120
  norm = mcolors.Normalize(vmin=vmin, vmax=vmax)
120
121
  colormap = plt.get_cmap("viridis" if cmap is None else cmap)
121
122
  colors = _get_colors(lambda f: colormap(norm(float(f))))
@@ -127,7 +128,7 @@ def draw_tree(
127
128
  hist_ax = inset_axes(ax, **default_hist_axes_kwargs) # pyright: ignore
128
129
 
129
130
  hist_kwargs = {} if hist_kwargs is None else hist_kwargs
130
- _, bins, patches = hist_ax.hist(features, **hist_kwargs) # pyright: ignore
131
+ _, bins, patches = hist_ax.hist(values, **hist_kwargs) # pyright: ignore
131
132
 
132
133
  for patch, b0, b1 in zip( # pyright: ignore
133
134
  patches, bins[:-1], bins[1:] # pyright: ignore
@@ -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: {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]:
@@ -32,9 +32,14 @@ def _parse_trees_block(lines: Iterator[str]) -> dict[str, Tree]:
32
32
  else:
33
33
  match = re.match(r"^TREE\s*\*?\s+(\S+)\s*=\s*(.+)$", line, re.IGNORECASE)
34
34
  if match is None:
35
- raise ValueError(f"Invalid tree line. Expected 'TREE name = newick'")
36
- trees[match.group(1)] = parse_newick(match.group(2), translations)
37
- return trees
35
+ raise ValueError(
36
+ f"Invalid tree line. Expected 'TREE <name> = <newick>'."
37
+ )
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)
42
+ raise ValueError("Unterminated TREES block.")
38
43
 
39
44
 
40
45
  def load_nexus(nexus_file: str | Path) -> dict[str, Tree]:
@@ -1,21 +1,17 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: phylogenie
3
- Version: 3.1.1
4
- Summary: Generate phylogenetic datasets with minimal setup effort
5
- Author: Gabriele Marino
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.3
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=6WHLxXXyTKq6pxuPBfDgZfEZti3UkJVhDory2pJzdIc,5499
2
+ phylogenie/draw.py,sha256=qAFFA9bZPoVMvaOAceC4S-XzF5CXk-qTU2yIwbrA0Ac,5487
3
+ phylogenie/main.py,sha256=vtvSpQxBNlYABoFQ25czl-l3fIr4QRo3svWVd-jcArw,1170
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=7g5lHb1GZczdLIXnkOUwjwTYtLZJX_4C-zOD4TW_Dao,1628
31
- phylogenie/treesimulator/model.py,sha256=L0RsL6H1ynFDPecULniSs4Cs8dvz87ovviQOXFy5Qt0,4580
32
- phylogenie/treesimulator/tree.py,sha256=-yMW14018x9dw45TonS6nRlzWcwXcaHv3Jn5HYriLQQ,6009
33
- phylogenie/treesimulator/utils.py,sha256=OxZwVHxN004Jf-kYZ_GfJgIY0beo-0tYq80CuFGQt-M,3416
34
- phylogenie/typeguards.py,sha256=JtqmbEWJZBRHbWgCvcl6nrWm3VcBfzRbklbTBYHItn0,1325
35
- phylogenie/typings.py,sha256=p694PBe_tk25A6N8vGGWxuqoDtt3nHFUsIYJrwR_76Y,494
36
- phylogenie-3.1.1.dist-info/LICENSE.txt,sha256=NUrDqElK-eD3I0WqC004CJsy6cs0JgsAoebDv_42-pw,1071
37
- phylogenie-3.1.1.dist-info/METADATA,sha256=tI27FQyUYrIiTxygC2M_g8I-ruY_R3OFEi_hK2cAmg4,5476
38
- phylogenie-3.1.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
39
- phylogenie-3.1.1.dist-info/entry_points.txt,sha256=Rt6_usN0FkBX1ZfiqCirjMN9FKOgFLG8rydcQ8kugeE,51
40
- phylogenie-3.1.1.dist-info/RECORD,,
35
+ phylogenie/treesimulator/io/nexus.py,sha256=tPZRPejnG0OEE7YTorwvyZe2vnZHv4KiC9f-N7Kx6qg,1849
36
+ phylogenie-3.1.3.dist-info/licenses/LICENSE.txt,sha256=NUrDqElK-eD3I0WqC004CJsy6cs0JgsAoebDv_42-pw,1071
37
+ phylogenie-3.1.3.dist-info/METADATA,sha256=1n5ZhRstpxMfZsQLOamnd82GZGTVgL2_zIAEKtXkcY4,5163
38
+ phylogenie-3.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
39
+ phylogenie-3.1.3.dist-info/entry_points.txt,sha256=BBH8LoReHnNFnvq4sROEsVFegfkKJ6c_oHZ7bgK7Jl4,52
40
+ phylogenie-3.1.3.dist-info/top_level.txt,sha256=1YGZJhKA9tN9qI0Hcj6Cn_sOoDpba0HQlNcgQTjMD-8,11
41
+ phylogenie-3.1.3.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ phylogenie = phylogenie.main:main
@@ -0,0 +1 @@
1
+ phylogenie
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- phylogenie=phylogenie.main:main
3
-