diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..bd28b9c --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.9 diff --git a/pyproject.toml b/pyproject.toml index 6d7b5fe..9aff969 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,7 +85,7 @@ select = [ # "I", # isort (Ensures imports are sorted properly) # "B", # flake8-bugbear (Detects likely bugs and bad practices) # "TID", # flake8-tidy-imports (Checks for banned or misplaced imports) - # "UP", # pyupgrade (Automatically updates old Python syntax) + "UP", # pyupgrade (Automatically updates old Python syntax) # "YTT", # flake8-2020 (Detects outdated Python 2/3 compatibility issues) # "FLY", # flynt (Converts old-style string formatting to f-strings) # "PIE", # flake8-pie diff --git a/src/lasso/diffcrash/diffcrash_run.py b/src/lasso/diffcrash/diffcrash_run.py index 9901e64..289bccd 100644 --- a/src/lasso/diffcrash/diffcrash_run.py +++ b/src/lasso/diffcrash/diffcrash_run.py @@ -10,7 +10,7 @@ import time import typing from concurrent import futures -from typing import List, Union +from typing import Union from pathlib import Path import psutil @@ -688,9 +688,7 @@ def run_import(self, pool: futures.ThreadPoolExecutor): if n_imports_finished != n_new_imports_finished: # pylint: disable = consider-using-f-string - msg = "Running Imports ... [{0}/{1}] - {2:3.2f}%\r".format( - n_new_imports_finished, len(return_code_futures), percentage - ) + msg = f"Running Imports ... [{n_new_imports_finished}/{len(return_code_futures)}] - {percentage:3.2f}%\r" print(str_running(msg), end="", flush=True) self.logger.info(msg) @@ -1091,7 +1089,7 @@ def is_logfile_successful(self, logfile: Path) -> bool: success : `bool` """ - with open(logfile, "r", encoding="utf-8") as fp: + with open(logfile, encoding="utf-8") as fp: for line in fp: if "successfully" in line: return True @@ -1181,7 +1179,7 @@ def clear_project_dir(self): # reinit logger self.logger = self._setup_logger() - def read_config_file(self, config_file: str) -> List[str]: + def read_config_file(self, config_file: str) -> list[str]: """Read a diffcrash config file Parameters @@ -1203,7 +1201,7 @@ def read_config_file(self, config_file: str) -> List[str]: # pylint: disable = too-many-branches # pylint: disable = too-many-statements - with open(config_file, "r", encoding="utf-8") as conf: + with open(config_file, encoding="utf-8") as conf: conf_lines = conf.readlines() line = 0 @@ -1303,7 +1301,7 @@ def read_config_file(self, config_file: str) -> List[str]: return export_item_list - def check_if_logfiles_show_success(self, pattern: str) -> List[str]: + def check_if_logfiles_show_success(self, pattern: str) -> list[str]: """Check if a logfiles with given pattern show success Parameters diff --git a/src/lasso/dimred/dimred_run.py b/src/lasso/dimred/dimred_run.py index d822395..42631d1 100644 --- a/src/lasso/dimred/dimred_run.py +++ b/src/lasso/dimred/dimred_run.py @@ -7,7 +7,8 @@ import sys import time from concurrent.futures.process import ProcessPoolExecutor -from typing import Sequence, Tuple, Union +from typing import Union +from collections.abc import Sequence import h5py import numpy as np @@ -529,7 +530,7 @@ def _parse_simulation_and_reference_runs( reference_run_pattern: Union[None, str], exclude_runs: Sequence[str], table: Table, - ) -> Tuple[Sequence[str], str, Sequence[str]]: + ) -> tuple[Sequence[str], str, Sequence[str]]: # pylint: disable = too-many-locals # search all denoted runs diff --git a/src/lasso/dimred/hashing.py b/src/lasso/dimred/hashing.py index 2186a8c..6280ff0 100644 --- a/src/lasso/dimred/hashing.py +++ b/src/lasso/dimred/hashing.py @@ -1,7 +1,8 @@ import multiprocessing import os import time -from typing import List, Tuple, Union, Sequence +from typing import Union +from collections.abc import Sequence import h5py import numpy as np @@ -104,8 +105,8 @@ def _compute_mode_similarities( hashes2: np.ndarray, eigenvectors_sub1: np.ndarray, eigenvectors_sub2: np.ndarray, - matches: List[Tuple[int, int]], -) -> List[float]: + matches: list[tuple[int, int]], +) -> list[float]: """Compute the mode similarity between different meshes Parameters @@ -217,7 +218,7 @@ def _join_hash_comparison_thread_files( def run_hash_comparison( comparison_filepath: str, - hashes_filepaths: List[str], + hashes_filepaths: list[str], n_threads: int = 1, print_progress: bool = False, ): @@ -597,7 +598,7 @@ def curve_normalizer(x: np.ndarray, y: np.ndarray): def compute_hashes( eig_vecs: np.ndarray, result_field: np.ndarray, n_points: int = 100, bandwidth: float = 0.05 -) -> List[Tuple[np.ndarray, np.ndarray]]: +) -> list[tuple[np.ndarray, np.ndarray]]: """Compute hashes for a result field Parameters diff --git a/src/lasso/dimred/hashing_sphere.py b/src/lasso/dimred/hashing_sphere.py index 44415cb..e656d15 100644 --- a/src/lasso/dimred/hashing_sphere.py +++ b/src/lasso/dimred/hashing_sphere.py @@ -1,5 +1,4 @@ import os -import typing import warnings import h5py @@ -15,7 +14,7 @@ warnings.simplefilter(action="ignore", category=FutureWarning) -def _create_sphere_mesh(diameter: np.ndarray) -> typing.Tuple[np.ndarray, np.ndarray]: +def _create_sphere_mesh(diameter: np.ndarray) -> tuple[np.ndarray, np.ndarray]: """Compute the alpha and beta increments for a meshed sphere for binning the projected values @@ -70,7 +69,7 @@ def _create_sphere_mesh(diameter: np.ndarray) -> typing.Tuple[np.ndarray, np.nda def _project_to_sphere( points: np.ndarray, centroid: np.ndarray, axis: str = "Z" -) -> typing.Tuple[np.ndarray, np.ndarray]: +) -> tuple[np.ndarray, np.ndarray]: """compute the projection vectors of centroid to each point in terms of spherical coordinates Parameters diff --git a/src/lasso/dimred/svd/clustering_betas.py b/src/lasso/dimred/svd/clustering_betas.py index 08938a9..75fd5b3 100644 --- a/src/lasso/dimred/svd/clustering_betas.py +++ b/src/lasso/dimred/svd/clustering_betas.py @@ -1,4 +1,5 @@ -from typing import Sequence, Tuple, Union +from typing import Union +from collections.abc import Sequence import numpy as np from sklearn.cluster import DBSCAN, OPTICS, KMeans, SpectralClustering @@ -418,7 +419,7 @@ def document_algorithm(keyword): } -def create_cluster_arg_dict(args: Sequence[str]) -> Union[Tuple[str, dict], str]: +def create_cluster_arg_dict(args: Sequence[str]) -> Union[tuple[str, dict], str]: """Determines which cluster to use and creates a python dictionary to use as cluster_params Parameters @@ -493,7 +494,7 @@ def create_cluster_arg_dict(args: Sequence[str]) -> Union[Tuple[str, dict], str] return cluster_type, cluster_arg_dict -def create_detector_arg_dict(args: Sequence[str]) -> Union[Tuple[str, dict], str]: +def create_detector_arg_dict(args: Sequence[str]) -> Union[tuple[str, dict], str]: """Determines which detector to use and creates a python dictionary to use as detector_params Parameters @@ -579,7 +580,7 @@ def group_betas( detector=None, cluster_params=None, detector_params=None, -) -> Union[Tuple[list, list], str]: +) -> Union[tuple[list, list], str]: """ Base function to to group betas into groups, detect outliers. Provides that all different clustering and outlier detection algorithms are implemented in an easy to access environment. diff --git a/src/lasso/dimred/svd/keyword_types.py b/src/lasso/dimred/svd/keyword_types.py index 0043487..ffaaccf 100644 --- a/src/lasso/dimred/svd/keyword_types.py +++ b/src/lasso/dimred/svd/keyword_types.py @@ -1,6 +1,3 @@ -import typing - - class ClusterType: """Specifies names of specific clustering algorithms @@ -22,7 +19,7 @@ class ClusterType: SpectralClustering = "SpectralClustering" @staticmethod - def get_cluster_type_name() -> typing.List[str]: + def get_cluster_type_name() -> list[str]: """Get the name of the clustering algorithms""" return [ ClusterType.OPTICS, @@ -51,7 +48,7 @@ class DetectorType: # Experimental = "Experimental" @staticmethod - def get_detector_type_name() -> typing.List[str]: + def get_detector_type_name() -> list[str]: """Get the name of the detector algorithms""" return [ DetectorType.IsolationForest, diff --git a/src/lasso/dimred/svd/plot_beta_clusters.py b/src/lasso/dimred/svd/plot_beta_clusters.py index 804d63d..fc6adcf 100644 --- a/src/lasso/dimred/svd/plot_beta_clusters.py +++ b/src/lasso/dimred/svd/plot_beta_clusters.py @@ -2,7 +2,8 @@ import re import time import webbrowser -from typing import Sequence, Union +from typing import Union +from collections.abc import Sequence import numpy as np @@ -118,11 +119,13 @@ def plot_clusters_js( id_nr.append(id_group) # pylint: disable = consider-using-f-string - _three_min_ = '<script type="text/javascript">%s</script>' % _read_file( - os.path.join( - # move path to "~/lasso/" - os.path.split(os.path.split(os.path.dirname(__file__))[0])[0], - "plotting/resources/three_latest.min.js", + _three_min_ = '<script type="text/javascript">{}</script>'.format( + _read_file( + os.path.join( + # move path to "~/lasso/" + os.path.split(os.path.split(os.path.dirname(__file__))[0])[0], + "plotting/resources/three_latest.min.js", + ) ) ) @@ -136,10 +139,10 @@ def plot_clusters_js( name = "outliers" color = "black" else: - name = "cluster {i}".format(i=index) + name = f"cluster {index}" color = colorlist[(index - 1) % 10] formatted_trace = TRACE_STRING.format( - _traceNr_="trace{i}".format(i=index), + _traceNr_=f"trace{index}", _name_=name, _color_=color, _runIDs_=id_cluster[index].tolist(), diff --git a/src/lasso/dimred/svd/pod_functions.py b/src/lasso/dimred/svd/pod_functions.py index d367539..3c233c2 100644 --- a/src/lasso/dimred/svd/pod_functions.py +++ b/src/lasso/dimred/svd/pod_functions.py @@ -1,4 +1,4 @@ -from typing import Tuple, Union +from typing import Union import numpy as np from scipy.sparse import csc_matrix @@ -37,7 +37,7 @@ def calculate_v_and_betas( stacked_sub_displ: np.ndarray, progress_bar: Union[None, Progress, PlaceHolderBar] = None, task_id: Union[None, TaskID] = None, -) -> Union[str, Tuple[np.ndarray, np.ndarray]]: +) -> Union[str, tuple[np.ndarray, np.ndarray]]: """ Calculates the right reduced order Basis V and up to 10 eigenvalues of the subsamples diff --git a/src/lasso/dimred/svd/subsampling_methods.py b/src/lasso/dimred/svd/subsampling_methods.py index 5a26611..eda14ed 100644 --- a/src/lasso/dimred/svd/subsampling_methods.py +++ b/src/lasso/dimred/svd/subsampling_methods.py @@ -1,7 +1,8 @@ import os import random import time -from typing import List, Sequence, Tuple, Union +from typing import Union +from collections.abc import Sequence import numpy as np from sklearn.neighbors import NearestNeighbors @@ -45,7 +46,7 @@ def _mark_dead_eles(node_indexes: np.ndarray, alive_shells: np.ndarray) -> np.nd def _extract_shell_parts( part_list: Sequence[int], d3plot: D3plot -) -> Union[Tuple[np.ndarray, np.ndarray], str]: +) -> Union[tuple[np.ndarray, np.ndarray], str]: """ Extracts a shell part defined by its part ID out of the given d3plot. Returns a new node index, relevant coordinates and displacement @@ -123,7 +124,7 @@ def _extract_shell_parts( return err_msg.format(part) def mask_parts( - part_list2: List[int], element_part_index: np.ndarray, element_node_index: np.ndarray + part_list2: list[int], element_part_index: np.ndarray, element_node_index: np.ndarray ) -> np.ndarray: element_part_filter = np.full(element_part_index.shape, False) proc_parts = [] @@ -180,7 +181,7 @@ def mask_parts( def create_reference_subsample( load_path: str, parts: Sequence[int], nr_samples=2000 -) -> Union[Tuple[np.ndarray, float, float], str]: +) -> Union[tuple[np.ndarray, float, float], str]: """ Loads the D3plot at load_path, extracts the node coordinates of part 13, returns a random subsample of these nodes @@ -238,7 +239,7 @@ def create_reference_subsample( def remap_random_subsample( load_path: str, parts: list, reference_subsample: np.ndarray -) -> Union[Tuple[np.ndarray, float, float], str]: +) -> Union[tuple[np.ndarray, float, float], str]: """ Remaps the specified sample onto a new mesh provided by reference subsampl, using knn matching diff --git a/src/lasso/dyna/array_type.py b/src/lasso/dyna/array_type.py index 27fecf0..7c5c535 100644 --- a/src/lasso/dyna/array_type.py +++ b/src/lasso/dyna/array_type.py @@ -1,6 +1,3 @@ -import typing - - class ArrayType: """Specifies the names for specific arrays @@ -494,7 +491,7 @@ class ArrayType: rigid_wall_position = "rigid_wall_position" @staticmethod - def get_state_array_names() -> typing.List[str]: + def get_state_array_names() -> list[str]: """Get the names of all state arrays Returns: diff --git a/src/lasso/dyna/binout.py b/src/lasso/dyna/binout.py index be03569..d85b983 100644 --- a/src/lasso/dyna/binout.py +++ b/src/lasso/dyna/binout.py @@ -1,5 +1,5 @@ import glob -from typing import List, Union +from typing import Union import h5py import numpy as np @@ -67,13 +67,13 @@ def __init__(self, filepath: str): # check file existence if not self.filelist: - raise IOError("No file was found.") + raise OSError("No file was found.") # open lsda buffer self.lsda = Lsda(self.filelist, "r") self.lsda_root = self.lsda.root - def read(self, *path) -> Union[List[str], str, np.ndarray]: + def read(self, *path) -> Union[list[str], str, np.ndarray]: """Read all data from Binout (top to low level) Parameters diff --git a/src/lasso/dyna/d3plot.py b/src/lasso/dyna/d3plot.py index cc59317..4eb67d2 100644 --- a/src/lasso/dyna/d3plot.py +++ b/src/lasso/dyna/d3plot.py @@ -10,7 +10,8 @@ import traceback import typing import webbrowser -from typing import Any, BinaryIO, Dict, Iterable, List, Set, Tuple, Union +from typing import Any, BinaryIO, Union +from collections.abc import Iterable import numpy as np @@ -30,7 +31,7 @@ LOGGER = get_logger(__name__) -def _check_ndim(d3plot, array_dim_names: Dict[str, List[str]]): +def _check_ndim(d3plot, array_dim_names: dict[str, list[str]]): """Checks if the specified array is fine in terms of ndim Parameters @@ -50,7 +51,7 @@ def _check_ndim(d3plot, array_dim_names: Dict[str, List[str]]): def _check_array_occurrence( - d3plot, array_names: List[str], required_array_names: List[str] + d3plot, array_names: list[str], required_array_names: list[str] ) -> bool: """Check if an array exists, if all depending on it exist too @@ -80,7 +81,7 @@ def _check_array_occurrence( return False -def _negative_to_positive_state_indexes(indexes: Set[int], n_entries) -> Set[int]: +def _negative_to_positive_state_indexes(indexes: set[int], n_entries) -> set[int]: """Convert negative indexes of an iterable to positive ones Parameters @@ -96,7 +97,7 @@ def _negative_to_positive_state_indexes(indexes: Set[int], n_entries) -> Set[int the positive indexes """ - new_entries: Set[int] = set() + new_entries: set[int] = set() for _, index in enumerate(indexes): new_index = index + n_entries if index < 0 else index if new_index >= n_entries: @@ -1171,8 +1172,8 @@ def pack(self, value: Any, size=None, dtype_hint=None) -> bytes: raise RuntimeError(msg, type(value), value) def count_array_state_var( - self, array_type: str, dimension_names: List[str], has_layers: bool, n_layers: int = 0 - ) -> Tuple[int, int]: + self, array_type: str, dimension_names: list[str], has_layers: bool, n_layers: int = 0 + ) -> tuple[int, int]: """This functions checks and updates the variable count for certain types of arrays Parameters @@ -1432,8 +1433,8 @@ def __init__( filepath: str = None, use_femzip: Union[bool, None] = None, n_files_to_load_at_once: Union[int, None] = None, - state_array_filter: Union[List[str], None] = None, - state_filter: Union[None, Set[int]] = None, + state_array_filter: Union[list[str], None] = None, + state_filter: Union[None, set[int]] = None, buffered_reading: bool = False, ): """Constructor for a D3plot @@ -1744,7 +1745,7 @@ def _n_rigid_walls(self) -> int: # pylint: disable = unused-argument, too-many-locals def _read_d3plot_file_generator( - self, buffered_reading: bool, state_filter: Union[None, Set[int]] + self, buffered_reading: bool, state_filter: Union[None, set[int]] ) -> typing.Any: """Generator function for reading bare d3plot files @@ -1782,7 +1783,7 @@ def _read_d3plot_file_generator( # if using buffered reading, we load one state at a time # into memory if buffered_reading: - file_infos_tmp: List[MemoryInfo] = [] + file_infos_tmp: list[MemoryInfo] = [] n_previous_states = 0 for minfo in file_infos: for i_file_state in range(minfo.n_states): @@ -1818,7 +1819,7 @@ def _read_d3plot_file_generator( yield buffer, n_states def _read_femzip_file_generator( - self, buffered_reading: bool, state_filter: Union[None, Set[int]] + self, buffered_reading: bool, state_filter: Union[None, set[int]] ) -> typing.Any: """Generator function for reading femzipped d3plot files @@ -1845,7 +1846,7 @@ def _read_femzip_file_generator( n_timesteps: int = buffer_info.n_timesteps # convert negative filter indexes - state_filter_parsed: Set[int] = set() + state_filter_parsed: set[int] = set() if state_filter is not None: state_filter_parsed = _negative_to_positive_state_indexes(state_filter, n_timesteps) n_states_to_load = len(state_filter) @@ -2657,7 +2658,7 @@ def _read_rigid_body_description(self): info = self._rigid_body_info info.n_rigid_bodies = rigid_body_description_header["nrigid"] - rigid_bodies: List[RigidBodyMetadata] = [] + rigid_bodies: list[RigidBodyMetadata] = [] for _ in range(info.n_rigid_bodies): rigid_body_info = { # rigid body part internal number @@ -5661,7 +5662,7 @@ def _read_states_rigid_body_motion( return var_index - def _collect_file_infos(self, size_per_state: int) -> List[MemoryInfo]: + def _collect_file_infos(self, size_per_state: int) -> list[MemoryInfo]: """This routine collects the memory and file info for the d3plot files Parameters @@ -5828,8 +5829,8 @@ def _collect_file_infos(self, size_per_state: int) -> List[MemoryInfo]: @staticmethod def _read_file_from_memory_info( - memory_infos: Union[MemoryInfo, List[MemoryInfo]], - ) -> Tuple[BinaryBuffer, int]: + memory_infos: Union[MemoryInfo, list[MemoryInfo]], + ) -> tuple[BinaryBuffer, int]: """Read files from a single or multiple memory infos Parameters @@ -6051,7 +6052,7 @@ def plot( i_timestep: int = 0, field: Union[np.ndarray, None] = None, is_element_field: bool = True, - fringe_limits: Union[Tuple[float, float], None] = None, + fringe_limits: Union[tuple[float, float], None] = None, export_filepath: str = "", ): """Plot the d3plot geometry @@ -7604,7 +7605,7 @@ def _write_states_globals( n_parts = settings.header["nmmat"] - def _write_part_field(array_type: str, default_shape: Union[int, Tuple], dtype: np.dtype): + def _write_part_field(array_type: str, default_shape: Union[int, tuple], dtype: np.dtype): array = ( self.arrays[array_type][i_timestep] if array_type in self.arrays @@ -9354,7 +9355,7 @@ def _write_states_rigid_bodies( return n_bytes_written def check_array_dims( - self, array_dimensions: Dict[str, int], dimension_name: str, dimension_size: int = -1 + self, array_dimensions: dict[str, int], dimension_name: str, dimension_size: int = -1 ): """This function checks if multiple arrays share an array dimensions with the same size. diff --git a/src/lasso/dyna/d3plot_header.py b/src/lasso/dyna/d3plot_header.py index 6b62414..b7334bc 100644 --- a/src/lasso/dyna/d3plot_header.py +++ b/src/lasso/dyna/d3plot_header.py @@ -1,5 +1,5 @@ import enum -from typing import Any, Dict, Tuple, Union +from typing import Any, Union import numpy as np import rich @@ -317,7 +317,7 @@ class D3plotHeader: itype: np.dtype = np.int32 ftype: np.dtype = np.float32 wordsize: int = 4 - raw_header: Dict[str, Any] = {} + raw_header: dict[str, Any] = {} external_numbers_dtype = np.int32 n_header_bytes: int = 0 @@ -345,7 +345,7 @@ class D3plotHeader: quadratic_elems_has_full_connectivity: bool = False quadratic_elems_has_data_at_integration_points: bool = False n_post_branches: int = 0 - n_types: Tuple[int, ...] = () + n_types: tuple[int, ...] = () # parts n_parts: int = 0 @@ -1099,7 +1099,7 @@ def read_words(self, bb: BinaryBuffer, words_to_read: dict, storage_dict: dict = @staticmethod def _determine_file_settings( bb: Union[BinaryBuffer, None] = None, - ) -> Tuple[int, Union[np.int32, np.int64], Union[np.float32, np.float64]]: + ) -> tuple[int, Union[np.int32, np.int64], Union[np.float32, np.float64]]: """Determine the precision of the file Parameters @@ -1169,7 +1169,7 @@ def _determine_file_settings( return word_size, itype, ftype - def compare(self, other: "D3plotHeader") -> Dict[str, Tuple[Any, Any]]: + def compare(self, other: "D3plotHeader") -> dict[str, tuple[Any, Any]]: """Compare two headers and get the differences Parameters diff --git a/src/lasso/dyna/femzip_mapper.py b/src/lasso/dyna/femzip_mapper.py index 2324385..0e858d8 100644 --- a/src/lasso/dyna/femzip_mapper.py +++ b/src/lasso/dyna/femzip_mapper.py @@ -1,7 +1,7 @@ import logging import re import traceback -from typing import Dict, List, Set, Tuple, Union +from typing import Union import numpy as np from lasso.dyna.array_type import ArrayType @@ -9,8 +9,8 @@ from lasso.femzip.fz_config import FemzipArrayType, FemzipVariableCategory, get_last_int_of_line -TRANSL_FEMZIP_ARRATYPE_TO_D3PLOT_ARRAYTYPE: Dict[ - Tuple[FemzipArrayType, FemzipVariableCategory], Set[str] +TRANSL_FEMZIP_ARRATYPE_TO_D3PLOT_ARRAYTYPE: dict[ + tuple[FemzipArrayType, FemzipVariableCategory], set[str] ] = { # GLOBAL (FemzipArrayType.GLOBAL_DATA, FemzipVariableCategory.GLOBAL): { @@ -336,8 +336,8 @@ def femzip_to_d3plot( - result_arrays: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray], -) -> Dict[str, np.ndarray]: + result_arrays: dict[tuple[int, str, FemzipVariableCategory], np.ndarray], +) -> dict[str, np.ndarray]: """Map femzip arrays to d3plot arrays Parameters @@ -407,7 +407,7 @@ def set_n_timesteps(self, n_timesteps: Union[int, None]) -> None: """ self._set_attr("n_timesteps", n_timesteps) - def to_shape(self) -> Tuple[int, ...]: + def to_shape(self) -> tuple[int, ...]: """Set the number of variables Returns @@ -437,14 +437,14 @@ class D3plotArrayMapping: just_assign: bool = False - def to_slice(self) -> Tuple[Union[int, slice], ...]: + def to_slice(self) -> tuple[Union[int, slice], ...]: """Get the slices mapping a femzip array to a d3plot array Returns ------- slices: Tuple[Union[int, slice], ...] """ - slices: List[Union[slice, int]] = [slice(None), slice(None)] + slices: list[Union[slice, int]] = [slice(None), slice(None)] if self.d3_layer_slice is not None: slices.append(self.d3_layer_slice) if self.d3_var_slice is not None: @@ -467,7 +467,7 @@ class FemzipArrayInfo: i_layer: Union[int, None] = None i_var: Union[int, None] = None - mappings: List[D3plotArrayMapping] + mappings: list[D3plotArrayMapping] def __init__(self): self.mappings = [] @@ -491,13 +491,13 @@ class FemzipMapper: FORTRAN_OFFSET: int = 1 - _d3plot_arrays: Dict[str, np.ndarray] = {} + _d3plot_arrays: dict[str, np.ndarray] = {} _fz_array_slices = {} def __init__(self): pass - def map(self, result_arrays: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray]): + def map(self, result_arrays: dict[tuple[int, str, FemzipVariableCategory], np.ndarray]): """Map femzip data to d3plot arrays. Parameters @@ -521,8 +521,8 @@ def map(self, result_arrays: Dict[Tuple[int, str, FemzipVariableCategory], np.nd self._map_arrays(array_infos, self._d3plot_arrays) def _convert( - self, result_arrays: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray] - ) -> List[FemzipArrayInfo]: + self, result_arrays: dict[tuple[int, str, FemzipVariableCategory], np.ndarray] + ) -> list[FemzipArrayInfo]: """Convert femzip result arrays into array infos Parameters @@ -558,7 +558,7 @@ def _convert( return array_infos @staticmethod - def _build(fz_arrays: List[FemzipArrayInfo]) -> Dict[str, Tuple[int, ...]]: + def _build(fz_arrays: list[FemzipArrayInfo]) -> dict[str, tuple[int, ...]]: """Counts the occurrence of all variables in the result array such as the number of layers and stresses. @@ -577,8 +577,8 @@ def _build(fz_arrays: List[FemzipArrayInfo]) -> Dict[str, Tuple[int, ...]]: Some variables only have partial stress results written for Sigma-x and Sigma-y and layers one to three for example. """ - shape_infos: Dict[str, ArrayShapeInfo] = {} - name_count: Dict[Tuple[str, FemzipVariableCategory], int] = {} + shape_infos: dict[str, ArrayShapeInfo] = {} + name_count: dict[tuple[str, FemzipVariableCategory], int] = {} for arr_info in fz_arrays: # print(arr_info) @@ -661,7 +661,7 @@ def _build(fz_arrays: List[FemzipArrayInfo]) -> Dict[str, Tuple[int, ...]]: return {name: info.to_shape() for name, info in shape_infos.items()} - def _map_arrays(self, array_infos: List[FemzipArrayInfo], d3plot_arrays: Dict[str, np.ndarray]): + def _map_arrays(self, array_infos: list[FemzipArrayInfo], d3plot_arrays: dict[str, np.ndarray]): """Allocate a femzip variable to its correct position in the d3plot array dictionary. @@ -699,8 +699,8 @@ def _map_arrays(self, array_infos: List[FemzipArrayInfo], d3plot_arrays: Dict[st d3plot_array[slices] = arr_info.array def _allocate_d3plot_arrays( - self, array_shapes: Dict[str, Tuple[int, ...]] - ) -> Dict[str, np.ndarray]: + self, array_shapes: dict[str, tuple[int, ...]] + ) -> dict[str, np.ndarray]: """Initialize all the d3plot arrays. Parameters @@ -725,7 +725,7 @@ def d3plot_arrays(self): def _parse_femzip_name( self, fz_name: str, var_type: FemzipVariableCategory - ) -> Tuple[str, Union[int, None], Union[int, None], Union[int, None]]: + ) -> tuple[str, Union[int, None], Union[int, None], Union[int, None]]: """Parses the femzip variable names. Parameters @@ -789,7 +789,7 @@ def _parse_femzip_name( def filter_femzip_variables( - file_metadata: FemzipFileMetadata, d3plot_array_filter: Union[Set[str], None] + file_metadata: FemzipFileMetadata, d3plot_array_filter: Union[set[str], None] ) -> FemzipFileMetadata: """Filters variable infos regarding d3plot array types @@ -809,7 +809,7 @@ def filter_femzip_variables( # pylint: disable = too-many-locals # find out which arrays we need and - vars_to_copy: List[int] = [] + vars_to_copy: list[int] = [] for i_var in range(file_metadata.number_of_variables): try: diff --git a/src/lasso/dyna/lsda_py3.py b/src/lasso/dyna/lsda_py3.py index 9870172..3f2b811 100644 --- a/src/lasso/dyna/lsda_py3.py +++ b/src/lasso/dyna/lsda_py3.py @@ -140,7 +140,7 @@ def writedata(self, sym, data): self.fp.write(struct.pack(self.lcunpack, length, Lsda.DATA)) self.fp.write(struct.pack("bb", sym.type, nlen) + bytes(sym.name, "utf-8")) # fmt=self.ordercode+self.packtype[sym.type]*sym.length - fmt = "%c%d%c" % (self.ordercode, sym.length, self.packtype[sym.type]) + fmt = f"{self.ordercode}{sym.length}{self.packtype[sym.type]}" self.fp.write(struct.pack(fmt, *data)) sym.file = self @@ -239,7 +239,7 @@ def lread(self, start=0, end=2000000000): self.file.ateof = 0 # format = self.file.ordercode + _Diskfile.packtype[self.type]*(end-start) # return struct.unpack(format,self.file.fp.read(size*(end-start))) - format = "%c%d%c" % (self.file.ordercode, (end - start), _Diskfile.packtype[self.type]) + format = f"{(self.file.ordercode)}{end - start}{_Diskfile.packtype[self.type]}" if self.type == Lsda.LINK: return struct.unpack(format, self.file.fp.read(size * (end - start)))[0] else: @@ -622,7 +622,7 @@ def nextfile(self): # Open next file in sequence newname = parts[0] + "%001" else: ret = int(parts[1]) + 1 - newname = "%s%%%3.3d" % (parts[0], ret) + newname = f"{parts[0]}%{ret:03d}" if self.mode == "w": self.fw = _Diskfile(newname, "w") else: @@ -639,5 +639,5 @@ def nextfile(self): # Open next file in sequence s = struct.pack(a, x) if len(s) != b: print("LSDA: initialization error") - print("Data type %s has length %d instead of %d" % (a, len(s), b)) + print(f"Data type {a} has length {len(s)} instead of {b}") types_ok = 0 diff --git a/src/lasso/femzip/femzip_api.py b/src/lasso/femzip/femzip_api.py index f955826..1b3a2d9 100644 --- a/src/lasso/femzip/femzip_api.py +++ b/src/lasso/femzip/femzip_api.py @@ -18,7 +18,7 @@ c_uint64, sizeof, ) -from typing import Any, Dict, List, Set, Tuple, Union +from typing import Any, Union import numpy as np @@ -355,7 +355,7 @@ def api(self) -> CDLL: return self._api @staticmethod - def _parse_state_filter(state_filter: Union[Set[int], None], n_timesteps: int) -> Set[int]: + def _parse_state_filter(state_filter: Union[set[int], None], n_timesteps: int) -> set[int]: # convert negative indexes state_filter_parsed = ( {entry if entry >= 0 else entry + n_timesteps for entry in state_filter} @@ -394,7 +394,7 @@ def _check_femzip_error(err: FemzipError) -> None: raise FemzipException(err_msg.format(err.ier, fz_error_msg)) @staticmethod - def struct_to_dict(struct: Structure) -> Dict[str, Any]: + def struct_to_dict(struct: Structure) -> dict[str, Any]: """Converts a ctypes struct into a dict Parameters @@ -481,7 +481,7 @@ def get_part_titles( return memoryview(buffer).cast("B") def read_state_deletion_info( - self, buffer_info: FemzipBufferInfo, state_filter: Union[Set[int], None] = None + self, buffer_info: FemzipBufferInfo, state_filter: Union[set[int], None] = None ) -> np.ndarray: """Get information which elements are alive @@ -824,7 +824,7 @@ def read_states( self, filepath: str, buffer_info: Union[FemzipBufferInfo, None] = None, - state_filter: Union[Set[int], None] = None, + state_filter: Union[set[int], None] = None, ) -> np.ndarray: """Reads all femzip state information @@ -945,7 +945,7 @@ def _get_variables_state_buffer_size( # pylint: disable=too-many-statements buffer_size_state = 0 - var_indexes_to_remove: Set[int] = set() + var_indexes_to_remove: set[int] = set() for i_var in range(file_metadata.number_of_variables): var_info = file_metadata.variable_infos[i_var] variable_name = var_info.name.decode("utf-8") @@ -1023,14 +1023,14 @@ def _decompose_read_variables_array( all_vars_array: np.ndarray, n_timesteps_read: int, file_metadata: FemzipFileMetadata, - ) -> Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray]: + ) -> dict[tuple[int, str, FemzipVariableCategory], np.ndarray]: # pylint: disable=too-many-arguments # pylint: disable=too-many-locals # pylint: disable=too-many-branches # pylint: disable=too-many-statements # decompose array - result_arrays: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray] = {} + result_arrays: dict[tuple[int, str, FemzipVariableCategory], np.ndarray] = {} var_pos = 0 for i_var in range(file_metadata.number_of_variables): var_info: VariableInfo = file_metadata.variable_infos[i_var] @@ -1139,8 +1139,8 @@ def read_variables( n_rigid_wall_vars: int, n_airbag_particles: int, n_airbags: int, - state_filter: Union[Set[int], None] = None, - ) -> Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray]: + state_filter: Union[set[int], None] = None, + ) -> dict[tuple[int, str, FemzipVariableCategory], np.ndarray]: """Read specific variables from Femzip Parameters @@ -1291,12 +1291,12 @@ class FemzipD3plotArrayMapping: i_integration_point: Union[int, None] i_var_index: Union[int, None] - fz_array_slices = Tuple[slice] + fz_array_slices = tuple[slice] def __init__( self, d3plot_array_type: str, - fz_array_slices: Tuple[slice] = (slice(None),), + fz_array_slices: tuple[slice] = (slice(None),), i_integration_point: Union[int, None] = None, i_var_index: Union[int, None] = None, ): @@ -1311,7 +1311,7 @@ class FemzipArrayMetadata: array_type: FemzipArrayType category: FemzipVariableCategory - d3plot_mappings: List[FemzipD3plotArrayMapping] + d3plot_mappings: list[FemzipD3plotArrayMapping] # set when parsed fz_var_index: Union[int, None] = None @@ -1319,7 +1319,7 @@ def __init__( self, array_type: FemzipArrayType, category: FemzipVariableCategory, - d3plot_mappings: List[FemzipD3plotArrayMapping], + d3plot_mappings: list[FemzipD3plotArrayMapping], ): self.array_type = array_type self.category = category diff --git a/src/lasso/femzip/fz_config.py b/src/lasso/femzip/fz_config.py index 7dd9a71..d565e11 100644 --- a/src/lasso/femzip/fz_config.py +++ b/src/lasso/femzip/fz_config.py @@ -1,9 +1,9 @@ -from typing import Dict, Union, Tuple +from typing import Union import enum -def get_last_int_of_line(line: str) -> Tuple[str, Union[None, int]]: +def get_last_int_of_line(line: str) -> tuple[str, Union[None, int]]: """Searches an integer in the line Parameters @@ -117,7 +117,7 @@ def from_int(number: int) -> "FemzipVariableCategory": return FEMZIP_CATEGORY_TRANSL_DICT[number] -FEMZIP_CATEGORY_TRANSL_DICT: Dict[int, FemzipVariableCategory] = { +FEMZIP_CATEGORY_TRANSL_DICT: dict[int, FemzipVariableCategory] = { entry.value: entry for entry in FemzipVariableCategory.__members__.values() } diff --git a/src/lasso/io/binary_buffer.py b/src/lasso/io/binary_buffer.py index 9dfa185..1a12d68 100644 --- a/src/lasso/io/binary_buffer.py +++ b/src/lasso/io/binary_buffer.py @@ -1,6 +1,6 @@ import mmap import os -from typing import Any, List, Union +from typing import Any, Union import numpy as np @@ -225,7 +225,7 @@ def save(self, filepath: Union[str, None] = None): self.filepath_ = filepath_parsed - def load(self, filepath: Union[List[str], str, None] = None, n_bytes: int = 0): + def load(self, filepath: Union[list[str], str, None] = None, n_bytes: int = 0): """load a file Parameters diff --git a/src/lasso/io/files.py b/src/lasso/io/files.py index 1e112dd..3773848 100644 --- a/src/lasso/io/files.py +++ b/src/lasso/io/files.py @@ -2,7 +2,8 @@ import glob import os import typing -from typing import Iterator, List, Union +from typing import Union +from collections.abc import Iterator @contextlib.contextmanager @@ -37,7 +38,7 @@ def open_file_or_filepath( def collect_files( - dirpath: Union[str, List[str]], patterns: Union[str, List[str]], recursive: bool = False + dirpath: Union[str, list[str]], patterns: Union[str, list[str]], recursive: bool = False ): """Collect files from directories diff --git a/src/lasso/plotting/plot_shell_mesh.py b/src/lasso/plotting/plot_shell_mesh.py index 66ec7a7..3f71fe5 100644 --- a/src/lasso/plotting/plot_shell_mesh.py +++ b/src/lasso/plotting/plot_shell_mesh.py @@ -4,7 +4,7 @@ import json from base64 import b64encode from zipfile import ZipFile, ZIP_DEFLATED -from typing import Union, Tuple +from typing import Union import numpy as np @@ -21,7 +21,7 @@ def _read_file(filepath: str): file_content : str """ - with open(filepath, "r", encoding="utf-8") as fp_filepath: + with open(filepath, encoding="utf-8") as fp_filepath: return fp_filepath.read() @@ -30,7 +30,7 @@ def plot_shell_mesh( shell_node_indexes: np.ndarray, field: Union[np.ndarray, None] = None, is_element_field: bool = True, - fringe_limits: Union[Tuple[float, float], None] = None, + fringe_limits: Union[tuple[float, float], None] = None, ): """Plot a mesh @@ -190,23 +190,17 @@ def plot_shell_mesh( _html_jquery_js = script_string_js.format(jszip_jquery_format) # pylint: disable = consider-using-f-string - return """ + return f""" <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> - {_jquery_js} - {_jszip_js} - {_three_js} - {_chroma_js} + {_html_jquery_js} + {_html_jszip_js} + {_html_three_js} + {_html_chroma_js} </head> <body> {_html_div} </body> -</html>""".format( - _html_div=_html_div, - _jszip_js=_html_jszip_js, - _three_js=_html_three_js, - _chroma_js=_html_chroma_js, - _jquery_js=_html_jquery_js, - ) +</html>""" diff --git a/test/unit_tests/dimred/svd/test_clustering_betas.py b/test/unit_tests/dimred/svd/test_clustering_betas.py index 850fd87..32de5bc 100644 --- a/test/unit_tests/dimred/svd/test_clustering_betas.py +++ b/test/unit_tests/dimred/svd/test_clustering_betas.py @@ -9,7 +9,7 @@ def test_group_betas(self): """tests correct function of the group_betas function in clustering_betas.py""" - fake_names = np.array(["betas_{i}".format(i=i) for i in range(25)]) + fake_names = np.array([f"betas_{i}" for i in range(25)]) fake_cluster_0 = np.random.rand(12, 3) + 5 fake_cluster_1 = np.random.rand(12, 3) - 5 fake_betas = np.stack([*fake_cluster_0, *fake_cluster_1, np.array([0, 0, 0])]) diff --git a/test/unit_tests/dimred/svd/test_pod_functions.py b/test/unit_tests/dimred/svd/test_pod_functions.py index 5f0a544..d0e7779 100644 --- a/test/unit_tests/dimred/svd/test_pod_functions.py +++ b/test/unit_tests/dimred/svd/test_pod_functions.py @@ -1,7 +1,6 @@ from unittest import TestCase from lasso.dimred.svd.pod_functions import calculate_v_and_betas import numpy as np -from typing import Tuple class PodFunctionsTest(TestCase): @@ -25,7 +24,7 @@ def test_calculate_v_and_betas(self): result = calculate_v_and_betas(rand_samples) # returns Tuple containing v_rob and betas - self.assertTrue(isinstance(result, Tuple)) + self.assertTrue(isinstance(result, tuple)) v_rob, betas = result diff --git a/test/unit_tests/dimred/svd/test_subsampling_methods.py b/test/unit_tests/dimred/svd/test_subsampling_methods.py index cf100ee..9307925 100644 --- a/test/unit_tests/dimred/svd/test_subsampling_methods.py +++ b/test/unit_tests/dimred/svd/test_subsampling_methods.py @@ -1,6 +1,5 @@ import os import tempfile -from typing import Tuple from unittest import TestCase import numpy as np @@ -21,7 +20,7 @@ def test_create_reference_sample(self): result = create_reference_subsample(load_path, parts=[], nr_samples=n_nodes) # result should be tuple containing subsample, load time and total process time - self.assertTrue(isinstance(result, Tuple)) + self.assertTrue(isinstance(result, tuple)) ref_sample, t_total, t_load = result @@ -68,7 +67,7 @@ def test_remap_random_subsample(self): # sub_result should be Tuple containing subsample, total process time, # and plot load time - self.assertTrue(isinstance(sub_result, Tuple)) + self.assertTrue(isinstance(sub_result, tuple)) subsample, t_total, t_load = sub_result diff --git a/test/unit_tests/dyna/test_d3plot.py b/test/unit_tests/dyna/test_d3plot.py index 2cd1ba9..713965b 100644 --- a/test/unit_tests/dyna/test_d3plot.py +++ b/test/unit_tests/dyna/test_d3plot.py @@ -154,7 +154,7 @@ def test_header(self): header = d3plot.header for name, value in test_header_data.items(): - self.assertEqual(header.raw_header[name], value, "Invalid var %s" % name) + self.assertEqual(header.raw_header[name], value, f"Invalid var {name}") def test_beam_integration_points(self): self.maxDiff = None @@ -173,14 +173,10 @@ def test_beam_integration_points(self): for array_name, minmax in maxmin_test_values.items(): array = d3plot.arrays[array_name] self.assertAlmostEqual( - array.min(), - minmax[0], - msg="{0}: {1} != {2}".format(array_name, array.min(), minmax[0]), + array.min(), minmax[0], msg=f"{array_name}: {array.min()} != {minmax[0]}" ) self.assertAlmostEqual( - array.max(), - minmax[1], - msg="{0}: {1} != {2}".format(array_name, array.max(), minmax[1]), + array.max(), minmax[1], msg=f"{array_name}: {array.max()} != {minmax[1]}" ) def test_correct_sort_of_more_than_100_state_files(self): diff --git a/test/unit_tests/dyna/test_mapper.py b/test/unit_tests/dyna/test_mapper.py index 1b59266..2cdd3eb 100644 --- a/test/unit_tests/dyna/test_mapper.py +++ b/test/unit_tests/dyna/test_mapper.py @@ -1,4 +1,4 @@ -from typing import Dict, Set, Tuple, Union +from typing import Union from unittest import TestCase import numpy as np @@ -7,7 +7,7 @@ from lasso.dyna.array_type import ArrayType from lasso.dyna.femzip_mapper import FemzipMapper -part_global_femzip_translations: Dict[Tuple[FemzipArrayType, FemzipVariableCategory], Set[str]] = { +part_global_femzip_translations: dict[tuple[FemzipArrayType, FemzipVariableCategory], set[str]] = { # GLOBAL (FemzipArrayType.GLOBAL_DATA, FemzipVariableCategory.GLOBAL): { # ArrayType.global_timesteps, @@ -26,7 +26,7 @@ }, } -element_nope_femzip_translations: Dict[Tuple[str, FemzipVariableCategory], str] = { +element_nope_femzip_translations: dict[tuple[str, FemzipVariableCategory], str] = { # NODE ( FemzipArrayType.NODE_DISPLACEMENT.value, @@ -254,7 +254,7 @@ class MapperTest(TestCase): def validate( self, - fz: Dict[Tuple[str, FemzipVariableCategory], np.ndarray], + fz: dict[tuple[str, FemzipVariableCategory], np.ndarray], d3plot_shape: tuple, data_index_positions: Union[tuple, slice] = slice(None), ): @@ -334,7 +334,7 @@ def test_dependent_variable(self): d1 = np.random.randn(2, 1200) d2 = np.random.randn(2, 1200) - fz: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray] = { + fz: dict[tuple[int, str, FemzipVariableCategory], np.ndarray] = { (1, "element_dependent_variable_2", FemzipVariableCategory.SHELL): d2, (2, "element_dependent_variable_1", FemzipVariableCategory.SHELL): d1, } @@ -355,7 +355,7 @@ def test_effective_p_strain(self): d2 = np.random.randn(2, 20000) d3 = np.random.randn(2, 20000) - fz: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray] = { + fz: dict[tuple[int, str, FemzipVariableCategory], np.ndarray] = { (1, "Effective plastic strain ( 1)", FemzipVariableCategory.SHELL): d1, (2, "Effective plastic strain ( 2)", FemzipVariableCategory.SHELL): d2, (3, "Effective plastic strain ( 3)", FemzipVariableCategory.SHELL): d3, @@ -390,7 +390,7 @@ def test_others(self): history_vars1 = np.random.randn(3, 2) history_vars2 = np.random.randn(3, 2) - fz: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray] = { + fz: dict[tuple[int, str, FemzipVariableCategory], np.ndarray] = { # stress (1, "Sigma-x (IP 6)", FemzipVariableCategory.SOLID): stress_1, (2, "Sigma-y (IP 3)", FemzipVariableCategory.SOLID): stress_2, @@ -439,7 +439,7 @@ def test_beam(self): bending = np.random.randn(3, 123) torsion = np.random.rand(2, 5) - fz: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray] = { + fz: dict[tuple[int, str, FemzipVariableCategory], np.ndarray] = { (1, "axial_force", FemzipVariableCategory.BEAM): axial_force, (2, "s_shear_resultant", FemzipVariableCategory.BEAM): shear, (3, "t_bending_moment", FemzipVariableCategory.BEAM): bending,