Coverage for tests / tests_simulation / test_state.py: 100%
89 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-09 16:40 +0100
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-09 16:40 +0100
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/>.
27import numpy as np
28import pytest
29from numpy.typing import NDArray
31from physioblocks.computing.quantities import Quantity
32from physioblocks.simulation.state import State
34_X0_ID = "x0"
35_X1_ID = "x1"
36_X2_ID = "x2"
39@pytest.fixture
40def scalar() -> float:
41 return 1.0
44@pytest.fixture
45def vector() -> NDArray[np.float64]:
46 return np.array(
47 [1.0, 1.0],
48 )
51class TestState:
52 def test_constructor(self):
53 state = State()
54 assert state.size == 0
56 def test_variables(self, scalar, vector):
57 state = State()
59 state.add_variable(_X0_ID, scalar)
60 assert state.size == 1
61 assert _X0_ID in state
62 assert state.get_variable_index(_X0_ID) == 0
63 assert state.get_variable_size(_X0_ID) == 1
64 assert state.get_variable_id(0) == _X0_ID
66 message = str.format("No variable at index {0}", 1)
67 with pytest.raises(KeyError, match=message):
68 state.get_variable_id(1)
70 state.add_variable(_X1_ID, vector)
71 assert state.size == 3
72 assert _X1_ID in state
73 assert state.get_variable_index(_X1_ID) == 1
74 assert state.get_variable_size(_X1_ID) == 2
75 assert state.get_variable_id(1) == _X1_ID
77 state.add_variable(_X2_ID, vector)
78 assert state.size == 5
79 assert state.get_variable_index(_X2_ID) == 3
81 assert state.indexes == {_X0_ID: 0, _X1_ID: 1, _X2_ID: 3}
83 state.remove_variable(_X1_ID)
84 assert (_X1_ID in state) is False
85 assert state.size == 3
86 assert state.get_variable_index(_X0_ID) == 0
87 assert state.get_variable_index(_X2_ID) == 1
89 variables = [_X0_ID, _X2_ID]
90 assert list(state.indexes.keys()) == variables
92 error_message = str.format("{0} is already registered.", _X0_ID)
93 with pytest.raises(KeyError, match=error_message):
94 state.add_variable(_X0_ID, scalar)
96 def test_set_variable_quantity(self, scalar: float, vector: NDArray[np.float64]):
97 state = State()
98 state[_X0_ID] = Quantity(scalar)
99 state.add_variable(_X1_ID, scalar)
100 state[_X1_ID] = Quantity(scalar)
102 assert state[_X0_ID].current == pytest.approx(scalar)
103 assert state[_X1_ID].current == pytest.approx(scalar)
105 with pytest.raises(ValueError):
106 state[_X0_ID] = Quantity(vector)
108 with pytest.raises(KeyError):
109 state["unregistered"]
111 def test_state_vector(self, scalar: float, vector: NDArray[np.float64]):
112 state = State()
114 state.add_variable(_X0_ID, 0.0)
115 state[_X0_ID].initialize(scalar)
116 state.add_variable(_X1_ID, [0.0, 0.0])
117 state[_X1_ID].initialize(vector)
119 init_ref = np.ones(
120 shape=3,
121 )
122 update_ref = np.array(
123 [0.1, 0.2, 0.3],
124 )
125 set_ref = np.zeros(
126 shape=3,
127 )
129 assert state.state_vector == pytest.approx(init_ref)
131 with pytest.raises(AttributeError):
132 state.state_vector = update_ref
134 state.update_state_vector(update_ref)
135 assert state.state_vector == pytest.approx(update_ref)
136 assert state[_X0_ID].new == pytest.approx(update_ref[0])
137 assert state[_X0_ID].current == pytest.approx(init_ref[0])
138 assert state[_X1_ID].new == pytest.approx(update_ref[1:3])
139 assert state[_X1_ID].current == pytest.approx(init_ref[1:3])
141 state.set_state_vector(set_ref)
142 assert state.state_vector == pytest.approx(set_ref)
143 assert state[_X0_ID].new == pytest.approx(set_ref[0])
144 assert state[_X0_ID].current == pytest.approx(set_ref[0])
145 assert state[_X1_ID].new == pytest.approx(set_ref[1:3])
146 assert state[_X1_ID].current == pytest.approx(set_ref[1:3])
148 wrong_size_vector = np.zeros(
149 shape=5,
150 )
151 with pytest.raises(ValueError):
152 state.update_state_vector(wrong_size_vector)
154 with pytest.raises(ValueError):
155 state.set_state_vector(wrong_size_vector)