Coverage for ebcpy/modelica/__init__.py: 98%

65 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-09-19 12:21 +0000

1""" 

2This package aims to help manipulate simulation files (dsfinal.txt or dsin.txt) 

3or to load simulation result files (.mat) efficiently into a pandas.DataFrame 

4""" 

5import re 

6from typing import Union, List 

7 

8 

9def get_expressions(filepath_model: str, 

10 get_protected: bool = False, 

11 modelica_type: Union[str, List] = "parameters", 

12 excludes: List = None): 

13 """ 

14 This function extracts specific expressions out of modelica models. 

15 

16 :param str,os.path.normpath filepath_model: 

17 Full path of modelica model on the given os 

18 e.g. path_model = "C://MyLibrary//TestModel.mo" 

19 :param str,list modelica_type: 

20 Type you want to have matched. "parameters" and "variables" 

21 have a special regex pattern. 

22 For other models, you can parse a string like: 

23 "replaceable package Medium" and it will yield all 

24 afflicted lines. You can also give a list of strings if 

25 multiple strings are relevant to you. 

26 Special cases: 

27 parameters: 

28 - include: ["parameter"] 

29 - excludes: ["final", "in", "of", "replaceable"] 

30 variables: Note: The case for already imported SIUnits is not considered here. 

31 - include: ["Modelica.SIunits", "Real", "Boolean", "Integer"] 

32 - excludes: ["parameter", "import", "constant"] 

33 :param list excludes: 

34 List of strings to exclude from expression. Default is None. 

35 :param Boolean get_protected: 

36 Whether to extract protected parameters or not. Default is false 

37 

38 :return: list matches 

39 List with all lines matching the given expression. 

40 """ 

41 if excludes is None: 

42 excludes = [] 

43 if modelica_type == "parameters": 

44 _includes = ["parameter"] 

45 _excludes = ["final", "in", "of", "replaceable"] + excludes 

46 elif modelica_type == "variables": 

47 _includes = ["Modelica.SIunits", "Real", "Boolean", "Integer"] 

48 _excludes = ["parameter", "import", "constant"] + excludes 

49 else: 

50 _includes = [modelica_type] 

51 _excludes = excludes 

52 if _excludes: 

53 _exclude_str = r"(?<!" + r"\s)(?<!".join(_excludes) + r"\s)" 

54 else: # Case if list is empty 

55 _exclude_str = "" 

56 _pattern = r'((?:\s.+)?{}({})(.|\n)*?;)'.format(_exclude_str, 

57 "|".join(_includes)) 

58 

59 # Open the file 

60 with open(filepath_model, "r") as file: 

61 file.seek(0) 

62 script = file.read() 

63 

64 # Find desired expression in modelica script 

65 expr = re.findall(_pattern, script, re.MULTILINE) 

66 

67 expr_filtered = [" ".join(expr_unfiltered[0].split()) for expr_unfiltered in expr] 

68 

69 if not get_protected: 

70 return expr_filtered 

71 

72 # Get position of expressions 

73 pos_expr = [] 

74 for match in re.finditer(_pattern, script, re.MULTILINE): 

75 pos_expr.append(match.span()[0]) 

76 

77 # Check if parameter are protected 

78 expr_unprotected = [] 

79 expr_protected = [] 

80 

81 # Get position of "protected"-expression 

82 protected = re.search(r'protected', script) 

83 

84 if protected: 

85 pos_protected = protected.span()[0] 

86 for i, temp_expr in enumerate(expr): 

87 # If expressions is before 'proteceted' --> refer to expr_unprotected 

88 if pos_expr[i] < pos_protected: 

89 expr_unprotected.append(temp_expr) 

90 # If expressions is after 'proteceted' --> refer to expr_protected 

91 else: 

92 expr_protected.append(temp_expr) 

93 else: 

94 expr_unprotected = expr 

95 

96 return expr_unprotected, expr_protected 

97 

98 

99def get_names_and_values_of_lines(lines: List[str]) -> dict: 

100 """ 

101 All unnecessary code is deleted (annotations, doc). 

102 Only the name of the variable and the value is extracted. 

103 

104 :param List[str] lines: 

105 List of strings with lines from a modelica file. 

106 

107 :return: 

108 dict: Containing the names as key and values as value. 

109 

110 Example: 

111 

112 >>> lines = ['parameter Boolean my_boolean=true "Some description"', 

113 >>> 'parameter Real my_real=12.0 "Some description" annotation("Some annotation")'] 

114 >>> output = get_names_and_values_of_lines(lines=lines) 

115 >>> print(output) 

116 {'my_boolean': True, 'my_real': 12.0} 

117 """ 

118 res = {} 

119 for line in lines: 

120 line = line.replace(";", "") 

121 

122 # Check if line is a commented line and if so, skip the line: 

123 if line.startswith("//"): 

124 continue 

125 

126 # Remove part behind possible annotation: 

127 loc = line.find("annotation") 

128 if loc >= 0: 

129 line = line[:loc] 

130 # Remove possible brackets, like "param(min=0, start=5) 

131 line = re.sub(r'[\(\[].*?[\)\]]', '', line) 

132 # And now any quotes / doc / strings 

133 line = re.sub(r'".*"', '', line) 

134 # If a value is present (e.g. for parameters, one = sign is still present (always) 

135 if line.find("=") >= 0: 

136 name_str, val_str = line.split("=") 

137 name_str = name_str.strip() 

138 name = name_str.split(" ")[-1].replace(" ", "") 

139 val_str_stripped = val_str.replace(" ", "") 

140 if val_str_stripped in ["true", "false"]: 

141 value = val_str_stripped == "true" 

142 else: 

143 try: 

144 value = float(val_str_stripped) 

145 except ValueError: 

146 # Neither float, integer nor boolean, hence None 

147 value = None 

148 # else no value is stored in the line 

149 else: 

150 line = line.strip() 

151 name = line.split(" ")[-1].replace(" ", "") 

152 value = None 

153 res.update({name: value}) 

154 

155 return res