cardiac-geometriesx 0.0.1__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.
Potentially problematic release.
This version of cardiac-geometriesx might be problematic. Click here for more details.
- cardiac_geometries/__init__.py +8 -0
- cardiac_geometries/cli.py +875 -0
- cardiac_geometries/fibers/__init__.py +6 -0
- cardiac_geometries/fibers/lv_ellipsoid.py +150 -0
- cardiac_geometries/fibers/slab.py +150 -0
- cardiac_geometries/fibers/utils.py +84 -0
- cardiac_geometries/geometry.py +126 -0
- cardiac_geometries/mesh.py +727 -0
- cardiac_geometries/utils.py +173 -0
- cardiac_geometriesx-0.0.1.dist-info/METADATA +52 -0
- cardiac_geometriesx-0.0.1.dist-info/RECORD +14 -0
- cardiac_geometriesx-0.0.1.dist-info/WHEEL +5 -0
- cardiac_geometriesx-0.0.1.dist-info/entry_points.txt +2 -0
- cardiac_geometriesx-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,727 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import math
|
|
3
|
+
import json
|
|
4
|
+
import datetime
|
|
5
|
+
from importlib.metadata import metadata
|
|
6
|
+
from structlog import get_logger
|
|
7
|
+
|
|
8
|
+
from mpi4py import MPI
|
|
9
|
+
import cardiac_geometries_core as cgc
|
|
10
|
+
|
|
11
|
+
from . import utils
|
|
12
|
+
from .geometry import Geometry
|
|
13
|
+
|
|
14
|
+
meta = metadata("cardiac-geometriesx")
|
|
15
|
+
__version__ = meta["Version"]
|
|
16
|
+
|
|
17
|
+
logger = get_logger()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def biv_ellipsoid(
|
|
21
|
+
outdir: str | Path,
|
|
22
|
+
char_length: float = 0.5,
|
|
23
|
+
center_lv_x: float = 0.0,
|
|
24
|
+
center_lv_y: float = 0.0,
|
|
25
|
+
center_lv_z: float = 0.0,
|
|
26
|
+
a_endo_lv: float = 2.5,
|
|
27
|
+
b_endo_lv: float = 1.0,
|
|
28
|
+
c_endo_lv: float = 1.0,
|
|
29
|
+
a_epi_lv: float = 3.0,
|
|
30
|
+
b_epi_lv: float = 1.5,
|
|
31
|
+
c_epi_lv: float = 1.5,
|
|
32
|
+
center_rv_x: float = 0.0,
|
|
33
|
+
center_rv_y: float = 0.5,
|
|
34
|
+
center_rv_z: float = 0.0,
|
|
35
|
+
a_endo_rv: float = 3.0,
|
|
36
|
+
b_endo_rv: float = 1.5,
|
|
37
|
+
c_endo_rv: float = 1.5,
|
|
38
|
+
a_epi_rv: float = 4.0,
|
|
39
|
+
b_epi_rv: float = 2.5,
|
|
40
|
+
c_epi_rv: float = 2.0,
|
|
41
|
+
create_fibers: bool = False,
|
|
42
|
+
fiber_angle_endo: float = -60,
|
|
43
|
+
fiber_angle_epi: float = +60,
|
|
44
|
+
fiber_space: str = "P_1",
|
|
45
|
+
) -> Geometry:
|
|
46
|
+
"""Create BiV ellipsoidal geometry
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
outdir : str | Path
|
|
51
|
+
Directory where to save the results.
|
|
52
|
+
char_length : float, optional
|
|
53
|
+
Characteristic length of mesh, by default 0.5
|
|
54
|
+
center_lv_y : float, optional
|
|
55
|
+
X-coordinate for the center of the lv, by default 0.0
|
|
56
|
+
center_lv_y : float, optional
|
|
57
|
+
Y-coordinate for the center of the lv, by default 0.0
|
|
58
|
+
center_lv_z : float, optional
|
|
59
|
+
Z-coordinate for the center of the lv, by default 0.0
|
|
60
|
+
a_endo_lv : float, optional
|
|
61
|
+
Dilation of lv endo ellipsoid in the x-direction, by default 2.5
|
|
62
|
+
b_endo_lv : float, optional
|
|
63
|
+
Dilation of lv endo ellipsoid in the y-direction, by default 1.0
|
|
64
|
+
c_endo_lv : float, optional
|
|
65
|
+
Dilation of lv endo ellipsoid in the z-direction, by default 1.0
|
|
66
|
+
a_epi_lv : float, optional
|
|
67
|
+
Dilation of lv epi ellipsoid in the x-direction, by default 3.0
|
|
68
|
+
b_epi_lv : float, optional
|
|
69
|
+
Dilation of lv epi ellipsoid in the y-direction, by default 1.5
|
|
70
|
+
c_epi_lv : float, optional
|
|
71
|
+
Dilation of lv epi ellipsoid in the z-direction, by default 1.5
|
|
72
|
+
center_rv_x : float, optional
|
|
73
|
+
X-coordinate for the center of the rv, by default 0.0
|
|
74
|
+
center_rv_y : float, optional
|
|
75
|
+
Y-coordinate for the center of the rv, by default 0.5
|
|
76
|
+
center_rv_z : float, optional
|
|
77
|
+
Z-coordinate for the center of the rv, by default 0.0
|
|
78
|
+
a_endo_rv : float, optional
|
|
79
|
+
Dilation of rv endo ellipsoid in the x-direction, by default 3.0
|
|
80
|
+
b_endo_rv : float, optional
|
|
81
|
+
Dilation of rv endo ellipsoid in the y-direction, by default 1.5
|
|
82
|
+
c_endo_rv : float, optional
|
|
83
|
+
Dilation of rv endo ellipsoid in the z-direction, by default 1.5
|
|
84
|
+
a_epi_rv : float, optional
|
|
85
|
+
Dilation of rv epi ellipsoid in the x-direction, by default 4.0
|
|
86
|
+
b_epi_rv : float, optional
|
|
87
|
+
Dilation of rv epi ellipsoid in the y-direction, by default 2.5
|
|
88
|
+
c_epi_rv : float, optional
|
|
89
|
+
Dilation of rv epi ellipsoid in the z-direction, by default 2.0
|
|
90
|
+
create_fibers : bool, optional
|
|
91
|
+
If True create analytic fibers, by default False
|
|
92
|
+
fiber_angle_endo : float, optional
|
|
93
|
+
Angle for the endocardium, by default -60
|
|
94
|
+
fiber_angle_epi : float, optional
|
|
95
|
+
Angle for the epicardium, by default +60
|
|
96
|
+
fiber_space : str, optional
|
|
97
|
+
Function space for fibers of the form family_degree, by default "P_1"
|
|
98
|
+
|
|
99
|
+
Returns
|
|
100
|
+
-------
|
|
101
|
+
Geometry
|
|
102
|
+
A Geometry with the mesh, markers, markers functions and fibers.
|
|
103
|
+
|
|
104
|
+
"""
|
|
105
|
+
comm = MPI.COMM_WORLD
|
|
106
|
+
outdir = Path(outdir)
|
|
107
|
+
mesh_name = outdir / "biv_ellipsoid.msh"
|
|
108
|
+
if comm.rank == 0:
|
|
109
|
+
outdir.mkdir(exist_ok=True, parents=True)
|
|
110
|
+
|
|
111
|
+
with open(outdir / "info.json", "w") as f:
|
|
112
|
+
json.dump(
|
|
113
|
+
{
|
|
114
|
+
"char_length": char_length,
|
|
115
|
+
"center_lv_x": center_lv_x,
|
|
116
|
+
"center_lv_y": center_lv_y,
|
|
117
|
+
"center_lv_z": center_lv_z,
|
|
118
|
+
"a_endo_lv": a_endo_lv,
|
|
119
|
+
"b_endo_lv": b_endo_lv,
|
|
120
|
+
"c_endo_lv": c_endo_lv,
|
|
121
|
+
"a_epi_lv": a_epi_lv,
|
|
122
|
+
"b_epi_lv": b_epi_lv,
|
|
123
|
+
"c_epi_lv": c_epi_lv,
|
|
124
|
+
"center_rv_x": center_rv_x,
|
|
125
|
+
"center_rv_y": center_rv_y,
|
|
126
|
+
"center_rv_z": center_rv_z,
|
|
127
|
+
"a_endo_rv": a_endo_rv,
|
|
128
|
+
"b_endo_rv": b_endo_rv,
|
|
129
|
+
"c_endo_rv": c_endo_rv,
|
|
130
|
+
"a_epi_rv": a_epi_rv,
|
|
131
|
+
"b_epi_rv": b_epi_rv,
|
|
132
|
+
"c_epi_rv": c_epi_rv,
|
|
133
|
+
"create_fibers": create_fibers,
|
|
134
|
+
"fibers_angle_endo": fiber_angle_endo,
|
|
135
|
+
"fibers_angle_epi": fiber_angle_epi,
|
|
136
|
+
"fiber_space": fiber_space,
|
|
137
|
+
# "mesh_type": MeshTypes.biv_ellipsoid.value,
|
|
138
|
+
"cardiac_geometry_version": __version__,
|
|
139
|
+
"timestamp": datetime.datetime.now().isoformat(),
|
|
140
|
+
},
|
|
141
|
+
f,
|
|
142
|
+
indent=2,
|
|
143
|
+
default=utils.json_serial,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
cgc.biv_ellipsoid(
|
|
147
|
+
mesh_name=mesh_name.as_posix(),
|
|
148
|
+
char_length=char_length,
|
|
149
|
+
center_lv_x=center_lv_x,
|
|
150
|
+
center_lv_y=center_lv_y,
|
|
151
|
+
center_lv_z=center_lv_z,
|
|
152
|
+
a_endo_lv=a_endo_lv,
|
|
153
|
+
b_endo_lv=b_endo_lv,
|
|
154
|
+
c_endo_lv=c_endo_lv,
|
|
155
|
+
a_epi_lv=a_epi_lv,
|
|
156
|
+
b_epi_lv=b_epi_lv,
|
|
157
|
+
c_epi_lv=c_epi_lv,
|
|
158
|
+
center_rv_x=center_rv_x,
|
|
159
|
+
center_rv_y=center_rv_y,
|
|
160
|
+
center_rv_z=center_rv_z,
|
|
161
|
+
a_endo_rv=a_endo_rv,
|
|
162
|
+
b_endo_rv=b_endo_rv,
|
|
163
|
+
c_endo_rv=c_endo_rv,
|
|
164
|
+
a_epi_rv=a_epi_rv,
|
|
165
|
+
b_epi_rv=b_epi_rv,
|
|
166
|
+
c_epi_rv=c_epi_rv,
|
|
167
|
+
)
|
|
168
|
+
comm.barrier()
|
|
169
|
+
geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
|
|
170
|
+
|
|
171
|
+
if comm.rank == 0:
|
|
172
|
+
with open(outdir / "markers.json", "w") as f:
|
|
173
|
+
json.dump(geometry.markers, f, default=utils.json_serial)
|
|
174
|
+
comm.barrier()
|
|
175
|
+
if create_fibers:
|
|
176
|
+
raise NotImplementedError("Fibers not implemented yet for biv ellipsoid.")
|
|
177
|
+
# from .fibers._biv_ellipsoid import create_biv_fibers
|
|
178
|
+
|
|
179
|
+
# create_biv_fibers(
|
|
180
|
+
# mesh=geometry.mesh,
|
|
181
|
+
# ffun=geometry.marker_functions.ffun,
|
|
182
|
+
# markers=geometry.markers,
|
|
183
|
+
# fiber_space=fiber_space,
|
|
184
|
+
# alpha_endo=fiber_angle_endo,
|
|
185
|
+
# alpha_epi=fiber_angle_epi,
|
|
186
|
+
# outdir=outdir,
|
|
187
|
+
# )
|
|
188
|
+
|
|
189
|
+
geo = Geometry.from_folder(comm=comm, folder=outdir)
|
|
190
|
+
return geo
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def biv_ellipsoid_torso(
|
|
194
|
+
outdir: str | Path,
|
|
195
|
+
char_length: float = 0.5,
|
|
196
|
+
heart_as_surface: bool = False,
|
|
197
|
+
torso_length: float = 20.0,
|
|
198
|
+
torso_width: float = 20.0,
|
|
199
|
+
torso_height: float = 20.0,
|
|
200
|
+
rotation_angle: float = math.pi / 6,
|
|
201
|
+
center_lv_x: float = 0.0,
|
|
202
|
+
center_lv_y: float = 0.0,
|
|
203
|
+
center_lv_z: float = 0.0,
|
|
204
|
+
a_endo_lv: float = 2.5,
|
|
205
|
+
b_endo_lv: float = 1.0,
|
|
206
|
+
c_endo_lv: float = 1.0,
|
|
207
|
+
a_epi_lv: float = 3.0,
|
|
208
|
+
b_epi_lv: float = 1.5,
|
|
209
|
+
c_epi_lv: float = 1.5,
|
|
210
|
+
center_rv_x: float = 0.0,
|
|
211
|
+
center_rv_y: float = 0.5,
|
|
212
|
+
center_rv_z: float = 0.0,
|
|
213
|
+
a_endo_rv: float = 3.0,
|
|
214
|
+
b_endo_rv: float = 1.5,
|
|
215
|
+
c_endo_rv: float = 1.5,
|
|
216
|
+
a_epi_rv: float = 4.0,
|
|
217
|
+
b_epi_rv: float = 2.5,
|
|
218
|
+
c_epi_rv: float = 2.0,
|
|
219
|
+
create_fibers: bool = False,
|
|
220
|
+
fiber_angle_endo: float = -60,
|
|
221
|
+
fiber_angle_epi: float = +60,
|
|
222
|
+
fiber_space: str = "P_1",
|
|
223
|
+
) -> Geometry:
|
|
224
|
+
"""Create BiV ellipsoidal geometry
|
|
225
|
+
|
|
226
|
+
Parameters
|
|
227
|
+
----------
|
|
228
|
+
outdir : str | Path
|
|
229
|
+
Directory where to save the results.
|
|
230
|
+
char_length : float, optional
|
|
231
|
+
Characteristic length of mesh, by default 0.5
|
|
232
|
+
heart_as_surface: bool
|
|
233
|
+
If true, create the heart as a a surface inside the torso,
|
|
234
|
+
otherwise let the heart be a volume, by default True.
|
|
235
|
+
torso_length : float, optional
|
|
236
|
+
Length of torso in the x-direction, by default 20.0
|
|
237
|
+
torso_width : float, optional
|
|
238
|
+
Length of torso in the y-direction, by default 20.0
|
|
239
|
+
torso_height : float, optional
|
|
240
|
+
Length of torso in the z-direction, by default 20.0
|
|
241
|
+
rotation_angle: float, optional
|
|
242
|
+
Angle to rotate the torso in order to object realistic position of
|
|
243
|
+
the heart in a torso, by default pi / 6
|
|
244
|
+
center_lv_x : float, optional
|
|
245
|
+
X-coordinate for the center of the lv, by default 0.0
|
|
246
|
+
center_lv_y : float, optional
|
|
247
|
+
Y-coordinate for the center of the lv, by default 0.0
|
|
248
|
+
center_lv_z : float, optional
|
|
249
|
+
Z-coordinate for the center of the lv, by default 0.0
|
|
250
|
+
a_endo_lv : float, optional
|
|
251
|
+
Dilation of lv endo ellipsoid in the x-direction, by default 2.5
|
|
252
|
+
b_endo_lv : float, optional
|
|
253
|
+
Dilation of lv endo ellipsoid in the y-direction, by default 1.0
|
|
254
|
+
c_endo_lv : float, optional
|
|
255
|
+
Dilation of lv endo ellipsoid in the z-direction, by default 1.0
|
|
256
|
+
a_epi_lv : float, optional
|
|
257
|
+
Dilation of lv epi ellipsoid in the x-direction, by default 3.0
|
|
258
|
+
b_epi_lv : float, optional
|
|
259
|
+
Dilation of lv epi ellipsoid in the y-direction, by default 1.5
|
|
260
|
+
c_epi_lv : float, optional
|
|
261
|
+
Dilation of lv epi ellipsoid in the z-direction, by default 1.5
|
|
262
|
+
center_rv_x : float, optional
|
|
263
|
+
X-coordinate for the center of the rv, by default 0.0
|
|
264
|
+
center_rv_y : float, optional
|
|
265
|
+
Y-coordinate for the center of the rv, by default 0.5
|
|
266
|
+
center_rv_z : float, optional
|
|
267
|
+
Z-coordinate for the center of the rv, by default 0.0
|
|
268
|
+
a_endo_rv : float, optional
|
|
269
|
+
Dilation of rv endo ellipsoid in the x-direction, by default 3.0
|
|
270
|
+
b_endo_rv : float, optional
|
|
271
|
+
Dilation of rv endo ellipsoid in the y-direction, by default 1.5
|
|
272
|
+
c_endo_rv : float, optional
|
|
273
|
+
Dilation of rv endo ellipsoid in the z-direction, by default 1.5
|
|
274
|
+
a_epi_rv : float, optional
|
|
275
|
+
Dilation of rv epi ellipsoid in the x-direction, by default 4.0
|
|
276
|
+
b_epi_rv : float, optional
|
|
277
|
+
Dilation of rv epi ellipsoid in the y-direction, by default 2.5
|
|
278
|
+
c_epi_rv : float, optional
|
|
279
|
+
Dilation of rv epi ellipsoid in the z-direction, by default 2.0
|
|
280
|
+
create_fibers : bool, optional
|
|
281
|
+
If True create analytic fibers, by default False
|
|
282
|
+
fiber_angle_endo : float, optional
|
|
283
|
+
Angle for the endocardium, by default -60
|
|
284
|
+
fiber_angle_epi : float, optional
|
|
285
|
+
Angle for the epicardium, by default +60
|
|
286
|
+
fiber_space : str, optional
|
|
287
|
+
Function space for fibers of the form family_degree, by default "P_1"
|
|
288
|
+
|
|
289
|
+
Returns
|
|
290
|
+
-------
|
|
291
|
+
Geometry
|
|
292
|
+
A Geometry with the mesh, markers, markers functions and fibers.
|
|
293
|
+
|
|
294
|
+
"""
|
|
295
|
+
comm = MPI.COMM_WORLD
|
|
296
|
+
outdir = Path(outdir)
|
|
297
|
+
mesh_name = outdir / "biv_ellipsoid_torso.msh"
|
|
298
|
+
if comm.rank == 0:
|
|
299
|
+
outdir.mkdir(exist_ok=True, parents=True)
|
|
300
|
+
|
|
301
|
+
with open(outdir / "info.json", "w") as f:
|
|
302
|
+
json.dump(
|
|
303
|
+
{
|
|
304
|
+
"char_length": char_length,
|
|
305
|
+
"heart_as_surface": heart_as_surface,
|
|
306
|
+
"torso_length": torso_length,
|
|
307
|
+
"torso_width": torso_width,
|
|
308
|
+
"torso_height": torso_height,
|
|
309
|
+
"rotation_angle": rotation_angle,
|
|
310
|
+
"center_lv_x": center_lv_x,
|
|
311
|
+
"center_lv_y": center_lv_y,
|
|
312
|
+
"center_lv_z": center_lv_z,
|
|
313
|
+
"a_endo_lv": a_endo_lv,
|
|
314
|
+
"b_endo_lv": b_endo_lv,
|
|
315
|
+
"c_endo_lv": c_endo_lv,
|
|
316
|
+
"a_epi_lv": a_epi_lv,
|
|
317
|
+
"b_epi_lv": b_epi_lv,
|
|
318
|
+
"c_epi_lv": c_epi_lv,
|
|
319
|
+
"center_rv_x": center_rv_x,
|
|
320
|
+
"center_rv_y": center_rv_y,
|
|
321
|
+
"center_rv_z": center_rv_z,
|
|
322
|
+
"a_endo_rv": a_endo_rv,
|
|
323
|
+
"b_endo_rv": b_endo_rv,
|
|
324
|
+
"c_endo_rv": c_endo_rv,
|
|
325
|
+
"a_epi_rv": a_epi_rv,
|
|
326
|
+
"b_epi_rv": b_epi_rv,
|
|
327
|
+
"c_epi_rv": c_epi_rv,
|
|
328
|
+
"create_fibers": create_fibers,
|
|
329
|
+
"fibers_angle_endo": fiber_angle_endo,
|
|
330
|
+
"fibers_angle_epi": fiber_angle_epi,
|
|
331
|
+
"fiber_space": fiber_space,
|
|
332
|
+
# "mesh_type": MeshTypes.biv_ellipsoid.value,
|
|
333
|
+
"cardiac_geometry_version": __version__,
|
|
334
|
+
"timestamp": datetime.datetime.now().isoformat(),
|
|
335
|
+
},
|
|
336
|
+
f,
|
|
337
|
+
indent=2,
|
|
338
|
+
default=utils.json_serial,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
cgc.biv_ellipsoid_torso(
|
|
342
|
+
mesh_name=mesh_name.as_posix(),
|
|
343
|
+
char_length=char_length,
|
|
344
|
+
heart_as_surface=heart_as_surface,
|
|
345
|
+
torso_length=torso_length,
|
|
346
|
+
torso_height=torso_height,
|
|
347
|
+
torso_width=torso_width,
|
|
348
|
+
rotation_angle=rotation_angle,
|
|
349
|
+
center_lv_x=center_lv_x,
|
|
350
|
+
center_lv_y=center_lv_y,
|
|
351
|
+
center_lv_z=center_lv_z,
|
|
352
|
+
a_endo_lv=a_endo_lv,
|
|
353
|
+
b_endo_lv=b_endo_lv,
|
|
354
|
+
c_endo_lv=c_endo_lv,
|
|
355
|
+
a_epi_lv=a_epi_lv,
|
|
356
|
+
b_epi_lv=b_epi_lv,
|
|
357
|
+
c_epi_lv=c_epi_lv,
|
|
358
|
+
center_rv_x=center_rv_x,
|
|
359
|
+
center_rv_y=center_rv_y,
|
|
360
|
+
center_rv_z=center_rv_z,
|
|
361
|
+
a_endo_rv=a_endo_rv,
|
|
362
|
+
b_endo_rv=b_endo_rv,
|
|
363
|
+
c_endo_rv=c_endo_rv,
|
|
364
|
+
a_epi_rv=a_epi_rv,
|
|
365
|
+
b_epi_rv=b_epi_rv,
|
|
366
|
+
c_epi_rv=c_epi_rv,
|
|
367
|
+
)
|
|
368
|
+
comm.barrier()
|
|
369
|
+
|
|
370
|
+
geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
|
|
371
|
+
|
|
372
|
+
if comm.rank == 0:
|
|
373
|
+
with open(outdir / "markers.json", "w") as f:
|
|
374
|
+
json.dump(geometry.markers, f, default=utils.json_serial)
|
|
375
|
+
comm.barrier()
|
|
376
|
+
|
|
377
|
+
if create_fibers:
|
|
378
|
+
if heart_as_surface:
|
|
379
|
+
logger.warning("Can only create fibers when heart is a volume.")
|
|
380
|
+
else:
|
|
381
|
+
raise NotImplementedError("Fibers not implemented yet for biv ellipsoid.")
|
|
382
|
+
# from .fibers._biv_ellipsoid import create_biv_in_torso_fibers
|
|
383
|
+
|
|
384
|
+
# create_biv_in_torso_fibers(
|
|
385
|
+
# mesh=geometry.mesh,
|
|
386
|
+
# ffun=geometry.marker_functions.ffun,
|
|
387
|
+
# cfun=geometry.marker_functions.cfun,
|
|
388
|
+
# markers=geometry.markers,
|
|
389
|
+
# fiber_space=fiber_space,
|
|
390
|
+
# alpha_endo=fiber_angle_endo,
|
|
391
|
+
# alpha_epi=fiber_angle_epi,
|
|
392
|
+
# outdir=outdir,
|
|
393
|
+
# )
|
|
394
|
+
|
|
395
|
+
geo = Geometry.from_folder(comm=comm, folder=outdir)
|
|
396
|
+
return geo
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def lv_ellipsoid(
|
|
400
|
+
outdir: Path | str,
|
|
401
|
+
r_short_endo: float = 7.0,
|
|
402
|
+
r_short_epi: float = 10.0,
|
|
403
|
+
r_long_endo: float = 17.0,
|
|
404
|
+
r_long_epi: float = 20.0,
|
|
405
|
+
psize_ref: float = 3,
|
|
406
|
+
mu_apex_endo: float = -math.pi,
|
|
407
|
+
mu_base_endo: float = -math.acos(5 / 17),
|
|
408
|
+
mu_apex_epi: float = -math.pi,
|
|
409
|
+
mu_base_epi: float = -math.acos(5 / 20),
|
|
410
|
+
create_fibers: bool = False,
|
|
411
|
+
fiber_angle_endo: float = -60,
|
|
412
|
+
fiber_angle_epi: float = +60,
|
|
413
|
+
fiber_space: str = "P_1",
|
|
414
|
+
aha: bool = True,
|
|
415
|
+
) -> Geometry:
|
|
416
|
+
"""Create an LV ellipsoidal geometry
|
|
417
|
+
|
|
418
|
+
Parameters
|
|
419
|
+
----------
|
|
420
|
+
outdir : Optional[Path], optional
|
|
421
|
+
Directory where to save the results.
|
|
422
|
+
r_short_endo : float, optional
|
|
423
|
+
Shortest radius on the endocardium layer, by default 7.0
|
|
424
|
+
r_short_epi : float, optional
|
|
425
|
+
Shortest radius on the epicardium layer, by default 10.0
|
|
426
|
+
r_long_endo : float, optional
|
|
427
|
+
Longest radius on the endocardium layer, by default 17.0
|
|
428
|
+
r_long_epi : float, optional
|
|
429
|
+
Longest radius on the epicardium layer, by default 20.0
|
|
430
|
+
psize_ref : float, optional
|
|
431
|
+
The reference point size (smaller values yield as finer mesh, by default 3
|
|
432
|
+
mu_apex_endo : float, optional
|
|
433
|
+
Angle for the endocardial apex, by default -math.pi
|
|
434
|
+
mu_base_endo : float, optional
|
|
435
|
+
Angle for the endocardial base, by default -math.acos(5 / 17)
|
|
436
|
+
mu_apex_epi : float, optional
|
|
437
|
+
Angle for the epicardial apex, by default -math.pi
|
|
438
|
+
mu_base_epi : float, optional
|
|
439
|
+
Angle for the epicardial apex, by default -math.acos(5 / 20)
|
|
440
|
+
create_fibers : bool, optional
|
|
441
|
+
If True create analytic fibers, by default False
|
|
442
|
+
fiber_angle_endo : float, optional
|
|
443
|
+
Angle for the endocardium, by default -60
|
|
444
|
+
fiber_angle_epi : float, optional
|
|
445
|
+
Angle for the epicardium, by default +60
|
|
446
|
+
fiber_space : str, optional
|
|
447
|
+
Function space for fibers of the form family_degree, by default "P_1"
|
|
448
|
+
aha : bool, optional
|
|
449
|
+
If True create 17-segment AHA regions
|
|
450
|
+
|
|
451
|
+
Returns
|
|
452
|
+
-------
|
|
453
|
+
Geometry
|
|
454
|
+
A Geometry with the mesh, markers, markers functions and fibers.
|
|
455
|
+
|
|
456
|
+
"""
|
|
457
|
+
comm = MPI.COMM_WORLD
|
|
458
|
+
outdir = Path(outdir)
|
|
459
|
+
mesh_name = outdir / "lv_ellipsoid.msh"
|
|
460
|
+
if comm.rank == 0:
|
|
461
|
+
outdir.mkdir(exist_ok=True, parents=True)
|
|
462
|
+
|
|
463
|
+
with open(outdir / "info.json", "w") as f:
|
|
464
|
+
json.dump(
|
|
465
|
+
{
|
|
466
|
+
"r_short_endo": r_short_endo,
|
|
467
|
+
"r_short_epi": r_short_epi,
|
|
468
|
+
"r_long_endo": r_long_endo,
|
|
469
|
+
"r_long_epi": r_long_epi,
|
|
470
|
+
"psize_ref": psize_ref,
|
|
471
|
+
"mu_apex_endo": mu_apex_endo,
|
|
472
|
+
"mu_base_endo": mu_base_endo,
|
|
473
|
+
"mu_apex_epi": mu_apex_epi,
|
|
474
|
+
"mu_base_epi": mu_base_epi,
|
|
475
|
+
"create_fibers": create_fibers,
|
|
476
|
+
"fibers_angle_endo": fiber_angle_endo,
|
|
477
|
+
"fibers_angle_epi": fiber_angle_epi,
|
|
478
|
+
"fiber_space": fiber_space,
|
|
479
|
+
"aha": aha,
|
|
480
|
+
# "mesh_type": MeshTypes.lv_ellipsoid.value,
|
|
481
|
+
"cardiac_geometry_version": __version__,
|
|
482
|
+
"timestamp": datetime.datetime.now().isoformat(),
|
|
483
|
+
},
|
|
484
|
+
f,
|
|
485
|
+
indent=2,
|
|
486
|
+
default=utils.json_serial,
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
cgc.lv_ellipsoid(
|
|
490
|
+
mesh_name=mesh_name.as_posix(),
|
|
491
|
+
r_short_endo=r_short_endo,
|
|
492
|
+
r_short_epi=r_short_epi,
|
|
493
|
+
r_long_endo=r_long_endo,
|
|
494
|
+
r_long_epi=r_long_epi,
|
|
495
|
+
mu_base_endo=mu_base_endo,
|
|
496
|
+
mu_base_epi=mu_base_epi,
|
|
497
|
+
mu_apex_endo=mu_apex_endo,
|
|
498
|
+
mu_apex_epi=mu_apex_epi,
|
|
499
|
+
psize_ref=psize_ref,
|
|
500
|
+
)
|
|
501
|
+
comm.barrier()
|
|
502
|
+
|
|
503
|
+
geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
|
|
504
|
+
|
|
505
|
+
# if aha:
|
|
506
|
+
# from .aha import lv_aha
|
|
507
|
+
|
|
508
|
+
# geometry = lv_aha(
|
|
509
|
+
# geometry=geometry,
|
|
510
|
+
# r_long_endo=r_long_endo,
|
|
511
|
+
# r_short_endo=r_short_endo,
|
|
512
|
+
# mu_base=mu_base_endo,
|
|
513
|
+
# )
|
|
514
|
+
# from dolfin import XDMFFile
|
|
515
|
+
|
|
516
|
+
# with XDMFFile((outdir / "cfun.xdmf").as_posix()) as xdmf:
|
|
517
|
+
# xdmf.write(geometry.marker_functions.cfun)
|
|
518
|
+
|
|
519
|
+
if comm.rank == 0:
|
|
520
|
+
with open(outdir / "markers.json", "w") as f:
|
|
521
|
+
json.dump(geometry.markers, f, default=utils.json_serial)
|
|
522
|
+
|
|
523
|
+
if create_fibers:
|
|
524
|
+
from .fibers.lv_ellipsoid import create_microstructure
|
|
525
|
+
|
|
526
|
+
create_microstructure(
|
|
527
|
+
mesh=geometry.mesh,
|
|
528
|
+
ffun=geometry.ffun,
|
|
529
|
+
markers=geometry.markers,
|
|
530
|
+
function_space=fiber_space,
|
|
531
|
+
r_short_endo=r_short_endo,
|
|
532
|
+
r_short_epi=r_short_epi,
|
|
533
|
+
r_long_endo=r_long_endo,
|
|
534
|
+
r_long_epi=r_long_epi,
|
|
535
|
+
alpha_endo=fiber_angle_endo,
|
|
536
|
+
alpha_epi=fiber_angle_epi,
|
|
537
|
+
outdir=outdir,
|
|
538
|
+
)
|
|
539
|
+
|
|
540
|
+
geo = Geometry.from_folder(comm=comm, folder=outdir)
|
|
541
|
+
# if aha:
|
|
542
|
+
# # Update schema
|
|
543
|
+
# from .geometry import H5Path
|
|
544
|
+
|
|
545
|
+
# cfun = geo.schema["cfun"].to_dict()
|
|
546
|
+
# cfun["fname"] = "cfun.xdmf:f"
|
|
547
|
+
# geo.schema["cfun"] = H5Path(**cfun)
|
|
548
|
+
|
|
549
|
+
return geo
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
def slab(
|
|
553
|
+
outdir: Path | str,
|
|
554
|
+
lx: float = 20.0,
|
|
555
|
+
ly: float = 7.0,
|
|
556
|
+
lz: float = 3.0,
|
|
557
|
+
dx: float = 1.0,
|
|
558
|
+
create_fibers: bool = True,
|
|
559
|
+
fiber_angle_endo: float = -60,
|
|
560
|
+
fiber_angle_epi: float = +60,
|
|
561
|
+
fiber_space: str = "P_1",
|
|
562
|
+
) -> Geometry:
|
|
563
|
+
"""Create slab geometry
|
|
564
|
+
|
|
565
|
+
Parameters
|
|
566
|
+
----------
|
|
567
|
+
outdir : Optional[Path], optional
|
|
568
|
+
Directory where to save the results.
|
|
569
|
+
lx : float, optional
|
|
570
|
+
Length of slab the x-direction, by default 20.0
|
|
571
|
+
ly : float, optional
|
|
572
|
+
Length of slab the x-direction, by default 7.0
|
|
573
|
+
lz : float, optional
|
|
574
|
+
Length of slab the z-direction, by default 3.0
|
|
575
|
+
dx : float, optional
|
|
576
|
+
Element size, by default 1.0
|
|
577
|
+
create_fibers : bool, optional
|
|
578
|
+
If True create analytic fibers, by default True
|
|
579
|
+
fiber_angle_endo : float, optional
|
|
580
|
+
Angle for the endocardium, by default -60
|
|
581
|
+
fiber_angle_epi : float, optional
|
|
582
|
+
Angle for the epicardium, by default +60
|
|
583
|
+
fiber_space : str, optional
|
|
584
|
+
Function space for fibers of the form family_degree, by default "P_1"
|
|
585
|
+
|
|
586
|
+
Returns
|
|
587
|
+
-------
|
|
588
|
+
Geometry
|
|
589
|
+
A Geometry with the mesh, markers, markers functions and fibers.
|
|
590
|
+
|
|
591
|
+
"""
|
|
592
|
+
comm = MPI.COMM_WORLD
|
|
593
|
+
outdir = Path(outdir)
|
|
594
|
+
mesh_name = outdir / "slab.msh"
|
|
595
|
+
if comm.rank == 0:
|
|
596
|
+
outdir.mkdir(exist_ok=True, parents=True)
|
|
597
|
+
|
|
598
|
+
with open(outdir / "info.json", "w") as f:
|
|
599
|
+
json.dump(
|
|
600
|
+
{
|
|
601
|
+
"lx": lx,
|
|
602
|
+
"ly": ly,
|
|
603
|
+
"lz": lz,
|
|
604
|
+
"dx": dx,
|
|
605
|
+
"create_fibers": create_fibers,
|
|
606
|
+
"fibers_angle_endo": fiber_angle_endo,
|
|
607
|
+
"fibers_angle_epi": fiber_angle_epi,
|
|
608
|
+
"fiber_space": fiber_space,
|
|
609
|
+
# "mesh_type": MeshTypes.slab.value,
|
|
610
|
+
"cardiac_geometry_version": __version__,
|
|
611
|
+
"timestamp": datetime.datetime.now().isoformat(),
|
|
612
|
+
},
|
|
613
|
+
f,
|
|
614
|
+
indent=2,
|
|
615
|
+
default=utils.json_serial,
|
|
616
|
+
)
|
|
617
|
+
|
|
618
|
+
cgc.slab(mesh_name=mesh_name.as_posix(), lx=lx, ly=ly, lz=lz, dx=dx)
|
|
619
|
+
comm.barrier()
|
|
620
|
+
|
|
621
|
+
geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
|
|
622
|
+
|
|
623
|
+
if comm.rank == 0:
|
|
624
|
+
with open(outdir / "markers.json", "w") as f:
|
|
625
|
+
json.dump(geometry.markers, f, default=utils.json_serial)
|
|
626
|
+
|
|
627
|
+
if create_fibers:
|
|
628
|
+
from .fibers.slab import create_microstructure
|
|
629
|
+
|
|
630
|
+
create_microstructure(
|
|
631
|
+
mesh=geometry.mesh,
|
|
632
|
+
ffun=geometry.ffun,
|
|
633
|
+
markers=geometry.markers,
|
|
634
|
+
function_space=fiber_space,
|
|
635
|
+
alpha_endo=fiber_angle_endo,
|
|
636
|
+
alpha_epi=fiber_angle_epi,
|
|
637
|
+
outdir=outdir,
|
|
638
|
+
)
|
|
639
|
+
|
|
640
|
+
geo = Geometry.from_folder(comm=comm, folder=outdir)
|
|
641
|
+
|
|
642
|
+
return geo
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
def slab_in_bath(
|
|
646
|
+
outdir: Path | str,
|
|
647
|
+
lx: float = 1.0,
|
|
648
|
+
ly: float = 0.01,
|
|
649
|
+
lz: float = 0.5,
|
|
650
|
+
bx: float = 0.0,
|
|
651
|
+
by: float = 0.0,
|
|
652
|
+
bz: float = 0.1,
|
|
653
|
+
dx: float = 0.001,
|
|
654
|
+
) -> Geometry:
|
|
655
|
+
"""Create slab geometry
|
|
656
|
+
|
|
657
|
+
Parameters
|
|
658
|
+
----------
|
|
659
|
+
outdir : Path
|
|
660
|
+
Directory where to save the results.
|
|
661
|
+
lx : float, optional
|
|
662
|
+
Length of slab the x-direction, by default 1.0
|
|
663
|
+
ly : float, optional
|
|
664
|
+
Length of slab the x-direction, by default 0.5
|
|
665
|
+
lz : float, optional
|
|
666
|
+
Length of slab the z-direction, by default 0.01
|
|
667
|
+
bx : float, optional
|
|
668
|
+
Thickness of bath the x-direction, by default 0.0
|
|
669
|
+
by : float, optional
|
|
670
|
+
Thickness of bath the x-direction, by default 0.0
|
|
671
|
+
bz : float, optional
|
|
672
|
+
Thickness of bath the z-direction, by default 0.1
|
|
673
|
+
dx : float, optional
|
|
674
|
+
Element size, by default 0.001
|
|
675
|
+
|
|
676
|
+
Returns
|
|
677
|
+
-------
|
|
678
|
+
Geometry
|
|
679
|
+
A Geometry with the mesh, markers, markers functions and fibers.
|
|
680
|
+
|
|
681
|
+
"""
|
|
682
|
+
comm = MPI.COMM_WORLD
|
|
683
|
+
|
|
684
|
+
outdir = Path(outdir)
|
|
685
|
+
mesh_name = outdir / "slab_in_bath.msh"
|
|
686
|
+
if comm.rank == 0:
|
|
687
|
+
outdir.mkdir(exist_ok=True, parents=True)
|
|
688
|
+
|
|
689
|
+
with open(outdir / "info.json", "w") as f:
|
|
690
|
+
json.dump(
|
|
691
|
+
{
|
|
692
|
+
"lx": lx,
|
|
693
|
+
"ly": ly,
|
|
694
|
+
"lz": lz,
|
|
695
|
+
"bx": bx,
|
|
696
|
+
"by": by,
|
|
697
|
+
"bz": bz,
|
|
698
|
+
"dx": dx,
|
|
699
|
+
# "mesh_type": MeshTypes.slab.value,
|
|
700
|
+
"cardiac_geometry_version": __version__,
|
|
701
|
+
"timestamp": datetime.datetime.now().isoformat(),
|
|
702
|
+
},
|
|
703
|
+
f,
|
|
704
|
+
indent=2,
|
|
705
|
+
default=utils.json_serial,
|
|
706
|
+
)
|
|
707
|
+
|
|
708
|
+
cgc.slab_in_bath(
|
|
709
|
+
mesh_name=mesh_name.as_posix(),
|
|
710
|
+
lx=lx,
|
|
711
|
+
ly=ly,
|
|
712
|
+
lz=lz,
|
|
713
|
+
bx=bx,
|
|
714
|
+
by=by,
|
|
715
|
+
bz=bz,
|
|
716
|
+
dx=dx,
|
|
717
|
+
)
|
|
718
|
+
|
|
719
|
+
geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
|
|
720
|
+
|
|
721
|
+
if comm.rank == 0:
|
|
722
|
+
with open(outdir / "markers.json", "w") as f:
|
|
723
|
+
json.dump(geometry.markers, f, default=utils.json_serial)
|
|
724
|
+
|
|
725
|
+
geo = Geometry.from_folder(comm=comm, folder=outdir)
|
|
726
|
+
|
|
727
|
+
return geo
|