Source code for heatpro.external_factors.process.heating_season

import pandas as pd

[docs] def non_heating_season_basic(external_temperature: pd.Series, temperature_threshold: float, hot_day_min_share: float) -> tuple[pd.Timestamp,pd.Timestamp]: r""" Determines the beginning and end dates of the non-heating season for a district heating network. The non-heating season is defined as the longest period during which the average hourly temperature remains above a certain threshold, with a minimum share of hot days (days with average temperature above the threshold) within that period. Args: external_temperature (pd.Series): A pandas Series containing the hourly average external temperature. temperature_threshold (float): The temperature threshold above which a day is considered a hot day. hot_day_min_share (float): The minimum share of hot days required for a period to be considered part of the non-heating season. Returns: tuple[pd.Timestamp,pd.Timestamp]: A tuple containing the beginning and end dates of the non-heating season as pandas Timestamps. **Overview** We define : .. bullet list:: - :math:`(\bar{T}_{n})_{n\in\{1,\dots,365\}}` : the daily average outside temperature series (input is hourly time serie) - :math:`T_{threshold}` : the hot day temperature threshold, for :math:`n\in\{1,\dots,365\}` if :math:`\bar{T}_{n} > T_{threshold}` then day :math:`n` is a hot day, else it is a cold day - :math:`\sigma` : the minimal share of hot days the non-heating season must contain The function return :math:`n_{start},n_{end}\in\{1,\dots,365\}` defined as follow: .. math:: n_{end} - n_{start} subject to : .. math:: n_{end} > n_{start} .. math:: \sum_{n\in\{n_{start},\dots,n_{end}\}} \mathbb{1}_{\bar{T}_{n}>T_{threshold}} \geq \sigma \cdot ( n_{end} - n_{start}) :math:`n_{start},n_{end}` are found by testing all the combinations given that days :math:`n_{start} and :math:`n_{end}` are hot days next to cold days. """ # Resample the series to daily average temperatures daily_temps = external_temperature.resample('D').mean() # Identify days where the average temperature is above the threshold hot_days = (daily_temps > temperature_threshold).astype(int) # Initialize variables to keep track of the longest period of non-heating days max_length = 0 best_start = None best_end = None # Iterate over the possible start days for start in range(len(hot_days)): if hot_days.iloc[start] == 1: # Count hot days and total days hot_day_count = 0 total_days = 0 for end in range(start, len(hot_days)): total_days += 1 if hot_days.iloc[end] == 1: hot_day_count += 1 # Check if the current period meets the hot day share requirement if hot_day_count / total_days >= hot_day_min_share: if total_days > max_length: max_length = total_days best_start = start best_end = end if best_start is not None and best_end is not None: return daily_temps.index[best_start], daily_temps.index[best_end] else: return None, None