Skip to content

7.1 Interactive visualisation

Eric Breitbarth edited this page Sep 3, 2024 · 1 revision

We can use Streamlit to view the nodemap files interactively in the web browser. The code below is a minimal example.

# Imports
import os
import streamlit as st
from crackpy.fracture_analysis.data_processing import InputData
from crackpy.structure_elements.data_files import Nodemap
from crackpy.structure_elements.material import Material
import pyvista as pv
from stpyvista import stpyvista
from natsort import natsorted
import json
import re

# read JSON index file
with open('specimen_params.json', 'r') as json_file:
    specimen_list = json.load(json_file)

# Dropdown menu for selecting the specimen
selected_specimen = st.selectbox("Select a specimen", list(specimen_list.keys()))
NODEMAP_PATH = specimen_list[selected_specimen].get('nodemap_path', None)
CONNECTION_PATH = specimen_list[selected_specimen].get('connection_path', None)

# Get list of nodemap files
@st.cache_resource
def list_nodemap_files(NODEMAP_PATH):
    pattern = r'\d+\.txt'
    nodemap_files = []
    folder_content = os.listdir(NODEMAP_PATH)
    for file in folder_content:
        if re.search(pattern, file):
            nodemap_files.append(file)
    nodemap_files = natsorted(nodemap_files)
    return nodemap_files
nodemap_files = list_nodemap_files(NODEMAP_PATH)

# Slider for selecting the nodemap file
selected_file_index = st.slider("Select a Nodemap file", 0, len(nodemap_files) - 1)

# Dropdown menu for selecting the scalar
scalars = ['y [mm]', 'z [mm]', 'u_x [mm]', 'u_y [mm]', 'u_z [mm]', 'u_sum [mm]', 'eps_x [%]', 'eps_y [%]', 'eps_xy [1]',
           'eps_vm [%]', 'sig_x [MPa]', 'sig_y [MPa]', 'sig_xy [MPa]', 'sig_vm [MPa]', 'sig_1 [MPa]', 'sig_2 [MPa]',
           'eps_1 [%]', 'eps_2 [%]']

default_scalar = "eps_vm [%]"
default_index = scalars.index(default_scalar)

selected_scalar = st.selectbox("Select a scalar", scalars, index=default_index)

# Read data from nodemap file
NODEMAP_FILE = nodemap_files[selected_file_index]
CONNECTION_FILE = NODEMAP_FILE[:-4] + '_connections.txt'
nodemap = Nodemap(name=NODEMAP_FILE, folder=NODEMAP_PATH)
material = Material(E=72000, nu_xy=0.33, sig_yield=350)
data = InputData(nodemap)

if CONNECTION_PATH is not None:
    data.set_connection_file(CONNECTION_FILE, folder=CONNECTION_PATH)
data.calc_stresses(material)
data.calc_eps_vm()

# Display nodemap name
st.sidebar.markdown(f"**Path:** {NODEMAP_PATH}")
st.sidebar.markdown(f"**Selected Nodemap:** {NODEMAP_FILE}")

# get meta data
meta_attributes= data.meta_attributes + list(meta_attributes_to_keywords.keys())
for attribute in meta_attributes:
    if hasattr(data, attribute) and getattr(data, attribute) is not None:
        st.sidebar.markdown(f"**{attribute}:** {getattr(data, attribute)}")

# Create pyvista mesh
mesh = data.to_vtk()

# Slider for selecting the scalar
clim_min = st.number_input('clim_min', value=0.0)
clim_max = st.number_input('clim_max', value=0.5)

# Plot the mesh
plotter = pv.Plotter(window_size=[400, 400])
plotter.add_mesh(mesh, scalars=selected_scalar, clim=[clim_min, clim_max], cmap='jet')
plotter.camera_position = 'xy'

# Display the plot using stpyvista
stpyvista(plotter)

The specimen_params.json file stores the nodemap select box paths.

{
    "specimen_name": {
    "nodemap_path": "/nodemap_path",
    "connection_path": null
  }
}

interface