Skip to content
Snippets Groups Projects
Select Git revision
  • 0294e0bf97147c69f8ef9da7b9f63c83a34d27c6
  • main default protected
  • fix/build_instructions_from_unicado_package
  • feature/how_to_design
  • fix/missing-API-documentation-for-python-modules
  • fix/delete_mingw
  • feature/new_systems_methodology
  • fix/missing-api-documentation
  • feature/python_example_folder_update
  • beta_release protected
  • fix/revert-gitlab-config
  • fix/citationEcologicalAssessment
  • documentation/styleupdate
  • feature/lightMode
  • documentation/create_mission_xml
  • 28-empennage-design-update-documentation-according-to-workshop
  • documentation/fix-dot-equations
  • documentation/propulsion-design-module
  • documentation/gitlab-workflow
  • documentation/cost_estimation_update
  • documentation/mkdocs_python_update
  • 0.5.0
22 results

cost_estimation.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    utilities.py 8.95 KiB
    #!/usr/bin/env python3
    # -*- coding: UTF-8 -*-
    """
    This module contains usefule utilities for many
    different python scripts
    """
    from __future__ import print_function
    
    import re
    from functools import wraps
    from subprocess import Popen, PIPE
    from sys import __stdout__
    from os import mkdir
    from os.path import dirname, exists
    from typing import (
        Iterable, Optional, List, Callable, TypeVar, Union, Any, Tuple)
    from pathlib import Path
    from collections import OrderedDict
    
    from urllib3.exceptions import MaxRetryError
    from python_translator import Translator
    
    
    def running_average(X: List[float], n: int) -> List[float]:
        """creates a running average of X with n entries in both dircetions"""
        X_new = []
        for i in range(n):
            X_new += [sum(X[0: i + 1]) / (i + 1)]
        for i in range(n, len(X) - n):
            X_new += [sum(X[i - n: i + n + 1]) / (2 * n + 1)]
        for i in range(len(X) - n, len(X)):
            X_new += [sum(X[2 * i - len(X) + 1:]) / ((len(X) - (i + 1)) * 2 + 1)]
        return X_new
    
    
    def quality_of_fit(X: List[float], Y: List[float]) -> float:
        """calculates the quality of a fit 'bestimmtheitsmass'"""
        mean_x = sum(X) / len(X)
        return sum(x ** 2 - mean_x ** 2 for x in X)\
            / sum(x ** 2 - mean_x ** 2 for x in Y)
    
    
    Return = TypeVar("Return")
    
    
    def print_redirect(f: Callable[..., Return]) -> Callable[..., Return]:
        """
        wraps print to print to both stdout and __stdout__
        the reason for doing that is that abaqus replaces
        stdout and prints everything to abaqus
        this way everything can be seen both in the command line and in abaqus
        """
    
        @wraps(f)
        def inner_function(*args: Any, **argv: Any) -> Return:
            f(*args, **argv)
            for i, arg in enumerate(args):
                if isinstance(type, arg):
                    del arg[i]
            for _, val in argv.items():
                if isinstance(type, val):
                    del val
            argv["file"] = __stdout__
            f(*args, **argv)
            try:
                return f(*args, **argv)
            except TypeError:
                print("The argument 'file' is twice in a print statement")
                raise
    
        return inner_function
    
    
    def filter_function(x: str) -> bool:
        """filter function in order to remove unused
        arguments from this script before parsing"""
        if ":" in x or "rwth" in x:
            return False
        analysed_item = x.replace("--", ".")
        analysed_item = analysed_item.replace("-", "!")
        if len(analysed_item) > 2\
                and "." not in analysed_item\
                and "!" in analysed_item:
            return False
        return True
    
    
    def filter_argv(X: List[str]) -> List[str]:
        """removes unessecery entries from
        argv which have been generated by abaqus"""
        Y: List[str] = list(X)
        for i, x in enumerate(X):
            if not filter_function(x):
                del Y[i]
                if i < len(Y):
                    del Y[i + 1]
        return Y
    
    
    def dumb_plot(X: List[float], Y: List[float],
                  title: str = "title", log: bool = False) -> None:
        """plot X and Y using dumb gnuplot"""
        try:
            with Popen(["gnuplot"], stdin=PIPE) as gnuplot:
                assert gnuplot, """Gnuplot could not be started."""
                assert gnuplot.stdin, """Input to Gnuplot could not be found."""
                gnuplot.stdin.write(bytes("set term dumb 79 25\n", "utf-8"))
                if log:
                    gnuplot.stdin.write(bytes("set logscale xy\n", "utf-8"))
                gnuplot.stdin.write(
                    bytes(
                        f"""plot '-' using 1:2 title '{title}'
                        with linespoints \n""",
                        "utf-8"
                    )
                )
                for x, y in zip(X, Y):
                    gnuplot.stdin.write(bytes(f"{x} {y}\n", "utf-8"))
                gnuplot.stdin.write(bytes("e\n", "utf-8"))
                gnuplot.stdin.flush()
        except FileNotFoundError:
            print("There is no installed instance of gnuplot")
    
    
    def read_file(filename: Union[str, Path],
                  header: int = 0,
                  type_: type = float) -> Tuple[List[float], ...]:
        """read a file with given filename into
        a python-tuple. Skip n='header' lines in the beginning
        of the document"""
        # reads a given file and returns lists
        lists: List[List[float]] = []
        with open(filename, "r", encoding="utf-8") as input_file:
            for i, line in enumerate(input_file):
                if i < header:
                    continue
                lists += [[type_(v) for v in line.split()]]
        return tuple(list(v) for v in zip(*lists))
    
    
    def write_file(filename: Union[Path, str],
                   *args: Iterable[float],
                   title: Optional[str] = None) -> None:
        """write the rows given in 'arga' to a file"""
        # write data to a file
        if not any(args[0]):
            raise ValueError("Tried to write an empty row to a file.")
        if isinstance(filename, str):
            filename = Path(filename)
        with open(filename, "w", encoding="utf-8") as output_file:
            if title is not None:
                output_file.write(title + "\n")
            for row in zip(*args):
                output_file.write(" ".join(str(r) for r in row) + "\n")
    
    
    def mkdir_p(foldername: str) -> None:
        """creates a new folder if the folder does not exist"""
        try:
            if exists(foldername):
                return
            mkdir(foldername)
        except IOError as e:
            # recursive creation of needed folders
            if e.errno != 2:
                raise
            mkdir_p(dirname(foldername))
            mkdir_p(foldername)
    
    
    def trash_remover(func: Callable[..., Tuple[Return, ...]])\
            -> Callable[..., Return]:
        """only keeps the first output of a given function"""
    
        @wraps(func)
        def inner_function(*args: Any, **kwargs: Any) -> Return:
            result = func(*args, **kwargs)
            return result[0]
    
        return inner_function
    
    
    def use_translator(string: str, lang1: str, lang2: str) -> str:
        """
        Translate the given input string from lang2 to lang1 using google
        translate.
        """
        # one letter strings
        if len(string) <= 1:
            return string
    
        if r"\times" in string:
            return string
    
        try:
            translator = Translator()
            result: str
            result = translator.translate(string, lang1, lang2)
        except (OSError, MaxRetryError):
            return string
        return str(result)
    
    
    def translate(string: str, reverse: bool = False) -> str:
        """translates a string from english to german
        @input string any string wich contains specific english words
        @input reverse translate ger->en if set to true
        @return the german translation of the same string"""
    
        if r"$" in string or not string:
            return string
    
        if reverse:
            string = re.sub(r'(\d+),(\d+)', r'\1\.\2', string)
        else:
            string = re.sub(r'(\d+)\.(\d+)', r'\1,\2', string)
    
        _dict: dict[str, str] = OrderedDict({
            "leakage": "Leckage",
            "contact pressure": "Kontaktdruck",
            "fluid pressure": "Fluiddruck",
            "pressure": "Druck",
            "density": "Dichte",
            "roundness": "Rundheit",
            "eccentricity": r"Exzentrizit\"at",
            "contact area": r"Kontaktoberfl\"ache",
            "area": r"Fl\"ache",
            "maximal": "Maximale",
            "time": "Zeit",
            "normal-force": "Normalkraft",
            "normal force": "Normalkraft",
            "total force": "Gesamtkraft",
            "force": "Kraft",
            "distance": "Abstand",
            "position": "Position",
            "contact broadness": "Kontaktbreite",
            "broadness": "Breite",
            "contact": "Kontakt-",
            "seat": "Sitz",
            "ball": "Kugel",
            "high": "hoch",
            "low": "tief",
            "elastic": "elastisch",
            "plastic": "plastisch",
            "angle": "Winkel",
            "degree": "Grad",
            "deg": "Grad",
            "hard": "hart",
            "soft": "weich",
            "fit": "Fit",
            "data": "Messwerte",
            "velocity": "Geschwindigkeit",
            "measurement": "Messung",
            "experiment": "Experiment",
            "simulation": "Simulation",
            "analytical": "analytisch",
            "signal": "Signal",
            "valve control": "Ventilansteuerung",
            "off": "zu",
            "on": "auf",
            "status": "Zustand",
            "valve": "Ventil",
            "relative pressure": "Relativdruck",
            "absolute pressure": "Absolutdruck",
            "relative": "relativ",
            "absolute": "absolut",
            "plot": "Graph",
            "orifice": "Blende",
            "Hagen–Poiseuille": "Hagen-Poiseuille",
            "test": "Test"
        })
        if not reverse and r"\times" not in string:
            for key, value in _dict.items():
                if key in string.lower():
                    string = re.sub(
                        key, value, string,
                        flags=re.IGNORECASE)
                    break
            else:
                string = use_translator(string, "german", "english")
        else:
            for key, value in _dict.items():
                if value.lower() in string.lower():
                    string = string.lower().replace(value.lower(), key.lower())
                    break
            else:
                string = use_translator(string, "english", "german")
        return string