phylogenie 2.1.4__py3-none-any.whl → 3.1.7__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.
Files changed (40) hide show
  1. phylogenie/__init__.py +60 -14
  2. phylogenie/draw.py +690 -0
  3. phylogenie/generators/alisim.py +12 -12
  4. phylogenie/generators/configs.py +26 -4
  5. phylogenie/generators/dataset.py +3 -3
  6. phylogenie/generators/factories.py +38 -12
  7. phylogenie/generators/trees.py +48 -47
  8. phylogenie/io/__init__.py +3 -0
  9. phylogenie/io/fasta.py +34 -0
  10. phylogenie/main.py +27 -10
  11. phylogenie/mixins.py +33 -0
  12. phylogenie/skyline/matrix.py +11 -7
  13. phylogenie/skyline/parameter.py +12 -4
  14. phylogenie/skyline/vector.py +12 -6
  15. phylogenie/treesimulator/__init__.py +36 -3
  16. phylogenie/treesimulator/events/__init__.py +5 -5
  17. phylogenie/treesimulator/events/base.py +39 -0
  18. phylogenie/treesimulator/events/contact_tracing.py +38 -23
  19. phylogenie/treesimulator/events/core.py +21 -12
  20. phylogenie/treesimulator/events/mutations.py +46 -46
  21. phylogenie/treesimulator/features.py +49 -0
  22. phylogenie/treesimulator/gillespie.py +59 -55
  23. phylogenie/treesimulator/io/__init__.py +4 -0
  24. phylogenie/treesimulator/io/newick.py +104 -0
  25. phylogenie/treesimulator/io/nexus.py +50 -0
  26. phylogenie/treesimulator/model.py +25 -49
  27. phylogenie/treesimulator/tree.py +196 -0
  28. phylogenie/treesimulator/utils.py +108 -0
  29. phylogenie/typings.py +3 -3
  30. {phylogenie-2.1.4.dist-info → phylogenie-3.1.7.dist-info}/METADATA +13 -15
  31. phylogenie-3.1.7.dist-info/RECORD +41 -0
  32. {phylogenie-2.1.4.dist-info → phylogenie-3.1.7.dist-info}/WHEEL +2 -1
  33. phylogenie-3.1.7.dist-info/entry_points.txt +2 -0
  34. phylogenie-3.1.7.dist-info/top_level.txt +1 -0
  35. phylogenie/io.py +0 -107
  36. phylogenie/tree.py +0 -92
  37. phylogenie/utils.py +0 -17
  38. phylogenie-2.1.4.dist-info/RECORD +0 -32
  39. phylogenie-2.1.4.dist-info/entry_points.txt +0 -3
  40. {phylogenie-2.1.4.dist-info → phylogenie-3.1.7.dist-info/licenses}/LICENSE.txt +0 -0
@@ -0,0 +1,108 @@
1
+ import math
2
+ from math import comb
3
+
4
+ from phylogenie.treesimulator.tree import Tree
5
+
6
+
7
+ def get_node_leaf_counts(tree: Tree) -> dict[Tree, int]:
8
+ n_leaves: dict[Tree, int] = {}
9
+ for node in tree.postorder_traversal():
10
+ n_leaves[node] = sum(n_leaves[child] for child in node.children) or 1
11
+ return n_leaves
12
+
13
+
14
+ def get_node_depth_levels(tree: Tree) -> dict[Tree, int]:
15
+ depth_levels: dict[Tree, int] = {tree: tree.depth_level}
16
+ for node in tree.iter_descendants():
17
+ depth_levels[node] = depth_levels[node.parent] + 1 # pyright: ignore
18
+ return depth_levels
19
+
20
+
21
+ def get_node_depths(tree: Tree) -> dict[Tree, float]:
22
+ depths: dict[Tree, float] = {tree: tree.depth}
23
+ for node in tree.iter_descendants():
24
+ parent_depth = depths[node.parent] # pyright: ignore
25
+ depths[node] = node.branch_length_or_raise() + parent_depth
26
+ return depths
27
+
28
+
29
+ def get_node_height_levels(tree: Tree) -> dict[Tree, int]:
30
+ height_levels: dict[Tree, int] = {}
31
+ for node in tree.postorder_traversal():
32
+ height_levels[node] = (
33
+ 0
34
+ if node.is_leaf()
35
+ else max(1 + height_levels[child] for child in node.children)
36
+ )
37
+ return height_levels
38
+
39
+
40
+ def get_node_heights(tree: Tree) -> dict[Tree, float]:
41
+ heights: dict[Tree, float] = {}
42
+ for node in tree.postorder_traversal():
43
+ heights[node] = (
44
+ 0
45
+ if node.is_leaf()
46
+ else max(
47
+ child.branch_length_or_raise() + heights[child]
48
+ for child in node.children
49
+ )
50
+ )
51
+ return heights
52
+
53
+
54
+ def get_mrca(node1: Tree, node2: Tree) -> Tree:
55
+ node1_ancestors = set(node1.iter_upward())
56
+ for node2_ancestor in node2.iter_upward():
57
+ if node2_ancestor in node1_ancestors:
58
+ return node2_ancestor
59
+ raise ValueError(f"No common ancestor found between node {node1} and node {node2}.")
60
+
61
+
62
+ def get_path(node1: Tree, node2: Tree) -> list[Tree]:
63
+ mrca = get_mrca(node1, node2)
64
+ return [
65
+ *node1.iter_upward(stop=mrca.parent),
66
+ *reversed(list(node2.iter_upward(stop=mrca))),
67
+ ]
68
+
69
+
70
+ def count_hops(node1: Tree, node2: Tree) -> int:
71
+ return len(get_path(node1, node2)) - 1
72
+
73
+
74
+ def get_distance(node1: Tree, node2: Tree) -> float:
75
+ mrca = get_mrca(node1, node2)
76
+ path = get_path(node1, node2)
77
+ path.remove(mrca)
78
+ return sum(node.branch_length_or_raise() for node in path)
79
+
80
+
81
+ def compute_sackin_index(tree: Tree, normalize: bool = False) -> float:
82
+ depth_levels = get_node_depth_levels(tree)
83
+ sackin_index = sum(dl for node, dl in depth_levels.items() if node.is_leaf())
84
+ if normalize:
85
+ if not tree.is_binary():
86
+ raise ValueError(
87
+ "Normalized Sackin index is only defined for binary trees."
88
+ )
89
+ n = tree.n_leaves
90
+ h = math.floor(math.log2(n))
91
+ min_sackin_index = n * (h + 2) - 2 ** (h + 1)
92
+ max_sackin_index = n * (n - 1) / 2
93
+ return (sackin_index - min_sackin_index) / (max_sackin_index - min_sackin_index)
94
+ return sackin_index
95
+
96
+
97
+ def compute_mean_leaf_pairwise_distance(tree: Tree) -> float:
98
+ leaves = tree.get_leaves()
99
+ n_leaves = len(leaves)
100
+ if n_leaves < 2:
101
+ return 0.0
102
+
103
+ total_distance = sum(
104
+ get_distance(leaves[i], leaves[j])
105
+ for i in range(n_leaves)
106
+ for j in range(i + 1, n_leaves)
107
+ )
108
+ return total_distance / comb(n_leaves, 2)
phylogenie/typings.py CHANGED
@@ -15,6 +15,6 @@ OneOrMany2DScalars = OneOrMany2D[Scalar]
15
15
  Many2DScalars = Many2D[Scalar]
16
16
  Many3DScalars = Many3D[Scalar]
17
17
 
18
- Vector1D = list[Scalar]
19
- Vector2D = list[Vector1D]
20
- Vector3D = list[Vector2D]
18
+ Vector1D = tuple[Scalar, ...]
19
+ Vector2D = tuple[Vector1D, ...]
20
+ Vector3D = tuple[Vector2D, ...]
@@ -1,20 +1,17 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: phylogenie
3
- Version: 2.1.4
3
+ Version: 3.1.7
4
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: pandas (>=2.2.2,<3.0.0)
14
- Requires-Dist: pydantic (>=2.11.5,<3.0.0)
15
- Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
16
- Requires-Dist: tqdm (>=4.66.4,<5.0.0)
5
+ Requires-Python: >=3.10
17
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
18
15
 
19
16
  <p align="center">
20
17
  <img src="https://raw.githubusercontent.com/gabriele-marino/phylogenie/main/logo.png" style="width:100%; height:auto;"/>
@@ -24,6 +21,8 @@ Description-Content-Type: text/markdown
24
21
 
25
22
  [![AliSim](https://img.shields.io/badge/Powered%20by-AliSim-orange?style=flat-square)](https://iqtree.github.io/doc/AliSim)
26
23
  [![PyPI version](https://img.shields.io/pypi/v/phylogenie)](https://pypi.org/project/phylogenie/)
24
+ ![Downloads](https://img.shields.io/pypi/dm/phylogenie)
25
+
27
26
 
28
27
  Phylogenie is a [Python](https://www.python.org/) package designed to easily simulate phylogenetic datasets—such as trees and multiple sequence alignments (MSAs)—with minimal setup effort. Simply specify the distributions from which your parameters should be sampled, and Phylogenie will handle the rest!
29
28
 
@@ -100,4 +99,3 @@ This project is licensed under [MIT License](https://raw.githubusercontent.com/g
100
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).
101
100
 
102
101
  If you need help with the configuration files, feel free to reach out — I am always very available and happy to assist!
103
-
@@ -0,0 +1,41 @@
1
+ phylogenie/__init__.py,sha256=redo-SdvWwQPlyqOfdSW0TkkZf-aP98kLRCUIg4pB8c,3304
2
+ phylogenie/draw.py,sha256=djG0cG9mmNFZ7vf3jo8Ei3bNBJVqujp6gtZtwPxyfSY,23341
3
+ phylogenie/main.py,sha256=ry3B3HiwibZG3_qB58T5UhWy5dp6neYUtSqzL9LrSkA,1698
4
+ phylogenie/mixins.py,sha256=wMwqP6zkqME9eMyzx5FS6-p9X8yW09jIC8jge8pHlkk,907
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
9
+ phylogenie/generators/__init__.py,sha256=zsOxy28-9j9alOQLIgrOAFfmM58NNHO_NEtW-KXQXAY,888
10
+ phylogenie/generators/alisim.py,sha256=oizyUz2xNKUdO4HrmZFqtVUfzPBN4BRgxgYczofgeYs,2809
11
+ phylogenie/generators/configs.py,sha256=xDIyDgGxuaqdET9wVkpdrXk02jIbibSp8mgxuIcM5qQ,1489
12
+ phylogenie/generators/dataset.py,sha256=Z3a4Mhh6zMTYmhd-aIT3aCaJMTVg4I_QvWWIrCw2l4E,2121
13
+ phylogenie/generators/factories.py,sha256=2mTFdFbbLyV3v79JaOEVtqLOmxQHaOUv1S-Y3vVo7U0,8480
14
+ phylogenie/generators/trees.py,sha256=8dO1CkU34E6mmMAHrYqiLV_VA8r54cSEOo-UzoHiN20,10467
15
+ phylogenie/generators/typeguards.py,sha256=yj4VkhOaUXJ2OrY-6zhOeY9C4yKIQxjZtk2d-vIxttQ,828
16
+ phylogenie/io/__init__.py,sha256=3v_bxv9RVeQ3KZzxNFeV9KLVxaC_Whf7rgWLnBKoEr0,95
17
+ phylogenie/io/fasta.py,sha256=kx9uVATLpzpXdhhNNMvMpB5Vdwh9CTWepTGachvEwV4,1154
18
+ phylogenie/skyline/__init__.py,sha256=7pF4CUb4ZCLzNYJNhOjpuTOLTRhlK7L6ugfccNqjIGo,620
19
+ phylogenie/skyline/matrix.py,sha256=v4SitY7VbXprqlqQckjWTzW5hwRmCyIF595R6IJMxWw,9268
20
+ phylogenie/skyline/parameter.py,sha256=TVqkqirGXNN-VP8hnIJACPkOxUan6LkGa5o_JcPfwbY,4834
21
+ phylogenie/skyline/vector.py,sha256=60jtp7PieiEaEH0Tp6zNjNKjyzpN_nT5uwBUXbgeATk,7261
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=DEdzCh4vABq2f095beh3tD3_aee7EyXPDSjcyHKgKLg,6064
27
+ phylogenie/treesimulator/utils.py,sha256=OxZwVHxN004Jf-kYZ_GfJgIY0beo-0tYq80CuFGQt-M,3416
28
+ phylogenie/treesimulator/events/__init__.py,sha256=w2tJ0D2WB5AiCbr3CsKN6vdADueiAEMzd_ve0rpa4zg,939
29
+ phylogenie/treesimulator/events/base.py,sha256=JQKYUZmhB2Q-WQOy2ULGKQiabsMz-JvwMVfDoa3ZKyo,1170
30
+ phylogenie/treesimulator/events/contact_tracing.py,sha256=t64omKEO2d-DfN_dhDJlXp_Kg9egy2ZE346yWjV3ZrA,5148
31
+ phylogenie/treesimulator/events/core.py,sha256=bhgQgi5L-oaHsoWJmUOsTTzWxi0POYxVLoF-KrC8AGQ,8179
32
+ phylogenie/treesimulator/events/mutations.py,sha256=8Nqa2fg7fwaVNe5XSkGDSwp9pIKQ7XaBQCCj-LYlfzA,3666
33
+ phylogenie/treesimulator/io/__init__.py,sha256=rfP-zp8SP8baq5_4dPAr10WH0W6KfoMCxdTZDCSXtzE,185
34
+ phylogenie/treesimulator/io/newick.py,sha256=8Pr_jixByPOaVch18w-rFt62HYy0U97YMu0H-QSwIy0,3449
35
+ phylogenie/treesimulator/io/nexus.py,sha256=zqT9dzj413z_s0hqp3Cdq5NMO6lv-zuuaJlaqzaqaB8,1847
36
+ phylogenie-3.1.7.dist-info/licenses/LICENSE.txt,sha256=NUrDqElK-eD3I0WqC004CJsy6cs0JgsAoebDv_42-pw,1071
37
+ phylogenie-3.1.7.dist-info/METADATA,sha256=qnvdSWDQUd2fJa7RHSByFdCKvDgYqaPP_2QeCD2F-eg,5194
38
+ phylogenie-3.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
39
+ phylogenie-3.1.7.dist-info/entry_points.txt,sha256=BBH8LoReHnNFnvq4sROEsVFegfkKJ6c_oHZ7bgK7Jl4,52
40
+ phylogenie-3.1.7.dist-info/top_level.txt,sha256=1YGZJhKA9tN9qI0Hcj6Cn_sOoDpba0HQlNcgQTjMD-8,11
41
+ phylogenie-3.1.7.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
phylogenie/io.py DELETED
@@ -1,107 +0,0 @@
1
- from typing import Callable
2
-
3
- from phylogenie.msa import MSA, Sequence
4
- from phylogenie.tree import Tree
5
-
6
-
7
- def _parse_newick(newick: str) -> Tree:
8
- newick = newick.strip()
9
- stack: list[list[Tree]] = []
10
- current_children: list[Tree] = []
11
- current_nodes: list[Tree] = []
12
- i = 0
13
- while i < len(newick):
14
-
15
- def _parse_chars(stoppers: list[str]) -> str:
16
- nonlocal i
17
- chars = ""
18
- while newick[i] not in stoppers:
19
- chars += newick[i]
20
- i += 1
21
- return chars
22
-
23
- if newick[i] == "(":
24
- stack.append(current_nodes)
25
- current_nodes = []
26
- else:
27
- id = _parse_chars([":", ",", ")", ";", "["])
28
- branch_length = None
29
- if newick[i] == ":":
30
- i += 1
31
- branch_length = float(_parse_chars([",", ")", ";", "["]))
32
-
33
- current_node = Tree(id, branch_length)
34
- for node in current_children:
35
- current_node.add_child(node)
36
- current_children = []
37
- current_nodes.append(current_node)
38
-
39
- if newick[i] == "[":
40
- i += 1
41
- features = _parse_chars(["]"]).split(":")
42
- i += 1
43
- if features[0] != "&&NHX":
44
- raise ValueError(f"Expected '&&NHX' for node features.")
45
- for feature in features[1:]:
46
- key, value = feature.split("=", 1)
47
- current_node.set(key, eval(value))
48
-
49
- if newick[i] == ")":
50
- current_children = current_nodes
51
- current_nodes = stack.pop()
52
- elif newick[i] == ";":
53
- return current_node
54
-
55
- i += 1
56
-
57
- raise ValueError("Newick string is invalid.")
58
-
59
-
60
- def load_newick(filepath: str) -> Tree | list[Tree]:
61
- with open(filepath, "r") as file:
62
- trees = [_parse_newick(newick) for newick in file]
63
- return trees[0] if len(trees) == 1 else trees
64
-
65
-
66
- def _to_newick(tree: Tree) -> str:
67
- children_newick = ",".join([_to_newick(child) for child in tree.children])
68
- newick = tree.id
69
- if children_newick:
70
- newick = f"({children_newick}){newick}"
71
- if tree.branch_length is not None:
72
- newick += f":{tree.branch_length}"
73
- if tree.features:
74
- reprs = {k: repr(v).replace("'", '"') for k, v in tree.features.items()}
75
- features = [f"{k}={repr}" for k, repr in reprs.items()]
76
- newick += f"[&&NHX:{':'.join(features)}]"
77
- return newick
78
-
79
-
80
- def dump_newick(trees: Tree | list[Tree], filepath: str) -> None:
81
- if isinstance(trees, Tree):
82
- trees = [trees]
83
- with open(filepath, "w") as file:
84
- for t in trees:
85
- file.write(_to_newick(t) + ";\n")
86
-
87
-
88
- def load_fasta(
89
- fasta_file: str, extract_time_from_id: Callable[[str], float] | None = None
90
- ) -> MSA:
91
- sequences: list[Sequence] = []
92
- with open(fasta_file, "r") as f:
93
- for line in f:
94
- if not line.startswith(">"):
95
- raise ValueError(f"Invalid FASTA format: expected '>', got '{line[0]}'")
96
- id = line[1:].strip()
97
- time = None
98
- if extract_time_from_id is not None:
99
- time = extract_time_from_id(id)
100
- elif "|" in id:
101
- try:
102
- time = float(id.split("|")[-1])
103
- except ValueError:
104
- pass
105
- chars = next(f).strip()
106
- sequences.append(Sequence(id, chars, time))
107
- return MSA(sequences)
phylogenie/tree.py DELETED
@@ -1,92 +0,0 @@
1
- from collections.abc import Iterator
2
- from typing import Any
3
-
4
-
5
- class Tree:
6
- def __init__(self, id: str = "", branch_length: float | None = None):
7
- self.id = id
8
- self.branch_length = branch_length
9
- self._parent: Tree | None = None
10
- self._children: list[Tree] = []
11
- self._features: dict[str, Any] = {}
12
-
13
- @property
14
- def children(self) -> tuple["Tree", ...]:
15
- return tuple(self._children)
16
-
17
- @property
18
- def parent(self) -> "Tree | None":
19
- return self._parent
20
-
21
- @property
22
- def features(self) -> dict[str, Any]:
23
- return self._features
24
-
25
- def add_child(self, child: "Tree") -> "Tree":
26
- child._parent = self
27
- self._children.append(child)
28
- return self
29
-
30
- def remove_child(self, child: "Tree") -> None:
31
- self._children.remove(child)
32
- child._parent = None
33
-
34
- def set_parent(self, node: "Tree | None"):
35
- self._parent = node
36
- if node is not None:
37
- node._children.append(self)
38
-
39
- def preorder_traversal(self) -> Iterator["Tree"]:
40
- yield self
41
- for child in self.children:
42
- yield from child.preorder_traversal()
43
-
44
- def postorder_traversal(self) -> Iterator["Tree"]:
45
- for child in self.children:
46
- yield from child.postorder_traversal()
47
- yield self
48
-
49
- def get_node(self, id: str) -> "Tree":
50
- for node in self:
51
- if node.id == id:
52
- return node
53
- raise ValueError(f"Node with id {id} not found.")
54
-
55
- def is_leaf(self) -> bool:
56
- return not self.children
57
-
58
- def get_leaves(self) -> list["Tree"]:
59
- return [node for node in self if not node.children]
60
-
61
- def get_time(self) -> float:
62
- parent_time = 0 if self.parent is None else self.parent.get_time()
63
- if self.branch_length is None:
64
- if self.parent is not None:
65
- raise ValueError(
66
- f"Branch length of non-root node {self.id} is not set."
67
- )
68
- return 0.0
69
- return self.branch_length + parent_time
70
-
71
- def set(self, key: str, value: Any) -> None:
72
- self._features[key] = value
73
-
74
- def get(self, key: str) -> Any:
75
- return self._features.get(key)
76
-
77
- def delete(self, key: str) -> None:
78
- del self._features[key]
79
-
80
- def copy(self):
81
- new_tree = Tree(self.id, self.branch_length)
82
- for key, value in self._features.items():
83
- new_tree.set(key, value)
84
- for child in self.children:
85
- new_tree.add_child(child.copy())
86
- return new_tree
87
-
88
- def __iter__(self) -> Iterator["Tree"]:
89
- return self.preorder_traversal()
90
-
91
- def __repr__(self) -> str:
92
- return f"TreeNode(id='{self.id}', branch_length={self.branch_length}, features={self.features})"
phylogenie/utils.py DELETED
@@ -1,17 +0,0 @@
1
- from typing import Any
2
-
3
- from pydantic import BaseModel, ConfigDict
4
-
5
-
6
- class StrictBaseModel(BaseModel):
7
- model_config = ConfigDict(extra="forbid")
8
-
9
-
10
- class Distribution(BaseModel):
11
- type: str
12
- model_config = ConfigDict(extra="allow")
13
-
14
- @property
15
- def args(self) -> dict[str, Any]:
16
- assert self.model_extra is not None
17
- return self.model_extra
@@ -1,32 +0,0 @@
1
- phylogenie/__init__.py,sha256=T2mRLsYtoLlWt8GlxrrUnfXJ9XVioq7hTvVq3uJpwQI,2215
2
- phylogenie/generators/__init__.py,sha256=zsOxy28-9j9alOQLIgrOAFfmM58NNHO_NEtW-KXQXAY,888
3
- phylogenie/generators/alisim.py,sha256=3mANgyQrlozhslV3_ryt-m4ItkRcKKRLufWf6SNBTnQ,2781
4
- phylogenie/generators/configs.py,sha256=AiiFS6rpH9BPwDKCkT4SVrRzfLFFrwRCJM4CRj0Srdk,1072
5
- phylogenie/generators/dataset.py,sha256=loVKC_1G7gzkPDN9W3GF-Rj9od8AeOJgIC0aJJa-4KA,2110
6
- phylogenie/generators/factories.py,sha256=jLwDuq0mrmDz2U5rZM19KJ2hSpamG3r6zb83YCc6snA,7619
7
- phylogenie/generators/trees.py,sha256=q03WPG82M4ucp-jyjoKEBy7TKMBzD3RkKn8hS0G0-i0,10463
8
- phylogenie/generators/typeguards.py,sha256=yj4VkhOaUXJ2OrY-6zhOeY9C4yKIQxjZtk2d-vIxttQ,828
9
- phylogenie/io.py,sha256=y7nQIvLgCvqELsXFKfm1GgKJO_saoQ-7zQpE3Kvajzc,3509
10
- phylogenie/main.py,sha256=vtvSpQxBNlYABoFQ25czl-l3fIr4QRo3svWVd-jcArw,1170
11
- phylogenie/msa.py,sha256=JDGyZUsAq6-m-SQjoCDjAkAZIxfgyl_PDIhdYn5HOow,2064
12
- phylogenie/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- phylogenie/skyline/__init__.py,sha256=7pF4CUb4ZCLzNYJNhOjpuTOLTRhlK7L6ugfccNqjIGo,620
14
- phylogenie/skyline/matrix.py,sha256=Gl8OgKjtieG0NwPYiPimKI36gefV8fm_OeorjdXxPTs,9146
15
- phylogenie/skyline/parameter.py,sha256=EM9qlPt0JhMBy3TbztM0dj24BaGNEy8KWKdTObDKhbI,4644
16
- phylogenie/skyline/vector.py,sha256=bJP7_FNX_Klt6wXqsyfj0KX3VNj6-dIhzCKSJuQcOV0,7115
17
- phylogenie/tree.py,sha256=KTx3m_tJPdeBqA5i0SA3dwCIobxsFcJwZFunMfDmVBY,2791
18
- phylogenie/treesimulator/__init__.py,sha256=XG_xwETKWgDmCihqNUFCcMHtFg4WvZu5qbqWn9Dndt8,879
19
- phylogenie/treesimulator/events/__init__.py,sha256=UGfvXOVJ_ZAkk_8sBPihjmxciiaEnXZEPFIY53sttWI,940
20
- phylogenie/treesimulator/events/contact_tracing.py,sha256=_nJ85yhgGkeruQgMHvGpDYoyhheBf8M4LgZWiWdi5dY,4801
21
- phylogenie/treesimulator/events/core.py,sha256=JokGmieAv2xEX7KsjBWZr05jHN1jB-XZbpxe9gwdbDA,7953
22
- phylogenie/treesimulator/events/mutations.py,sha256=xkXUIppbLIWZqKwVf-hi7d-_pS42TG2EPVfJA_grxBg,3443
23
- phylogenie/treesimulator/gillespie.py,sha256=naoxPyZixWVkd5f7B3KhEtOFiQI4NDIp_589NCLTHKM,4831
24
- phylogenie/treesimulator/model.py,sha256=0Im6cFTlpMlJrSP4pTTKtvLT9qrQWV8MSTesAsBxT8g,5422
25
- phylogenie/typeguards.py,sha256=JtqmbEWJZBRHbWgCvcl6nrWm3VcBfzRbklbTBYHItn0,1325
26
- phylogenie/typings.py,sha256=GknvAFXyiaWeeYJ8Lk5d6E2VHT-xW6ONEojYbtJYiB8,476
27
- phylogenie/utils.py,sha256=pCg9ob0RpLUHwM49x4knKxL4FNPr3-EU_6zMXsvxtAg,370
28
- phylogenie-2.1.4.dist-info/LICENSE.txt,sha256=NUrDqElK-eD3I0WqC004CJsy6cs0JgsAoebDv_42-pw,1071
29
- phylogenie-2.1.4.dist-info/METADATA,sha256=xp3v_zG0Cua0UQN6TlF7yS9NuchhdlKnDf8-O3e-l_8,5375
30
- phylogenie-2.1.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
31
- phylogenie-2.1.4.dist-info/entry_points.txt,sha256=Rt6_usN0FkBX1ZfiqCirjMN9FKOgFLG8rydcQ8kugeE,51
32
- phylogenie-2.1.4.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- phylogenie=phylogenie.main:main
3
-