VanOsta2022 Physiology
python
1"""
2Tutorial CircAdapt VanOsta2022.
3
4November 2022, by Nick van Osta
5
6The goal of this tutorial is to understand the CircAdapt framework and to use
7the VanOsta2022 model. This tutorial assumes little to no knowledge about
8python. Therefore, basic python conventions and syntax will be discussed.
9This tutorial assumes the installation is followed as described on the wiki
10(https://wiki.circadapt.org/index.php?title=Circadapt_in_Python). This uses
11Python >3.9 installed with anaconda and editted in Spyder. Other ways are
12possible, but might not be in line with this tutorial.
13
14Content
15-------
16 1. Basics of python
17 2. Load the model
18 3. Plot global hemodynamics
19 4. Change parameters
20 5. Multipatch and local dynamics
21 6. Save and Load
22"""
23
24# %% 1. Basics of python
25print('1. Basics of python')
26
27# Always start the document with importing modules.
28# Numpy is used for mathematics, Matplotlib for plots. These are conventionally
29# imported as np and plt.
30import numpy as np
31import matplotlib.pyplot as plt
32
33# Only import the class we need in this tutorial.
34from circadapt import VanOsta2022
35# CA = VanOsta2022()
36
37# alternatively, you can import the whole package, but it changes the way you
38# make the object.
39# import circadapt
40# CA = circadapt.VanOsta2022()
41
42# Parameters types are automaticaly set or changed by the interpreter, but it
43# is good to create an integer when you need an integer and float when needed.
44i = 1 # integer
45f = 1. # float
46b = True # bool
47l = [1, 2, 3] # list
48d = {'a': 1, 'b': 2} # dictionary
49
50# get data from the list and dictionary
51first_item_of_list = l[0]
52item_from_dictionary = d['a']
53
54# the use of numpy is advised for more complex use and for calculation
55numpy_array = np.array(l)
56print('Find if array is 2: ', (numpy_array == 2))
57print('Multiply array with 2: ', (numpy_array * 2))
58
59# In spyder, you can place bullits. While debugging, ipython will stop at these
60# bullits. You can also press f9 to run a single line or selection and press
61# crtl+<enter> to run a block seperated by # %%
62
63# %% 2. load model
64print('\n 2. Load model. ')
65# Load predefined model with predefined parameterization
66# More information on this model can be found here:
67# https://wiki.circadapt.org/index.php?title=VanOsta2022
68CA = VanOsta2022()
69
70# CircAdapt tries to follow the syntax of python and numpy as much as possible.
71# The object can be handled as a dictionary. Content can be printed in the
72# console, and printed on request in the ipython console.
73print('The result of printing the object gives information about the '
74 'components: ')
75print(CA)
76
77# components can also be retrieved as a list of strings
78components = CA.components
79print('Components of this model: ', components, '\n')
80
81# Similar to the object itself, components can be printed
82print('Patches in this model: ')
83print(CA['Patch2022'])
84
85# Each component points to multiple c++ objects of that component type. The
86# objects can also be obtained using
87objects = CA['Patch2022'].objects
88parameters = CA['Patch2022'].parameters
89signals = CA['Patch2022'].signals
90
91# Signals are not stored, so they are only available after running a beat.
92# Therefore the model should run. You can either run a number of beats, or run
93# until the model is hemodynamically stable.
94CA.run(5)
95CA.run(run_stable=True)
96
97# %% 3. Plot global hemodynamics
98# Here is an example code to plot the PV loop
99# First we open a figure. Assigning this figure to a variable is optional, but
100# is useful for design purposes.
101fig = plt.figure(1)
102
103# get volume and pressure of LV
104Vlv = CA['Cavity']['V'][:, 6]*1e6
105plv = CA['Cavity']['p'][:, 6]*7.5e-3
106
107# get volume and pressure of RV
108Vrv = CA['Cavity']['V'][:, 7]*1e6
109prv = CA['Cavity']['p'][:, 7]*7.5e-3
110
111# You can also use location names to get/set signals and parameters
112# For this, use only the last part of the full object name, e.g. cLv for
113# Model.Peri.TriSeg.cLv. You can get one signal or multiple signals
114Vlv = CA['Cavity']['V'][:, 'cLv']*1e6
115Vrv = CA['Cavity']['V'][:, 'cRv']*1e6
116pressure = CA['Cavity']['p'][:, ['cLv', 'cRv']]*7.5e-3
117
118# you can split the two pressure signals into two parameters using the
119# following line. First transpose the pressure such that the first axis sets
120# the signals
121plv, prv = pressure.T
122
123# Now we plot the two lines.
124line1 = plt.plot(Vlv, plv, c='k', label='Lv')
125line2 = plt.plot(Vrv, prv, c='r', label='Rv')
126plt.ylabel('Pressure [mmHg]')
127plt.xlabel('Volume [mL]')
128plt.legend()
129
130# %% 4. Change parameters
131# Now reduce the contractility of all 3 ventricular walls, run the simulation,
132# and plot the data
133CA['Patch2022']['SfAct'][2:] = 60e3
134CA.run(run_stable=True)
135plt.plot(CA['Cavity']['V'][:, 6]*1e6, CA['Cavity']['p'][:, 6]*7.5e-3, 'k--', label='Lv Reduced SfAct')
136plt.plot(CA['Cavity']['V'][:, 7]*1e6, CA['Cavity']['p'][:, 7]*7.5e-3, 'r--', label='Rv Reduced SfAct')
137plt.legend()
138
139
140# %% 5. Multipatch and local dynamics
141# Set up a new multipatch model and set an activation delay
142CA_multipatch = VanOsta2022()
143
144# The number of patches is specified in the wall. Here, we set 12 Lv patches
145# and 6 Sv patches. Then, we change the dT in these patches.
146CA_multipatch['Wall2022']['nPatch'][2:4] = [12, 6]
147CA_multipatch['Patch2022']['dT'][2:14] = np.linspace(0, 0.01, 12)
148CA_multipatch['Patch2022']['dT'][14:20] = np.linspace(0, 0.01, 6)
149
150# Run beats
151CA_multipatch.run(run_stable=True)
152
153# Plot data
154fig = plt.figure(2)
155
156# In the first subplot, plot all volumes
157ax1 = plt.subplot(2, 2, 1)
158plt.plot(CA_multipatch['Solver']['t']*1e3,
159 CA_multipatch['Cavity']['V']*1e6,
160 )
161# in the second subplot, plot all pressures
162ax1 = plt.subplot(2, 2, 2)
163plt.plot(CA_multipatch['Solver']['t']*1e3,
164 CA_multipatch['Cavity']['p']*7.5e-3,
165 )
166# in the third subplot, plot all natural fiber strains.
167ax1 = plt.subplot(2, 2, 3)
168plt.plot(CA_multipatch['Solver']['t']*1e3,
169 CA_multipatch['Patch2022']['Ef'][:, 2:20],
170 )
171
172# %% 6. Save and Load
173# Simulations can be saved and loaded using the following code.
174CA_reference = VanOsta2022()
175
176# use .npy extension in filename
177CA_reference.save('reference.npy')
178CA_reference.load('reference.npy')
179
180# if you want to save and load a structure without writing it to a file, use
181# the follow lines. Note that signals are not filled, you have to run at least
182# 1 beat.
183data = CA_reference.model_export()
184CA_reference.model_import(data)