Source code for viiapackage.reference_approach.viia_generate_ref_report

### ===================================================================================================================
###   Functions to get the reference object models from MYVIIA
### ===================================================================================================================
# Copyright ©VIIA 2024

### ===================================================================================================================
###   1. Import modules
### ===================================================================================================================

# General imports
from __future__ import annotations
from pathlib import Path
from datetime import datetime
from typing import TYPE_CHECKING, List, Optional

# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.fem_tools import fem_create_folder

# References for functions and classes in the viiaPackage
if TYPE_CHECKING:
    from viiapackage.viiaStatus import ViiaProject
from viiapackage.reference_approach.reference_wall.ref_wall_ip import RefWallIP
from viiapackage.reference_approach.reference_wall.ref_wall_oop import RefWallOOP

# References for openpyxl functions
from openpyxl import load_workbook
from openpyxl.utils.cell import get_column_letter


### ===================================================================================================================
###   2. Collect data for the In-Plane failure checks
### ===================================================================================================================

[docs]def viia_generate_ref_ip_data(obj_vs_measures: dict, ref_models: dict) -> List[RefWallIP]: """ Function to generate the required data for the in-plane failure mechanism according the Reference Approach. Input: - obj_vs_measures (dict): Dictionary with object parts and the applied measures - ref_models (dict): Dictionary with reference models that need to be considered. Output: - Returns a tuple, first is a list of instances of RefWallIP with data and scores per wall. The second item is the current wall as instance of CurrentWall. """ # Raise error if no reference models were loaded in if not ref_models: raise ValueError("ERROR: No reference models available for the in-plane failure check.") # Collect all walls of all reference objects with models in a list total_wall_list = [] for ref_model in ref_models.values(): subproject = ref_model['model'] measures = obj_vs_measures[f"{ref_model['object']} - {ref_model['object_part']}"] for wall in subproject.collections.walls: total_wall_list.append(RefWallIP(wall=wall, measures=measures)) # Returns the list in data structure for reporting and include the current wall return total_wall_list
### =================================================================================================================== ### 3. Collect data for the Out-of-Plane failure checks ### ===================================================================================================================
[docs]def viia_generate_ref_oop_data(obj_vs_measures: dict, ref_models: dict) -> List[RefWallOOP]: """ Function to generate the required data for the out-of-plane failure mechanism according the Reference Approach. Input: - obj_vs_measures (dict): Dictionary with object parts and the applied measures - ref_models (dict): Dictionary with reference models that need to be considered. Output: - Returns a tuple, first is a list of instances of RefWallOOP with data and scores per wall. The second item is the current wall as instance of CurrentWall. """ # Raise error if no reference models were loaded in if not ref_models: raise ValueError("ERROR: No reference models available for the out-of-plane failure check.") # Collect all walls of all reference objects with models in a list total_wall_list = [] for ref_model in ref_models.values(): subproject = ref_model['model'] measures = obj_vs_measures[f"{ref_model['object']} - {ref_model['object_part']}"] for wall in subproject.collections.walls: segments = wall.get_segments() if segments is None or len(segments) == 0: # Skip any non-complying walls continue if len(segments) == 1: total_wall_list.append(RefWallOOP(wall=wall, measures=measures, segment_width=segments[0])) continue for i, segment in enumerate(segments): total_wall_list.append(RefWallOOP(wall=wall, measures=measures, segment_width=segment, segment_nr=i+1)) # Returns the list in data structure for reporting and include the current wall return total_wall_list
### =================================================================================================================== ### 4. Create and fill excel for In-Plane and Out-of-Plane failure checks ### ===================================================================================================================
[docs]def viia_generate_ref_report( project: ViiaProject, wall_data: List[dict], failure_mechanism: str, output_folder: Optional[Path] = None) -> Path: """ This function creates an excel-sheet with a (sorted) list of all walls in the referenced object models. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - wall_data (list of obj): List of data about the walls in the reference objects, including the current wall at first position. - failure_mechanism (str): The type of report required. Possible options are 'IP' and 'OOP'. - output_folder (Path): Optional input for location where to create the report. Default value is None, indicating the default location is used. In normal production objects do not change this! Output: - Creates an excel-sheet with the detailed data of the walls in the reference objects, ranked by comparison to the current wall that is being investigated """ # Collect template file template_location = None if failure_mechanism == 'IP': template_location = project.viia_settings.project_specific_package_location / 'reference_approach' / \ 'templates' / 'VIIA_Template_REF_in_plane_20221130.xlsx' elif failure_mechanism == 'OOP': template_location = project.viia_settings.project_specific_package_location / 'reference_approach' / \ 'templates' / 'VIIA_Template_REF_out_of_plane_20230125.xlsx' if not template_location.exists(): raise FileNotFoundError( f"ERROR: REF template file could not be found in expected location " f"'{template_location.as_posix()}'. Please provide it manually to generate this report.") # Create or check the location where the report is to be generated if output_folder is None: # Create subfolder fem_create_folder('ER', ref_folder=project.workfolder_location) report_location = project.workfolder_location / 'ER' else: if isinstance(output_folder, str): output_folder = Path(output_folder) report_location = output_folder # Check if output-folder is created if not report_location.exists(): raise FileNotFoundError("ERROR: The specified output-folder does not exist, please check input.") # Generate the report time_reference = datetime.now().strftime('%Y%m%d%H%M%S') document_name = 'REF-IP' if failure_mechanism == 'IP' else 'REF-OOP' output_document_name = f"VIIA-{project.name}-{document_name}-{time_reference}.xlsx" target_file = report_location / output_document_name # Writing to excel wb = load_workbook(template_location) ws = wb.worksheets[0] # Fill in header ws['C2'] = project.project_information['objectnummer_viia'] ws['C3'] = f"{project.project_information['objectdeel']} ({project.project_information['analysis_subtype']})" ws['C4'] = datetime.now() # Collect table object table = ws.tables['WallsInPlane'] if failure_mechanism == 'IP' else ws.tables['WallsOutofPlane'] # Set up top left cell top_left_cell = table.ref.split(':')[0] # table.ref looks like 'A5:AD17' top_left_row = "" for ch in top_left_cell: if not ch.isalpha(): top_left_row += ch # Removes the column letters from the top left cell string top_left_row = int(top_left_row) # Set up bottom right cell bottom_right_cell = table.ref.split(':')[1] bottom_right_column = "" for ch in bottom_right_cell: if ch.isalpha(): bottom_right_column += ch # Removes the row numbers from the bottom right cell string # Table length is header + current wall + reference walls + totals column bottom_right_cell = bottom_right_column + str(top_left_row + 1 + len(wall_data) + 1) # Set up new table size table.ref = f"{top_left_cell}:{bottom_right_cell}" # Loop over data entries of the reference objects and fill in template row_pointer = top_left_row for data_entry in wall_data: row_pointer += 1 for k, v in data_entry.items(): if k in table.column_names: if isinstance(v, list) and len(v) == 0: ws[get_column_letter(table.column_names.index(k) + 1) + str(row_pointer)] = '-' elif isinstance(v, list): try: ws[get_column_letter(table.column_names.index(k) + 1) + str(row_pointer)] = (', '.join(v)) except TypeError: ws[get_column_letter(table.column_names.index(k) + 1) + str(row_pointer)] = str(v) else: ws[get_column_letter(table.column_names.index(k) + 1) + str(row_pointer)] = v # Save the target excel file wb.save(target_file) excel_sheet = 'in-plane' if failure_mechanism == 'IP' else 'out-of-plane' project.write_log( f"Successfully created {excel_sheet} excel-sheet for reference approach at '{target_file.as_posix()}'.") return target_file
### =================================================================================================================== ### 5. End of script ### ===================================================================================================================