phylogenie 1.0.8__py3-none-any.whl → 2.0.0__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/generators/__init__.py +14 -0
- phylogenie/generators/alisim.py +71 -0
- phylogenie/generators/configs.py +41 -0
- phylogenie/{core → generators}/dataset.py +25 -23
- phylogenie/{core → generators}/factories.py +42 -52
- phylogenie/generators/trees.py +220 -0
- phylogenie/generators/typeguards.py +32 -0
- phylogenie/io.py +92 -0
- phylogenie/main.py +2 -2
- phylogenie/msa.py +72 -0
- phylogenie/skyline/matrix.py +62 -45
- phylogenie/skyline/vector.py +8 -6
- phylogenie/tree.py +53 -0
- phylogenie/treesimulator/__init__.py +21 -0
- phylogenie/treesimulator/events.py +256 -0
- phylogenie/treesimulator/gillespie.py +66 -0
- phylogenie/treesimulator/model.py +100 -0
- phylogenie/typings.py +0 -2
- {phylogenie-1.0.8.dist-info → phylogenie-2.0.0.dist-info}/METADATA +6 -18
- phylogenie-2.0.0.dist-info/RECORD +28 -0
- phylogenie/backend/__init__.py +0 -0
- phylogenie/backend/remaster/__init__.py +0 -21
- phylogenie/backend/remaster/generate.py +0 -187
- phylogenie/backend/remaster/reactions.py +0 -165
- phylogenie/backend/treesimulator.py +0 -163
- phylogenie/configs.py +0 -5
- phylogenie/core/__init__.py +0 -14
- phylogenie/core/configs.py +0 -37
- phylogenie/core/context/__init__.py +0 -4
- phylogenie/core/context/configs.py +0 -28
- phylogenie/core/context/distributions.py +0 -125
- phylogenie/core/context/factories.py +0 -54
- phylogenie/core/msas/__init__.py +0 -10
- phylogenie/core/msas/alisim.py +0 -35
- phylogenie/core/msas/base.py +0 -51
- phylogenie/core/trees/__init__.py +0 -11
- phylogenie/core/trees/base.py +0 -13
- phylogenie/core/trees/remaster/__init__.py +0 -3
- phylogenie/core/trees/remaster/configs.py +0 -14
- phylogenie/core/trees/remaster/factories.py +0 -26
- phylogenie/core/trees/remaster/generator.py +0 -177
- phylogenie/core/trees/treesimulator.py +0 -199
- phylogenie/core/typeguards.py +0 -32
- phylogenie-1.0.8.dist-info/RECORD +0 -39
- {phylogenie-1.0.8.dist-info → phylogenie-2.0.0.dist-info}/LICENSE.txt +0 -0
- {phylogenie-1.0.8.dist-info → phylogenie-2.0.0.dist-info}/WHEEL +0 -0
- {phylogenie-1.0.8.dist-info → phylogenie-2.0.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import subprocess
|
|
3
|
-
from collections.abc import Iterable
|
|
4
|
-
from xml.dom import minidom
|
|
5
|
-
from xml.etree.ElementTree import Element, tostring
|
|
6
|
-
|
|
7
|
-
from phylogenie.backend.remaster.reactions import (
|
|
8
|
-
DEFAULT_POPULATION,
|
|
9
|
-
SAMPLE_POPULATION,
|
|
10
|
-
PunctualReaction,
|
|
11
|
-
Reaction,
|
|
12
|
-
)
|
|
13
|
-
from phylogenie.skyline import skyline_parameter
|
|
14
|
-
|
|
15
|
-
TREE_ID = "Tree"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def _beautify_xml(xml: bytes) -> str:
|
|
19
|
-
xml_str = minidom.parseString(xml).toprettyxml(indent="\t")
|
|
20
|
-
xml_str = re.sub(r"\n\s*\n+", "\n", xml_str)
|
|
21
|
-
xml_str = xml_str.strip()
|
|
22
|
-
return xml_str
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def _generate_config_file(
|
|
26
|
-
output_xml_file: str,
|
|
27
|
-
tree_filename: str,
|
|
28
|
-
populations: list[str],
|
|
29
|
-
init_values: list[int],
|
|
30
|
-
sample_population: str,
|
|
31
|
-
reactions: Iterable[Reaction] | None = None,
|
|
32
|
-
punctual_reactions: Iterable[PunctualReaction] | None = None,
|
|
33
|
-
trajectory_attrs: dict[str, str] | None = None,
|
|
34
|
-
n_simulations: int = 1,
|
|
35
|
-
) -> None:
|
|
36
|
-
simulate = Element("simulate", {"spec": "SimulatedTree", "id": TREE_ID})
|
|
37
|
-
|
|
38
|
-
if trajectory_attrs is None:
|
|
39
|
-
trajectory_attrs = {}
|
|
40
|
-
trajectory = Element(
|
|
41
|
-
"trajectory", {"spec": "StochasticTrajectory", **trajectory_attrs}
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
for population, init_value in zip(populations, init_values):
|
|
45
|
-
trajectory.append(
|
|
46
|
-
Element(
|
|
47
|
-
"population",
|
|
48
|
-
{"spec": "RealParameter", "id": population, "value": str(init_value)},
|
|
49
|
-
)
|
|
50
|
-
)
|
|
51
|
-
trajectory.append(
|
|
52
|
-
Element(
|
|
53
|
-
"samplePopulation",
|
|
54
|
-
{"spec": "RealParameter", "id": sample_population, "value": "0"},
|
|
55
|
-
)
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
if reactions is not None:
|
|
59
|
-
for reaction in reactions:
|
|
60
|
-
if not reaction.rate:
|
|
61
|
-
continue
|
|
62
|
-
rate = skyline_parameter(reaction.rate)
|
|
63
|
-
attrs = {
|
|
64
|
-
"spec": "Reaction",
|
|
65
|
-
"rate": " ".join(map(str, rate.value)),
|
|
66
|
-
"value": reaction.value,
|
|
67
|
-
}
|
|
68
|
-
if rate.change_times:
|
|
69
|
-
attrs["changeTimes"] = " ".join(map(str, rate.change_times))
|
|
70
|
-
trajectory.append(Element("reaction", attrs))
|
|
71
|
-
|
|
72
|
-
if punctual_reactions is not None:
|
|
73
|
-
for punctual_reaction in punctual_reactions:
|
|
74
|
-
attrs = {
|
|
75
|
-
"spec": "PunctualReaction",
|
|
76
|
-
"value": punctual_reaction.value,
|
|
77
|
-
"times": " ".join(map(str, punctual_reaction.times)),
|
|
78
|
-
}
|
|
79
|
-
if punctual_reaction.p is not None:
|
|
80
|
-
attrs["p"] = " ".join(map(str, punctual_reaction.p))
|
|
81
|
-
if punctual_reaction.n is not None:
|
|
82
|
-
attrs["n"] = " ".join(map(str, punctual_reaction.n))
|
|
83
|
-
trajectory.append(Element("reaction", attrs))
|
|
84
|
-
|
|
85
|
-
simulate.append(trajectory)
|
|
86
|
-
|
|
87
|
-
logger = Element(
|
|
88
|
-
"logger", {"spec": "Logger", "mode": "tree", "fileName": tree_filename}
|
|
89
|
-
)
|
|
90
|
-
logger.append(
|
|
91
|
-
Element(
|
|
92
|
-
"log",
|
|
93
|
-
{
|
|
94
|
-
"spec": "TypedTreeLogger",
|
|
95
|
-
"tree": f"@{TREE_ID}",
|
|
96
|
-
"removeSingletonNodes": "true",
|
|
97
|
-
"noLabels": "true",
|
|
98
|
-
},
|
|
99
|
-
)
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
run = Element("run", {"spec": "Simulator", "nSims": str(n_simulations)})
|
|
103
|
-
run.append(simulate)
|
|
104
|
-
run.append(logger)
|
|
105
|
-
|
|
106
|
-
beast = Element(
|
|
107
|
-
"beast",
|
|
108
|
-
{
|
|
109
|
-
"version": "2.0",
|
|
110
|
-
"namespace": ":".join(
|
|
111
|
-
["beast.base.inference", "beast.base.inference.parameter", "remaster"]
|
|
112
|
-
),
|
|
113
|
-
},
|
|
114
|
-
)
|
|
115
|
-
beast.append(run)
|
|
116
|
-
|
|
117
|
-
with open(output_xml_file, "w") as f:
|
|
118
|
-
f.write(_beautify_xml(tostring(beast, method="xml")))
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def _postprocess_tree(input_file: str, output_file: str, attributes: list[str]) -> None:
|
|
122
|
-
|
|
123
|
-
def _replace_metadata(match: re.Match[str]) -> str:
|
|
124
|
-
metadata = match.group(0)
|
|
125
|
-
attrs: list[tuple[str, str]] = re.findall(r'(\w+)=(".*?"|[^,)\]]+)', metadata)
|
|
126
|
-
values = [v.strip('"') for k, v in attrs if k in attributes]
|
|
127
|
-
return "|" + "|".join(values)
|
|
128
|
-
|
|
129
|
-
with open(input_file, "r") as infile:
|
|
130
|
-
with open(output_file, "w") as outfile:
|
|
131
|
-
for line in infile:
|
|
132
|
-
line = line.strip()
|
|
133
|
-
if line.lower().startswith("tree"):
|
|
134
|
-
parts = line.split("=", 1)
|
|
135
|
-
newick = parts[1].strip()
|
|
136
|
-
transformed_newick = re.sub(
|
|
137
|
-
r"\[\&[^\]]*\]", _replace_metadata, newick
|
|
138
|
-
)
|
|
139
|
-
outfile.write(transformed_newick + "\n")
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
def generate_trees(
|
|
143
|
-
tree_filename: str,
|
|
144
|
-
populations: str | list[str] = DEFAULT_POPULATION,
|
|
145
|
-
init_population: str = DEFAULT_POPULATION,
|
|
146
|
-
sample_population: str = SAMPLE_POPULATION,
|
|
147
|
-
reactions: Iterable[Reaction] | None = None,
|
|
148
|
-
punctual_reactions: Iterable[PunctualReaction] | None = None,
|
|
149
|
-
trajectory_attrs: dict[str, str] | None = None,
|
|
150
|
-
output_xml_file: str | None = None,
|
|
151
|
-
n_simulations: int = 1,
|
|
152
|
-
seed: int | None = None,
|
|
153
|
-
beast_path: str = "beast",
|
|
154
|
-
) -> None:
|
|
155
|
-
if isinstance(populations, str):
|
|
156
|
-
populations = [populations]
|
|
157
|
-
init_values = [0] * len(populations)
|
|
158
|
-
init_values[populations.index(init_population)] = 1
|
|
159
|
-
|
|
160
|
-
if output_xml_file is None:
|
|
161
|
-
xml_file = f"{tree_filename}-temp.xml"
|
|
162
|
-
else:
|
|
163
|
-
xml_file = output_xml_file
|
|
164
|
-
|
|
165
|
-
temp_tree_filename = f"{tree_filename}-temp.nex"
|
|
166
|
-
_generate_config_file(
|
|
167
|
-
output_xml_file=xml_file,
|
|
168
|
-
tree_filename=temp_tree_filename,
|
|
169
|
-
populations=populations,
|
|
170
|
-
init_values=init_values,
|
|
171
|
-
sample_population=sample_population,
|
|
172
|
-
reactions=reactions,
|
|
173
|
-
punctual_reactions=punctual_reactions,
|
|
174
|
-
trajectory_attrs=trajectory_attrs,
|
|
175
|
-
n_simulations=n_simulations,
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
cmd = [beast_path]
|
|
179
|
-
if seed is not None:
|
|
180
|
-
cmd.extend(["-seed", str(seed)])
|
|
181
|
-
cmd.append(xml_file)
|
|
182
|
-
subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
183
|
-
|
|
184
|
-
_postprocess_tree(temp_tree_filename, tree_filename, ["type", "time"])
|
|
185
|
-
if output_xml_file is None:
|
|
186
|
-
subprocess.run(["rm", xml_file], check=True)
|
|
187
|
-
subprocess.run(["rm", temp_tree_filename], check=True)
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
|
|
3
|
-
import phylogenie.typings as pgt
|
|
4
|
-
from phylogenie.skyline import (
|
|
5
|
-
SkylineMatrixCoercible,
|
|
6
|
-
SkylineParameterLike,
|
|
7
|
-
SkylineVectorCoercible,
|
|
8
|
-
skyline_matrix,
|
|
9
|
-
skyline_vector,
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
SAMPLE_POPULATION = "sample"
|
|
13
|
-
DEFAULT_POPULATION = "X"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@dataclass
|
|
17
|
-
class Reaction:
|
|
18
|
-
rate: SkylineParameterLike
|
|
19
|
-
value: str
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@dataclass
|
|
23
|
-
class PunctualReaction:
|
|
24
|
-
times: pgt.ManyScalars
|
|
25
|
-
value: str
|
|
26
|
-
p: pgt.ManyScalars | None = None
|
|
27
|
-
n: pgt.Many[int] | None = None
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def get_canonical_reactions(
|
|
31
|
-
populations: str | list[str] = DEFAULT_POPULATION,
|
|
32
|
-
sample_population: str = SAMPLE_POPULATION,
|
|
33
|
-
birth_rates: SkylineVectorCoercible = 0,
|
|
34
|
-
death_rates: SkylineVectorCoercible = 0,
|
|
35
|
-
sampling_rates: SkylineVectorCoercible = 0,
|
|
36
|
-
removal_probabilities: SkylineVectorCoercible = 0,
|
|
37
|
-
migration_rates: SkylineMatrixCoercible = 0,
|
|
38
|
-
birth_rates_among_demes: SkylineMatrixCoercible = 0,
|
|
39
|
-
) -> list[Reaction]:
|
|
40
|
-
if isinstance(populations, str):
|
|
41
|
-
populations = [populations]
|
|
42
|
-
N = len(populations)
|
|
43
|
-
|
|
44
|
-
birth_rates = skyline_vector(birth_rates, N=N)
|
|
45
|
-
death_rates = skyline_vector(death_rates, N=N)
|
|
46
|
-
sampling_rates = skyline_vector(sampling_rates, N=N)
|
|
47
|
-
removal_probabilities = skyline_vector(removal_probabilities, N=N)
|
|
48
|
-
migration_rates = skyline_matrix(migration_rates, N=N, zero_diagonal=True)
|
|
49
|
-
birth_rates_among_demes = skyline_matrix(
|
|
50
|
-
birth_rates_among_demes, N=N, zero_diagonal=True
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
reactions: list[Reaction] = []
|
|
54
|
-
for i, population in enumerate(populations):
|
|
55
|
-
reactions.append(Reaction(birth_rates[i], f"{population} -> 2{population}"))
|
|
56
|
-
reactions.append(Reaction(death_rates[i], f"{population} -> 0"))
|
|
57
|
-
reactions.append(
|
|
58
|
-
Reaction(
|
|
59
|
-
sampling_rates[i] * removal_probabilities[i],
|
|
60
|
-
f"{population} -> {sample_population}",
|
|
61
|
-
)
|
|
62
|
-
)
|
|
63
|
-
reactions.append(
|
|
64
|
-
Reaction(
|
|
65
|
-
sampling_rates[i] * (1 - removal_probabilities[i]),
|
|
66
|
-
f"{population} -> {population} + {sample_population}",
|
|
67
|
-
)
|
|
68
|
-
)
|
|
69
|
-
for j, other_population in enumerate(populations):
|
|
70
|
-
if i == j:
|
|
71
|
-
continue
|
|
72
|
-
reactions.append(
|
|
73
|
-
Reaction(migration_rates[i][j], f"{population} -> {other_population}")
|
|
74
|
-
)
|
|
75
|
-
reactions.append(
|
|
76
|
-
Reaction(
|
|
77
|
-
birth_rates_among_demes[i][j],
|
|
78
|
-
f"{population} -> {population} + {other_population}",
|
|
79
|
-
)
|
|
80
|
-
)
|
|
81
|
-
return reactions
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def get_epidemiological_reactions(
|
|
85
|
-
populations: str | list[str] = DEFAULT_POPULATION,
|
|
86
|
-
sample_population: str = SAMPLE_POPULATION,
|
|
87
|
-
reproduction_numbers: SkylineVectorCoercible = 0,
|
|
88
|
-
become_uninfectious_rates: SkylineVectorCoercible = 0,
|
|
89
|
-
sampling_proportions: SkylineVectorCoercible = 0,
|
|
90
|
-
removal_probabilities: SkylineVectorCoercible = 0,
|
|
91
|
-
migration_rates: SkylineMatrixCoercible = 0,
|
|
92
|
-
reproduction_numbers_among_demes: SkylineMatrixCoercible = 0,
|
|
93
|
-
) -> list[Reaction]:
|
|
94
|
-
if isinstance(populations, str):
|
|
95
|
-
populations = [populations]
|
|
96
|
-
N = len(populations)
|
|
97
|
-
|
|
98
|
-
reproduction_numbers = skyline_vector(reproduction_numbers, N=N)
|
|
99
|
-
become_uninfectious_rates = skyline_vector(become_uninfectious_rates, N=N)
|
|
100
|
-
sampling_proportions = skyline_vector(sampling_proportions, N=N)
|
|
101
|
-
removal_probabilities = skyline_vector(removal_probabilities, N=N)
|
|
102
|
-
reproduction_numbers_among_demes = skyline_matrix(
|
|
103
|
-
reproduction_numbers_among_demes, N=N, zero_diagonal=True
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
birth_rates = reproduction_numbers * become_uninfectious_rates
|
|
107
|
-
birth_rates_among_demes = (
|
|
108
|
-
reproduction_numbers_among_demes * become_uninfectious_rates
|
|
109
|
-
)
|
|
110
|
-
sampling_rates = become_uninfectious_rates * sampling_proportions
|
|
111
|
-
death_rates = become_uninfectious_rates - removal_probabilities * sampling_rates
|
|
112
|
-
|
|
113
|
-
return get_canonical_reactions(
|
|
114
|
-
populations=populations,
|
|
115
|
-
sample_population=sample_population,
|
|
116
|
-
birth_rates=birth_rates,
|
|
117
|
-
death_rates=death_rates,
|
|
118
|
-
sampling_rates=sampling_rates,
|
|
119
|
-
removal_probabilities=removal_probabilities,
|
|
120
|
-
migration_rates=migration_rates,
|
|
121
|
-
birth_rates_among_demes=birth_rates_among_demes,
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def get_FBD_reactions(
|
|
126
|
-
populations: str | list[str] = DEFAULT_POPULATION,
|
|
127
|
-
sample_population: str = SAMPLE_POPULATION,
|
|
128
|
-
diversification: SkylineVectorCoercible = 0,
|
|
129
|
-
turnover: SkylineVectorCoercible = 0,
|
|
130
|
-
sampling_proportions: SkylineVectorCoercible = 0,
|
|
131
|
-
removal_probabilities: SkylineVectorCoercible = 0,
|
|
132
|
-
migration_rates: SkylineMatrixCoercible = 0,
|
|
133
|
-
diversification_between_types: SkylineMatrixCoercible = 0,
|
|
134
|
-
):
|
|
135
|
-
if isinstance(populations, str):
|
|
136
|
-
populations = [populations]
|
|
137
|
-
N = len(populations)
|
|
138
|
-
|
|
139
|
-
diversification = skyline_vector(diversification, N=N)
|
|
140
|
-
turnover = skyline_vector(turnover, N=N)
|
|
141
|
-
sampling_proportions = skyline_vector(sampling_proportions, N=N)
|
|
142
|
-
removal_probabilities = skyline_vector(removal_probabilities, N=N)
|
|
143
|
-
diversification_between_types = skyline_matrix(
|
|
144
|
-
diversification_between_types, N=N, zero_diagonal=True
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
birth_rates = diversification / (1 - turnover)
|
|
148
|
-
death_rates = turnover * birth_rates
|
|
149
|
-
sampling_rates = (
|
|
150
|
-
sampling_proportions
|
|
151
|
-
* death_rates
|
|
152
|
-
/ (1 - removal_probabilities * sampling_proportions)
|
|
153
|
-
)
|
|
154
|
-
birth_rates_among_demes = diversification_between_types + death_rates
|
|
155
|
-
|
|
156
|
-
return get_canonical_reactions(
|
|
157
|
-
populations=populations,
|
|
158
|
-
sample_population=sample_population,
|
|
159
|
-
birth_rates=birth_rates,
|
|
160
|
-
death_rates=death_rates,
|
|
161
|
-
sampling_rates=sampling_rates,
|
|
162
|
-
removal_probabilities=removal_probabilities,
|
|
163
|
-
migration_rates=migration_rates,
|
|
164
|
-
birth_rates_among_demes=birth_rates_among_demes,
|
|
165
|
-
)
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
from treesimulator import STATE, save_forest
|
|
5
|
-
from treesimulator.generator import generate
|
|
6
|
-
from treesimulator.mtbd_models import CTModel, Model
|
|
7
|
-
|
|
8
|
-
from phylogenie.skyline import (
|
|
9
|
-
SkylineMatrixCoercible,
|
|
10
|
-
SkylineParameterLike,
|
|
11
|
-
SkylineVectorCoercible,
|
|
12
|
-
skyline_matrix,
|
|
13
|
-
skyline_parameter,
|
|
14
|
-
skyline_vector,
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
DEFAULT_POPULATION = "X"
|
|
18
|
-
INFECTIOUS_POPULATION = "I"
|
|
19
|
-
EXPOSED_POPULATION = "E"
|
|
20
|
-
SUPERSPREADER_POPULATION = "S"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@dataclass
|
|
24
|
-
class TreeParams:
|
|
25
|
-
populations: str | list[str]
|
|
26
|
-
transmission_rates: SkylineMatrixCoercible
|
|
27
|
-
removal_rates: SkylineVectorCoercible
|
|
28
|
-
sampling_proportions: SkylineVectorCoercible
|
|
29
|
-
transition_rates: SkylineMatrixCoercible = 0
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def generate_tree(
|
|
33
|
-
output_file: str,
|
|
34
|
-
params: TreeParams,
|
|
35
|
-
min_tips: int,
|
|
36
|
-
max_tips: int,
|
|
37
|
-
T: float = np.inf,
|
|
38
|
-
state_frequencies: list[float] | None = None,
|
|
39
|
-
notification_probability: SkylineParameterLike = 0,
|
|
40
|
-
notification_sampling_rate: SkylineParameterLike = np.inf,
|
|
41
|
-
allow_irremovable_states: bool = False,
|
|
42
|
-
max_notified_contacts: int = 1,
|
|
43
|
-
root_state: str | None = None,
|
|
44
|
-
random_seed: int | None = None,
|
|
45
|
-
) -> None:
|
|
46
|
-
populations = params.populations
|
|
47
|
-
if isinstance(populations, str):
|
|
48
|
-
populations = [populations]
|
|
49
|
-
N = len(populations)
|
|
50
|
-
|
|
51
|
-
transition_rates = skyline_matrix(params.transition_rates, N=N, zero_diagonal=True)
|
|
52
|
-
transmission_rates = skyline_matrix(params.transmission_rates, N=N)
|
|
53
|
-
removal_rates = skyline_vector(params.removal_rates, N=N)
|
|
54
|
-
sampling_proportions = skyline_vector(params.sampling_proportions, N=N)
|
|
55
|
-
|
|
56
|
-
change_times = sorted(
|
|
57
|
-
set(
|
|
58
|
-
[
|
|
59
|
-
*transition_rates.change_times,
|
|
60
|
-
*transmission_rates.change_times,
|
|
61
|
-
*removal_rates.change_times,
|
|
62
|
-
*sampling_proportions.change_times,
|
|
63
|
-
]
|
|
64
|
-
)
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
models = [
|
|
68
|
-
Model(
|
|
69
|
-
states=populations,
|
|
70
|
-
transition_rates=transition_rates.get_value_at_time(t),
|
|
71
|
-
transmission_rates=transmission_rates.get_value_at_time(t),
|
|
72
|
-
removal_rates=removal_rates.get_value_at_time(t),
|
|
73
|
-
ps=sampling_proportions.get_value_at_time(t),
|
|
74
|
-
)
|
|
75
|
-
for t in [0, *change_times]
|
|
76
|
-
]
|
|
77
|
-
|
|
78
|
-
if notification_probability:
|
|
79
|
-
notification_sampling_rate = skyline_parameter(notification_sampling_rate)
|
|
80
|
-
notification_probability = skyline_parameter(notification_probability)
|
|
81
|
-
models = [
|
|
82
|
-
CTModel(
|
|
83
|
-
model,
|
|
84
|
-
phi=notification_sampling_rate.get_value_at_time(t),
|
|
85
|
-
upsilon=notification_probability.get_value_at_time(t),
|
|
86
|
-
allow_irremovable_states=allow_irremovable_states,
|
|
87
|
-
)
|
|
88
|
-
for t, model in zip([0, *change_times], models)
|
|
89
|
-
]
|
|
90
|
-
|
|
91
|
-
[tree], _, _ = generate(
|
|
92
|
-
models,
|
|
93
|
-
min_tips=min_tips,
|
|
94
|
-
max_tips=max_tips,
|
|
95
|
-
T=T,
|
|
96
|
-
skyline_times=change_times,
|
|
97
|
-
state_frequencies=state_frequencies,
|
|
98
|
-
max_notified_contacts=max_notified_contacts,
|
|
99
|
-
root_state=root_state,
|
|
100
|
-
random_seed=random_seed,
|
|
101
|
-
)
|
|
102
|
-
for i, leaf in enumerate(tree.iter_leaves()):
|
|
103
|
-
state: str = getattr(leaf, STATE)
|
|
104
|
-
delattr(leaf, STATE)
|
|
105
|
-
date = tree.get_distance(leaf)
|
|
106
|
-
leaf.name = f"{i}|{state}|{date}"
|
|
107
|
-
save_forest([tree], output_file)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def get_BD_params(
|
|
111
|
-
reproduction_number: SkylineParameterLike,
|
|
112
|
-
infectious_period: SkylineParameterLike,
|
|
113
|
-
sampling_proportion: SkylineParameterLike,
|
|
114
|
-
) -> TreeParams:
|
|
115
|
-
transmission_rate = reproduction_number / infectious_period
|
|
116
|
-
removal_rate = 1 / infectious_period
|
|
117
|
-
return TreeParams(
|
|
118
|
-
populations=INFECTIOUS_POPULATION,
|
|
119
|
-
transmission_rates=transmission_rate,
|
|
120
|
-
removal_rates=removal_rate,
|
|
121
|
-
sampling_proportions=sampling_proportion,
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def get_BDEI_params(
|
|
126
|
-
reproduction_number: SkylineParameterLike,
|
|
127
|
-
infectious_period: SkylineParameterLike,
|
|
128
|
-
incubation_period: SkylineParameterLike,
|
|
129
|
-
sampling_proportion: SkylineParameterLike,
|
|
130
|
-
) -> TreeParams:
|
|
131
|
-
transmission_rates = [[0, 0], [reproduction_number / infectious_period, 0]]
|
|
132
|
-
transition_rates = [[0, 1 / incubation_period], [0, 0]]
|
|
133
|
-
removal_rates = [0, 1 / infectious_period]
|
|
134
|
-
sampling_proportions = [0, sampling_proportion]
|
|
135
|
-
return TreeParams(
|
|
136
|
-
populations=[EXPOSED_POPULATION, INFECTIOUS_POPULATION],
|
|
137
|
-
transition_rates=transition_rates,
|
|
138
|
-
transmission_rates=transmission_rates,
|
|
139
|
-
removal_rates=removal_rates,
|
|
140
|
-
sampling_proportions=sampling_proportions,
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def get_BDSS_params(
|
|
145
|
-
reproduction_number: SkylineParameterLike,
|
|
146
|
-
infectious_period: SkylineParameterLike,
|
|
147
|
-
superspreading_ratio: SkylineParameterLike,
|
|
148
|
-
superspreaders_proportion: SkylineParameterLike,
|
|
149
|
-
sampling_proportion: SkylineParameterLike,
|
|
150
|
-
) -> TreeParams:
|
|
151
|
-
gamma = 1 / infectious_period
|
|
152
|
-
f_SS = superspreaders_proportion
|
|
153
|
-
r_SS = superspreading_ratio
|
|
154
|
-
lambda_IS = reproduction_number * gamma * f_SS / (1 + r_SS * f_SS - f_SS)
|
|
155
|
-
lambda_SI = (reproduction_number * gamma - r_SS * lambda_IS) * r_SS
|
|
156
|
-
lambda_SS = r_SS * lambda_IS
|
|
157
|
-
lambda_II = lambda_SI / r_SS
|
|
158
|
-
return TreeParams(
|
|
159
|
-
populations=[INFECTIOUS_POPULATION, SUPERSPREADER_POPULATION],
|
|
160
|
-
transmission_rates=[[lambda_II, lambda_IS], [lambda_SI, lambda_SS]],
|
|
161
|
-
removal_rates=gamma,
|
|
162
|
-
sampling_proportions=sampling_proportion,
|
|
163
|
-
)
|
phylogenie/configs.py
DELETED
phylogenie/core/__init__.py
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
from typing import Annotated
|
|
2
|
-
|
|
3
|
-
from pydantic import Field
|
|
4
|
-
|
|
5
|
-
from phylogenie.core.dataset import DatasetGenerator
|
|
6
|
-
from phylogenie.core.msas import MSAsGeneratorConfig
|
|
7
|
-
from phylogenie.core.trees import TreesGeneratorConfig
|
|
8
|
-
|
|
9
|
-
DatasetGeneratorConfig = Annotated[
|
|
10
|
-
TreesGeneratorConfig | MSAsGeneratorConfig,
|
|
11
|
-
Field(discriminator="data_type"),
|
|
12
|
-
]
|
|
13
|
-
|
|
14
|
-
__all__ = ["DatasetGeneratorConfig", "DatasetGenerator"]
|
phylogenie/core/configs.py
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import phylogenie.typings as pgt
|
|
2
|
-
from phylogenie.configs import StrictBaseModel
|
|
3
|
-
|
|
4
|
-
IntConfig = str | int
|
|
5
|
-
ScalarConfig = str | pgt.Scalar
|
|
6
|
-
ManyIntsConfig = str | list[IntConfig]
|
|
7
|
-
ManyScalarsConfig = str | list[ScalarConfig]
|
|
8
|
-
OneOrManyScalarsConfig = ScalarConfig | list[ScalarConfig]
|
|
9
|
-
OneOrMany2DScalarsConfig = ScalarConfig | list[list[ScalarConfig]]
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class SkylineParameterValueModel(StrictBaseModel):
|
|
13
|
-
value: ManyScalarsConfig
|
|
14
|
-
change_times: ManyScalarsConfig
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
SkylineParameterLikeConfig = ScalarConfig | SkylineParameterValueModel
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class SkylineVectorValueModel(StrictBaseModel):
|
|
21
|
-
value: str | list[OneOrManyScalarsConfig]
|
|
22
|
-
change_times: ManyScalarsConfig
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
SkylineVectorCoercibleConfig = (
|
|
26
|
-
str | pgt.Scalar | list[SkylineParameterLikeConfig] | SkylineVectorValueModel
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class SkylineMatrixValueModel(StrictBaseModel):
|
|
31
|
-
value: str | list[OneOrMany2DScalarsConfig]
|
|
32
|
-
change_times: ManyScalarsConfig
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
SkylineMatrixCoercibleConfig = (
|
|
36
|
-
str | pgt.Scalar | list[SkylineVectorCoercibleConfig] | SkylineMatrixValueModel
|
|
37
|
-
)
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
from phylogenie.configs import StrictBaseModel
|
|
2
|
-
from phylogenie.core.context.distributions import (
|
|
3
|
-
DistributionConfig,
|
|
4
|
-
ScalarDistributionConfig,
|
|
5
|
-
)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class VectorModel(StrictBaseModel):
|
|
9
|
-
x: ScalarDistributionConfig
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class Vector1DModel(VectorModel):
|
|
13
|
-
size: int
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class Vector2DModel(VectorModel):
|
|
17
|
-
size: tuple[int, int]
|
|
18
|
-
zero_diagonal: bool = False
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class Vector3DModel(VectorModel):
|
|
22
|
-
size: tuple[int, int, int]
|
|
23
|
-
zero_diagonal: bool = False
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
ContextConfig = dict[
|
|
27
|
-
str, DistributionConfig | Vector1DModel | Vector2DModel | Vector3DModel
|
|
28
|
-
]
|