Source code for febid.libraries.vtk_rendering.show_animation_new

"""
View series of consequent 3D-Structure files as an animated process.
"""
import os, time
from datetime import datetime
from tkinter import filedialog as fd

import numpy as np
import vtk

import febid.libraries.vtk_rendering.VTK_Rendering as vr
from febid.Structure import Structure

[docs]def open_file(directory=''): """ Gather files and timestamps sorted in the order of creation :param directory: folder with vtk files :return: filenames and timestamps """ # Getting all filenames in the specified directory # Getting creation dates of the files # Zipping them together and sorting by the creation date # Unzipping and returning to the order sorted # directory = '/Users/sandrik1742/Documents/PycharmProjects/FEBID/code/Experiment runs/gr=0' files = sorted(os.listdir(directory))[:] n = 0 for i in range(len(files)-1, -1, -1): if os.path.splitext(files[i])[1] != '.vtk': files.pop(i) n += 1 ctimes = [time.ctime(os.path.getmtime(os.path.join(directory, file))) for file in files] times = [datetime.strptime(t, '%a %b %d %H:%M:%S %Y') for t in ctimes] # occurences = [re.findall("^\d+",file) for file in files] # ocurrences = [int(item[0]) for item in occurences] ocurrences = zip(times, files) ocurrences = sorted(ocurrences) files = [item for _, item in ocurrences] times.sort() # times = [re.findall("\d\d:\d\d:\d\d",file) for file in files] return files, times
[docs]def show_animation(directory='', show='precursor'): """ Show animated process from series of vtk files. Files must have consequent creation dates to align correctly :param directory: folder with vtk files :param show: which dataset to use for imaging. Accepts 'precursor' for surface precursor density or 'deposit' for surface deposit filling. :return: """ # The space where a 3D object appears when rendered is called a Scene # The Scene also contains all the rendered texts, scalar bars and buttons # Opening files if not directory: os.chdir('../../..') init_dir = os.getcwd() directory = fd.askdirectory() files, times = open_file(directory) # Getting data for initialization structure = Structure() vtk_obj = vr.pv.read(os.path.join(directory, files[0])) structure.load_from_vtk(vtk_obj) cell_dim, deposit, precursor, surface_bool, semi_surface_bool, ghosts_bool = structure.cell_dimension, \ structure.deposit, \ structure.precursor, \ structure.surface_bool, \ structure.semi_surface_bool, \ structure.ghosts_bool # Determining rendered dataset if show not in ['precursor', 'deposit', 'temperature']: raise RuntimeError(f'The specified dataset \'{show}\' is not supported.') if show == 'precursor': data_name = show.capitalize() cmap = 'plasma' mask_name = 'surface_bool' if show == 'deposit': data_name = show.capitalize() cmap = 'viridis' mask_name = 'surface_bool' if show == 'temperature': data_name = show.capitalize() cmap = 'inferno' mask_name = 'deposit' data = structure.__getattribute__(show) mask = structure.__getattribute__(mask_name) t, sim_time, beam_position = vr.read_field_data(vtk_obj) # getting deposition process features # Preparing left corner text with times text = '' if t: text += f'Time: {t} \n' if sim_time: text += f'Simulation time: {sim_time:.7f} s \n' # Setting the setup scene render = vr.Render(cell_dim) render._add_3Darray(data) render.p.add_text('Adjust the scene for the animation \n and close the window.', position='upper_edge') cam_pos = render.show() # Setting the first frame render = vr.Render(cell_dim) # Creating an arrow at beam position if beam_position is not None: x_pos, y_pos = beam_position x, y = int(x_pos / render.cell_dim), int(y_pos / render.cell_dim) max_z = structure.deposit[:, y, x].nonzero()[0].max() start = np.array([0, 0, 100]).reshape(1, 3) # position of the center of the arrow end = np.array([0, 0, -100]).reshape(1, 3) # direction and resulting size render.arrow = render.p.add_arrows(start, end, color='tomato', name='Beam_position') render.arrow.SetPosition(x_pos, y_pos, max_z * render.cell_dim + 30) # relative to the initial position render._add_3Darray(data, opacity=1, show_edges=True, scalar_name=data_name, button_name=data_name, cmap=cmap) # Hiding cells index = np.zeros_like(data, dtype=np.uint8) index[mask == False] = vtk.vtkDataSetAttributes.HIDDENCELL render.p.mesh.cell_data[vtk.vtkDataSetAttributes.GhostArrayName()] = index.ravel() render.p.mesh.set_active_scalars(data_name) # Adding text t, sim_time, beam_position = vr.read_field_data(vtk_obj) text = '' if t: text += f'Time: {t} \n' if sim_time: text += f'Simulation time: {sim_time:.7f} s \n' font_size = 12 stats = '''Cells: Height: Volume: Frame ''' render.p.add_text(text, position='upper_left', font_size=font_size, name='time') render.p.add_text(stats, font_size=font_size, position='upper_right', name='stats') render.show(interactive_update=True, cam_pos=cam_pos) init_layer = np.count_nonzero(deposit==-2) # substrate layer total_dep_cells = [np.count_nonzero(deposit[deposit<0])-init_layer] # total number of fully deposited cells growth_rate=[] # growth rate on each step # Animation for i in range(1, len(files)): # Reading data vtk_obj = vr.pv.read(os.path.join(directory, files[i])) # Loading the structure structure.load_from_vtk(vtk_obj) cell_dim = structure.cell_dimension surface_bool = structure.surface_bool deposit = structure.deposit data = structure.__getattribute__(show) if show == 'precursor': mask = surface_bool if show == 'deposit': mask = surface_bool if show == 'temperature': mask = deposit<0 # Calculating deposition process features total_dep_cells.append(np.count_nonzero(deposit[deposit < 0]) - init_layer) volume = int((total_dep_cells[i] + deposit[surface_bool].sum())*cell_dim**3) delta_t = (times[i] - times[i - 1]).total_seconds() if delta_t < 1: delta_t = 1 growth_rate.append(cell_dim**3 * (total_dep_cells[i] - total_dep_cells[i - 1]) / delta_t * 60 * 60) t, sim_time, beam_position = vr.read_field_data(vtk_obj) # Setting up text # Left corner text = '' if t: text += f'Time: {t} \n' if sim_time: text += f'Simulation time: {sim_time:.7f} s \n' # Right corner stats = f'Cells: {total_dep_cells[i]} \n\ Height: {int(np.nonzero(deposit)[0].max() * cell_dim)} nm \n\ Volume: {volume} nm^3 \n\ Frame {i+1}/{len(files)}' # Updating arrow position if beam_position is not None: x_pos, y_pos = beam_position x, y = int(x_pos / render.cell_dim), int(y_pos / render.cell_dim) max_z = structure.deposit[:, y, x].nonzero()[0].max() render.arrow.SetPosition(x_pos, y_pos, max_z * render.cell_dim + 30) # relative to the initial position # Redrawing the 3D object if necessary if render.p.mesh.n_cells != data.size: # must redraw if shape changes data_visibility = render.p.renderer.actors[data_name].GetVisibility() render.p.remove_actor(data_name+'_caption') render.y_pos = 5 render.p.button_widgets.clear() render.p.remove_actor(data_name) render._add_3Darray(data, opacity=1, show_edges=True, scalar_name=data_name, button_name=data_name, cmap=cmap) render.p.renderer.actors[data_name].SetVisibility(data_visibility) index = np.zeros_like(data, dtype=np.uint8) render.p.mesh.cell_data[vtk.vtkDataSetAttributes.GhostArrayName()] = index.ravel() render.p.mesh.set_active_scalars(data_name) else: render.p.mesh[data_name] = data.ravel() # new data, ravel() sends a view # Updating hidden cells index[mask == 0] = vtk.vtkDataSetAttributes.HIDDENCELL index[mask == 1] = 0 # surface_bool is not bool type and cannot be used directly as index # Updating text render.p.actors['time'].SetText(2, text) render.p.actors['stats'].SetText(3, stats) # render.p.mesh.cell_data[vtk.vtkDataSetAttributes.GhostArrayName()] = index.ravel() p=data[mask] # Updating the scalar bar try: render.p.update_scalar_bar_range([np.partition(p[p!=p.min()], 4)[2], p.max()]) except: pass render.update() else: # finishing with a static scene # Clearing the scene render.y_pos = 5 render.p.button_widgets.clear() render.p.clear() # Reading data vtk_obj = vr.pv.read(os.path.join(directory, files[-1])) # Loading the structure structure.load_from_vtk(vtk_obj) cell_dim = structure.cell_dimension surface_bool = structure.surface_bool deposit = structure.deposit data = structure.__getattribute__(show) total_dep_cells.append(np.count_nonzero(deposit[deposit < 0]) - init_layer) render._add_3Darray(data, opacity=1, show_edges=True, scalar_name=data_name, button_name=data_name, cmap=cmap) # adding structure render.p.update_scalar_bar_range([np.partition(p[p != p.min()], 4)[2], p.max()]) render.p.mesh.cell_data[vtk.vtkDataSetAttributes.GhostArrayName()] = index.ravel() render.p.mesh.set_active_scalars(data_name) t, sim_time, beam_position = vr.read_field_data(vtk_obj) text = '' if t: text += f'Time: {t} \n' if sim_time: text += f'Simulation time: {sim_time:.7f} s \n' render.p.add_text(text, position='upper_left', font_size=font_size) # showing time passed render.p.add_text(f'Cells: {total_dep_cells[i-1]} \n' # showing total number of deposited cells f'Height: {int(np.nonzero(deposit)[0].max() * cell_dim)} nm \n' # showing current height of the structure f'Volume: {volume} nm^3 \n' f'Growth rate: {int(np.asarray(growth_rate).mean())} cell/h \n' # showing average growth rate f'Frame {i+1}/{len(files)} \n', position='upper_right', font_size=font_size) if beam_position is not None: x_pos, y_pos = beam_position x, y = int(x_pos / render.cell_dim), int(y_pos / render.cell_dim) max_z = structure.deposit[:, y, x].nonzero()[0].max() start = np.array([0, 0, 100]).reshape(1, 3) # position of the center of the arrow end = np.array([0, 0, -100]).reshape(1, 3) # direction and resulting size render.arrow = render.p.add_arrows(start, end, color='tomato') render.arrow.SetPosition(x_pos, y_pos, max_z * render.cell_dim + 30) # relative to the initial position render.show(interactive_update=False)
if __name__ == '__main__': show_animation()