{ "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 comparisons**" ] }, { "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 }