Source code for haskoning_atr_tools.signal_processing_tool.utils.utils

### ===================================================================================================================
###   Utilities for Signal Processing Tool
### ===================================================================================================================
# Copyright ©2025 Haskoning Nederland B.V.

### ===================================================================================================================
###   1. Constants
### ===================================================================================================================

# General imports
import csv
import openpyxl
from pathlib import Path
from typing import Union

# Importing internal modules
from haskoning_atr_tools.signal_processing_tool.utils.constants import SRB_VIBRATION_LIMITS


### ===================================================================================================================
###   2. Handle csv and xlsx files
### ===================================================================================================================

[docs] def read_columns_from_file( file: Union[str, Path], skip_rows: int, columns: list, delimiter: str = ',') -> list[list[float]]: """ This function reads the specified columns from a file (csv or xlsx-file). Input: - file (Path or str): The file path to the data file. - skip_rows (int): The number of rows to skip at the beginning of the file. - columns (list): The names or indices of the columns to read. - delimiter (str): The delimiter used in the csv-file. Default is ','. Output: - Returns a list of lists, each containing the data from the specified columns. Order according the requested columns to be read. """ if isinstance(file, str): file = Path(file) if file.suffix == '.csv': with open(file, 'r') as file: reader = csv.reader(file, delimiter=delimiter) lines = list(reader)[skip_rows-1:] # Check if columns are provided as names if isinstance(columns[0], str): # Read the header row to find the indices of the specified columns header = lines[0] column_indices = [header.index(col) for col in columns] else: # Use the provided indices directly column_indices = columns # Skip the specified number of rows lines = lines[1:] num_lines = len(lines) # Preallocate the data structure data = [[0.0] * num_lines for _ in column_indices] # Read the data from the specified columns for row_idx, row in enumerate(lines): for i, col_idx in enumerate(column_indices): data[i][row_idx] = float(row[col_idx]) return data elif file.suffix == '.xlsx': wb = openpyxl.load_workbook(file, data_only=True) sheet = wb.active rows = list(sheet.iter_rows(values_only=True)) # Check if columns are provided as names if isinstance(columns[0], str): # Read the header row to find the indices of the specified columns header = rows[skip_rows - 1] column_indices = [header.index(col) for col in columns] else: # Use the provided indices directly column_indices = columns # Skip the specified number of rows rows = rows[skip_rows:] num_rows = len(rows) # Preallocate the data structure data = [[0.0] * num_rows for _ in column_indices] # Read the data from the specified columns for i, col_idx in enumerate(column_indices): data[i] = [float(row[col_idx]) for row in rows] return data raise ValueError( f"ERROR: The Signal Processing Tool is only implemented for file types 'csv' or 'xlsx'. Provided was a " f"{file.suffix.replace('.', '')}-file.")
[docs] def write_data_to_file( folder_path: str, file_name: str, data: list[list[float]], columns_header: list, column_numbers: list, skip_rows: int = 0, file_type: str = 'csv') -> Path: """ Writes specified columns to a file (CSV or Excel). Input: - folder_path (str): The path to the folder. - file_name (str): The name of the file. - data (list[list[float]]): The data to write, each sublist representing a column. - columns_header (list): The names of the columns. - column_numbers (list): The column numbers to write the data into. - skip_rows (int): The number of rows to skip at the beginning of the file. - file_type (str): The type of the file ('csv' or 'xlsx'). Defaults to 'csv'. Output: - Returns the path of the created csv- or xlsx-file. """ if file_type not in ['csv', 'xlsx']: raise ValueError("ERROR: Invalid file type. Must be 'csv' or 'xlsx'.") if file_type == 'csv': file_path = Path(folder_path + '/' + file_name + '.csv') with open(file_path, 'w', newline='') as file: writer = csv.writer(file) for _ in range(skip_rows): writer.writerow([]) writer.writerow(columns_header) # Write the header row for row in zip(*data): row_data = [''] * len(columns_header) for i, col_num in enumerate(column_numbers): row_data[col_num] = row[i] writer.writerow(row_data) else: file_path = Path(folder_path + '/' + file_name + '.xlsx') wb = openpyxl.Workbook() sheet = wb.active for _ in range(skip_rows): sheet.append([]) sheet.append(columns_header) # Write the header row for row in zip(*data): row_data = [''] * len(columns_header) for i, col_num in enumerate(column_numbers): row_data[col_num] = row[i] sheet.append(row_data) wb.save(file_path) return file_path
### =================================================================================================================== ### 3. SBR vibration limits ### ===================================================================================================================
[docs] def get_sbr_vibration_limit(building_function: str, time_of_day: str, limit_type: str) -> float: """ Retrieves the SRB vibration limit based on building function, time of day, and limit type. Input: - building_function (str): The function of the building. Select from 'residential', 'healthcare', 'meeting', 'office', or 'critical'. - time_of_day (str): Select the time of day: 'day', or 'night'. - limit_type (str): Select the type of limit: 'A1', 'A2', or 'A3'. Output: - Returns the vibration limit value. """ # Normalize inputs building_function = building_function.lower() time_of_day = time_of_day.lower() limit_type = limit_type.upper() # Retrieve the limit try: return SRB_VIBRATION_LIMITS[building_function][time_of_day][limit_type] except KeyError: raise KeyError( "ERROR: Invalid input to determine the SBR vibration limit. Please check the building function, time of " "day, or limit type.")
### =================================================================================================================== ### 4. End of script ### ===================================================================================================================