Files
CACER-simulator/Reporting.ipynb
2025-06-16 09:31:15 +02:00

3405 lines
139 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Cambiare policy su powershell : Set-ExecutionPolicy remotesigned\n",
"from src.Functions_General import (clear_folder_content, province_to_region, get_calendar, province_italian_to_english)\n",
"from src.Functions_Energy_Model import get_coordinates\n",
"import pandas as pd\n",
"import yaml\n",
"import plotly.graph_objects as go\n",
"import dataframe_image as dfi\n",
"import glob\n",
"from datetime import datetime\n",
"import os\n",
"from plotly.subplots import make_subplots\n",
"import numpy as np\n",
"import xlwings as xw\n",
"from pvlib import solarposition\n",
"import matplotlib.pyplot as plt\n",
"plt.ioff() # turn off interactive mode\n",
"from simple_colors import *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;4;34m\n",
"Create report:\u001b[0m \n",
"\n"
]
}
],
"source": [
"print(blue(\"\\nCreate report:\", ['bold', 'underlined']), '\\n')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"global num_graph, flag_show, detailed_report"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"config = yaml.safe_load(open(\"config.yml\", 'r'))\n",
"report_yaml = yaml.safe_load(open(config[\"filename_report\"], 'r'))\n",
"num_graph = 0\n",
"num_table = 0\n",
"flag_show = report_yaml['flag_show']\n",
"detailed_report = report_yaml['detailed_report']\n",
"name_months = ['GEN', 'FEB', 'MAR', 'APR', 'MAG', 'GIU', 'LUG', 'AGO', 'SET', 'OTT', 'NOV', 'DIC']"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"filename_CACER_energy_monthly = config['filename_CACER_energy_monthly']\n",
"foldername_graphs_energy = config['foldername_graphs_energy']\n",
"foldername_graphs = config['foldername_graphs']\n",
"foldername_result_energy = config[\"foldername_result_energy\"]\n",
"foldername_graphs_generali = config[\"foldername_graphs_generali\"]\n",
"foldername_graphs_finance = config[\"foldername_graphs_finance\"]\n",
"\n",
"day_winter = config[\"day_winter\"]\n",
"day_summer = config[\"day_summer\"]\n",
"\n",
"recap = yaml.safe_load(open(config[\"filename_recap\"], 'r'))\n",
"utenti = yaml.safe_load(open(config[\"filename_registry_users_yml\"], 'r'))\n",
"user_types = yaml.safe_load(open(config[\"filename_registry_user_types_yml\"], 'r'))\n",
"\n",
"foldername_result_finance = config[\"foldername_result_finance\"]\n",
"case_denomination = recap[\"case_denomination\"]\n",
"\n",
"charts = yaml.safe_load(open(foldername_graphs + \"layout_charts.yml\", 'r'))\n",
"col = charts[\"colors\"]\n",
"\n",
"user_set = recap[\"list_user_types\"]\n",
"user_type_list_consuming = recap[\"list_types_prosumers\"] + recap[\"list_types_consumers\"]\n",
"prosumers = recap[\"list_types_prosumers\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"All files in assets\\\\energy\\\\ folder deleted\n",
"All files in assets\\\\finance\\\\ folder deleted\n",
"All files in assets\\\\general\\\\ folder deleted\n"
]
}
],
"source": [
"# remove all pictures from previous simulations\n",
"clear_folder_content(foldername_graphs_energy)\n",
"clear_folder_content(foldername_graphs_finance)\n",
"clear_folder_content(foldername_graphs_generali)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# tale funzione consente di plottare rapidamente un grafico di tipo scatter\n",
"\n",
"def plot_scatter(x, y, title, title_y, output_file):\n",
" fig = go.Figure(go.Scatter(x=x, y=y, mode='lines'))\n",
" fig.update_layout(\n",
" title_text = title, \n",
" # xaxis = dict(title='Ora', \n",
" # rangeslider=dict(visible=True), type='date')\n",
" # )\n",
" )\n",
" fig.update_layout(plot_bgcolor='white',\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.25, xanchor=\"left\", x=0.01), \n",
" )\n",
" fig.update_yaxes(title_text = title_y)\n",
" if flag_show:\n",
" fig.show()\n",
" fig.write_html(output_file + \".html\")\n",
" fig.write_image(output_file + \".png\", width=1000, height=1200/13.2*5, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Create denomination users**"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"filename_utenze_xls = config['filename_users_CACER_xls'] # si importa il nome del file .xls contenente gli utenti da simulare (tutte le tipologie di utenza!)\n",
"\n",
"# si apre il file excel e si importa il foglio \"utenti\" in un df\n",
"app = xw.App(visible = False)\n",
"wb = xw.Book(filename_utenze_xls)\n",
"df = wb.sheets[\"Utenti\"].range('A1').options(pd.DataFrame, \n",
" header=1,\n",
" index=False, \n",
" expand='table').value\n",
"wb.close()\n",
"app.quit()\n",
"\n",
"assert len(df.user_type.unique()) == len(df.user_type), \"some user_type share the same ID!\" # si verifica che lo user ID sia unico per ogni utente\n",
"df.set_index(\"user_type\", inplace=True) # si setta lo user ID come index\n",
"df.drop(columns=[\"number_type_id\"],inplace=True) # si elimina la prima colonna\n",
"df.num = df.num.fillna(0).astype(int) # si annulla la numerosità di tutti gli utenti\n",
"\n",
"denomination_users = df.denomination.copy()\n",
"\n",
"for user in user_type_list_consuming:\n",
" denomination_users_list = []\n",
" denomination_users_list.append(denomination_users[user])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **General**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **1. Create table with all users' parameters**"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_excel(config[\"filename_users_CACER_xls\"], sheet_name=\"Utenti\") # si legge il foglio excel contenente le caratteristiche della configurazione in esame\n",
"\n",
"df = df[df[\"num\"] > 0] # togliamo le tipologie di utenti che non sono inclusi nella simulazione\n",
"df = df[df[\"flag\"] == True] # togliamo le tipologie di utenti che non sono inclusi nella simulazione\n",
"\n",
"# si eliminano dal df tutte le colonne non necessarie\n",
"df.drop(columns=[\"number_type_id\",\"flag\",\"consuming\",\"producing\",\"wind\",\"error\",\n",
" \"power_range\", \"supplier\", \"tariff\",\n",
" \"flag_cacer\", \"disbursement_month\", \"commissioning_month\", \"entry_month\", \"exit_month\", \"CP\", \"location\", \"denomination\",\n",
" \"dummy_user\", \"grant_private\", \n",
" \"new_plant\", \"pv_mounting\", \"stakeholder\", \"condominium\", \"mv_cabinet\", \"tilt_angle\", \"azimuth\"\n",
" ],inplace=True)\n",
"\n",
"# si rinominano le colonne con dei label più adatti alla stesura del report\n",
"df.rename(columns={\"user_type_id\":\"Tipo utente\", \"num\": \"Utenti\", \"type\":\"Tipologia\", \"category\":\"Categoria\",\n",
" # \"power_range\":\"Classe potenza\", \"supplier\":\"Fornitore\",\"tariff\":\"Schema tariffario\", \n",
" \"load_profile_id\":\"Tipologia carico\",\n",
" \"pv\":\"Capacità PV\", \"battery\":\"Capacità accumulo\",\n",
" # \"new_plant\":\"Nuovo impianto\",\n",
" \"funding_scheme\":\"Modello Finanziamento\",\n",
" \"grant_pnrr\":\"Fondo PNRR\",\n",
" \"debt\":\"Quota di debito\",\n",
" \"voltage\":\"Livello tensione\"}, inplace=True)\n",
"\n",
"# si definisce una funzione che assegna un colore in base alla tipologia di utente (prosumer; producer; consumer)\n",
"def color_tipologia(value):\n",
" if value == \"prosumer\":\n",
" color = col[\"arancione\"]\n",
" elif value == \"producer\":\n",
" color = col[\"blu\"]\n",
" else:\n",
" color = col[\"verde\"]\n",
" return 'color: %s' % color\n",
"\n",
"# si definisce una funzione che assegna un colore in base alla tipologia di utenza (domestico; industriale; pubblico; commerciale)\n",
"def color_categoria(value):\n",
" if value == \"domestico\":\n",
" color = col[\"rosso\"]\n",
" elif value == \"industriale\":\n",
" color = col[\"violetto\"]\n",
" elif value == \"pubblico\":\n",
" color = col[\"azzurro\"]\n",
" else: \n",
" color = col[\"marrone\"]\n",
" return 'color: %s' % color\n",
"\n",
"df.reset_index(drop=True, inplace=True)\n",
"\n",
"# si definisce una tabella riassuntiva con le principali informazioni relative alla configurazione in esame\n",
"if detailed_report:\n",
"\n",
" styled_df = df.style.format(precision=0, thousands=\".\", decimal=\",\",na_rep=\"\")\\\n",
" .set_caption(\"Tabella riassuntiva degli utenti della comunità divisi per tipologia\")\\\n",
" .format_index(str, axis=1)\\\n",
" # .applymap(color_tipologia, subset=['Tipologia'])\\\n",
" # .bar(subset=[\"Capacità PV\"], color=col[\"blu\"],vmax=sum(x if not pd.isna(x) else 0 for x in df[\"Capacità PV\"]))\\\n",
" # .bar(subset=[\"Capacità accumulo\",], color=col[\"rosso\"],vmax=sum(x if not pd.isna(x) else 0 for x in df[\"Capacità accumulo\"]))\\\n",
" # .bar(subset=[\"Utenti\"], color=col[\"giallo\"], vmax=sum(df[\"Utenti\"]))\\\n",
" # .applymap(color_categoria, subset=['Categoria'])\\\n",
" # .hide(axis=\"index\")\n",
"\n",
" # .relabel_index([\"row 1\", \"row 2\"], axis=0)\n",
" # {\":.2f\"}%})\n",
" # .hide_index() \\\n",
" # .bar(subset=[\"Tipologia\",], color='lightgreen')\n",
" # .applymap(color_tipologia, subset=['Tipologia'])\n",
"\n",
" styled_df.set_properties(subset=['Utenti'], **{'width': '80px'})\n",
" styled_df.set_properties(subset=['Capacità PV'], **{'width': '80px'})\n",
" styled_df.set_properties(subset=['Capacità accumulo'], **{'width': '60px'})\n",
" styled_df.set_properties(subset=['Livello tensione'], **{'width': '50px'})\n",
"\n",
" # si genera e si salva la tabella definita sopra\n",
" title = 'CACER_users_table.png'\n",
"\n",
" # ATTENTION: the following line stopped working due to library issues\n",
" # https://stackoverflow.com/questions/75687844/problem-with-dataframe-image-no-such-file-or-directory-appdata-local-tem\n",
" # dfi.export(styled_df, foldername_graphs_generali + str(num_table) + \"_\" + title dpi = 550) # This only works for styled dataframes\n",
"\n",
" # As a temporary solution, the following works but losing the coloring\n",
" dfi.export(styled_df, foldername_graphs_generali + str(num_table) + \"_\" + title, table_conversion='matplotlib')\n",
"\n",
" if flag_show: display(styled_df)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **2. Energy consumption**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **2.1. Yearly energy consumptions of the different users** "
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(config[\"filename_carichi\"]) # si legge il grafico contenente le informazioni circa i consumi elettrici\n",
"\n",
"df[\"year\"] = df[\"datetime\"].str[:4]\n",
"df.drop(columns=\"datetime\",inplace=True)\n",
"df_yearly = df.groupby(\"year\").sum()\n",
"\n",
"df_yearly = df_yearly[user_type_list_consuming] # teniamo solo gli users che ci servono, uno per tipo, nell'ordine che abbiamo dato \n",
"colors = {\"prosumer\":\"orange\",\n",
" \"consumer\":\"blue\"} \n",
"\n",
"if detailed_report: # usually not needed\n",
"\n",
" for i, user in enumerate(user_type_list_consuming):\n",
" \n",
" title = 'Yearly energy consumption: ' + denomination_users[user]\n",
"\n",
" fig = go.Figure()\n",
" \n",
" fig.add_trace(go.Bar(\n",
" x = df_yearly.index, y = df_yearly[user]/1000, \n",
" # marker_color = colors[utenti[user][\"type\"]], \n",
" name = str(denomination_users[str(user)]) + \" (\" + str(user_types[str(user)][\"type\"]) +\")\",\n",
" text=round(df_yearly[user]/1000,1), textposition='auto',\n",
" ))\n",
"\n",
" fig.update_layout(\n",
" title_text = title, \n",
" xaxis = dict(title='years',\n",
" ),\n",
" yaxis = dict(title='MWh/year'))\n",
"\n",
" fig.update_layout(plot_bgcolor='white',\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
" if flag_show: fig.show()\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **2.2. Comparison yearly energy consumption for the first year** "
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"valori_anno_1 = df_yearly.iloc[0]\n",
"\n",
"title = 'Comparison yearly consumption (year 1)'\n",
"\n",
"colors = {\"prosumer\":\"orange\",\n",
" \"consumer\":\"blue\"} \n",
"\n",
"x = user_type_list_consuming.copy()\n",
"for i, value in enumerate(x):\n",
" x[i] = denomination_users[value]\n",
"\n",
"fig = go.Figure(go.Bar(\n",
" x = x, \n",
" y = valori_anno_1/1000, \n",
" # marker_color = colors[user_types[user][\"type\"]], \n",
" # name = denomination_users_list,\n",
" text=round(valori_anno_1/1000,1), textposition='auto',\n",
" ))\n",
"\n",
"fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='anni',\n",
" # type='category'\n",
" ),\n",
" yaxis = dict(title='MWh/anno'))\n",
"\n",
"fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
"if flag_show: fig.show()\n",
"\n",
"num_graph+=1\n",
"\n",
"fig.write_html(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".html\")\n",
"fig.write_image(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **2.3. Energy consumption friday, saturday and sunday for the different users**"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"cal = get_calendar()\n",
"friday_flag = 0\n",
"count = 0\n",
"while friday_flag == 0: #cerciamo un venerdi che abbia un carico normale non da vacanza\n",
" if cal.loc[count,\"day_week\"] == 4: friday_flag = 1\n",
" else: count += 1 #count è l'indice della mezzanotte del primo venerdi della serie, che usiamo per plottare i profili"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(config[\"filename_carichi\"])\n",
"df = df[count:count+96*3]\n",
"df.set_index(\"datetime\",inplace=True)\n",
"\n",
"if detailed_report:\n",
" for user in user_type_list_consuming:\n",
"\n",
" title = \"Energy consumption for a week (weekday, saturday and sunday): \" + str(denomination_users[user])\n",
"\n",
" fig = go.Figure()\n",
" fig.add_trace(go.Scatter(\n",
" x = df.index, \n",
" y = df[user]*4, \n",
" name = denomination_users[str(user)],\n",
" ))\n",
" \n",
" fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='hour',\n",
" # type='category'\n",
" ),\n",
" yaxis = dict(title='Power (kW)'))\n",
" \n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
" if flag_show: fig.show()\n",
" \n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **2.4. Energy consumption <u>comparisons<u>**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### **2.4.1. Industrial users**"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(config[\"filename_carichi\"])\n",
"df = df[count:count+96*3]\n",
"df.set_index(\"datetime\",inplace=True)\n",
"\n",
"user_type_list_industrial = [user_type for user_type in user_types if user_types[user_type][\"category\"] == \"industriale\" and user_types[user_type][\"num\"]>0 and user_types[user_type][\"dummy_user\"] != True and user_types[user_type][\"consuming\"] == True]\n",
"\n",
"title = \"Energy consumption for a week (weekday, saturday and sunday): industrial users\"\n",
"\n",
"if user_type_list_industrial != []:\n",
"\n",
" fig = go.Figure()\n",
"\n",
" for user in user_type_list_industrial:\n",
"\n",
" title = title\n",
"\n",
" fig.add_trace(go.Scatter(\n",
" x = df.index, \n",
" y = df[user]*4, \n",
" # marker_color = colors[utenti[user][\"type\"]], \n",
" name = denomination_users[str(user)],\n",
" # text=round(df[user]*4,1), textposition='auto',\n",
" ))\n",
" \n",
" fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='orario',\n",
" # type='category'\n",
" ),\n",
" yaxis = dict(title='Potenza impiegata (kW)'))\n",
" \n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
" if flag_show: fig.show()\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### **2.4.2. NON industrial users**"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"greys = [\n",
" # 'rgb(255,255,255)',\n",
" # 'rgb(240,240,240)',\n",
" 'rgb(217,217,217)',\n",
" 'rgb(189,189,189)',\n",
" 'rgb(150,150,150)',\n",
" 'rgb(115,115,115)',\n",
" 'rgb(82,82,82)',\n",
" 'rgb(37,37,37)',\n",
" 'rgb(0,0,0,0.5)',\n",
" 'rgb(0,0,0,1)',\n",
" 'rgb(0,0,0,0.1)',\n",
" ]\n",
"\n",
"lines = ['solid', \n",
" 'dot', \n",
" 'dash', \n",
" 'longdash', \n",
" 'dashdot', \n",
" 'longdashdot', \n",
" 'solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"count = count + 24*4*7*2 # saltiamo di 2 settimane"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(config[\"filename_carichi\"])\n",
"\n",
"df = df[count:count+96*3]\n",
"df.set_index(\"datetime\",inplace=True)\n",
"\n",
"user_type_list_non_industrial = [user_type for user_type in user_types if user_types[user_type][\"category\"] != \"industriale\" and user_types[user_type][\"num\"]>0 and user_types[user_type][\"dummy_user\"] != True and user_types[user_type][\"consuming\"] == True]\n",
"\n",
"title = \"Energy consumption for a week (weekday, saturday and sunday): NON industrial users\"\n",
"\n",
"if detailed_report:\n",
"\n",
" if user_type_list_non_industrial != []:\n",
"\n",
" fig = go.Figure()\n",
"\n",
" for i, user_type in enumerate(user_type_list_non_industrial):\n",
" # print(user_type)\n",
"\n",
" title = title\n",
"\n",
" fig.add_trace(go.Scatter(\n",
" x = df.index, \n",
" y = df[user_type]*4, \n",
" name = denomination_users[str(user_type)],\n",
" mode='lines',\n",
" ))\n",
" \n",
" fig.update_layout(plot_bgcolor='white', \n",
" title_text = title, \n",
" xaxis = dict(title='Time',\n",
" ),\n",
" yaxis = dict(title='Power (kW)'))\n",
" \n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
" if flag_show: fig.show()\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*6, scale = 4)\n",
" fig.write_image(config[\"foldername_graphs_energy\"] + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **2.5. Monthly energy consumption comparison**"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"# a barre e a colori\n",
"df = pd.read_csv(config[\"filename_carichi\"])\n",
"df[\"year\"] = df[\"datetime\"].str[:4]\n",
"df[\"month\"] = df[\"datetime\"].str[5:7]\n",
"df = df[df[\"year\"] == df.loc[0,\"year\"]] #prendiamo solo il primo anno\n",
"df_monthly = df.drop(columns=[\"datetime\",\"year\"]).groupby(\"month\").sum()\n",
"\n",
"fig = go.Figure()\n",
"\n",
"title = \"Monthly energy consumption and seasonal effect per user types\"\n",
"\n",
"for i, user in enumerate(user_type_list_consuming):\n",
" fig.add_trace(go.Bar(\n",
" # x = df_monthly.index, \n",
" x = name_months,\n",
" y = df_monthly[user]/1000, \n",
" name = denomination_users[user],\n",
" ))\n",
" \n",
" fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='month',\n",
" ),\n",
" yaxis = dict(title='MWh for month'))\n",
" \n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
"if flag_show: fig.show()\n",
"\n",
"num_graph+=1\n",
"\n",
"fig.write_html(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".html\")\n",
"fig.write_image(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)\n",
"fig.write_image(config[\"foldername_graphs_energy\"] + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### **2.5.1. Table with monthly energy consumption recap**"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"# ci ricreiamo l'aggregato mensile ma solo delle tipologie di utenti, non di tutti\n",
"df_table = df_monthly.copy()\n",
"df_table = df_table[user_type_list_consuming] #facciamo una selezione degli utenti attivi\n",
"\n",
"df_table[\"Totale CACER\"] = 0\n",
"for user in user_type_list_consuming:\n",
" df_table[\"Totale CACER\"] += df_table[user].multiply(user_types[user][\"num\"], axis=\"index\") # sommiamo l'aggregato di tutti gli utenti di quel tipo\n",
"\n",
"for user in df_table.columns:\n",
" if user in user_type_list_consuming:\n",
" df_table.rename(columns={str(user) : str(denomination_users[str(user)])}, inplace=True)\n",
"\n",
"if flag_show: display(df_table)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"# si assegna uno stile alla tabella creata in precedenza\n",
"\n",
"# more here: https://www.analyticsvidhya.com/blog/2021/06/style-your-pandas-dataframe-and-make-it-stunning/\n",
"\n",
"if detailed_report:\n",
" df_table.loc['Total'] = df_table.sum(numeric_only=True)\n",
" df_table.index.rename(\"Mese\", inplace=True)\n",
"\n",
" styled_df = df_table.style.format(precision=1, thousands=\".\", decimal=\",\") \\\n",
" .format_index(str, axis=1)\\\n",
" .set_caption(\"Consumi anno 1 per tipologia di utente (kWh/mese)\") \\\n",
" .background_gradient()\n",
"\n",
" path = foldername_graphs_generali\n",
" num_table+=1\n",
" title = 'CACER 2tabella.png'\n",
"\n",
" # dfi.export(styled_df, path + \"table_\" + str(num_table) + \"_\" + title, dpi = 150) # This only works for styled dataframes # NO LONGER WORKING, USE THE LESS COOL ONE BELOW\n",
" dfi.export(styled_df, path + \"table_\" + str(num_table) + \"_\" + title, table_conversion='matplotlib')\n",
" \n",
" if flag_show: display(styled_df)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **2.6. Monthly energy consumption for the different users**"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"totale_mensile_tutti_utenti = df_table[\"Totale CACER\"]\n",
"\n",
"fig = go.Figure()\n",
"title = \"CACER aggregated monthly energy consumption\"\n",
"\n",
"for user in user_type_list_consuming:\n",
" for i in range(user_types[user][\"num\"]):\n",
" fig.add_trace(go.Bar(\n",
" x = df_monthly.index, \n",
" y = df_monthly[user]/1000, \n",
" name = str(denomination_users[str(user)]) + '_' + str(i+1),\n",
" ))\n",
" fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='Month',\n",
" ),\n",
" yaxis = dict(title='MWh/month'))\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"fig.update_layout(barmode='stack')\n",
"\n",
"#aggiungiamo linea trasparente per indicare il totale a numero\n",
"fig.add_trace(go.Scatter(\n",
" x = df_monthly.index,\n",
" # x = name_months,\n",
" y = totale_mensile_tutti_utenti/1000, \n",
" marker_color= 'rgba(255, 0, 0, 0)', \n",
" mode='markers+text',\n",
" name = \"Total\",\n",
" text=round(totale_mensile_tutti_utenti/1000,1), textposition='top center',\n",
" ))\n",
"\n",
"if flag_show: fig.show()\n",
"\n",
"num_graph+=1\n",
"\n",
"fig.write_html(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".html\")\n",
"if len(user_type_list_consuming) > 10: fig.update_layout(showlegend=False) #se abbiamo troppi utenti mutiamo la legenda dal png, che altrimenti non si legge nulla\n",
"fig.write_image(foldername_graphs_generali + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **3. Sun charts**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"if detailed_report:\n",
" title = \"Plots sun chart 1\"\n",
"\n",
" # lat, lon, tilt_angle, azimuth = get_coordinates() \n",
" name_location = str(province_italian_to_english())\n",
" lat, lon = get_coordinates(name_location)\n",
" lat = float(lat) #float is required\n",
" lon = float(lon) #float is required\n",
"\n",
" tz='Europe/Rome'\n",
"\n",
" times = pd.date_range('2019-01-01 00:00:00', '2020-01-01', \n",
" # closed='left',\n",
" freq='H', tz=tz)\n",
" solpos = solarposition.get_solarposition(times, lat, lon)\n",
" # remove nighttime\n",
" solpos = solpos.loc[solpos['apparent_elevation'] > 0, :]\n",
"\n",
" ax = plt.subplot(1, 1, 1, projection='polar')\n",
" # draw the analemma loops\n",
" points = ax.scatter(np.radians(solpos.azimuth), solpos.apparent_zenith,\n",
" s=2, label=None, c=solpos.index.dayofyear)\n",
" ax.figure.colorbar(points)\n",
"\n",
" # draw hour labels\n",
" for hour in np.unique(solpos.index.hour):\n",
" # choose label position by the smallest radius for each hour\n",
" subset = solpos.loc[solpos.index.hour == hour, :]\n",
" r = subset.apparent_zenith\n",
" pos = solpos.loc[r.idxmin(), :]\n",
" ax.text(np.radians(pos['azimuth']), pos['apparent_zenith'], str(hour))\n",
"\n",
" # draw individual days\n",
" for i, date in enumerate(pd.to_datetime(['2019-03-21', '2019-06-21', '2019-12-21'])):\n",
" times = pd.date_range(date, date+pd.Timedelta('24h'), freq='5min', tz=tz)\n",
" solpos = solarposition.get_solarposition(times, lat, lon)\n",
" solpos = solpos.loc[solpos['apparent_elevation'] > 0, :]\n",
" #label = date.strftime('%Y-%m-%d')\n",
" labels = ['Equinoxes','Solstice March','Solstice December']\n",
" ax.plot(np.radians(solpos.azimuth), solpos.apparent_zenith, label=labels[i])\n",
"\n",
" ax.figure.legend(loc='upper left')\n",
"\n",
" # change coordinates to be like a compass\n",
" ax.set_theta_zero_location('N')\n",
" ax.set_theta_direction(-1)\n",
" ax.set_rmax(90)\n",
"\n",
" num_graph+=1\n",
" plot_saved = plt.savefig(config[\"foldername_graph_pv\"] + str(num_graph) + \"_\" + title + \".png\", bbox_inches = 'tight')\n",
"\n",
" if flag_show: plt.show() # after plt.show() is called, a new figure is created"
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {},
"outputs": [],
"source": [
"if detailed_report:\n",
" title = \"Plots sun chart 2\"\n",
"\n",
" name_location = str(province_italian_to_english())\n",
" lat, lon = get_coordinates(name_location)\n",
" lat = float(lat) #float is required\n",
" lon = float(lon) #float is required\n",
"\n",
" tz='Europe/Rome'\n",
"\n",
" times = pd.date_range('2019-01-01 00:00:00', '2020-01-01', \n",
" # closed='left',\n",
" freq='H', tz=tz)\n",
"\n",
" solpos = solarposition.get_solarposition(times, lat, lon)\n",
" # remove nighttime\n",
" solpos = solpos.loc[solpos['apparent_elevation'] > 0, :]\n",
"\n",
" fig, ax = plt.subplots()\n",
" points = ax.scatter(solpos.azimuth, solpos.apparent_elevation, s=2,\n",
" c=solpos.index.dayofyear, label=None)\n",
" fig.colorbar(points)\n",
"\n",
" for hour in np.unique(solpos.index.hour):\n",
" # choose label position by the largest elevation for each hour\n",
" subset = solpos.loc[solpos.index.hour == hour, :]\n",
" height = subset.apparent_elevation\n",
" pos = solpos.loc[height.idxmax(), :]\n",
" ax.text(pos['azimuth'], pos['apparent_elevation'], str(hour))\n",
"\n",
" for i, date in enumerate(pd.to_datetime(['2019-03-21', '2019-06-21', '2019-12-21'])):\n",
" times = pd.date_range(date, date+pd.Timedelta('24h'), freq='5min', tz=tz)\n",
" solpos = solarposition.get_solarposition(times, lat, lon)\n",
" solpos = solpos.loc[solpos['apparent_elevation'] > 0, :]\n",
" #label = date.strftime('%Y-%m-%d')\n",
" labels = ['Equinoxes','Solstice March','Solstice December']\n",
" ax.plot(solpos.azimuth, solpos.apparent_elevation, label=labels[i])\n",
"\n",
" ax.figure.legend(loc='upper left')\n",
" ax.set_xlabel('Solar Azimuth (degrees)')\n",
" ax.set_ylabel('Solar Elevation (degrees)')\n",
"\n",
" num_graph+=1\n",
"\n",
" plot_saved = plt.savefig(config[\"foldername_graph_pv\"] + str(num_graph) + \"_\" + title + \".png\", bbox_inches = 'tight')\n",
"\n",
" \n",
" if flag_show: plt.show() # after plt.show() is called, a new figure is created"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **4. CACER plots**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **4.1. Sankey energy flows CACER**"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_excel(filename_CACER_energy_monthly, sheet_name=\"CACER\")"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"def plot_sankey(df, user):\n",
" global num_graph, data\n",
" df[\"Eprel_non_cond\"] = df[\"Eprel\"] - df[\"Econd\"]\n",
" df[\"Evend_non_cond\"] = df[\"Eimm\"] - df[\"Econd\"]\n",
"\n",
" Eaut_tot = df[\"Eaut\"].sum() # energia autoconsumata totale\n",
" Eimm_tot = df[\"Eimm\"].sum() # energia immessa totale\n",
" Eut_tot = df[\"Eut\"].sum() # energia consumata totale\n",
" Econd_tot = df[\"Econd\"].sum() # energia condivisa totale\n",
" Eprod_tot = df[\"Eprod\"].sum() # energia prodotta totale\n",
" Eprel_tot = df[\"Eprel\"].sum() # energia prelevata totale\n",
" Eprel_non_cond_tot = df[\"Eprel\"].sum() - df[\"Econd\"].sum() # energia prelevata non condivisa totale\n",
" Evend_non_cond_tot = df[\"Eimm\"].sum() - df[\"Econd\"].sum() # energia venduta non condivisa totale\n",
" Eperdite_tot = df[\"Eperdite\"].sum() # perdite di energia\n",
"\n",
" ## ITALIANO\n",
" # data = {\n",
" # \"Econd\": {\"value\": Econd_tot, \"col\": col[\"verde\"],\"label\": \"Energia condivisa\"},\n",
" # \"Eprod\": {\"value\": Eprod_tot,\"col\": col[\"giallo\"],\"label\": \"Energia prodotta dalla CACER\"},\n",
" # \"Evend_non_cond\": {\"value\": Evend_non_cond_tot,\"col\": col[\"blu\"],\"label\": \"Energia immessa non condivisa\"},\n",
" # \"Eperdite\": {\"value\": Eperdite_tot,\"col\": col[\"marrone\"],\"label\": \"Perdite conversione\"},\n",
" # \"Eprel_non_cond\": {\"value\": Eprel_non_cond_tot,\"col\": col[\"rosso\"],\"label\": \"Energia prelevata non condivisa\"},\n",
" # \"Eprel\": {\"value\": Eprel_tot,\"col\": col[\"rosso\"],\"label\": \"Energia prelevata da rete\"},\n",
" # \"Eaut\": {\"value\": Eaut_tot,\"col\": col[\"arancione\"],\"label\": \"Energia autoconsumata\"},\n",
" # \"Eut\": {\"value\": Eut_tot,\"col\": col[\"violetto\"],\"label\": \"Energia consumata dalla CACER\"},\n",
" # \"Eimm\": {\"value\": Eimm_tot,\"col\": col[\"blu\"],\"label\": \"Energia immessa e venduta in rete\"}, \n",
" # }\n",
"\n",
"\n",
" ## INGLESE\n",
" data = {\n",
" \"Econd\": {\"value\": Econd_tot, \"col\": col[\"verde\"],\"label\": \"Shared Energy\"},\n",
" \"Eprod\": {\"value\": Eprod_tot,\"col\": col[\"giallo\"],\"label\": \"CACER Energy Produced\"},\n",
" \"Evend_non_cond\": {\"value\": Evend_non_cond_tot,\"col\": col[\"blu\"],\"label\": \"Energy injected into the grid and not share\"},\n",
" \"Eperdite\": {\"value\": Eperdite_tot,\"col\": col[\"marrone\"],\"label\": \"Energy Losses\"},\n",
" \"Eprel_non_cond\": {\"value\": Eprel_non_cond_tot,\"col\": col[\"rosso\"],\"label\": \"Energy purchased from grid and not shared\"},\n",
" \"Eprel\": {\"value\": Eprel_tot,\"col\": col[\"rosso\"],\"label\": \"Energy purchased from grid\"},\n",
" \"Eaut\": {\"value\": Eaut_tot,\"col\": col[\"arancione\"],\"label\": \"Self_consumed energy\"}, \n",
" \"Eut\": {\"value\": Eut_tot,\"col\": col[\"violetto\"],\"label\": \"CACER Energy Demand\"},\n",
" \"Eimm\": {\"value\": Eimm_tot,\"col\": col[\"blu\"],\"label\": \"Energy injected and sold to grid\"}, \n",
" }\n",
"\n",
" flows = pd.read_excel(foldername_graphs + \"sankey_inputs.xlsx\", sheet_name=\"CER\")\n",
"\n",
" \"\"\"Plot the Sankey with the energy flows\n",
" more info: https://plotly.com/python/sankey-diagram/\n",
" \"\"\"\n",
" title = \"Energy flows - \" + user\n",
"\n",
" fig = go.Figure(data=[go.Sankey(\n",
" valuesuffix = \"kWh\",\n",
" node = dict(\n",
" pad = 15,\n",
" thickness = 20,\n",
" line = dict(color = \"black\", width = 0.5),\n",
" label = [data[\"Eprod\"][\"label\"], # node 0 = prod,\n",
" data[\"Eaut\"][\"label\"], # node 1 = aut,\n",
" data[\"Eut\"][\"label\"], # node 2 = consumi,\n",
" data[\"Eimm\"][\"label\"], # node 3 = immessa in rete e venduta ,\n",
" data[\"Econd\"][\"label\"], # node 4 = condivisa\n",
" data[\"Eprel\"][\"label\"], # node 5 = prelevata da rete e acquistata da fornitore\n",
" data[\"Evend_non_cond\"][\"label\"], # node 6 = venduta ma non condivisa,\n",
" data[\"Eperdite\"][\"label\"], # node 7 = perdite\n",
" data[\"Eprel_non_cond\"][\"label\"], # node 8 = prelevata da rete ma non condivisa\n",
" ], \n",
" color = [data[\"Eprod\"][\"col\"], # node 0 = prod,\n",
" data[\"Eaut\"][\"col\"], # node 1 = aut,\n",
" data[\"Eut\"][\"col\"], # node 2 = consumi,\n",
" data[\"Eimm\"][\"col\"], # node 3 = immessa in rete e venduta ,\n",
" data[\"Econd\"][\"col\"], # node 4 = condivisa\n",
" data[\"Eprel\"][\"col\"], # node 5 = prelevata da rete e acquistata da fornitore\n",
" data[\"Evend_non_cond\"][\"col\"], # node 6 = venduta ma non condivisa,\n",
" data[\"Eperdite\"][\"col\"], # node 7 = perdite\n",
" data[\"Eprel_non_cond\"][\"col\"], # node 8 = prelevata da rete ma non condivisa\n",
" ], \n",
" ),\n",
" link = dict(\n",
" source = flows[\"source\"],\n",
" target = flows[\"target\"],\n",
" value = [data[flows.loc[i,\"value\"]][\"value\"] for i in range(len(flows[\"value\"]))], # andiamo a prendere il valore del dizionario data corrispondente al nome dato nel csv\n",
" color = [data[flows.loc[i,\"color\"]][\"col\"] for i in range(len(flows[\"color\"]))], # stessa cosa di sopra ma per il colore\n",
" # label = [\"%.2f\" % data[flows.loc[i,\"value\"]][\"value\"] for i in range(len(flows[\"value\"]))]\n",
" ))])\n",
"\n",
" fig.update_layout(title_text=title, font_size=10)\n",
"\n",
" if flag_show: fig.show()\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)\n",
" \n",
"plot_sankey(df, user=\"CACER\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **4.2 Pie chart energy mix CACER (total energy consumption)**"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
"fills = [\"o\",\"x\",\"/\"]"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"def plot_pie_consumption(df, user):\n",
" \n",
" global num_graph, Eaut_tot, Econd_tot, Eprel_non_cond_tot\n",
" \n",
" # title = \"Allocazione dell'energia consumata [%] - \" + user\n",
" # labels = ['Energia Autoconsumata dai prosumer', 'Energia Condivisa dalla CACER ', 'Energia Acquistata da rete non condivisa']\n",
"\n",
" title = \"CACER Energy consumption allocation - [%]\"\n",
" labels = ['Prosumers energy self-consumption', 'Energy purchased from grid and shared', 'Energy purchased from grid and not shared']\n",
" \n",
" Eaut_tot = df[\"Eaut\"].sum() # energia autoconsumata totale\n",
" Econd_tot = df[\"Econd\"].sum() # energia condivisa totale\n",
" Eprel_non_cond_tot = df[\"Eprel\"].sum() - df[\"Econd\"].sum() # energia prelevata non condivisa totale\n",
" \n",
" values_kWh = [Eaut_tot,Econd_tot,Eprel_non_cond_tot]\n",
"\n",
" fig = go.Figure(data=[go.Pie(labels=labels, values=values_kWh, pull=[0.05, 0.05, 0.05])])\n",
"\n",
" fig.update_layout(title_text = title)\n",
"\n",
" fig.update_traces(marker=dict(colors=[col[\"arancione\"], col[\"verde\"], col[\"rosso\"]]))\n",
"\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.1, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".png\", width=500, height=500, scale = 4)\n",
" if flag_show: fig.show()\n",
"\n",
" fig.write_image(config[\"foldername_graphs_energy\"] + title + \".png\", width=500, height=500, scale = 4)\n",
"\n",
"plot_pie_consumption(df, user=\"CACER\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **4.3. Pie chart energy mix CACER (total produced energy)**"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
"def plot_pie_generation(df, user):\n",
" \n",
" global num_graph, Eaut_tot, Econd_tot, Evend_non_cond_tot\n",
" \n",
" # title = \"Allocazione dell'energia prodotta [%] - \" + user\n",
" # labels = ['Energia autoconsumata dai prosumer', 'Energia venduta in rete e condivisa con la CACER', 'Energia venduta in rete non condivisa']\n",
"\n",
" title = \"CACER Energy generation allocation - [%]\"\n",
" labels = ['Prosumers energy self-consumption', 'Energy sold to grid and shared', 'Energy sold to grid and not shared']\n",
" \n",
" Eaut_tot = df[\"Eaut\"].sum() # energia autoconsumata totale\n",
" Econd_tot = df[\"Econd\"].sum() # energia condivisa totale\n",
" Evend_non_cond_tot = df[\"Eimm\"].sum() - df[\"Econd\"].sum() # energia venduta non condivisa totale\n",
"\n",
" values_kWh = [Eaut_tot, Econd_tot, Evend_non_cond_tot]\n",
"\n",
" fig = go.Figure(data=[go.Pie(labels=labels, values=values_kWh, pull=[0.05, 0.05, 0.05])])\n",
"\n",
" fig.update_layout(title_text = title)\n",
"\n",
" fig.update_traces(marker=dict(colors=[col[\"arancione\"], col[\"verde\"], col[\"blu\"]]))\n",
"\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.1, xanchor=\"left\", x=-0.01), \n",
" )\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".png\", width=500, height=500, scale = 4)\n",
" if flag_show: fig.show()\n",
"\n",
" fig.write_image(config[\"foldername_graphs_energy\"] + title + \".png\", width=500, height=500, scale = 4)\n",
"\n",
"plot_pie_generation(df, user=\"CACER\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **4.4 Area graphs energy mix CACER (total energy consumption)**"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [],
"source": [
"def plot_area_lifetime_consumption(df, user):\n",
" global num_graph\n",
" \n",
" # title = 'Ripartizione energia consumata mensilmente [%] - ' + user\n",
" # labels = ['Energia Autoconsumata dai prosumer', 'Energia acquistata da rete e condivisa dalla CACER', 'Energia Acquistata da rete non condivisa']\n",
" \n",
" title = \"CACER Energy consumption allocation - [%]\"\n",
" # labels = ['Prosumers energy self-consumption', 'Energy purchased from grid and shared', 'Energy purchased from grid and not shared']\n",
" \n",
" fig = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
"\n",
" for i in [\"Eaut\",\"Econd\",\"Eprel_non_cond\"]:\n",
"\n",
" ################ IN PERCENTUALE\n",
" y_perc = df[i] / (df[\"Eaut\"] + df[\"Econd\"] + df[\"Eprel_non_cond\"]) * 100\n",
" fig.add_trace(go.Scatter(\n",
" x = df.month, \n",
" y = y_perc, \n",
" marker_color = data[i][\"col\"], \n",
" name = data[i][\"label\"],\n",
" text=round(y_perc,1), textposition='middle center',\n",
" stackgroup='one',\n",
" ),\n",
" secondary_y= True)\n",
"\n",
" # ########## QUESTO È IN MWH \n",
" # fig.add_trace(go.Bar(\n",
" # x = df_last_year.month, \n",
" # y = df_last_year[i]/1000, \n",
" # marker_color = data[i][\"col\"], \n",
" # name = data[i][\"label\"],\n",
" # text=round(df_last_year[i]/1000,1), textposition='auto',\n",
" # ))\n",
"\n",
" fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='mese',\n",
" ))\n",
"\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
" fig.update_layout(barmode='stack')\n",
"\n",
" fig.update_yaxes(title_text = 'Prelievi in MWh', secondary_y=False, exponentformat= \"none\")\n",
"\n",
" fig.update_yaxes(title_text = 'Percentuale sui prelievi (%)', secondary_y=True, exponentformat= \"none\",\n",
" mirror=True,\n",
" showline=True,\n",
" gridcolor='lightgrey')\n",
"\n",
" if flag_show: fig.show()\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)\n",
"\n",
"plot_area_lifetime_consumption(df, user=\"CACER\")"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
"def plot_area_year1_consumption(df, user):\n",
" \n",
" global num_graph\n",
"\n",
" df[\"year\"] = df.month.str[:4]\n",
" df_last_year = df.copy()\n",
" df_last_year = df_last_year[df_last_year[\"year\"] == df_last_year[\"year\"][0]]\n",
" df_last_year[\"Percentuale autoconsumo\"] = df_last_year[\"Eaut\"] / (df_last_year[\"Eaut\"] + df_last_year[\"Econd\"] + df_last_year[\"Eprel_non_cond\"])\n",
" df_last_year[\"Percentuale condivisione\"] = df_last_year[\"Econd\"] / (df_last_year[\"Eaut\"] + df_last_year[\"Econd\"] + df_last_year[\"Eprel_non_cond\"])\n",
" df_last_year[\"Percentuale prelievo senza condivisione\"] = df_last_year[\"Eprel_non_cond\"] / (df_last_year[\"Eaut\"] + df_last_year[\"Econd\"] + df_last_year[\"Eprel_non_cond\"])\n",
"\n",
" title = 'Energy consumption repartition for the first year - ' + user \n",
" # labels = ['Energia Autoconsumata dai prosumer', 'Energia acquistata da rete e condivisa dalla CACER', 'Energia Acquistata da rete non condivisa']\n",
" \n",
" fig = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
"\n",
" for i in [\"Eaut\",\"Econd\",\"Eprel_non_cond\"]:\n",
"\n",
" ################ IN PERCENTUALE\n",
" y_perc = df_last_year[i] / (df_last_year[\"Eaut\"] + df_last_year[\"Econd\"] + df_last_year[\"Eprel_non_cond\"]) * 100\n",
" fig.add_trace(go.Scatter(\n",
" x = df_last_year.month, \n",
" y = y_perc, \n",
" marker_color = data[i][\"col\"], \n",
" name = data[i][\"label\"],\n",
" text=round(y_perc,1), textposition='middle center',\n",
" stackgroup='one',\n",
" ),\n",
" secondary_y= True)\n",
"\n",
" # ########## QUESTO È IN MWH \n",
" # fig.add_trace(go.Bar(\n",
" # x = df_last_year.month, \n",
" # y = df_last_year[i]/1000, \n",
" # marker_color = data[i][\"col\"], \n",
" # name = data[i][\"label\"],\n",
" # text=round(df_last_year[i]/1000,1), textposition='auto',\n",
" # ))\n",
"\n",
" fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='mese',\n",
" ))\n",
"\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
" fig.update_layout(barmode='stack')\n",
"\n",
" fig.update_yaxes(title_text = 'Percentage on withdrawals (%)', secondary_y=True, exponentformat= \"none\",\n",
" mirror=True,\n",
" showline=True,\n",
" gridcolor='lightgrey')\n",
"\n",
" if flag_show: fig.show()\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)\n",
"\n",
"plot_area_year1_consumption(df, user=\"CACER\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **4.5. Area grapfh energy mix CACER (total produced energy)**"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"def plot_area_lifetime_generation(df, user):\n",
" \n",
" global num_graph\n",
" \n",
" # title = \"Ripartizione energia prodotta nell'intero progetto - \" + user\n",
" # labels = ['Energia Autoconsumata dai prosumer', 'Energia prodotta e condivisa dalla CACER', 'Energia prodotta e non condivisa']\n",
" \n",
" title = \"Energy generation repartition - \" + user\n",
"\n",
" fig = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
"\n",
" for i in [\"Eaut\",\"Econd\",\"Evend_non_cond\"]:\n",
"\n",
" ################ IN PERCENTUALE\n",
" y_perc = df[i] / (df[\"Eaut\"] + df[\"Econd\"] + df[\"Evend_non_cond\"]) * 100\n",
" fig.add_trace(go.Scatter(\n",
" x = df.month, \n",
" y = y_perc, \n",
" marker_color = data[i][\"col\"], \n",
" name = data[i][\"label\"],\n",
" text=round(y_perc,1), textposition='middle center',\n",
" stackgroup='one',\n",
" ),\n",
" secondary_y= True)\n",
"\n",
" # ########## QUESTO È IN MWH \n",
" # fig.add_trace(go.Bar(\n",
" # x = df_last_year.month, \n",
" # y = df_last_year[i]/1000, \n",
" # marker_color = data[i][\"col\"], \n",
" # name = data[i][\"label\"],\n",
" # text=round(df_last_year[i]/1000,1), textposition='auto',\n",
" # ))\n",
"\n",
" fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='mese',\n",
" ))\n",
"\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
" fig.update_layout(barmode='stack')\n",
"\n",
" fig.update_yaxes(title_text = ' Percentage on production (%)', secondary_y=True, exponentformat= \"none\",\n",
" mirror=True,\n",
" showline=True,\n",
" gridcolor='lightgrey')\n",
"\n",
" if flag_show: fig.show()\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)\n",
"\n",
"plot_area_lifetime_generation(df, user=\"CACER\")"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"def plot_area_year1_generation(df, user):\n",
" global num_graph\n",
" \n",
" df[\"year\"] = df.month.str[:4]\n",
" df_last_year = df.copy()\n",
" df_last_year = df_last_year[df_last_year[\"year\"] == df_last_year[\"year\"][0]]\n",
" df_last_year[\"Percentuale autoconsumo\"] = df_last_year[\"Eaut\"] / (df_last_year[\"Eaut\"] + df_last_year[\"Econd\"] + df_last_year[\"Evend_non_cond\"])\n",
" df_last_year[\"Percentuale condivisione\"] = df_last_year[\"Econd\"] / (df_last_year[\"Eaut\"] + df_last_year[\"Econd\"] + df_last_year[\"Evend_non_cond\"])\n",
" df_last_year[\"Percentuale produzione senza condivisione\"] = df_last_year[\"Evend_non_cond\"] / (df_last_year[\"Eaut\"] + df_last_year[\"Econd\"] + df_last_year[\"Evend_non_cond\"])\n",
"\n",
" # title = 'Ripartizione energia prodotta nel primo anno - ' + user\n",
" # labels = ['Energia Autoconsumata dai prosumer', 'Energia prodotta e condivisa dalla CACER', 'Energia prodotta e non condivisa']\n",
"\n",
" title = \"Energy generation repartition for the first year - \" + user\n",
"\n",
" fig = make_subplots(specs=[[{\"secondary_y\": True}]])\n",
"\n",
" for i in [\"Eaut\",\"Econd\",\"Evend_non_cond\"]:\n",
"\n",
" ################ IN PERCENTUALE\n",
" y_perc = df_last_year[i] / (df_last_year[\"Eaut\"] + df_last_year[\"Econd\"] + df_last_year[\"Evend_non_cond\"]) * 100\n",
" fig.add_trace(go.Scatter(\n",
" x = df_last_year.month, \n",
" y = y_perc, \n",
" marker_color = data[i][\"col\"], \n",
" name = data[i][\"label\"],\n",
" text=round(y_perc,1), textposition='middle center',\n",
" stackgroup='one',\n",
" ),\n",
" secondary_y= True)\n",
"\n",
" # ########## QUESTO È IN MWH \n",
" # fig.add_trace(go.Bar(\n",
" # x = df_last_year.month, \n",
" # y = df_last_year[i]/1000, \n",
" # marker_color = data[i][\"col\"], \n",
" # name = data[i][\"label\"],\n",
" # text=round(df_last_year[i]/1000,1), textposition='auto',\n",
" # ))\n",
"\n",
" fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='mese',\n",
" ))\n",
"\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
" fig.update_layout(barmode='stack')\n",
"\n",
" fig.update_yaxes(title_text = 'Percentage on production (%)', secondary_y=True, exponentformat= \"none\",\n",
" mirror=True,\n",
" showline=True,\n",
" gridcolor='lightgrey')\n",
"\n",
" if flag_show: fig.show()\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)\n",
"\n",
"plot_area_year1_generation(df, user=\"CACER\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **4.6. Energy flows in specific days**"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(config[\"filename_CACER_energy_hourly\"]).fillna(0)"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [],
"source": [
"# ENERGY FLOW FOR ALL CACER!\n",
"df = pd.read_csv(config[\"filename_CACER_energy_hourly\"]).fillna(0)\n",
"\n",
"line_shape = 'linear' # hv, vh, hvh, vhv, spline, linear\n",
"\n",
"# labels = {\"Eaut\":'Energia Autoconsumata dai prosumer', \n",
"# \"Econd\":'Energia condivisa dalla CACER', \n",
"# \"Eprel\": 'Energia prelevata e non condivisa',\n",
"# \"Eimm\": 'Energia immessa e non condivisa',\n",
"# \"Eperdite\": \"Perdite conversione\"}\n",
"\n",
"labels = {\"Eaut\":'Prosumers energy self-consumption', \n",
" \"Econd\":'Energy shared with the CACER', \n",
" \"Eprel\": 'Energy purchased from grid and not shared',\n",
" \"Eimm\": 'Energy injected into the grid and not shared',\n",
" \"Eperdite\": \"Energy Losses\"}\n",
"\n",
"for active_day_str in [\"day_spring\", \"day_summer\", \"day_autumn\",\"day_winter\"]:\n",
"\n",
" active_day = str(config[active_day_str]) # deve essere una stringa, non un datetime.data\n",
"\n",
" title = \"Energy flows - \" + active_day + \" - CACER \"\n",
" \n",
" df_plot = df[[string.startswith(active_day) for x,string in enumerate(df[\"dayhour\"])]] \n",
" assert len(df_plot) > 0, active_day + \" not found! Check inputs\"\n",
" assert len(df_plot) <= 24*4, active_day + \"has too may datapoints! Investigate\"\n",
"\n",
" df_plot = df_plot.set_index(\"dayhour\")\n",
"\n",
" # togliamo cio che non ci serve\n",
" # df_plot.drop(columns=[\"battery_cumulative_charge\",\"SOCkWh\",\"SOCperc\",\"LCF_aut\",\"SCF_aut\",\"Eprod\",\"Eaut_PV\", \"Eaut_batt\"], inplace=True, errors=\"ignore\")\n",
" # fixing order of columns, needed for the stacked area chart\n",
" df_plot = df_plot[[\"Eut\", \"Eprod\", \"Eaut\", \"Econd\", \"Eimm\", \"Eprel\", \"Eperdite\"]]\n",
"\n",
" df_plot[\"Eprel\"] = df_plot[\"Eprel\"] - df_plot[\"Econd\"] # diventa solo la quota non condivisa\n",
" df_plot[\"Eimm\"] = df_plot[\"Eimm\"] - df_plot[\"Econd\"] # diventa solo la quota non condivisa\n",
"\n",
" # # se siamo a base quartoraria, dobbiamo allora passare da kWh/quartodora a kW, moltiplicando per 4\n",
" # if config[\"delta_t\"] in [\"15min\", \"15Min\"]:\n",
" # print(\"Quarterly!\")\n",
" # df_plot = df_plot * 4 \n",
"\n",
" fig = go.Figure()\n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, y = df_plot[\"Eut\"], marker_color=data[\"Eut\"][\"col\"], mode='lines+markers',\n",
" name = data[\"Eut\"][\"label\"], \n",
" line_shape = line_shape,\n",
" textposition='top center',stackgroup=None))\n",
" \n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, y = df_plot[\"Eprod\"], marker_color=data[\"Eprod\"][\"col\"], mode='lines+markers',\n",
" name = data[\"Eprod\"][\"label\"], \n",
" line_shape = line_shape,\n",
" textposition='top center',stackgroup=None))\n",
" \n",
" # tutte queste sono cumulate, quindi stacked area\n",
" for column in df_plot.columns:\n",
" if column == \"datetime\" or column in [\"Eut\", \"Eprod\"]: continue\n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, y = df_plot[column], marker_color=data[column][\"col\"], mode='lines',\n",
" name = labels[column], \n",
" line_shape = line_shape,\n",
" textposition='top center',stackgroup='one'))\n",
"\n",
" fig.update_layout(\n",
" title_text = title, \n",
" )\n",
"\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.25, xanchor=\"left\", x=0.01), \n",
" )\n",
" fig.update_yaxes(title_text = \"Power (kW)\")\n",
"\n",
" ##############################################################################################################################\n",
"\n",
" fig.update_xaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_yaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_layout({'plot_bgcolor': 'white',\n",
" 'paper_bgcolor': 'white',\n",
" })\n",
"\n",
" ##############################################################################################################################\n",
"\n",
" if flag_show: fig.show()\n",
" \n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)\n",
"\n",
" if active_day_str in [\"day_summer\", \"day_winter\"]:\n",
" fig.write_image(config[\"foldername_graphs_energy\"] + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [],
"source": [
"# # ENERGY FLOW FOR ALL CACER for 4 days in the same chart\n",
"# df = pd.read_csv(config[\"filename_CACER_energy_quarterly\"]).fillna(0)\n",
"\n",
"# labels = {\"Eaut\":'Energia Autoconsumata dai prosumer', \n",
"# \"Econd\":'Energia condivisa dalla CACER', \n",
"# \"Eprel\": 'Energia prelevata e non condivisa',\n",
"# \"Eimm\": 'Energia immessa e non condivisa',\n",
"# \"Eperdite\": \"Perdite conversione\"}\n",
"\n",
"# fig = make_subplots(rows=2, cols=2)\n",
"# title = \"Flussi energetici di un giorno casuale per ogni stagione dell'anno\"\n",
"\n",
"# for i, active_day_str in enumerate([\"day_spring\", \"day_summer\", \"day_autumn\",\"day_winter\"]):\n",
"\n",
"# active_day = str(config[active_day_str]) # deve essere una stringa, non un datetime.data\n",
" \n",
"# df_plot = df[[string.startswith(active_day) for x,string in enumerate(df[\"datetime\"])]] \n",
"# assert len(df_plot) > 0, active_day + \" not found! Check inputs\"\n",
"# assert len(df_plot) <= 24*4, active_day + \"has too may datapoints! Investigate\"\n",
"\n",
"# df_plot = df_plot.set_index(\"datetime\")\n",
"# # df_plot.set_index(\"datetime\")\n",
"\n",
"# # togliamo cio che non ci serve\n",
"# # df_plot.drop(columns=[\"battery_cumulative_charge\",\"SOCkWh\",\"SOCperc\",\"LCF_aut\",\"SCF_aut\",\"Eprod\",\"Eaut_PV\", \"Eaut_batt\"], inplace=True, errors=\"ignore\")\n",
"# # fixing order of columns, needed for the stacked area chart\n",
"# df_plot = df_plot[[\"Eut\", \"Eprod\", \"Eaut\", \"Econd\", \"Eprel\", \"Eimm\", \"Eperdite\"]]\n",
"\n",
"# df_plot[\"Eprel\"] = df_plot[\"Eprel\"] - df_plot[\"Econd\"] # diventa solo la quota non condivisa\n",
"# df_plot[\"Eimm\"] = df_plot[\"Eimm\"] - df_plot[\"Econd\"] # diventa solo la quota non condivisa\n",
"\n",
"# # se siamo a base quartoraria, dobbiamo allora passare da kWh/quartodora a kW, moltiplicando per 4\n",
"# if config[\"delta_t\"] in [\"15min\", \"15Min\"]:\n",
"# df_plot = df_plot * 4 \n",
" \n",
"# fig.add_trace(go.Scatter(\n",
"# x = df_plot.index, y = df_plot[\"Eut\"], marker_color=data[\"Eut\"][\"col\"], mode='lines+markers',\n",
"# name = data[\"Eut\"][\"label\"], \n",
"# textposition='top center',stackgroup=None),\n",
"# row=round((i+1)/4)+1, col=i%2+1)\n",
" \n",
"# fig.add_trace(go.Scatter(\n",
"# x = df_plot.index, y = df_plot[\"Eprod\"], marker_color=data[\"Eprod\"][\"col\"], mode='lines+markers',\n",
"# name = data[\"Eprod\"][\"label\"], \n",
"# textposition='top center',stackgroup=None),\n",
"# row=round((i+1)/4)+1, col=i%2+1)\n",
" \n",
"# # tutte queste sono cumulate, quindi stacked area\n",
"# for column in df_plot.columns:\n",
"# if column == \"datetime\" or column in [\"Eut\", \"Eprod\"]: continue\n",
"# fig.add_trace(go.Scatter(\n",
"# x = df_plot.index, y = df_plot[column], marker_color=data[column][\"col\"], mode='lines',\n",
"# name = labels[column], \n",
"# textposition='top center',stackgroup='one'),\n",
"# row=round((i+1)/4)+1, col=i%2+1)\n",
"\n",
"# fig.update_layout(\n",
"# title_text = title, \n",
"# # xaxis = dict(title='Ora', \n",
"# # rangeslider=dict(visible=True), type='date')\n",
"# # )\n",
"# )\n",
"\n",
"\n",
"# ##############################################################################################################################\n",
"\n",
"# fig.update_xaxes(\n",
"# # mirror=True,\n",
"# # ticks='outside',\n",
"# # showline=True,\n",
"# # linecolor='lightgrey',\n",
"# gridcolor='white'\n",
"# )\n",
"\n",
"# fig.update_yaxes(\n",
"# # mirror=True,\n",
"# # ticks='outside',\n",
"# # showline=True,\n",
"# # linecolor='lightgrey',\n",
"# gridcolor='white'\n",
"# )\n",
"\n",
"# fig.update_layout({'plot_bgcolor': 'white',\n",
"# 'paper_bgcolor': 'white',\n",
"# })\n",
"\n",
"# ##############################################################################################################################\n",
"\n",
"# fig.update_layout(\n",
"# legend = dict(orientation='h',\n",
"# yanchor=\"top\", y = -0.25, xanchor=\"left\", x=0.01), \n",
"# )\n",
"# fig.update_yaxes(title_text = \"Power (kW)\")\n",
"\n",
"# # fig.show()\n",
"# if flag_show:\n",
"# fig.show()\n",
"# path = foldername_graphs_energy\n",
"# num_graph+=1\n",
"\n",
"# fig.write_html(path + str(num_graph) + \"_\" + title + \".html\")\n",
"# fig.write_image(path + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1800/13.2*5, scale = 4)"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [],
"source": [
"# ENERGY FLOW FOR ALL CACER for 4 days in the same chart\n",
"df = pd.read_csv(config[\"filename_CACER_energy_hourly\"]).fillna(0)\n",
"\n",
"# labels = {\"Eaut\":'Energia Autoconsumata dai prosumer', \n",
"# \"Econd\":'Energia condivisa dalla CACER', \n",
"# \"Eprel\": 'Energia prelevata e non condivisa',\n",
"# \"Eimm\": 'Energia immessa e non condivisa',\n",
"# \"Eperdite\": \"Perdite conversione\"}\n",
"\n",
"labels = {\"Eaut\":'Sel-consumed energy', \n",
" \"Econd\":'Shared energy', \n",
" \"Eprel\": 'Energy purchased and not shared',\n",
" \"Eimm\": 'Energy injected and not shared',\n",
" \"Eperdite\": \"Energy losses\"}\n",
"\n",
"fig = make_subplots(rows=2, cols=2)\n",
"# title = \"Flussi energetici di un giorno casuale per ogni stagione dell'anno\"\n",
"title = \"Energy flows in 4 days for each of the seasons of the year\"\n",
"\n",
"for i, active_day_str in enumerate([\"day_spring\", \"day_summer\", \"day_autumn\",\"day_winter\"]):\n",
"\n",
" active_day = str(config[active_day_str]) # deve essere una stringa, non un datetime.data\n",
" \n",
" df_plot = df[[string.startswith(active_day) for x,string in enumerate(df[\"dayhour\"])]] \n",
" assert len(df_plot) > 0, active_day + \" not found! Check inputs\"\n",
" assert len(df_plot) <= 24*4, active_day + \"has too may datapoints! Investigate\"\n",
"\n",
" df_plot = df_plot.set_index(\"dayhour\")\n",
" # df_plot.set_index(\"datetime\")\n",
"\n",
" # togliamo cio che non ci serve\n",
" # df_plot.drop(columns=[\"battery_cumulative_charge\",\"SOCkWh\",\"SOCperc\",\"LCF_aut\",\"SCF_aut\",\"Eprod\",\"Eaut_PV\", \"Eaut_batt\"], inplace=True, errors=\"ignore\")\n",
" # fixing order of columns, needed for the stacked area chart\n",
" df_plot = df_plot[[\"Eut\", \"Eprod\", \"Eaut\", \"Econd\", \"Eprel\", \"Eimm\", \"Eperdite\"]]\n",
"\n",
" df_plot[\"Eprel\"] = df_plot[\"Eprel\"] - df_plot[\"Econd\"] # diventa solo la quota non condivisa\n",
" df_plot[\"Eimm\"] = df_plot[\"Eimm\"] - df_plot[\"Econd\"] # diventa solo la quota non condivisa\n",
"\n",
" # # se siamo a base quartoraria, dobbiamo allora passare da kWh/quartodora a kW, moltiplicando per 4\n",
" # if config[\"delta_t\"] in [\"15min\", \"15Min\"]:\n",
" # df_plot = df_plot * 4 \n",
" \n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, y = df_plot[\"Eut\"], marker_color=data[\"Eut\"][\"col\"], mode='lines+markers',\n",
" name = data[\"Eut\"][\"label\"], \n",
" line_shape = line_shape,\n",
" textposition='top center',stackgroup=None),\n",
" row=round((i+1)/4)+1, col=i%2+1)\n",
" \n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, y = df_plot[\"Eprod\"], marker_color=data[\"Eprod\"][\"col\"], mode='lines+markers',\n",
" name = data[\"Eprod\"][\"label\"], \n",
" line_shape = line_shape,\n",
" textposition='top center',stackgroup=None),\n",
" row=round((i+1)/4)+1, col=i%2+1)\n",
" \n",
" # tutte queste sono cumulate, quindi stacked area\n",
" for column in df_plot.columns:\n",
" if column == \"datetime\" or column in [\"Eut\", \"Eprod\"]: continue\n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, y = df_plot[column], marker_color=data[column][\"col\"], mode='lines',\n",
" name = labels[column], \n",
" line_shape = line_shape,\n",
" textposition='top center',stackgroup='one'),\n",
" row=round((i+1)/4)+1, col=i%2+1)\n",
"\n",
" fig.update_layout(\n",
" title_text = title, \n",
" )\n",
"\n",
"\n",
" ##############################################################################################################################\n",
"\n",
" fig.update_xaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_yaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_layout({'plot_bgcolor': 'white',\n",
" 'paper_bgcolor': 'white',\n",
" })\n",
"\n",
" ##############################################################################################################################\n",
"\n",
"fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.25, xanchor=\"left\", x=0.01), \n",
" )\n",
"fig.update_yaxes(title_text = \"Power (kW)\")\n",
"\n",
"if flag_show: fig.show()\n",
"\n",
"num_graph+=1\n",
"\n",
"fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".html\")\n",
"fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1800/13.2*5, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **5. Configurations**"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [],
"source": [
"configurations = recap[\"configurations\"]"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_excel(filename_CACER_energy_monthly, sheet_name=\"CACER\")\n",
"plot_sankey(df, user = \"CACER\")"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [],
"source": [
"if len(configurations) > 1: # if we only have 1 configuration, then that is the \"CACER\" itself that was already analyzed\n",
"# if True: # if we only have 1 configuration, then that is the \"CACER\" itself that was already analyzed\n",
" for configuration in configurations: \n",
" df = pd.read_excel(filename_CACER_energy_monthly, sheet_name=configuration)\n",
" plot_sankey(df, user = configuration)\n",
" plot_pie_consumption(df, user = configuration)\n",
" plot_pie_generation(df, user = configuration)\n",
" plot_area_lifetime_consumption(df, user = configuration)\n",
" plot_area_lifetime_generation(df, user = configuration)\n",
" plot_area_year1_consumption(df, user = configuration)\n",
" plot_area_year1_generation(df, user = configuration)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **6. Prosumers**"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [],
"source": [
"filename_utenze_yml = config[\"filename_registry_user_types_yml\"]\n",
"utenti = yaml.safe_load(open(filename_utenze_yml, 'r'))\n",
"all_user_set = list(utenti.keys()) # this is the list of all users IDs of the \"utenti.yml\" file\n",
"prosumers = recap[\"list_types_prosumers\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **6.1. Sankey energy flows for a each prosumer**"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [],
"source": [
"if detailed_report:\n",
" for prosumer in prosumers:\n",
" \n",
" df = pd.read_excel(filename_CACER_energy_monthly, sheet_name=prosumer)\n",
"\n",
" Eaut_tot = df[\"Eaut\"].sum()\n",
" Eaut_PV_tot = df[\"Eaut_PV\"].sum()\n",
" Eaut_batt_tot = df[\"Eaut_batt\"].sum()\n",
" Eimm_tot = df[\"Eimm\"].sum()\n",
" Eimm_PV_tot = Eimm_tot # DA MODIFICARE QUANDO SI AVRà IL DINAMICO\n",
" Eimm_batt_tot = 0 # DA MODIFICARE QUANDO SI AVRà IL DINAMICO\n",
" Eut_tot = df[\"Eut\"].sum()\n",
" Eprod_tot = df[\"Eprod\"].sum()\n",
" Eprel_tot = df[\"Eprel\"].sum()\n",
" Eperdite_tot = df[\"Eperdite\"].sum()\n",
" Epv2batt_tot = Eprod_tot - Eaut_PV_tot - Eimm_PV_tot - Eperdite_tot\n",
"\n",
" # Ita\n",
" # data_prosumers = {\n",
" # \"Eprod\": {\"value\": Eprod_tot,\"col\": col[\"giallo\"],\"label\": \"Energia prodotta\"},\n",
" # \"Eperdite\": {\"value\": Eperdite_tot,\"col\": col[\"marrone\"],\"label\": \"Perdite conversione\"},\n",
" # \"Eprel\": {\"value\": Eprel_tot,\"col\": col[\"rosso\"],\"label\": \"Energia prelevata da rete\"},\n",
" # \"Eaut\": {\"value\": Eaut_tot,\"col\": col[\"arancione\"],\"label\": \"Energia autoconsumata\"},\n",
" # \"Eaut_PV\": {\"value\": Eaut_PV_tot,\"col\": col[\"arancione\"],\"label\": \"Energia autoconsumata da PV\"},\n",
" # \"Eaut_batt\": {\"value\": Eaut_batt_tot,\"col\": col[\"arancione\"],\"label\": \"Energia autoconsumata da accumulo\"},\n",
" # \"Eut\": {\"value\": Eut_tot,\"col\": col[\"violetto\"],\"label\": \"Energia consumata\"},\n",
" # \"Eimm\": {\"value\": Eimm_tot,\"col\": col[\"blu\"],\"label\": \"Energia immessa in rete\"},\n",
" # \"Eimm_PV\": {\"value\": Eimm_PV_tot,\"col\": col[\"blu\"],\"label\": \"Energia immessa da PV\"},\n",
" # \"Eimm_batt\": {\"value\": Eimm_batt_tot,\"col\": col[\"blu\"],\"label\": \"Energia immessa da accumulo\"}, \n",
" # \"Ebatt\": {\"col\": col[\"blu\"],\"label\": \"Accumulo\"}, \n",
" # \"Epv2batt\": {\"value\": Epv2batt_tot,\"col\": col[\"giallo\"],\"label\": \"Ricarica accumulo\"}, \n",
" # }\n",
" \n",
" # Eng\n",
" data_prosumers = {\n",
" \"Eprod\": {\"value\": Eprod_tot,\"col\": col[\"giallo\"],\"label\": \"Produced energy\"},\n",
" \"Eperdite\": {\"value\": Eperdite_tot,\"col\": col[\"marrone\"],\"label\": \"Energy loss\"},\n",
" \"Eprel\": {\"value\": Eprel_tot,\"col\": col[\"rosso\"],\"label\": \"Energy withdrawn from the grid\"},\n",
" \"Eaut\": {\"value\": Eaut_tot,\"col\": col[\"arancione\"],\"label\": \"Sel-consumed energy\"},\n",
" \"Eaut_PV\": {\"value\": Eaut_PV_tot,\"col\": col[\"arancione\"],\"label\": \"Self- consumed energy PV\"},\n",
" \"Eaut_batt\": {\"value\": Eaut_batt_tot,\"col\": col[\"arancione\"],\"label\": \"Self-consumed energy storage\"},\n",
" \"Eut\": {\"value\": Eut_tot,\"col\": col[\"violetto\"],\"label\": \"Energy consumption\"},\n",
" \"Eimm\": {\"value\": Eimm_tot,\"col\": col[\"blu\"],\"label\": \"Injected energy\"},\n",
" \"Eimm_PV\": {\"value\": Eimm_PV_tot,\"col\": col[\"blu\"],\"label\": \"Injected energy PV\"},\n",
" \"Eimm_batt\": {\"value\": Eimm_batt_tot,\"col\": col[\"blu\"],\"label\": \"Injected energy storage\"}, \n",
" \"Ebatt\": {\"col\": col[\"blu\"],\"label\": \"Storage\"}, \n",
" \"Epv2batt\": {\"value\": Epv2batt_tot,\"col\": col[\"giallo\"],\"label\": \"Storage charge\"}, \n",
" }\n",
"\n",
" flows = pd.read_excel(foldername_graphs + \"sankey_inputs.xlsx\", sheet_name=\"prosumer\")\n",
"\n",
" \"\"\"Plot the Sankey with the energy flows\n",
" more info: https://plotly.com/python/sankey-diagram/\n",
" \"\"\"\n",
" title = \"Energy flows prosumer\"\n",
" \n",
" fig = go.Figure(data=[go.Sankey(\n",
" valuesuffix = \"kWh\",\n",
" node = dict(\n",
" pad = 15,\n",
" thickness = 20,\n",
" line = dict(color = \"black\", width = 0.5),\n",
" label = [data_prosumers[\"Eprod\"][\"label\"], # node 0 = prod,\n",
" data_prosumers[\"Eaut\"][\"label\"], # node 1 = aut,\n",
" data_prosumers[\"Eut\"][\"label\"], # node 2 = consumi,\n",
" data_prosumers[\"Eimm\"][\"label\"], # node 3 = immessa in rete e venduta ,\n",
" data_prosumers[\"Ebatt\"][\"label\"], # node 4 = condivisa\n",
" data_prosumers[\"Eperdite\"][\"label\"], # node 5 = perdite\n",
" data_prosumers[\"Eprel\"][\"label\"], # node 6 = prelevata da rete e acquistata da fornitore\n",
" ],\n",
" color = [data_prosumers[\"Eprod\"][\"col\"], # node 0 = prod,\n",
" data_prosumers[\"Eaut\"][\"col\"], # node 1 = aut,\n",
" data_prosumers[\"Eut\"][\"col\"], # node 2 = consumi,\n",
" data_prosumers[\"Eimm\"][\"col\"], # node 3 = immessa in rete e venduta ,\n",
" data_prosumers[\"Ebatt\"][\"col\"], # node 4 = condivisa\n",
" data_prosumers[\"Eperdite\"][\"col\"], # node 5 = perdite\n",
" data_prosumers[\"Eprel\"][\"col\"], # node 6 = prelevata da rete e acquistata da fornitore\n",
" ],\n",
" ),\n",
" link = dict(\n",
" source = flows[\"source\"],\n",
" target = flows[\"target\"],\n",
" value = [data_prosumers[flows.loc[i,\"value\"]][\"value\"] for i in range(len(flows[\"value\"]))], # andiamo a prendere il valore del dizionario data corrispondente al nome dato nel csv\n",
" color = [data_prosumers[flows.loc[i,\"color\"]][\"col\"] for i in range(len(flows[\"color\"]))] # stessa cosa di sopra ma per il colore\n",
" #label = [\"%.2f\" % number for number in numbers]\n",
" ))])\n",
"\n",
" fig.update_layout(title_text=title + \" - \" + denomination_users[prosumer], font_size=10)\n",
" \n",
" if flag_show: fig.show()\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **6.2. Energy flows for specific days - prosumer**"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [],
"source": [
"if detailed_report:\n",
" # ENERGY FLOW FOR ALL PROSUMERS!\n",
" for prosumer in prosumers:\n",
" df = pd.read_csv(foldername_result_energy+prosumer+\".csv\")\n",
"\n",
" for active_day in [\"day_spring\", \"day_summer\", \"day_autumn\",\"day_winter\"]:\n",
"\n",
" active_day = str(config[active_day]) # deve essere una stringa, non un datetime.data\n",
"\n",
" title = \"Energy flows - \" + active_day + \" - Prosumer \" + denomination_users[prosumer] \n",
" \n",
" df_plot = df[[string.startswith(active_day) for x,string in enumerate(df[\"datetime\"])]] \n",
" assert len(df_plot) > 0, active_day + \" not found! Check inputs\"\n",
" assert len(df_plot) <= 24*4, active_day + \"has too may datapoints! Investigate\"\n",
"\n",
" df_plot = df_plot.set_index(\"datetime\")\n",
"\n",
" # togliamo cio che non ci serve\n",
" df_plot.drop(columns=[\"battery_cumulative_charge\",\"SOCkWh\",\"SOCperc\",\"LCF_aut\",\"SCF_aut\",\"Eprod\",\"Eaut_PV\", \"Eaut_batt\"], inplace=True, errors=\"ignore\")\n",
"\n",
" # se siamo a base quartoraria, dobbiamo allora passare da kWh/quartodora a kW, moltiplicando per 4\n",
" if config[\"delta_t\"] in [\"15min\", \"15Min\"]:\n",
" df_plot = df_plot * 4 \n",
"\n",
" fig = go.Figure()\n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, y = df_plot[\"Eut\"], marker_color=data_prosumers[\"Eut\"][\"col\"], mode='lines+markers',\n",
" name = data_prosumers[\"Eut\"][\"label\"], \n",
" textposition='top center',stackgroup=None))\n",
" \n",
" # tutte queste sono cumulate, quindi stacked area\n",
" for column in df_plot.columns:\n",
" if column == \"datetime\" or column == \"Eut\": continue\n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, y = df_plot[column], marker_color=data_prosumers[column][\"col\"], mode='lines',\n",
" name = data_prosumers[column][\"label\"], \n",
" textposition='top center',stackgroup='one'))\n",
"\n",
" fig.update_layout(\n",
" title_text = title, \n",
" )\n",
"\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.25, xanchor=\"left\", x=0.01), \n",
" )\n",
" fig.update_yaxes(title_text = \"Power (kW)\")\n",
"\n",
" ##############################################################################################################################\n",
"\n",
" fig.update_xaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_yaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_layout({'plot_bgcolor': 'white',\n",
" 'paper_bgcolor': 'white',\n",
" })\n",
"\n",
" ##############################################################################################################################\n",
" if flag_show: fig.show()\n",
" \n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \" - \" + prosumer + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \" - \" + prosumer + \".png\", width=1000, height=1100/13.2*5, scale = 4)"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [],
"source": [
"if detailed_report:\n",
" # ENERGY FLOW FOR ALL PROSUMERS!\n",
" for prosumer in prosumers:\n",
" df = pd.read_csv(foldername_result_energy+prosumer+\".csv\")\n",
"\n",
" # labels = {\"Eaut\":'Energia Autoconsumata dai prosumer', \n",
" # \"Econd\":'Energia condivisa dalla CACER', \n",
" # \"Eprel\": 'Energia prelevata e non condivisa',\n",
" # \"Eimm\": 'Energia immessa e non condivisa',\n",
" # \"Eperdite\": \"Perdite conversione\"}\n",
"\n",
" labels = {\"Eaut\":'Sel-consumed energy', \n",
" \"Econd\":'Shared energy', \n",
" \"Eprel\": 'Energy purchased and not shared',\n",
" \"Eimm\": 'Energy injected and not shared',\n",
" \"Eperdite\": \"Energy losses\"}\n",
"\n",
" fig = make_subplots(rows=2, cols=2)\n",
"\n",
" title = \"Energy flows in 4 days for each of the seasons of the year user - \" + denomination_users[prosumer]\n",
" # title = \"Flussi energetici di un giorno casuale per ogni stagione dell'anno - utente \" + denomination_users[prosumer]\n",
"\n",
" for i, active_day in enumerate([\"day_spring\", \"day_summer\", \"day_autumn\",\"day_winter\"]):\n",
"\n",
" active_day = str(config[active_day]) # deve essere una stringa, non un datetime.data\n",
" \n",
" df_plot = df[[string.startswith(active_day) for x,string in enumerate(df[\"datetime\"])]] \n",
" assert len(df_plot) > 0, active_day + \" not found! Check inputs\"\n",
" assert len(df_plot) <= 24*4, active_day + \"has too may datapoints! Investigate\"\n",
"\n",
" df_plot = df_plot.set_index(\"datetime\")\n",
" df_plot.index = pd.to_datetime(df_plot.index)\n",
"\n",
" # togliamo cio che non ci serve\n",
" # df_plot.drop(columns=[\"battery_cumulative_charge\",\"SOCkWh\",\"SOCperc\",\"LCF_aut\",\"SCF_aut\",\"Eprod\",\"Eaut_PV\", \"Eaut_batt\"], inplace=True, errors=\"ignore\")\n",
" # fixing order of columns, needed for the stacked area chart\n",
" df_plot = df_plot[[\"Eut\", \"Eprod\", \"Eaut\", \"Eprel\", \"Eimm\"]]\n",
"\n",
" # df_plot[\"Eprel\"] = df_plot[\"Eprel\"] - df_plot[\"Econd\"] # diventa solo la quota non condivisa\n",
" # df_plot[\"Eimm\"] = df_plot[\"Eimm\"] - df_plot[\"Econd\"] # diventa solo la quota non condivisa\n",
"\n",
" # se siamo a base quartoraria, dobbiamo allora passare da kWh/quartodora a kW, moltiplicando per 4\n",
" if config[\"delta_t\"] in [\"15min\", \"15Min\"]:\n",
" df_plot = df_plot * 4 \n",
" \n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, y = df_plot[\"Eut\"], marker_color=data[\"Eut\"][\"col\"], mode='lines+markers',\n",
" name = data[\"Eut\"][\"label\"], \n",
" line_shape = line_shape,\n",
" textposition='top center',stackgroup=None),\n",
" row=round((i+1)/4)+1, col=i%2+1)\n",
" \n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, y = df_plot[\"Eprod\"], marker_color=data[\"Eprod\"][\"col\"], mode='lines+markers',\n",
" name = data[\"Eprod\"][\"label\"], \n",
" line_shape = line_shape,\n",
" textposition='top center',stackgroup=None),\n",
" row=round((i+1)/4)+1, col=i%2+1)\n",
" \n",
" # tutte queste sono cumulate, quindi stacked area\n",
" for column in df_plot.columns:\n",
" if column == \"datetime\" or column in [\"Eut\", \"Eprod\"]: continue\n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, y = df_plot[column], marker_color=data[column][\"col\"], mode='lines',\n",
" name = labels[column], \n",
" line_shape = line_shape,\n",
" textposition='top center',stackgroup='one'),\n",
" row=round((i+1)/4)+1, col=i%2+1)\n",
"\n",
" fig.update_layout(\n",
" title_text = title, \n",
" )\n",
"\n",
" ##############################################################################################################################\n",
"\n",
" fig.update_xaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_yaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_layout({'plot_bgcolor': 'white',\n",
" 'paper_bgcolor': 'white',\n",
" })\n",
"\n",
" ##############################################################################################################################\n",
"\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.25, xanchor=\"left\", x=0.01), \n",
" )\n",
" fig.update_yaxes(title_text = \"Power (kW)\")\n",
"\n",
" if flag_show: fig.show()\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \" - \" + prosumer + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \" - \" + prosumer + \".png\", width=1000, height=1800/13.2*5, scale = 4)"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [],
"source": [
"if detailed_report:\n",
" for prosumer in prosumers:\n",
" \n",
" df = pd.read_excel(filename_CACER_energy_monthly, sheet_name=prosumer)\n",
"\n",
" Eaut_tot = df[\"Eaut\"].sum()\n",
" Eaut_PV_tot = df[\"Eaut_PV\"].sum()\n",
" Eaut_batt_tot = df[\"Eaut_batt\"].sum()\n",
" Eimm_tot = df[\"Eimm\"].sum()\n",
" Eimm_PV_tot = Eimm_tot # DA MODIFICARE QUANDO SI AVRà IL DINAMICO\n",
" Eimm_batt_tot = 0 # DA MODIFICARE QUANDO SI AVRà IL DINAMICO\n",
" Eut_tot = df[\"Eut\"].sum()\n",
" Eprod_tot = df[\"Eprod\"].sum()\n",
" Eprel_tot = df[\"Eprel\"].sum()\n",
" Eperdite_tot = df[\"Eperdite\"].sum()\n",
" Epv2batt_tot = Eprod_tot - Eaut_PV_tot - Eimm_PV_tot - Eperdite_tot\n",
"\n",
" ######################################## chart 1\n",
"\n",
" # title = f\"Allocazione dell'energia consumata da {denomination_users[prosumer]} - [%]\"\n",
" # labels = ['Energia Autoconsumata', 'Energia Acquistata da rete']\n",
"\n",
" title = f\"Allocation energy consumption - {denomination_users[prosumer]} - [%]\"\n",
" labels = ['Self-consumed energy', 'Energy purchased from grid']\n",
"\n",
" values_kWh = [Eaut_tot, Eprel_tot]\n",
"\n",
" fig = go.Figure(data=[go.Pie(labels=labels, values=values_kWh, pull=[0.05, 0.05])])\n",
"\n",
" fig.update_layout(title_text = title)\n",
"\n",
" fig.update_traces(marker=dict(colors=[col[\"arancione\"], col[\"rosso\"]]))\n",
"\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.1, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
" path = foldername_graphs_energy\n",
" num_graph+=1\n",
"\n",
" fig.write_html(path + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(path + str(num_graph) + \"_\" + title + \".png\", width=700, height=450, scale = 4)\n",
" \n",
" if flag_show: fig.show()\n",
"\n",
" ######################################## chart 2\n",
"\n",
" values_kWh = [Eaut_tot, Eimm_tot]\n",
"\n",
" fig = go.Figure(data=[go.Pie(labels=labels, values=values_kWh, pull=[0.05, 0.05])])\n",
"\n",
" fig.update_layout(title_text = title)\n",
"\n",
" fig.update_traces(marker=dict(colors=[col[\"arancione\"], col[\"blu\"]]))\n",
"\n",
" fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.1, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_energy + str(num_graph) + \"_\" + title + \" - \" + prosumer + \".html\")\n",
" fig.write_image(foldername_graphs_energy + str(num_graph) + \"_\" + title + \" - \" + prosumer + \".png\", width=700, height=450, scale = 4)\n",
" \n",
" if flag_show: fig.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **7. FINANCE**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **7.1. Bills**"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [],
"source": [
"columns = [\"me_cost\",\"transport_cost\",\"ogs_cost\",\"duty_cost\",\"vat_cost\"]\n",
"colors = charts[\"colors\"]\n",
"colors_bills = [colors[\"rosso\"],colors[\"arancione\"],colors[\"blu\"],colors[\"verde\"],colors[\"violetto\"]]\n",
"\n",
"path = config[\"foldername_graphs_bills\"]\n",
"\n",
"for user_type in user_types:\n",
" if not user_types[user_type][\"consuming\"]: continue\n",
" if user_types[user_type][\"num\"] == 0: continue\n",
"\n",
" if user_types[user_type][\"type\"] == \"consumer\": \n",
" prosumer_flag = False\n",
" scenarios = [\"bau\"]\n",
" else:\n",
" prosumer_flag = True\n",
" scenarios = [\"bau\",\"pv\"]\n",
"\n",
" for scenario in scenarios:\n",
" df = pd.read_excel(config[\"foldername_bills\"] + \"\\\\\" + user_type + \".xlsx\", sheet_name=scenario, index_col=\"month\")\n",
" \n",
"################################################# PLOT 1\n",
" \n",
" df_plot = df[columns]\n",
" \n",
" fig = go.Figure()\n",
" title = f\"Bills user {user_type} in scenario {scenario} - line chart\"\n",
" \n",
" for i, column in enumerate(columns):\n",
" fig.add_trace(go.Scatter(\n",
" x = df_plot.index, \n",
" y = df_plot[column], \n",
" marker_color = colors_bills[i], \n",
" name = column,\n",
" stackgroup='one',\n",
" ),\n",
" )\n",
" \n",
" fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='mese',\n",
" ))\n",
" \n",
" fig.update_yaxes(title_text = '€/month', exponentformat= \"none\")\n",
" \n",
" if flag_show: fig.show()\n",
" fig.write_html(path + title + \".html\")\n",
" fig.write_image(path + title + \".png\", width=1000, height=1200/13.2*5, scale = 4)\n",
"\n",
"################################################# PLOT 2 \n",
" \n",
" df_plot = df[columns]\n",
" \n",
" fig = go.Figure(data=[go.Pie(labels=df_plot.columns, values=df_plot.sum(axis=0), marker_colors=colors_bills, pull=[0.05, 0.05, 0.05, 0.05, 0.05])])\n",
" title = f\"Bills user {user_type} in scenario {scenario} - pie chart\"\n",
" \n",
" fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='mese',\n",
" ))\n",
" \n",
" if flag_show: fig.show()\n",
" fig.write_html(path + title + \".html\")\n",
" fig.write_image(path + title + \".png\", width=1000, height=1200/13.2*5, scale = 4)\n",
"\n",
" if prosumer_flag:\n",
"\n",
" ################################################# PLOT 3 \n",
" \n",
" pv = pd.read_excel(config[\"foldername_bills\"] + \"\\\\\" + user_type + \".xlsx\", sheet_name=\"pv\",index_col=\"month\")\n",
" bau = pd.read_excel(config[\"foldername_bills\"] + \"\\\\\" + user_type + \".xlsx\", sheet_name=\"bau\",index_col=\"month\")\n",
" fig = go.Figure()\n",
" \n",
" title = f\"Bills user {user_type} in scenario {scenario} - bar chart\"\n",
"\n",
" for i,column in enumerate(columns):\n",
"\n",
" fig.add_trace(go.Bar(\n",
" x = [\"bau\",\"pv\"], \n",
" y = [sum(bau[column]) / config[\"project_lifetime_yrs\"], sum(pv[column]) / config[\"project_lifetime_yrs\"]], \n",
" marker_color = colors_bills[i], \n",
" name = column,\n",
" ))\n",
"\n",
" fig.update_layout(barmode='stack')\n",
" fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='Scenarios',\n",
" ))\n",
" \n",
" fig.update_yaxes(title_text = '€/month', exponentformat= \"none\")\n",
"\n",
" if flag_show: fig.show()\n",
" \n",
" fig.write_html(path + title + \".html\")\n",
" fig.write_image(path + title + \".png\", width=1000, height=1200/13.2*5, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **7.2. PZO**"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(config[\"filename_output_csv_PZO_data\"],index_col=\"datetime\")\n",
"df.sort_index(inplace=True)\n",
"x = df.index\n",
"y = df[\"PZO\"]\n",
"title = \"PZO seasonal (€ per kWh)\"\n",
"output_file = foldername_graphs_finance + \"Input - \" + title \n",
"title_y = \"€/kWh\"\n",
"plot_scatter(x, y, title, title_y, output_file)"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [],
"source": [
"df[\"year\"] = df.index.str[0:4]\n",
"df_yr1 = df[df[\"year\"] == df[\"year\"][0]]\n",
"x = df_yr1.index\n",
"y = df_yr1[\"PZO\"]\n",
"title = \"PZO seasonal - year 1 (€ per kWh)\"\n",
"output_file = foldername_graphs_finance + \"Input - \" + title \n",
"title_y = \"€/kWh\"\n",
"plot_scatter(x, y, title, title_y, output_file)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(config[\"filename_FM_results_last_simulation\"],index_col=0)"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(config[\"filename_FM_results_last_simulation\"],index_col=0)\n",
"df.loc[\"IRR\"] = df.loc[\"IRR\"].replace(\"n.a.\",0)\n",
"df.loc[\"IRR\",:] = df.loc[\"IRR\",:].astype(float)"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [],
"source": [
"df_t = df.T\n",
"df_t.set_index(\"user_type\", inplace=True)\n",
"df_t\n",
"for i in df_t.index:\n",
" if i == 'ICT_1MW':\n",
" df_t.drop(index='ICT_1MW', inplace=True)"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [],
"source": [
"for i in df_t.index:\n",
" if i == 'CER':\n",
" df_t.drop(index='CER', inplace=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **7.3 Different economic flows calculation**"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [],
"source": [
"users_set = yaml.safe_load(open(config[\"filename_registry_users_yml\"], 'r'))"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [],
"source": [
"if detailed_report:\n",
" df = pd.read_csv(config[\"filename_FM_results_last_simulation\"],index_col=0)\n",
"\n",
" for user_type in user_types:\n",
" if user_types[user_type][\"dummy_user\"]: continue # no need to plot dummy users\n",
" \n",
" users_of_user_type = [user for user in users_set if users_set[user][\"user_type\"] == user_type] \n",
" if users_of_user_type == []: continue # alcune tipologie di utenti in questa simulaizone potrebbero essere in numero pari a 0 (in analisi di sensibilità puo accadere)\n",
" \n",
" user = users_of_user_type[0]\n",
" \n",
" df_results = df[user]\n",
" \n",
" # VERSIONE 2\n",
" # creo una copia senza valori, ma con le colonne e l'indice\n",
" df_ricavi = float(df_results.loc[\"revenues_total_taxable\"])\n",
" df_ricavi_BAU = 0\n",
"\n",
" df_costi = -(float(df_results.loc[\"capex_total\"]) + float(df_results.loc[\"debt_interest\"]) + float(df_results.loc[\"opex_total\"]) + float(df_results.loc[\"taxes_total\"]) + float(df_results.loc[\"electricity_bills\"]))\n",
" df_costi_BAU = - float(df_results.loc[\"electricity_bills_bau\"])\n",
"\n",
" ###############################################################################################################\n",
"\n",
" # questi ora avranno le unità di misura corrette. SERIES\n",
" df_spesa_energetica = df_costi - df_ricavi\n",
"\n",
" x = [\"BAU\", \"case study\"]\n",
" df_plot = pd.DataFrame(index=x)\n",
" df_plot.loc[\"case study\",\"spesa_energetica\"] = df_spesa_energetica\n",
" df_plot.loc[\"case study\",\"costi\"] = df_costi\n",
" df_plot.loc[\"case study\",\"ricavi\"] = df_ricavi\n",
" df_plot.loc[\"BAU\",\"ricavi\"] = df_ricavi_BAU\n",
" df_plot.loc[\"BAU\",\"costi\"] = df_costi_BAU\n",
" df_plot.loc[\"BAU\",\"spesa_energetica\"] = df_costi_BAU - df_ricavi_BAU\n",
"\n",
" # riportiamo tutti i df che ci servono da somma totale di tutto il progetto a valori annuali medi\n",
" df_plot = df_plot / config[\"project_lifetime_yrs\"]\n",
" \n",
" ################################## GRAFICO\n",
"\n",
" formato = \"€{:,.2f}\"\n",
" \n",
" # si crea un grafico a 3 quadranti su un'unica riga \n",
" fig = make_subplots(rows=1, cols=3, shared_yaxes=True, subplot_titles=(\"Energy expenditure\",\"Costs\", \"Revenues\")) # creo subplot con 3 grafici, con asse y in comune per mantenere rapporti relativi corretti\n",
"\n",
" if user not in users_set: \n",
" user_name = user\n",
" else:\n",
" user_name = users_set[user][\"denomination\"]\n",
"\n",
" title = \"Financial analysis user - \" + str(user_name)\n",
"\n",
" #CICLO SULLA SPESA ENERGETICA\n",
" fig.add_trace(go.Bar(\n",
" x = x, \n",
" y = df_plot[\"spesa_energetica\"], \n",
" marker_color = col[\"arancione\"], \n",
" name = \"Total energy expenditure\",\n",
" text = df_plot[\"spesa_energetica\"].map('€{:,.0f}'.format), \n",
" textposition='auto',\n",
" ),\n",
" row=1, col=1 # si indica il quadrante in cui si creerà il grafico\n",
" )\n",
" ### aggiungo il riempitivo in rosso tratteggiato\n",
" fig.add_trace(go.Bar(\n",
" x = x, \n",
" y = df_plot.loc[\"BAU\", \"spesa_energetica\"] - df_plot[\"spesa_energetica\"], # si indicano anche in questo caso due valori, si fissa 0 per lo scenario BAU\n",
" marker_color = col[\"rosso\"], \n",
" marker_pattern_shape=[\"\",\"/\",\"/\",\"/\"],\n",
" name = \"Risparmio complessivo\",\n",
" ),\n",
" row=1, col=1 # si indica il quadrante in cui si creerà il grafico\n",
" )\n",
"\n",
" #### ANNOTATIONS\n",
" # max_value = max(df_spesa_energetica_BAU.loc[user], df_spesa_energetica_CER.loc[user])\n",
" # risparmio = round(df_spesa_energetica_BAU.loc[user] - df_spesa_energetica_CER.loc[user],1)\n",
" # mensilita = round(risparmio/(df_spesa_energetica_BAU.loc[user] /12),1)\n",
" # fig.add_annotation(x=1, y=0,\n",
" # text=\"Risparmi annui medi: \" + formato.format(risparmio),\n",
" # showarrow=False,\n",
" # yshift=50)\n",
" # fig.add_annotation(x=1, y=0,\n",
" # text=\"(equivalente a \" + str(mensilita) + \" mensilità all'anno)\",\n",
" # showarrow=False,\n",
" # yshift=50-20)\n",
"\n",
" #CICLO SUI COSTI\n",
" fig.add_trace(go.Bar(\n",
" x = x,\n",
" y = df_plot[\"costi\"], \n",
" marker_color = \"#9ED4B9\",\n",
" # mode = \"text\", \n",
" name = \"Costi\",\n",
" text = df_plot[\"costi\"].map('€{:,.0f}'.format),\n",
" textposition='auto',\n",
" ),\n",
" row=1, col=2 # si indica il quadrante in cui si creerà il grafico\n",
" )\n",
"\n",
" #CICLO SUI RICAVI\n",
" fig.add_trace(go.Bar(\n",
" x = x, \n",
" y = df_plot[\"ricavi\"], \n",
" marker_color = \"#FADD75\",\n",
" # mode = \"text\", \n",
" name = \"Ricavi\",\n",
" text = df_plot[\"ricavi\"].map('€{:,.0f}'.format),\n",
" textposition='auto',\n",
" ),\n",
" row=1, col=3 # si indica il quadrante in cui si creerà il grafico\n",
" )\n",
"\n",
" fig.update_layout(title_text=title)\n",
" fig.update_layout(showlegend=True, barmode='relative')\n",
" fig.update_layout(legend=dict(\n",
" orientation=\"h\",\n",
" yanchor=\"bottom\",\n",
" y=-0.3,\n",
" xanchor=\"right\",\n",
" x=1\n",
" ))\n",
" # fig.update_yaxes(title_text=\"€ all'anno\", row=1, col=1)\n",
" fig.update_yaxes(title_text=\"Yearly amount (€/year)\", row=1, col=1)\n",
" ##############################################################################################################################\n",
"\n",
" fig.update_xaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_yaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_layout({'plot_bgcolor': 'white',\n",
" 'paper_bgcolor': 'white',\n",
" })\n",
"\n",
" ##############################################################################################################################\n",
"\n",
" if flag_show: fig.show()\n",
" \n",
" path = config[\"foldername_graphs_finance\"]\n",
" fig.write_html(path + title + \"_\" + title + \".html\")\n",
" fig.write_image(path + title + \"_\" + title + \".png\", width=1000, height=1200/13.2*5, scale = 4)"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [],
"source": [
"# incentivo per configurazione\n",
"df = pd.read_csv(config[\"filename_CACER_incentivi_per_configuration\"], index_col = 0)"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [],
"source": [
"colori = [col[\"arancione\"], col[\"verde_piemonte\"], col[\"blu_piemonte\"], col[\"rosso_piemonte\"], col[\"giallo\"], col[\"violetto\"]] # aggiungi se ci sono piu di 6 configurazioni"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [],
"source": [
"df_plot = df.drop(columns=[\"valorizzazione\",\"incentivo\"])\n",
"title = 'Incentives per types and per configurations'\n",
"\n",
"fig = go.Figure()\n",
"for column in df_plot.columns:\n",
"\n",
" ################ IN PERCENTUALE\n",
" fig.add_trace(go.Bar(\n",
" x = df.index, \n",
" y = df_plot[column], \n",
" name = column,\n",
" ),\n",
" )\n",
"\n",
"fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" xaxis = dict(title='month',\n",
" ))\n",
"\n",
"fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.2, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
"fig.update_layout(barmode='stack')\n",
"\n",
"fig.update_yaxes(title_text = 'Euro per month (€/m)', exponentformat= \"none\")\n",
"\n",
"# fig.update_yaxes(title_text = 'Euro al', secondary_y=True, exponentformat= \"none\",\n",
"# mirror=True,\n",
"# # ticks='outside',\n",
"# showline=True,\n",
"# # linecolor='black',\n",
"# gridcolor='lightgrey')\n",
"\n",
"if flag_show: fig.show()\n",
"\n",
"path = foldername_graphs_energy\n",
"num_graph+=1\n",
"\n",
"fig.write_html(path + str(num_graph) + \"_\" + title + \"CACER.html\")\n",
"fig.write_image(path + str(num_graph) + \"_\" + title + \"CACER.png\", width=1000, height=1100/13.2*5, scale = 4)"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [],
"source": [
"df_agg = df_plot.sum()\n",
"title = \"Incentives generation from the different configurations\"\n",
"fig = go.Figure(data=[go.Pie(labels=df_agg.index, values=df_agg, pull = 0.1)])\n",
"fig.update_layout(plot_bgcolor='white',\n",
" title_text = title, \n",
" )\n",
"\n",
"if flag_show: fig.show()\n",
"\n",
"path = foldername_graphs_finance\n",
"num_graph+=1\n",
"\n",
"fig.write_html(path + str(num_graph) + \"_\" + title + \" - CACER.html\")\n",
"fig.write_image(path + str(num_graph) + \"_\" + title + \" - CACER.png\", width=800, height=400, scale = 4)"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [],
"source": [
"totals = []\n",
"for configuration in configurations:\n",
" # print(configuration)\n",
" cols = [item for item in list(df_agg.index) if configuration in item]\n",
" total = df_agg[cols].sum()\n",
" totals.append(total)\n",
"\n",
"fig = go.Figure(data=[go.Pie(labels=configurations, values=totals, pull = [0.05] * len(configurations))])\n",
"fig.update_layout(title_text = title)\n",
"\n",
"fig.update_traces(marker=dict(colors=colori[:len(configurations)]))\n",
"# fig.update_traces(marker=dict(colors=[greys[0],greys[2], greys[4]]))\n",
"\n",
"fig.update_layout(\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", y = -0.1, xanchor=\"left\", x=0.01), \n",
" )\n",
"\n",
"if flag_show: fig.show()\n",
"\n",
"path = foldername_graphs_finance\n",
"num_graph+=1\n",
"\n",
"fig.write_html(path + str(num_graph) + \"_\" + title + \".html\")\n",
"fig.write_image(path + str(num_graph) + \"_\" + title + \".png\", width=900, height=400, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## **8. Discounted Cash Flows**"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(config[\"filename_FM_results_last_simulation\"],index_col=0)\n",
"df_t = df.T"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [],
"source": [
"colonne_FC = [string for x,string in enumerate(df_t.columns) if string.startswith(\"DCF_yr\")]\n",
"df_FC = df_t.copy()\n",
"df_FC = df_FC[colonne_FC].astype(float)\n",
"df_FC\n",
"df_FC_cum = df_FC.cumsum(axis=1).T"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **8.1. Discounted Cash Flows for the different users**"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [],
"source": [
"if detailed_report:\n",
" fig = go.Figure()\n",
"\n",
" title = \"Aggregated Discounted Cah Flows for user types\"\n",
"\n",
" ###############################################################################################################################\n",
"\n",
" x = list(df_FC_cum.index)\n",
" # x = recap[\"list_user_types_CER\"]\n",
"\n",
" # years for the x axis\n",
" x_list = ()\n",
" for i, value in enumerate(x):\n",
" x_list +=(i+1, )\n",
"\n",
" user_type_list_found = [] # plotting only one user per user_type. initialization of the user type list\n",
"\n",
" ###############################################################################################################################\n",
"\n",
" users = [user for user in df_FC_cum.columns if user.startswith(\"u_\")]\n",
"\n",
" for i, item in enumerate(users):\n",
"\n",
" # plotting only one user per user_type.\n",
" if item in users_set:\n",
" if users_set[item][\"user_type\"] in user_type_list_found or users_set[item][\"dummy_user\"] == True:\n",
" continue \n",
" else: \n",
" user_type_list_found.append(users_set[item][\"user_type\"])\n",
" \n",
" if item in user_type_list_consuming:\n",
" item_name = denomination_users[item]\n",
" elif item == \"CACER\" or item in recap[\"stakeholders\"]:\n",
" item_name = item\n",
" else:\n",
" item_name = users_set[item][\"denomination\"]\n",
" \n",
" # adding the trace to the figure\n",
" fig.add_trace(go.Bar(\n",
" x = x_list, \n",
" y = df_FC_cum[item], \n",
" name = item_name,\n",
" ))\n",
" \n",
" ###############################################################################################################################\n",
"\n",
" # if type(payback_CER) != str:\n",
" # fig.add_annotation(x=payback_CER, y=50,\n",
" # text=\"Anno CACER payback: \" + str(payback_CER),\n",
" # showarrow=False,\n",
" # arrowhead=1)\n",
" \n",
" ###############################################################################################################################\n",
"\n",
" fig.update_layout(\n",
" title_text = title, \n",
" xaxis = dict(title='anni',\n",
" tickmode = 'linear',\n",
" tick0 = 0,\n",
" dtick = 1\n",
" ),\n",
" yaxis = dict(title='€'\n",
" ),\n",
"\n",
" legend = dict(orientation='h',\n",
" yanchor=\"top\", \n",
" y = -0.2, \n",
" xanchor=\"left\", \n",
" x=0.01), \n",
" )\n",
"\n",
" fig.update_layout(showlegend=True)\n",
" ##############################################################################################################################\n",
"\n",
" fig.update_xaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_yaxes(\n",
" gridcolor='white'\n",
" )\n",
"\n",
" fig.update_layout({'plot_bgcolor': 'white',\n",
" 'paper_bgcolor': 'white',\n",
" })\n",
"\n",
" ############################################################################################################################\n",
"\n",
" if flag_show: fig.show()\n",
"\n",
" num_graph+=1\n",
"\n",
" fig.write_html(foldername_graphs_finance + str(num_graph) + \"_\" + title + \".html\")\n",
" fig.write_image(foldername_graphs_finance + str(num_graph) + \"_\" + title + \".png\", width=1000, height=1100/13.2*5, scale = 4)"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [],
"source": [
"def financial_sums():\n",
"\n",
" for file in glob.glob(config[\"foldername_finance_users\"]+'*.xlsx'): \n",
" \n",
" user = file.split(\"\\\\\")[-1].split(\".\")[0]\n",
" \n",
" # discount_factor = pd.read_excel(config[\"foldername_finance_users\"]+user+\".xlsx\", sheet_name=\"totals\", index_col=0).T[\"discount_factor\"] # month_number on index\n",
"\n",
" df = pd.read_excel(config[\"foldername_finance_users\"]+user+\".xlsx\",index_col=0)\n",
"\n",
" # LOOP OVER PLANTS AND CACER SHEETS\n",
" sheet_names = pd.ExcelFile(config[\"foldername_finance_users\"]+ user +\".xlsx\").sheet_names\n",
" sheets = [sheet for sheet in sheet_names if sheet.startswith(\"p_\")]\n",
" sheets.append(\"CACER\")\n",
" flag_initialization = True\n",
"\n",
" for sheet in sheets:\n",
"\n",
" df = pd.read_excel(config[\"foldername_finance_users\"]+user+\".xlsx\", sheet_name=sheet, index_col=0).drop(\"month\")\n",
"\n",
" # df = df * discount_factor # Discounting\n",
"\n",
" df_aggregated = df.sum(axis=1)\n",
" \n",
" capex_index = [index for index in df_aggregated.index if index.startswith(\"capex\")]\n",
" if \"debt_interest\" in capex_index: capex_index.append(\"debt_interest\") \n",
" opex_index = [index for index in df_aggregated.index if index.startswith(\"opex\")]\n",
" revenues_index = [index for index in df_aggregated.index if index.startswith(\"revenues\")]\n",
"\n",
" all_indexes = capex_index + opex_index + revenues_index\n",
"\n",
" df_sheet = pd.DataFrame(df_aggregated[all_indexes], columns=[\"value\"]).reset_index().rename(columns={\"index\":\"item\"})\n",
"\n",
" df_sheet = df_sheet[df_sheet[\"value\"] != 0]\n",
"\n",
" df_sheet[\"source\"] = sheet\n",
" df_sheet[\"target\"] = user\n",
"\n",
" # check if df_merged exists already within the variables, if yes just append the dataframe\n",
" if not flag_initialization:\n",
" df_merged = pd.concat([df_merged, df_sheet], ignore_index=True)\n",
" else:\n",
" df_merged = df_sheet\n",
" flag_initialization = False\n",
" \n",
" assert not df_merged.isnull().values.any(), f\"ERROR: There are NaN values in the {user} merged dataframe\"\n",
" \n",
" # check if df_results exists already within the variables, if yes just append the dataframe\n",
" if \"df_results\" in locals():\n",
" df_results = pd.concat([df_results, df_merged], ignore_index=True)\n",
" else:\n",
" df_results = df_merged\n",
" \n",
" df_results[\"sign\"] = \"cost\"\n",
" df_results.loc[df_results[\"value\"] > 0, \"sign\"] = \"revenue\"\n",
"\n",
" df_results[\"value\"] = df_results[\"value\"].abs()\n",
" \n",
" return df_results"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {},
"outputs": [],
"source": [
"df_results = financial_sums()"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [],
"source": [
"title = \"Cash Flows in the CACER\"\n",
"\n",
"df_results_raw = df_results.copy()\n",
"\n",
"# https://medium.com/@enigma.pythonml/how-to-create-sankey-diagrams-from-data-frames-in-python-plotly-and-kaggles-titanic-data-1f7d56b28096\n",
"colors = {\"cost\": col[\"rosso\"], \"revenue\": col[\"blu\"]}\n",
"\n",
"#for using with 'label' parameter in plotly \n",
"#https://sparkbyexamples.com/pandas/pandas-find-unique-values-from-columns\n",
"unique_source_target = list(pd.unique(df_results[['source', 'target']].values.ravel('K')))\n",
"\n",
"#for assigning unique number to each source and target\n",
"mapping_dict = {k: v for v, k in enumerate(unique_source_target)}\n",
"\n",
"#mapping of full data\n",
"df_results['source'] = df_results['source'].map(mapping_dict)\n",
"df_results['target'] = df_results['target'].map(mapping_dict)\n",
"\n",
"df_results['color'] = df_results['sign'].map(colors)\n",
"\n",
"#converting full dataframe as list for using with in plotly\n",
"df_results_dict = df_results.to_dict(orient='list')\n",
"\n",
"#Sankey Diagram Code \n",
"fig = go.Figure(data=[go.Sankey(\n",
" node = dict(\n",
" pad = 15,\n",
" thickness = 20,\n",
" line = dict(color = \"black\", width = 0.5),\n",
" label = unique_source_target,\n",
" \n",
" ),\n",
" link = dict(\n",
" source = df_results_dict[\"source\"],\n",
" target = df_results_dict[\"target\"],\n",
" value = df_results_dict[\"value\"],\n",
" label = df_results_dict[\"item\"],\n",
" color = df_results_dict[\"color\"],\n",
" \n",
" ))])\n",
"\n",
"fig.update_layout(title_text=title, font_size=10, width=1000, height=600)\n",
"\n",
"if flag_show: fig.show()\n",
"\n",
"num_graph+=1\n",
"\n",
"fig.write_html(foldername_graphs_finance + str(num_graph) + \"_\" + title + \".html\")\n",
"fig.write_image(foldername_graphs_finance + str(num_graph) + \"_\" + title + \".png\", width=1000, height=700, scale = 4)"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {},
"outputs": [],
"source": [
"df_results = df_results_raw[df_results_raw[\"sign\"] == \"cost\"]\n",
"title = \"Cash Flows in the CACER - Costs\"\n",
"\n",
"# https://medium.com/@enigma.pythonml/how-to-create-sankey-diagrams-from-data-frames-in-python-plotly-and-kaggles-titanic-data-1f7d56b28096\n",
"colors = {\"cost\": col[\"rosso\"], \"revenue\": col[\"blu\"]}\n",
"\n",
"#for using with 'label' parameter in plotly \n",
"#https://sparkbyexamples.com/pandas/pandas-find-unique-values-from-columns\n",
"unique_source_target = list(pd.unique(df_results[['source', 'target']].values.ravel('K')))\n",
"\n",
"#for assigning unique number to each source and target\n",
"mapping_dict = {k: v for v, k in enumerate(unique_source_target)}\n",
"\n",
"#mapping of full data\n",
"df_results['source'] = df_results['source'].map(mapping_dict)\n",
"df_results['target'] = df_results['target'].map(mapping_dict)\n",
"\n",
"df_results['color'] = df_results['sign'].map(colors)\n",
"\n",
"#converting full dataframe as list for using with in plotly\n",
"df_results_dict = df_results.to_dict(orient='list')\n",
"\n",
"#Sankey Diagram Code \n",
"fig = go.Figure(data=[go.Sankey(\n",
" node = dict(\n",
" pad = 15,\n",
" thickness = 20,\n",
" line = dict(color = \"black\", width = 0.5),\n",
" label = unique_source_target,\n",
" \n",
" ),\n",
" link = dict(\n",
" source = df_results_dict[\"source\"],\n",
" target = df_results_dict[\"target\"],\n",
" value = df_results_dict[\"value\"],\n",
" label = df_results_dict[\"item\"],\n",
" color = df_results_dict[\"color\"],\n",
" \n",
" ))])\n",
"\n",
"fig.update_layout(title_text=title, font_size=10, width=1000, height=600)\n",
"\n",
"if flag_show: fig.show()\n",
"\n",
"num_graph+=1\n",
"\n",
"fig.write_html(foldername_graphs_finance + str(num_graph) + \"_\" + title + \".html\")\n",
"fig.write_image(foldername_graphs_finance + str(num_graph) + \"_\" + title + \".png\", width=1000, height=700, scale = 4)"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [],
"source": [
"df_results = df_results_raw[df_results_raw[\"sign\"] == \"revenue\"]\n",
"title = \"Cash Flows in the CACER - Revenues\"\n",
"\n",
"# https://medium.com/@enigma.pythonml/how-to-create-sankey-diagrams-from-data-frames-in-python-plotly-and-kaggles-titanic-data-1f7d56b28096\n",
"colors = {\"cost\": col[\"rosso\"], \"revenue\": col[\"blu\"]}\n",
"\n",
"#for using with 'label' parameter in plotly \n",
"#https://sparkbyexamples.com/pandas/pandas-find-unique-values-from-columns\n",
"unique_source_target = list(pd.unique(df_results[['source', 'target']].values.ravel('K')))\n",
"\n",
"#for assigning unique number to each source and target\n",
"mapping_dict = {k: v for v, k in enumerate(unique_source_target)}\n",
"\n",
"#mapping of full data\n",
"df_results['source'] = df_results['source'].map(mapping_dict)\n",
"df_results['target'] = df_results['target'].map(mapping_dict)\n",
"\n",
"df_results['color'] = df_results['sign'].map(colors)\n",
"\n",
"#converting full dataframe as list for using with in plotly\n",
"df_results_dict = df_results.to_dict(orient='list')\n",
"\n",
"#Sankey Diagram Code \n",
"fig = go.Figure(data=[go.Sankey(\n",
" node = dict(\n",
" pad = 15,\n",
" thickness = 20,\n",
" line = dict(color = \"black\", width = 0.5),\n",
" label = unique_source_target,\n",
" \n",
" ),\n",
" link = dict(\n",
" source = df_results_dict[\"source\"],\n",
" target = df_results_dict[\"target\"],\n",
" value = df_results_dict[\"value\"],\n",
" label = df_results_dict[\"item\"],\n",
" color = df_results_dict[\"color\"],\n",
" \n",
" ))])\n",
"\n",
"fig.update_layout(title_text=title, font_size=10, width=1000, height=600)\n",
"\n",
"if flag_show: fig.show()\n",
"\n",
"num_graph+=1\n",
"\n",
"fig.write_html(foldername_graphs_finance + str(num_graph) + \"_\" + title + \".html\")\n",
"fig.write_image(foldername_graphs_finance + str(num_graph) + \"_\" + title + \".png\", width=1000, height=700, scale = 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## DOCX"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [],
"source": [
"provincia = config[\"provincia_it\"]\n",
"regione = province_to_region()\n",
"\n",
"file_recap_yml = config['filename_recap']\n",
"recap = yaml.safe_load(open(file_recap_yml, 'r'))"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"**** Report exported! ****\n"
]
}
],
"source": [
"from docx import Document\n",
"from docx.shared import Inches\n",
"from docx.enum.text import WD_ALIGN_PARAGRAPH\n",
"\n",
"filename_report = config['filename_template_report']\n",
"\n",
"document = Document(filename_report)\n",
"\n",
"document.add_heading('Report simulation CACER', 0)\n",
"\n",
"p = document.add_paragraph('Simulation tool producet by: \\nRSE - Technical Unity of \"Efficienza Energetica Usi Finali e Territorio\" - Research Group of \"Utente al centro \\n')\n",
"p.add_run('Data: ')\n",
"p.add_run(datetime.now().strftime(\"%d-%m-%Y\")).bold = True\n",
"\n",
"########################################### RECAP DATI INPUT #################################\n",
"\n",
"document.add_heading('CACER - Input data for the simulation', level=1)\n",
"\n",
"document.add_paragraph(\n",
" 'Location: '+ provincia + \" - \" + regione,# style='List Bullet'\n",
")\n",
"\n",
"document.add_paragraph(\n",
" 'Total CACER users: ' + str(recap['numero_prosumers']+recap['numero_producers']+recap['numero_consumers']) + \":\",\n",
").bold = True\n",
"\n",
"document.add_paragraph(\n",
" 'Number of prosumers: ' + str(recap['numero_prosumers']), style='List Bullet'\n",
" )\n",
"\n",
"document.add_paragraph(\n",
" 'Number of plants in total injection: ' + str(recap['numero_producers']), style='List Bullet'\n",
" )\n",
"\n",
"document.add_paragraph(\n",
" 'Number of consumers: ' + str(recap['numero_consumers']), style='List Bullet'\n",
" )\n",
"\n",
"##################################################################################################\n",
"\n",
"# assets/general/\n",
"\n",
"document.add_heading('General plots', level=1)\n",
"\n",
"for file in glob.glob(foldername_graphs_generali + \"*.png\"):\n",
" document.add_picture(file, width=Inches(6.5))\n",
"\n",
" last_paragraph = document.paragraphs[-1]\n",
" last_paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER\n",
"\n",
"##################################################################################################\n",
"\n",
"# assets/gen_pv/\n",
"\n",
"document.add_heading('Sun charts', level=1)\n",
"\n",
"for file in glob.glob(config[\"foldername_graph_pv\"] + \"*.png\"):\n",
" document.add_picture(file, width=Inches(4))\n",
"\n",
" last_paragraph = document.paragraphs[-1]\n",
" last_paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER\n",
"\n",
"##################################################################################################\n",
"\n",
"# assets/energy/ -> only CACER plots\n",
"\n",
"document.add_heading('CACER - Results', level=1)\n",
"\n",
"for file in glob.glob(foldername_graphs_energy + \"*\" + \"CACER.png\"):\n",
" if \"Allocation\" in file:\n",
" w = 4\n",
" else: \n",
" w = 6.5\n",
" document.add_picture(file, width=Inches(w))\n",
"\n",
" last_paragraph = document.paragraphs[-1]\n",
" last_paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER\n",
"\n",
"##################################################################################################\n",
"\n",
"# assets/energy/ -> only prosumers' plots\n",
"\n",
"document.add_heading('Prosumers - Risultati energetici', level=1)\n",
"\n",
"for prosumer_type in recap[\"list_types_prosumers\"]:\n",
" document.add_heading('Prosumer: ' + prosumer_type, level=2)\n",
" for file in glob.glob(foldername_graphs_energy + \"*\" + prosumer_type + \".png\"):\n",
" if \"Allocation\" in file:\n",
" w = 4\n",
" else: \n",
" w = 6.5\n",
" document.add_picture(file, width=Inches(w))\n",
"\n",
" last_paragraph = document.paragraphs[-1]\n",
" last_paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER\n",
"\n",
"##################################################################################################\n",
"\n",
"# assets/finance/\n",
"\n",
"document.add_heading('CACER - Financial results', level=1)\n",
"\n",
"for file in glob.glob(foldername_graphs_finance + \"*.png\"):\n",
" document.add_picture(file, width=Inches(6.5))\n",
"\n",
" last_paragraph = document.paragraphs[-1]\n",
" last_paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER\n",
"\n",
"##################################################################################################\n",
"\n",
"# assets/bills/\n",
"\n",
"document.add_heading('Bills results', level=1)\n",
"\n",
"for file in glob.glob(config[\"foldername_graphs_bills\"] + \"*.png\"):\n",
" document.add_picture(file, width=Inches(6.5))\n",
"\n",
" last_paragraph = document.paragraphs[-1]\n",
" last_paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER\n",
"\n",
"##################################################################################################\n",
"\n",
"output_file_docx = config[\"foldername_result_finance\"] + recap[\"case_denomination\"] + '.docx'\n",
"document.save(output_file_docx)\n",
"print(\"\\n**** Report exported! ****\")"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {},
"outputs": [],
"source": [
"os.startfile(output_file_docx)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.10"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}