physioblocks 1.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.
Files changed (93) hide show
  1. physioblocks/__init__.py +37 -0
  2. physioblocks/base/__init__.py +27 -0
  3. physioblocks/base/operators.py +176 -0
  4. physioblocks/base/registers.py +108 -0
  5. physioblocks/computing/__init__.py +47 -0
  6. physioblocks/computing/assembling.py +291 -0
  7. physioblocks/computing/models.py +811 -0
  8. physioblocks/computing/quantities.py +354 -0
  9. physioblocks/configuration/__init__.py +38 -0
  10. physioblocks/configuration/aliases.py +203 -0
  11. physioblocks/configuration/base.py +123 -0
  12. physioblocks/configuration/computing/__init__.py +27 -0
  13. physioblocks/configuration/computing/quantities.py +56 -0
  14. physioblocks/configuration/constants.py +121 -0
  15. physioblocks/configuration/description/__init__.py +33 -0
  16. physioblocks/configuration/description/blocks.py +239 -0
  17. physioblocks/configuration/description/nets.py +155 -0
  18. physioblocks/configuration/functions.py +695 -0
  19. physioblocks/configuration/simulation/__init__.py +32 -0
  20. physioblocks/configuration/simulation/simulations.py +280 -0
  21. physioblocks/description/__init__.py +34 -0
  22. physioblocks/description/blocks.py +418 -0
  23. physioblocks/description/flux.py +157 -0
  24. physioblocks/description/nets.py +746 -0
  25. physioblocks/io/__init__.py +29 -0
  26. physioblocks/io/aliases.py +73 -0
  27. physioblocks/io/configuration.py +125 -0
  28. physioblocks/launcher/__main__.py +285 -0
  29. physioblocks/launcher/configuration.py +231 -0
  30. physioblocks/launcher/configure/__main__.py +99 -0
  31. physioblocks/launcher/constants.py +105 -0
  32. physioblocks/launcher/files.py +150 -0
  33. physioblocks/launcher/series.py +165 -0
  34. physioblocks/library/__init__.py +27 -0
  35. physioblocks/library/aliases/blocks/c_block.json +5 -0
  36. physioblocks/library/aliases/blocks/rc_block.json +5 -0
  37. physioblocks/library/aliases/blocks/rcr_block.json +5 -0
  38. physioblocks/library/aliases/blocks/spherical_cavity_block.json +5 -0
  39. physioblocks/library/aliases/blocks/valve_rl_block.json +5 -0
  40. physioblocks/library/aliases/flux/heart_flux_dof_couples.jsonc +4 -0
  41. physioblocks/library/aliases/model_components/active_law_macro_huxley_two_moments.json +5 -0
  42. physioblocks/library/aliases/model_components/rheology_fiber_additive.json +5 -0
  43. physioblocks/library/aliases/model_components/spherical_dynamics.json +5 -0
  44. physioblocks/library/aliases/model_components/velocity_law_hht.json +5 -0
  45. physioblocks/library/aliases/nets/circulation_alone_net.json +31 -0
  46. physioblocks/library/aliases/nets/spherical_heart_net.json +93 -0
  47. physioblocks/library/aliases/simulations/circulation_alone_forward_simulation.jsonc +55 -0
  48. physioblocks/library/aliases/simulations/default_forward_simulation.jsonc +7 -0
  49. physioblocks/library/aliases/simulations/default_time.jsonc +8 -0
  50. physioblocks/library/aliases/simulations/newton_method_solver.json +5 -0
  51. physioblocks/library/aliases/simulations/spherical_heart_forward_simulation.jsonc +157 -0
  52. physioblocks/library/aliases/simulations/spherical_heart_with_respiration_forward_simulation.jsonc +45 -0
  53. physioblocks/library/blocks/__init__.py +27 -0
  54. physioblocks/library/blocks/capacitances.py +516 -0
  55. physioblocks/library/blocks/cavity.py +192 -0
  56. physioblocks/library/blocks/valves.py +281 -0
  57. physioblocks/library/functions/__init__.py +27 -0
  58. physioblocks/library/functions/base_operations.py +129 -0
  59. physioblocks/library/functions/first_order.py +113 -0
  60. physioblocks/library/functions/piecewise.py +271 -0
  61. physioblocks/library/functions/trigonometric.py +78 -0
  62. physioblocks/library/functions/watchers.py +113 -0
  63. physioblocks/library/model_components/__init__.py +27 -0
  64. physioblocks/library/model_components/active_law.py +345 -0
  65. physioblocks/library/model_components/dynamics.py +986 -0
  66. physioblocks/library/model_components/rheology.py +160 -0
  67. physioblocks/library/model_components/velocity_law.py +169 -0
  68. physioblocks/references/circulation_alone_sim.jsonc +24 -0
  69. physioblocks/references/spherical_heart_respiration_sim.jsonc +33 -0
  70. physioblocks/references/spherical_heart_sim.jsonc +29 -0
  71. physioblocks/registers/__init__.py +32 -0
  72. physioblocks/registers/load_function_register.py +93 -0
  73. physioblocks/registers/save_function_register.py +106 -0
  74. physioblocks/registers/type_register.py +97 -0
  75. physioblocks/simulation/__init__.py +48 -0
  76. physioblocks/simulation/constants.py +30 -0
  77. physioblocks/simulation/functions.py +71 -0
  78. physioblocks/simulation/runtime.py +484 -0
  79. physioblocks/simulation/saved_quantities.py +129 -0
  80. physioblocks/simulation/setup.py +576 -0
  81. physioblocks/simulation/solvers.py +235 -0
  82. physioblocks/simulation/state.py +340 -0
  83. physioblocks/simulation/time_manager.py +354 -0
  84. physioblocks/utils/__init__.py +27 -0
  85. physioblocks/utils/dynamic_import_utils.py +150 -0
  86. physioblocks/utils/exceptions_utils.py +115 -0
  87. physioblocks/utils/gradient_test_utils.py +337 -0
  88. physioblocks/utils/math_utils.py +109 -0
  89. physioblocks-1.0.0.dist-info/METADATA +127 -0
  90. physioblocks-1.0.0.dist-info/RECORD +93 -0
  91. physioblocks-1.0.0.dist-info/WHEEL +4 -0
  92. physioblocks-1.0.0.dist-info/licenses/licenses/GPL-3.0-only.txt +674 -0
  93. physioblocks-1.0.0.dist-info/licenses/licenses/LGPL-3.0-only.txt +165 -0
@@ -0,0 +1,337 @@
1
+ # SPDX-FileCopyrightText: Copyright INRIA
2
+ #
3
+ # SPDX-License-Identifier: LGPL-3.0-only
4
+ #
5
+ # Copyright INRIA
6
+ #
7
+ # This file is part of PhysioBlocks, a library mostly developed by the
8
+ # [Ananke project-team](https://team.inria.fr/ananke) at INRIA.
9
+ #
10
+ # Authors:
11
+ # - Colin Drieu
12
+ # - Dominique Chapelle
13
+ # - François Kimmig
14
+ # - Philippe Moireau
15
+ #
16
+ # PhysioBlocks is free software: you can redistribute it and/or modify it under the
17
+ # terms of the GNU Lesser General Public License as published by the Free Software
18
+ # Foundation, version 3 of the License.
19
+ #
20
+ # PhysioBlocks is distributed in the hope that it will be useful, but WITHOUT ANY
21
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
22
+ # PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
23
+ #
24
+ # You should have received a copy of the GNU Lesser General Public License along with
25
+ # PhysioBlocks. If not, see <https://www.gnu.org/licenses/>.
26
+
27
+ """
28
+ Define functions to perform gradient tests to check the coherence between an
29
+ function and its gradient.
30
+
31
+ The gradient test principle is to compare the result of a **computed** and estimated
32
+ gradient from a :class:`~physioblocks.computing.assembling.EqSystem` object.
33
+ """
34
+
35
+ from __future__ import annotations
36
+
37
+ import logging
38
+ from os import linesep
39
+ from typing import Any
40
+
41
+ import numpy as np
42
+ from numpy.typing import NDArray
43
+ from scipy.optimize import approx_fprime
44
+
45
+ import physioblocks.simulation.setup as setup
46
+ from physioblocks.computing.assembling import EqSystem
47
+ from physioblocks.computing.models import Block, Expression, ModelComponent
48
+ from physioblocks.configuration.aliases import unwrap_aliases
49
+ from physioblocks.configuration.functions import load
50
+ from physioblocks.io.configuration import read_json
51
+ from physioblocks.simulation.runtime import AbstractSimulation
52
+ from physioblocks.simulation.state import State
53
+
54
+ _logger = logging.getLogger(__name__)
55
+
56
+ _ZERO = 1e-16
57
+ _REL_TOL = 1e-6
58
+ _NEW_STATE_SHIFT_FACTOR = 1e-3
59
+ _SHIFT_FACTOR = 1e-4
60
+ _CONVERGENCE_FACTOR = 0.1
61
+ _CONVERGENCE_TOL = 0.11
62
+
63
+
64
+ def gradient_test_from_file(config_file_path: str) -> bool:
65
+ """
66
+ Read the given configuration file and perform a gradient test on the full Net
67
+ with the provided parameters and variables.
68
+
69
+ .. warning::
70
+
71
+ Every type (especially **Blocks**, **ModelComponents** and **Functions**) and
72
+ alias used in the configuration file have to be loaded.
73
+ Follow this
74
+ :ref:`user guide section <user_guide_level_3_block_test_dynamic_import>`
75
+ to import libraries and aliases dynamically.
76
+
77
+ :param config_file_path: the file path to the simulation configuration file.
78
+ :type config_file_path: str
79
+
80
+ :return: True if the gradient test is successfull, false otherwise.
81
+ """
82
+ configuration = read_json(config_file_path)
83
+ configuration = unwrap_aliases(configuration)
84
+ sim: AbstractSimulation = load(configuration)
85
+ sim._initialize() # noqa SLF001
86
+ return gradient_test(
87
+ sim.eq_system,
88
+ sim.state,
89
+ sim.solver._get_state_magnitude(sim.state, sim.magnitudes), # noqa: SLF001
90
+ )
91
+
92
+
93
+ def gradient_test_from_model(
94
+ model: ModelComponent, state: State, state_magnitude: NDArray[np.float64]
95
+ ) -> bool:
96
+ """
97
+ Create an equation system for the given block only and perform a gradient test.
98
+
99
+ .. note::
100
+
101
+ It does not test the submodels of the model.
102
+
103
+ :param model: the model to test.
104
+ :type model: str
105
+
106
+ :param state: the state used to determine the variables in the model.
107
+ :type state: str
108
+
109
+ :param state_magnitude: the state variables magnitudes
110
+ :type state_magnitude: str
111
+
112
+ :return: True if the gradient test is successfull, false otherwise.
113
+ """
114
+ line_index = 0
115
+ expressions = setup.SystemExpressions()
116
+ for internal_expr_def in type(model).internal_expressions:
117
+ expressions.append((line_index, internal_expr_def.expression, model))
118
+ line_index += internal_expr_def.expression.size
119
+
120
+ if isinstance(model, Block):
121
+ for fluxes_expr_def in type(model).fluxes_expressions.values():
122
+ expressions.append((line_index, fluxes_expr_def.expression, model))
123
+ line_index += fluxes_expr_def.expression.size
124
+
125
+ eq_system = setup.build_eq_system(expressions, state)
126
+ model.initialize()
127
+ return gradient_test(eq_system, state, state_magnitude)
128
+
129
+
130
+ def gradient_test_from_expression(
131
+ expr: Expression,
132
+ expr_params: Any,
133
+ state: State,
134
+ state_magnitude: NDArray[np.float64],
135
+ ) -> bool:
136
+ """
137
+ Create an equation system for the given expression only and perform a gradient test.
138
+
139
+ :param expr: the expression to test.
140
+ :type expr: Expression
141
+
142
+ :param expr_params: the parameters to pass to the expression
143
+ :type expr_params: Any
144
+
145
+ :param state: the state used to determine the variables in the expression.
146
+ :type state: str
147
+
148
+ :param state_magnitude: the state variables magnitudes
149
+ :type state_magnitude: str
150
+
151
+ :return: True if the gradient test is successfull, false otherwise.
152
+ :rtype: bool
153
+ """
154
+
155
+ eq_system = setup.build_eq_system([(0, expr, expr_params)], state)
156
+ return gradient_test(eq_system, state, state_magnitude)
157
+
158
+
159
+ def gradient_test(
160
+ eq_system: EqSystem, state: State, state_magnitude: NDArray[np.float64]
161
+ ) -> bool:
162
+ """
163
+ Test the computed gradient for the equation system by comparing it to
164
+ a gradient estimated with finite differences.
165
+
166
+ :param eq_system: the equation system providing method to compute a residual and a
167
+ gradient
168
+ :type eq_system: EqSystem
169
+
170
+ :param state: system state
171
+ :type state: State
172
+
173
+ :param state_magnitude: the state variables magnitudes
174
+ :type state_magnitude: str
175
+
176
+ :return: True if the estimated and computed gradient meet tolerance,
177
+ False otherwise.
178
+ """
179
+
180
+ _logger.info(str.format("State:{0}{1}", linesep, state))
181
+ _logger.info(str.format("System:{0}{1}", linesep, eq_system))
182
+
183
+ new_state = state.state_vector + _NEW_STATE_SHIFT_FACTOR * state_magnitude
184
+
185
+ shift_1 = _SHIFT_FACTOR * state_magnitude
186
+ state.update_state_vector(new_state)
187
+
188
+ res = eq_system.compute_residual()
189
+ grad = eq_system.compute_gradient()
190
+
191
+ grad_estimated_1 = _estimate_gradient(eq_system, shift_1, state)
192
+
193
+ shift_2 = _CONVERGENCE_FACTOR * shift_1
194
+ state.update_state_vector(new_state)
195
+ grad_estimated_2 = _estimate_gradient(eq_system, shift_2, state)
196
+
197
+ state.update_state_vector(new_state)
198
+
199
+ with np.printoptions(precision=9, linewidth=10000, suppress=True):
200
+ _logger.debug(str.format("Residual:{0}{1}", linesep, res))
201
+ _logger.debug(str.format("Gradient{0}{1}", linesep, grad))
202
+ _logger.debug(
203
+ str.format("Gradient Estimated:{0}{1}", linesep, grad_estimated_1)
204
+ )
205
+
206
+ grad_error_pos = get_errors_gradient(grad, grad_estimated_1, grad_estimated_2)
207
+
208
+ error_message = str.format("State:{0}{1}", linesep, state)
209
+ error_message += str.format("System:{0}{1}{0}{0}", linesep, eq_system)
210
+
211
+ for line_error, col_error in grad_error_pos:
212
+ error_msg_line = str.format(
213
+ "Error in gradient at ({0},{1}).{2}", line_error, col_error, linesep
214
+ )
215
+ _logger.debug(error_msg_line)
216
+ error_message += error_msg_line
217
+
218
+ error_msg_line = str.format(
219
+ "Variable Id: {0}.{1}", state.get_variable_id(col_error), linesep
220
+ )
221
+ _logger.debug(error_msg_line)
222
+
223
+ error_msg_line = str.format("Residual Index: {0}.{1}{1}", line_error, linesep)
224
+ _logger.debug(error_msg_line)
225
+
226
+ if len(grad_error_pos) != 0:
227
+ raise GradientError(error_message)
228
+
229
+ return len(grad_error_pos) == 0
230
+
231
+
232
+ def _estimate_gradient(
233
+ eq_system: EqSystem, shift: NDArray[np.float64], state: State
234
+ ) -> NDArray[np.float64]:
235
+ """
236
+ Gradient finite difference estimation
237
+
238
+ :param eq_system: the equation system providing method to compute a residual
239
+ and a gradient
240
+ :type eq_system: EqSystem
241
+
242
+ :param shift_factor: the shift factor to apply on the state (can be 0).
243
+ It is multiplied with the variables magnitude then added to the state.
244
+ :type shift_factor: NDArray
245
+
246
+ :param state: system state
247
+ :type state: State
248
+ """
249
+
250
+ def residual(x: NDArray[np.float64]) -> NDArray[np.float64]:
251
+ state.update_state_vector(x)
252
+ res = eq_system.compute_residual()
253
+
254
+ return res
255
+
256
+ x0 = state.state_vector
257
+ grad_est = np.atleast_2d(approx_fprime(x0, residual, shift))
258
+
259
+ return grad_est
260
+
261
+
262
+ def get_errors_gradient(
263
+ computed: NDArray[np.float64],
264
+ estimated_1: NDArray[np.float64],
265
+ estimated_2: NDArray[np.float64],
266
+ ) -> list[tuple[int, int]]:
267
+ """
268
+ Get the ``(line, column)`` positions of the errors in the gradient matrix.
269
+
270
+ :param computed: computed gradient
271
+ :type computed: NDArray[np.float64]
272
+
273
+ :param estimated_1: first gradient estimate
274
+ :type estimated_1: NDArray[np.float64]
275
+
276
+ :param estimated_2: second gradient estimate
277
+ :type estimated_2: NDArray[np.float64]
278
+
279
+ :return: the position of the errors in the gradient matrix
280
+ :rtype: list[tuple[int, int]]
281
+ """
282
+ abs_computed = np.abs(computed)
283
+
284
+ error_1 = np.empty(computed.shape)
285
+ error_1[:] = np.inf
286
+ error_2 = error_1.copy()
287
+
288
+ for grad_line in range(0, computed.shape[0]):
289
+ for grad_col in range(0, computed.shape[1]):
290
+ if abs_computed[grad_line, grad_col] < _ZERO:
291
+ error_1[grad_line, grad_col] = (
292
+ np.abs(
293
+ computed[grad_line, grad_col] - estimated_1[grad_line, grad_col]
294
+ )
295
+ / _ZERO
296
+ )
297
+ error_2[grad_line, grad_col] = (
298
+ np.abs(
299
+ computed[grad_line, grad_col] - estimated_2[grad_line, grad_col]
300
+ )
301
+ / _ZERO
302
+ )
303
+ else:
304
+ error_1[grad_line, grad_col] = (
305
+ np.abs(
306
+ computed[grad_line, grad_col] - estimated_1[grad_line, grad_col]
307
+ )
308
+ / abs_computed[grad_line, grad_col]
309
+ )
310
+ error_2[grad_line, grad_col] = (
311
+ np.abs(
312
+ computed[grad_line, grad_col] - estimated_2[grad_line, grad_col]
313
+ )
314
+ / abs_computed[grad_line, grad_col]
315
+ )
316
+
317
+ with np.printoptions(precision=9, linewidth=10000, suppress=False):
318
+ _logger.debug(str.format("Error:{0}{1}", error_1, linesep))
319
+
320
+ error_positions = []
321
+
322
+ for grad_line in range(0, computed.shape[0]):
323
+ for grad_col in range(0, computed.shape[1]):
324
+ if error_1[grad_line, grad_col] > _REL_TOL:
325
+ err_div = error_2[grad_line, grad_col] / error_1[grad_line, grad_col]
326
+ if err_div > _CONVERGENCE_TOL:
327
+ error_positions.append((grad_line, grad_col))
328
+ elif np.isnan(error_1[grad_line, grad_col]):
329
+ error_positions.append((grad_line, grad_col))
330
+
331
+ return error_positions
332
+
333
+
334
+ class GradientError(Exception):
335
+ """Error raised when the estimated and computed gradients do not match."""
336
+
337
+ pass
@@ -0,0 +1,109 @@
1
+ # SPDX-FileCopyrightText: Copyright INRIA
2
+ #
3
+ # SPDX-License-Identifier: LGPL-3.0-only
4
+ #
5
+ # Copyright INRIA
6
+ #
7
+ # This file is part of PhysioBlocks, a library mostly developed by the
8
+ # [Ananke project-team](https://team.inria.fr/ananke) at INRIA.
9
+ #
10
+ # Authors:
11
+ # - Colin Drieu
12
+ # - Dominique Chapelle
13
+ # - François Kimmig
14
+ # - Philippe Moireau
15
+ #
16
+ # PhysioBlocks is free software: you can redistribute it and/or modify it under the
17
+ # terms of the GNU Lesser General Public License as published by the Free Software
18
+ # Foundation, version 3 of the License.
19
+ #
20
+ # PhysioBlocks is distributed in the hope that it will be useful, but WITHOUT ANY
21
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
22
+ # PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
23
+ #
24
+ # You should have received a copy of the GNU Lesser General Public License along with
25
+ # PhysioBlocks. If not, see <https://www.gnu.org/licenses/>.
26
+
27
+ """Defines some math functions to help compute quantities"""
28
+
29
+ from typing import Any
30
+
31
+ import numpy as np
32
+
33
+
34
+ def exp_diff(a: float, b: float, diff: float) -> Any:
35
+ """
36
+ Computes exponential differences with more numerical accuracy when a and b are close
37
+ using the relationship:
38
+
39
+ .. math::
40
+
41
+ e^a - e^b = 2\\ e^{\\frac{a + b}{2}}\\ \\text{sinh}(\\frac{a + b}{2})
42
+
43
+ :param a: value of a
44
+ :type a: np.float64
45
+
46
+ :param b: value of b
47
+ :type b: np.float64
48
+
49
+ :param diff: value of a - b
50
+ :type diff: np.float64
51
+
52
+ :return: exponential difference value
53
+ :rtype: np.float64
54
+ """
55
+ return np.exp(0.5 * (a + b)) * 2.0 * np.sinh(0.5 * diff)
56
+
57
+
58
+ def power_diff(a: float, b: float, diff: float, n: int) -> Any:
59
+ """
60
+ Computes the a and b power n difference with more numerical accuracy when a and
61
+ b are close by using the following relationship:
62
+
63
+ .. math::
64
+
65
+ a^n - b^n = (a-b) * \\sum_{i = 0}^{n -1}{a^i b^{n-1-i}}
66
+
67
+ When n is negative, the following transformation is used:
68
+
69
+ .. math::
70
+
71
+ \\frac{1}{a^n} - \\frac{1}{b^n} = -\\frac{a^n-b^n}{{ab}^n}
72
+
73
+ :param a: value of a
74
+ :type a: np.float64
75
+
76
+ :param b: value of b
77
+ :type b: np.float64
78
+
79
+ :param diff: value of a - b
80
+ :type diff: np.float64
81
+
82
+ :return: the a and b power n difference value
83
+ :rtype: np.float64
84
+ """
85
+
86
+ if n < 0:
87
+ return -power_diff(a, b, diff, -n) / np.pow(a * b, -n)
88
+ elif n > 0:
89
+ return diff * _power_dec(a, b, n - 1, 0)
90
+ else:
91
+ return 0.0
92
+
93
+
94
+ def _power_dec(a: float, b: float, n1: int, n2: int) -> Any:
95
+ """
96
+ Helper recursive function used by :func:`power_diff` to compute the term:
97
+
98
+ .. math::
99
+
100
+ \\sum_{i = 0}^{n -1}{a^i b^{n-1-i}}
101
+ """
102
+
103
+ if n1 != 0 or n2 != 0:
104
+ if n1 != 0:
105
+ return np.pow(a, n1) * np.pow(b, n2) + _power_dec(a, b, n1 - 1, n2 + 1)
106
+ else:
107
+ return np.pow(b, n2)
108
+
109
+ return 1.0
@@ -0,0 +1,127 @@
1
+ Metadata-Version: 2.4
2
+ Name: physioblocks
3
+ Version: 1.0.0
4
+ Dynamic: Author
5
+ Dynamic: Author-email
6
+ Dynamic: License
7
+ Dynamic: License-Expression
8
+ Summary: Physioblocks allows the simulation of dynamical models of physiological systems
9
+ Project-URL: Homepage, https://github.com/physioblocks/physioblocks
10
+ Project-URL: Documentation, https://physioblocks.gitlabpages.inria.fr/physioblocks/
11
+ Project-URL: Issues, https://github.com/physioblocks/physioblocks/issues
12
+ Project-URL: Discussions, https://github.com/physioblocks/physioblocks/discussions
13
+ License-File: licenses/GPL-3.0-only.txt
14
+ License-File: licenses/LGPL-3.0-only.txt
15
+ Keywords: block diagram,cardiovascular modeling,dynamical systems,physiology
16
+ Classifier: Development Status :: 5 - Production/Stable
17
+ Classifier: Intended Audience :: Science/Research
18
+ Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
26
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
27
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
28
+ Requires-Python: >=3.10
29
+ Requires-Dist: numpy
30
+ Requires-Dist: pandas
31
+ Requires-Dist: plotly
32
+ Requires-Dist: pyarrow
33
+ Requires-Dist: regex
34
+ Requires-Dist: scipy
35
+ Provides-Extra: doc
36
+ Requires-Dist: sphinx; extra == 'doc'
37
+ Requires-Dist: sphinx-rtd-theme; extra == 'doc'
38
+ Requires-Dist: sphinxcontrib-tikz; extra == 'doc'
39
+ Provides-Extra: quality
40
+ Requires-Dist: mypy; extra == 'quality'
41
+ Requires-Dist: ruff; extra == 'quality'
42
+ Provides-Extra: test
43
+ Requires-Dist: coverage; extra == 'test'
44
+ Requires-Dist: pytest>=8; extra == 'test'
45
+ Provides-Extra: tox
46
+ Requires-Dist: tox>=4; extra == 'tox'
47
+ Description-Content-Type: text/markdown
48
+
49
+ # PhysioBlocks
50
+
51
+ PhysioBlocks allows the simulation of dynamical models of physiological systems.
52
+
53
+ ## User Levels
54
+
55
+ They are several use cases for PhysioBlocks depending on the user profile:
56
+
57
+ * __Level 1:__ Configure and run physiological systems simulation (for pre-existing systems)
58
+ * __Level 2:__ Create new systems with existing blocks without writing code
59
+ * __Level 3:__ Write and add new blocks to the library.
60
+
61
+ ## Principle
62
+
63
+ * A __Net__ (system) is built from __Nodes__ and __Blocks__ connected by those nodes.
64
+ * At each node in the net, connected blocks share __Degrees of Freedom__ (ex: pressure) and send __Fluxes__ that verify Kirchhoff Law.
65
+ * __ModelComponents__ concatenate blocks equations to the global system (if necessary, for modularity purposes within the block)
66
+
67
+ ## Interactions
68
+
69
+ __Level 1:__ Configure and run a simulation : JSON
70
+ * Update the model parameters
71
+
72
+ __Level 2:__ Create Nets : JSON
73
+ * Declare the nodes, the blocks, and the block - nodes connections
74
+
75
+
76
+ __Level 3:__ Write and add models to the library: Python
77
+ * Declare the quantities to use in the model
78
+ * Write the fluxes and equations
79
+
80
+ ## Documentation
81
+
82
+ Here are the links to the sections of the [full documentation](https://physioblocks.gitlabpages.inria.fr/physioblocks/):
83
+ * [Installation](https://physioblocks.gitlabpages.inria.fr/physioblocks/installation.html)
84
+ * [User Guide](https://physioblocks.gitlabpages.inria.fr/physioblocks/user_guide.html)
85
+ * [Library](https://physioblocks.gitlabpages.inria.fr/physioblocks/library.html)
86
+ * [API Reference](https://physioblocks.gitlabpages.inria.fr/physioblocks/api_reference.html)
87
+
88
+ ## Quick start
89
+
90
+ Complete instructions are available in the [documentation](https://physioblocks.gitlabpages.inria.fr/physioblocks/). This instructions will enable you to launch a reference simulation.
91
+
92
+ ### Installation
93
+
94
+ This project requires a recent version of python installed.
95
+ Then:
96
+ ```
97
+ pip install physioblocks
98
+ ```
99
+
100
+ ### Configuration
101
+
102
+ To configure PhysioBlocks Launcher:
103
+
104
+ ```
105
+ # Create an empty folder where you want to store simulations results.
106
+ mkdir $LAUNCHER_FOLDER_PATH$
107
+
108
+ # Configure the folder
109
+ python -m physioblocks.launcher.configure -d $LAUNCHER_FOLDER_PATH$ -v
110
+ ```
111
+
112
+ ### Launch a simulation
113
+
114
+ With a Launcher folder configured:
115
+
116
+ ```
117
+ # Move to your configured launcher folder
118
+ cd $LAUNCHER_FOLDER_PATH$
119
+
120
+ # Launch a reference simulation
121
+ python -m physioblocks.launcher references/spherical_heart_sim.jsonc -v -t -s QuickStart
122
+
123
+ # This can take some time.
124
+ ```
125
+
126
+
127
+ Results will be available in the `$LAUNCHER_FOLDER_PATH$/simulations/QuickStart` series folder.
@@ -0,0 +1,93 @@
1
+ physioblocks/__init__.py,sha256=0ZHZb8nU30moO0pf0Z2UarcVWvhTPtI878IkQcpSDpc,1169
2
+ physioblocks/base/__init__.py,sha256=2h6bk0fe8pwQvJ15Buytg4SZzYOH-Ep7WqoD6pd1eOQ,986
3
+ physioblocks/base/operators.py,sha256=uUfswQZsaMNd2bd7wsaxSGFIYLAr1hQCQ6SQfYawdBc,5689
4
+ physioblocks/base/registers.py,sha256=Cd0hmy1XqojjPQgb_jn4mGeAMTyWWgDkl3qJHCVjCRU,3119
5
+ physioblocks/computing/__init__.py,sha256=rLjuzRCA0nVAnHcYsL0jhn2KQpl6MnC3DJLf3a0i6uw,1302
6
+ physioblocks/computing/assembling.py,sha256=2pKNA85PWJJ4fwSPRi7IitMdjlYTTiWQIgnKyhHja-8,9308
7
+ physioblocks/computing/models.py,sha256=2V5Xbsoy3jK_OcubTKxmTUa7nKBag0x-T4Zivcul7So,24489
8
+ physioblocks/computing/quantities.py,sha256=f2wU0VDylJ8nuUtOsV0FsA1mJnqNy1AvoK6-w04Fctc,8934
9
+ physioblocks/configuration/__init__.py,sha256=XNeIev97Fc9DAy_mA3CAZ0kMif7Nkop9sCI38ZZ2wgM,1454
10
+ physioblocks/configuration/aliases.py,sha256=o7E54IYeW0NfmCX_r3zLKURVHsQoCmTlLD5085kY0eg,6302
11
+ physioblocks/configuration/base.py,sha256=eLxZXZdc4QkSsA7TOA0-E5ckfMZZkdgPJ6JVrFwM4nY,3627
12
+ physioblocks/configuration/constants.py,sha256=JsXGcoxHXgaixpIIiYZDPNiKSeD7Y_4YswVm0Uaf-Hs,3056
13
+ physioblocks/configuration/functions.py,sha256=pJl5BkSwRoIydH3bSMNilu0wj7yOVJ_BVAPNS-yMl8k,23520
14
+ physioblocks/configuration/computing/__init__.py,sha256=duNJXdaHTZ9_V9XScNXjJgPsKSc6FbHGrwNDLrcYDg8,1012
15
+ physioblocks/configuration/computing/quantities.py,sha256=fM5L4YeeM1NQQjhbdU4e50yxZ9B2ogF0WzDIYqFDbgg,1721
16
+ physioblocks/configuration/description/__init__.py,sha256=-KyjKPheXzgKiVZ0jL-nl8H-uN9cYjXJkX6XL6q9oVg,1169
17
+ physioblocks/configuration/description/blocks.py,sha256=FGYFR5S15jGlZnIIfvZLdMr33bXabXMi9Vj9jETLeeM,8003
18
+ physioblocks/configuration/description/nets.py,sha256=wKAH1Qq_tQ65-bn17qV6c_n0dt__PtY9r8TnYtZsPTY,5124
19
+ physioblocks/configuration/simulation/__init__.py,sha256=RuRdBDvwqBcyghwh1D0ud3qwdUEcw2vgHPoB8drXp6w,1126
20
+ physioblocks/configuration/simulation/simulations.py,sha256=4W-pcSDIMBKRFYjkkHOePrcZfXiFdfCHdyI_qpFSZ_c,8795
21
+ physioblocks/description/__init__.py,sha256=o6G4LgLuSKSXOF6Uex-nua-8MyWsiwBd_G4dQLJsA6Y,1200
22
+ physioblocks/description/blocks.py,sha256=y0qLvdE4VBmdDmOeHFaRFsmPRg-7_JVSGs2thAAUzHc,13542
23
+ physioblocks/description/flux.py,sha256=aKs31bO1KyfAlHhmWUP9ZS7V7SryyVe_6MZG_Sp9jCQ,4858
24
+ physioblocks/description/nets.py,sha256=pKG2uB-4dABc-lvGswkybiho18bOkUwsVJYBdlX7p5s,23604
25
+ physioblocks/io/__init__.py,sha256=bOGWA0hAifT9wHxD4kWFQuAXpAx0GzDmGfmcgNDUCGo,990
26
+ physioblocks/io/aliases.py,sha256=d_Gqz0-8SVD6tA9N-T9xYL8SRhaSMmIOjqvOKHBb-Yo,2288
27
+ physioblocks/io/configuration.py,sha256=UY8whA_7KcMwi_gXPIt5h8_gD7TKO2Co5cyf9MHO0yg,3578
28
+ physioblocks/launcher/__main__.py,sha256=pLTJzaMZGN7elr8aAvgkjYOhnp6fbGouH5SWq_5bKIg,8811
29
+ physioblocks/launcher/configuration.py,sha256=dqHCR_7PSDInA8NC3NFONqK3PPwSQYpLkZgYSyVU1vs,7959
30
+ physioblocks/launcher/constants.py,sha256=FIBKde1vJrUzMk9dSl4q8f8jqN7bFxYF05EIG2-V0zw,3033
31
+ physioblocks/launcher/files.py,sha256=zvif_8Woh3vEYCb_K3YnFFZYpgMhdlf4c2OSIVW4jC4,4950
32
+ physioblocks/launcher/series.py,sha256=x2XazVzVT6Co8Nco92jdO8XlsjgCxFHkxGQZ5RSl4Ik,5048
33
+ physioblocks/launcher/configure/__main__.py,sha256=4RPUtUSBV2DlJeHmOf0fqRFAdud3Tx12M-nKQ3epRGc,2955
34
+ physioblocks/library/__init__.py,sha256=Yilh0uLw1Ac7xe9aLqCg-DFYQobzZJMk9B64cAuCUKk,1026
35
+ physioblocks/library/aliases/blocks/c_block.json,sha256=-63XyPEv7xhvMoHIF9ShLIz8jqDRWkOyRAyfF4VpIFY,84
36
+ physioblocks/library/aliases/blocks/rc_block.json,sha256=OesNIQadZainjoU7O0gXy2Tnd8LWoYsS6JM0XiwRacc,85
37
+ physioblocks/library/aliases/blocks/rcr_block.json,sha256=u9ILSfzn29y84jGX-CnNFQkoPloE6YDc4rtHWTsUplM,86
38
+ physioblocks/library/aliases/blocks/spherical_cavity_block.json,sha256=_cWeg4kHL2Cm9t6em3eoMUIZov04XgysRq3R6ZduSQM,99
39
+ physioblocks/library/aliases/blocks/valve_rl_block.json,sha256=cuNCgx88JkP7FfNH6mHHCxRB-jt8d3PySbkVGzIuLXQ,91
40
+ physioblocks/library/aliases/flux/heart_flux_dof_couples.jsonc,sha256=P09q70D-qIoj6l2IcwN3LQaPqZ8sJ_m7Fm2sf9H00Uw,83
41
+ physioblocks/library/aliases/model_components/active_law_macro_huxley_two_moments.json,sha256=Pw4ZupAKIDukUXCAXZ3ERNF7RoEzNtgUC-umuqGDnIw,112
42
+ physioblocks/library/aliases/model_components/rheology_fiber_additive.json,sha256=dw0zC8UFjIjNsNdl9l6P1nWQ0lRBe3QmYZ8vXCEkbZE,100
43
+ physioblocks/library/aliases/model_components/spherical_dynamics.json,sha256=Tcd1t6JSVO-ty-gfksTUl_oXX_l1GuwBFuvH-fujLus,95
44
+ physioblocks/library/aliases/model_components/velocity_law_hht.json,sha256=HKbc5_2hGuOiQKUvLGto6tBQI_Z5AbbhXp8Itwmo2ag,93
45
+ physioblocks/library/aliases/nets/circulation_alone_net.json,sha256=M3TiXIXgaXCsdwfyA5cm3fqspViiIl0Kyb6NKMiFsQ8,874
46
+ physioblocks/library/aliases/nets/spherical_heart_net.json,sha256=UnOSQslMJuvbT6dXXPWj-HEvqe6U4fG1CK17_sKTxM8,3057
47
+ physioblocks/library/aliases/simulations/circulation_alone_forward_simulation.jsonc,sha256=0l4dKEvmY6-3NLB70B4zVF_OJs-bzgxAsesgr3KZ7P0,1983
48
+ physioblocks/library/aliases/simulations/default_forward_simulation.jsonc,sha256=TE_82KWUYAQdMX4MpDGY-Hi_djpwYAhSB5uzYtzYqcA,136
49
+ physioblocks/library/aliases/simulations/default_time.jsonc,sha256=LM2_EU-GvOeGXJMvXXyJeWEOv-cfy25luhcaSMj5hkw,165
50
+ physioblocks/library/aliases/simulations/newton_method_solver.json,sha256=p0jgVCpySTR0Npo5iFZrUUys3SRcy4j_EesQw9SvoyA,79
51
+ physioblocks/library/aliases/simulations/spherical_heart_forward_simulation.jsonc,sha256=CXG5m8lRftbqYUchDedA_ggO81v1M0qiqyshRCMOl4E,5664
52
+ physioblocks/library/aliases/simulations/spherical_heart_with_respiration_forward_simulation.jsonc,sha256=kCy065DN5Cau3d7ouuzdDAaLevBuzlnZkWtROG3DgtY,1542
53
+ physioblocks/library/blocks/__init__.py,sha256=EhnoyZYTooSd_cTfysnT-YR6Ylrn15dJsfWwALFV00I,991
54
+ physioblocks/library/blocks/capacitances.py,sha256=-coa-Zb4rVHwZVM2ip3iAHKURlQ9Mzw4Q34eCc-DHKc,14175
55
+ physioblocks/library/blocks/cavity.py,sha256=JODm84TYz0Zuji3QXHb-bhQZlM_QZh6lTluf_8c0GL8,6064
56
+ physioblocks/library/blocks/valves.py,sha256=jMo5ZaBIONaiG-e2y-5zRnayOq7YhsG44zL6mn900Ag,7747
57
+ physioblocks/library/functions/__init__.py,sha256=k9cFPqrsApbeSkcnu-FbhonilTTeJS0Cp5EJCrfPeII,988
58
+ physioblocks/library/functions/base_operations.py,sha256=TpN7rabrX9Nojd2uu90j1Dw_7OpdjbBSuiM_HWzJH3M,3507
59
+ physioblocks/library/functions/first_order.py,sha256=oSkFyECA7ywgQCYKt-sEZmSu84QrRere_Ee736vk2Ik,3687
60
+ physioblocks/library/functions/piecewise.py,sha256=xpR22eP0Jkfuskc737uttenbpOOMXEfrOAyconAg_-4,8401
61
+ physioblocks/library/functions/trigonometric.py,sha256=Y5UolXZTASEi4EH_GpLpUIxMZbXIVHc-THFEXg9vrtg,2126
62
+ physioblocks/library/functions/watchers.py,sha256=fY1SSPn-7R9cix0VMFP69H5-pmJzl4OXs1tgvjCetvM,3212
63
+ physioblocks/library/model_components/__init__.py,sha256=JcDL2PaPTrT9mTlDUbPjUsyFfsiGh5GgroJ7J3g2uwE,998
64
+ physioblocks/library/model_components/active_law.py,sha256=97D3fC7Dmzw8jLqDALxUJgl48EZYOx39SYjZgGJx-Eo,11634
65
+ physioblocks/library/model_components/dynamics.py,sha256=SZaOU2_EFMRlqvJvsW9NXLTviN8NBAhy_9z_0EErPb0,35282
66
+ physioblocks/library/model_components/rheology.py,sha256=7x5RrB_0DXMWlm0mIrTxdLlsjXVa1WPuFYYifW4fKeg,4724
67
+ physioblocks/library/model_components/velocity_law.py,sha256=UYr9MywlLkRw0LszK0u_AamwThjobDMV9jYbaSbdDkU,5047
68
+ physioblocks/registers/__init__.py,sha256=trxT3MHDFX8cJ-IBX2cEIm8-uZBnfs2UkV8QDclq9so,1081
69
+ physioblocks/registers/load_function_register.py,sha256=z2iXShQCJHwSUJFNv2hJ19CLVSX5zlc2caxFg9x4-WE,2626
70
+ physioblocks/registers/save_function_register.py,sha256=mOK486hKsX3dqi5P_KBnH5DE0_xl3Uzvik9xE4N-SIM,2943
71
+ physioblocks/registers/type_register.py,sha256=JUlrPfP-X_TjIOHewSTkzf7Ck3L0ivVoHOvHQkyRpBM,2577
72
+ physioblocks/simulation/__init__.py,sha256=wqKVI3OLLVWuQoUcWwKSs5ibdkTP3Da_5DOe36v1up4,1504
73
+ physioblocks/simulation/constants.py,sha256=w9CsB4V7YtvcdW4N1p7Iu6MeV4i-kazcEPAygE7mSx0,1075
74
+ physioblocks/simulation/functions.py,sha256=c6HFwXK8IAzH7gSkz9aMiXLqnWXn_4_9WsX4jrGN9pY,2307
75
+ physioblocks/simulation/runtime.py,sha256=xMtUL07SSQYpskK_EnNi-qz2D1d4wlDAESWHPqMUHn8,16762
76
+ physioblocks/simulation/saved_quantities.py,sha256=fKWr1wScqxHPhuCE7aDNs8lpm9oWfyLN8NZDus2knPM,4111
77
+ physioblocks/simulation/setup.py,sha256=UmIklaHmfkxi_BIdYKOhorLoC9QT9D4oEXwC-Xfd6v0,18109
78
+ physioblocks/simulation/solvers.py,sha256=IrLHrsLJhM97SYzeygz2-UkkNbpp2hsixCuUi0Nis98,7353
79
+ physioblocks/simulation/state.py,sha256=jE6fTxzsnGKch1H6mErunpi7lwTb_9fvs2Hx77LIaMA,10310
80
+ physioblocks/simulation/time_manager.py,sha256=AbP_Y8mcG7-6x-3rGY5CHFQwKMqksO4HvdCJ-mU03d4,9381
81
+ physioblocks/utils/__init__.py,sha256=EMwPHVznBryA1uOEFfY_11L9Sd9bdCU_x_huNgIaZtQ,988
82
+ physioblocks/utils/dynamic_import_utils.py,sha256=AvGFRYPQcI2JSVpScXCgnYJDgF2uh8QI7xBewoe_9Ks,4862
83
+ physioblocks/utils/exceptions_utils.py,sha256=2w2q1XP-UDnxCXFu4XI2k1-jLUub24oYuwdUfd6tOkE,3421
84
+ physioblocks/utils/gradient_test_utils.py,sha256=41FVSrjzOLWmxvaiZI258QbmnQOA7M2tBm-Vd2GsEuo,11208
85
+ physioblocks/utils/math_utils.py,sha256=w5MDs4cP5WiTPHe8WofFuNZZ20WDNLT0XmFGlbisJJ0,2881
86
+ physioblocks/references/circulation_alone_sim.jsonc,sha256=qv27nzmK7jennhtCJ7wQ_f83mt9_YJSOTABjGCYMcZw,736
87
+ physioblocks/references/spherical_heart_respiration_sim.jsonc,sha256=kKq5xf94r90O1KpkCHk1qwgy6DJ37ePo3-8buEtcu5Y,1397
88
+ physioblocks/references/spherical_heart_sim.jsonc,sha256=kGGBqxY8dnmGKmpMv216kbneyJRGz_3VkcYn1OWavIA,1151
89
+ physioblocks-1.0.0.dist-info/METADATA,sha256=FcgqHhXq-C2RQKkG6t8WzxJ3-MvEoOGNHs_r5VGC_b0,4558
90
+ physioblocks-1.0.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
91
+ physioblocks-1.0.0.dist-info/licenses/licenses/GPL-3.0-only.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
92
+ physioblocks-1.0.0.dist-info/licenses/licenses/LGPL-3.0-only.txt,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
93
+ physioblocks-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any