Contracting LV with diffusion random walk#
In this notebook, the DiffusionTaylor
trajectory module is presented. This trajectory module combines deterministic particle trajectories with local random walk diffusional motion. To this end, the module fits a taylor expansion to the deterministic trajectories and the eigenvector orientation of a 3x3 tensor capturing gaussian diffusion.
Imports#
[1]:
from IPython.display import display, HTML, clear_output
import base64
import tensorflow as tf
gpu = tf.config.get_visible_devices("GPU")[0]
tf.config.set_visible_devices(gpu, device_type="GPU")
tf.config.experimental.set_memory_growth(gpu, True)
import imageio
import pyvista
import numpy as np
from tqdm.notebook import tqdm
import matplotlib.pyplot as plt
from pint import Quantity
import sys
sys.path.insert(0, "../../")
sys.path.append("..")
import cmrsim
import local_functions
Load determinisitic trajectories#
The node-trajectories of a sliced contracting left ventricle mesh is used to define deterministic part for the trajectory module. The diffusion tensor eigen-vectors are defined by the fiber and sheet directions stored in the reference mesh. In the cells below, the mesh is loaded and rendered including the fiber and sheet directions.
[2]:
files = [f'../../../cmr-random-diffmaps/notebooks/example_data/example_mesh/Displacements/Displ{i:03}.vtk' for i in range(0, 73, 1)]
timing = Quantity(np.loadtxt("../../../cmr-random-diffmaps/notebooks/example_data/example_mesh/PV_loop_reordered.txt")[:, 1], "ms")
original_mesh = cmrsim.datasets.CardiacMeshDataset.from_list_of_meshes(files, timing[:len(files)],
mesh_numbers=(4, 40, 30),
time_precision_ms=3)
refined_mesh = original_mesh.refine(longitudinal_factor=2, circumferential_factor=2, radial_factor=3)
slice_dict = dict(slice_thickness=Quantity(10, "mm"), slice_normal=np.array((0., 0., 1.)),
slice_position=Quantity([0, 0, -3], "cm"), reference_time = Quantity(105, "ms"))
temp = refined_mesh.select_slice(**slice_dict)
slice_mesh = cmrsim.datasets.MeshDataset(temp, refined_mesh.timing)
reference_mesh = pyvista.read("../example_resources/mesh_displacements/ED_reference_mesh.vtk")
slice_mesh.probe_reference(reference_mesh, ["fibers", "sheets"], reference_time=None)
slice_mesh.transform_vectors(slice_mesh.timing, ["fibers", "sheets"], reference_time=None, rotation_only=False)
Render animations
[3]:
plotter = pyvista.Plotter(off_screen=True, window_size=(600, 600), theme=local_functions.get_custom_theme())
slice_mesh.render_input_animation("vectors_slice_fiber", plotter=plotter,
start=Quantity(0, "ms"), end=None, vector="fibers",
mesh_kwargs=dict(opacity=0., show_scalar_bar=False),
vector_kwargs=dict(mag=5e-3, color="red"),
text_kwargs={'position': 'upper_right', 'color': 'black', 'font_size': 16})
plotter.close()
plotter = pyvista.Plotter(off_screen=True, window_size=(600, 600), theme=local_functions.get_custom_theme())
slice_mesh.render_input_animation("vectors_slice_sheets", plotter=plotter,
start=Quantity(0, "ms"), end=None, vector="sheets",
mesh_kwargs=dict(opacity=0., show_scalar_bar=False),
vector_kwargs=dict(mag=5e-3, color="blue"),
text_kwargs={'position': 'upper_right', 'color': 'black', 'font_size': 16})
plotter.close()
gif1 = imageio.v3.imread(f"vectors_slice_fiber.gif")
gif2 = imageio.v3.imread(f"vectors_slice_sheets.gif")
combined_gif = imageio.get_writer(f'meshmesh.gif')
for f1, f2 in tqdm(zip(gif1, gif2), total=gif1.shape[0]):
combined_gif.append_data(np.concatenate([f1, f2], axis=1))
combined_gif.close()
b64 = base64.b64encode(open("meshmesh.gif",'rb').read()).decode('ascii')
display(HTML(f'<img src="data:image/gif;base64,{b64}" />'))