Skip to content
Snippets Groups Projects
Commit 984ceeeb authored by sroscher's avatar sroscher
Browse files

- Updated all files to comply with current python code standard

parent 2a229c1c
No related tags found
1 merge request!77Updated Python code example
Pipeline #1640306 passed
Showing
with 19757 additions and 5094 deletions
"""Calculation module main file."""
# Import standard modules.
import logging
import traceback
from sys import argv, exit
# Import own modules.
from runmodule import run_module
from src.datapreprocessing import data_preprocessing
from src.datapostprocessing import data_postprocessing
def main():
"""Execute the main program for cost estimation.
This function serves as the main entry point for performing the cost estimation.
It goes through the following key steps:
(1) Preprocessing - Acquire necessary data and paths: Call the 'data_preprocessing' function from
'datapreprocessing.py' to set up data and routing information.
(2) Run (main processing) - Execute code depending on method layers: Execute the 'run_module' function from the
'methodexecutionpackage' library. The 'run_module' function is responsible for the programs primary logic.
(3) Postprocessing - Write data to the aircraft exchange file and generate plots and reports: Call the
'data_postprocessing' function from 'datapostprocessing.py' to handle postprocessing tasks. This step receives
data from both the preprocessing and the main processing step.
Note: The 'routing_dict' dictionary is used to manage the routing and execution of different program components.
:raises Exception: Raised to handle other exceptions
:return: None
"""
# Initialize exception string and runtime output logger.
tool_name = 'cost estimation'
runtime_output = logging.getLogger('module_logger')
try:
"""Preprocessing: Acquire necessary data and paths."""
# Run 'data_preprocessing' function from 'datapreprocessing.py'.
paths_and_names, routing_dict, runtime_output = data_preprocessing('cost_estimation_conf.xml', argv)
runtime_output.print('Cost estimation started...')
"""Run: Execute code depending on method layers."""
# Execute 'run_module' function from 'methodexecutionpackage' library. This function is responsible for the main
# logic of the program.
run_output_dict = run_module(paths_and_names, routing_dict, runtime_output)
"""Postprocessing: Write data to aircraft exchange file and generate plots and reports."""
# Run 'data_postprocessing' function from 'datapostprocessing.py' to handle postprocessing tasks. Receives data
# from preprocessing and main processing step.
data_postprocessing(paths_and_names, routing_dict, run_output_dict, runtime_output)
runtime_output.print('Operating cost estimation finished.')
except Exception as e: # pylint: disable=broad-exception-caught
# Handle other exceptions.
runtime_output.critical(exception_string_msg(e, tool_name))
exit(1)
def exception_string_msg(error, tool_name: str):
"""Generate exception message.
Generate a formatted string detailing the type and location of an exception, along with an error message, for
diagnostic purposes. This function is particularly useful for logging or displaying comprehensive error information
when an exception occurs in a specific module or function.
:param exception error: Caught exception object from which details will be extracted
:param str tool_name: Name of the tool or module where the error occurred, used in the final error message
:return str: String including error type, file name, function/method name, line number, code that caused the error,
and error message.
"""
error_type = str(type(error).__name__)
error_trace = traceback.extract_tb(error.__traceback__)
error_file, error_line, error_func, error_code = error_trace[-1]
error_file = error_file.split('/')[-1]
exception_string = f"{error_type}: \n"
exception_string += f" - File : {error_file} \n"
exception_string += f" - Function / Method: {error_func} \n"
exception_string += f" - Line : {error_line} \n"
exception_string += f" - Code : {error_code} \n"
exception_string += f" - Error message : {str(error)} \n"
return exception_string + f"Main execution of {tool_name} module failed! \n" \
f"Program aborted."
if __name__ == "__main__":
main()
"""Calculation module main file."""
# Import standard modules.
import logging
import traceback
from sys import argv, exit
# Import own modules.
from runmodule import run_module
from src.datapreprocessing import data_preprocessing
from src.datapostprocessing import data_postprocessing
def main():
"""Execute the main program for cost estimation.
This function serves as the main entry point for performing the cost estimation.
It goes through the following key steps:
(1) Preprocessing - Acquire necessary data and paths: Call the 'data_preprocessing' function from
'datapreprocessing.py' to set up data and routing information.
(2) Run (main processing) - Execute code depending on method layers: Execute the 'run_module' function from the
'methodexecutionpackage' library. The 'run_module' function is responsible for the programs primary logic.
(3) Postprocessing - Write data to the aircraft exchange file and generate plots and reports: Call the
'data_postprocessing' function from 'datapostprocessing.py' to handle postprocessing tasks. This step receives
data from both the preprocessing and the main processing step.
Note: The 'routing_dict' dictionary is used to manage the routing and execution of different program components.
:raises Exception: Raised to handle other exceptions
:return: None
"""
# Initialize exception string and runtime output logger.
tool_name = 'cost estimation'
tool_version = '0.5.0'
runtime_output = logging.getLogger('module_logger')
try:
"""Preprocessing: Acquire necessary data and paths."""
# Run 'data_preprocessing' function from 'datapreprocessing.py'.
paths_and_names, routing_dict, runtime_output = data_preprocessing('cost_estimation_conf.xml', tool_version, argv)
runtime_output.print('Cost estimation started...')
"""Run: Execute code depending on method layers."""
# Execute 'run_module' function from 'methodexecutionpackage' library. This function is responsible for the main
# logic of the program.
run_output_dict = run_module(paths_and_names, routing_dict, runtime_output)
"""Postprocessing: Write data to aircraft exchange file and generate plots and reports."""
# Run 'data_postprocessing' function from 'datapostprocessing.py' to handle postprocessing tasks. Receives data
# from preprocessing and main processing step.
data_postprocessing(paths_and_names, routing_dict, run_output_dict, runtime_output)
runtime_output.print('Operating cost estimation finished.')
except Exception as e: # pylint: disable=broad-exception-caught
# Handle other exceptions.
runtime_output.critical(exception_string_msg(e, tool_name))
exit(1)
def exception_string_msg(error, tool_name: str):
"""Generate exception message.
Generate a formatted string detailing the type and location of an exception, along with an error message, for
diagnostic purposes. This function is particularly useful for logging or displaying comprehensive error information
when an exception occurs in a specific module or function.
:param exception error: Caught exception object from which details will be extracted
:param str tool_name: Name of the tool or module where the error occurred, used in the final error message
:return str: String including error type, file name, function/method name, line number, code that caused the error,
and error message.
"""
error_type = str(type(error).__name__)
error_trace = traceback.extract_tb(error.__traceback__)
error_file, error_line, error_func, error_code = error_trace[-1]
error_file = error_file.split('/')[-1]
exception_string = f"{error_type}: \n"
exception_string += f" - File : {error_file} \n"
exception_string += f" - Function / Method: {error_func} \n"
exception_string += f" - Line : {error_line} \n"
exception_string += f" - Code : {error_code} \n"
exception_string += f" - Error message : {str(error)} \n"
return exception_string + f"Main execution of {tool_name} module failed! \n" \
f"Program aborted."
if __name__ == "__main__":
main()
......@@ -2,10 +2,10 @@
<module_configuration_file Name="Cost Estimation Runtime Configuration"> <!-- Change naming according to module name -->
<control_settings description="General control settings for this tool">
<aircraft_exchange_file_name description="Specify the name of the exchange file">
<value>CSR-02.xml</value>
<value>UNICADO-SMR-180-TF.xml</value>
</aircraft_exchange_file_name>
<aircraft_exchange_file_directory description="Specify the direction in which the aircraft exchange file can be found">
<value>./projects/CSR/CSR-02/</value>
<value>../projects/UNICADO-SMR/UNICADO-SMR-180-TF/</value>
</aircraft_exchange_file_directory>
<own_tool_level description="Specify the tool level of this tool">
<value>2</value>
......
"""Module providing functions for data preprocessing."""
# Import standard modules.
import importlib
import sys
# Import own modules.
from datapreprocessingmodule import get_paths_and_names, read_routing_values_from_xml
from src.readlayertext import read_energy_carrier
def data_preprocessing(module_configuration_file, argv):
"""Conduct data preprocessing.
This function provides data preprocessing functionalities. It sets up the necessary data and imports relevant
modules. The importlib module is used to dynamically import necessary modules.
The output dictionary 'preprocessing_dict' contains the following values:
- 'layer_1': First routing layer (aircraft configuration) (str)
- 'layer_2': Second routing layer (calculation method fidelity) (str)
- 'layer_3': Third routing layer (calculation method) (str)
- 'user_layer': Last routing layer (fuel type) (user layer) (str)
- 'tool_level': Tool level of current tool (str)
- 'module_import_name': Dynamic string for dynamically generated module import name based on layers (str)
- 'module_name': Module name (name of the module configuration file without its file extension) (str)
- 'func_user_method_data_input_preparation': Reference to 'user_method_data_input_preparation' function
- 'func_user_method_data_output_preparation': Reference to 'user_method_data_output_preparation' function
- 'func_user_method_plot': Reference to 'method_plot' function
- 'func_user_method_html_report': Reference to 'method_html_report' function
- 'func_user_method_xml_export': Reference to 'method_xml_export' function
:param str module_configuration_file: Name of module configuration file
:param list argv: List with optional input arguments
:raises ModuleNotFoundError: Raised if module import failed
:returns:
- dict paths_and_names: Dictionary containing system paths and ElementTrees
- dict preprocessing_dict: Dictionary containing data preprocessing results
- logging.Logger runtime_output: Logging object used for capturing log messages in the module
"""
"""Get paths, names, and xml trees for module configuration and aircraft exchange file."""
# Call 'get_paths_and_names' function to obtain various paths and names.
paths_and_names, runtime_output = get_paths_and_names(module_configuration_file, argv)
# Note: It is the exclusive responsibility of the module manager to modify the following information!
# Create layer description dictionary according to the number of individual layers. The dictionary associates
# layers with their respective XML paths and expected data types according to the following scheme:
# layer_description_dict = {'layer_1': [path, expected data type], 'layer_2': [...]}
# If any information cannot be directly extracted from a specific aircraft exchange file path, please write 'None'
# and manually add the missing value afterward.
aircraft_exchange_tmp_path = 'aircraft_exchange_file/requirements_and_specifications/design_specification/'
module_configuration_tmp_path = 'module_configuration_file/program_settings/configuration/'
layer_description_dict = {
'layer_1': [aircraft_exchange_tmp_path + 'configuration/configuration_type/value', float],
'layer_2': [module_configuration_tmp_path + 'fidelity_name/value', str],
'layer_3': [module_configuration_tmp_path + 'method_name/value', str],
'user_layer': [None, str]
}
""" Extract data from aircraft exchange and module configuration file."""
# Extract root and path to aircraft exchange file and write key data to aircraft exchange file.
root_of_aircraft_exchange_tree = paths_and_names['root_of_aircraft_exchange_tree']
root_of_module_configuration_file = paths_and_names['root_of_module_config_tree']
# Extract data from *.xml files based on the provided layer description (if no path information given ('None'),
# the entry has to be specified manually afterward). The result is stored in the 'preprocessing_dict' dictionary.
# It has the following output format (all values are strings):
# dict_out = {'layer_1': value, 'layer_2': value, 'layer_3': value, 'user_layer': value, 'tool_level': value}
preprocessing_dict = read_routing_values_from_xml(layer_description_dict, root_of_aircraft_exchange_tree,
root_of_module_configuration_file, runtime_output)
# Manual specification of missing layer values ('None' entry layer).
preprocessing_dict['user_layer'] = read_energy_carrier(root_of_aircraft_exchange_tree, runtime_output)
"""Prepare and import modules."""
# Generate a dynamic import name 'module_import_name' for the selected calculation method modules based on the
# provided layer values according to the following scheme:
# 'src.[value of layer_1].[value of layer_2].[value of layer_3]'
module_import_name = 'src'
for _, value in list(preprocessing_dict.items())[:-2]:
module_import_name += '.' + value
# Create import commands by appending the python file name (incl. sub-folders, if necessary) to the generated
# 'module_import_name'. E.g., the import command for the module import from the 'usermethoddatapreparation.py' file
# is as follows:
# 'src.[value of layer_1].[value of layer_2].[value of layer_3].usermethoddatapreparation'
# The import command for the module import from the 'methodplot.py' file in the 'general' folder is as follows:
# 'src.[value of layer_1].[value of layer_2].[value of layer_3].general.methodplot'
# This step is executed for the following python files:
# * 'usermethoddatapreparation.py'
# * 'methodplot.py'
# * 'methodhtmlreport.py'
# * 'methodxmlexport.py'
# * 'methodtexoutput'.py'
import_command_user_method_data_preparation = module_import_name + '.usermethoddatapreparation'
import_command_user_method_plot = module_import_name + '.general.methodplot'
import_command_user_method_html_report = module_import_name + '.general.methodhtmlreport'
import_command_user_method_xml_export = module_import_name + '.general.methodxmlexport'
import_command_user_method_tex_output = module_import_name + '.general.methodtexoutput'
# Add module name and tool level to the preprocessing_dict.
preprocessing_dict['module_import_name'] = module_import_name
preprocessing_dict['module_name'] = module_configuration_file[:-9]
# Dynamically import modules and functions based on the generated import commands.
try:
# Import functions from the specified modules.
import_user_method_data_preparation = importlib.import_module(import_command_user_method_data_preparation)
import_user_method_plot = importlib.import_module(import_command_user_method_plot)
import_user_method_html_report = importlib.import_module(import_command_user_method_html_report)
import_user_method_xml_export = importlib.import_module(import_command_user_method_xml_export)
import_user_method_tex_output = importlib.import_module(import_command_user_method_tex_output)
# Save the imported functions as variables in the 'preprocessing_dict' dictionary.
preprocessing_dict['func_user_method_data_input_preparation'] \
= import_user_method_data_preparation.user_method_data_input_preparation
preprocessing_dict['func_user_method_data_output_preparation'] \
= import_user_method_data_preparation.user_method_data_output_preparation
preprocessing_dict['func_user_method_plot'] = import_user_method_plot.method_plot
preprocessing_dict['func_user_method_html_report'] = import_user_method_html_report.method_html_report
preprocessing_dict['func_user_method_xml_export'] = import_user_method_xml_export.method_xml_export
preprocessing_dict['func_user_method_tex_output'] = import_user_method_tex_output.method_tex_output
# Exception handling for module import error.
except ModuleNotFoundError as module_import_error:
runtime_output_string = ('Error: ' + str(module_import_error) + ' found in '
+ preprocessing_dict['module_name'] + '.\n'
+ ' Program aborted.')
runtime_output.critical(runtime_output_string)
sys.exit(1)
return paths_and_names, preprocessing_dict, runtime_output
"""Module providing functions for data preprocessing."""
# Import standard modules.
import importlib
import sys
# Import own modules.
from datapreprocessingmodule import get_paths_and_names, read_routing_values_from_xml
from src.readlayertext import read_energy_carrier
def data_preprocessing(module_configuration_file, tool_version, argv):
"""Conduct data preprocessing.
This function provides data preprocessing functionalities. It sets up the necessary data and imports relevant
modules. The importlib module is used to dynamically import necessary modules.
The output dictionary 'preprocessing_dict' contains the following values:
- 'layer_1': First routing layer (aircraft configuration) (str)
- 'layer_2': Second routing layer (calculation method fidelity) (str)
- 'layer_3': Third routing layer (calculation method) (str)
- 'user_layer': Last routing layer (fuel type) (user layer) (str)
- 'tool_level': Tool level of current tool (str)
- 'module_import_name': Dynamic string for dynamically generated module import name based on layers (str)
- 'module_name': Module name (name of the module configuration file without its file extension) (str)
- 'func_user_method_data_input_preparation': Reference to 'user_method_data_input_preparation' function
- 'func_user_method_data_output_preparation': Reference to 'user_method_data_output_preparation' function
- 'func_user_method_plot': Reference to 'method_plot' function
- 'func_user_method_html_report': Reference to 'method_html_report' function
- 'func_user_method_xml_export': Reference to 'method_xml_export' function
:param str module_configuration_file: Name of module configuration file
:param list argv: List with optional input arguments
:raises ModuleNotFoundError: Raised if module import failed
:returns:
- dict paths_and_names: Dictionary containing system paths and ElementTrees
- dict preprocessing_dict: Dictionary containing data preprocessing results
- logging.Logger runtime_output: Logging object used for capturing log messages in the module
"""
"""Get paths, names, and xml trees for module configuration and aircraft exchange file."""
# Call 'get_paths_and_names' function to obtain various paths and names.
paths_and_names, runtime_output = get_paths_and_names(module_configuration_file, argv)
paths_and_names['tool_version'] = tool_version
# Note: It is the exclusive responsibility of the module manager to modify the following information!
# Create layer description dictionary according to the number of individual layers. The dictionary associates
# layers with their respective XML paths and expected data types according to the following scheme:
# layer_description_dict = {'layer_1': [path, expected data type], 'layer_2': [...]}
# If any information cannot be directly extracted from a specific aircraft exchange file path, please write 'None'
# and manually add the missing value afterward.
aircraft_exchange_tmp_path = 'aircraft_exchange_file/requirements_and_specifications/design_specification/'
module_configuration_tmp_path = 'module_configuration_file/program_settings/configuration/'
layer_description_dict = {
'layer_1': [aircraft_exchange_tmp_path + 'configuration/configuration_type/value', float],
'layer_2': [module_configuration_tmp_path + 'fidelity_name/value', str],
'layer_3': [module_configuration_tmp_path + 'method_name/value', str],
'user_layer': [None, str]
}
""" Extract data from aircraft exchange and module configuration file."""
# Extract root and path to aircraft exchange file and write key data to aircraft exchange file.
root_of_aircraft_exchange_tree = paths_and_names['root_of_aircraft_exchange_tree']
root_of_module_configuration_file = paths_and_names['root_of_module_config_tree']
# Extract data from *.xml files based on the provided layer description (if no path information given ('None'),
# the entry has to be specified manually afterward). The result is stored in the 'preprocessing_dict' dictionary.
# It has the following output format (all values are strings):
# dict_out = {'layer_1': value, 'layer_2': value, 'layer_3': value, 'user_layer': value, 'tool_level': value}
preprocessing_dict = read_routing_values_from_xml(layer_description_dict, root_of_aircraft_exchange_tree,
root_of_module_configuration_file, runtime_output)
# Manual specification of missing layer values ('None' entry layer).
preprocessing_dict['user_layer'] = read_energy_carrier(root_of_aircraft_exchange_tree, runtime_output)
"""Prepare and import modules."""
# Generate a dynamic import name 'module_import_name' for the selected calculation method modules based on the
# provided layer values according to the following scheme:
# 'src.[value of layer_1].[value of layer_2].[value of layer_3]'
module_import_name = 'src'
for _, value in list(preprocessing_dict.items())[:-2]:
module_import_name += '.' + value
# Create import commands by appending the python file name (incl. sub-folders, if necessary) to the generated
# 'module_import_name'. E.g., the import command for the module import from the 'usermethoddatapreparation.py' file
# is as follows:
# 'src.[value of layer_1].[value of layer_2].[value of layer_3].usermethoddatapreparation'
# The import command for the module import from the 'methodplot.py' file in the 'general' folder is as follows:
# 'src.[value of layer_1].[value of layer_2].[value of layer_3].general.methodplot'
# This step is executed for the following python files:
# * 'usermethoddatapreparation.py'
# * 'methodplot.py'
# * 'methodhtmlreport.py'
# * 'methodxmlexport.py'
# * 'methodtexoutput'.py'
import_command_user_method_data_preparation = module_import_name + '.usermethoddatapreparation'
import_command_user_method_plot = module_import_name + '.general.methodplot'
import_command_user_method_html_report = module_import_name + '.general.methodhtmlreport'
import_command_user_method_xml_export = module_import_name + '.general.methodxmlexport'
import_command_user_method_tex_output = module_import_name + '.general.methodtexoutput'
# Add module name and tool level to the preprocessing_dict.
preprocessing_dict['module_import_name'] = module_import_name
preprocessing_dict['module_name'] = module_configuration_file[:-9]
# Dynamically import modules and functions based on the generated import commands.
try:
# Import functions from the specified modules.
import_user_method_data_preparation = importlib.import_module(import_command_user_method_data_preparation)
import_user_method_plot = importlib.import_module(import_command_user_method_plot)
import_user_method_html_report = importlib.import_module(import_command_user_method_html_report)
import_user_method_xml_export = importlib.import_module(import_command_user_method_xml_export)
import_user_method_tex_output = importlib.import_module(import_command_user_method_tex_output)
# Save the imported functions as variables in the 'preprocessing_dict' dictionary.
preprocessing_dict['func_user_method_data_input_preparation'] \
= import_user_method_data_preparation.user_method_data_input_preparation
preprocessing_dict['func_user_method_data_output_preparation'] \
= import_user_method_data_preparation.user_method_data_output_preparation
preprocessing_dict['func_user_method_plot'] = import_user_method_plot.method_plot
preprocessing_dict['func_user_method_html_report'] = import_user_method_html_report.method_html_report
preprocessing_dict['func_user_method_xml_export'] = import_user_method_xml_export.method_xml_export
preprocessing_dict['func_user_method_tex_output'] = import_user_method_tex_output.method_tex_output
# Exception handling for module import error.
except ModuleNotFoundError as module_import_error:
runtime_output_string = ('Error: ' + str(module_import_error) + ' found in '
+ preprocessing_dict['module_name'] + '.\n'
+ ' Program aborted.')
runtime_output.critical(runtime_output_string)
sys.exit(1)
return paths_and_names, preprocessing_dict, runtime_output
<module_results_file Name="Cost estimation specific outputs">
<general_information description="General information on module execution">
<workflow_version description="Version number of the current workflow">
<value>2.1.0</value>
</workflow_version>
<execution_date description="Execution date and time of the code">
<value>2024-11-18_10-48-55</value>
</execution_date>
<project_name description="Name of the current aircraft project">
<value>CSR-02</value>
</project_name>
<method_name description="Name of current module calculation method">
<value>operating_cost_estimation_tu_berlin</value>
</method_name>
<routing_layer description="Routing layer information">
<layer_1 description="Routing layer_1">
<value>tube_and_wing</value>
</layer_1>
<layer_2 description="Routing layer_2">
<value>empirical</value>
</layer_2>
<layer_3 description="Routing layer_3">
<value>operating_cost_estimation_tu_berlin</value>
</layer_3>
<user_layer description="Routing user_layer">
<value>kerosene</value>
</user_layer>
</routing_layer>
</general_information>
<calculation_results description="Results of calculation method">
<operating_cost_estimation_tu_berlin description="Empirical method to estimate the direct operating costs (DOC) and indirect operating costs (IOC) of an aircraft.">
<design_mission description="Cost estimation results of the design mission">
<direct_operating_costs description="Direct operating costs">
<direct_operating_costs_per_year description="Direct operating costs per year at design point (sum of route dependent and route independent costs)">
<value>30</value>
<unit>EUR</unit>
</direct_operating_costs_per_year>
</direct_operating_costs>
<indirect_operating_costs description="Indirect operating costs">
<value>40</value>
<unit>EUR</unit>
</indirect_operating_costs>
</design_mission>
</operating_cost_estimation_tu_berlin>
</calculation_results>
</module_results_file>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment