Skip to content

Commit 209654c

Browse files
committed
refactor: simplify consumer function mapping
1 parent 1b95ce2 commit 209654c

4 files changed

Lines changed: 55 additions & 92 deletions

File tree

src/libecalc/domain/resource.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,31 @@
1-
from typing import Protocol
1+
import abc
2+
import logging
23

4+
from libecalc.common.errors.exceptions import InvalidColumnException
35

4-
class Resource(Protocol):
6+
logger = logging.getLogger(__name__)
7+
8+
9+
class Resource(abc.ABC):
510
"""
611
A resource containing tabular data
712
"""
813

14+
@abc.abstractmethod
915
def get_headers(self) -> list[str]: ...
1016

17+
@abc.abstractmethod
1118
def get_column(self, header: str) -> list[float | int | str]: ...
1219

20+
def get_float_column(self, header: str) -> list[float]:
21+
try:
22+
column = self.get_column(header)
23+
column = [float(value) for value in column]
24+
except ValueError as e:
25+
msg = f"Resource contains non-numeric value: {e}"
26+
logger.error(msg)
27+
raise InvalidColumnException(header=header, message=msg) from e
28+
return column
29+
1330

1431
Resources = dict[str, Resource]

src/libecalc/presentation/yaml/mappers/energy_model_factory.py

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/libecalc/presentation/yaml/mappers/facility_input.py

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from collections.abc import Callable
12
from typing import Union
23

34
from pydantic import ValidationError
@@ -15,7 +16,6 @@
1516
from libecalc.domain.process.pump.pump import PumpModelDTO
1617
from libecalc.domain.resource import Resource, Resources
1718
from libecalc.presentation.yaml.file_context import FileContext, FileMark
18-
from libecalc.presentation.yaml.mappers.energy_model_factory import EnergyModelFactory
1919
from libecalc.presentation.yaml.mappers.utils import (
2020
YAML_UNIT_MAPPING,
2121
chart_curves_as_resource_to_dto_format,
@@ -45,7 +45,7 @@
4545
# Used here to make pydantic understand which object to instantiate.
4646
EnergyModelUnionType = Union[GeneratorSetModel, TabularEnergyFunction, CompressorTrainSampledDTO]
4747

48-
energy_model_type_map = {
48+
energy_model_type_map: dict[str, EnergyModelType | ChartType] = {
4949
EcalcYamlKeywords.facility_type_electricity2fuel: EnergyModelType.GENERATOR_SET_SAMPLED,
5050
EcalcYamlKeywords.facility_type_pump_chart_single_speed: ChartType.SINGLE_SPEED,
5151
EcalcYamlKeywords.facility_type_pump_chart_variable_speed: ChartType.VARIABLE_SPEED,
@@ -76,7 +76,8 @@ def _get_column_or_none(resource: Resource, header: str) -> list[float | int | s
7676

7777

7878
def _create_compressor_train_sampled_dto_model_data(
79-
resource: Resource, facility_data: YamlCompressorTabularModel, **kwargs
79+
resource: Resource,
80+
facility_data: YamlCompressorTabularModel,
8081
) -> CompressorTrainSampledDTO:
8182
# kwargs just to allow this to be used with _default_facility_to_dto_model_data which needs type until we have
8283
# replaced _default_facility_to_dto_model_data and have separate functions for all types
@@ -115,7 +116,8 @@ def _create_compressor_train_sampled_dto_model_data(
115116

116117

117118
def _create_pump_model_single_speed_dto_model_data(
118-
resource: Resource, facility_data: YamlPumpChartSingleSpeed, **kwargs
119+
resource: Resource,
120+
facility_data: YamlPumpChartSingleSpeed,
119121
) -> PumpModelDTO:
120122
chart_data = get_single_speed_chart_data(resource=resource)
121123

@@ -144,7 +146,8 @@ def _create_pump_model_single_speed_dto_model_data(
144146

145147

146148
def _create_pump_chart_variable_speed_dto_model_data(
147-
resource: Resource, facility_data: YamlPumpChartVariableSpeed, **kwargs
149+
resource: Resource,
150+
facility_data: YamlPumpChartVariableSpeed,
148151
) -> PumpModelDTO:
149152
curves_data = chart_curves_as_resource_to_dto_format(resource=resource)
150153

@@ -177,47 +180,41 @@ def _create_pump_chart_variable_speed_dto_model_data(
177180
)
178181

179182

180-
def _create_generator_set_dto_model_data(
181-
resource: Resource, facility_data: YamlGeneratorSetModel, **kwargs
183+
def _create_generator_set_model(
184+
resource: Resource,
185+
facility_data: YamlGeneratorSetModel,
182186
) -> GeneratorSetModel:
183187
# Extract adjustment constants from facility data
184188
adjustment_constant = _get_adjustment_constant(facility_data)
185189
adjustment_factor = _get_adjustment_factor(facility_data)
186190

187-
# Ensure the 'name' field is present in facility data
188-
name = getattr(facility_data, "name", "default_generator_set_name")
189-
190191
# Create and return the GeneratorSetProcessUnit instance
191192
return GeneratorSetModel(
192-
name=name,
193+
name=facility_data.name,
193194
resource=resource,
194195
energy_usage_adjustment_constant=adjustment_constant,
195196
energy_usage_adjustment_factor=adjustment_factor,
196197
)
197198

198199

199-
def _default_facility_to_dto_model_data(
200-
resource: Resource, typ: EnergyModelType, facility_data: YamlFacilityModelBase
201-
) -> EnergyModelUnionType:
200+
def _create_tabulated_model(resource: Resource, facility_data: YamlFacilityModelBase) -> EnergyModelUnionType:
202201
resource_headers = resource.get_headers()
203-
resource_data = [resource.get_column(header) for header in resource_headers]
204-
205-
model_data = {
206-
"typ": typ,
207-
"headers": resource_headers,
208-
"data": resource_data,
209-
"energy_usage_adjustment_constant": _get_adjustment_constant(data=facility_data),
210-
"energy_usage_adjustment_factor": _get_adjustment_factor(data=facility_data),
211-
}
202+
resource_data = [resource.get_float_column(header) for header in resource_headers]
212203

213-
return EnergyModelFactory.create(typ, model_data)
204+
return TabularEnergyFunction(
205+
headers=resource_headers,
206+
data=resource_data,
207+
energy_usage_adjustment_factor=_get_adjustment_constant(data=facility_data),
208+
energy_usage_adjustment_constant=_get_adjustment_constant(data=facility_data),
209+
)
214210

215211

216-
facility_input_to_dto_map = {
212+
facility_input_to_dto_map: dict[EnergyModelType | ChartType, Callable] = {
217213
EnergyModelType.COMPRESSOR_SAMPLED: _create_compressor_train_sampled_dto_model_data,
218-
EnergyModelType.GENERATOR_SET_SAMPLED: _create_generator_set_dto_model_data,
214+
EnergyModelType.GENERATOR_SET_SAMPLED: _create_generator_set_model,
219215
ChartType.SINGLE_SPEED: _create_pump_model_single_speed_dto_model_data,
220216
ChartType.VARIABLE_SPEED: _create_pump_chart_variable_speed_dto_model_data,
217+
EnergyModelType.TABULATED: _create_tabulated_model,
221218
}
222219

223220

@@ -238,13 +235,17 @@ def from_yaml_to_dto(self, data: YamlFacilityModel) -> EnergyModel:
238235

239236
typ = energy_model_type_map.get(data.type)
240237

238+
if typ is None:
239+
raise DataValidationError(
240+
data=data.model_dump(),
241+
message=f"Unsupported facility input type '{data.type}'",
242+
dump_flow_style=DumpFlowStyle.BLOCK,
243+
)
244+
241245
try:
242-
return facility_input_to_dto_map.get(
243-
typ, # type: ignore[operator, arg-type]
244-
_default_facility_to_dto_model_data,
245-
)(
246+
assert typ in facility_input_to_dto_map
247+
return facility_input_to_dto_map[typ](
246248
resource=resource,
247-
typ=typ,
248249
facility_data=data,
249250
)
250251
except ValidationError as ve:

src/libecalc/presentation/yaml/mappers/utils.py

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ def get_units_from_chart_config(
255255

256256
def get_single_speed_chart_data(resource: Resource) -> ChartData:
257257
try:
258-
speed_values = _get_float_column(resource=resource, header=EcalcYamlKeywords.consumer_chart_speed)
258+
speed_values = resource.get_float_column(EcalcYamlKeywords.consumer_chart_speed)
259259

260260
if not _all_numbers_equal(speed_values):
261261
raise InvalidColumnException(
@@ -268,31 +268,11 @@ def get_single_speed_chart_data(resource: Resource) -> ChartData:
268268
logger.debug("Speed not specified for single speed chart, setting speed to 1.")
269269
speed = 1
270270

271-
efficiency_values = _get_float_column(
272-
resource=resource,
273-
header=EcalcYamlKeywords.consumer_chart_efficiency,
274-
)
275-
rate_values = _get_float_column(
276-
resource=resource,
277-
header=EcalcYamlKeywords.consumer_chart_rate,
278-
)
279-
head_values = _get_float_column(
280-
resource=resource,
281-
header=EcalcYamlKeywords.consumer_chart_head,
282-
)
271+
efficiency_values = resource.get_float_column(EcalcYamlKeywords.consumer_chart_efficiency)
272+
rate_values = resource.get_float_column(EcalcYamlKeywords.consumer_chart_rate)
273+
head_values = resource.get_float_column(EcalcYamlKeywords.consumer_chart_head)
283274
return ChartData(speed, rate_values, head_values, efficiency_values)
284275

285276

286-
def _get_float_column(resource: Resource, header: str) -> list[float]:
287-
try:
288-
column = resource.get_column(header)
289-
column = [float(value) for value in column]
290-
except ValueError as e:
291-
msg = f"Resource contains non-numeric value: {e}"
292-
logger.error(msg)
293-
raise InvalidColumnException(header=header, message=msg) from e
294-
return column
295-
296-
297277
def _all_numbers_equal(values: list[int | float]) -> bool:
298278
return len(set(values)) == 1

0 commit comments

Comments
 (0)