phylogenie 1.0.1__py3-none-any.whl → 1.0.2__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/backend/remaster/generate.py +3 -4
- phylogenie/backend/remaster/reactions.py +23 -23
- phylogenie/backend/treesimulator.py +6 -6
- phylogenie/core/configs.py +17 -12
- phylogenie/core/context/factories.py +5 -8
- phylogenie/core/dataset.py +3 -3
- phylogenie/core/factories.py +146 -69
- phylogenie/core/msas/alisim.py +2 -2
- phylogenie/core/msas/base.py +3 -3
- phylogenie/core/trees/remaster/configs.py +3 -3
- phylogenie/core/trees/remaster/factories.py +8 -12
- phylogenie/core/trees/remaster/generator.py +55 -47
- phylogenie/core/trees/treesimulator.py +17 -15
- phylogenie/core/typeguards.py +12 -20
- phylogenie/skyline/__init__.py +14 -4
- phylogenie/skyline/matrix.py +45 -55
- phylogenie/skyline/parameter.py +29 -20
- phylogenie/skyline/vector.py +42 -51
- phylogenie/typeguards.py +10 -8
- phylogenie/typings.py +8 -7
- {phylogenie-1.0.1.dist-info → phylogenie-1.0.2.dist-info}/METADATA +2 -2
- phylogenie-1.0.2.dist-info/RECORD +39 -0
- phylogenie/core/typings.py +0 -10
- phylogenie/utils.py +0 -20
- phylogenie-1.0.1.dist-info/RECORD +0 -41
- {phylogenie-1.0.1.dist-info → phylogenie-1.0.2.dist-info}/LICENSE.txt +0 -0
- {phylogenie-1.0.1.dist-info → phylogenie-1.0.2.dist-info}/WHEEL +0 -0
- {phylogenie-1.0.1.dist-info → phylogenie-1.0.2.dist-info}/entry_points.txt +0 -0
|
@@ -11,7 +11,6 @@ from phylogenie.backend.remaster.reactions import (
|
|
|
11
11
|
Reaction,
|
|
12
12
|
)
|
|
13
13
|
from phylogenie.skyline import skyline_parameter
|
|
14
|
-
from phylogenie.utils import vectorify1D
|
|
15
14
|
|
|
16
15
|
TREE_ID = "Tree"
|
|
17
16
|
|
|
@@ -75,12 +74,12 @@ def _generate_config_file(
|
|
|
75
74
|
attrs = {
|
|
76
75
|
"spec": "PunctualReaction",
|
|
77
76
|
"value": punctual_reaction.value,
|
|
78
|
-
"times": " ".join(map(str,
|
|
77
|
+
"times": " ".join(map(str, punctual_reaction.times)),
|
|
79
78
|
}
|
|
80
79
|
if punctual_reaction.p is not None:
|
|
81
|
-
attrs["p"] = " ".join(map(str,
|
|
80
|
+
attrs["p"] = " ".join(map(str, punctual_reaction.p))
|
|
82
81
|
if punctual_reaction.n is not None:
|
|
83
|
-
attrs["n"] = " ".join(map(str,
|
|
82
|
+
attrs["n"] = " ".join(map(str, punctual_reaction.n))
|
|
84
83
|
trajectory.append(Element("reaction", attrs))
|
|
85
84
|
|
|
86
85
|
simulate.append(trajectory)
|
|
@@ -2,9 +2,9 @@ from dataclasses import dataclass
|
|
|
2
2
|
|
|
3
3
|
import phylogenie.typings as pgt
|
|
4
4
|
from phylogenie.skyline import (
|
|
5
|
-
|
|
5
|
+
SkylineMatrixCoercible,
|
|
6
6
|
SkylineParameterLike,
|
|
7
|
-
|
|
7
|
+
SkylineVectorCoercible,
|
|
8
8
|
skyline_matrix,
|
|
9
9
|
skyline_vector,
|
|
10
10
|
)
|
|
@@ -21,21 +21,21 @@ class Reaction:
|
|
|
21
21
|
|
|
22
22
|
@dataclass
|
|
23
23
|
class PunctualReaction:
|
|
24
|
-
times: pgt.
|
|
24
|
+
times: pgt.ManyScalars
|
|
25
25
|
value: str
|
|
26
|
-
p: pgt.
|
|
27
|
-
n: pgt.
|
|
26
|
+
p: pgt.ManyScalars | None = None
|
|
27
|
+
n: pgt.Many[int] | None = None
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
def get_canonical_reactions(
|
|
31
31
|
populations: str | list[str] = DEFAULT_POPULATION,
|
|
32
32
|
sample_population: str = SAMPLE_POPULATION,
|
|
33
|
-
birth_rates:
|
|
34
|
-
death_rates:
|
|
35
|
-
sampling_rates:
|
|
36
|
-
removal_probabilities:
|
|
37
|
-
migration_rates:
|
|
38
|
-
birth_rates_among_demes:
|
|
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
39
|
) -> list[Reaction]:
|
|
40
40
|
if isinstance(populations, str):
|
|
41
41
|
populations = [populations]
|
|
@@ -84,12 +84,12 @@ def get_canonical_reactions(
|
|
|
84
84
|
def get_epidemiological_reactions(
|
|
85
85
|
populations: str | list[str] = DEFAULT_POPULATION,
|
|
86
86
|
sample_population: str = SAMPLE_POPULATION,
|
|
87
|
-
reproduction_numbers:
|
|
88
|
-
become_uninfectious_rates:
|
|
89
|
-
sampling_proportions:
|
|
90
|
-
removal_probabilities:
|
|
91
|
-
migration_rates:
|
|
92
|
-
reproduction_numbers_among_demes:
|
|
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
93
|
) -> list[Reaction]:
|
|
94
94
|
if isinstance(populations, str):
|
|
95
95
|
populations = [populations]
|
|
@@ -125,12 +125,12 @@ def get_epidemiological_reactions(
|
|
|
125
125
|
def get_FBD_reactions(
|
|
126
126
|
populations: str | list[str] = DEFAULT_POPULATION,
|
|
127
127
|
sample_population: str = SAMPLE_POPULATION,
|
|
128
|
-
diversification:
|
|
129
|
-
turnover:
|
|
130
|
-
sampling_proportions:
|
|
131
|
-
removal_probabilities:
|
|
132
|
-
migration_rates:
|
|
133
|
-
diversification_between_types:
|
|
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
134
|
):
|
|
135
135
|
if isinstance(populations, str):
|
|
136
136
|
populations = [populations]
|
|
@@ -6,9 +6,9 @@ from treesimulator.generator import generate
|
|
|
6
6
|
from treesimulator.mtbd_models import CTModel, Model
|
|
7
7
|
|
|
8
8
|
from phylogenie.skyline import (
|
|
9
|
-
|
|
9
|
+
SkylineMatrixCoercible,
|
|
10
10
|
SkylineParameterLike,
|
|
11
|
-
|
|
11
|
+
SkylineVectorCoercible,
|
|
12
12
|
skyline_matrix,
|
|
13
13
|
skyline_parameter,
|
|
14
14
|
skyline_vector,
|
|
@@ -22,10 +22,10 @@ EXPOSED_POPULATION = "E"
|
|
|
22
22
|
@dataclass
|
|
23
23
|
class TreeParams:
|
|
24
24
|
populations: str | list[str] = DEFAULT_POPULATION
|
|
25
|
-
transition_rates:
|
|
26
|
-
transmission_rates:
|
|
27
|
-
removal_rates:
|
|
28
|
-
sampling_proportions:
|
|
25
|
+
transition_rates: SkylineMatrixCoercible = 0
|
|
26
|
+
transmission_rates: SkylineMatrixCoercible = 0
|
|
27
|
+
removal_rates: SkylineVectorCoercible = 0
|
|
28
|
+
sampling_proportions: SkylineVectorCoercible = 0
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
def generate_tree(
|
phylogenie/core/configs.py
CHANGED
|
@@ -3,33 +3,38 @@ from phylogenie.configs import StrictBaseModel
|
|
|
3
3
|
|
|
4
4
|
IntConfig = str | int
|
|
5
5
|
ScalarConfig = str | pgt.Scalar
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
ManyIntsConfig = str | list[IntConfig]
|
|
7
|
+
ManyScalarsConfig = str | list[ScalarConfig]
|
|
8
|
+
OneOrManyScalarsConfig = ScalarConfig | list[ScalarConfig]
|
|
9
|
+
OneOrMany2DScalarsConfig = ScalarConfig | list[list[ScalarConfig]]
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class SkylineParameterValueModel(StrictBaseModel):
|
|
11
|
-
value:
|
|
12
|
-
change_times:
|
|
13
|
+
value: ManyScalarsConfig
|
|
14
|
+
change_times: ManyScalarsConfig
|
|
13
15
|
|
|
14
16
|
|
|
15
|
-
SkylineParameterLikeConfig =
|
|
17
|
+
SkylineParameterLikeConfig = ScalarConfig | SkylineParameterValueModel
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
class SkylineVectorValueModel(StrictBaseModel):
|
|
19
|
-
value: str |
|
|
20
|
-
change_times:
|
|
21
|
+
value: str | list[OneOrManyScalarsConfig]
|
|
22
|
+
change_times: ManyScalarsConfig
|
|
21
23
|
|
|
22
24
|
|
|
25
|
+
SkylineVectorCoercibleConfig = (
|
|
26
|
+
str | pgt.Scalar | list[SkylineParameterLikeConfig] | SkylineVectorValueModel
|
|
27
|
+
)
|
|
23
28
|
SkylineVectorLikeConfig = (
|
|
24
|
-
str |
|
|
29
|
+
str | list[SkylineParameterLikeConfig] | SkylineVectorValueModel
|
|
25
30
|
)
|
|
26
31
|
|
|
27
32
|
|
|
28
33
|
class SkylineMatrixValueModel(StrictBaseModel):
|
|
29
|
-
value: str |
|
|
30
|
-
change_times:
|
|
34
|
+
value: str | list[OneOrMany2DScalarsConfig]
|
|
35
|
+
change_times: ManyScalarsConfig
|
|
31
36
|
|
|
32
37
|
|
|
33
|
-
|
|
34
|
-
str | pgt.Scalar |
|
|
38
|
+
SkylineMatrixCoercibleConfig = (
|
|
39
|
+
str | pgt.Scalar | list[SkylineVectorLikeConfig] | SkylineMatrixValueModel
|
|
35
40
|
)
|
|
@@ -3,18 +3,15 @@ from numpy.random import Generator
|
|
|
3
3
|
import phylogenie.core.context.configs as cfg
|
|
4
4
|
import phylogenie.typings as pgt
|
|
5
5
|
from phylogenie.core.context import distributions
|
|
6
|
-
from phylogenie.core.typings import Data
|
|
7
6
|
|
|
8
7
|
|
|
9
|
-
def _sample_vector1D(
|
|
10
|
-
x: distributions.Scalar, N: int, rng: Generator
|
|
11
|
-
) -> list[pgt.Scalar]:
|
|
8
|
+
def _sample_vector1D(x: distributions.Scalar, N: int, rng: Generator) -> pgt.Vector1D:
|
|
12
9
|
return [x.sample(rng) for _ in range(N)]
|
|
13
10
|
|
|
14
11
|
|
|
15
12
|
def _sample_vector2D(
|
|
16
13
|
x: distributions.Scalar, N: int, zero_diagonal: bool, rng: Generator
|
|
17
|
-
) ->
|
|
14
|
+
) -> pgt.Vector2D:
|
|
18
15
|
v = [_sample_vector1D(x, N, rng) for _ in range(N)]
|
|
19
16
|
if zero_diagonal:
|
|
20
17
|
for i in range(N):
|
|
@@ -24,12 +21,12 @@ def _sample_vector2D(
|
|
|
24
21
|
|
|
25
22
|
def _sample_vector3D(
|
|
26
23
|
x: distributions.Scalar, N: int, T: int, zero_diagonal: bool, rng: Generator
|
|
27
|
-
) ->
|
|
24
|
+
) -> pgt.Vector3D:
|
|
28
25
|
return [_sample_vector2D(x, N, zero_diagonal, rng) for _ in range(T)]
|
|
29
26
|
|
|
30
27
|
|
|
31
|
-
def context_factory(x: cfg.ContextConfig, rng: Generator) -> Data:
|
|
32
|
-
data: Data = {}
|
|
28
|
+
def context_factory(x: cfg.ContextConfig, rng: Generator) -> pgt.Data:
|
|
29
|
+
data: pgt.Data = {}
|
|
33
30
|
for key, value in x.items():
|
|
34
31
|
if isinstance(value, distributions.Distribution):
|
|
35
32
|
data[key] = value.sample(rng)
|
phylogenie/core/dataset.py
CHANGED
|
@@ -7,9 +7,9 @@ import pandas as pd
|
|
|
7
7
|
from numpy.random import Generator, default_rng
|
|
8
8
|
from tqdm import tqdm
|
|
9
9
|
|
|
10
|
+
import phylogenie.typings as pgt
|
|
10
11
|
from phylogenie.configs import StrictBaseModel
|
|
11
12
|
from phylogenie.core.context import ContextConfig, context_factory
|
|
12
|
-
from phylogenie.core.typings import Data
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class DataType(str, Enum):
|
|
@@ -27,10 +27,10 @@ class DatasetGenerator(ABC, StrictBaseModel):
|
|
|
27
27
|
context: ContextConfig | None = None
|
|
28
28
|
|
|
29
29
|
@abstractmethod
|
|
30
|
-
def _generate_one(self, filename: str, rng: Generator, data: Data) -> None: ...
|
|
30
|
+
def _generate_one(self, filename: str, rng: Generator, data: pgt.Data) -> None: ...
|
|
31
31
|
|
|
32
32
|
def generate_one(
|
|
33
|
-
self, filename: str, data: Data | None = None, seed: int | None = None
|
|
33
|
+
self, filename: str, data: pgt.Data | None = None, seed: int | None = None
|
|
34
34
|
) -> None:
|
|
35
35
|
data = {} if data is None else data
|
|
36
36
|
self._generate_one(filename=filename, rng=default_rng(seed), data=data)
|
phylogenie/core/factories.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any
|
|
1
|
+
from typing import Any, overload
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
@@ -6,28 +6,32 @@ import phylogenie.core.configs as cfg
|
|
|
6
6
|
import phylogenie.core.typeguards as ctg
|
|
7
7
|
import phylogenie.typeguards as tg
|
|
8
8
|
import phylogenie.typings as pgt
|
|
9
|
-
from phylogenie.core.typings import Data
|
|
10
9
|
from phylogenie.skyline import (
|
|
11
10
|
SkylineMatrix,
|
|
12
|
-
|
|
11
|
+
SkylineMatrixCoercible,
|
|
13
12
|
SkylineParameter,
|
|
14
13
|
SkylineParameterLike,
|
|
15
14
|
SkylineVector,
|
|
15
|
+
SkylineVectorCoercible,
|
|
16
16
|
SkylineVectorLike,
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def _eval_expression(expression: str, data: Data) -> Any:
|
|
20
|
+
def _eval_expression(expression: str, data: pgt.Data) -> Any:
|
|
21
21
|
return np.array(
|
|
22
22
|
eval(
|
|
23
23
|
expression,
|
|
24
|
-
{
|
|
24
|
+
{
|
|
25
|
+
"__builtins__": __builtins__,
|
|
26
|
+
# "np": np,
|
|
27
|
+
# **{k: np.array(v) for k, v in data.items()},
|
|
28
|
+
},
|
|
25
29
|
{k: np.array(v) for k, v in data.items()},
|
|
26
30
|
)
|
|
27
31
|
).tolist()
|
|
28
32
|
|
|
29
33
|
|
|
30
|
-
def int_factory(x: cfg.IntConfig, data: Data) -> int:
|
|
34
|
+
def int_factory(x: cfg.IntConfig, data: pgt.Data) -> int:
|
|
31
35
|
if isinstance(x, str):
|
|
32
36
|
e = _eval_expression(x, data)
|
|
33
37
|
if isinstance(e, int):
|
|
@@ -38,7 +42,7 @@ def int_factory(x: cfg.IntConfig, data: Data) -> int:
|
|
|
38
42
|
return x
|
|
39
43
|
|
|
40
44
|
|
|
41
|
-
def scalar_factory(x: cfg.ScalarConfig, data: Data) -> pgt.Scalar:
|
|
45
|
+
def scalar_factory(x: cfg.ScalarConfig, data: pgt.Data) -> pgt.Scalar:
|
|
42
46
|
if isinstance(x, str):
|
|
43
47
|
e = _eval_expression(x, data)
|
|
44
48
|
if isinstance(e, pgt.Scalar):
|
|
@@ -49,130 +53,203 @@ def scalar_factory(x: cfg.ScalarConfig, data: Data) -> pgt.Scalar:
|
|
|
49
53
|
return x
|
|
50
54
|
|
|
51
55
|
|
|
52
|
-
def
|
|
53
|
-
x: cfg.OneOrManyScalarsConfig, data: Data
|
|
54
|
-
) -> pgt.OneOrMany[pgt.Scalar]:
|
|
56
|
+
def many_ints_factory(x: cfg.ManyIntsConfig, data: pgt.Data) -> pgt.Many[int]:
|
|
55
57
|
if isinstance(x, str):
|
|
56
58
|
e = _eval_expression(x, data)
|
|
57
|
-
if tg.
|
|
59
|
+
if tg.is_many_ints(e):
|
|
58
60
|
return e
|
|
59
61
|
raise ValueError(
|
|
60
|
-
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected a
|
|
62
|
+
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected a sequence of integers."
|
|
61
63
|
)
|
|
62
|
-
|
|
63
|
-
return x
|
|
64
|
-
return [scalar_factory(v, data) for v in x]
|
|
64
|
+
return [int_factory(v, data) for v in x]
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
def
|
|
68
|
-
x: cfg.OneOrManyIntsConfig, data: Data
|
|
69
|
-
) -> pgt.OneOrMany[int]:
|
|
67
|
+
def many_scalars_factory(x: cfg.ManyScalarsConfig, data: pgt.Data) -> pgt.ManyScalars:
|
|
70
68
|
if isinstance(x, str):
|
|
71
69
|
e = _eval_expression(x, data)
|
|
72
|
-
if tg.
|
|
70
|
+
if tg.is_many_scalars(e):
|
|
73
71
|
return e
|
|
74
72
|
raise ValueError(
|
|
75
|
-
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected
|
|
73
|
+
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected a sequence of scalars."
|
|
76
74
|
)
|
|
77
|
-
|
|
78
|
-
return x
|
|
79
|
-
return [int_factory(v, data) for v in x]
|
|
75
|
+
return [scalar_factory(v, data) for v in x]
|
|
80
76
|
|
|
81
77
|
|
|
82
|
-
def
|
|
83
|
-
x: cfg.
|
|
84
|
-
) ->
|
|
78
|
+
def one_or_many_scalars_factory(
|
|
79
|
+
x: cfg.OneOrManyScalarsConfig, data: pgt.Data
|
|
80
|
+
) -> pgt.OneOrManyScalars:
|
|
85
81
|
if isinstance(x, str):
|
|
86
82
|
e = _eval_expression(x, data)
|
|
87
|
-
if
|
|
83
|
+
if tg.is_one_or_many_scalars(e):
|
|
88
84
|
return e
|
|
89
85
|
raise ValueError(
|
|
90
|
-
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected a
|
|
86
|
+
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected a scalar or a sequence of them."
|
|
91
87
|
)
|
|
92
88
|
if isinstance(x, pgt.Scalar):
|
|
93
89
|
return x
|
|
90
|
+
return many_scalars_factory(x, data)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def skyline_parameter_like_factory(
|
|
94
|
+
x: cfg.SkylineParameterLikeConfig, data: pgt.Data
|
|
95
|
+
) -> SkylineParameterLike:
|
|
96
|
+
if isinstance(x, cfg.ScalarConfig):
|
|
97
|
+
return scalar_factory(x, data)
|
|
98
|
+
return SkylineParameter(
|
|
99
|
+
value=many_scalars_factory(x.value, data),
|
|
100
|
+
change_times=many_scalars_factory(x.change_times, data),
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
from typing import Literal
|
|
94
105
|
|
|
106
|
+
|
|
107
|
+
@overload
|
|
108
|
+
def _parse_skyline_vector_value_model(
|
|
109
|
+
x: cfg.SkylineVectorValueModel, data: pgt.Data, coercible: Literal[True]
|
|
110
|
+
) -> SkylineVector | SkylineParameter: ...
|
|
111
|
+
@overload
|
|
112
|
+
def _parse_skyline_vector_value_model(
|
|
113
|
+
x: cfg.SkylineVectorValueModel, data: pgt.Data, coercible: Literal[False]
|
|
114
|
+
) -> SkylineVector: ...
|
|
115
|
+
def _parse_skyline_vector_value_model(
|
|
116
|
+
x: cfg.SkylineVectorValueModel, data: pgt.Data, coercible: bool
|
|
117
|
+
) -> SkylineVector | SkylineParameter:
|
|
118
|
+
change_times = many_scalars_factory(x.change_times, data)
|
|
95
119
|
if isinstance(x.value, str):
|
|
96
120
|
e = _eval_expression(x.value, data)
|
|
97
|
-
if tg.
|
|
121
|
+
if tg.is_many_one_or_many_scalars(e):
|
|
98
122
|
value = e
|
|
99
123
|
else:
|
|
100
124
|
raise ValueError(
|
|
101
|
-
f"Expression '{x.value}' evaluated to {e} of type {type(e)}, which
|
|
125
|
+
f"Expression '{x.value}' evaluated to {e} of type {type(e)}, which cannot be coerced to a valid value for a SkylineVector (expected a sequence composed of scalars and/or sequences of scalars)."
|
|
102
126
|
)
|
|
103
127
|
else:
|
|
104
|
-
value = [
|
|
105
|
-
|
|
128
|
+
value = [one_or_many_scalars_factory(v, data) for v in x.value]
|
|
129
|
+
|
|
130
|
+
if tg.is_many_scalars(value):
|
|
131
|
+
if coercible:
|
|
132
|
+
return SkylineParameter(value=value, change_times=change_times)
|
|
133
|
+
else:
|
|
134
|
+
raise ValueError(
|
|
135
|
+
f"Parsing SkylineVector value {x.value} yielded a sequence of scalars ({value}) when a nested (2D) sequence of scalars was expected."
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
Ns = {len(elem) for elem in value if tg.is_many(elem)}
|
|
139
|
+
if len(Ns) > 1:
|
|
140
|
+
raise ValueError(
|
|
141
|
+
f"All elements in the value of a SkylineVector config must be scalars or have the same length (got value={value} with inconsistent lengths {Ns})."
|
|
142
|
+
)
|
|
143
|
+
(N,) = Ns
|
|
144
|
+
value = [[p] * N if isinstance(p, pgt.Scalar) else p for p in value]
|
|
145
|
+
|
|
146
|
+
return SkylineVector(
|
|
106
147
|
value=value,
|
|
107
|
-
change_times=
|
|
148
|
+
change_times=change_times,
|
|
108
149
|
)
|
|
109
150
|
|
|
110
151
|
|
|
111
|
-
def
|
|
112
|
-
x: cfg.
|
|
113
|
-
) ->
|
|
152
|
+
def skyline_vector_coercible_factory(
|
|
153
|
+
x: cfg.SkylineVectorCoercibleConfig, data: pgt.Data
|
|
154
|
+
) -> SkylineVectorCoercible:
|
|
114
155
|
if isinstance(x, str):
|
|
115
156
|
e = _eval_expression(x, data)
|
|
116
157
|
if tg.is_one_or_many_scalars(e):
|
|
117
158
|
return e
|
|
118
159
|
raise ValueError(
|
|
119
|
-
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected a
|
|
160
|
+
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected a SkylineVectorCoercible object (e.g., a scalar or a sequence of them)."
|
|
120
161
|
)
|
|
121
162
|
if isinstance(x, pgt.Scalar):
|
|
122
163
|
return x
|
|
123
|
-
if ctg.
|
|
164
|
+
if ctg.is_list_of_skyline_parameter_like_configs(x):
|
|
124
165
|
return [skyline_parameter_like_factory(p, data) for p in x]
|
|
125
166
|
|
|
126
167
|
assert isinstance(x, cfg.SkylineVectorValueModel)
|
|
127
|
-
|
|
128
|
-
e = _eval_expression(x.value, data)
|
|
129
|
-
if tg.is_many_one_or_many_scalars(e):
|
|
130
|
-
value = e
|
|
131
|
-
else:
|
|
132
|
-
raise ValueError(
|
|
133
|
-
f"Expression '{x.value}' evaluated to {e} of type {type(e)}, which is not a valid value for a SkylineVector (expected a sequence containing scalars and/or sequences of them)."
|
|
134
|
-
)
|
|
135
|
-
else:
|
|
136
|
-
value = [one_or_many_scalars_factory(x, data) for x in x.value]
|
|
137
|
-
return SkylineVector(
|
|
138
|
-
value=value,
|
|
139
|
-
change_times=one_or_many_scalars_factory(x.change_times, data),
|
|
140
|
-
)
|
|
168
|
+
return _parse_skyline_vector_value_model(x, data, coercible=True)
|
|
141
169
|
|
|
142
170
|
|
|
143
|
-
def
|
|
144
|
-
x: cfg.
|
|
145
|
-
) ->
|
|
171
|
+
def skyline_vector_like_factory(
|
|
172
|
+
x: cfg.SkylineVectorLikeConfig, data: pgt.Data
|
|
173
|
+
) -> SkylineVectorLike:
|
|
146
174
|
if isinstance(x, str):
|
|
147
175
|
e = _eval_expression(x, data)
|
|
148
|
-
if tg.
|
|
176
|
+
if tg.is_many_scalars(e):
|
|
149
177
|
return e
|
|
150
178
|
raise ValueError(
|
|
151
|
-
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected a
|
|
179
|
+
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected a SkylineVectorLike object (e.g., a sequence of scalars)."
|
|
180
|
+
)
|
|
181
|
+
if ctg.is_list_of_skyline_parameter_like_configs(x):
|
|
182
|
+
return [skyline_parameter_like_factory(p, data) for p in x]
|
|
183
|
+
|
|
184
|
+
assert isinstance(x, cfg.SkylineVectorValueModel)
|
|
185
|
+
return _parse_skyline_vector_value_model(x, data, coercible=False)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def one_or_many_2D_scalars_factory(
|
|
189
|
+
x: cfg.OneOrMany2DScalarsConfig, data: pgt.Data
|
|
190
|
+
) -> pgt.OneOrMany2DScalars:
|
|
191
|
+
if isinstance(x, str):
|
|
192
|
+
e = _eval_expression(x, data)
|
|
193
|
+
if tg.is_one_or_many_2D_scalars(e):
|
|
194
|
+
return e
|
|
195
|
+
raise ValueError(
|
|
196
|
+
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected a nested (2D) sequence of scalars."
|
|
152
197
|
)
|
|
153
198
|
if isinstance(x, pgt.Scalar):
|
|
154
199
|
return x
|
|
155
|
-
|
|
200
|
+
return [many_scalars_factory(v, data) for v in x]
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def skyline_matrix_coercible_factory(
|
|
204
|
+
x: cfg.SkylineMatrixCoercibleConfig, data: pgt.Data
|
|
205
|
+
) -> SkylineMatrixCoercible:
|
|
206
|
+
if isinstance(x, str):
|
|
207
|
+
e = _eval_expression(x, data)
|
|
208
|
+
if tg.is_one_or_many_2D_scalars(e):
|
|
209
|
+
return e
|
|
210
|
+
raise ValueError(
|
|
211
|
+
f"Expression '{x}' evaluated to {e} of type {type(e)}, expected a SkylineMatrixCoercible object (e.g., a scalar or a nested (2D) sequence of them)."
|
|
212
|
+
)
|
|
213
|
+
if isinstance(x, pgt.Scalar):
|
|
214
|
+
return x
|
|
215
|
+
if ctg.is_list_of_skyline_vector_like_configs(x):
|
|
156
216
|
return [skyline_vector_like_factory(v, data) for v in x]
|
|
157
217
|
|
|
158
218
|
assert isinstance(x, cfg.SkylineMatrixValueModel)
|
|
219
|
+
|
|
220
|
+
change_times = many_scalars_factory(x.change_times, data)
|
|
159
221
|
if isinstance(x.value, str):
|
|
160
222
|
e = _eval_expression(x.value, data)
|
|
161
|
-
if tg.
|
|
223
|
+
if tg.is_many_one_or_many_2D_scalars(e):
|
|
162
224
|
value = e
|
|
163
225
|
else:
|
|
164
226
|
raise ValueError(
|
|
165
|
-
f"Expression '{x.value}' evaluated to {e} of type {type(e)}, which
|
|
227
|
+
f"Expression '{x.value}' evaluated to {e} of type {type(e)}, which cannot be coerced to a valid value for a SkylineMatrix (expected a sequence composed of scalars and/or nested (2D) sequences of scalars)."
|
|
166
228
|
)
|
|
167
229
|
else:
|
|
168
|
-
value = [
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
230
|
+
value = [one_or_many_2D_scalars_factory(v, data) for v in x.value]
|
|
231
|
+
|
|
232
|
+
if tg.is_many_scalars(value):
|
|
233
|
+
return SkylineParameter(value=value, change_times=change_times)
|
|
234
|
+
|
|
235
|
+
Ns: set[int] = set()
|
|
236
|
+
for elem in value:
|
|
237
|
+
if tg.is_many_2D_scalars(elem):
|
|
238
|
+
n_rows = len(elem)
|
|
239
|
+
if any(len(row) != n_rows for row in elem):
|
|
240
|
+
raise ValueError(
|
|
241
|
+
f"All elements in the value of a SkylineMatrix config must be scalars or square matrices (got non-square matrix: {elem})."
|
|
242
|
+
)
|
|
243
|
+
Ns.add(n_rows)
|
|
244
|
+
|
|
245
|
+
if len(Ns) > 1:
|
|
246
|
+
raise ValueError(
|
|
247
|
+
f"All elements in the value of a SkylineMatrix config must be scalars or have the same square shape (got value={value} with inconsistent lengths {Ns})."
|
|
248
|
+
)
|
|
249
|
+
(N,) = Ns
|
|
250
|
+
value = [[[p] * N] * N if isinstance(p, pgt.Scalar) else p for p in value]
|
|
251
|
+
|
|
176
252
|
return SkylineMatrix(
|
|
177
|
-
value=value,
|
|
253
|
+
value=value,
|
|
254
|
+
change_times=change_times,
|
|
178
255
|
)
|
phylogenie/core/msas/alisim.py
CHANGED
|
@@ -3,8 +3,8 @@ from typing import Literal
|
|
|
3
3
|
|
|
4
4
|
from numpy.random import Generator
|
|
5
5
|
|
|
6
|
+
import phylogenie.typings as pgt
|
|
6
7
|
from phylogenie.core.msas.base import BackendType, MSAsGenerator
|
|
7
|
-
from phylogenie.core.typings import Data
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class AliSimGenerator(MSAsGenerator):
|
|
@@ -13,7 +13,7 @@ class AliSimGenerator(MSAsGenerator):
|
|
|
13
13
|
args: dict[str, str | int | float]
|
|
14
14
|
|
|
15
15
|
def _generate_one_from_tree(
|
|
16
|
-
self, filename: str, tree_file: str, rng: Generator, data: Data
|
|
16
|
+
self, filename: str, tree_file: str, rng: Generator, data: pgt.Data
|
|
17
17
|
) -> None:
|
|
18
18
|
command = [
|
|
19
19
|
self.iqtree_path,
|
phylogenie/core/msas/base.py
CHANGED
|
@@ -6,9 +6,9 @@ from typing import Literal
|
|
|
6
6
|
|
|
7
7
|
from numpy.random import Generator
|
|
8
8
|
|
|
9
|
+
import phylogenie.typings as pgt
|
|
9
10
|
from phylogenie.core.dataset import DatasetGenerator, DataType
|
|
10
11
|
from phylogenie.core.trees import TreesGeneratorConfig
|
|
11
|
-
from phylogenie.core.typings import Data
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class BackendType(str, Enum):
|
|
@@ -22,10 +22,10 @@ class MSAsGenerator(DatasetGenerator):
|
|
|
22
22
|
|
|
23
23
|
@abstractmethod
|
|
24
24
|
def _generate_one_from_tree(
|
|
25
|
-
self, filename: str, tree_file: str, rng: Generator, data: Data
|
|
25
|
+
self, filename: str, tree_file: str, rng: Generator, data: pgt.Data
|
|
26
26
|
) -> None: ...
|
|
27
27
|
|
|
28
|
-
def _generate_one(self, filename: str, rng: Generator, data: Data) -> None:
|
|
28
|
+
def _generate_one(self, filename: str, rng: Generator, data: pgt.Data) -> None:
|
|
29
29
|
if isinstance(self.trees, str):
|
|
30
30
|
tree_files = os.listdir(self.trees)
|
|
31
31
|
tree_file = os.path.join(self.trees, str(rng.choice(tree_files)))
|
|
@@ -8,7 +8,7 @@ class ReactionConfig(StrictBaseModel):
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class PunctualReactionConfig(StrictBaseModel):
|
|
11
|
-
times: cfg.
|
|
11
|
+
times: cfg.ManyScalarsConfig
|
|
12
12
|
value: str
|
|
13
|
-
p: cfg.
|
|
14
|
-
n: cfg.
|
|
13
|
+
p: cfg.ManyScalarsConfig | None = None
|
|
14
|
+
n: cfg.ManyIntsConfig | None = None
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import phylogenie.core.trees.remaster.configs as cfg
|
|
2
|
+
import phylogenie.typings as pgt
|
|
2
3
|
from phylogenie.backend.remaster import PunctualReaction, Reaction
|
|
3
4
|
from phylogenie.core.factories import (
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
many_ints_factory,
|
|
6
|
+
many_scalars_factory,
|
|
6
7
|
skyline_parameter_like_factory,
|
|
7
8
|
)
|
|
8
|
-
from phylogenie.core.typings import Data
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def reaction_factory(
|
|
12
|
-
x: cfg.ReactionConfig,
|
|
13
|
-
data: Data,
|
|
14
|
-
) -> Reaction:
|
|
11
|
+
def reaction_factory(x: cfg.ReactionConfig, data: pgt.Data) -> Reaction:
|
|
15
12
|
return Reaction(
|
|
16
13
|
rate=skyline_parameter_like_factory(x.rate, data),
|
|
17
14
|
value=x.value,
|
|
@@ -19,12 +16,11 @@ def reaction_factory(
|
|
|
19
16
|
|
|
20
17
|
|
|
21
18
|
def punctual_reaction_factory(
|
|
22
|
-
x: cfg.PunctualReactionConfig,
|
|
23
|
-
data: Data,
|
|
19
|
+
x: cfg.PunctualReactionConfig, data: pgt.Data
|
|
24
20
|
) -> PunctualReaction:
|
|
25
21
|
return PunctualReaction(
|
|
26
|
-
times=
|
|
22
|
+
times=many_scalars_factory(x.times, data),
|
|
27
23
|
value=x.value,
|
|
28
|
-
p=None if x.p is None else
|
|
29
|
-
n=None if x.n is None else
|
|
24
|
+
p=None if x.p is None else many_scalars_factory(x.p, data),
|
|
25
|
+
n=None if x.n is None else many_ints_factory(x.n, data),
|
|
30
26
|
)
|