| Conditions | 9 |
| Total Lines | 138 |
| Code Lines | 93 |
| Lines | 52 |
| Ratio | 37.68 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | """ |
||
| 136 | def evaluate_df(self, df, ctx): |
||
| 137 | """ |
||
| 138 | Evaluate capacity comparison. |
||
| 139 | |||
| 140 | Parameters |
||
| 141 | ---------- |
||
| 142 | df : pd.DataFrame |
||
| 143 | DataFrame with output_capacity_mw and input_capacity_mw columns |
||
| 144 | ctx : dict |
||
| 145 | Context information |
||
| 146 | |||
| 147 | Returns |
||
| 148 | ------- |
||
| 149 | RuleResult |
||
| 150 | Validation result with success/failure status |
||
| 151 | """ |
||
| 152 | if df.empty: |
||
| 153 | return RuleResult( |
||
| 154 | rule_id=self.rule_id, |
||
| 155 | task=self.task, |
||
| 156 | table=self.table, |
||
| 157 | kind=self.kind, |
||
| 158 | success=False, |
||
| 159 | message=f"No data found for {self.carrier} capacity comparison", |
||
| 160 | severity=Severity.ERROR, |
||
| 161 | schema=self.schema, |
||
| 162 | table_name=self.table_name, |
||
| 163 | rule_class=self.__class__.__name__ |
||
| 164 | ) |
||
| 165 | |||
| 166 | output_capacity = float(df["output_capacity_mw"].values[0]) |
||
| 167 | input_capacity = float(df["input_capacity_mw"].values[0]) |
||
| 168 | |||
| 169 | # Case 1: Both zero - OK, no capacity needed |
||
| 170 | View Code Duplication | if output_capacity == 0 and input_capacity == 0: |
|
|
|
|||
| 171 | return RuleResult( |
||
| 172 | rule_id=self.rule_id, |
||
| 173 | task=self.task, |
||
| 174 | table=self.table, |
||
| 175 | kind=self.kind, |
||
| 176 | success=True, |
||
| 177 | observed=0.0, |
||
| 178 | expected=0.0, |
||
| 179 | message=( |
||
| 180 | f"No {self.carrier} {self.component_type} capacity needed " |
||
| 181 | f"for {self.scenario} (both input and output are zero)" |
||
| 182 | ), |
||
| 183 | severity=Severity.INFO, |
||
| 184 | schema=self.schema, |
||
| 185 | table_name=self.table_name, |
||
| 186 | rule_class=self.__class__.__name__ |
||
| 187 | ) |
||
| 188 | |||
| 189 | # Case 2: Input > 0 but output = 0 - ERROR |
||
| 190 | View Code Duplication | if input_capacity > 0 and output_capacity == 0: |
|
| 191 | return RuleResult( |
||
| 192 | rule_id=self.rule_id, |
||
| 193 | task=self.task, |
||
| 194 | table=self.table, |
||
| 195 | kind=self.kind, |
||
| 196 | success=False, |
||
| 197 | observed=0.0, |
||
| 198 | expected=input_capacity, |
||
| 199 | message=( |
||
| 200 | f"{self.carrier} {self.component_type} capacity was not distributed at all! " |
||
| 201 | f"Input: {input_capacity:.2f} MW, Output: 0 MW for {self.scenario}" |
||
| 202 | ), |
||
| 203 | severity=Severity.ERROR, |
||
| 204 | schema=self.schema, |
||
| 205 | table_name=self.table_name, |
||
| 206 | rule_class=self.__class__.__name__ |
||
| 207 | ) |
||
| 208 | |||
| 209 | # Case 3: Output > 0 but input = 0 - ERROR |
||
| 210 | View Code Duplication | if output_capacity > 0 and input_capacity == 0: |
|
| 211 | return RuleResult( |
||
| 212 | rule_id=self.rule_id, |
||
| 213 | task=self.task, |
||
| 214 | table=self.table, |
||
| 215 | kind=self.kind, |
||
| 216 | success=False, |
||
| 217 | observed=output_capacity, |
||
| 218 | expected=0.0, |
||
| 219 | message=( |
||
| 220 | f"{self.carrier} {self.component_type} capacity was distributed " |
||
| 221 | f"even though no input was provided! " |
||
| 222 | f"Output: {output_capacity:.2f} MW, Input: 0 MW for {self.scenario}" |
||
| 223 | ), |
||
| 224 | severity=Severity.ERROR, |
||
| 225 | schema=self.schema, |
||
| 226 | table_name=self.table_name, |
||
| 227 | rule_class=self.__class__.__name__ |
||
| 228 | ) |
||
| 229 | |||
| 230 | # Case 4: Both > 0 - Check deviation |
||
| 231 | deviation = abs(output_capacity - input_capacity) / input_capacity |
||
| 232 | deviation_pct = deviation * 100 |
||
| 233 | error_pct = ((output_capacity - input_capacity) / input_capacity) * 100 |
||
| 234 | |||
| 235 | success = deviation <= self.rtol |
||
| 236 | |||
| 237 | if success: |
||
| 238 | return RuleResult( |
||
| 239 | rule_id=self.rule_id, |
||
| 240 | task=self.task, |
||
| 241 | table=self.table, |
||
| 242 | kind=self.kind, |
||
| 243 | success=True, |
||
| 244 | observed=output_capacity, |
||
| 245 | expected=input_capacity, |
||
| 246 | message=( |
||
| 247 | f"{self.carrier} {self.component_type} capacity valid for {self.scenario}: " |
||
| 248 | f"Output: {output_capacity:.2f} MW, Input: {input_capacity:.2f} MW, " |
||
| 249 | f"Deviation: {error_pct:+.2f}% (tolerance: ±{self.rtol*100:.2f}%)" |
||
| 250 | ), |
||
| 251 | severity=Severity.INFO, |
||
| 252 | schema=self.schema, |
||
| 253 | table_name=self.table_name, |
||
| 254 | rule_class=self.__class__.__name__ |
||
| 255 | ) |
||
| 256 | else: |
||
| 257 | return RuleResult( |
||
| 258 | rule_id=self.rule_id, |
||
| 259 | task=self.task, |
||
| 260 | table=self.table, |
||
| 261 | kind=self.kind, |
||
| 262 | success=False, |
||
| 263 | observed=output_capacity, |
||
| 264 | expected=input_capacity, |
||
| 265 | message=( |
||
| 266 | f"{self.carrier} {self.component_type} capacity deviation too large for {self.scenario}: " |
||
| 267 | f"Output: {output_capacity:.2f} MW, Input: {input_capacity:.2f} MW, " |
||
| 268 | f"Deviation: {error_pct:+.2f}% (tolerance: ±{self.rtol*100:.2f}%)" |
||
| 269 | ), |
||
| 270 | severity=Severity.ERROR, |
||
| 271 | schema=self.schema, |
||
| 272 | table_name=self.table_name, |
||
| 273 | rule_class=self.__class__.__name__ |
||
| 274 | ) |
||
| 275 |