Coverage for bim2sim/elements/mapping/condition.py: 57%

87 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-03-12 17:09 +0000

1"""Module for validating an element by a condition""" 

2import logging 

3 

4from bim2sim.elements.mapping.units import ureg 

5 

6 

7class Condition: 

8 """Class for validating an element by a condition""" 

9 

10 _logger = None 

11 

12 def __init__(self, name, critical_for_creation=True): 

13 self.name = name 

14 self.critical_for_creation = critical_for_creation 

15 

16 @property 

17 def logger(self): 

18 """logger instance""" 

19 if not Condition._logger: 

20 Condition._logger = logging.getLogger(__name__) 

21 return Condition._logger 

22 

23 def check(self, element, value): 

24 pass 

25 

26 

27class RangeCondition(Condition): 

28 """"Validate through a simple ValueRange 

29 

30 Args: 

31 key: attribute of the element to validate 

32 value_min: minimum allowed value 

33 value_max: maximum allowed value 

34 incl_edges: if True, the value_min and value_max are valid as well 

35 critical_for_creation: if True, the element will not be created if the 

36 validation fails 

37 Return: 

38 True if valid, False if not valid 

39 """ 

40 

41 def __init__(self, key: str, value_min, value_max, incl_edges: bool = False, 

42 critical_for_creation: bool = True): 

43 super().__init__(key, critical_for_creation) 

44 self.key = key 

45 self.valueMin = value_min 

46 self.valueMax = value_max 

47 self.incl_edges = incl_edges 

48 self.critical_for_creation = critical_for_creation 

49 

50 def check(self, element, value): 

51 if value is None: 

52 return False 

53 if not isinstance(value, (list, set)): 

54 value = [value] 

55 check_list = [] 

56 for v in value: 

57 if self.incl_edges: 

58 check_list.append(False if not v or v <= self.valueMin 

59 or v >= self.valueMax else True) 

60 else: 

61 check_list.append(False if not v or v < self.valueMin 

62 or v > self.valueMax else True) 

63 return all(check_list) 

64 

65 

66class ListCondition(Condition): 

67 """Validate if a list has elements, or a specific number of elements 

68 

69 Args: 

70 key: attribute of the element to validate 

71 values: list of allowed values 

72 critical_for_creation: if True, the element will not be created if the 

73 validation fails 

74 Return: 

75 True if valid, False if not valid 

76 """ 

77 

78 def __init__(self, key: str, list_length: int = None, 

79 critical_for_creation: bool = True): 

80 super().__init__(key, critical_for_creation) 

81 self.key = key 

82 self.listLength = list_length 

83 self.critical_for_creation = critical_for_creation 

84 

85 def check(self, element, value): 

86 if type(value) is not list: 

87 return False 

88 if self.listLength is None: 

89 return True if len(value) > 0 else False 

90 else: 

91 return True if len(value) == self.listLength else False 

92 

93 

94class ThicknessCondition(Condition): 

95 def __init__(self, key: str, 

96 threshold: ureg.Quantity = 0, 

97 critical_for_creation: bool = True): 

98 super().__init__(key, critical_for_creation) 

99 self.key = key 

100 self.threshold = threshold 

101 self.critical_for_creation = critical_for_creation 

102 

103 def check(self, element, value): 

104 if value is None: 

105 return False 

106 value_from_layers = sum(layer.thickness for layer in element.layers) 

107 if not value_from_layers: 

108 return False 

109 if not self.threshold: 

110 return True if value == value_from_layers else False 

111 discrepancy = abs(value - value_from_layers) / value 

112 return True if discrepancy <= self.threshold else False 

113 

114 

115class UValueCondition(Condition): 

116 def __init__(self, key: str, 

117 threshold: ureg.Quantity = 0, 

118 critical_for_creation: bool = True): 

119 super().__init__(key, critical_for_creation) 

120 self.key = key 

121 self.threshold = threshold 

122 self.critical_for_creation = critical_for_creation 

123 

124 def check(self, element, value): 

125 if value is None: 

126 return False 

127 value_from_layers = self.get_u_value_from_layers(element.layerset) 

128 if not value_from_layers: 

129 return False 

130 if not self.threshold: 

131 return True if value == value_from_layers else False 

132 discrepancy = abs(value - value_from_layers) / value 

133 return True if discrepancy <= self.threshold else False 

134 

135 @staticmethod 

136 def get_u_value_from_layers(layer_set): 

137 layers_r = 0 

138 for layer in layer_set.layers: 

139 if layer.thickness: 

140 if layer.material.thermal_conduc and \ 

141 layer.material.thermal_conduc > 0: 

142 layers_r += layer.thickness / layer.material.thermal_conduc 

143 

144 if layers_r > 0: 

145 return 1 / layers_r 

146 return None