Coverage for physioblocks / library / functions / base_operations.py: 100%
47 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/>.
27"""Define simple operations to initialize parameters in the configuration."""
29from __future__ import annotations
31from collections.abc import Iterable
32from dataclasses import dataclass, field
33from typing import Any
35import numpy as np
37from physioblocks.base.operators import AbstractBaseOperators
38from physioblocks.registers.type_register import register_type
39from physioblocks.simulation import AbstractFunction
41# Sum funtion type id
42SUM_TYPE_ID = "sum"
45@dataclass
46@register_type(SUM_TYPE_ID)
47class Sum(AbstractFunction, AbstractBaseOperators):
48 """
49 Sum the elements in ``add`` and subtract the elements in ``subtract``.
50 """
52 add: Iterable[Any] = field(default_factory=list)
53 """the values to sum"""
55 subtract: Iterable[Any] | None = None
56 """the values to subtract"""
58 @property
59 def operation_value(self) -> Any:
60 """
61 Value used with base operators.
63 :return: the current evaluation of the function
64 :rtype: Any
65 """
66 return self.eval()
68 def eval(self) -> Any:
69 """
70 Sum the elements in ``add`` and subtract the elements in ``subtract``.
72 :return: the sum result
73 :rtype: Any
74 """
76 pos = np.sum(np.array(self.add), axis=0)
78 if self.subtract is None:
79 return pos
81 neg = np.sum(np.array(self.subtract), axis=0)
82 return pos - neg
85def _multiply(elements: Iterable[Any]) -> Any:
86 result = 1.0
87 for elem in elements:
88 result = np.multiply(result, elem)
89 return result
92# Product function type name
93PRODUCT_TYPE_ID = "product"
96@dataclass
97@register_type(PRODUCT_TYPE_ID)
98class Product(AbstractFunction, AbstractBaseOperators):
99 """
100 Multiply all values provided in ``factors`` list and divide the
101 result with the multiplication of the values in the ``inverses`` list.
103 ..note:: It uses the numpy multiply function
105 """
107 factors: Iterable[Any] = field(default_factory=list)
108 """The values to multiply"""
110 inverses: Iterable[Any] | None = None
111 """The values to inverse then multiply"""
113 @property
114 def operation_value(self) -> Any:
115 """
116 Value used with base operators.
118 :return: the current evaluation of the function
119 :rtype: Any
120 """
121 return self.eval()
123 def eval(self) -> Any:
124 product = _multiply(self.factors)
125 if self.inverses is None:
126 return product
127 else:
128 inverses_product = _multiply(self.inverses)
129 return product / inverses_product