diff --git a/dev/general_scan_v3.ipynb b/dev/general_scan_v3.ipynb new file mode 100644 index 0000000..e7f67b9 --- /dev/null +++ b/dev/general_scan_v3.ipynb @@ -0,0 +1,897 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [], + "source": [ + "from functions_v2 import*\n", + "from methods import MethodFinder\n", + "\n", + "import brightway2 as bw\n", + "import bw2data as bd\n", + "import bw2analyzer as ba\n", + "\n", + "#reduce?\n", + "import ast\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Biosphere database already present!!! No setup is needed\n" + ] + } + ], + "source": [ + "bd.projects.set_current(\"premise-validation-try1\")\n", + "bw.bw2setup()\n", + "\n", + "bio3=bw.Database('biosphere3')\n", + "ei39=bw.Database('ecoinvent 3.9.1 cutoff')\n", + "ei39SSP2=bw.Database('ei_cutoff_3.9_image_SSP2-RCP19_2050 2024-06-27')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "LCA DATA TO EXCEL " + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [], + "source": [ + "#sector filters file names/paths\n", + "\n", + "cement = 'cement_small.yaml'\n", + "electricity = 'electricity_small.yaml'\n", + "fuels= 'fuels_small.yaml'\n", + "steel = 'steel_small.yaml'\n", + "transport = 'transport_small.yaml'" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Cement': {'yaml': 'yamls\\\\cement_small.yaml', 'yaml identifier': 'Cement'},\n", + " 'Electricity': {'yaml': 'yamls\\\\electricity_small.yaml',\n", + " 'yaml identifier': 'Electricity'}}" + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "files_dict={}\n", + "files_dict['Cement']={'yaml': 'yamls\\cement_small.yaml',\n", + " 'yaml identifier': 'Cement'}\n", + "files_dict['Electricity']= {'yaml':'yamls\\electricity_small.yaml',\n", + " 'yaml identifier': 'Electricity'} #yaml identifier is the name of the filter in the yaml file, in the first line.\n", + "files_dict" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [], + "source": [ + "# Assuming generate_sets_from_filters is a predefined function\n", + "def process_yaml_files(files_dict, database):\n", + " main_dict=files_dict.copy()\n", + " for key, value in main_dict.items():\n", + " yaml_file = value['yaml']\n", + " yaml_identifier = value['yaml identifier']\n", + " \n", + " # Generate the sector activities\n", + " sector_activities = generate_sets_from_filters(yaml_file, database=database)\n", + " \n", + " # Convert the set of activities to a list\n", + " activities_list = list(sector_activities[yaml_identifier])\n", + " \n", + " # Add to the sectors_dict\n", + " main_dict[key]['activities'] = activities_list\n", + " \n", + " return main_dict\n" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [], + "source": [ + "sectors_dict= process_yaml_files(files_dict, ei39SSP2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(sectors_dict['Electricity']['activities'][0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sectors_dict['Electricity']['activities'][0].as_dict()['name']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sectors_dict['Electricity']['activities'][4].as_dict()['name']" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'method_1': {'object': Brightway2 Method: IPCC 2013: climate change: global warming potential (GWP100),\n", + " 'method name': ('IPCC 2013',\n", + " 'climate change',\n", + " 'global warming potential (GWP100)'),\n", + " 'short name': 'global warming potential (GWP100)',\n", + " 'unit': 'kg CO2-Eq'},\n", + " 'method_2': {'object': Brightway2 Method: EN15804: inventory indicators ISO21930: Cumulative Energy Demand - non-renewable energy resources,\n", + " 'method name': ('EN15804',\n", + " 'inventory indicators ISO21930',\n", + " 'Cumulative Energy Demand - non-renewable energy resources'),\n", + " 'short name': 'Cumulative Energy Demand - non-renewable energy resources',\n", + " 'unit': 'megajoule'}}" + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#Get Methods\n", + "finder=MethodFinder()\n", + "finder.find_and_create_method(criteria=['IPCC', '2013', 'GWP100'], exclude=['no LT'])\n", + "finder.find_and_create_method(criteria=['EN15804','Cumulative', 'non-renewable' ])\n", + "# finder.find_and_create_method(criteria=['land occupation','selected'])\n", + "# finder.find_and_create_method(criteria=['EN15804','fresh water'])\n", + "method_dict=finder.get_all_methods()\n", + "method_dict" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [], + "source": [ + "def sector_lca_scores(main_dict, method_dict):\n", + " '''\n", + " Generates the LCA scores for the sectors activities in the main dictionary \n", + " for the different methods in the method dictionary.\n", + "\n", + " It returns the main dictionary updated as scores dictionary which also holds the former information for each sector.\n", + " The LCA scores are stored by method name in the respective sector dictionary within the main dictionary.\n", + " '''\n", + "\n", + " # Initialize scores_dict as a copy of main_dict\n", + " scores_dict = main_dict.copy()\n", + "\n", + " # Loop through each sector in main_dict\n", + " for sector in scores_dict.keys():\n", + " # Extract activities for the current sector\n", + " sector_activities = scores_dict[sector]['activities']\n", + " \n", + " # Calculate LCA scores using the specified method\n", + " lca_scores = compare_activities_multiple_methods(\n", + " activities_list=sector_activities,\n", + " methods=method_dict,\n", + " identifier=sector,\n", + " mode='absolute'\n", + " )\n", + " \n", + " # Apply the small_inputs_to_other_column function with the cutoff value\n", + " lca_scores = small_inputs_to_other_column(lca_scores, cutoff=0.02)\n", + " \n", + " # Save the LCA scores to the scores_dict\n", + " scores_dict[sector]['lca_scores'] = lca_scores\n", + "\n", + " return scores_dict" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Omitting activity name common prefix: 'cement production, '\n", + "Omitting activity name common prefix: 'cement production, '\n", + "Omitting activity name common prefix: 'electricity production, at biomass-fired IGCC power '\n", + "Omitting activity name common prefix: 'electricity production, at biomass-fired IGCC power '\n" + ] + } + ], + "source": [ + "scores_dict=sector_lca_scores(sectors_dict, method_dict) \n", + "\n", + "# this function is omitting common parts in the activities names, because only one type of activity portland and biomass from ICGGC is looked at \n", + "# the results are 'Portland' and 'plant' in the activity column" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "scores_dict['Cement']['lca_scores'].keys()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "scores_dict['Electricity']['lca_scores'].keys()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "scores_dict['Cement'].keys()" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [], + "source": [ + "def add_statistics(df, column_name='total'):\n", + "\n", + " #Need a rank row to plot the total LCA scores in descending order (satter opepyxl function takes in non categorial values)\n", + " df['rank'] = df[column_name].rank(method='max') \n", + " # Calculate mean, standard deviation, and IQR\n", + " df['mean'] = df[column_name].mean()\n", + " df['2std_abv'] = df['mean'] + df[column_name].std() * 2\n", + " df['2std_blw'] = df['mean'] - df[column_name].std() * 2\n", + " df['q1'] = df[column_name].quantile(0.25)\n", + " df['q3'] = df[column_name].quantile(0.75)\n", + " \n", + " # Reorder the columns to place the new columns after 'total'\n", + " cols = df.columns.tolist()\n", + " total_index = cols.index(column_name) + 1\n", + " new_cols = ['rank', 'mean', '2std_abv', '2std_blw', 'q1', 'q3']\n", + " cols = cols[:total_index] + new_cols + cols[total_index:-len(new_cols)]\n", + " \n", + " return df[cols]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [], + "source": [ + "def sector_lca_scores_to_excel(scores_dict, excel_file_name):\n", + " # Prepare to save each LCA score table to a different worksheet in the same Excel file\n", + " excel_file = excel_file_name\n", + " with pd.ExcelWriter(excel_file, engine='openpyxl') as writer:\n", + " for sector in scores_dict.keys():\n", + " lca_scores = scores_dict[sector]['lca_scores']\n", + " for method, table in lca_scores.items():\n", + " # Create a DataFrame for the current LCA score table\n", + " df = pd.DataFrame(table)\n", + " # Add the index as a new column at the beginning\n", + " df.insert(0, 'Index', df.index)\n", + " # Add statistics to the DataFrame\n", + " df = add_statistics(df)\n", + " # Add sector marker column\n", + " df['sector']=str(sector) # potentially remove!\n", + " # Generate a worksheet name\n", + " worksheet_name = f\"{sector}_{method}\"\n", + " if len(worksheet_name) > 31:\n", + " worksheet_name = worksheet_name[:31]\n", + " # Save the DataFrame to the Excel file in a new worksheet\n", + " df.to_excel(writer, sheet_name=worksheet_name, index=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 141, + "metadata": {}, + "outputs": [], + "source": [ + "lca_scores_in_excel=sector_lca_scores_to_excel(scores_dict, 'output_v20_2.xlsx')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "PLOTS IN EXCEL" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Input : one excel file which holds the sector workesheets\n", + "# create a dictionary of worksheet names which fullfill the criteria.\n", + "# iterate through the list to get the worksheets\n", + "# Grouping sector graphs in one worksheet - for worksheets with same sector create a chart each in a worksheet called sector_charts\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": {}, + "outputs": [], + "source": [ + "from openpyxl import load_workbook\n", + "\n", + "def categorize_sheets_by_sector(file_path):\n", + " # Load the workbook\n", + " workbook = load_workbook(filename=file_path, read_only=True)\n", + " \n", + " # Initialize a dictionary to hold sectors and their corresponding sheet names\n", + " worksheet_dict = {}\n", + " \n", + " # Iterate over all sheet names in the workbook\n", + " for sheet_name in workbook.sheetnames:\n", + " # Split the sheet name to extract the sector (assumes sector is the first part)\n", + " sector = sheet_name.split('_')[0]\n", + " \n", + " # Add the sheet name to the corresponding sector in the dictionary\n", + " if sector in worksheet_dict:\n", + " worksheet_dict[sector].append(sheet_name)\n", + " else:\n", + " worksheet_dict[sector] = [sheet_name]\n", + " \n", + " return worksheet_dict" + ] + }, + { + "cell_type": "code", + "execution_count": 142, + "metadata": {}, + "outputs": [], + "source": [ + "worksheet_dict=categorize_sheets_by_sector('output_v20_2.xlsx')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Just for one dataframe at the moment, but at least it works" + ] + }, + { + "cell_type": "code", + "execution_count": 143, + "metadata": {}, + "outputs": [], + "source": [ + "from openpyxl.chart import ScatterChart, Reference, Series\n", + "from openpyxl import load_workbook\n", + "from openpyxl.drawing.text import CharacterProperties\n", + "from openpyxl.chart.label import DataLabelList\n", + "\n", + "\n", + "def plot(filepath_workbook, worksheet_dict):\n", + " \n", + " # Load the workbook\n", + " wb = load_workbook(filepath_workbook)\n", + " \n", + " # Iterate over each sector and its associated worksheets\n", + " for sector, worksheet_names in worksheet_dict.items():\n", + " \n", + " # Create or get the chart sheet for the current sector\n", + " chart_sheet_name = f\"{sector}_charts\"\n", + " if chart_sheet_name in wb.sheetnames:\n", + " ws_charts = wb[chart_sheet_name]\n", + " else:\n", + " ws_charts = wb.create_sheet(chart_sheet_name)\n", + " \n", + " # Initial position for the first chart\n", + " current_row = 1 # Start placing charts from row 1\n", + " chart_height = 21 # Number of rows a chart occupies, adjust as needed\n", + " \n", + " # Iterate over each worksheet name in the current sector\n", + " for worksheet_name in worksheet_names:\n", + " ws = wb[worksheet_name]\n", + "\n", + " # Find max_row and max_column\n", + " max_row = ws.max_row\n", + " max_column = ws.max_column\n", + " \n", + " # Create a ScatterChart (or other chart type as needed)\n", + " chart = ScatterChart()\n", + "\n", + " # Chart titles\n", + " chart.title = f\"{ws['F2'].value} LCA scores for {sector} sector\"\n", + " chart.y_axis.title = f\"{ws['G2'].value}\"\n", + " chart.x_axis.title = 'activity index'\n", + " # Avoid overlap\n", + " chart.title.overlay = False\n", + " chart.x_axis.title.overlay = False\n", + " chart.y_axis.title.overlay = False \n", + "\n", + "\n", + " # Define the data range for the chart\n", + " y_values = Reference(ws, min_col=8, min_row=1, max_row=max_row)\n", + " x_values = Reference(ws, min_col=9, min_row=1, max_row=max_row)\n", + "\n", + " # Create a series and add it to the chart\n", + " series = Series(y_values, x_values, title_from_data=True)\n", + " chart.series.append(series)\n", + " chart.style = 9\n", + "\n", + " # Customize the series to show only markers (dots)\n", + " series.marker.symbol = \"circle\"\n", + " series.marker.size = 5\n", + " series.graphicalProperties.line.noFill = True\n", + "\n", + "\n", + " # ADJUST X-AXIS\n", + " chart.x_axis.tickLblPos = \"low\"\n", + " chart.x_axis.majorGridlines = None\n", + " chart.x_axis.tickMarkSkip = 0 # Show all tick marks\n", + " chart.x_axis.tickLblSkip = 0 # Show all labels\n", + "\n", + " # Set x-axis to be a value axis instead of a category axis\n", + " chart.x_axis.scaling.orientation = \"minMax\"\n", + " chart.x_axis.crosses = \"autoZero\"\n", + " chart.x_axis.axPos = \"b\"\n", + " chart.x_axis.delete = False\n", + "\n", + " # ADJUST Y-AXIS\n", + "\n", + " # Calculate the min and max y-values to determine the axis range\n", + " y_values_list = [ws.cell(row=row, column=8).value for row in range(2,8)] #number of rows need to be defined based on dataframe\n", + " min_y_value = min(y_values_list)-min(y_values_list)*0.1\n", + " max_y_value = max(y_values_list)+ max(y_values_list)*0.1\n", + "\n", + " # Set y-axis range with some padding\n", + " padding = (max_y_value - min_y_value) * 0.1 # 10% padding on each side\n", + " chart.y_axis.scaling.min = min_y_value - padding\n", + " chart.y_axis.scaling.max = max_y_value + padding\n", + "\n", + " # Explicitly set tick labels to be visible\n", + " chart.y_axis.tickLblPos = \"nextTo\" # Position the labels next to the tick marks\n", + " #chart.y_axis.majorGridlines = True # Ensure major gridlines are enabled (though you mentioned they're visible)\n", + " chart.y_axis.delete = False # Ensure axis is not deleted\n", + " # Format the y-axis to show 2 decimal places\n", + " chart.y_axis.number_format = '0.00'\n", + "\n", + "\n", + " # ---------\n", + " # ADD STATS\n", + " # ---------\n", + " # MEAN\n", + " # Add a new series to the chart for the mean line\n", + " mean_y = Reference(ws, min_col=10, min_row=1, max_row=max_row)\n", + " mean_series = Series(mean_y, x_values, title_from_data=\"True\")\n", + " chart.series.append(mean_series)\n", + "\n", + " # Customize the mean series to show as a line\n", + " mean_series.marker.symbol = \"none\" # No markers, just a line\n", + " mean_series.graphicalProperties.line.solidFill = \"FF0000\" # Red line for mean value\n", + " mean_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "\n", + " # IQR\n", + " # Add a new series to the chart for the iqr lines\n", + " iqr1= Reference(ws, min_col=13, min_row=1, max_row=max_row)\n", + " iqr3= Reference(ws, min_col=14, min_row=1, max_row=max_row)\n", + " iqr1_series = Series(iqr1, x_values, title_from_data=\"True\")\n", + " iqr3_series = Series(iqr3, x_values, title_from_data=\"True\")\n", + " chart.series.append(iqr1_series)\n", + " chart.series.append(iqr3_series)\n", + "\n", + " # Customize the iqr 1,3 series to show as a line\n", + " iqr1_series.marker.symbol = \"none\" # No markers, just a line\n", + " iqr3_series.marker.symbol = \"none\"\n", + " iqr1_series.graphicalProperties.line.solidFill = \"6082B6\" # Blue line \n", + " iqr3_series.graphicalProperties.line.solidFill = \"6082B6\" \n", + " iqr1_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + " iqr3_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "\n", + " # STD\n", + " # Add a new series to the chart for the std lines\n", + " std_abv= Reference(ws, min_col=11, min_row=1, max_row=max_row)\n", + " std_blw= Reference(ws, min_col=12, min_row=1, max_row=max_row)\n", + " std_abv_series = Series(std_abv, x_values, title_from_data=\"True\")\n", + " std_blw_series = Series(std_blw, x_values, title_from_data=\"True\")\n", + " chart.series.append(std_abv_series)\n", + " chart.series.append(std_blw_series)\n", + "\n", + " # Customize the iqr 1,3 series to show as a line\n", + " std_abv_series.marker.symbol = \"none\" # No markers, just a line\n", + " std_blw_series.marker.symbol = \"none\"\n", + " std_abv_series.graphicalProperties.line.solidFill = \"FFC300\" # yellow line\n", + " std_blw_series.graphicalProperties.line.solidFill = \"FFC300\" \n", + " std_abv_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + " std_blw_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "\n", + " # Set legend position to the right of the plot area\n", + " chart.legend.position = 'r' # 'r' for right\n", + " chart.legend.overlay= False\n", + "\n", + " # Adjust chart dimensions and position to make space for the legend\n", + " chart.width = 18 # Example width, adjust as needed\n", + " chart.height = 10 # Example height, adjust as needed\n", + "\n", + " # Add the chart to the chart worksheet\n", + " # Calculate the position for this chart\n", + " position = f\"A{current_row}\"\n", + " ws_charts.add_chart(chart, position)\n", + " \n", + " # Update current_row to position the next chart below the current one\n", + " current_row += chart_height\n", + "\n", + " wb.save(filepath_workbook)" + ] + }, + { + "cell_type": "code", + "execution_count": 144, + "metadata": {}, + "outputs": [], + "source": [ + "plot('output_v20_2.xlsx', worksheet_dict=worksheet_dict)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from openpyxl.chart import ScatterChart, Reference, Series\n", + "from openpyxl import load_workbook\n", + "from openpyxl.drawing.text import CharacterProperties\n", + "\n", + "for key, value in worksheets_dict.items():\n", + "\n", + "def plot1 (filepath_workbook):\n", + " \n", + "wb = load_workbook('output_v2_2.xlsx')\n", + "\n", + "\n", + "ws = wb['Cement_Cement_global_warming_po']\n", + "ws_charts = wb.create_sheet('Charts_cement')\n", + "\n", + "chart = ScatterChart() # thats the name of the chart, we could also give it a different one\n", + "location_chart=[\"B3\", \"M3\", \"X3\",\n", + " \"B25\", \"M25\", \"X25\",\n", + " \"B46\", \"M46\", \"X46\" \n", + " ]\n", + "\n", + "\n", + "\n", + "#add max_row= len(df)... smthn like this\n", + "\n", + "# Chart titles\n", + "chart.title = 'LCA scores of portland cement production'\n", + "chart.x_axis.title = 'activities'\n", + "chart.y_axis.title = 'method unit'\n", + "# Avoid overlap\n", + "chart.title.overlay = False\n", + "chart.x_axis.title.overlay = False\n", + "chart.y_axis.title.overlay = False \n", + "\n", + "\n", + "# Define the data range for the chart\n", + "y_values = Reference(ws, min_col=8, min_row=1, max_row=8)\n", + "x_values = Reference(ws, min_col=4, min_row=2, max_row=8)\n", + "\n", + "# Create a series and add it to the chart\n", + "series = Series(y_values, x_values, title_from_data=True)\n", + "chart.series.append(series)\n", + "chart.style = 9\n", + "\n", + "# Customize the series to show only markers (dots)\n", + "series.marker.symbol = \"circle\"\n", + "series.marker.size = 5\n", + "series.graphicalProperties.line.noFill = True\n", + "\n", + "# ADJUST X-AXIS\n", + "\n", + "# # ADJUST X-AXIS\n", + "chart.x_axis.tickLblPos = \"low\"\n", + "chart.x_axis.majorGridlines = None\n", + "chart.x_axis.tickMarkSkip = 0 # Show all tick marks\n", + "chart.x_axis.tickLblSkip = 0 # Show all labels\n", + "\n", + "# Set x-axis to be a value axis instead of a category axis\n", + "chart.x_axis.scaling.orientation = \"minMax\"\n", + "chart.x_axis.crosses = \"autoZero\"\n", + "chart.x_axis.axPos = \"b\"\n", + "chart.x_axis.delete = False\n", + "\n", + "# ADJUST Y-AXIS\n", + "\n", + "# Calculate the min and max y-values to determine the axis range\n", + "y_values_list = [ws.cell(row=row, column=8).value for row in range(2,8)] #number of rows need to be defined based on dataframe\n", + "min_y_value = min(y_values_list)\n", + "max_y_value = max(y_values_list)\n", + "\n", + "# Set y-axis range with some padding\n", + "padding = (max_y_value - min_y_value) * 0.1 # 10% padding on each side\n", + "chart.y_axis.scaling.min = min_y_value - padding\n", + "chart.y_axis.scaling.max = max_y_value + padding\n", + "\n", + "# Explicitly set tick labels to be visible\n", + "chart.y_axis.tickLblPos = \"nextTo\" # Position the labels next to the tick marks\n", + "#chart.y_axis.majorGridlines = True # Ensure major gridlines are enabled (though you mentioned they're visible)\n", + "chart.y_axis.delete = False # Ensure axis is not deleted\n", + "# Format the y-axis to show 2 decimal places\n", + "chart.y_axis.number_format = '0.00'\n", + "\n", + "\n", + "# ---------\n", + "# ADD STATS\n", + "# ---------\n", + "# MEAN\n", + "# Add a new series to the chart for the mean line\n", + "mean_y = Reference(ws, min_col=9, min_row=1, max_row=8)\n", + "mean_series = Series(mean_y, x_values, title_from_data=\"True\")\n", + "chart.series.append(mean_series)\n", + "\n", + "# Customize the mean series to show as a line\n", + "mean_series.marker.symbol = \"none\" # No markers, just a line\n", + "mean_series.graphicalProperties.line.solidFill = \"FF0000\" # Red line for mean value\n", + "mean_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "\n", + "# IQR\n", + "# Add a new series to the chart for the iqr lines\n", + "iqr1= Reference(ws, min_col=12, min_row=1, max_row=8)\n", + "iqr3= Reference(ws, min_col=13, min_row=1, max_row=8)\n", + "iqr1_series = Series(iqr1, x_values, title_from_data=\"True\")\n", + "iqr3_series = Series(iqr3, x_values, title_from_data=\"True\")\n", + "chart.series.append(iqr1_series)\n", + "chart.series.append(iqr3_series)\n", + "\n", + "# Customize the iqr 1,3 series to show as a line\n", + "iqr1_series.marker.symbol = \"none\" # No markers, just a line\n", + "iqr3_series.marker.symbol = \"none\"\n", + "iqr1_series.graphicalProperties.line.solidFill = \"6082B6\" # Blue line \n", + "iqr3_series.graphicalProperties.line.solidFill = \"6082B6\" \n", + "iqr1_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "iqr3_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "\n", + "# STD\n", + "# Add a new series to the chart for the std lines\n", + "std_abv= Reference(ws, min_col=10, min_row=1, max_row=8)\n", + "std_blw= Reference(ws, min_col=11, min_row=1, max_row=8)\n", + "std_abv_series = Series(std_abv, x_values, title_from_data=\"True\")\n", + "std_blw_series = Series(std_blw, x_values, title_from_data=\"True\")\n", + "chart.series.append(std_abv_series)\n", + "chart.series.append(std_blw_series)\n", + "\n", + "# Customize the iqr 1,3 series to show as a line\n", + "std_abv_series.marker.symbol = \"none\" # No markers, just a line\n", + "std_blw_series.marker.symbol = \"none\"\n", + "std_abv_series.graphicalProperties.line.solidFill = \"FFC300\" # yellow line\n", + "std_blw_series.graphicalProperties.line.solidFill = \"FFC300\" \n", + "std_abv_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "std_blw_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "\n", + "# Set legend position to the right of the plot area\n", + "chart.legend.position = 'r' # 'r' for right\n", + "chart.legend.overlay= False\n", + "\n", + "# Adjust chart dimensions and position to make space for the legend\n", + "chart.width = 18 # Example width, adjust as needed\n", + "chart.height = 10 # Example height, adjust as needed\n", + "\n", + "ws_charts.add_chart(chart, location_chart) #wher top left corner begins\n", + "wb.save('output_v2_2.xlsx')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from openpyxl.chart import ScatterChart, Reference, Series\n", + "from openpyxl import load_workbook\n", + "from openpyxl.drawing.text import CharacterProperties\n", + "\n", + "wb = load_workbook('output_v2_2.xlsx')\n", + "ws = wb['Cement_Cement_cumulative_energy']\n", + "\n", + "#add clause... if sheet already existst... add to sheet. If not create as new sheet.\n", + "ws_charts = wb['Charts_cement']\n", + "\n", + "chart = ScatterChart() # thats the name of the chart, we could also give it a different one\n", + "\n", + "# Chart titles\n", + "chart.title = 'LCA scores of portland cement production'\n", + "chart.x_axis.title = 'activities'\n", + "chart.y_axis.title = 'method unit'\n", + "# Avoid overlap\n", + "chart.title.overlay = False\n", + "chart.x_axis.title.overlay = False\n", + "chart.y_axis.title.overlay = False \n", + "\n", + "\n", + "# Define the data range for the chart\n", + "y_values = Reference(ws, min_col=8, min_row=1, max_row=8)\n", + "x_values = Reference(ws, min_col=4, min_row=2, max_row=8)\n", + "\n", + "# Create a series and add it to the chart\n", + "series = Series(y_values, x_values, title_from_data=True)\n", + "chart.series.append(series)\n", + "chart.style = 9\n", + "\n", + "# Customize the series to show only markers (dots)\n", + "series.marker.symbol = \"circle\"\n", + "series.marker.size = 5\n", + "series.graphicalProperties.line.noFill = True\n", + "\n", + "# ADJUST X-AXIS\n", + "\n", + "# # ADJUST X-AXIS\n", + "chart.x_axis.tickLblPos = \"low\"\n", + "chart.x_axis.majorGridlines = None\n", + "chart.x_axis.tickMarkSkip = 0 # Show all tick marks\n", + "chart.x_axis.tickLblSkip = 0 # Show all labels\n", + "\n", + "# Set x-axis to be a value axis instead of a category axis\n", + "chart.x_axis.scaling.orientation = \"minMax\"\n", + "chart.x_axis.crosses = \"autoZero\"\n", + "chart.x_axis.axPos = \"b\"\n", + "chart.x_axis.delete = False\n", + "\n", + "# ADJUST Y-AXIS\n", + "\n", + "# Calculate the min and max y-values to determine the axis range\n", + "y_values_list = [ws.cell(row=row, column=8).value for row in range(2, 9)]\n", + "min_y_value = min(y_values_list)\n", + "max_y_value = max(y_values_list)\n", + "\n", + "# Set y-axis range with some padding\n", + "padding = (max_y_value - min_y_value) * 0.1 # 10% padding on each side\n", + "chart.y_axis.scaling.min = min_y_value - padding\n", + "chart.y_axis.scaling.max = max_y_value + padding\n", + "\n", + "# Explicitly set tick labels to be visible\n", + "chart.y_axis.tickLblPos = \"nextTo\" # Position the labels next to the tick marks\n", + "#chart.y_axis.majorGridlines = True # Ensure major gridlines are enabled (though you mentioned they're visible)\n", + "chart.y_axis.delete = False # Ensure axis is not deleted\n", + "# Format the y-axis to show 2 decimal places\n", + "chart.y_axis.number_format = '0.00'\n", + "\n", + "# ---------\n", + "# ADD STATS\n", + "# ---------\n", + "# MEAN\n", + "# Add a new series to the chart for the mean line\n", + "mean_y = Reference(ws, min_col=9, min_row=1, max_row=8)\n", + "mean_series = Series(mean_y, x_values, title_from_data=\"True\")\n", + "chart.series.append(mean_series)\n", + "\n", + "# Customize the mean series to show as a line\n", + "mean_series.marker.symbol = \"none\" # No markers, just a line\n", + "mean_series.graphicalProperties.line.solidFill = \"FF0000\" # Red line for mean value\n", + "mean_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "\n", + "# IQR\n", + "# Add a new series to the chart for the iqr lines\n", + "iqr1= Reference(ws, min_col=12, min_row=1, max_row=8)\n", + "iqr3= Reference(ws, min_col=13, min_row=1, max_row=8)\n", + "iqr1_series = Series(iqr1, x_values, title_from_data=\"True\")\n", + "iqr3_series = Series(iqr3, x_values, title_from_data=\"True\")\n", + "chart.series.append(iqr1_series)\n", + "chart.series.append(iqr3_series)\n", + "\n", + "# Customize the iqr 1,3 series to show as a line\n", + "iqr1_series.marker.symbol = \"none\" # No markers, just a line\n", + "iqr3_series.marker.symbol = \"none\"\n", + "iqr1_series.graphicalProperties.line.solidFill = \"6082B6\" # Blue line \n", + "iqr3_series.graphicalProperties.line.solidFill = \"6082B6\" \n", + "iqr1_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "iqr3_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "\n", + "# STD\n", + "# Add a new series to the chart for the std lines\n", + "std_abv= Reference(ws, min_col=10, min_row=1, max_row=8)\n", + "std_blw= Reference(ws, min_col=11, min_row=1, max_row=8)\n", + "std_abv_series = Series(std_abv, x_values, title_from_data=\"True\")\n", + "std_blw_series = Series(std_blw, x_values, title_from_data=\"True\")\n", + "chart.series.append(std_abv_series)\n", + "chart.series.append(std_blw_series)\n", + "\n", + "# Customize the iqr 1,3 series to show as a line\n", + "std_abv_series.marker.symbol = \"none\" # No markers, just a line\n", + "std_blw_series.marker.symbol = \"none\"\n", + "std_abv_series.graphicalProperties.line.solidFill = \"FFC300\" # yellow line\n", + "std_blw_series.graphicalProperties.line.solidFill = \"FFC300\" \n", + "std_abv_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "std_blw_series.graphicalProperties.line.width = 10000 # Set line width (default units are EMUs)\n", + "\n", + "# Set legend position to the right of the plot area\n", + "chart.legend.position = 'r' # 'r' for right\n", + "chart.legend.overlay= False\n", + "\n", + "# Adjust chart dimensions and position to make space for the legend\n", + "chart.width = 18 # Example width, adjust as needed\n", + "chart.height = 10 # Example height, adjust as needed\n", + "\n", + "ws_charts.add_chart(chart, \"M3\") #wher top left corner begins\n", + "wb.save('output_v2_2.xlsx')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "premise", + "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.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}