### ===================================================================================================================
### Result pictures and plots for analysis
### ===================================================================================================================
# Copyright ©VIIA 2024
### ===================================================================================================================
### 1. Import modules
### ===================================================================================================================
# General imports
from __future__ import annotations
from typing import TYPE_CHECKING, List, Union, Optional
from pathlib import Path
# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.analyses import Analysis
from rhdhv_fem.shapes import Reinforcements
from rhdhv_fem.pictures import ResultPicture, View
from rhdhv_fem.output_items import StrainOutputItem, StressOutputItem
# References for functions and classes in the viiaPackage
if TYPE_CHECKING:
from viiapackage.viiaStatus import ViiaProject
from viiapackage.pictures.result_pictures.helper_functions import viia_load_result_picture_yaml, \
viia_get_resultcase_info, viia_get_output_item, viia_get_scope_shape_sets, viia_get_result_picture_name, \
viia_set_model_and_analysis_diana, viia_get_limits, viia_get_legend_values, viia_get_legend_colours
### ===================================================================================================================
### 2. Function to create the result pictures or plots
### ===================================================================================================================
[docs]def viia_create_result_pictures_plots(
project: ViiaProject, analysis: Analysis = None, pictures: bool = True, view: Optional[View] = None) -> \
Union[List[ResultPicture], List[Path]]:
"""
Function to create the analysis result pictures or plots.
Input:
- project (obj): VIIA project object containing collections of fem objects and project variables.
- analysis (obj): Object reference of analysis, to retrieve the result case, result items, result file and
relevant information. If None is provided it will be checked if there is only one analysis and that one will
be taken. Default is None.
- pictures (bool): Indicates if pictures (to be made in the software gui) of plots (from python memory) should
be made.
- view (obj): View that should be used for the pictures. When None the default view will be used. Default is
None.
Output:
- Returns the result pictures created for nonlinear time-history analysis.
"""
if pictures and (not (project.software == 'abaqus' or project.rhdhvDIANA.run_diana)) and \
not project.rhdhvDIANA.debug:
project.write_log(
"ERROR: Result pictures can only be made in DianaIE or for Abaqus. The creation of result pictures is "
"aborted.")
return []
if analysis is None:
if len(project.collections.analyses) != 1:
project.write_log(
"WARNING: No analysis was given and number of analyses is not equal to 1. The function will be "
"aborted.")
return []
analysis = project.collections.analyses[0]
if analysis.name in [
'A4 - Lineair seismische analyse met fixed base',
'A12 - Niet-lineair seismische analyse met flexbase',
'A15 - Niet-lineair seismische analyse met flexbase met versterkingen'
]:
analysis_type = 'nlth'
elif analysis.name in [
'A10 - Niet-lineair statische analyse met flexbase',
'A13 - Non-linear static flex base strengthening'
]:
analysis_type = 'nls'
elif analysis.name in ['A7 - Eigenwaarde analyse met flex base']:
analysis_type = 'eigen'
else:
raise ValueError("ERROR: Analysis name is not recognised.")
# Get the result picture dictionary
picture_data = viia_load_result_picture_yaml(project=project)
# Find the result scope
result_scopes = picture_data['result_scope'][analysis.name]
# Create defaults
render, result_file = None, None
# Not all plots are available yet
available_plots = ['Dynamic-ShearNxy-Max', 'Dynamic-ShearNxy-Min']
# Create render and view
if pictures:
# The model is created
if not project.rhdhvDIANA.model_created:
if not project.diana_settings.latest_dat_file:
project.diana_settings.latest_dat_file = project.viia_get_file(
path=project.current_analysis_folder, suffix='.dat')
if project.rhdhvDIANA.run_diana:
viia_set_model_and_analysis_diana(project=project, analysis=analysis)
if view is None:
if project.rhdhvDIANA.model_created and project.rhdhvDIANA.run_diana:
project.rhdhvDIANA.showAll('SHAPE')
project.rhdhvDIANA.setViewPoint('ISO1')
diana_view_point = list(project.rhdhvDIANA.currentViewPoint()).copy()
view = project.create_view_from_diana_view_point(name='User_defined', diana_view_point=diana_view_point)
else:
view = project.create_view(name='ISO1')
render = project.create_render(
name=f'Render_{analysis.name.split(" - ")[0]}', geometry=None, mesh='solid shading with free face edge')
# Loop through result scope and picture type
pictures_plots = []
pictures_save_folders = []
tb_files_read = []
for pic_type_key, scopes in result_scopes.items():
# Not all plots are available yet
if not pictures and pic_type_key not in available_plots:
project.write_log(
f"WARNING: Picture type {pic_type_key} is not yet available for plots.")
continue
picture_type = picture_data['picture_type'][pic_type_key]
# Collect the output-block for the requested picture-type and set up the pasth of the result file
output_block_pic = None
if pictures:
for output_block in analysis.calculation_blocks[-1].output_blocks:
if output_block.name == picture_type['output_filename'].replace('SXXX_', ''):
output_block_pic = output_block
if output_block_pic is None:
raise ValueError(f"ERROR: The output-block for {analysis.name} is not recognised.")
result_file = project.current_analysis_folder / (output_block_pic.output_filename + '.dnb')
else:
for output_block in analysis.calculation_blocks[-1].output_blocks:
if output_block.name == picture_type['output_filename'].replace('SXXX_', '') + '_TB':
output_block_pic = output_block
if output_block_pic is None:
raise ValueError(f"ERROR: The output-block for {analysis.name} is not recognised.")
result_file = project.current_analysis_folder / (output_block_pic.output_filename + '.tb')
if result_file not in tb_files_read:
project.read_diana_tbfile(file=result_file)
tb_files_read.append(result_file)
# Set units for the result picture
unit_setting = None
if picture_type.get('unit_type'):
unit_setting = {}
for unit_type, units in zip(picture_type.get('unit_type'), picture_type.get('units')):
unit_setting[unit_type] = units
# Get the step and execute block
step, execute = viia_get_resultcase_info(
analysis=analysis, analysis_block=analysis.calculation_blocks[-1],
case=picture_type['case'], eigenfrequencies=None)
# Loop through scopes, defining the shapes visible
for scope in scopes:
shapes_sets = viia_get_scope_shape_sets(project=project, scope=scope, pic_type=pic_type_key)
# Defining the components, defining for example the directions
for component in picture_type['components']:
# Collect the output-item required for the result picture
output_item = viia_get_output_item(
project=project, picture_type=picture_type,
output_item_lst=output_block_pic.output_items, component=component)
if not output_item:
continue
# Interface results need an item to get the proper abbreviation, but others don't
abbreviation = None
if not ('Interfaces-storey' in scope and ('Line' in scope or 'Point' in scope)):
if 'reinforcements' in scope.lower() and \
isinstance(output_item, (StrainOutputItem, StressOutputItem)):
abbreviation = \
output_item.diana_result_picture(
plot_type=picture_type['plot_type'], result_component=component,
is_reinforcement_result=True)['component']
else:
abbreviation = \
output_item.diana_result_picture(
plot_type=picture_type['plot_type'], result_component=component)['component']
for layer, shapes in shapes_sets.items():
if not shapes:
project.write_log(
f"No picture created for {scope} for layer {layer} because there are no shapes present for "
f"this picture. Picture for component {component} and picture key: {pic_type_key}.",
print_message=False)
continue
if not isinstance(shapes, dict): # Make dict so same functionality can be used.
shapes = {None: shapes}
for property_item, property_shapes in shapes.items():
shapes = [shape for shape in property_shapes if not isinstance(shape, Reinforcements)]
reinforcements = None
if 'reinforcements' in scope.lower():
reinforcements = [shape for shape in property_shapes if isinstance(shape, Reinforcements)]
# Log to logfile the process for pictures
if not shapes and not reinforcements:
project.write_log(
f"No picture created for {scope} for layer {layer} because there are no shapes or "
f"reinforcements present for this picture (in {property_item}). Picture for component "
f"{component} and picture key: {pic_type_key}.", print_message=False)
continue
if not reinforcements and 'reinforcements' in scope.lower():
# No pictures created for reinforcements if they are not present
continue
shapes_as_str = [shape.name if hasattr(shape, 'name') else shape for shape in property_shapes]
project.write_log(
f"Creating picture {scope} for {property_item} ({', '.join(shapes_as_str)}) in "
f"layer {layer}. Picture for component {component} and picture key: {pic_type_key}.",
print_message=False)
# Interface results need an item to get the proper abbreviation
if 'Interfaces-storey' in scope and ('Line' in scope or 'Point' in scope):
abbreviation = \
output_item.diana_result_picture(
plot_type=picture_type['plot_type'], result_component=component,
item=property_shapes[0])['component']
# Get the limits for criterion checks
max_value, min_value, limit_found = viia_get_limits(
project=project, shape_set=property_shapes, scope=scope, component=component,
pic_type=pic_type_key, material=property_item, output_item=output_item)
# if max and min value are None, save in a sub-folder
save_folder = None
if not limit_found:
save_folder = project.current_analysis_folder / 'Non-standard materials result pictures'
if not save_folder.exists():
save_folder.mkdir()
# Decide the legend levels
level_values = None
upper_bound_colour = None
lower_bound_colour = None
if max_value or min_value:
level_values = viia_get_legend_values(
max_value=max_value, min_value=min_value, pic_type=pic_type_key, fraction_digits=5)
upper_bound_colour, lower_bound_colour = viia_get_legend_colours(pic_type=pic_type_key)
max_value = max(level_values)
min_value = min(level_values)
# Set the maximum and minimum value in the legend for the result picture type
contour_legend = project.create_contour_legend(
unit_settings=unit_setting, max_value=max_value, min_value=min_value,
upper_bound_colour=upper_bound_colour, lower_bound_colour=lower_bound_colour,
level_values=level_values, legend_size=[0.015, 0.8])
# Create the picture name
pic_name = viia_get_result_picture_name(
diana_component_abbreviation=abbreviation, scope=scope,
pic_type_key=pic_type_key, layer=layer, material_type=property_item,
analysis_type=analysis_type)
if pictures:
pictures_save_folders.append(save_folder)
# Create the picture
pictures_plots.append(project.create_result_picture(
name=pic_name, analysis=analysis, render=render, shapes=shapes,
reinforcements=reinforcements, view=view, output_block=output_block_pic,
execute_block=execute, output_item=output_item, legend=contour_legend,
result_layer=picture_type.get('result_layer'), step=step,
plot_type=picture_type.get('plot_type'), result_file=result_file.as_posix()))
else:
historic_envelope = None
if pic_type_key.split('-')[-1] in ['Max', '1', '4', '7']:
historic_envelope = 'maximum'
elif pic_type_key.split('-')[-1] in ['Min']:
historic_envelope = 'minimum'
if not save_folder:
save_file = project.current_analysis_folder / (pic_name+'.png')
else:
save_file = save_folder / (pic_name+'.png')
analysis_reference = project.get_analysis_reference(
analysis=analysis, calculation_block=analysis.calculation_blocks[-1],
execute_block=execute, step_nr=step,
historic_envelope=historic_envelope)
# Compute the maximum and minimum values of the plot contour
for index, shape in enumerate(property_shapes):
# Check if there are any results for the shape present, otherwise
if not shape.results:
continue
# Collect the requested results
result_collections = shape.results.get_result_collections(
output_item=output_item, analysis_reference=analysis_reference)
if index == 0:
max_value_plot = max(result_collections[0].node_results)
min_value_plot = min(result_collections[0].node_results)
else:
if max(result_collections[0].node_results) > max_value_plot:
max_value_plot = max(result_collections[0].node_results)
if min(result_collections[0].node_results) < min_value_plot:
min_value_plot = min(result_collections[0].node_results)
if analysis_reference:
title_text = (
f'<b>{analysis_reference.analysis.name}<br>'
f'Extreme {analysis_reference.historic_envelope} upto step '
f'{analysis_reference.step_nr}<br>'
f'{output_item.theoretical_formulation}, {output_item.engineering_notation}</br>'
f'min: {min_value_plot} {output_item.units}, '
f'max: {max_value_plot} {output_item.units}</b>')
else:
title_text = None
project.plot_results_3d(output_item=output_item, node_averaging=False,
legend=contour_legend, shapes=property_shapes,
analysis_reference=analysis_reference, show_plot=False,
show_mesh=False, save_file=save_file, title=title_text)
# Create the result pictures when running in DIANA
if pictures:
if project.rhdhvDIANA.run_diana:
# Getting result picture from existing result files
current_dnb_file = None
for picture in pictures_plots:
picture.to_diana(
current_dnb_file=current_dnb_file, folder=pictures_save_folders[pictures_plots.index(picture)])
current_dnb_file = picture.result_file
elif project.software == 'abaqus':
# Create the images in ABAQUS
for picture in pictures_plots:
picture.to_abaqus()
# Notifications for user and return the created result pictures
project.write_log(f"{len(pictures_plots)} result pictures for {analysis.name.split(' - ')[0]} are created.")
else:
# Notifications for user and return the created result plots
project.write_log(f"{len(pictures_plots)} result plots for {analysis.name.split(' - ')[0]} are created.")
return pictures_plots
### ===================================================================================================================
### 3. End of script
### ===================================================================================================================