# Calculate the start and end dates for the dataframe
start_date = pd.to_datetime('2022-01-03')
end_date = start_date + pd.offsets.MonthEnd(12)

# Filter 'wind_power_TN_sum' for the current month
wind_power_tso_sum.index = pd.to_datetime(wind_power_tso_sum.index)

# Convert index of 'wind_power_tso_sum' DataFrame to Timestamp type
wind_power_tso_sum_filtered = wind_power_tso_sum.loc[start_date:end_date]

# Filter 'EC_Solar_Wind' for the current month, localize index to None, and resample to hourly frequency
EC_Solar_Wind_resampled = EC_Solar_Wind.tz_localize(None).loc[start_date:end_date].resample('H').mean()


# Define names of columns
TSOs = ['TransnetBW', 'TenneT', 'Amprion', '50Hertz']
TSOs_EC = ['Wind onshore Transnet BW', 'Wind onshore Tennet', 'Wind onshore Amprion', 'Wind onshore 50Hertz']

# Summary
model_max = wind_power_tso_sum_filtered[TSOs].max()
EC_max = EC_Solar_Wind_resampled[TSOs_EC].max()
model_max_err = pd.DataFrame(model_max.values-EC_max.values)
model_max_err.index = model_max.index

# Empty dict for errors of each TSO 
model_errors = {}
# Subplots: Looping analysis of error calculations per TSO
fig, axs = plt.subplots(2, 2, figsize=(18, 12), dpi=300)
for idx, (TSO, TSO_EC) in enumerate(zip(TSOs, TSOs_EC)):
    
    # Calculate the error between the wind powers
    model_TSO = wind_power_tso_sum_filtered[TSO]
    EC_TSO = EC_Solar_Wind_resampled[TSO_EC] 
    
    model_error = abs(model_TSO - EC_TSO)  # absolute error 
    precent_err = (model_error / EC_TSO) * 100  # percentage error 
    
    model_errors[TSO] = {'Maximum Error': model_error.max(),
                         'Minimum Error': model_error.min(),
                         'Mean Absolute Error': model_error.mean(),
                         'Mean Square Error' : ((model_TSO - EC_TSO) ** 2).mean(),
                         'Root Mean Square Error': np.sqrt((((model_TSO - EC_TSO) ** 2).mean()))
                        }
    
    max_power = max(model_TSO.max(), EC_TSO.max())
    range_value = round(max_power / 24, 1)
    num_ranges = int(max_power / range_value) + 1
    
    mismatch_ranges = [(i * range_value, (i + 1) * range_value) for i in range(num_ranges)]
    mismatch_sums = []
    
    for start, end in mismatch_ranges:
        mask = (model_TSO >= start) & (model_TSO < end)
        mismatch_sums.append(model_error[mask].mean())
    
    x_labels = [f'{round(start, 2)} - {round(end, 2)}' for start, end in mismatch_ranges]
    x_pos = range(len(x_labels))
    
    # Define color palette based on the values of mismatch_sums
    color_map = cm.get_cmap('autumn').reversed()
    
    # Calculate the minimum and maximum values of mismatch_sums
    min_value = min(mismatch_sums)
    max_value = max(mismatch_sums)
    
    # Adjust the range for desired color intensity between 0.5 and 1
    adjusted_min = min_value - (max_value) * 0.5
    adjusted_max = max_value
    
    # Normalize the values within the adjusted range
    norm = plt.Normalize(adjusted_min, adjusted_max)
    colors = color_map(norm(mismatch_sums))
    
    # Plot the subplot
    ax = axs[idx // 2, idx % 2]  # Get the appropriate subplot axes
    ax.bar(x_pos, mismatch_sums, align='center', alpha=0.9, color=colors)
    ax.set_xticks(x_pos)
    ax.set_xticklabels(x_labels, fontsize=12, rotation=90)
    # ax.set_yticks(fontsize=12)
    
    if idx in [0, 2]:  # Leftmost subplots
        ax.set_ylabel('Sum of Absolute Error (GW)', fontsize=14)
    if idx in [2, 3]:  # Bottom subplots
        ax.set_xlabel('Power Range (GW)', fontsize=14)
    
    ax.set_title(f'Model vs. {TSO}', fontsize=16)
    ax.grid(axis='y')
    ax.margins(0.05)


# Add a title for the entire plot
fig.suptitle('Mean Absolute Error: Model vs. TSO - Onshore Wind Power 2022', fontsize=18)

# Adjust the spacing between subplots
plt.tight_layout(rect=[0, 0, 1, 0.96])

# Save the figure
# plt.savefig(dirname+'\output\Wind_Power_Analysis_TSO_V01\Avg_Error_Onshore_Model_vs_TSOs_2022.png', dpi=300, bbox_inches='tight')

# Show the figure
plt.show()


Change the code to to generate plots for mean, max, min, and sum instead of just model_error[mask].mean()