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: QWidget

Main 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.

Parameters:
  • folder_manager (object) – Folder manager instance.

  • data_manager (object) – Data manager instance.

  • config_manager (object) – Configuration manager instance.

  • parent (QWidget) – Parent widget.

initDialogs()[source]

Initialize dialogs for economic parameters.

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).

initUI()[source]

Initialize user interface components.

createMainScrollArea()[source]

Create main scroll area for the tab.

createMenu()[source]

Create menu bar for the tab.

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

createTabs()[source]

Create tab widget and its sub-tabs.

createProgressBar()[source]

Create progress bar for calculation progress.

createConfigBar()[source]

Create the energy config selector bar (ComboBox + action buttons).

createMainLayout()[source]

Create main layout for the tab.

Returns:

Main layout.

Return type:

QVBoxLayout

setupParameters()[source]

Set up economic parameters.

updateEconomicParameters()[source]

Update economic parameters from dialog.

openEconomicParametersDialog()[source]

Open economic parameters dialog.

validateInputs()[source]

Validate inputs for calculation.

Returns:

True if inputs are valid, False otherwise.

Return type:

bool

preprocessData()[source]

Preprocess data before calculation.

calculate_energy_system(optimize=False, weights=None)[source]

Start calculation process.

Parameters:
  • optimize (bool) – Whether to optimize the calculation.

  • weights (dict) – Weights for optimization.

start_optimization()[source]

Open optimization dialog and start optimization process.

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.

stop_threads()[source]

Stop the running calculation thread (called from the main window on close).

process_data()[source]
sensitivity(gas_range, electricity_range, wood_range, weights=None)[source]

Perform sensitivity analysis over a range of prices.

Parameters:
  • gas_range (tuple) – Range of gas prices (lower, upper, num_points).

  • electricity_range (tuple) – Range of electricity prices (lower, upper, num_points).

  • wood_range (tuple) – Range of wood prices (lower, upper, num_points).

  • weights (dict) – Weights for optimization.

generate_values(price_range)[source]

Generate values within a specified range.

Parameters:

price_range (tuple) – Price range (lower, upper, num_points).

Returns:

Generated values within the range.

Return type:

list

calculate_sensitivity(gas_price, electricity_price, wood_price, weights)[source]

Calculate energy mix for given prices and weights.

Parameters:
  • gas_price (float) – Gas price.

  • electricity_price (float) – Electricity price.

  • wood_price (float) – Wood price.

  • weights (dict) – Weights for optimization.

Returns:

Calculation results.

Return type:

dict

show_sankey()[source]

Show Sankey diagram of energy flows.

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.

save_results_JSON(show_dialog=True)[source]

Save results and technology objects to the active config JSON file.

Parameters:

show_dialog (bool) – Whether to show dialogs.

load_results_JSON(show_dialog=True)[source]

Load EnergySystem from the active config JSON file.

Parameters:

show_dialog (bool) – Whether to show success/error 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: QDialog

Dialog for inputting economic parameters.

__init__(parent=None)[source]

Initialize the EconomicParametersDialog.

Parameters:

parent (QWidget) – Parent widget.

initUI()[source]

Initialize user interface components.

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:

dict

updateValues(new_values)[source]

Update default values and reload them into input fields.

Parameters:

new_values (dict) – Dictionary containing new values.

connectSignals()[source]

Connect input field signals to validation method.

validateInput()[source]

Validate input fields and update plot if valid.

showErrorMessage(message)[source]

Show error message dialog.

Parameters:

message (str) – Message to display.

plotPriceDevelopment()[source]

Plot price development of energy carriers over time.

class districtheatingsim.gui.EnergySystemTab._02_energy_system_dialogs.KostenBerechnungDialog(parent=None, label=None, value=None, type=None)[source]

Bases: QDialog

Dialog for calculating costs based on a geoJSON file.

__init__(parent=None, label=None, value=None, type=None)[source]

Initialize the KostenBerechnungDialog.

Parameters:
  • parent (QWidget) – Parent widget.

  • label (str) – Label for specific cost input field.

  • value (str) – Default value for specific cost input field.

  • type (str) – Type of cost calculation.

initUI()[source]

Initialize user interface components.

onAccept()[source]

Read unified GeoJSON file and calculate total cost based on input values.

class districtheatingsim.gui.EnergySystemTab._02_energy_system_dialogs.WeightDialog[source]

Bases: QDialog

Dialog for setting weights for optimization.

__init__()[source]

Initialize the WeightDialog.

get_weights()[source]

Get weights from input fields.

Returns:

Dictionary with weights for heat generation costs, CO2 emissions, and primary energy factor.

Return type:

dict

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: QListWidget

Custom list widget with drag-drop functionality for technology ordering.

__init__(parent=None)[source]
dropEvent(event)[source]

Handle drop event to update technology object order.

Parameters:

event (QDropEvent) – Drop event.

class districtheatingsim.gui.EnergySystemTab._03_technology_tab.TechnologyTab(data_manager, config_manager, parent=None)[source]

Bases: QWidget

Tab 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

__init__(data_manager, config_manager, parent=None)[source]

Initialize the TechnologyTab.

Parameters:
  • data_manager (object) – Data manager instance.

  • config_manager (object) – Configuration manager instance.

  • parent (QWidget) – Parent widget.

initFileInputs()[source]

Initialize file input widgets.

updateDefaultPath(new_base_path)[source]

Update default path for file inputs.

Parameters:

new_base_path (str) – New base path.

initUI()[source]

Initialize UI components.

createMainScrollArea()[source]

Create main scroll area.

setupFileInputs()[source]

Set up file input widgets and layout.

addLabel(text)[source]

Add label to main layout.

Parameters:

text (str) – Label text.

on_selectFileButton_clicked()[source]

Handle select file button click event.

setupScaleFactor()[source]

Set up scale factor input widgets and layout.

addHorizontalLayout(*widgets)[source]

Add horizontal layout with given widgets to main layout.

Parameters:

widgets (tuple) – Widgets to add to horizontal layout.

addButtonLayout()[source]

Add button layout for managing technologies.

setupTechnologySelection()[source]

Set up technology selection widgets and layout.

createTechnology(tech_type, inputs)[source]

Create technology object based on type and inputs.

Parameters:
  • tech_type (str) – Technology type.

  • inputs (dict) – Technology inputs.

Returns:

Created technology object.

Return type:

Technology

addTech(tech_type, tech_data)[source]

Add new technology to list.

Parameters:
  • tech_type (str) – Technology type.

  • tech_data (dict) – Technology data.

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.

rebuildScene()[source]

Rebuild entire scene by adding all remaining technologies.

updateTechNames(tech_type)[source]

Update names and labels of remaining objects of a technology class.

Parameters:

tech_type (str) – Technology type.

removeTech()[source]

Remove all technologies from list.

updateTechList()[source]

Update technology list display.

updateTechObjectsOrder()[source]

Update order of technology objects based on list display.

formatTechForDisplay(tech)[source]

Delegate formatting of display text to technology object.

Parameters:

tech (Technology) – Technology object.

Returns:

Formatted string for display.

Return type:

str

createMainLayout()[source]

Create main layout for TechnologyTab.

Returns:

Main layout.

Return type:

QVBoxLayout

setupPlotAndSchematic()[source]

Set up plot area and schematic scene area.

createPlotCanvas()[source]

Create plot canvas for displaying graphs.

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.

showInfoMessageOnPlot(message)[source]

Display information message on plot canvas with modern styling.

Parameters:

message (str) – Message to display.

addTechToScene(tech)[source]

Add technology to SchematicScene and store reference in tech object.

Parameters:

tech (object) – Technology object.

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: QDialog

Dialog for inputting technology-specific data based on technology type.

__init__(tech_type, tech_data=None)[source]

Initialize TechInputDialog with technology type and data.

Parameters:
  • tech_type (str) – Technology type.

  • tech_data (dict) – Technology data.

initUI()[source]

Initializes the user interface for the dialog.

accept()[source]

Accept dialog and retrieve input data from specific technology dialog.

getInputs()[source]

Retrieves the input data from the dialog.

Returns:

The input data

Return type:

dict

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: object

A single text-input row mapping a tech_data key 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 (float by default; e.g. int for 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 reads th_Leistung_kW but writes thermal_capacity_kW). Defaults to key.

key: str
label: str
default: str
cast

alias of float

in_key: str | None = None
property read_key: str
__init__(key: str, label: str, default: str, cast: Callable = <class 'float'>, in_key: str | None = None) None
class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.CheckField(key: str, label: str, default: bool = False)[source]

Bases: object

A checkbox row producing a bool in getInputs().

key: str
label: str
default: bool = False
__init__(key: str, label: str, default: bool = False) None
class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.SchemaDialog(tech_data: dict | None = None)[source]

Bases: QWidget

Base widget that builds itself from a declarative field schema.

Subclasses set class attributes:

  • main_schema: flat list of Field / ComboField / CheckField (rendered in a single form).

  • sections: alternatively, a list of Section rendered as titled group boxes. When set it takes precedence over main_schema.

  • storage_schema: optional list of Field rendered in a side panel whose visibility is toggled by the storage_toggle_key checkbox; its keys are only included in getInputs() 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] = []
sections: list[Section] | None = None
storage_schema: list[Field] | None = None
storage_toggle_key: str = 'speicher_aktiv'
title: str = ''
__init__(tech_data: dict | None = None)[source]
getInputs() dict[source]

Collect the field values into a tech_data dict.

class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.GasBoilerDialog(tech_data: dict | None = None)[source]

Bases: SchemaDialog

Configure gas-boiler parameters.

title: str = 'Eingabe für Gaskessel'
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: SchemaDialog

Configure Power-to-Heat parameters.

title: str = 'Eingabe für Power-to-Heat'
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: SchemaDialog

Configure 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: SchemaDialog

Configure biomass-boiler parameters with optional buffer storage.

title: str = 'Eingabe für Biomassekessel'
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: SchemaDialog

Configure 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: SchemaDialog

Configure 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: SchemaDialog

Configure 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)])]
updateVisualization()[source]

Updates the visualization of the collector orientation.

class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.GeothermalDialog(tech_data: dict | None = None)[source]

Bases: SchemaDialog

Configure 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)]
updateVisualization()[source]

Updates the 3D visualization of the borehole configuration.

class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.RiverHeatPumpDialog(tech_data: dict | None = None)[source]

Bases: SchemaDialog

Configure 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)]
openCSV()[source]

Opens a file dialog to select a CSV file and loads its content.

loadCSV(filename)[source]

Loads temperature data from a CSV file.

Parameters:

filename (str) – The path to the CSV file

getInputs()[source]

Retrieves the input values, resolving the river temperature from the CSV import, an existing array, or the scalar field.

class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.AqvaHeatDialog(tech_data: dict | None = None)[source]

Bases: SchemaDialog

Configure AqvaHeat parameters (no inputs yet).

main_schema: list[Field | ComboField | CheckField] = []
class districtheatingsim.gui.EnergySystemTab._04_technology_dialogs.ThermalStorage1DDialog(tech_data=None)[source]

Bases: QWidget

Dialog 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

__init__(tech_data=None)[source]
getInputs() dict[source]

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: object

A single text-input row mapping a tech_data key 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 (float by default; e.g. int for 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 reads th_Leistung_kW but writes thermal_capacity_kW). Defaults to key.

key: str
label: str
default: str
cast

alias of float

in_key: str | None = None
property read_key: str
__init__(key: str, label: str, default: str, cast: Callable = <class 'float'>, in_key: str | None = None) None
class districtheatingsim.gui.EnergySystemTab.technology_dialogs._base.ComboField(key: str, label: str, options: list[str], default: str)[source]

Bases: object

A dropdown row producing the selected option string in getInputs().

key: str
label: str
options: list[str]
default: str
__init__(key: str, label: str, options: list[str], default: str) None
class districtheatingsim.gui.EnergySystemTab.technology_dialogs._base.CheckField(key: str, label: str, default: bool = False)[source]

Bases: object

A checkbox row producing a bool in getInputs().

key: str
label: str
default: bool = False
__init__(key: str, label: str, default: bool = False) None
class districtheatingsim.gui.EnergySystemTab.technology_dialogs._base.Section(title: str, fields: list[Field | ComboField | CheckField])[source]

Bases: object

A titled QGroupBox grouping a set of fields (purely a layout container).

title: str
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: QWidget

Base widget that builds itself from a declarative field schema.

Subclasses set class attributes:

  • main_schema: flat list of Field / ComboField / CheckField (rendered in a single form).

  • sections: alternatively, a list of Section rendered as titled group boxes. When set it takes precedence over main_schema.

  • storage_schema: optional list of Field rendered in a side panel whose visibility is toggled by the storage_toggle_key checkbox; its keys are only included in getInputs() 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] = []
sections: list[Section] | None = None
storage_schema: list[Field] | None = None
storage_toggle_key: str = 'speicher_aktiv'
title: str = ''
__init__(tech_data: dict | None = None)[source]
getInputs() dict[source]

Collect the field values into a tech_data dict.

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: QDialog

Dialog for inputting technology-specific data based on technology type.

__init__(tech_type, tech_data=None)[source]

Initialize TechInputDialog with technology type and data.

Parameters:
  • tech_type (str) – Technology type.

  • tech_data (dict) – Technology data.

initUI()[source]

Initializes the user interface for the dialog.

accept()[source]

Accept dialog and retrieve input data from specific technology dialog.

getInputs()[source]

Retrieves the input data from the dialog.

Returns:

The input data

Return type:

dict

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: SchemaDialog

Configure gas-boiler parameters.

title: str = 'Eingabe für Gaskessel'
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: SchemaDialog

Configure Power-to-Heat parameters.

title: str = 'Eingabe für Power-to-Heat'
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: SchemaDialog

Configure 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: SchemaDialog

Configure biomass-boiler parameters with optional buffer storage.

title: str = 'Eingabe für Biomassekessel'
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: SchemaDialog

Configure 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: SchemaDialog

Configure 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: SchemaDialog

Configure 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)])]
updateVisualization()[source]

Updates the visualization of the collector orientation.

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: SchemaDialog

Configure 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)]
updateVisualization()[source]

Updates the 3D visualization of the borehole configuration.

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: SchemaDialog

Configure 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)]
openCSV()[source]

Opens a file dialog to select a CSV file and loads its content.

loadCSV(filename)[source]

Loads temperature data from a CSV file.

Parameters:

filename (str) – The path to the CSV file

getInputs()[source]

Retrieves the input values, resolving the river temperature from the CSV import, an existing array, or the scalar field.

class districtheatingsim.gui.EnergySystemTab.technology_dialogs._heat_pump.AqvaHeatDialog(tech_data: dict | None = None)[source]

Bases: SchemaDialog

Configure 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: QWidget

Dialog 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

__init__(tech_data=None)[source]
getInputs() dict[source]

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: QWidget

Tab 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

__init__(folder_manager, config_manager, parent=None)[source]

Initializes the CostTab instance.

Parameters:
  • folder_manager (object) – Reference to the folder manager instance

  • config_manager (object) – Reference to the config manager instance

  • parent (QWidget or None) – Reference to the parent widget

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

initUI()[source]

Initializes the user interface components for the CostTab.

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

setupInfrastructureCostsTable()[source]

Sets up the infrastructure costs table.

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.

Parameters:

value (float) – The cost value

Returns:

Formatted cost string

Return type:

str

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.

removeRow()[source]

Removes the selected row from the table and DataFrame.

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.

Parameters:
  • A0 (float) – Initial investment cost

  • TN (int) – Lifetime of the investment

  • f_Inst (float) – Installation factor

  • f_W_Insp (float) – Maintenance and inspection factor

  • Bedienaufwand (float) – Operating effort

Returns:

The calculated annuity

Return type:

float

updateSummaryRow()[source]

Recalculates the summary row and appends it to the DataFrame.

updateTableValue(row, column, value)[source]

Updates the value in the specified table cell.

Parameters:
  • row (int) – The row index

  • column (int) – The column index

  • value (Any) – The value to set

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.

setupTechDataTable()[source]
updateTechDataTable(tech_objects)[source]

Updates the technology data table with the given technology objects.

Parameters:

tech_objects (list) – List of technology objects

addSummaryTechCosts()[source]

Adds a summary row for the technology costs.

updateSumLabel()[source]

Updates the label displaying the total costs using the summary row from the DataFrame.

setupCostCompositionChart()[source]

Sets up two separate figures for the bar chart and pie chart.

addFigure()[source]

Creates and returns a new figure and its canvas.

Returns:

The figure and canvas

Return type:

tuple

plotCostComposition()[source]

Plots the cost composition with two separate figures: a bar chart and a pie chart. Clears the diagrams before replotting.

adjustTableSize(table)[source]

Adjusts the size of the table to fit its contents.

Parameters:

table (QTableWidget) – The table to adjust

totalCostLabel()[source]

Returns the total cost label.

Returns:

The total cost label

Return type:

QLabel

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 shared energy_system (BACKLOG C1). GUI-free so it is unit-testable without a QThread / 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:

list

class districtheatingsim.gui.EnergySystemTab._06_calculate_energy_system_thread.CalculateEnergySystemThread(energy_system, optimize, weights)[source]

Bases: QThread

Thread 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

__init__(energy_system, optimize, weights)[source]

Initialize the CalculateEnergySystemThread.

Parameters:
  • energy_system (object) – Energy system to calculate.

  • optimize (bool) – Whether to optimize the mix.

  • weights (dict) – Weights for optimization criteria.

run()[source]

Run heat generation mix calculation.

stop()[source]

Request the thread to stop and block until it has finished.

calculate_mix is 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: QWidget

A 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:

DataManager

parent

The parent widget.

Type:

QWidget

results

A dictionary to store results.

Type:

dict

selected_variables

A list of selected variables for plotting.

Type:

list

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

initUI()[source]

Initializes the UI components of the ResultsTab.

setupDiagrams()[source]

Sets up the collapsible diagrams for the ResultsTab.

setupCollapsibleResultsSections()[source]

Sets up the collapsible sections for displaying results tables.

addLabel(text)[source]

Adds a label to the layout.

Parameters:

text (str) – The text for the label

setupResultsTable()[source]

Sets up the results table with additional columns for operational hours and starts.

setupAdditionalResultsTable()[source]

Sets up the additional results table.

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.

plotResults()[source]

Plots the results in the diagrams.

updateSelectedVariables()[source]

Updates the selected variables and re-plots the diagram.

plotStorage()[source]

Draws the 4-panel network storage overview plot. Hidden when no ThermalStorageAdapter is attached to the energy system.

plotBufferStorages()[source]

Dynamically create/update one 4-panel collapsible section per generator that has an active buffer storage (CHP, BiomassBoiler with speicher_aktiv=True). Old sections are destroyed and rebuilt on each call.

updatePieChart()[source]

Updates the pie chart with results from the EnergySystem.

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: QWidget

A 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:

DataManager

parent

The parent widget.

Type:

QWidget

results

A dictionary to store results.

Type:

dict

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

initUI()[source]

Initializes the UI components of the SensitivityTab.

createInputFields()[source]

Creates the input fields for sensitivity analysis ranges.

createRangeInputField(label_text, unit_text, ll=10, ul=50, nP=5)[source]

Creates a range input field for sensitivity analysis.

Parameters:
  • label_text (str) – The text for the label

  • unit_text (str) – The text for the unit label

  • ll (int or float) – The lower limit

  • ul (int or float) – The upper limit

  • nP (int) – The number of points

Returns:

The layout containing the input fields

Return type:

QVBoxLayout

createPlotArea()[source]

Creates the plot area for displaying graphs.

start_sensitivity_analysis()[source]

Starts the sensitivity analysis based on the input ranges.

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

plotSensitivity(results)[source]

Plots the sensitivity analysis results.

Parameters:

results (list) – The results of the sensitivity analysis

plotSensitivitySurface(results)[source]

Plots the sensitivity analysis results as a surface plot.

Parameters:

results (list) – The results of the sensitivity analysis

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: QDialog

Dialog to display a Sankey diagram using Plotly in a QWebEngineView.

__init__(results=None, parent=None)[source]
initUI()[source]

Initialize the Sankey dialog UI and display the Plotly diagram.

plotSankey()[source]

Generate and display a Sankey diagram using Plotly based on results data.

closeEvent(event)[source]

Clean up the temporary HTML file when the dialog is closed.

Parameters:

event (QCloseEvent) – The close event

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: QComboBox

Combo 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.

updateText()[source]

Update displayed text to show checked items.

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.

setItemChecked(text, checked=True)[source]

Set check state of an item.

Parameters:
  • text (str) – Item text.

  • checked (bool) – Check state.

clear()[source]

Clear all items from combo box.

checkedItems()[source]

Get list of checked items.

Returns:

List of checked items.

Return type:

list

class districtheatingsim.gui.EnergySystemTab._10_utilities.CollapsibleHeader(title, content_widget)[source]

Bases: QWidget

__init__(title, content_widget)[source]
toggle_content()[source]
sizeHint(self) QSize[source]

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

__init__(scene)[source]
fit_to_scene()[source]

Fits the entire scene into the view, considering the current window size.

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

mousePressEvent(event)[source]

Activates panning on middle mouse button press.

Parameters:

event (QMouseEvent) – The mouse press event

mouseReleaseEvent(event)[source]

Deactivates panning when middle mouse button is released.

Parameters:

event (QMouseEvent) – The mouse release 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

__init__(x, y, width, height, parent=None)[source]
mouseMoveEvent(event)[source]

Handles mouse move events in the scene.

Parameters:

event (QMouseEvent) – The mouse move event

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'}}
__init__(width, height, parent=None)[source]
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.

Parameters:
  • start_x (float) – The start x-coordinate

  • end_x (float) – The end x-coordinate

update_pipes_connected_to_lines()[source]

Updates pipes that are connected to the parallel lines.

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:
  • item_type (str) – Type of the generator (e.g., ‘CHP’, ‘Solar’)

  • item_name (str) – Unique name for the generator (e.g., ‘BHKW_1’)

  • connect_to_lines (bool) – Whether to connect to the parallel lines

Returns:

The created generator component

Return type:

ComponentItem

add_storage(position, item_type='Storage', item_name='Speicher')[source]

Helper function to create and add a storage unit with custom geometry.

Parameters:
  • position (QPointF) – The position for the storage

  • item_type (str) – Type of storage

  • item_name (str) – Name of the storage

Returns:

The created storage component

Return type:

ComponentItem

add_generator_with_storage(item_name, name)[source]

Adds a generator and a storage unit, connecting them and the storage to the consumer.

Parameters:
  • item_name (str) – Type of the generator

  • name (str) – Unique name for the generator

Returns:

The created generator component

Return type:

ComponentItem

add_consumer_net(item_type, item_name='Wärmenetz', connect_to_lines=False)[source]

Adds the consumer (network).

Parameters:
  • item_type (str) – Type of consumer

  • item_name (str) – Name of the consumer

  • connect_to_lines (bool) – Whether to connect to lines

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:
  • item_type (str) – Type of seasonal storage

  • item_name (str) – Name of the storage

  • connect_to_lines (bool) – Whether to connect to the parallel lines

Returns:

The created storage component

Return type:

ComponentItem

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:

bool

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:
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.

Parameters:
  • item_name (str) – Type of the component (e.g., ‘CHP’, ‘Solar’)

  • name (str) – Unique name for the component (e.g., ‘BHKW_1’)

  • storage (bool) – If True, add a storage with the component

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.

Parameters:

item (Pipe) – The item to check

Returns:

True if connected to consumer, False otherwise

Return type:

bool

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

boundingRect()[source]

Return the predefined geometry passed in during creation

paint(painter, option, widget=None)[source]

Draw the item with the specified shape and color.

create_connection_points()[source]

Create connection points (ports) for the item based on the shape.

create_connection_point(x_offset, y_offset, direction, color)[source]

Helper method to create a connection point at a relative position based on the bounding rectangle.

itemChange(change, value)[source]

Update connected pipes, label, and background when the component moves.

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.

update_position()[source]

Update the position of the connection point relative to the parent item and its extension line

get_end_point()[source]

Return the end point of the connection line (for pipe connections).

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

update_path()[source]

Update the pipe path to connect components to parallel lines with vertical and horizontal segments only.

check_collision(point, excluded_items=None)[source]

Check if the given point collides with any item (generator, consumer, storage)

Module contents