Source code for postResults

import os
import pandas as pd
import pyvista as pv
import matplotlib as mpl
import numpy as np
import h5py

[docs] def readVariousFormats(base_file_name,dirResults): """ Reads data from various file formats (HDF5, Parquet, CSV) stored in a specified directory. This function checks for the presence of HDF5 and Parquet files first. If neither is found, it falls back to reading a CSV file. The data is then returned as a pandas DataFrame. Parameters: ----------- base_file_name : str The base name of the file (without the extension). dirResults : str The directory where the files are located. Returns: -------- df : pandas.DataFrame The data loaded into a DataFrame from the appropriate file format. """ csv_file_path = os.path.join(dirResults, f"{base_file_name}.csv") hdf5_file_path = os.path.join(dirResults, f"{base_file_name}.h5") parquet_file_path = os.path.join(dirResults, f"{base_file_name}.parquet") if os.path.exists(hdf5_file_path): # Read from HDF5 if available df = pd.read_hdf(hdf5_file_path) elif os.path.exists(parquet_file_path): # Read from Parquet if available df = pd.read_parquet(parquet_file_path) else: # Read from CSV and convert to HDF5 and Parquet df = pd.read_csv(csv_file_path) return df
[docs] def pathForResults(self): """ Returns the path to the directory where results are stored. If a custom path is provided (`self.customPath`), it returns that path. Otherwise, it returns a default path. Parameters: ----------- self : object The instance of the class calling this function. It should have an attribute `customPath`. Returns: -------- resultsPath : str The path to the results directory. """ if self.customPath is not None: resultsPath=self.customPath else: resultsPath="/Users/alessandromastrofini/LocalFiles/acePlaqueGlobalResults/FinalOne/" return resultsPath
[docs] def importResults(self, ptName, step, customPath=None, myStr = ''): """ Imports results data from HDF5 files based on the patient name (`ptName`), step number (`step`), and an optional custom string filter (`myStr`). This function searches for the appropriate file, reads the data from it, and returns it as a pandas DataFrame. Parameters: ----------- self : object The instance of the class calling this function. ptName : str The name of the patient. step : int The step number in the process. customPath : str, optional A custom path to the results directory. If `None`, a default path is used. myStr : str, optional A custom string to filter the files. Defaults to an empty string. Returns: -------- df : pandas.DataFrame The data loaded from the HDF5 file into a DataFrame. Raises: ------- FileNotFoundError If no file matching the criteria is found. """ if customPath is not None: dirResults=os.path.join(customPath,ptName,"Results") resultsFiles=os.listdir(dirResults) sorted_files = sorted(resultsFiles) filtered_files = list(filter(lambda file: myStr in file, sorted_files)) sub = [s for s in filtered_files if "__step_"+str(step) in s] if not sub: raise FileNotFoundError(f"No file found for step {step}") else: file_to_load = os.path.join(dirResults,sub[0]) #print(file_to_load) with h5py.File(file_to_load, 'r') as hdf: # List all datasets (keys) in the HDF5 file dataset_keys = list(hdf.keys()) # Initialize a dictionary to hold data for each key data_dict = {} # Loop over each dataset key and load it into the dictionary for key in dataset_keys: data_dict[key] = hdf[key][:] # Convert the dictionary to a pandas DataFrame df = pd.DataFrame(data_dict) return df
[docs] def importClassicResults(self,ptName,step,customPath=None): """ Imports classic results for a given patient and step number. This function is a wrapper around `importResults`, specifically designed to filter files with the "classic_" prefix. Parameters: ----------- self : object The instance of the class calling this function. ptName : str The name of the patient. step : int The step number in the process. customPath : str, optional A custom path to the results directory. Returns: -------- df : pandas.DataFrame The classic results data loaded into a DataFrame. """ df = importResults(self, ptName, step, customPath, "classic_") return df
[docs] def importGrowthResults(self,ptName,step,customPath=None): """ Imports growth results for a given patient and step number. This function is a wrapper around `importResults`, specifically designed to filter files with the "growth_" prefix. Parameters: ----------- self : object The instance of the class calling this function. ptName : str The name of the patient. step : int The step number in the process. customPath : str, optional A custom path to the results directory. Returns: -------- df : pandas.DataFrame The growth results data loaded into a DataFrame. """ df = importResults(self, ptName, step, customPath, "growth_") return df
[docs] def show3DmeshWithFields(mesh,field='field1',clim=[-10, 80],scaling='',plotter=None): """ Imports growth results for a given patient and step number. This function is a wrapper around `importResults`, specifically designed to filter files with the "growth_" prefix. Parameters: ----------- self : object The instance of the class calling this function. ptName : str The name of the patient. step : int The step number in the process. customPath : str, optional A custom path to the results directory. Returns: -------- df : pandas.DataFrame The growth results data loaded into a DataFrame. """ p=get3DmeshWithFields(mesh,field=field,clim=clim,scaling=scaling,plotter=plotter) p.show()
[docs] def get3DmeshWithFields(mesh,field='field1',clim=[-10, 80],scaling='',plotter=None, center = None, cmap = None): """ Creates a 3D visualization of the mesh with slices along the x, y, and z axes and maps a scalar field to the mesh. The function returns a plotter object for further customization or display. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be visualized. field : str, optional The name of the scalar field to display on the mesh. Defaults to `'field1'`. clim : list, optional Color limits for the scalar field. Defaults to `[-10, 80]`. scaling : str, optional A string for scaling information to be displayed as a label. plotter : pyvista.Plotter, optional An existing `pyvista` plotter instance. If `None`, a new one is created. center : tuple, optional The center point for slicing. If `None`, the mesh center is used. cmap : str, optional The colormap to use for the scalar field. Defaults to `'jet'`. Returns: -------- p : pyvista.Plotter The plotter object with the 3D mesh and field visualized. """ if cmap is None: cmap = 'jet' if center is None: center = mesh.center else: center = center # Create slices at the center of the mesh slice_x = mesh.slice(normal='x', origin=center) slice_y = mesh.slice(normal='y', origin=center) slice_z = mesh.slice(normal='z', origin=center) # Create a plotter if plotter is None: p = pv.Plotter(window_size=[600, 800]) else: p = plotter # Add the slices to the plotter p.add_mesh(slice_x, scalars=field, cmap=cmap,show_scalar_bar=False, clim=clim) p.add_mesh(slice_y, scalars=field, cmap=cmap, show_scalar_bar=False, clim=clim) p.add_mesh(slice_z, scalars=field, cmap=cmap, show_scalar_bar=False, clim=clim) p.add_scalar_bar(title=None, label_font_size=10, title_font_size=14, position_x=0.22) if scaling is not None: p.add_text(field + " ["+scaling+"]", position="lower_edge", font_size=6, color="black") p.view_isometric() p.camera.zoom(1.2) return p
[docs] def get3DSlicesWithFields(mesh,field='field1',clim=[-10, 80],scaling='',plotter=None,normal=None, center=None, textLabel = True, scalarBar = True, cmap= None): """ Creates a 3D visualization of the mesh with a single slice along a specified normal axis, mapping a scalar field to the slice. The function returns a plotter object for further customization or display. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be visualized. field : str, optional The name of the scalar field to display on the mesh slice. Defaults to `'field1'`. clim : list, optional Color limits for the scalar field. Defaults to `[-10, 80]`. scaling : str, optional A string for scaling information to be displayed as a label. plotter : pyvista.Plotter, optional An existing `pyvista` plotter instance. If `None`, a new one is created. normal : str, optional The normal axis for slicing the mesh (`'x'`, `'y'`, or `'z'`). Defaults to `'z'`. center : tuple, optional The center point for slicing. If `None`, the mesh center is used. textLabel : bool, optional Whether to add a text label indicating the field name and scaling. Defaults to `True`. scalarBar : bool, optional Whether to add a scalar bar to the plot. Defaults to `True`. cmap : str, optional The colormap to use for the scalar field. Defaults to `'jet'`. Returns: -------- p : pyvista.Plotter The plotter object with the 3D mesh slice and field visualized. """ if cmap is None: cmap = 'jet' if plotter is None: p = pv.Plotter(window_size=[600, 800]) else: p = plotter if normal is None: n = 'z' else: n = normal if center is None: c = mesh.center else: c = center # Create slices at the center of the mesh slice = mesh.slice(normal=n, origin=c) # Add the slices to the plotter #p.add_mesh(slice, scalars='mats', cmap=cmap, show_scalar_bar=False) p.add_mesh(slice, scalars=field, cmap=cmap, show_scalar_bar=False, clim=clim) if scalarBar: p.add_scalar_bar(title=None, label_font_size=10, title_font_size=14, position_x=0.22) if scaling is not None: scalingString = scaling else: scalingString = '' if textLabel: p.add_text(field + " ["+scalingString+"]", position="lower_edge", font_size=6, color="black") p.camera.zoom(1.2) if n == 'z': p.view_xy() elif n == 'y': p.view_xz() elif n == 'x': p.view_yz() return p
[docs] def show3DmeshWithMaterials(mesh,plotter=None): """ Displays a 3D mesh with segmented material properties visualized on it using the `pyvista` library. This function uses `get3DmeshWithMaterials` to prepare the plot and then displays it. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be visualized. plotter : pyvista.Plotter, optional An existing `pyvista` plotter instance. If `None`, a new one is created. Returns: -------- None """ p=get3DmeshWithMaterials(mesh,plotter=plotter) p.show()
# def get3DmeshWithMaterials(mesh,plotter=None): # if plotter is None: # p = pv.Plotter(window_size=[600, 800]) # else: # p = plotter # mesh.set_active_scalars("mats") # # Apply a threshold over a data range # calc = mesh.threshold([-228000,-(228000+33200)/2]) # lipid = mesh.threshold([-(228000+33200)/2, (126000-33200)/2]) # cmap = mpl.colors.ListedColormap(["navy", "orange", "red"]) # p.add_mesh(mesh, color = 'red', opacity=0.1, label='MATX') # p.add_mesh(calc, color = 'navy', opacity=0.4, label='CALC') # p.add_mesh(lipid, color = 'orange', opacity=0.4, label='LRNC/IPH') # p.add_legend(loc='lower right',bcolor='white', face='None') # p.camera.zoom(1.2) # p.view_isometric() # return p
[docs] def get3DmeshWithMaterials(mesh,plotter=None, addLegend=True): """ Creates a 3D visualization of the mesh with segmented material properties, applying different colors and opacities for each material. The function returns a plotter object for further customization or display. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be visualized. plotter : pyvista.Plotter, optional An existing `pyvista` plotter instance. If `None`, a new one is created. addLegend : bool, optional Whether to add a legend to the plot indicating the materials. Defaults to `True`. Returns: -------- p : pyvista.Plotter The plotter object with the 3D mesh and materials visualized. """ if plotter is None: p = pv.Plotter(window_size=[600, 800]) else: p = plotter mesh.set_active_scalars("matsSegmented") # Apply a threshold over a data range calc = mesh.threshold([-0.1,0.1]) lipid = mesh.threshold([1.9, 2.1]) fibr = mesh.threshold([2.9, 3.1]) p.add_mesh(mesh, color = 'red', opacity=0.1, label='MATX') p.add_mesh(calc, color = 'navy', opacity=0.3, label='CALC') p.add_mesh(lipid, color = 'orange', opacity=0.3, label='LRNC') p.add_mesh(fibr, color = 'darkred', opacity=0.3, label='FIBR') if addLegend: p.add_legend(loc='lower right',bcolor='white', face='None') p.camera.zoom(1.2) p.view_isometric() return p
[docs] def getSlicemeshWithMaterials(mesh,plotter=None,normal=None,center=None,addBar=False): """ Creates a 3D visualization of a single slice of the mesh with segmented material properties, applying different colors for each material. The function returns a plotter object for further customization or display. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be visualized. plotter : pyvista.Plotter, optional An existing `pyvista` plotter instance. If `None`, a new one is created. normal : str, optional The normal axis for slicing the mesh (`'x'`, `'y'`, or `'z'`). Defaults to `'z'`. center : tuple, optional The center point for slicing. If `None`, the mesh center is used. addBar : bool, optional Whether to add a scalar bar to the plot. Defaults to `False`. Returns: -------- p : pyvista.Plotter The plotter object with the 3D mesh slice and materials visualized. """ if plotter is None: p = pv.Plotter(window_size=[600, 800]) else: p = plotter if normal is None: n = 'z' else: n = normal if center is None: c = mesh.center else: c = center # Create slices at the center of the mesh #slice = mesh.slice(normal=n, origin=c) sl = mesh.slice(normal=n, origin=c) mask = sl.threshold(value=[-0.000001,0.00001], scalars='matsSegmented') p.add_mesh(mask, color='navy') mask2 = sl.threshold(value=[0.9,1.1], scalars='matsSegmented') p.add_mesh(mask2, color='red') mask3 = sl.threshold(value=[1.99999,2.000001], scalars='matsSegmented') p.add_mesh(mask3, color='orange') mask4 = sl.threshold(value=[2.99999,3.000001], scalars='matsSegmented') p.add_mesh(mask4, color='darkred') cmap = mpl.colors.ListedColormap(["navy", "red", "orange","darkred"]) # Add the slices to the plotter #p.add_mesh(slice, scalars='mats', cmap=cmap, show_scalar_bar=False) #p.add_mesh(slice, scalars='matsSegmented', cmap=cmap, show_scalar_bar=False, clim=[0,3]) if addBar: p.add_scalar_bar(title=None, label_font_size=0, n_labels=0, title_font_size=14, position_x=0.22) p.add_text("MATX", position=(400, 18), font_size=5, color="black") p.add_text("LRNC/IPH", position=(280, 18), font_size=5, color="black") p.add_text("CALC", position=(180, 18), font_size=5, color="black") p.add_text("FIBR", position=(180, 18), font_size=5, color="black") if n == 'z': p.view_xy() elif n == 'y': p.view_xz() elif n == 'x': p.view_yz() return p
[docs] def show3DslicesWithMaterials(mesh,plotter=None): """ Displays 3D slices of the mesh with segmented material properties visualized on them using the `pyvista` library. This function uses `get3DslicesWithMaterials` to prepare the plot and then displays it. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be visualized. plotter : pyvista.Plotter """ p= get3DslicesWithMaterials(mesh,plotter=plotter) p.show()
[docs] def get3DslicesWithMaterials(mesh,plotter=None, normal=None, center=None, addBar= True): """ Creates a 3D visualization of the mesh with slices along the x, y, and z axes, showing segmented material properties. The function returns a plotter object for further customization or display. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be visualized. plotter : pyvista.Plotter, optional An existing `pyvista` plotter instance. If `None`, a new one is created. normal : str, optional The normal axis for slicing the mesh. If `None`, slices are made along all three axes. center : tuple, optional The center point for slicing. If `None`, the mesh center is used. addBar : bool, optional Whether to add a scalar bar to the plot. Defaults to `True`. Returns: -------- p : pyvista.Plotter The plotter object with the 3D mesh slices and materials visualized. """ if plotter is None: p = pv.Plotter(window_size=[600, 800]) else: p = plotter p.add_mesh(mesh, opacity=0.2, color='red', show_scalar_bar=False) cmap = mpl.colors.ListedColormap(["navy", "red", "orange", "darkred"]) if center is None: c = mesh.center else: c = center if normal is None or c is None: # Create slices at the center of the mesh slice_x = mesh.slice(normal='x', origin=c) slice_y = mesh.slice(normal='y', origin=c) slice_z = mesh.slice(normal='z', origin=c) p.add_mesh(slice_x, scalars='matsSegmented', cmap=cmap, show_scalar_bar=False,clim=[0,3]) p.add_mesh(slice_y, scalars='matsSegmented', cmap=cmap, show_scalar_bar=False,clim=[0,3]) p.add_mesh(slice_z, scalars='matsSegmented', cmap=cmap, show_scalar_bar=False,clim=[0,3]) else: slice = mesh.slice(normal=normal, origin=c) p.add_mesh(slice, scalars='matsSegmented', cmap=cmap, show_scalar_bar=False,clim=[0,3]) # Add the slices to the plotter if addBar: p.add_scalar_bar(title=None, label_font_size=0, n_labels=0, title_font_size=14, position_x=0.22) p.add_text("MATX", position=(400, 18), font_size=5, color="black") p.add_text("LRNC/IPH", position=(280, 18), font_size=5, color="black") p.add_text("CALC", position=(180, 18), font_size=5, color="black") p.add_text("FIBR", position=(180, 18), font_size=5, color="black") p.camera.zoom(1.2) p.view_isometric() return p
[docs] def show3Dmesh(mesh,plotter=None): """ Displays a 3D mesh using the `pyvista` library. This function uses `get3Dmesh` to prepare the plot and then displays it. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be visualized. plotter : pyvista.Plotter, optional An existing `pyvista` plotter instance. If `None`, a new one is created. Returns: -------- None """ p = get3Dmesh(mesh,plotter=plotter) p.show()
[docs] def get3Dmesh(mesh, plotter=None): """ Creates a 3D visualization of the mesh with slices along the x, y, and z axes. The function returns a plotter object for further customization or display. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be visualized. plotter : pyvista.Plotter, optional An existing `pyvista` plotter instance. If `None`, a new one is created. Returns: -------- p : pyvista.Plotter The plotter object with the 3D mesh and slices visualized. """ center = mesh.center # Create slices at the center of the mesh slice_x = mesh.slice(normal='x', origin=center) slice_y = mesh.slice(normal='y', origin=center) slice_z = mesh.slice(normal='z', origin=center) if plotter is None: p = pv.Plotter(window_size=[600, 800]) else: p = plotter p.add_mesh(mesh, scalars=None, color='red', opacity=0.3, show_scalar_bar=False) # Add the slices to the plotter p.add_mesh(slice_x, scalars=None, color='blue', opacity =0.2,show_scalar_bar=False) p.add_mesh(slice_z, scalars=None, color='blue', opacity =0.2,show_scalar_bar=False) p.add_mesh(slice_y, scalars=None, color='blue', opacity =0.2,show_scalar_bar=False) p.view_isometric() p.camera.zoom(1.2) return p
[docs] def saveSlice(mesh,normal,posRatio,path,clim=[-10, 80]): """ Saves screenshots of a slice of the mesh with field data and material properties. This function creates a slice along a specified axis at a given position, visualizes the field data, and saves it as an image. It also visualizes segmented materials and saves another image. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be sliced and visualized. normal : str The axis normal to the slice (`'x'`, `'y'`, or `'z'`). posRatio : float The position ratio along the normal axis where the slice is made (0 to 100). path : str The base path where the screenshots will be saved. clim : list, optional Color limits for the scalar field. Defaults to `[-10, 80]`. Returns: -------- None """ center = mesh.center origin=center xmin, xmax, ymin, ymax, zmin, zmax = mesh.bounds if normal=='x': origin[0]= xmin+(xmax-xmin)*posRatio/100 elif normal=='y': origin[1]= ymin+(ymax-ymin)*posRatio/100 elif normal=='z': origin[2]= zmin+ (zmax-zmin)*posRatio/100 # Create slices at the center of the mesh slice = mesh.slice(normal=normal, origin=center) # Create a plotter p = pv.Plotter(window_size=[600, 800]) # Add the slices to the plotter p.add_mesh(slice, scalars='field1', cmap='jet',show_scalar_bar=False, clim=clim) p.add_scalar_bar(title=None, label_font_size=10, title_font_size=14, position_x=0.22) p.add_text("1° principal stress", position="lower_edge", font_size=6, color="black") if normal=='x': p.view_yz() elif normal=='y': p.view_xz() elif normal=='z': p.view_xy() p.screenshot(path+"_stress.png") # compute the position (max - min )* ratio cmap = mpl.colors.ListedColormap(["red", "navy", "orange"]) p = pv.Plotter(window_size=[600, 800]) # Add the slices to the plotter p.add_mesh(slice, scalars='matsSegmented', cmap=cmap, show_scalar_bar=False) p.add_scalar_bar(title=None, label_font_size=0, n_labels=0, title_font_size=14, position_x=0.22) p.add_text("MATX", position=(400, 18), font_size=5, color="black") p.add_text("LRNC/IPH", position=(280, 18), font_size=5, color="black") p.add_text("CALC", position=(180, 18), font_size=5, color="black") if normal=='x': p.view_yz() elif normal=='y': p.view_xz() elif normal=='z': p.view_xy() p.screenshot(path+"_mats.png") return
[docs] def saveMeshIsoViewWithMaterialSlice(mesh,path): """ Saves a screenshot of the 3D mesh in an isometric view with material slices. This function creates slices along the x, y, and z axes, visualizes the segmented material properties, and saves the resulting view as an image. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be sliced and visualized. path : str The path where the screenshot will be saved. Returns: -------- None """ center = mesh.center # Create slices at the center of the mesh slice_x = mesh.slice(normal='x', origin=center) slice_y = mesh.slice(normal='y', origin=center) slice_z = mesh.slice(normal='z', origin=center) # Create a plotter p = pv.Plotter(window_size=[600, 800]) # Create a plotter p = pv.Plotter(window_size=[600, 800]) cmap = mpl.colors.ListedColormap(["navy", "red", "orange"]) # Add the slices to the plotter p.add_mesh(mesh, opacity=0.1, show_scalar_bar=False) p.add_mesh(slice_x, scalars='mats', cmap=cmap, show_scalar_bar=False) p.add_mesh(slice_y, scalars='mats', cmap=cmap, show_scalar_bar=False) p.add_mesh(slice_z, scalars='mats', cmap=cmap, show_scalar_bar=False) #p.add_scalar_bar(title=None, label_font_size=0, n_labels=0, title_font_size=14, position_x=0.22) #p.add_text("MATX", position=(400, 18), font_size=5, color="black") #p.add_text("LRNC/IPH", position=(280, 18), font_size=5, color="black") #p.add_text("CALC", position=(180, 18), font_size=5, color="black") p.camera.zoom(1.2) p.view_isometric() p.screenshot(path+".png")
[docs] def saveMeshIsoView(mesh,path): """ Saves a screenshot of the 3D mesh in an isometric view. This function visualizes the mesh without any additional slices or field data, and saves the resulting view as an image. Parameters: ----------- mesh : pyvista.PolyData The mesh data to be visualized. path : str The path where the screenshot will be saved. Returns: -------- None """ center = mesh.center # Create slices at the center of the mesh # Create a plotter p = pv.Plotter(window_size=[600, 800]) # Create a plotter p = pv.Plotter(window_size=[600, 800]) # Add the slices to the plotter p.add_mesh(mesh, opacity=0.3, show_scalar_bar=False) p.camera.zoom(1.2) p.view_isometric() p.screenshot(path+".png")