-
Notifications
You must be signed in to change notification settings - Fork 2
/
heartbeat.py
138 lines (114 loc) · 4.74 KB
/
heartbeat.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
from simframe.frame.updater import Updater
from simframe.utils.color import colorize
class Heartbeat(object):
"""This class controls an update including ``systole`` and ``diastole``.
A full cardiac cycle constists of a systole operation, the actual update and a systole operation.
All three are of type ``Updater``.
The ``beat`` function calls ``systole``, ``updater``, ``diastole`` in that order and returns the return value
of the ``updater``. Any positional or keyword arguments are only passed to the ``updater``, NOT to
``systole`` and ``diastole``.
"""
__name__ = "Heartbeat"
def __init__(self, updater=None, systole=None, diastole=None):
"""``Heartbeat`` class
Parameters
----------
updater : Updater, callable, None, optional, default : None
This it the main updater of the heartbeat object
systole : Updater, callable, None, optional, default : None
The updater of the systole
diastole : Updater, callable, None, optional, default : None
The updater of the diastole"""
self.updater = updater
self.systole = systole
self.diastole = diastole
def __str__(self):
return "{}".format(str(self.__name__))
def __repr__(self):
s = self.__str__() + "\n"
s += (len(s)-1)*"-" + "\n"
s += "\n"
s += "{} {}".format(colorize("Systole: ", color="red"),
str(self.systole._func)) + "\n"
s += "{} {}".format(colorize("Updater: ", color="red"),
str(self.updater._func)) + "\n"
s += "{} {}".format(colorize("Diastole:", color="red"),
str(self.diastole._func)) + "\n"
s += "\n"
s += "Docstrings" + "\n"
s += 10*"-" + "\n"
s += "\n"
s += colorize("Systole:", color="red") + "\n"
s += str(self.systole._func.__doc__ or None) + "\n"
s += "\n"
s += colorize("Updater:", color="red") + "\n"
s += str(self.updater._func.__doc__ or None) + "\n"
s += "\n"
s += colorize("Diastole:", color="red") + "\n"
s += str(self.diastole._func.__doc__ or None)
return s
@property
def systole(self):
'''``Updater`` that is called in the beginning of cardiac cycle.'''
return self._systole
@systole.setter
def systole(self, value):
if isinstance(value, Updater):
self._systole = value
elif hasattr(value, "__call__") or value is None:
self._systole = Updater(value)
else:
raise TypeError(
"Systole has to be of type Updater, None, or has to be callable.")
@property
def updater(self):
'''``Updater`` that is performing the update instruction.'''
return self._updater
@updater.setter
def updater(self, value):
if isinstance(value, Updater):
self._updater = value
elif hasattr(value, "__call__") or value is None:
self._updater = Updater(value)
else:
raise TypeError(
"Updater has to be of type Updater, None, or has to be callable.")
@property
def diastole(self):
'''``Updater`` that is called at the end of the cardiac cycle.'''
return self._diastole
@diastole.setter
def diastole(self, value):
if isinstance(value, Updater):
self._diastole = value
elif hasattr(value, "__call__") or value is None:
self._diastole = Updater(value)
else:
raise TypeError(
"Diastole has to be of type Updater, None, or has to be callable.")
def beat(self, owner, *args, Y=None, **kwargs):
"""This method executes ``systole``, ``updater``, and ``distole`` in that order and returns the return value of
the ``updater``.
Parameters
----------
owner : Frame
Parent frame object to which updater belongs
Y : Field, optional, default : None
Field that should be updated
Notes
-----
*args and **kwargs are only passed to updater, NOT to systole and diastole
Returns
-------
ret : Return value of updater."""
# Perform systole operation
self.systole.update(owner)
# Perform update operation and save return value.
ret = self.updater.update(owner, *args, **kwargs)
# If Y is given and a return value was received, then beat is updating a field.
# The new field value needs to be set here, so the diastole has access to the new value.
if Y is not None and ret is not None:
Y[...] = ret
# Perform diastole operation.
self.diastole.update(owner)
return ret