modelbase2 0.5.0__py3-none-any.whl → 0.7.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.
modelbase2/scope.py DELETED
@@ -1,96 +0,0 @@
1
- """Label Scope Module.
2
-
3
- This module provides functions for creating and managing label scopes in metabolic models.
4
- It includes functionality for initializing label scopes and retrieving reachable label positions.
5
-
6
- Functions:
7
- get_label_scope: Return all label positions that can be reached step by step.
8
- """
9
-
10
- from __future__ import annotations
11
-
12
- # def _create_label_scope_seed(
13
- # self, *, initial_labels: dict[str, int] | dict[str, list[int]]
14
- # ) -> dict[str, int]:
15
- # """Create initial label scope seed."""
16
- # # initialise all compounds with 0 (no label)
17
- # labelled_compounds = {compound: 0 for compound in self.get_compounds()}
18
- # # Set all unlabelled compounds to 1
19
- # for name, compound in self.label_compounds.items():
20
- # num_labels = compound["num_labels"]
21
- # labelled_compounds[f"{name}__{'0' * num_labels}"] = 1
22
- # # Also set all non-label compounds to 1
23
- # for name in self.nonlabel_compounds:
24
- # labelled_compounds[name] = 1
25
- # # Set initial label
26
- # for i in [
27
- # self.get_compound_isotopomer_with_label_position(
28
- # base_compound=base_compound, label_position=label_position
29
- # )
30
- # for base_compound, label_position in initial_labels.items()
31
- # ]:
32
- # labelled_compounds[i] = 1
33
- # return labelled_compounds
34
-
35
-
36
- # def get_label_scope(
37
- # self,
38
- # initial_labels: dict[str, int] | dict[str, list[int]],
39
- # ) -> dict[int, set[str]]:
40
- # """Return all label positions that can be reached step by step.
41
-
42
- # Parameters:
43
- # initial_labels : dict(str: num)
44
-
45
- # Returns:
46
- # label_scope : dict{step : set of new positions}
47
-
48
- # Examples:
49
- # >>> l.get_label_scope({"x": 0})
50
- # >>> l.get_label_scope({"x": [0, 1], "y": 0})
51
-
52
- # """
53
- # labelled_compounds = self._create_label_scope_seed(initial_labels=initial_labels)
54
- # new_labels = set("non empty entry to not fulfill while condition")
55
- # # Loop until no new labels are inserted
56
- # loop_count = 0
57
- # result = {}
58
- # while new_labels != set():
59
- # new_cpds = labelled_compounds.copy()
60
- # for rec, cpd_dict in self.get_stoichiometries().items():
61
- # # Isolate substrates
62
- # cpds = [i for i, j in cpd_dict.items() if j < 0]
63
- # # Count how many of the substrates are 1
64
- # i = 0
65
- # for j in cpds:
66
- # i += labelled_compounds[j]
67
- # # If all substrates are 1, set all products to 1
68
- # if i == len(cpds):
69
- # for cpd in self.get_stoichiometries()[rec]:
70
- # new_cpds[cpd] = 1
71
- # if self.rates[rec]["reversible"]:
72
- # # Isolate substrates
73
- # cpds = [i for i, j in cpd_dict.items() if j > 0]
74
- # # Count how many of the substrates are 1
75
- # i = 0
76
- # for j in cpds:
77
- # i += labelled_compounds[j]
78
- # # If all substrates are 1, set all products to 1
79
- # if i == len(cpds):
80
- # for cpd in self.get_stoichiometries()[rec]:
81
- # new_cpds[cpd] = 1
82
- # # Isolate "old" labels
83
- # s1 = pd.Series(labelled_compounds)
84
- # s1 = cast(pd.Series, s1[s1 == 1])
85
- # # Isolate new labels
86
- # s2 = pd.Series(new_cpds)
87
- # s2 = cast(pd.Series, s2[s2 == 1])
88
- # # Find new labels
89
- # new_labels = cast(set[str], set(s2.index).difference(set(s1.index)))
90
- # # Break the loop once no new labels can be found
91
- # if new_labels == set():
92
- # break
93
- # labelled_compounds = new_cpds
94
- # result[loop_count] = new_labels
95
- # loop_count += 1
96
- # return result
modelbase2/surrogates.py DELETED
@@ -1,322 +0,0 @@
1
- """Surrogate Models Module.
2
-
3
- This module provides classes and functions for creating and training surrogate models
4
- for metabolic simulations. It includes functionality for both steady-state and time-series
5
- data using neural networks.
6
-
7
- Classes:
8
- AbstractSurrogate: Abstract base class for surrogate models.
9
- TorchSurrogate: Surrogate model using PyTorch.
10
- Approximator: Neural network approximator for surrogate modeling.
11
-
12
- Functions:
13
- train_torch_surrogate: Train a PyTorch surrogate model.
14
- train_torch_time_course_estimator: Train a PyTorch time course estimator.
15
- """
16
-
17
- from __future__ import annotations
18
-
19
- from abc import abstractmethod
20
- from dataclasses import dataclass
21
- from pathlib import Path
22
- from typing import TYPE_CHECKING
23
-
24
- import numpy as np
25
- import pandas as pd
26
- import torch
27
- import tqdm
28
- from torch import nn
29
- from torch.optim.adam import Adam
30
-
31
- from modelbase2.parallel import Cache
32
-
33
- if TYPE_CHECKING:
34
- from collections.abc import Callable
35
-
36
- from torch.optim.optimizer import ParamsT
37
-
38
- __all__ = [
39
- "AbstractSurrogate",
40
- "Approximator",
41
- "DefaultCache",
42
- "DefaultDevice",
43
- "MockSurrogate",
44
- "TorchSurrogate",
45
- "train_torch_surrogate",
46
- ]
47
-
48
-
49
- DefaultDevice = torch.device("cpu")
50
- DefaultCache = Cache(Path(".cache"))
51
-
52
-
53
- @dataclass(kw_only=True)
54
- class AbstractSurrogate:
55
- """Abstract base class for surrogate models.
56
-
57
- Attributes:
58
- inputs: List of input variable names.
59
- stoichiometries: Dictionary mapping reaction names to stoichiometries.
60
-
61
- Methods:
62
- predict: Abstract method to predict outputs based on input data.
63
-
64
- """
65
-
66
- inputs: list[str]
67
- stoichiometries: dict[str, dict[str, float]]
68
-
69
- @abstractmethod
70
- def predict(self, y: np.ndarray) -> dict[str, float]:
71
- """Predict outputs based on input data."""
72
-
73
-
74
- @dataclass(kw_only=True)
75
- class MockSurrogate(AbstractSurrogate):
76
- """Mock surrogate model for testing purposes."""
77
-
78
- def predict(
79
- self,
80
- y: np.ndarray,
81
- ) -> dict[str, float]:
82
- """Predict outputs based on input data."""
83
- return dict(zip(self.stoichiometries, y, strict=True))
84
-
85
-
86
- @dataclass(kw_only=True)
87
- class TorchSurrogate(AbstractSurrogate):
88
- """Surrogate model using PyTorch.
89
-
90
- Attributes:
91
- model: PyTorch neural network model.
92
-
93
- Methods:
94
- predict: Predict outputs based on input data using the PyTorch model.
95
-
96
- """
97
-
98
- model: torch.nn.Module
99
-
100
- def predict(self, y: np.ndarray) -> dict[str, float]:
101
- """Predict outputs based on input data using the PyTorch model.
102
-
103
- Args:
104
- y: Input data as a numpy array.
105
-
106
- Returns:
107
- dict[str, float]: Dictionary mapping output variable names to predicted values.
108
-
109
- """
110
- with torch.no_grad():
111
- return dict(
112
- zip(
113
- self.stoichiometries,
114
- self.model(
115
- torch.tensor(y, dtype=torch.float32),
116
- ).numpy(),
117
- strict=True,
118
- )
119
- )
120
-
121
-
122
- class Approximator(nn.Module):
123
- """Neural network approximator for surrogate modeling.
124
-
125
- Attributes:
126
- net: Sequential neural network model.
127
-
128
- Methods:
129
- forward: Forward pass through the neural network.
130
-
131
- """
132
-
133
- def __init__(self, n_inputs: int, n_outputs: int) -> None:
134
- """Initializes the surrogate model with the given number of inputs and outputs.
135
-
136
- Args:
137
- n_inputs (int): The number of input features.
138
- n_outputs (int): The number of output features.
139
-
140
- Initializes a neural network with the following architecture:
141
- - Linear layer with `n_inputs` inputs and 50 outputs
142
- - ReLU activation
143
- - Linear layer with 50 inputs and 50 outputs
144
- - ReLU activation
145
- - Linear layer with 50 inputs and `n_outputs` outputs
146
-
147
- The weights of the linear layers are initialized with a normal distribution
148
- (mean=0, std=0.1) and the biases are initialized to 0.
149
-
150
- """
151
- super().__init__()
152
-
153
- self.net = nn.Sequential(
154
- nn.Linear(n_inputs, 50),
155
- nn.ReLU(),
156
- nn.Linear(50, 50),
157
- nn.ReLU(),
158
- nn.Linear(50, n_outputs),
159
- )
160
-
161
- for m in self.net.modules():
162
- if isinstance(m, nn.Linear):
163
- nn.init.normal_(m.weight, mean=0, std=0.1)
164
- nn.init.constant_(m.bias, val=0)
165
-
166
- def forward(self, x: torch.Tensor) -> torch.Tensor:
167
- """Forward pass through the neural network.
168
-
169
- Args:
170
- x: Input tensor.
171
-
172
- Returns:
173
- torch.Tensor: Output tensor.
174
-
175
- """
176
- return self.net(x)
177
-
178
-
179
- def _train_batched(
180
- aprox: nn.Module,
181
- features: pd.DataFrame,
182
- targets: pd.DataFrame,
183
- epochs: int,
184
- optimizer: Adam,
185
- device: torch.device,
186
- batch_size: int,
187
- ) -> pd.Series:
188
- """Train the neural network using mini-batch gradient descent.
189
-
190
- Args:
191
- aprox: Neural network model to train.
192
- features: Input features as a tensor.
193
- targets: Target values as a tensor.
194
- epochs: Number of training epochs.
195
- optimizer: Optimizer for training.
196
- device: torch device
197
- batch_size: Size of mini-batches for training.
198
-
199
- Returns:
200
- pd.Series: Series containing the training loss history.
201
-
202
- """
203
- rng = np.random.default_rng()
204
- losses = {}
205
- for i in tqdm.trange(epochs):
206
- idxs = rng.choice(features.index, size=batch_size)
207
- X = torch.Tensor(features.iloc[idxs].to_numpy(), device=device)
208
- Y = torch.Tensor(targets.iloc[idxs].to_numpy(), device=device)
209
- optimizer.zero_grad()
210
- loss = torch.mean(torch.abs(aprox(X) - Y))
211
- loss.backward()
212
- optimizer.step()
213
- losses[i] = loss.detach().numpy()
214
- return pd.Series(losses, dtype=float)
215
-
216
-
217
- def _train_full(
218
- aprox: nn.Module,
219
- features: pd.DataFrame,
220
- targets: pd.DataFrame,
221
- epochs: int,
222
- optimizer: Adam,
223
- device: torch.device,
224
- ) -> pd.Series:
225
- """Train the neural network using full-batch gradient descent.
226
-
227
- Args:
228
- aprox: Neural network model to train.
229
- features: Input features as a tensor.
230
- targets: Target values as a tensor.
231
- epochs: Number of training epochs.
232
- optimizer: Optimizer for training.
233
- device: Torch device
234
-
235
- Returns:
236
- pd.Series: Series containing the training loss history.
237
-
238
- """
239
- X = torch.Tensor(features.to_numpy(), device=device)
240
- Y = torch.Tensor(targets.to_numpy(), device=device)
241
-
242
- losses = {}
243
- for i in tqdm.trange(epochs):
244
- optimizer.zero_grad()
245
- loss = torch.mean(torch.abs(aprox(X) - Y))
246
- loss.backward()
247
- optimizer.step()
248
- losses[i] = loss.detach().numpy()
249
- return pd.Series(losses, dtype=float)
250
-
251
-
252
- def train_torch_surrogate(
253
- features: pd.DataFrame,
254
- targets: pd.DataFrame,
255
- epochs: int,
256
- surrogate_inputs: list[str],
257
- surrogate_stoichiometries: dict[str, dict[str, float]],
258
- batch_size: int | None = None,
259
- approximator: nn.Module | None = None,
260
- optimimzer_cls: Callable[[ParamsT], Adam] = Adam,
261
- device: torch.device = DefaultDevice,
262
- ) -> tuple[TorchSurrogate, pd.Series]:
263
- """Train a PyTorch surrogate model.
264
-
265
- Examples:
266
- >>> train_torch_surrogate(
267
- ... features,
268
- ... targets,
269
- ... epochs=100,
270
- ... surrogate_inputs=["x1", "x2"],
271
- ... surrogate_stoichiometries={
272
- ... "v1": {"x1": -1, "x2": 1, "ATP": -1},
273
- ... },
274
- ...)
275
-
276
- Args:
277
- features: DataFrame containing the input features for training.
278
- targets: DataFrame containing the target values for training.
279
- epochs: Number of training epochs.
280
- surrogate_inputs: List of input variable names for the surrogate model.
281
- surrogate_stoichiometries: Dictionary mapping reaction names to stoichiometries.
282
- batch_size: Size of mini-batches for training (None for full-batch).
283
- approximator: Predefined neural network model (None to use default).
284
- optimimzer_cls: Optimizer class to use for training (default: Adam).
285
- device: Device to run the training on (default: DefaultDevice).
286
-
287
- Returns:
288
- tuple[TorchSurrogate, pd.Series]: Trained surrogate model and loss history.
289
-
290
- """
291
- if approximator is None:
292
- approximator = Approximator(
293
- n_inputs=len(features.columns),
294
- n_outputs=len(targets.columns),
295
- ).to(device)
296
-
297
- optimizer = optimimzer_cls(approximator.parameters())
298
- if batch_size is None:
299
- losses = _train_full(
300
- aprox=approximator,
301
- features=features,
302
- targets=targets,
303
- epochs=epochs,
304
- optimizer=optimizer,
305
- device=device,
306
- )
307
- else:
308
- losses = _train_batched(
309
- aprox=approximator,
310
- features=features,
311
- targets=targets,
312
- epochs=epochs,
313
- optimizer=optimizer,
314
- device=device,
315
- batch_size=batch_size,
316
- )
317
- surrogate = TorchSurrogate(
318
- model=approximator,
319
- inputs=surrogate_inputs,
320
- stoichiometries=surrogate_stoichiometries,
321
- )
322
- return surrogate, losses
@@ -1,46 +0,0 @@
1
- modelbase2/__init__.py,sha256=ArYJZoCTulkjFctJzxk7c9CDBXYRl2J9_LXr1EORilk,4048
2
- modelbase2/distributions.py,sha256=i456B0KYKdiGwuoVjoj3rey5lKdJmu9EVvacnfWXHGA,8744
3
- modelbase2/fit.py,sha256=WEI2lxLhdHFr6ax5xXrrkHUTxcEhmXyBHebfHEcXwCY,8172
4
- modelbase2/fns.py,sha256=8JtIzPk3DAnNHz3LoJ1ukLFTjPNO1rNCeZ7VnRmJY2o,4503
5
- modelbase2/label_map.py,sha256=LUwcOHQWiGfBGV5XUmPM_SOwM9IyDVcQVJ11DPfVpAo,17774
6
- modelbase2/linear_label_map.py,sha256=gA8CHxcehgtI6ovwZ9qNUPDvxfqbO1J1kBC_mltD4TY,10225
7
- modelbase2/mc.py,sha256=zlDL7e_udpIMRhSjfFJo5AwkigD0B_3H2rQxyelBuzI,16285
8
- modelbase2/mca.py,sha256=nMS2VnzR2VEujCFUaj9WL82CNd-oxTb3jCHP8IlJvxA,8845
9
- modelbase2/model.py,sha256=d-iAu64oxVgH9QgNYhNnJnrISic_U1Z5hX6ij6eDqh0,55260
10
- modelbase2/nnarchitectures.py,sha256=OA1X4UHrn7gsLuuqxK6Dhv5aiKnQflhHezYCUV-NuO8,4012
11
- modelbase2/npe.py,sha256=o876zHjyfJelGijSmCL0vUBfWbIhcbQyyPkwp8hZ4NA,8743
12
- modelbase2/parallel.py,sha256=kX4Td5YoovDwZp6kX_3cfO6QtHSS9ieJ0bMZiKs3Xv8,5002
13
- modelbase2/parameterise.py,sha256=7VrYxrQv0visraqUthWSnWfx-cxh2evlXbszIY5031U,690
14
- modelbase2/paths.py,sha256=uatKXDa79uniUB2Z3dr8eBJVuUPXDI-o_bf-DqPKq1Y,1039
15
- modelbase2/plot.py,sha256=72Oivv-jsCF9J9U7Uli15p5SnuEHSnHRXCaRP8uUaJo,22724
16
- modelbase2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- modelbase2/scan.py,sha256=PvWZA4EgNS0JVMvm87bF72hSmhvo6O2KGg4vRzxve_8,18104
18
- modelbase2/scope.py,sha256=4twnEh8LrTmlLE-uRvubVkE3SSWejlLvtBzTCPqG3Aw,3710
19
- modelbase2/simulator.py,sha256=0_KXL3QUsMHtckdH4nPlzJoGNLoQaVttV7PUt2RU1m8,19823
20
- modelbase2/surrogates.py,sha256=Dk-YEXb-ot22W3r5Bl3rxApbCyvNdBnNCvRi_1f_NnA,9276
21
- modelbase2/types.py,sha256=N74pWUZDcGlSMfDkjqqwHn5dkozlqgS6Wqg-58YKdvg,9904
22
- modelbase2/experimental/__init__.py,sha256=IzgcQ7MtMII7n6cg1PMp-oZm06CNVR19ax2exvb9Ny0,444
23
- modelbase2/experimental/_backup.py,sha256=As-L75tMQjWfkheRPk8xcroQPKDsSSejBJ2dXqPXmVo,46644
24
- modelbase2/experimental/codegen.py,sha256=i0soAT64oMBILGsWonoSSVkYMWOcCTY4RJ4TZoYlTos,6962
25
- modelbase2/experimental/diff.py,sha256=e7fjD9kqxkRUNxSevbAznd5cOlEdWJ6pj0y7Kd5KKrw,8973
26
- modelbase2/experimental/notes.md,sha256=YlM2biTzub6jSlx-aDZaBYsvQcGwb7NHyVAbbl2acGE,238
27
- modelbase2/experimental/strikepy.py,sha256=cKBs9InXR9mEPgx70Ynv0qkmAGfloksqinbpppTiC6U,19464
28
- modelbase2/experimental/symbolic.py,sha256=QT82TSW42RSVsvXK2WTQW1XluXnflWzrHbx6RFr_YmY,9953
29
- modelbase2/experimental/tex.py,sha256=q9k9NfQucUhYzNjAKkroU9XnBcfdegPK6h3DHhkfGOg,13618
30
- modelbase2/integrators/__init__.py,sha256=kqmV6a0TRyLGR_XqbyAI652AfptYnXAUpqbSFg0CpP8,450
31
- modelbase2/integrators/int_assimulo.py,sha256=VEQIZFZcEovLPy8i_jR8H8XcxBRQoRVmNzzCYzInPc0,4611
32
- modelbase2/integrators/int_scipy.py,sha256=-_9MS55eTc9jI7tk-3X49p-c7zrydoXaCCvDTn7Tybw,4334
33
- modelbase2/sbml/__init__.py,sha256=FBaQsVvrVc7QbCBXuG9tZOdSzHcqmmsaRbFx80rxrac,231
34
- modelbase2/sbml/_data.py,sha256=XwT1sSxn6KLTXYMbk4ORbEAEgZhQDBfoyrjMBDAoY_s,1135
35
- modelbase2/sbml/_export.py,sha256=9BLD3Qz86vlfDTZXwOnNOSVWq8mHrJoQjQmKJRZL_Wo,20285
36
- modelbase2/sbml/_import.py,sha256=1hP3xSktmbNic5asyk-b7L-FYQccEYvGAPchuLT4gqE,21586
37
- modelbase2/sbml/_mathml.py,sha256=bNk9RQ_NQFDhY1R354p-gwqqHaIiyAwZ1xLPHHhiguQ,24436
38
- modelbase2/sbml/_name_conversion.py,sha256=XK9DEyzhrD0GBBwwjK9RA0yORrDX5c-Uvx0VtKMR5rA,1325
39
- modelbase2/sbml/_unit_conversion.py,sha256=dW_I6_Ou09ccwnp6LIdrPriIQnQUK5lJcjzM2Fawm6U,1927
40
- modelbase2/surrogates/__init__.py,sha256=N_iXERECKvmrHiihwnyQEKOSBsmlGEuQhEotn-mWKdk,924
41
- modelbase2/surrogates/_poly.py,sha256=zjlNL4iYR9G51gjvZPHe3CAYF-tgACGdIBe4QUYXLQk,3110
42
- modelbase2/surrogates/_torch.py,sha256=CBS_3JzSgI2-xQrbq9CIXY0fJQsxbhBnWkG2TQyj7Zs,5885
43
- modelbase2-0.5.0.dist-info/METADATA,sha256=plD8PQFIOOvu2jENW3PLVROFUOuSrXElAj6knn0YDeo,3344
44
- modelbase2-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
45
- modelbase2-0.5.0.dist-info/licenses/LICENSE,sha256=qvG2VolmSkrcocL34V1ieOx-Rn-fpVcUbb25gHzVgZw,35079
46
- modelbase2-0.5.0.dist-info/RECORD,,