EnergySystemTab package
Das EnergySystemTab-Paket enthält die GUI-Komponenten für die Konfiguration und Verwaltung von Energiesystemen in der DistrictHeatingSim-Anwendung.
Energy System Main Tab Module
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
Main tab for managing energy system design, including technology definitions, cost calculations, and results display.
- class districtheatingsim.gui.EnergySystemTab._01_energy_system_main_tab.EnergySystemTab(folder_manager, data_manager, config_manager, parent=None)[source]
Bases:
QWidgetMain tab for defining and managing energy mix design for heat generation projects.
- Signal data_added:
Signal emitted when new data is added.
- data_added
int = …, arguments: Sequence = …) -> PYQT_SIGNAL
types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.
- Type:
pyqtSignal(*types, name
- Type:
str = …, revision
- __init__(folder_manager, data_manager, config_manager, parent=None)[source]
Initialize the EnergySystemTab.
- updateDefaultPath(new_base_path)[source]
Update project default path and refresh the config selector.
- Parameters:
new_base_path (str) – New base path for the project (variant folder).
- createAction(title, method)[source]
Create a menu action.
- Parameters:
title (str) – Action title.
method (function) – Method to be called when triggered.
- Returns:
Created action.
- Return type:
QAction
- createMainLayout()[source]
Create main layout for the tab.
- Returns:
Main layout.
- Return type:
QVBoxLayout
- validateInputs()[source]
Validate inputs for calculation.
- Returns:
True if inputs are valid, False otherwise.
- Return type:
- on_calculation_done(result)[source]
Handle calculation completion.
- Parameters:
result (dict) – Calculation results.
- on_calculation_error(error_message)[source]
Handle calculation errors.
- Parameters:
error_message (str) – Error message.
- sensitivity(gas_range, electricity_range, wood_range, weights=None)[source]
Perform sensitivity analysis over a range of prices.
- calculate_sensitivity(gas_price, electricity_price, wood_price, weights)[source]
Calculate energy mix for given prices and weights.
- save_heat_generation_results_to_csv(show_dialog=True)[source]
Save heat generation results to CSV file.
- Parameters:
show_dialog (bool) – Whether to show dialogs.
Energy System Dialogs Module
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
Dialogs for the Energy System Tab, including economic parameters input, cost calculation, and weight settings for optimization.
- class districtheatingsim.gui.EnergySystemTab._02_energy_system_dialogs.EconomicParametersDialog(parent=None)[source]
Bases:
QDialogDialog for inputting economic parameters.
- __init__(parent=None)[source]
Initialize the EconomicParametersDialog.
- Parameters:
parent (QWidget) – Parent widget.
- loadValues(values)[source]
Load values into input fields.
- Parameters:
values (dict) – Dictionary containing values to load.
- getValues()[source]
Get values from input fields.
- Returns:
Dictionary containing input values.
- Return type:
- updateValues(new_values)[source]
Update default values and reload them into input fields.
- Parameters:
new_values (dict) – Dictionary containing new values.
- class districtheatingsim.gui.EnergySystemTab._02_energy_system_dialogs.KostenBerechnungDialog(parent=None, label=None, value=None, type=None)[source]
Bases:
QDialogDialog for calculating costs based on a geoJSON file.
- class districtheatingsim.gui.EnergySystemTab._02_energy_system_dialogs.WeightDialog[source]
Bases:
QDialogDialog for setting weights for optimization.
Technology Tab Module
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
Managing and displaying technologies in district heating simulation, including add, edit, remove, and schematic visualization.
- class districtheatingsim.gui.EnergySystemTab._03_technology_tab.CustomListWidget(parent=None)[source]
Bases:
QListWidgetCustom list widget with drag-drop functionality for technology ordering.
- class districtheatingsim.gui.EnergySystemTab._03_technology_tab.TechnologyTab(data_manager, config_manager, parent=None)[source]
Bases:
QWidgetTab for managing and displaying heat generation technologies.
- Signal data_added:
Signal that emits data as an object.
- global_counters = {'Abwärmepumpe': 0, 'AqvaHeat': 0, 'BHKW': 0, 'Biomassekessel': 0, 'Flusswärmepumpe': 0, 'Gaskessel': 0, 'Geothermie': 0, 'Holzgas-BHKW': 0, 'Power-to-Heat': 0, 'Solarthermie': 0, 'Thermischer Netzspeicher': 0}
- data_added
int = …, arguments: Sequence = …) -> PYQT_SIGNAL
types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.
- Type:
pyqtSignal(*types, name
- Type:
str = …, revision
- updateDefaultPath(new_base_path)[source]
Update default path for file inputs.
- Parameters:
new_base_path (str) – New base path.
- addHorizontalLayout(*widgets)[source]
Add horizontal layout with given widgets to main layout.
- Parameters:
widgets (tuple) – Widgets to add to horizontal layout.
- editTech(item)[source]
Edit selected technology.
- Parameters:
item (QListWidgetItem) – Selected item to edit.
- removeSelectedTech()[source]
Remove selected technology object and update counters and object names.
- updateTechNames(tech_type)[source]
Update names and labels of remaining objects of a technology class.
- Parameters:
tech_type (str) – Technology type.
- formatTechForDisplay(tech)[source]
Delegate formatting of display text to technology object.
- Parameters:
tech (Technology) – Technology object.
- Returns:
Formatted string for display.
- Return type:
- createMainLayout()[source]
Create main layout for TechnologyTab.
- Returns:
Main layout.
- Return type:
QVBoxLayout
- loadFileAndPlot()[source]
Load file and plot data, display message if file unavailable or has issues.
- plotData(data)[source]
Plot data on canvas with modern styling and hour-based x-axis.
- Parameters:
data (DataFrame) – Data to plot.
Technology Input Dialogs Module — compatibility façade.
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
The dialog classes were extracted into the technology_dialogs package
(schema-driven base + one module per technology family; BACKLOG B1). This module
re-exports them so existing imports — notably
from ..._04_technology_dialogs import TechInputDialog in
_03_technology_tab.py — keep working unchanged.
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.TechInputDialog(tech_type, tech_data=None)[source]
Bases:
QDialogDialog for inputting technology-specific data based on technology type.
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.Field(key: str, label: str, default: str, cast: Callable = <class 'float'>, in_key: str | None = None)[source]
Bases:
objectA single text-input row mapping a
tech_datakey to a QLineEdit.- Parameters:
key – Output key written by
getInputs().label – German label shown next to the field.
default – Default text when the value is absent from
tech_data.cast – Callable applied to the text on output (
floatby default; e.g.intfor node counts).in_key – Key read for the initial value, when it differs from
key. Reproduces the legacy read/write asymmetry of some dialogs (e.g. GasBoiler readsth_Leistung_kWbut writesthermal_capacity_kW). Defaults tokey.
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.CheckField(key: str, label: str, default: bool = False)[source]
Bases:
objectA checkbox row producing a bool in
getInputs().
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.SchemaDialog(tech_data: dict | None = None)[source]
Bases:
QWidgetBase widget that builds itself from a declarative field schema.
Subclasses set class attributes:
main_schema: flat list ofField/ComboField/CheckField(rendered in a single form).sections: alternatively, a list ofSectionrendered as titled group boxes. When set it takes precedence overmain_schema.storage_schema: optional list ofFieldrendered in a side panel whose visibility is toggled by thestorage_toggle_keycheckbox; its keys are only included ingetInputs()when that checkbox is checked.storage_toggle_key: key of the controlling checkbox (default"speicher_aktiv").title: optional window title.
Dialogs with custom widgets override
_build()(calling_build_fields()for the schema part) and, if needed,getInputs().- main_schema: list[Field | ComboField | CheckField] = []
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.GasBoilerDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure gas-boiler parameters.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='thermal_capacity_kW', label='Thermische Leistung Gaskessel in kW', default='1000', cast=<class 'float'>, in_key=None), Field(key='Nutzungsgrad', label='Nutzungsgrad Gaskessel', default='0.9', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten', label='spez. Investitionskosten in €/kW', default='30', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.PowerToHeatDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure Power-to-Heat parameters.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='thermal_capacity_kW', label='Thermische Leistung Power-To-Heat in kW', default='1000', cast=<class 'float'>, in_key=None), Field(key='Nutzungsgrad', label='Nutzungsgrad Power-to-Heat', default='0.9', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten', label='spez. Investitionskosten in €/kW', default='30', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.WasteHeatPumpDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure waste-heat-pump parameters.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='Kühlleistung_Abwärme', label='Kühlleistung Abwärme in kW', default='30', cast=<class 'float'>, in_key=None), Field(key='Temperatur_Abwärme', label='Temperatur Abwärme in °C', default='30', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Abwärme', label='spez. Investitionskosten Abwärmenutzung in €/kW', default='500', cast=<class 'float'>, in_key=None), Field(key='spezifische_Investitionskosten_WP', label='spez. Investitionskosten Wärmepumpe', default='1000', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.BiomassBoilerDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure biomass-boiler parameters with optional buffer storage.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='thermal_capacity_kW', label='th. Leistung in kW', default='240', cast=<class 'float'>, in_key=None), Field(key='Größe_Holzlager', label='Größe Holzlager in t', default='40', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten', label='spez. Investitionskosten Kessel in €/kW', default='200', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Holzlager', label='spez. Investitionskosten Holzlager in €/t', default='400', cast=<class 'float'>, in_key=None), Field(key='Nutzungsgrad_BMK', label='Nutzungsgrad Biomassekessel', default='0.8', cast=<class 'float'>, in_key=None), Field(key='min_Teillast', label='minimale Teillast', default='0.3', cast=<class 'float'>, in_key=None), Field(key='opt_BMK_min', label='Untere Grenze th. Leistung Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_BMK_max', label='Obere Grenze th. Leistung Optimierung', default='5000', cast=<class 'float'>, in_key=None), CheckField(key='speicher_aktiv', label='Speicher aktiv', default=False)]
- storage_schema: list[Field] | None = [Field(key='Speicher_Volumen', label='Speicher Volumen', default='20', cast=<class 'float'>, in_key=None), Field(key='T_vorlauf', label='Vorlauftemperatur', default='90', cast=<class 'float'>, in_key=None), Field(key='T_ruecklauf', label='Rücklauftemperatur', default='60', cast=<class 'float'>, in_key=None), Field(key='initial_fill', label='initiale Füllung', default='0.0', cast=<class 'float'>, in_key=None), Field(key='min_fill', label='minimale Füllung', default='0.2', cast=<class 'float'>, in_key=None), Field(key='max_fill', label='maximale Füllung', default='0.8', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Speicher', label='spez. Investitionskosten Speicher in €/m³', default='750', cast=<class 'float'>, in_key=None), Field(key='opt_Speicher_min', label='Untere Grenze Speichervolumen Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_Speicher_max', label='Obere Grenze Speichervolumen Optimierung', default='100', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.CHPDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure gas-CHP parameters with optional buffer storage.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='th_Leistung_kW', label='thermische Leistung', default='100', cast=<class 'float'>, in_key=None), Field(key='el_Wirkungsgrad', label='elektrischer Wirkungsgrad BHKW', default='0.33', cast=<class 'float'>, in_key=None), Field(key='KWK_Wirkungsgrad', label='KWK Wirkungsgrad', default='0.9', cast=<class 'float'>, in_key=None), Field(key='min_Teillast', label='minimale Teillast', default='0.7', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_GBHKW', label='spez. Investitionskosten BHKW', default='1500', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_min', label='Untere Grenze th. Leistung Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_max', label='Obere Grenze th. Leistung Optimierung', default='1000', cast=<class 'float'>, in_key=None), CheckField(key='speicher_aktiv', label='Speicher aktiv', default=False)]
- storage_schema: list[Field] | None = [Field(key='Speicher_Volumen_BHKW', label='Speicher Volumen', default='20', cast=<class 'float'>, in_key=None), Field(key='T_vorlauf', label='Vorlauftemperatur', default='90', cast=<class 'float'>, in_key=None), Field(key='T_ruecklauf', label='Rücklauftemperatur', default='60', cast=<class 'float'>, in_key=None), Field(key='initial_fill', label='initiale Füllung', default='0.0', cast=<class 'float'>, in_key=None), Field(key='min_fill', label='minimale Füllung', default='0.2', cast=<class 'float'>, in_key=None), Field(key='max_fill', label='maximale Füllung', default='0.8', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Speicher', label='spez. Investitionskosten Speicher in €/m³', default='750', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_Speicher_min', label='Untere Grenze Speichervolumen Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_Speicher_max', label='Obere Grenze Speichervolumen Optimierung', default='100', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.HolzgasCHPDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure wood-gas-CHP parameters with optional buffer storage.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='th_Leistung_kW', label='thermische Leistung', default='100', cast=<class 'float'>, in_key=None), Field(key='el_Wirkungsgrad', label='elektrischer Wirkungsgrad BHKW', default='0.33', cast=<class 'float'>, in_key=None), Field(key='KWK_Wirkungsgrad', label='KWK Wirkungsgrad', default='0.9', cast=<class 'float'>, in_key=None), Field(key='min_Teillast', label='minimale Teillast', default='0.7', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_HBHKW', label='spez. Investitionskosten BHKW', default='1850', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_min', label='Untere Grenze th. Leistung Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_max', label='Obere Grenze th. Leistung Optimierung', default='1000', cast=<class 'float'>, in_key=None), CheckField(key='speicher_aktiv', label='Speicher aktiv', default=False)]
- storage_schema: list[Field] | None = [Field(key='Speicher_Volumen_BHKW', label='Speicher Volumen', default='20', cast=<class 'float'>, in_key=None), Field(key='T_vorlauf', label='Vorlauftemperatur', default='90', cast=<class 'float'>, in_key=None), Field(key='T_ruecklauf', label='Rücklauftemperatur', default='60', cast=<class 'float'>, in_key=None), Field(key='initial_fill', label='initiale Füllung', default='0.0', cast=<class 'float'>, in_key=None), Field(key='min_fill', label='minimale Füllung', default='0.2', cast=<class 'float'>, in_key=None), Field(key='max_fill', label='maximale Füllung', default='0.8', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Speicher', label='spez. Investitionskosten Speicher in €/m³', default='750', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_Speicher_min', label='Untere Grenze Speichervolumen Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_Speicher_max', label='Obere Grenze Speichervolumen Optimierung', default='100', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.SolarThermalDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure solar-thermal parameters with a live collector-orientation preview.
- sections: list[Section] | None = [Section(title='Technische Daten', fields=[Field(key='bruttofläche_STA', label='Kollektorbruttofläche in m²', default='200', cast=<class 'float'>, in_key=None), Field(key='vs', label='Solarspeichervolumen in m³', default='20', cast=<class 'float'>, in_key=None), ComboField(key='Typ', label='Kollektortyp', options=['Vakuumröhrenkollektor', 'Flachkollektor'], default='Vakuumröhrenkollektor'), Field(key='Tsmax', label='Maximale Speichertemperatur in °C', default='90', cast=<class 'float'>, in_key=None), Field(key='Longitude', label='Longitude des Erzeugerstandortes', default='-14.4222', cast=<class 'float'>, in_key=None), Field(key='STD_Longitude', label='STD_Longitude des Erzeugerstandortes', default='15', cast=<class 'int'>, in_key=None), Field(key='Latitude', label='Latitude des Erzeugerstandortes', default='51.1676', cast=<class 'float'>, in_key=None), Field(key='East_West_collector_azimuth_angle', label='Azimuth-Ausrichtung des Kollektors in °', default='0', cast=<class 'float'>, in_key=None), Field(key='Collector_tilt_angle', label='Neigungswinkel des Kollektors in ° (0-90)', default='36', cast=<class 'float'>, in_key=None), Field(key='Tm_rl', label='Startwert Rücklauftemperatur in Speicher in °C', default='60', cast=<class 'float'>, in_key=None), Field(key='Qsa', label='Startwert Speicherfüllstand', default='0', cast=<class 'float'>, in_key=None), Field(key='Vorwärmung_K', label='Mögliche Abweichung von Solltemperatur bei Vorwärmung', default='8', cast=<class 'float'>, in_key=None), Field(key='DT_WT_Solar_K', label='Grädigkeit Wärmeübertrager Kollektor/Speicher', default='5', cast=<class 'float'>, in_key=None), Field(key='DT_WT_Netz_K', label='Grädigkeit Wärmeübertrager Speicher/Netz', default='5', cast=<class 'float'>, in_key=None)]), Section(title='Kosten', fields=[Field(key='kosten_speicher_spez', label='spez. Kosten Solarspeicher in €/m³', default='750', cast=<class 'float'>, in_key=None), Field(key='kosten_fk_spez', label='spez. Kosten Flachkollektor in €/m²', default='430', cast=<class 'float'>, in_key=None), Field(key='kosten_vrk_spez', label='spez. Kosten Vakuumröhrenkollektor in €/m²', default='590', cast=<class 'float'>, in_key=None)]), Section(title='Optimierungsparameter', fields=[Field(key='opt_volume_min', label='Untere Grenze Speichervolumen Optimierung', default='1', cast=<class 'float'>, in_key=None), Field(key='opt_volume_max', label='Obere Grenze Speichervolumen Optimierung', default='200', cast=<class 'float'>, in_key=None), Field(key='opt_area_min', label='Untere Grenze Kollektorfläche Optimierung', default='1', cast=<class 'float'>, in_key=None), Field(key='opt_area_max', label='Obere Grenze Kollektorfläche Optimierung', default='2000', cast=<class 'float'>, in_key=None)])]
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.GeothermalDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure geothermal parameters with a live 3D borehole-field preview.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='Fläche', label='Fläche Erdsondenfeld in m²', default='100', cast=<class 'float'>, in_key=None), Field(key='Bohrtiefe', label='Bohrtiefe Sonden in m', default='100', cast=<class 'float'>, in_key=None), Field(key='Temperatur_Geothermie', label='Quelltemperatur in °C', default='10', cast=<class 'float'>, in_key=None), Field(key='Abstand_Sonden', label='Abstand Erdsonden in m', default='10', cast=<class 'float'>, in_key=None), Field(key='spez_Bohrkosten', label='spez. Bohrkosten pro Bohrmeter in €/m', default='120', cast=<class 'float'>, in_key=None), Field(key='spez_Entzugsleistung', label='spez. Entzugsleistung Untergrund in W/m', default='50', cast=<class 'float'>, in_key=None), Field(key='Vollbenutzungsstunden', label='Vollbenutzungsstunden Sondenfeld in h', default='2400', cast=<class 'float'>, in_key=None), Field(key='spezifische_Investitionskosten_WP', label='spez. Investitionskosten Wärmepumpe in €/kW', default='1000', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.RiverHeatPumpDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure river heat-pump parameters with optional CSV river-temperature data.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='Wärmeleistung_FW_WP', label='th. Leistung Wärmepumpe in kW', default='200', cast=<class 'float'>, in_key=None), Field(key='dT', label='Zulässige Abweichung Vorlauftemperatur Wärmepumpe von Netzvorlauftemperatur', default='0', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Flusswasser', label='spez. Investitionskosten Flusswärmenutzung', default='1000', cast=<class 'float'>, in_key=None), Field(key='spezifische_Investitionskosten_WP', label='spez. Investitionskosten Wärmepumpe', default='1000', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.AqvaHeatDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure AqvaHeat parameters (no inputs yet).
- main_schema: list[Field | ComboField | CheckField] = []
- class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.ThermalStorage1DDialog(tech_data=None)[source]
Bases:
QWidgetDialog for configuring a 1D stratified thermal storage (ThermalStorageAdapter).
Sections: - Basic: name, volume, height, geometry, n_nodes - Temperature limits: T_min, T_max, initial_temp - Loss model: constant / split / ground (dynamic fields) - Fluid properties: water / constant (dynamic fields) - Solver (collapsible advanced section) - Costs: specific investment cost
Declarative field schema + base dialog for technology-input widgets.
The simple and combustion technology dialogs differ only in which fields they
show and how those map to the tech_data dict. SchemaDialog builds the
QFormLayout and implements getInputs() from a declarative list of Field /
ComboField / CheckField entries, removing the per-dialog QLineEdit→dict
boilerplate.
Dialogs needing custom widgets (3D plots, CSV import) subclass SchemaDialog,
let it build the fields via _build_fields(), and arrange/extend them by
overriding _build() and getInputs() (see _solar.py / _heat_pump.py).
The 1D thermal-storage dialog (dynamic loss-model sections + conditional output)
stays fully hand-written — it is unique, not duplicated, so the schema buys nothing.
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._base.Field(key: str, label: str, default: str, cast: Callable = <class 'float'>, in_key: str | None = None)[source]
Bases:
objectA single text-input row mapping a
tech_datakey to a QLineEdit.- Parameters:
key – Output key written by
getInputs().label – German label shown next to the field.
default – Default text when the value is absent from
tech_data.cast – Callable applied to the text on output (
floatby default; e.g.intfor node counts).in_key – Key read for the initial value, when it differs from
key. Reproduces the legacy read/write asymmetry of some dialogs (e.g. GasBoiler readsth_Leistung_kWbut writesthermal_capacity_kW). Defaults tokey.
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._base.ComboField(key: str, label: str, options: list[str], default: str)[source]
Bases:
objectA dropdown row producing the selected option string in
getInputs().
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._base.CheckField(key: str, label: str, default: bool = False)[source]
Bases:
objectA checkbox row producing a bool in
getInputs().
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._base.Section(title: str, fields: list[Field | ComboField | CheckField])[source]
Bases:
objectA titled QGroupBox grouping a set of fields (purely a layout container).
- fields: list[Field | ComboField | CheckField]
- __init__(title: str, fields: list[Field | ComboField | CheckField]) None
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._base.SchemaDialog(tech_data: dict | None = None)[source]
Bases:
QWidgetBase widget that builds itself from a declarative field schema.
Subclasses set class attributes:
main_schema: flat list ofField/ComboField/CheckField(rendered in a single form).sections: alternatively, a list ofSectionrendered as titled group boxes. When set it takes precedence overmain_schema.storage_schema: optional list ofFieldrendered in a side panel whose visibility is toggled by thestorage_toggle_keycheckbox; its keys are only included ingetInputs()when that checkbox is checked.storage_toggle_key: key of the controlling checkbox (default"speicher_aktiv").title: optional window title.
Dialogs with custom widgets override
_build()(calling_build_fields()for the schema part) and, if needed,getInputs().- main_schema: list[Field | ComboField | CheckField] = []
Declarative field schemas for the schema-driven technology dialogs.
Each list mirrors, field-for-field and default-for-default, the original
hand-written dialog in _04_technology_dialogs.py (pre-refactor). Two legacy
quirks are reproduced on purpose and pinned by tests/test_technology_dialogs.py
(see BACKLOG): the capacity read/write key asymmetry (in_key) and the CHP
storage-cost default of "0.8" (Biomass uses "750").
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
- districtheatingsim.gui.EnergySystemTab.technology_dialogs._schemas.storage_fields(volume_key: str, opt_min_key: str, opt_max_key: str, spez_cost_default: str) list[Field][source]
Return the 9-field generator buffer-storage block.
Six fields are identical across the three combustion dialogs; the volume key, the two optimization-bound keys, and the specific-cost default differ and are passed in.
TechInputDialog — the public entry point that routes a technology type to its sub-dialog and wraps it with OK/Cancel buttons.
Dispatch logic (prefix matching, order) is preserved verbatim from the original
_04_technology_dialogs.py.
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._dispatcher.TechInputDialog(tech_type, tech_data=None)[source]
Bases:
QDialogDialog for inputting technology-specific data based on technology type.
Schema-driven dialogs for the simple single-block technologies.
GasBoiler, PowerToHeat and WasteHeatPump are plain QLineEdit forms with no storage section; they reduce to a class attribute pointing at their field schema.
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._simple.GasBoilerDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure gas-boiler parameters.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='thermal_capacity_kW', label='Thermische Leistung Gaskessel in kW', default='1000', cast=<class 'float'>, in_key=None), Field(key='Nutzungsgrad', label='Nutzungsgrad Gaskessel', default='0.9', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten', label='spez. Investitionskosten in €/kW', default='30', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._simple.PowerToHeatDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure Power-to-Heat parameters.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='thermal_capacity_kW', label='Thermische Leistung Power-To-Heat in kW', default='1000', cast=<class 'float'>, in_key=None), Field(key='Nutzungsgrad', label='Nutzungsgrad Power-to-Heat', default='0.9', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten', label='spez. Investitionskosten in €/kW', default='30', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._simple.WasteHeatPumpDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure waste-heat-pump parameters.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='Kühlleistung_Abwärme', label='Kühlleistung Abwärme in kW', default='30', cast=<class 'float'>, in_key=None), Field(key='Temperatur_Abwärme', label='Temperatur Abwärme in °C', default='30', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Abwärme', label='spez. Investitionskosten Abwärmenutzung in €/kW', default='500', cast=<class 'float'>, in_key=None), Field(key='spezifische_Investitionskosten_WP', label='spez. Investitionskosten Wärmepumpe', default='1000', cast=<class 'float'>, in_key=None)]
Schema-driven dialogs for the combustion technologies with a buffer-storage block.
BiomassBoiler, CHP and HolzgasCHP share an identical 9-field generator-storage
panel (toggled by the “Speicher aktiv” checkbox); only three keys and one default
differ, parametrised via _schemas.storage_fields.
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._combustion.BiomassBoilerDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure biomass-boiler parameters with optional buffer storage.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='thermal_capacity_kW', label='th. Leistung in kW', default='240', cast=<class 'float'>, in_key=None), Field(key='Größe_Holzlager', label='Größe Holzlager in t', default='40', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten', label='spez. Investitionskosten Kessel in €/kW', default='200', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Holzlager', label='spez. Investitionskosten Holzlager in €/t', default='400', cast=<class 'float'>, in_key=None), Field(key='Nutzungsgrad_BMK', label='Nutzungsgrad Biomassekessel', default='0.8', cast=<class 'float'>, in_key=None), Field(key='min_Teillast', label='minimale Teillast', default='0.3', cast=<class 'float'>, in_key=None), Field(key='opt_BMK_min', label='Untere Grenze th. Leistung Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_BMK_max', label='Obere Grenze th. Leistung Optimierung', default='5000', cast=<class 'float'>, in_key=None), CheckField(key='speicher_aktiv', label='Speicher aktiv', default=False)]
- storage_schema: list[Field] | None = [Field(key='Speicher_Volumen', label='Speicher Volumen', default='20', cast=<class 'float'>, in_key=None), Field(key='T_vorlauf', label='Vorlauftemperatur', default='90', cast=<class 'float'>, in_key=None), Field(key='T_ruecklauf', label='Rücklauftemperatur', default='60', cast=<class 'float'>, in_key=None), Field(key='initial_fill', label='initiale Füllung', default='0.0', cast=<class 'float'>, in_key=None), Field(key='min_fill', label='minimale Füllung', default='0.2', cast=<class 'float'>, in_key=None), Field(key='max_fill', label='maximale Füllung', default='0.8', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Speicher', label='spez. Investitionskosten Speicher in €/m³', default='750', cast=<class 'float'>, in_key=None), Field(key='opt_Speicher_min', label='Untere Grenze Speichervolumen Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_Speicher_max', label='Obere Grenze Speichervolumen Optimierung', default='100', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._combustion.CHPDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure gas-CHP parameters with optional buffer storage.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='th_Leistung_kW', label='thermische Leistung', default='100', cast=<class 'float'>, in_key=None), Field(key='el_Wirkungsgrad', label='elektrischer Wirkungsgrad BHKW', default='0.33', cast=<class 'float'>, in_key=None), Field(key='KWK_Wirkungsgrad', label='KWK Wirkungsgrad', default='0.9', cast=<class 'float'>, in_key=None), Field(key='min_Teillast', label='minimale Teillast', default='0.7', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_GBHKW', label='spez. Investitionskosten BHKW', default='1500', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_min', label='Untere Grenze th. Leistung Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_max', label='Obere Grenze th. Leistung Optimierung', default='1000', cast=<class 'float'>, in_key=None), CheckField(key='speicher_aktiv', label='Speicher aktiv', default=False)]
- storage_schema: list[Field] | None = [Field(key='Speicher_Volumen_BHKW', label='Speicher Volumen', default='20', cast=<class 'float'>, in_key=None), Field(key='T_vorlauf', label='Vorlauftemperatur', default='90', cast=<class 'float'>, in_key=None), Field(key='T_ruecklauf', label='Rücklauftemperatur', default='60', cast=<class 'float'>, in_key=None), Field(key='initial_fill', label='initiale Füllung', default='0.0', cast=<class 'float'>, in_key=None), Field(key='min_fill', label='minimale Füllung', default='0.2', cast=<class 'float'>, in_key=None), Field(key='max_fill', label='maximale Füllung', default='0.8', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Speicher', label='spez. Investitionskosten Speicher in €/m³', default='750', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_Speicher_min', label='Untere Grenze Speichervolumen Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_Speicher_max', label='Obere Grenze Speichervolumen Optimierung', default='100', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._combustion.HolzgasCHPDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure wood-gas-CHP parameters with optional buffer storage.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='th_Leistung_kW', label='thermische Leistung', default='100', cast=<class 'float'>, in_key=None), Field(key='el_Wirkungsgrad', label='elektrischer Wirkungsgrad BHKW', default='0.33', cast=<class 'float'>, in_key=None), Field(key='KWK_Wirkungsgrad', label='KWK Wirkungsgrad', default='0.9', cast=<class 'float'>, in_key=None), Field(key='min_Teillast', label='minimale Teillast', default='0.7', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_HBHKW', label='spez. Investitionskosten BHKW', default='1850', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_min', label='Untere Grenze th. Leistung Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_max', label='Obere Grenze th. Leistung Optimierung', default='1000', cast=<class 'float'>, in_key=None), CheckField(key='speicher_aktiv', label='Speicher aktiv', default=False)]
- storage_schema: list[Field] | None = [Field(key='Speicher_Volumen_BHKW', label='Speicher Volumen', default='20', cast=<class 'float'>, in_key=None), Field(key='T_vorlauf', label='Vorlauftemperatur', default='90', cast=<class 'float'>, in_key=None), Field(key='T_ruecklauf', label='Rücklauftemperatur', default='60', cast=<class 'float'>, in_key=None), Field(key='initial_fill', label='initiale Füllung', default='0.0', cast=<class 'float'>, in_key=None), Field(key='min_fill', label='minimale Füllung', default='0.2', cast=<class 'float'>, in_key=None), Field(key='max_fill', label='maximale Füllung', default='0.8', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Speicher', label='spez. Investitionskosten Speicher in €/m³', default='750', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_Speicher_min', label='Untere Grenze Speichervolumen Optimierung', default='0', cast=<class 'float'>, in_key=None), Field(key='opt_BHKW_Speicher_max', label='Obere Grenze Speichervolumen Optimierung', default='100', cast=<class 'float'>, in_key=None)]
Solar-thermal technology dialog: schema-driven fields (three group boxes, incl. a collector-type dropdown) plus a 3D collector-orientation plot.
Fields come from _schemas.SOLAR_SECTIONS via SchemaDialog; this
module adds the matplotlib canvas and the live visualization, which reads the
azimuth / tilt values from self._widgets.
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._solar.SolarThermalDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure solar-thermal parameters with a live collector-orientation preview.
- sections: list[Section] | None = [Section(title='Technische Daten', fields=[Field(key='bruttofläche_STA', label='Kollektorbruttofläche in m²', default='200', cast=<class 'float'>, in_key=None), Field(key='vs', label='Solarspeichervolumen in m³', default='20', cast=<class 'float'>, in_key=None), ComboField(key='Typ', label='Kollektortyp', options=['Vakuumröhrenkollektor', 'Flachkollektor'], default='Vakuumröhrenkollektor'), Field(key='Tsmax', label='Maximale Speichertemperatur in °C', default='90', cast=<class 'float'>, in_key=None), Field(key='Longitude', label='Longitude des Erzeugerstandortes', default='-14.4222', cast=<class 'float'>, in_key=None), Field(key='STD_Longitude', label='STD_Longitude des Erzeugerstandortes', default='15', cast=<class 'int'>, in_key=None), Field(key='Latitude', label='Latitude des Erzeugerstandortes', default='51.1676', cast=<class 'float'>, in_key=None), Field(key='East_West_collector_azimuth_angle', label='Azimuth-Ausrichtung des Kollektors in °', default='0', cast=<class 'float'>, in_key=None), Field(key='Collector_tilt_angle', label='Neigungswinkel des Kollektors in ° (0-90)', default='36', cast=<class 'float'>, in_key=None), Field(key='Tm_rl', label='Startwert Rücklauftemperatur in Speicher in °C', default='60', cast=<class 'float'>, in_key=None), Field(key='Qsa', label='Startwert Speicherfüllstand', default='0', cast=<class 'float'>, in_key=None), Field(key='Vorwärmung_K', label='Mögliche Abweichung von Solltemperatur bei Vorwärmung', default='8', cast=<class 'float'>, in_key=None), Field(key='DT_WT_Solar_K', label='Grädigkeit Wärmeübertrager Kollektor/Speicher', default='5', cast=<class 'float'>, in_key=None), Field(key='DT_WT_Netz_K', label='Grädigkeit Wärmeübertrager Speicher/Netz', default='5', cast=<class 'float'>, in_key=None)]), Section(title='Kosten', fields=[Field(key='kosten_speicher_spez', label='spez. Kosten Solarspeicher in €/m³', default='750', cast=<class 'float'>, in_key=None), Field(key='kosten_fk_spez', label='spez. Kosten Flachkollektor in €/m²', default='430', cast=<class 'float'>, in_key=None), Field(key='kosten_vrk_spez', label='spez. Kosten Vakuumröhrenkollektor in €/m²', default='590', cast=<class 'float'>, in_key=None)]), Section(title='Optimierungsparameter', fields=[Field(key='opt_volume_min', label='Untere Grenze Speichervolumen Optimierung', default='1', cast=<class 'float'>, in_key=None), Field(key='opt_volume_max', label='Obere Grenze Speichervolumen Optimierung', default='200', cast=<class 'float'>, in_key=None), Field(key='opt_area_min', label='Untere Grenze Kollektorfläche Optimierung', default='1', cast=<class 'float'>, in_key=None), Field(key='opt_area_max', label='Obere Grenze Kollektorfläche Optimierung', default='2000', cast=<class 'float'>, in_key=None)])]
Geothermal technology dialog: schema-driven fields plus a 3D borehole-field plot.
The numeric fields come from _schemas.GEOTHERMAL via SchemaDialog;
this module only adds the matplotlib canvas and the live visualization, which
reads the relevant values from self._widgets.
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._geothermal.GeothermalDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure geothermal parameters with a live 3D borehole-field preview.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='Fläche', label='Fläche Erdsondenfeld in m²', default='100', cast=<class 'float'>, in_key=None), Field(key='Bohrtiefe', label='Bohrtiefe Sonden in m', default='100', cast=<class 'float'>, in_key=None), Field(key='Temperatur_Geothermie', label='Quelltemperatur in °C', default='10', cast=<class 'float'>, in_key=None), Field(key='Abstand_Sonden', label='Abstand Erdsonden in m', default='10', cast=<class 'float'>, in_key=None), Field(key='spez_Bohrkosten', label='spez. Bohrkosten pro Bohrmeter in €/m', default='120', cast=<class 'float'>, in_key=None), Field(key='spez_Entzugsleistung', label='spez. Entzugsleistung Untergrund in W/m', default='50', cast=<class 'float'>, in_key=None), Field(key='Vollbenutzungsstunden', label='Vollbenutzungsstunden Sondenfeld in h', default='2400', cast=<class 'float'>, in_key=None), Field(key='spezifische_Investitionskosten_WP', label='spez. Investitionskosten Wärmepumpe in €/kW', default='1000', cast=<class 'float'>, in_key=None)]
River-water heat-pump and AqvaHeat dialogs.
RiverHeatPump is schema-driven for its four plain numeric fields
(_schemas.RIVER); it adds a custom river-temperature field plus a CSV
import button and overrides getInputs to emit Temperatur_FW_WP (scalar /
array / CSV). AqvaHeat currently has no inputs (empty schema).
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._heat_pump.RiverHeatPumpDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure river heat-pump parameters with optional CSV river-temperature data.
- main_schema: list[Field | ComboField | CheckField] = [Field(key='Wärmeleistung_FW_WP', label='th. Leistung Wärmepumpe in kW', default='200', cast=<class 'float'>, in_key=None), Field(key='dT', label='Zulässige Abweichung Vorlauftemperatur Wärmepumpe von Netzvorlauftemperatur', default='0', cast=<class 'float'>, in_key=None), Field(key='spez_Investitionskosten_Flusswasser', label='spez. Investitionskosten Flusswärmenutzung', default='1000', cast=<class 'float'>, in_key=None), Field(key='spezifische_Investitionskosten_WP', label='spez. Investitionskosten Wärmepumpe', default='1000', cast=<class 'float'>, in_key=None)]
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._heat_pump.AqvaHeatDialog(tech_data: dict | None = None)[source]
Bases:
SchemaDialogConfigure AqvaHeat parameters (no inputs yet).
- main_schema: list[Field | ComboField | CheckField] = []
1D stratified thermal-storage dialog (hand-written: dynamic loss-model / fluid
sections and a collapsible advanced solver block). Moved verbatim from
_04_technology_dialogs.py; not yet schema-driven.
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
- class districtheatingsim.gui.EnergySystemTab.technology_dialogs._storage.ThermalStorage1DDialog(tech_data=None)[source]
Bases:
QWidgetDialog for configuring a 1D stratified thermal storage (ThermalStorageAdapter).
Sections: - Basic: name, volume, height, geometry, n_nodes - Temperature limits: T_min, T_max, initial_temp - Loss model: constant / split / ground (dynamic fields) - Fluid properties: water / constant (dynamic fields) - Solver (collapsible advanced section) - Costs: specific investment cost
Cost Tab Module
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
Displaying and managing cost-related data for heat generation project components.
- class districtheatingsim.gui.EnergySystemTab._05_cost_tab.CostTab(folder_manager, config_manager, parent=None)[source]
Bases:
QWidgetTab for displaying and managing cost-related data for heat generation project components.
- Signal data_added:
Signal emitted when new data is added.
- data_added
int = …, arguments: Sequence = …) -> PYQT_SIGNAL
types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.
- Type:
pyqtSignal(*types, name
- Type:
str = …, revision
- updateDefaultPath(new_base_path)[source]
Updates the default path for the project.
- Parameters:
new_base_path (str) – The new base path for the project
- initData()[source]
Initializes the data as a pandas DataFrame with an index name and calculates the Annuität.
- Returns:
DataFrame with infrastructure costs and calculated annuity values
- Return type:
pd.DataFrame
- createMainScrollArea()[source]
Creates the main scroll area for the tab and sets it to take full width and height.
- createMainLayout()[source]
Creates the main layout for the tab with adjusted spacing and margins for better alignment.
- Returns:
The main layout for the tab
- Return type:
QVBoxLayout
- addLabel(text)[source]
Adds a label to the main layout.
- Parameters:
text (str) – The text for the label
- updateInfrastructureTable()[source]
Updates the infrastructure costs table with data from the DataFrame. Ensures proper formatting and correct handling of indices.
- format_cost(value)[source]
Formats the cost value in European style with spaces as thousand separators.
- updateDataFromTable(item)[source]
Updates the DataFrame with values from the QTableWidget and recalculates Annuität.
- Parameters:
item (QTableWidgetItem) – The changed table item
- addRow()[source]
Adds a new row to the table and DataFrame, with default values and calculated Annuität. The new row is added above the summary row.
- openHeaderContextMenu(position)[source]
Opens the context menu for the vertical header.
- Parameters:
position (QPoint) – The position where the context menu should be opened
- renameHeader(row)[source]
Renames the header item at the specified row.
- Parameters:
row (int) – The row index of the header item to rename
- calc_annuität(A0, TN, f_Inst, f_W_Insp, Bedienaufwand)[source]
Calculates the annuity for a given set of parameters.
- berechneWaermenetzKosten()[source]
Opens the dialog to calculate the cost of the heating network and updates the table.
- berechneHausanschlussKosten()[source]
Opens the dialog to calculate the cost of house connection stations and updates the table.
- updateTechDataTable(tech_objects)[source]
Updates the technology data table with the given technology objects.
- Parameters:
tech_objects (list) – List of technology objects
- updateSumLabel()[source]
Updates the label displaying the total costs using the summary row from the DataFrame.
- addFigure()[source]
Creates and returns a new figure and its canvas.
- Returns:
The figure and canvas
- Return type:
- plotCostComposition()[source]
Plots the cost composition with two separate figures: a bar chart and a pie chart. Clears the diagrams before replotting.
Calculate Energy System Thread Module
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
Thread for calculating heat generation mix in district heating simulation, running calculations in a separate thread.
- districtheatingsim.gui.EnergySystemTab._06_calculate_energy_system_thread.run_energy_system_calculation(energy_system, optimize, weights)[source]
Compute the heat-generation mix on a deep copy of
energy_system.The copy is what gets mutated and returned; the input object is left untouched so the UI thread can keep reading it until the result is swapped in on the main thread (via
calculation_done). This closes the read/write race on the sharedenergy_system(BACKLOG C1). GUI-free so it is unit-testable without aQThread/ event loop.- Parameters:
energy_system – The system to compute (not mutated).
optimize – Whether to also run the SLSQP mix optimization.
weights – Optimization criteria weights (used only when
optimize).
- Returns:
[system]or, when optimizing,[system, optimized_system]— both freshly computed copies, independent of the input.- Return type:
- class districtheatingsim.gui.EnergySystemTab._06_calculate_energy_system_thread.CalculateEnergySystemThread(energy_system, optimize, weights)[source]
Bases:
QThreadThread for calculating heat generation mix.
- Signal calculation_done:
Emitted when calculation is done.
- Signal calculation_error:
Emitted when error occurs during calculation.
- calculation_done
int = …, arguments: Sequence = …) -> PYQT_SIGNAL
types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.
- Type:
pyqtSignal(*types, name
- Type:
str = …, revision
- calculation_error
int = …, arguments: Sequence = …) -> PYQT_SIGNAL
types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.
- Type:
pyqtSignal(*types, name
- Type:
str = …, revision
- stop()[source]
Request the thread to stop and block until it has finished.
calculate_mixis not cooperatively interruptible, so this waits for the current run to complete (rather than killing it mid-computation) — enough to avoid emitting into a destroyed widget on close, consistent with the other worker threads.
Results Tab Module
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
Displaying results of energy system calculations with diagrams and tables, including stack plots, pie charts, and result tables.
- class districtheatingsim.gui.EnergySystemTab._07_results_tab.ResultsTab(data_manager, parent=None)[source]
Bases:
QWidgetA QWidget subclass representing the ResultsTab.
- data_added
A signal that emits data as an object.
- Type:
pyqtSignal
- data_manager
An instance of the DataManager class for managing data.
- Type:
- parent
The parent widget.
- Type:
QWidget
- data_added
int = …, arguments: Sequence = …) -> PYQT_SIGNAL
types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.
- Type:
pyqtSignal(*types, name
- Type:
str = …, revision
- __init__(data_manager, parent=None)[source]
Initializes the ResultsTab.
- Parameters:
data_manager (DataManager) – The data manager
parent (QWidget or None) – The parent widget
- updateDefaultPath(new_base_path)[source]
Updates the default base path.
- Parameters:
new_base_path (str) – The new base path
- setupCollapsibleResultsSections()[source]
Sets up the collapsible sections for displaying results tables.
- setupResultsTable()[source]
Sets up the results table with additional columns for operational hours and starts.
- adjustTableSize(table)[source]
Adjusts the size of the table to fit its contents.
- Parameters:
table (QTableWidget) – The table to adjust
- updateResults(energy_system)[source]
Updates the results in the ResultsTab.
- Parameters:
energy_system (EnergySystem) – The energy system instance containing results
- showResultsInTable()[source]
Displays the results in the results table, including calculated operational metrics. Resets the table rows before populating to avoid leftover rows from previous calculations.
- showAdditionalResultsTable()[source]
Displays the additional results in the additional results table.
- plotStorage()[source]
Draws the 4-panel network storage overview plot. Hidden when no ThermalStorageAdapter is attached to the energy system.
Sensitivity Tab Module
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
Performing sensitivity analysis on heat generation costs based on varying parameters, with 3D visualization.
- class districtheatingsim.gui.EnergySystemTab._08_sensitivity_tab.SensitivityTab(data_manager, parent=None)[source]
Bases:
QWidgetA QWidget subclass representing the SensitivityTab.
- data_added
A signal that emits data as an object.
- Type:
pyqtSignal
- data_manager
An instance of the DataManager class for managing data.
- Type:
- parent
The parent widget.
- Type:
QWidget
- data_added
int = …, arguments: Sequence = …) -> PYQT_SIGNAL
types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.
- Type:
pyqtSignal(*types, name
- Type:
str = …, revision
- __init__(data_manager, parent=None)[source]
Initializes the SensitivityTab.
- Parameters:
data_manager (DataManager) – The data manager
parent (QWidget or None) – The parent widget
- updateDefaultPath(new_base_path)[source]
Updates the default base path.
- Parameters:
new_base_path (str) – The new base path
- createRangeInputField(label_text, unit_text, ll=10, ul=50, nP=5)[source]
Creates a range input field for sensitivity analysis.
- parse_range(layout)[source]
Parses the range input fields and returns the range values.
- Parameters:
layout (QVBoxLayout) – The layout containing the input fields
- Returns:
The lower limit, upper limit, and number of points if valid, otherwise None
- Return type:
tuple or None
Sankey Dialog Module
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
Displaying Sankey diagram using Plotly to visualize energy flows in district heating systems.
- class districtheatingsim.gui.EnergySystemTab._09_sankey_dialog.SankeyDialog(results=None, parent=None)[source]
Bases:
QDialogDialog to display a Sankey diagram using Plotly in a QWebEngineView.
Energy System Tab Utilities Module
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
Utility classes for Energy System Tab, including collapsible sections, checkable combo boxes, and custom JSON encoding.
- class districtheatingsim.gui.EnergySystemTab._10_utilities.CheckableComboBox(parent=None)[source]
Bases:
QComboBoxCombo box that allows multiple items to be checked.
- __init__(parent=None)[source]
Initialize the CheckableComboBox.
- Parameters:
parent (QWidget) – Parent widget.
- handleItemPressed(index)[source]
Handle item pressed event to toggle check state.
- Parameters:
index (QModelIndex) – Index of the pressed item.
- addItem(text, data=None)[source]
Add item to combo box.
- Parameters:
text (str) – Item text.
data (Any) – Associated data.
- addItems(texts)[source]
Add multiple items to combo box.
- Parameters:
texts (list) – List of item texts to add.
- class districtheatingsim.gui.EnergySystemTab._10_utilities.CollapsibleHeader(title, content_widget)[source]
Bases:
QWidget
Generator Schematic Module
- author:
Dipl.-Ing. (FH) Jonas Pfeiffer
Custom QGraphicsScene and QGraphicsView for generator schematic editor with custom items and connections.
- class districtheatingsim.gui.EnergySystemTab._11_generator_schematic.CustomGraphicsView(scene)[source]
Bases:
QGraphicsView- resizeEvent(event)[source]
Ensures the scene fits into the view whenever the window is resized.
- Parameters:
event (QResizeEvent) – The resize event
- wheelEvent(event)[source]
Handles zooming with mouse wheel.
- Parameters:
event (QWheelEvent) – The wheel event
- class districtheatingsim.gui.EnergySystemTab._11_generator_schematic.CustomGraphicsScene(x, y, width, height, parent=None)[source]
Bases:
QGraphicsScene- mouse_position_changed
int = …, arguments: Sequence = …) -> PYQT_SIGNAL
types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.
- Type:
pyqtSignal(*types, name
- Type:
str = …, revision
- class districtheatingsim.gui.EnergySystemTab._11_generator_schematic.SchematicScene(width, height, parent=None)[source]
Bases:
CustomGraphicsScene- GRID_SIZE = 1
- GENERATOR_SPACING = 100
- GENERATOR_SPACING_STORAGE = 100
- LINE_Y_OFFSET_GENERATOR = 100
- GENERATOR_X_START = 20
- LINE_THICKNESS = 3
- FLOW_LINE_COLOR = 7
- RETURN_LINE_COLOR = 9
- TEXT_FONT = <PyQt6.QtGui.QFont object>
- OBJECTS = {'Aqva Heat Pump': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-25.0, -25.0, 50.0, 50.0), 'shape': 'rect'}, 'Biomass Boiler': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-25.0, -20.0, 50.0, 40.0), 'shape': 'rect'}, 'CHP': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-30.0, -15.0, 60.0, 30.0), 'shape': 'rect'}, 'Consumer': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-30.0, -15.0, 60.0, 30.0), 'shape': 'rect'}, 'Gas Boiler': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-25.0, -25.0, 50.0, 50.0), 'shape': 'rect'}, 'Geothermal Heat Pump': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-25.0, -25.0, 50.0, 50.0), 'shape': 'rect'}, 'Power-to-Heat': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-25.0, -25.0, 50.0, 50.0), 'shape': 'rect'}, 'River Heat Pump': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-25.0, -25.0, 50.0, 50.0), 'shape': 'rect'}, 'Seasonal Thermal Storage': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-30.0, -20.0, 60.0, 40.0), 'shape': 'trapezoid'}, 'Solar': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-20.0, -20.0, 40.0, 40.0), 'shape': 'circle'}, 'Storage': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-20.0, -40.0, 40.0, 80.0), 'shape': 'rect'}, 'Waste Heat Pump': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-25.0, -25.0, 50.0, 50.0), 'shape': 'rect'}, 'Wood-CHP': {'color': <PyQt6.QtGui.QColor object>, 'counter': 0, 'geometry': PyQt6.QtCore.QRectF(-30.0, -20.0, 60.0, 40.0), 'shape': 'rect'}}
- update_scene_size()[source]
Updates the scene size dynamically based on the positions of all items.
- update_selected_item()[source]
Updates the selected object when the selection in the scene changes.
- snap_to_grid(position)[source]
Snaps the given position to the nearest grid point.
- Parameters:
position (QPointF) – The position to snap
- Returns:
The snapped position
- Return type:
QPointF
- create_parallel_lines()[source]
Creates or updates the parallel Vorlauf (red) and Rücklauf (blue) lines and adds labels.
- update_parallel_labels(start_x, end_x)[source]
Updates the labels for the Vorlauf and Rücklauf lines dynamically.
- add_generator(item_type, item_name, connect_to_lines=True)[source]
Adds a generator at a fixed position and optionally connects it to the parallel lines.
- Parameters:
- Returns:
The created generator component
- Return type:
- add_storage(position, item_type='Storage', item_name='Speicher')[source]
Helper function to create and add a storage unit with custom geometry.
- Parameters:
- Returns:
The created storage component
- Return type:
- add_generator_with_storage(item_name, name)[source]
Adds a generator and a storage unit, connecting them and the storage to the consumer.
- Parameters:
- Returns:
The created generator component
- Return type:
- add_consumer_net(item_type, item_name='Wärmenetz', connect_to_lines=False)[source]
Adds the consumer (network).
- add_seasonal_storage(item_type='Seasonal Thermal Storage', item_name='Speicher', connect_to_lines=True)[source]
Adds a seasonal storage unit at a fixed position and optionally connects it to the parallel lines.
- Parameters:
- Returns:
The created storage component
- Return type:
- check_label_collision(new_label_rect)[source]
Checks if a new label would collide with existing component labels.
- Parameters:
new_label_rect (QRectF) – Rectangle of the new label
- Returns:
True if collision detected, False otherwise
- Return type:
- find_optimal_label_position(item, label)[source]
Finds optimal position for label to avoid collisions.
- Parameters:
item (ComponentItem) – The component item
label (QGraphicsTextItem) – The label to position
- Returns:
The optimal position
- Return type:
QPointF
- update_all_label_positions()[source]
Updates positions of all component labels to avoid collisions.
- update_label(item, new_text)[source]
Updates the label of a given item with new text.
- Parameters:
item (ComponentItem) – The component item
new_text (str) – The new label text
- connect_generator_to_storage(generator, storage)[source]
Connects two items (generator, storage, or consumer) using their connection points.
- Parameters:
generator (ComponentItem) – The generator component
storage (ComponentItem) – The storage component
- connect_items_to_lines(component, is_storage=False)[source]
Connects a component to the parallel Vorlauf (red) and Rücklauf (blue) lines.
- Parameters:
component (ComponentItem) – The component to connect
is_storage (bool) – Whether the component is a storage unit
- add_component(item_name, name, storage=False)[source]
Adds a component (generator or storage) to the scene.
- delete_selected()[source]
Delete the selected component (and its linked storage/generator partner), together with the pipes and label attached to them.
Only the affected items are removed; every other component keeps its manually-arranged position. (Previously this tore the whole scene down with
delete_all()and re-added the survivors, which reset all positions.)
- delete_all()[source]
Deletes all components, pipes, and resets all counters except for the consumer and its connections.
- is_connected_to_consumer(item)[source]
Helper method to check if a pipe is connected to the consumer.
- find_linked_generator(storage)[source]
Finds the generator linked to the given storage unit.
- Parameters:
storage (ComponentItem) – The storage component
- Returns:
The linked generator or None
- Return type:
ComponentItem or None
- find_linked_storage(generator)[source]
Finds the storage unit linked to the given generator.
- Parameters:
generator (ComponentItem) – The generator component
- Returns:
The linked storage or None
- Return type:
ComponentItem or None
- class districtheatingsim.gui.EnergySystemTab._11_generator_schematic.ComponentItem(position, item_type, item_name, color, geometry, flow_line_color=GlobalColor.red, return_line_color=GlobalColor.blue)[source]
Bases:
QGraphicsItem- __init__(position, item_type, item_name, color, geometry, flow_line_color=GlobalColor.red, return_line_color=GlobalColor.blue)[source]
Creates a general visual representation of a component.
- Parameters:
position (QPointF) – The position of the component
item_type (str) – Type of component
item_name (str) – Name of the component
color (QColor) – Color of the component
geometry (QRectF) – Geometry of the component
flow_line_color (Qt.GlobalColor) – Color for flow line
return_line_color (Qt.GlobalColor) – Color for return line
- create_connection_points()[source]
Create connection points (ports) for the item based on the shape.
- class districtheatingsim.gui.EnergySystemTab._11_generator_schematic.ConnectionPoint(parent, x_offset, y_offset, direction, color)[source]
Bases:
QGraphicsLineItem- __init__(parent, x_offset, y_offset, direction, color)[source]
Create a connection point as a short line extending from the parent item.
- class districtheatingsim.gui.EnergySystemTab._11_generator_schematic.Pipe(point1, point2, color, line_thickness)[source]
Bases:
QGraphicsPathItem- __init__(point1, point2, color, line_thickness)[source]
Create a flexible pipe (supply/return) between component and parallel lines