From e856d2b51c7d73a52e7fda561950780f6a19fa3a Mon Sep 17 00:00:00 2001 From: grgmiller Date: Wed, 1 Mar 2023 13:52:22 -0800 Subject: [PATCH 01/85] start implementing checks --- src/gross_to_net_generation.py | 10 ++++++---- src/validation.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/gross_to_net_generation.py b/src/gross_to_net_generation.py index f125615d..c17df576 100644 --- a/src/gross_to_net_generation.py +++ b/src/gross_to_net_generation.py @@ -210,10 +210,12 @@ def calculate_gross_to_net_conversion_factors( {"left_only": "cems_only", "right_only": "eia_only"} ) - # drop data that only exists in EIA, but not in CEMS, since there is no gross generation data to calculate NG for - combined_gen_data = combined_gen_data[ - ~(combined_gen_data["data_source"] == "eia_only") - ] + # validate the data + validation.check_nonzero_gross_gen_when_positive_net_gen(combined_gen_data) + # check for zero net gen when positive gross gen + # check when gross gen is less than net gen + # do this at the plant level too to see if allocation error + # calculate other groupings at the plant and annual levels annual_subplant_ratio = ( diff --git a/src/validation.py b/src/validation.py index 49ebcdb6..c49cccb4 100644 --- a/src/validation.py +++ b/src/validation.py @@ -239,6 +239,36 @@ def test_for_missing_subplant_id(df): return missing_subplant_test +def check_nonzero_gross_gen_when_positive_net_gen(combined_gen_data): + """checks that gross generation is positive when net generation is positive. + + This could indicate an issue with missing data or incorrect subplant matching. + """ + + zero_gross = combined_gen_data[ + (combined_gen_data["net_generation_mwh"] > 0) + & (~combined_gen_data["gross_generation_mwh"] > 0) + ] + + if len(zero_gross) > 0: + unique_subplants = len(zero_gross[["plant_id_eia", "suplant_id"]].unique()) + logger.warning( + f"There are {unique_subplants} subplants for which there is positive net generation associated with zero or missing gross generation." + ) + logger.warning( + "\n" + + zero_gross[ + [ + "plant_id_eia", + "suplant_id", + "report_date", + "gross_generation_mwh", + "net_generation_mwh", + ] + ].to_string() + ) + + def validate_gross_to_net_conversion(cems, eia923_allocated): """checks whether the calculated net generation matches the reported net generation from EIA-923 at the annual plant level.""" logger.info( From bd892dd352676c97a7045084603db3428cb3877e Mon Sep 17 00:00:00 2001 From: grgmiller Date: Wed, 1 Mar 2023 17:26:28 -0800 Subject: [PATCH 02/85] add new checks --- .../GH292_GTN_validation.ipynb | 262 ++++++++++++++++++ src/gross_to_net_generation.py | 51 ++-- src/validation.py | 105 ++++++- 3 files changed, 375 insertions(+), 43 deletions(-) create mode 100644 notebooks/work_in_progress/GH292_GTN_validation.ipynb diff --git a/notebooks/work_in_progress/GH292_GTN_validation.ipynb b/notebooks/work_in_progress/GH292_GTN_validation.ipynb new file mode 100644 index 00000000..27c2447a --- /dev/null +++ b/notebooks/work_in_progress/GH292_GTN_validation.ipynb @@ -0,0 +1,262 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# import packages\n", + "import pandas as pd\n", + "import numpy as np\n", + "import os\n", + "import plotly.express as px\n", + "\n", + "%reload_ext autoreload\n", + "%autoreload 2\n", + "\n", + "# # Tell python where to look for modules.\n", + "import sys\n", + "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "import download_data\n", + "import load_data\n", + "from column_checks import get_dtypes\n", + "from filepaths import *\n", + "import impute_hourly_profiles\n", + "import data_cleaning\n", + "import output_data\n", + "import emissions\n", + "import validation\n", + "from gross_to_net_generation import *\n", + "import eia930\n", + "\n", + "year = 2021\n", + "path_prefix = f\"{year}/\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems = pd.read_csv(outputs_folder(f\"{path_prefix}/cems_subplant_{year}.csv\"), dtype=get_dtypes())\n", + "eia923_allocated = pd.read_csv(outputs_folder(f\"{path_prefix}/eia923_allocated_{year}.csv\"), dtype=get_dtypes())\n", + "plant_attributes = pd.read_csv(outputs_folder(f\"{path_prefix}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from logging_util import get_logger, configure_root_logger" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "configure_root_logger()\n", + "logger = get_logger(\"test\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# aggregate the hourly cems data by subplant\n", + "gross_gen_data = cems[\n", + " [\n", + " \"plant_id_eia\",\n", + " \"subplant_id\",\n", + " \"report_date\",\n", + " \"datetime_utc\",\n", + " \"gross_generation_mwh\",\n", + " ]\n", + "].copy()\n", + "# identify the 2nd percentile lowest hourly gross generation value in a month\n", + "min_gross = (\n", + " gross_gen_data.groupby(\n", + " [\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False\n", + " )\n", + " .agg({\"gross_generation_mwh\": lambda x: x.quantile(0.02)})\n", + " .reset_index()\n", + " .rename(columns={\"gross_generation_mwh\": \"minimum_gross_generation_mwh\"})\n", + ")\n", + "# identify the 98th percentile highest hourly gross generation value in a month\n", + "max_gross = (\n", + " gross_gen_data.groupby(\n", + " [\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False\n", + " )\n", + " .agg({\"gross_generation_mwh\": lambda x: x.quantile(0.98)})\n", + " .reset_index()\n", + " .rename(columns={\"gross_generation_mwh\": \"maximum_gross_generation_mwh\"})\n", + ")\n", + "subplant_capacity = calculate_subplant_nameplate_capacity(year)\n", + "# aggregate the cems data to the monthly level\n", + "gross_gen_data = (\n", + " gross_gen_data.groupby(\n", + " [\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False\n", + " )\n", + " .agg({\"datetime_utc\": \"count\", \"gross_generation_mwh\": \"sum\"})\n", + " .reset_index()\n", + " .rename(columns={\"datetime_utc\": \"hours_in_month\"})\n", + ")\n", + "net_gen_data = (\n", + " eia923_allocated.dropna(subset=[\"net_generation_mwh\"])\n", + " .groupby([\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False)[\n", + " \"net_generation_mwh\"\n", + " ]\n", + " .sum()\n", + " .reset_index()\n", + ")\n", + "\n", + "# combine monthly gross and net generation data where we have data for both\n", + "combined_gen_data = (\n", + " gross_gen_data.merge(\n", + " min_gross,\n", + " how=\"left\",\n", + " on=[\"plant_id_eia\", \"subplant_id\", \"report_date\"],\n", + " validate=\"1:1\",\n", + " )\n", + " .merge(\n", + " max_gross,\n", + " how=\"left\",\n", + " on=[\"plant_id_eia\", \"subplant_id\", \"report_date\"],\n", + " validate=\"1:1\",\n", + " )\n", + " .merge(\n", + " subplant_capacity,\n", + " how=\"left\",\n", + " on=[\"plant_id_eia\", \"subplant_id\"],\n", + " validate=\"m:1\",\n", + " )\n", + " .merge(\n", + " net_gen_data,\n", + " how=\"outer\",\n", + " on=[\"plant_id_eia\", \"subplant_id\", \"report_date\"],\n", + " indicator=\"data_source\",\n", + " validate=\"1:1\",\n", + " )\n", + ")\n", + "combined_gen_data[\"data_source\"] = combined_gen_data[\"data_source\"].replace(\n", + " {\"left_only\": \"cems_only\", \"right_only\": \"eia_only\"}\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "combined_gen_data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "validation.check_missing_or_zero_generation_matches(combined_gen_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# calculate other groupings at the plant and annual levels\n", + "annual_subplant_ratio = (\n", + " combined_gen_data.dropna(subset=[\"gross_generation_mwh\", \"net_generation_mwh\"])\n", + " .groupby([\"plant_id_eia\", \"subplant_id\"], dropna=False)[\n", + " [\"gross_generation_mwh\", \"net_generation_mwh\", \"hours_in_month\"]\n", + " ]\n", + " .sum()\n", + " .reset_index()\n", + ")\n", + "monthly_plant_ratio = (\n", + " combined_gen_data.dropna(subset=[\"gross_generation_mwh\", \"net_generation_mwh\"])\n", + " .groupby([\"plant_id_eia\", \"report_date\"], dropna=False)[\n", + " [\"gross_generation_mwh\", \"net_generation_mwh\"]\n", + " ]\n", + " .sum()\n", + " .reset_index()\n", + ")\n", + "annual_plant_ratio = (\n", + " combined_gen_data.dropna(subset=[\"gross_generation_mwh\", \"net_generation_mwh\"])\n", + " .groupby([\"plant_id_eia\"], dropna=False)[\n", + " [\"gross_generation_mwh\", \"net_generation_mwh\", \"hours_in_month\"]\n", + " ]\n", + " .sum()\n", + " .reset_index()\n", + ")\n", + "\n", + "# calculate the ratios at each aggregation level\n", + "# fill missing values (due to divide by zero) with zero\n", + "# replace infinite values with missing\n", + "combined_gen_data[\"monthly_subplant_ratio\"] = (\n", + " combined_gen_data[\"net_generation_mwh\"]\n", + " / combined_gen_data[\"gross_generation_mwh\"]\n", + ").replace([np.inf, -np.inf], np.nan)\n", + "annual_subplant_ratio[\"annual_subplant_ratio\"] = (\n", + " annual_subplant_ratio[\"net_generation_mwh\"]\n", + " / annual_subplant_ratio[\"gross_generation_mwh\"]\n", + ").replace([np.inf, -np.inf], np.nan)\n", + "monthly_plant_ratio[\"monthly_plant_ratio\"] = (\n", + " monthly_plant_ratio[\"net_generation_mwh\"]\n", + " / monthly_plant_ratio[\"gross_generation_mwh\"]\n", + ").replace([np.inf, -np.inf], np.nan)\n", + "annual_plant_ratio[\"annual_plant_ratio\"] = (\n", + " annual_plant_ratio[\"net_generation_mwh\"]\n", + " / annual_plant_ratio[\"gross_generation_mwh\"]\n", + ").replace([np.inf, -np.inf], np.nan)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "validation.identify_anomalous_annual_plant_gtn_ratios(annual_plant_ratio)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "open_grid_emissions", + "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.9" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "b893a8d8fbb165be288531947168b3b06bdb1508177327a21c265e0400df3100" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/src/gross_to_net_generation.py b/src/gross_to_net_generation.py index c17df576..1894cf81 100644 --- a/src/gross_to_net_generation.py +++ b/src/gross_to_net_generation.py @@ -211,11 +211,7 @@ def calculate_gross_to_net_conversion_factors( ) # validate the data - validation.check_nonzero_gross_gen_when_positive_net_gen(combined_gen_data) - # check for zero net gen when positive gross gen - # check when gross gen is less than net gen - # do this at the plant level too to see if allocation error - + validation.check_missing_or_zero_generation_matches(combined_gen_data) # calculate other groupings at the plant and annual levels annual_subplant_ratio = ( @@ -247,37 +243,24 @@ def calculate_gross_to_net_conversion_factors( # fill missing values (due to divide by zero) with zero # replace infinite values with missing combined_gen_data["monthly_subplant_ratio"] = ( - ( - combined_gen_data["net_generation_mwh"] - / combined_gen_data["gross_generation_mwh"] - ) - .fillna(0) - .replace([np.inf, -np.inf], np.nan) - ) + combined_gen_data["net_generation_mwh"] + / combined_gen_data["gross_generation_mwh"] + ).replace([np.inf, -np.inf], np.nan) annual_subplant_ratio["annual_subplant_ratio"] = ( - ( - annual_subplant_ratio["net_generation_mwh"] - / annual_subplant_ratio["gross_generation_mwh"] - ) - .fillna(0) - .replace([np.inf, -np.inf], np.nan) - ) + annual_subplant_ratio["net_generation_mwh"] + / annual_subplant_ratio["gross_generation_mwh"] + ).replace([np.inf, -np.inf], np.nan) monthly_plant_ratio["monthly_plant_ratio"] = ( - ( - monthly_plant_ratio["net_generation_mwh"] - / monthly_plant_ratio["gross_generation_mwh"] - ) - .fillna(0) - .replace([np.inf, -np.inf], np.nan) - ) + monthly_plant_ratio["net_generation_mwh"] + / monthly_plant_ratio["gross_generation_mwh"] + ).replace([np.inf, -np.inf], np.nan) annual_plant_ratio["annual_plant_ratio"] = ( - ( - annual_plant_ratio["net_generation_mwh"] - / annual_plant_ratio["gross_generation_mwh"] - ) - .fillna(0) - .replace([np.inf, -np.inf], np.nan) - ) + annual_plant_ratio["net_generation_mwh"] + / annual_plant_ratio["gross_generation_mwh"] + ).replace([np.inf, -np.inf], np.nan) + + # flag anomalous plant ratios + validation.identify_anomalous_annual_plant_gtn_ratios(annual_plant_ratio) # calculate a monthly and annual shift factor combined_gen_data["monthly_subplant_shift_mw"] = ( @@ -508,7 +491,7 @@ def filter_gtn_conversion_factors(gtn_conversions): factors_to_use.loc[ factors_to_use[scaling_factor] < 0.75, scaling_factor ] = np.NaN - # remove any factors that would cause the generation in any hour to exceed 150% of nameplate capacity + # remove any factors that would cause the generation in any hour to exceed 125% of nameplate capacity factors_to_use.loc[ ( factors_to_use[scaling_factor] diff --git a/src/validation.py b/src/validation.py index c49cccb4..16b0331b 100644 --- a/src/validation.py +++ b/src/validation.py @@ -239,33 +239,120 @@ def test_for_missing_subplant_id(df): return missing_subplant_test -def check_nonzero_gross_gen_when_positive_net_gen(combined_gen_data): +def check_missing_or_zero_generation_matches(combined_gen_data): """checks that gross generation is positive when net generation is positive. This could indicate an issue with missing data or incorrect subplant matching. """ - zero_gross = combined_gen_data[ + # identify when there is zero or NA gross generation associated with positive net generation + missing_gross_gen = combined_gen_data[ (combined_gen_data["net_generation_mwh"] > 0) - & (~combined_gen_data["gross_generation_mwh"] > 0) + & ((combined_gen_data["gross_generation_mwh"] == 0)) ] - if len(zero_gross) > 0: - unique_subplants = len(zero_gross[["plant_id_eia", "suplant_id"]].unique()) + # identify when there is zero or NA net generation associated with nonzero gross generation + missing_net_gen = combined_gen_data[ + (combined_gen_data["gross_generation_mwh"] > 0) + & (combined_gen_data["net_generation_mwh"] == 0) + ] + + if len(missing_gross_gen) > 0: + unique_plants = len(missing_gross_gen[["plant_id_eia"]].drop_duplicates()) + unique_subplants = len( + missing_gross_gen[["plant_id_eia", "subplant_id"]].drop_duplicates() + ) logger.warning( - f"There are {unique_subplants} subplants for which there is positive net generation associated with zero or missing gross generation." + f"There are {unique_subplants} subplants at {unique_plants} plants for which there is zero gross generation associated with positive net generation." ) logger.warning( "\n" - + zero_gross[ + + missing_gross_gen[ [ "plant_id_eia", - "suplant_id", + "subplant_id", "report_date", "gross_generation_mwh", "net_generation_mwh", + "data_source", ] - ].to_string() + ] + .head(10) + .to_string() + + "\n...\n" + + missing_gross_gen[ + [ + "plant_id_eia", + "subplant_id", + "report_date", + "gross_generation_mwh", + "net_generation_mwh", + "data_source", + ] + ] + .tail(10) + .to_string() + ) + + if len(missing_net_gen) > 0: + unique_plants = len(missing_net_gen[["plant_id_eia"]].drop_duplicates()) + unique_subplants = len( + missing_net_gen[["plant_id_eia", "subplant_id"]].drop_duplicates() + ) + logger.warning( + f"There are {unique_subplants} subplants at {unique_plants} plants for which there is zero net generation associated with positive gross generation." + ) + logger.warning( + "\n" + + missing_net_gen[ + [ + "plant_id_eia", + "subplant_id", + "report_date", + "gross_generation_mwh", + "net_generation_mwh", + "data_source", + ] + ] + .head(10) + .to_string() + + "\n...\n" + + missing_net_gen[ + [ + "plant_id_eia", + "subplant_id", + "report_date", + "gross_generation_mwh", + "net_generation_mwh", + "data_source", + ] + ] + .tail(10) + .to_string() + ) + + +def identify_anomalous_annual_plant_gtn_ratios(annual_plant_ratio): + """Identifies when net generation for a plant is substantially higher than gross generation.""" + + anomalous_gtn = annual_plant_ratio[annual_plant_ratio["annual_plant_ratio"] > 1.25] + + if len(anomalous_gtn) > 0: + logger.warning( + "The following plants have annual net generation that is >125% of annual gross generation:" + ) + logger.warning( + "\n" + + anomalous_gtn[ + [ + "plant_id_eia", + "gross_generation_mwh", + "net_generation_mwh", + "annual_plant_ratio", + ] + ] + .sort_values(by="annual_plant_ratio", ascending=False) + .to_string() ) From 7ef00633780ad134f8cc60fb5db117bd1dadf339 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 11 Mar 2023 12:25:38 -0800 Subject: [PATCH 03/85] validate primary fuel --- notebooks/work_in_progress/sandbox.ipynb | 4 ++ src/column_checks.py | 17 ++++++ src/data_cleaning.py | 70 +++++++++++++----------- src/data_pipeline.py | 30 +++++++++- src/validation.py | 56 +++++++++++++++++++ 5 files changed, 143 insertions(+), 34 deletions(-) diff --git a/notebooks/work_in_progress/sandbox.ipynb b/notebooks/work_in_progress/sandbox.ipynb index 574e31b7..7b515fd4 100644 --- a/notebooks/work_in_progress/sandbox.ipynb +++ b/notebooks/work_in_progress/sandbox.ipynb @@ -30,6 +30,10 @@ "import validation\n", "import gross_to_net_generation\n", "import eia930\n", + "from logging_util import get_logger, configure_root_logger\n", + "configure_root_logger()\n", + "logger = get_logger(\"test\")\n", + "\n", "\n", "year = 2021\n", "path_prefix = f\"{year}/\"" diff --git a/src/column_checks.py b/src/column_checks.py index 5fb8fd03..42ca2cb0 100644 --- a/src/column_checks.py +++ b/src/column_checks.py @@ -18,6 +18,7 @@ checks. """ from logging_util import get_logger + logger = get_logger(__name__) @@ -332,6 +333,22 @@ "ba_code", "aggregated_plants", }, + "primary_fuel_table": { + "plant_id_eia", + "generator_id", + "subplant_id", + "energy_source_code", + "plant_primary_fuel_from_fuel_consumed_for_electricity_mmbtu", + "plant_primary_fuel_from_net_generation_mwh", + "plant_primary_fuel_from_capacity_mw", + "plant_primary_fuel_from_mode", + "plant_primary_fuel", + "subplant_primary_fuel_from_fuel_consumed_for_electricity_mmbtu", + "subplant_primary_fuel_from_net_generation_mwh", + "subplant_primary_fuel_from_capacity_mw", + "subplant_primary_fuel_from_mode", + "subplant_primary_fuel", + }, } diff --git a/src/data_cleaning.py b/src/data_cleaning.py index f103413a..5ba9aab4 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -593,12 +593,14 @@ def create_primary_fuel_table(gen_fuel_allocated, pudl_out, add_subplant_id, yea ] plant_primary_fuel = calculate_aggregated_primary_fuel( - gen_fuel_allocated, gen_primary_fuel, ["plant_id_eia"], pudl_out, year + gen_fuel_allocated, gen_primary_fuel, "plant", pudl_out, year ) + validation.flag_possible_primary_fuel_mismatches(plant_primary_fuel) + # merge the plant primary fuel into the gen primary fuel primary_fuel_table = gen_primary_fuel.merge( - plant_primary_fuel[["plant_id_eia", "plant_primary_fuel"]], + plant_primary_fuel, how="left", on="plant_id_eia", validate="many_to_one", @@ -609,14 +611,12 @@ def create_primary_fuel_table(gen_fuel_allocated, pudl_out, add_subplant_id, yea subplant_primary_fuel = calculate_aggregated_primary_fuel( gen_fuel_allocated, gen_primary_fuel, - ["plant_id_eia", "subplant_id"], + "subplant", pudl_out, year, ) primary_fuel_table = primary_fuel_table.merge( - subplant_primary_fuel[ - ["plant_id_eia", "subplant_id", "subplant_primary_fuel"] - ], + subplant_primary_fuel, how="left", on=["plant_id_eia", "subplant_id"], validate="many_to_one", @@ -626,7 +626,7 @@ def create_primary_fuel_table(gen_fuel_allocated, pudl_out, add_subplant_id, yea def calculate_aggregated_primary_fuel( - gen_fuel_allocated, gen_primary_fuel, agg_keys, pudl_out, year + gen_fuel_allocated, gen_primary_fuel, agg_level, pudl_out, year ): """ Takes generator-level fuel data and calculates primary fuel for the subplant or plant level. @@ -634,12 +634,20 @@ def calculate_aggregated_primary_fuel( Args: gen_fuel_allocated: dataframe of allocated fuel, generation, and emissions data by generator gen_primary_fuel: dataframe of primary fuel by generator - agg_keys: either ["plant_id_eia"] for plant aggregation or ["plant_id_eia", "subplant_id"] for subplant aggregation + agg_level: either "plant" or "subplant" pudl_out: for loading pudl output tables """ + if agg_level == "plant": + agg_keys = ["plant_id_eia"] + elif agg_level == "subplant": + agg_keys = ["plant_id_eia", "subplant_id"] + else: + raise UserWarning( + f"Argument agg_level must be 'plant' or 'subplant', not '{agg_level}'" + ) primary_fuel_from_capacity = calculate_capacity_based_primary_fuel( - pudl_out, agg_keys, year + pudl_out, agg_level, agg_keys, year ) # NOTE: In some rare cases, a plant will have no fuel specified by @@ -651,7 +659,7 @@ def calculate_aggregated_primary_fuel( .agg(lambda x: pd.Series.mode(x)[0]) .to_frame() .reset_index() - .rename(columns={"energy_source_code": "primary_fuel_from_mode"}) + .rename(columns={"energy_source_code": f"{agg_level}_primary_fuel_from_mode"}) ) # create a blank dataframe with all of the plant ids to hold primary fuel data @@ -686,7 +694,7 @@ def calculate_aggregated_primary_fuel( subset=agg_keys, keep=False ) primary_fuel_calc = primary_fuel_calc.rename( - columns={"energy_source_code": f"primary_fuel_from_{source}"} + columns={"energy_source_code": f"{agg_level}_primary_fuel_from_{source}"} ) # merge the primary fuel into the main table @@ -706,49 +714,45 @@ def calculate_aggregated_primary_fuel( # Use the fuel consumption-based primary fuel first, then fill using capacity-based # primary fuel, then generation based. Finally, to break all ties, use the energy # source code that appears most often for generators of a plant (mode). - if "subplant_id" in agg_keys: - level = "subplant" - else: - level = "plant" - agg_primary_fuel[f"{level}_primary_fuel"] = agg_primary_fuel[ - "primary_fuel_from_fuel_consumed_for_electricity_mmbtu" + agg_primary_fuel[f"{agg_level}_primary_fuel"] = agg_primary_fuel[ + f"{agg_level}_primary_fuel_from_fuel_consumed_for_electricity_mmbtu" ] - agg_primary_fuel[f"{level}_primary_fuel"] = agg_primary_fuel[ - f"{level}_primary_fuel" - ].fillna(agg_primary_fuel["primary_fuel_from_capacity_mw"]) - agg_primary_fuel[f"{level}_primary_fuel"] = agg_primary_fuel[ - f"{level}_primary_fuel" - ].fillna(agg_primary_fuel["primary_fuel_from_net_generation_mwh"]) - agg_primary_fuel[f"{level}_primary_fuel"] = agg_primary_fuel[ - f"{level}_primary_fuel" - ].fillna(agg_primary_fuel["primary_fuel_from_mode"]) + agg_primary_fuel[f"{agg_level}_primary_fuel"] = agg_primary_fuel[ + f"{agg_level}_primary_fuel" + ].fillna(agg_primary_fuel[f"{agg_level}_primary_fuel_from_capacity_mw"]) + agg_primary_fuel[f"{agg_level}_primary_fuel"] = agg_primary_fuel[ + f"{agg_level}_primary_fuel" + ].fillna(agg_primary_fuel[f"{agg_level}_primary_fuel_from_net_generation_mwh"]) + agg_primary_fuel[f"{agg_level}_primary_fuel"] = agg_primary_fuel[ + f"{agg_level}_primary_fuel" + ].fillna(agg_primary_fuel[f"{agg_level}_primary_fuel_from_mode"]) # sometimes nuclear generators report 0 fuel consumption in EIA-923. # To ensure that a nuclear plant does not get assigned a fuel code of # a backup generator, we use the nameplate capacity to assign the # primary fuel for any plants that contain a nuclear generator agg_primary_fuel.loc[ - agg_primary_fuel["primary_fuel_from_capacity_mw"] == "NUC", - f"{level}_primary_fuel", + agg_primary_fuel[f"{agg_level}_primary_fuel_from_capacity_mw"] == "NUC", + f"{agg_level}_primary_fuel", ] = "NUC" # check that there are no missing primary fuels - if len(agg_primary_fuel[agg_primary_fuel[f"{level}_primary_fuel"].isna()]) > 0: + if len(agg_primary_fuel[agg_primary_fuel[f"{agg_level}_primary_fuel"].isna()]) > 0: plants_with_no_primary_fuel = agg_primary_fuel[ - agg_primary_fuel[f"{level}_primary_fuel"].isna() + agg_primary_fuel[f"{agg_level}_primary_fuel"].isna() ] logger.warning( f"Check the following plants: {list(plants_with_no_primary_fuel.plant_id_eia.unique())}" ) raise UserWarning( - f"{level} primary fuel table contains missing primary fuels.\ + f"{agg_level} primary fuel table contains missing primary fuels.\ Update method of `create_primary_fuel_table()` to fix" ) return agg_primary_fuel -def calculate_capacity_based_primary_fuel(pudl_out, agg_keys, year): +def calculate_capacity_based_primary_fuel(pudl_out, agg_level, agg_keys, year): # create a table of primary fuel by nameplate capacity gen_capacity = pudl_out.gens_eia860().loc[ :, ["plant_id_eia", "generator_id", "capacity_mw", "energy_source_code_1"] @@ -789,7 +793,7 @@ def calculate_capacity_based_primary_fuel(pudl_out, agg_keys, year): gen_capacity.groupby(agg_keys, dropna=False)["capacity_mw"].transform(max) == gen_capacity["capacity_mw"] ][agg_keys + ["energy_source_code_1"]].rename( - columns={"energy_source_code_1": "primary_fuel_from_capacity_mw"} + columns={"energy_source_code_1": f"{agg_level}_primary_fuel_from_capacity_mw"} ) # drop any duplicate entries (if two fuel types have the same nameplate capacity) diff --git a/src/data_pipeline.py b/src/data_pipeline.py index dc78b996..a25035dd 100644 --- a/src/data_pipeline.py +++ b/src/data_pipeline.py @@ -157,9 +157,37 @@ def main(): primary_fuel_table, subplant_emission_factors, ) = data_cleaning.clean_eia923(year, args.small) + # output primary fuel table + output_data.output_intermediate_data( + primary_fuel_table, + "primary_fuel_table", + path_prefix, + year, + args.skip_outputs, + ) + # remove intermediate columns from primary fuel table + primary_fuel_table = primary_fuel_table[ + [ + "plant_id_eia", + "subplant_id", + "generator_id", + "energy_source_code", + "plant_primary_fuel", + "subplant_primary_fuel", + ] + ] # Add primary fuel data to each generator eia923_allocated = eia923_allocated.merge( - primary_fuel_table, + primary_fuel_table[ + [ + "plant_id_eia", + "subplant_id", + "generator_id", + "energy_source_code", + "plant_primary_fuel", + "subplant_primary_fuel", + ] + ], how="left", on=["plant_id_eia", "subplant_id", "generator_id"], validate="m:1", diff --git a/src/validation.py b/src/validation.py index 49ebcdb6..d6adf29c 100644 --- a/src/validation.py +++ b/src/validation.py @@ -88,6 +88,62 @@ def check_allocated_gf_matches_input_gf(pudl_out, gen_fuel_allocated): ) +def flag_possible_primary_fuel_mismatches(plant_primary_fuel): + """ + Since we do not know exactly how plants are assigned to fuel categories in EIA-930, + it is possible that the primary fuel we assign to the plant may differ from the + primary fuel category used in EIA-930. The most likely source of this disconnect is + if these plants are assigned a primary fuel based on the type of generation with the + highest nameplate capacity (since this is relatively static over time), rather than + based on fuel consumption (which may change year-to-year). + + This test identifies where the primary fuel that the pipeline assigns would lead to + the plant being categorized under a different fuel category than if a capacity-based + method were used. + + Plants flagged by this test are not necessarily incorrectly assigned, but rather + this is intended to bring this issue to our attention as a potential source of + inconsistency. + """ + test = plant_primary_fuel.copy()[ + ["plant_id_eia", "plant_primary_fuel_from_capacity_mw", "plant_primary_fuel"] + ] + + for esc_column in ["plant_primary_fuel_from_capacity_mw", "plant_primary_fuel"]: + + # load the fuel category table + energy_source_groups = pd.read_csv( + manual_folder("energy_source_groups.csv"), dtype=get_dtypes() + )[["energy_source_code", "fuel_category_eia930"]].rename( + columns={ + "energy_source_code": esc_column, + "fuel_category_eia930": f"{esc_column}_category", + } + ) + + # assign a fuel category to the monthly eia data + test = test.merge( + energy_source_groups, + how="left", + on=esc_column, + validate="m:1", + ) + + mismatched_primary_fuels = test[ + ( + test["plant_primary_fuel_from_capacity_mw_category"] + != test["plant_primary_fuel_category"] + ) + & (~test["plant_primary_fuel_from_capacity_mw_category"].isna()) + ] + + if len(mismatched_primary_fuels) > 0: + logger.warning( + f"There are {len(mismatched_primary_fuels)} plants where the assigned primary fuel doesn't match the capacity-based primary fuel.\nIt is possible that these plants will categorized as a different fuel in EIA-930" + ) + logger.warning("\n" + mismatched_primary_fuels.to_string()) + + def test_for_negative_values(df, small: bool = False): """Checks that there are no unexpected negative values in the data.""" logger.info("Checking that fuel and emissions values are positive... ") From 3a7f689929ef9fec8bec36855b79fc78c8eac969 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 11 Mar 2023 12:56:51 -0800 Subject: [PATCH 04/85] add method to gtn validation --- .../GH292_GTN_validation.ipynb | 111 +++++++++++++++++- src/validation.py | 13 ++ 2 files changed, 119 insertions(+), 5 deletions(-) diff --git a/notebooks/work_in_progress/GH292_GTN_validation.ipynb b/notebooks/work_in_progress/GH292_GTN_validation.ipynb index 27c2447a..8d1ad4f1 100644 --- a/notebooks/work_in_progress/GH292_GTN_validation.ipynb +++ b/notebooks/work_in_progress/GH292_GTN_validation.ipynb @@ -32,7 +32,12 @@ "import eia930\n", "\n", "year = 2021\n", - "path_prefix = f\"{year}/\"" + "path_prefix = f\"{year}/\"\n", + "\n", + "from logging_util import get_logger, configure_root_logger\n", + "\n", + "configure_root_logger()\n", + "logger = get_logger(\"test\")" ] }, { @@ -43,7 +48,7 @@ "source": [ "cems = pd.read_csv(outputs_folder(f\"{path_prefix}/cems_subplant_{year}.csv\"), dtype=get_dtypes())\n", "eia923_allocated = pd.read_csv(outputs_folder(f\"{path_prefix}/eia923_allocated_{year}.csv\"), dtype=get_dtypes())\n", - "plant_attributes = pd.read_csv(outputs_folder(f\"{path_prefix}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes())" + "#plant_attributes = pd.read_csv(outputs_folder(f\"{path_prefix}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes())" ] }, { @@ -52,7 +57,7 @@ "metadata": {}, "outputs": [], "source": [ - "from logging_util import get_logger, configure_root_logger" + "validation.validate_gross_to_net_conversion(cems, eia923_allocated)" ] }, { @@ -61,10 +66,106 @@ "metadata": {}, "outputs": [], "source": [ - "configure_root_logger()\n", - "logger = get_logger(\"test\")" + "logger.info(\n", + " \"Checking that calculated net generation matches reported net generation in EIA-923... \"\n", + ")\n", + "# merge together monthly subplant totals from EIA and calculated from CEMS\n", + "eia_netgen = (\n", + " eia923_allocated.groupby(\n", + " [\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False\n", + " )[[\"net_generation_mwh\"]]\n", + " .sum(min_count=1)\n", + " .reset_index()\n", + " .dropna(subset=\"net_generation_mwh\")\n", + ")\n", + "calculated_netgen = (\n", + " cems.groupby([\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False)[\n", + " \"net_generation_mwh\"\n", + " ]\n", + " .sum()\n", + " .reset_index()\n", + ")\n", + "validated_ng = eia_netgen.merge(\n", + " calculated_netgen,\n", + " how=\"inner\",\n", + " on=[\"plant_id_eia\", \"subplant_id\", \"report_date\"],\n", + " suffixes=(\"_eia\", \"_calc\"),\n", + " validate=\"1:1\",\n", + ")\n", + "\n", + "validated_ng = validated_ng.groupby(\"plant_id_eia\")[\n", + " [\"net_generation_mwh_eia\", \"net_generation_mwh_calc\"]\n", + "].sum()\n", + "\n", + "validated_ng = validated_ng.round(3)\n", + "validated_ng = validated_ng[\n", + " validated_ng[[\"net_generation_mwh_eia\", \"net_generation_mwh_calc\"]].sum(axis=1)\n", + " != 0\n", + "]\n", + "\n", + "validated_ng[\"pct_error\"] = (\n", + " validated_ng[\"net_generation_mwh_calc\"] - validated_ng[\"net_generation_mwh_eia\"]\n", + ") / validated_ng[\"net_generation_mwh_eia\"]\n", + "\n", + "cems_net_not_equal_to_eia = validated_ng[validated_ng[\"pct_error\"] != 0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gtn_method = cems.loc[cems[\"plant_id_eia\"].isin(list(cems_net_not_equal_to_eia.index)), [\"plant_id_eia\", \"gtn_method\"]].drop_duplicates()\n", + "gtn_method[\"gtn_method\"] = gtn_method[\"gtn_method\"].astype(str)\n", + "gtn_method.groupby(\"plant_id_eia\").agg([\"unique\"]).droplevel(level=1, axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gtn_method = (\n", + " cems[cems[\"plant_id_eia\"].isin(list(cems_net_not_equal_to_eia.index))]\n", + " .groupby(\"plant_id_eia\")[[\"gtn_method\"]]\n", + " .agg([\"unique\"])\n", + " )" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems = pd.read_csv(outputs_folder(f\"{path_prefix}/cems_subplant_{year}.csv\"), dtype=get_dtypes())\n", + "eia923_allocated = pd.read_csv(outputs_folder(f\"{path_prefix}/eia923_allocated_{year}.csv\"), dtype=get_dtypes())\n", + "plant_attributes = pd.read_csv(outputs_folder(f\"{path_prefix}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, diff --git a/src/validation.py b/src/validation.py index 16b0331b..88c3100e 100644 --- a/src/validation.py +++ b/src/validation.py @@ -401,6 +401,19 @@ def validate_gross_to_net_conversion(cems, eia923_allocated): cems_net_not_equal_to_eia = validated_ng[validated_ng["pct_error"] != 0] + # get the gtn method used for these plants + gtn_method = cems.loc[ + cems["plant_id_eia"].isin(list(cems_net_not_equal_to_eia.index)), + ["plant_id_eia", "gtn_method"], + ].drop_duplicates() + gtn_method["gtn_method"] = gtn_method["gtn_method"].astype(str) + gtn_method = ( + gtn_method.groupby("plant_id_eia").agg(["unique"]).droplevel(level=1, axis=1) + ) + cems_net_not_equal_to_eia = cems_net_not_equal_to_eia.merge( + gtn_method, how="left", left_index=True, right_index=True + ) + if len(cems_net_not_equal_to_eia) > 0: logger.warning( f"There are {len(cems_net_not_equal_to_eia)} plants where calculated annual net generation does not match EIA annual net generation." From 1456644c6fe58f75c9e2d6ded22a33fb48c61962 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 11 Mar 2023 14:00:45 -0800 Subject: [PATCH 05/85] validate cc subplants --- src/column_checks.py | 12 ++++++++++++ src/data_cleaning.py | 46 ++++++++++++++++++++++++++++++++++++-------- src/data_pipeline.py | 9 ++++++++- src/validation.py | 37 +++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 9 deletions(-) diff --git a/src/column_checks.py b/src/column_checks.py index 5fb8fd03..a1ac3696 100644 --- a/src/column_checks.py +++ b/src/column_checks.py @@ -18,6 +18,7 @@ checks. """ from logging_util import get_logger + logger = get_logger(__name__) @@ -325,6 +326,17 @@ "plant_regression_shift_mw", "plant_regression_rsq_adj", }, + "subplant_crosswalk": { + "plant_id_epa", + "emissions_unit_id_epa", + "plant_id_eia", + "generator_id", + "subplant_id", + "unit_id_pudl", + "current_planned_operating_date", + "retirement_date", + "prime_mover_code", + }, "shaped_aggregated_plants": { "plant_id_eia", "report_date", diff --git a/src/data_cleaning.py b/src/data_cleaning.py index f103413a..cf55d01d 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -59,7 +59,9 @@ def identify_subplants(year, number_of_years=5): # add subplant ids to the data logger.info("identifying unique subplants") - generate_subplant_ids(start_year, end_year, cems_ids) + subplant_crosswalk = generate_subplant_ids(start_year, end_year, cems_ids) + + return subplant_crosswalk def generate_subplant_ids(start_year, end_year, cems_ids): @@ -164,14 +166,14 @@ def generate_subplant_ids(start_year, end_year, cems_ids): subplant_crosswalk_complete = add_operating_and_retirement_dates( subplant_crosswalk_complete, start_year, end_year ) - - os.makedirs(outputs_folder(f"{end_year}"), exist_ok=True) - - # export the crosswalk to csv - subplant_crosswalk_complete.to_csv( - outputs_folder(f"{end_year}/subplant_crosswalk_{end_year}.csv"), - index=False, + # add prime mover code to the crosswalk + subplant_crosswalk_complete = add_prime_mover_to_subplant_crosswalk( + subplant_crosswalk_complete, end_year ) + # validate that there are no orphaned combined cycle plant parts in a subplant + validation.check_for_orphaned_cc_part_in_subplant(subplant_crosswalk_complete) + + return subplant_crosswalk_complete def manually_update_subplant_id(subplant_crosswalk): @@ -383,6 +385,34 @@ def add_operating_and_retirement_dates(df, start_year, end_year): return df +def add_prime_mover_to_subplant_crosswalk(df, year): + """Adds a column identifying each generator's prime_mover to a dataframe.""" + pudl_db = f"sqlite:///{downloads_folder()}pudl/pudl_data/sqlite/pudl.sqlite" + pudl_engine = sa.create_engine(pudl_db) + # get values starting with the year prior to teh start year so that we can get proposed operating dates for the start year (which are reported in year -1) + pudl_out_pm = pudl.output.pudltabl.PudlTabl( + pudl_engine, + freq="AS", + start_date=f"{year}-01-01", + end_date=f"{year}-12-31", + ) + generator_pm = pudl_out_pm.gens_eia860().loc[ + :, + [ + "plant_id_eia", + "generator_id", + "prime_mover_code", + ], + ] + + # merge the dates into the crosswalk + df = df.merge( + generator_pm, how="left", on=["plant_id_eia", "generator_id"], validate="m:1" + ) + + return df + + def clean_eia923( year: int, small: bool, diff --git a/src/data_pipeline.py b/src/data_pipeline.py index dc78b996..c70404bf 100644 --- a/src/data_pipeline.py +++ b/src/data_pipeline.py @@ -147,7 +147,14 @@ def main(): # 2. Identify subplants #################################################################################### logger.info("2. Identifying subplant IDs") - data_cleaning.identify_subplants(year) + subplant_crosswalk = data_cleaning.identify_subplants(year) + output_data.output_intermediate_data( + subplant_crosswalk, + "subplant_crosswalk", + path_prefix, + year, + args.skip_outputs, + ) # 3. Clean EIA-923 Generation and Fuel Data at the Monthly Level #################################################################################### diff --git a/src/validation.py b/src/validation.py index 49ebcdb6..bd796323 100644 --- a/src/validation.py +++ b/src/validation.py @@ -143,6 +143,43 @@ def test_for_missing_values(df, small: bool = False): return missing_test +def check_for_orphaned_cc_part_in_subplant(subplant_crosswalk): + """ + Combined cycle generators contain a steam part (CA) and turbine part (CT) that are + linked together. Thus, our subplant groups that contain one part of a combined cycle + plant should always in theory contain the other part as well. This test checks that + both parts exist in a subplant if one exists. + + Besides CT and CA prime movers, there is also CS prime movers which represent a + "single shaft" combined cycle unit where the steam and turbine parts share a single + generator. These prime movers are allowed to be by themselves in a subplant, as are + CC prime movers, which represent a "total unit." + """ + cc_pm_codes = ["CA", "CT", "CS", "CC"] + # keep all rows that contain a combined cycle prime mover part + cc_subplants = subplant_crosswalk[ + subplant_crosswalk["prime_mover_code"].isin(cc_pm_codes) + ] + # for each subplant, identify a list of all CC prime movers in that subplant + cc_subplants = cc_subplants.groupby(["plant_id_eia", "subplant_id"])[ + "prime_mover_code" + ].agg(["unique"]) + cc_subplants["unique_cc_pms"] = [ + ",".join(map(str, l)) for l in cc_subplants["unique"] + ] + cc_subplants = cc_subplants.drop(columns="unique") + # identify where there are subplants that only contain a single CC part + orphaned_cc_parts = cc_subplants[ + (cc_subplants["unique_cc_pms"] == "CA") + | (cc_subplants["unique_cc_pms"] == "CT") + ] + if len(orphaned_cc_parts) > 0: + logger.warning( + f"There are {len(orphaned_cc_parts)} subplants that only contain one part of a combined cycle system.\nSubplants that represent combined cycle generation should contain both CA and CT parts." + ) + logger.warning("\n" + orphaned_cc_parts.to_string()) + + def test_chp_allocation(df): """Checks that the CHP allocation didn't create any anomalous values.""" logger.info( From 8e15c75c567a64f3b4a0262a9fbcef62d7b3653c Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 25 Mar 2023 13:59:25 -0700 Subject: [PATCH 06/85] fix logging bug --- src/data_pipeline.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/data_pipeline.py b/src/data_pipeline.py index dc78b996..1f4e6c72 100644 --- a/src/data_pipeline.py +++ b/src/data_pipeline.py @@ -72,17 +72,6 @@ def main(): args = get_args() year = args.year - # configure the logger - # Log the print statements to a file for debugging. - configure_root_logger( - logfile=results_folder(f"{year}/data_quality_metrics/data_pipeline.log") - ) - logger = get_logger("data_pipeline") - print_args(args, logger) - - logger.info(f"Running data pipeline for year {year}") - validation.validate_year(year) - # 0. Set up directory structure path_prefix = "" if not args.small else "small/" path_prefix += "flat/" if args.flat else "" @@ -112,6 +101,17 @@ def main(): exist_ok=True, ) + # configure the logger + # Log the print statements to a file for debugging. + configure_root_logger( + logfile=results_folder(f"{year}/data_quality_metrics/data_pipeline.log") + ) + logger = get_logger("data_pipeline") + print_args(args, logger) + + logger.info(f"Running data pipeline for year {year}") + validation.validate_year(year) + # 1. Download data #################################################################################### logger.info("1. Downloading data") From 185021ff33ba0698090decdfff2f8e67b517d1cd Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 25 Mar 2023 14:09:05 -0700 Subject: [PATCH 07/85] update citation file --- CITATION.cff | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index f2125042..c09f942e 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -21,7 +21,7 @@ authors: affiliation: "Singularity Energy" identifiers: - type: doi - value: 'https://doi.org/10.5281/zenodo.7495818' -version: 0.2.0 + value: 'https://doi.org/10.5281/zenodo.7692997' +version: 0.2.2 license: MIT -date-released: '2022-12-30' +date-released: '2023-03-02' From 5ee7c3339b8c7065d763017a5853bb98be9380eb Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 25 Mar 2023 16:40:32 -0700 Subject: [PATCH 08/85] check for complete timeseries --- src/data_pipeline.py | 30 +++++++++++++++++++++++ src/output_data.py | 9 +++++++ src/validation.py | 58 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) diff --git a/src/data_pipeline.py b/src/data_pipeline.py index dc78b996..d72519ec 100644 --- a/src/data_pipeline.py +++ b/src/data_pipeline.py @@ -238,6 +238,12 @@ def main(): df_name="partial_cems_plant", keys=["plant_id_eia", "subplant_id"], ) + validation.check_for_complete_timeseries( + df=partial_cems_plant, + df_name="partial_cems_plant", + keys=["plant_id_eia", "subplant_id"], + period="month", + ) output_data.output_intermediate_data( partial_cems_plant, "partial_cems_plant", @@ -256,6 +262,12 @@ def main(): df_name="partial_cems_subplant", keys=["plant_id_eia", "subplant_id"], ) + validation.check_for_complete_timeseries( + df=partial_cems_subplant, + df_name="partial_cems_subplant", + keys=["plant_id_eia", "subplant_id"], + period="month", + ) output_data.output_intermediate_data( partial_cems_subplant, "partial_cems_subplant", @@ -299,6 +311,12 @@ def main(): df_name="cems_subplant", keys=["plant_id_eia", "subplant_id"], ) + validation.check_for_complete_timeseries( + df=cems, + df_name="cems_subplant", + keys=["plant_id_eia", "subplant_id"], + period="month", + ) output_data.output_intermediate_data( cems, "cems_subplant", path_prefix, year, args.skip_outputs ) @@ -456,6 +474,12 @@ def main(): df_name="shaped_eia_data", keys=["plant_id_eia"], ) + validation.check_for_complete_timeseries( + df=shaped_eia_data, + df_name="shaped_eia_data", + keys=["plant_id_eia"], + period="month", + ) output_data.output_intermediate_data( shaped_eia_data, "shaped_eia923_data", path_prefix, year, args.skip_outputs ) @@ -515,6 +539,12 @@ def main(): df_name="combined_plant_data", keys=["plant_id_eia"], ) + validation.check_for_complete_timeseries( + df=combined_plant_data, + df_name="combined_plant_data", + keys=["plant_id_eia"], + period="year", + ) if not args.shape_individual_plants: output_data.output_plant_data( combined_plant_data, diff --git a/src/output_data.py b/src/output_data.py index a3d891af..9d62f752 100644 --- a/src/output_data.py +++ b/src/output_data.py @@ -181,6 +181,9 @@ def output_plant_data(df, path_prefix, resolution, skip_outputs, plant_attribute validation.validate_unique_datetimes( df, "individual_plant_data", ["plant_id_eia"] ) + validation.check_for_complete_timeseries( + df, "individual_plant_data", ["plant_id_eia"], "year" + ) # Separately save real and aggregate plants output_to_results( df[df.plant_id_eia > 900000], @@ -551,6 +554,12 @@ def add_generated_emission_rate_columns(df): df_name="power sector hourly ba table", keys=["fuel_category"], ) + validation.check_for_complete_timeseries( + ba_table_hourly, + "power sector hourly ba table", + ["fuel_category"], + "year", + ) # export to a csv output_to_results( diff --git a/src/validation.py b/src/validation.py index 49ebcdb6..bc2391af 100644 --- a/src/validation.py +++ b/src/validation.py @@ -518,6 +518,64 @@ def validate_unique_datetimes(df, df_name, keys): ) +def check_for_complete_timeseries(df, df_name, keys, period): + """Validates that a timeseries contains complete hourly data. + + If the `period` is a 'year', checks that the length of the timeseries is 8760 (for a + non-leap year) or 8784 (for a leap year). If the `period` is a 'month', checks that + the length of the timeseries is equal to number of days * 24 in the month associated + with the `report_date` column. + + Args: + df: dataframe containing datetime columns + df_name: a descriptive name for the dataframe + year + keys: list of column names that contain the groups within which datetimes should be unique + period: either 'month' or 'year'. Period within which to ensure complete hourly data""" + + if period == "year": + # identify the year of the data + year = df.datetime_utc.dt.year.mode()[0] + # count the number of timestamps in each group + test = df.groupby(keys)[["datetime_utc"]].count() + # if the year is divisible by 4, it is a leap year + if year % 4 == 0: + hours_in_year = 8784 + else: + hours_in_year = 8760 + test["expected_num_hours"] = hours_in_year + # identify any rows where the number of timestamps is not equal to the total number of hours in the year + test = test[test["datetime_utc"] != test["expected_num_hours"]] + if len(test) > 0: + logger.warning( + f"There are incomplete timeseries for the following {keys} groups in {df_name}" + ) + logger.warning("\n" + test.to_string()) + elif period == "month": + + # count the number of timestamps in each group-month + test = ( + df.groupby(keys + ["report_date"])[["datetime_utc"]] + .agg(["count", "min", "max"]) + .droplevel(level=0, axis=1) + ) + # identify the number of hours in a complete date range for that month + test["expected_num_hours"] = test.apply( + lambda row: len(pd.date_range(row["min"], row["max"], freq="H")), axis=1 + ) + # identify any rows where the number of timestamps is not equal to the total number of hours in the month + test = test[test["count"] != test["expected_num_hours"]] + if len(test) > 0: + logger.warning( + f"There are incomplete timeseries for the following {keys} groups in {df_name}" + ) + logger.warning("\n" + test.to_string()) + else: + raise UserWarning( + f"{period} is not a valid value for the `period` argument in `check_for_complete_timeseries`. Value must be 'year' or 'month'" + ) + + # DATA QUALITY METRIC FUNCTIONS ######################################################################################## From 05a4c7ddd55786a1ea47020a436d4ef207c9b1e0 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 25 Mar 2023 16:43:44 -0700 Subject: [PATCH 09/85] update function doc --- src/validation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/validation.py b/src/validation.py index bc2391af..e828f77d 100644 --- a/src/validation.py +++ b/src/validation.py @@ -523,8 +523,8 @@ def check_for_complete_timeseries(df, df_name, keys, period): If the `period` is a 'year', checks that the length of the timeseries is 8760 (for a non-leap year) or 8784 (for a leap year). If the `period` is a 'month', checks that - the length of the timeseries is equal to number of days * 24 in the month associated - with the `report_date` column. + the length of the timeseries is equal to the length of the complete date_range + between the earliest and latest timestamp in a month. Args: df: dataframe containing datetime columns From 32b71aa87c330de24643ffc45ca38eb09777d8bb Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 13 May 2023 15:15:30 -0700 Subject: [PATCH 10/85] fix CAISO timestamp correction --- src/eia930.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/eia930.py b/src/eia930.py index 42ae2d6e..34f48ea9 100644 --- a/src/eia930.py +++ b/src/eia930.py @@ -421,11 +421,23 @@ def manual_930_adjust(raw: pd.DataFrame): raw = pd.concat([raw, sc_dat], axis="columns") # PJM, CISO, TEPC: shift by one hour - for ba in ["PJM", "CISO", "TEPC"]: + # CISO correction before Jun 16, 2022 + start_of_hour_bas = {"CISO": "2022-06-16 07:00:00+00", "PJM": None, "TEPC": None} + for ba in list(start_of_hour_bas.keys()): cols = get_columns(ba, raw.columns) - new = raw[cols].shift(1, freq="H") - raw = raw.drop(columns=cols) - raw = pd.concat([raw, new], axis="columns") + correction_end_date = start_of_hour_bas[ba] + if correction_end_date is not None: + new = raw[cols].copy() + new.loc[raw.index < correction_end_date, cols] = new.loc[ + new.index < correction_end_date, cols + ].shift(1, freq="H") + raw = raw.drop(columns=cols) + raw = pd.concat([raw, new], axis="columns") + else: + cols = get_columns(ba, raw.columns) + new = raw[cols].shift(1, freq="H") + raw = raw.drop(columns=cols) + raw = pd.concat([raw, new], axis="columns") # Interchange sign. Do before we change interchange time for PJM, because # identification of sign shift is based on raw data From d45f88e8fbff9d2a724abd529d72a5ca9c798a85 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 18 May 2023 09:37:57 -0700 Subject: [PATCH 11/85] remove WIP notebook --- .../GH292_GTN_validation.ipynb | 363 ------------------ 1 file changed, 363 deletions(-) delete mode 100644 notebooks/work_in_progress/GH292_GTN_validation.ipynb diff --git a/notebooks/work_in_progress/GH292_GTN_validation.ipynb b/notebooks/work_in_progress/GH292_GTN_validation.ipynb deleted file mode 100644 index 8d1ad4f1..00000000 --- a/notebooks/work_in_progress/GH292_GTN_validation.ipynb +++ /dev/null @@ -1,363 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# import packages\n", - "import pandas as pd\n", - "import numpy as np\n", - "import os\n", - "import plotly.express as px\n", - "\n", - "%reload_ext autoreload\n", - "%autoreload 2\n", - "\n", - "# # Tell python where to look for modules.\n", - "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", - "\n", - "import download_data\n", - "import load_data\n", - "from column_checks import get_dtypes\n", - "from filepaths import *\n", - "import impute_hourly_profiles\n", - "import data_cleaning\n", - "import output_data\n", - "import emissions\n", - "import validation\n", - "from gross_to_net_generation import *\n", - "import eia930\n", - "\n", - "year = 2021\n", - "path_prefix = f\"{year}/\"\n", - "\n", - "from logging_util import get_logger, configure_root_logger\n", - "\n", - "configure_root_logger()\n", - "logger = get_logger(\"test\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cems = pd.read_csv(outputs_folder(f\"{path_prefix}/cems_subplant_{year}.csv\"), dtype=get_dtypes())\n", - "eia923_allocated = pd.read_csv(outputs_folder(f\"{path_prefix}/eia923_allocated_{year}.csv\"), dtype=get_dtypes())\n", - "#plant_attributes = pd.read_csv(outputs_folder(f\"{path_prefix}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "validation.validate_gross_to_net_conversion(cems, eia923_allocated)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "logger.info(\n", - " \"Checking that calculated net generation matches reported net generation in EIA-923... \"\n", - ")\n", - "# merge together monthly subplant totals from EIA and calculated from CEMS\n", - "eia_netgen = (\n", - " eia923_allocated.groupby(\n", - " [\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False\n", - " )[[\"net_generation_mwh\"]]\n", - " .sum(min_count=1)\n", - " .reset_index()\n", - " .dropna(subset=\"net_generation_mwh\")\n", - ")\n", - "calculated_netgen = (\n", - " cems.groupby([\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False)[\n", - " \"net_generation_mwh\"\n", - " ]\n", - " .sum()\n", - " .reset_index()\n", - ")\n", - "validated_ng = eia_netgen.merge(\n", - " calculated_netgen,\n", - " how=\"inner\",\n", - " on=[\"plant_id_eia\", \"subplant_id\", \"report_date\"],\n", - " suffixes=(\"_eia\", \"_calc\"),\n", - " validate=\"1:1\",\n", - ")\n", - "\n", - "validated_ng = validated_ng.groupby(\"plant_id_eia\")[\n", - " [\"net_generation_mwh_eia\", \"net_generation_mwh_calc\"]\n", - "].sum()\n", - "\n", - "validated_ng = validated_ng.round(3)\n", - "validated_ng = validated_ng[\n", - " validated_ng[[\"net_generation_mwh_eia\", \"net_generation_mwh_calc\"]].sum(axis=1)\n", - " != 0\n", - "]\n", - "\n", - "validated_ng[\"pct_error\"] = (\n", - " validated_ng[\"net_generation_mwh_calc\"] - validated_ng[\"net_generation_mwh_eia\"]\n", - ") / validated_ng[\"net_generation_mwh_eia\"]\n", - "\n", - "cems_net_not_equal_to_eia = validated_ng[validated_ng[\"pct_error\"] != 0]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gtn_method = cems.loc[cems[\"plant_id_eia\"].isin(list(cems_net_not_equal_to_eia.index)), [\"plant_id_eia\", \"gtn_method\"]].drop_duplicates()\n", - "gtn_method[\"gtn_method\"] = gtn_method[\"gtn_method\"].astype(str)\n", - "gtn_method.groupby(\"plant_id_eia\").agg([\"unique\"]).droplevel(level=1, axis=1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gtn_method = (\n", - " cems[cems[\"plant_id_eia\"].isin(list(cems_net_not_equal_to_eia.index))]\n", - " .groupby(\"plant_id_eia\")[[\"gtn_method\"]]\n", - " .agg([\"unique\"])\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cems = pd.read_csv(outputs_folder(f\"{path_prefix}/cems_subplant_{year}.csv\"), dtype=get_dtypes())\n", - "eia923_allocated = pd.read_csv(outputs_folder(f\"{path_prefix}/eia923_allocated_{year}.csv\"), dtype=get_dtypes())\n", - "plant_attributes = pd.read_csv(outputs_folder(f\"{path_prefix}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# aggregate the hourly cems data by subplant\n", - "gross_gen_data = cems[\n", - " [\n", - " \"plant_id_eia\",\n", - " \"subplant_id\",\n", - " \"report_date\",\n", - " \"datetime_utc\",\n", - " \"gross_generation_mwh\",\n", - " ]\n", - "].copy()\n", - "# identify the 2nd percentile lowest hourly gross generation value in a month\n", - "min_gross = (\n", - " gross_gen_data.groupby(\n", - " [\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False\n", - " )\n", - " .agg({\"gross_generation_mwh\": lambda x: x.quantile(0.02)})\n", - " .reset_index()\n", - " .rename(columns={\"gross_generation_mwh\": \"minimum_gross_generation_mwh\"})\n", - ")\n", - "# identify the 98th percentile highest hourly gross generation value in a month\n", - "max_gross = (\n", - " gross_gen_data.groupby(\n", - " [\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False\n", - " )\n", - " .agg({\"gross_generation_mwh\": lambda x: x.quantile(0.98)})\n", - " .reset_index()\n", - " .rename(columns={\"gross_generation_mwh\": \"maximum_gross_generation_mwh\"})\n", - ")\n", - "subplant_capacity = calculate_subplant_nameplate_capacity(year)\n", - "# aggregate the cems data to the monthly level\n", - "gross_gen_data = (\n", - " gross_gen_data.groupby(\n", - " [\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False\n", - " )\n", - " .agg({\"datetime_utc\": \"count\", \"gross_generation_mwh\": \"sum\"})\n", - " .reset_index()\n", - " .rename(columns={\"datetime_utc\": \"hours_in_month\"})\n", - ")\n", - "net_gen_data = (\n", - " eia923_allocated.dropna(subset=[\"net_generation_mwh\"])\n", - " .groupby([\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False)[\n", - " \"net_generation_mwh\"\n", - " ]\n", - " .sum()\n", - " .reset_index()\n", - ")\n", - "\n", - "# combine monthly gross and net generation data where we have data for both\n", - "combined_gen_data = (\n", - " gross_gen_data.merge(\n", - " min_gross,\n", - " how=\"left\",\n", - " on=[\"plant_id_eia\", \"subplant_id\", \"report_date\"],\n", - " validate=\"1:1\",\n", - " )\n", - " .merge(\n", - " max_gross,\n", - " how=\"left\",\n", - " on=[\"plant_id_eia\", \"subplant_id\", \"report_date\"],\n", - " validate=\"1:1\",\n", - " )\n", - " .merge(\n", - " subplant_capacity,\n", - " how=\"left\",\n", - " on=[\"plant_id_eia\", \"subplant_id\"],\n", - " validate=\"m:1\",\n", - " )\n", - " .merge(\n", - " net_gen_data,\n", - " how=\"outer\",\n", - " on=[\"plant_id_eia\", \"subplant_id\", \"report_date\"],\n", - " indicator=\"data_source\",\n", - " validate=\"1:1\",\n", - " )\n", - ")\n", - "combined_gen_data[\"data_source\"] = combined_gen_data[\"data_source\"].replace(\n", - " {\"left_only\": \"cems_only\", \"right_only\": \"eia_only\"}\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "combined_gen_data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "validation.check_missing_or_zero_generation_matches(combined_gen_data)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# calculate other groupings at the plant and annual levels\n", - "annual_subplant_ratio = (\n", - " combined_gen_data.dropna(subset=[\"gross_generation_mwh\", \"net_generation_mwh\"])\n", - " .groupby([\"plant_id_eia\", \"subplant_id\"], dropna=False)[\n", - " [\"gross_generation_mwh\", \"net_generation_mwh\", \"hours_in_month\"]\n", - " ]\n", - " .sum()\n", - " .reset_index()\n", - ")\n", - "monthly_plant_ratio = (\n", - " combined_gen_data.dropna(subset=[\"gross_generation_mwh\", \"net_generation_mwh\"])\n", - " .groupby([\"plant_id_eia\", \"report_date\"], dropna=False)[\n", - " [\"gross_generation_mwh\", \"net_generation_mwh\"]\n", - " ]\n", - " .sum()\n", - " .reset_index()\n", - ")\n", - "annual_plant_ratio = (\n", - " combined_gen_data.dropna(subset=[\"gross_generation_mwh\", \"net_generation_mwh\"])\n", - " .groupby([\"plant_id_eia\"], dropna=False)[\n", - " [\"gross_generation_mwh\", \"net_generation_mwh\", \"hours_in_month\"]\n", - " ]\n", - " .sum()\n", - " .reset_index()\n", - ")\n", - "\n", - "# calculate the ratios at each aggregation level\n", - "# fill missing values (due to divide by zero) with zero\n", - "# replace infinite values with missing\n", - "combined_gen_data[\"monthly_subplant_ratio\"] = (\n", - " combined_gen_data[\"net_generation_mwh\"]\n", - " / combined_gen_data[\"gross_generation_mwh\"]\n", - ").replace([np.inf, -np.inf], np.nan)\n", - "annual_subplant_ratio[\"annual_subplant_ratio\"] = (\n", - " annual_subplant_ratio[\"net_generation_mwh\"]\n", - " / annual_subplant_ratio[\"gross_generation_mwh\"]\n", - ").replace([np.inf, -np.inf], np.nan)\n", - "monthly_plant_ratio[\"monthly_plant_ratio\"] = (\n", - " monthly_plant_ratio[\"net_generation_mwh\"]\n", - " / monthly_plant_ratio[\"gross_generation_mwh\"]\n", - ").replace([np.inf, -np.inf], np.nan)\n", - "annual_plant_ratio[\"annual_plant_ratio\"] = (\n", - " annual_plant_ratio[\"net_generation_mwh\"]\n", - " / annual_plant_ratio[\"gross_generation_mwh\"]\n", - ").replace([np.inf, -np.inf], np.nan)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "validation.identify_anomalous_annual_plant_gtn_ratios(annual_plant_ratio)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "open_grid_emissions", - "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.9" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "b893a8d8fbb165be288531947168b3b06bdb1508177327a21c265e0400df3100" - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From ad1cb1fbff9e7dc5f72bf5c251cc76ded783b580 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 18 May 2023 11:38:35 -0700 Subject: [PATCH 12/85] update CAISO timestamp correction --- src/eia930.py | 63 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/src/eia930.py b/src/eia930.py index 34f48ea9..59843e05 100644 --- a/src/eia930.py +++ b/src/eia930.py @@ -420,24 +420,51 @@ def manual_930_adjust(raw: pd.DataFrame): raw = raw.drop(columns=sc_dat.columns) raw = pd.concat([raw, sc_dat], axis="columns") - # PJM, CISO, TEPC: shift by one hour - # CISO correction before Jun 16, 2022 - start_of_hour_bas = {"CISO": "2022-06-16 07:00:00+00", "PJM": None, "TEPC": None} - for ba in list(start_of_hour_bas.keys()): - cols = get_columns(ba, raw.columns) - correction_end_date = start_of_hour_bas[ba] - if correction_end_date is not None: - new = raw[cols].copy() - new.loc[raw.index < correction_end_date, cols] = new.loc[ - new.index < correction_end_date, cols - ].shift(1, freq="H") - raw = raw.drop(columns=cols) - raw = pd.concat([raw, new], axis="columns") - else: - cols = get_columns(ba, raw.columns) - new = raw[cols].shift(1, freq="H") - raw = raw.drop(columns=cols) - raw = pd.concat([raw, new], axis="columns") + # PJM data reports start of hour instead of end of hour + # This issue is still active as of 5/18/2023 + # we need to shift all data by +1 hour + ba = "PJM" + cols = get_columns(ba, raw.columns) + cols = get_columns(ba, raw.columns) + new = raw[cols].shift(1, freq="H") + raw = raw.drop(columns=cols) + raw = pd.concat([raw, new], axis="columns") + + # TEPC data reports start of hour instead of end of hour + # This issue may have been fixed but will be addressed in a future PR + # we need to shift all data by +1 hour + ba = "TEPC" + cols = get_columns(ba, raw.columns) + cols = get_columns(ba, raw.columns) + new = raw[cols].shift(1, freq="H") + raw = raw.drop(columns=cols) + raw = pd.concat([raw, new], axis="columns") + + # CISO reported start of hour data through June 13, 2022 + # The June 14 data was corrected, but then the June 15 data went back to start of hour + # The data was permanantly fixed as of June 16 + ba = "CISO" + cols = get_columns(ba, raw.columns) + new = raw[cols].copy() + new.loc[ + (raw.index < "2022-06-14 07:00:00+00") + | ( + (raw.index >= "2022-06-15 07:00:00+00") + & (raw.index < "2022-06-16 07:00:00+00") + ), + cols, + ] = new.loc[ + (raw.index < "2022-06-14 07:00:00+00") + | ( + (raw.index >= "2022-06-15 07:00:00+00") + & (raw.index < "2022-06-16 07:00:00+00") + ), + cols, + ].shift( + 1, freq="H" + ) + raw = raw.drop(columns=cols) + raw = pd.concat([raw, new], axis="columns") # Interchange sign. Do before we change interchange time for PJM, because # identification of sign shift is based on raw data From 214d825888d1b3ee1e66de8a4b52ee55bcbc484a Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 2 Dec 2023 09:53:00 -0800 Subject: [PATCH 13/85] update pudl downloader --- src/data_cleaning.py | 4 +- src/download_data.py | 101 +++++++++++++++++++++++++-------- src/gross_to_net_generation.py | 4 +- src/load_data.py | 4 +- 4 files changed, 83 insertions(+), 30 deletions(-) diff --git a/src/data_cleaning.py b/src/data_cleaning.py index 66fa8f6a..eaec2368 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -325,7 +325,7 @@ def connect_ids(df, id_to_update, connecting_id): def add_operating_and_retirement_dates(df, start_year, end_year): """Adds columns listing a generator's planned operating date or retirement date to a dataframe.""" - pudl_db = f"sqlite:///{downloads_folder()}pudl/pudl_data/sqlite/pudl.sqlite" + pudl_db = "sqlite:///" + downloads_folder("pudl/pudl_data/sqlite/pudl.sqlite") pudl_engine = sa.create_engine(pudl_db) # get values starting with the year prior to teh start year so that we can get proposed operating dates for the start year (which are reported in year -1) pudl_out_status = pudl.output.pudltabl.PudlTabl( @@ -387,7 +387,7 @@ def add_operating_and_retirement_dates(df, start_year, end_year): def add_prime_mover_to_subplant_crosswalk(df, year): """Adds a column identifying each generator's prime_mover to a dataframe.""" - pudl_db = f"sqlite:///{downloads_folder()}pudl/pudl_data/sqlite/pudl.sqlite" + pudl_db = "sqlite:///" + downloads_folder("pudl/pudl_data/sqlite/pudl.sqlite") pudl_engine = sa.create_engine(pudl_db) # get values starting with the year prior to teh start year so that we can get proposed operating dates for the start year (which are reported in year -1) pudl_out_pm = pudl.output.pudltabl.PudlTabl( diff --git a/src/download_data.py b/src/download_data.py index 10763e06..b8845cb0 100644 --- a/src/download_data.py +++ b/src/download_data.py @@ -1,4 +1,5 @@ from typing import Optional +import datetime import gzip import os import requests @@ -41,9 +42,7 @@ def download_helper( # If the file already exists, do not re-download it. final_destination = output_path if output_path is not None else download_path if os.path.exists(final_destination): - logger.info( - f"{final_destination.split('/')[-1]} already downloaded, skipping." - ) + logger.info(f"{final_destination.split('/')[-1]} already downloaded, skipping.") return False # Otherwise, download to the file in chunks. @@ -80,35 +79,89 @@ def download_helper( return True -def download_pudl_data(zenodo_url: str): +def download_pudl_data(source: str = "aws"): """ - Downloads an archived PUDL data release. + Downloads the pudl database. OGE currently supports two sources: zenodo and aws + (i.e. nightly builds). For more information about data sources see: + https://catalystcoop-pudl.readthedocs.io/en/latest/data_access.html#data-access + Zenodo provides stable, versioned data based on the output of the `main` branch of + pudl but is updated less freqently. The most recent version can be found at: https://catalystcoop-pudl.readthedocs.io/en/latest/data_access.html#zenodo-archives + As of 12/2/2023, the most recent zenodo data was PUDL Data Release v2022.11.30. + + The `aws` source downloads data from the Catalyst's AWS Open Data Registry. This + data is updated nightly based on the most recent `dev` branch of pudl so is less + stable. + Inputs: - `zenodo_url`: the url to the .tgz file hosted on zenodo + `source`: where to download pudl from, either "aws" or "zenodo" """ - # get the version number - pudl_version = zenodo_url.split("/")[-1].replace(".tgz", "") + if source == "aws": + # define the urls + pudl_db_url = ( + "https://s3.us-west-2.amazonaws.com/pudl.catalyst.coop/dev/pudl.sqlite.gz" + ) + epacems_parquet_url = "https://s3.us-west-2.amazonaws.com/pudl.catalyst.coop/dev/hourly_emissions_epacems.parquet" + + # download the pudl sqlite database + if not os.path.exists(downloads_folder("pudl/pudl.sqlite")): + output_filepath = downloads_folder("pudl/pudl.sqlite") + download_helper( + pudl_db_url, + download_path=output_filepath + ".gz", + output_path=output_filepath, + requires_gzip=True, + should_clean=True, + ) - # if the pudl data already exists, do not re-download - if os.path.exists(downloads_folder("pudl")): - pudl_version_file = downloads_folder("pudl/pudl_version.txt") - with open(pudl_version_file, "r") as f: - existing_version = f.readlines()[0].replace("\n", "") - if pudl_version == existing_version: - logger.info("PUDL version already downloaded") - return - else: - logger.info("Downloading new version of pudl") - shutil.rmtree(downloads_folder("pudl")) + # add a version file + with open(downloads_folder("pudlo/pudl_sqlite_version.txt"), "w+") as v: + v.write(datetime.date.today()) + + if not os.path.exists( + downloads_folder("pudl/hourly_emissions_epacems.parquet") + ): + # download the epacems parquet + output_filepath = downloads_folder("pudl/hourly_emissions_epacems.parquet") + download_helper( + epacems_parquet_url, + download_path=output_filepath, + ) - download_pudl(zenodo_url, pudl_version) + # add a version file + with open(downloads_folder("pudlo/epacems_parquet_version.txt"), "w+") as v: + v.write(datetime.date.today()) + elif source == "zenodo": + # NOTE: This is the most recent available version as of 12/2/2023 + zenodo_url = "https://zenodo.org/record/7472137/files/pudl-v2022.11.30.tgz" + + # get the version number + pudl_version = zenodo_url.split("/")[-1].replace(".tgz", "") + + # if the pudl data already exists, do not re-download + if os.path.exists(downloads_folder("pudl_zenodo")): + pudl_version_file = downloads_folder("pudl_zenodo/pudl_version.txt") + with open(pudl_version_file, "r") as f: + existing_version = f.readlines()[0].replace("\n", "") + if pudl_version == existing_version: + logger.info("Most recent PUDL Zenodo archive already downloaded.") + return + else: + logger.info("Downloading new version of pudl") + shutil.rmtree(downloads_folder("pudl_zenodo")) + + download_pudl_from_zenodo(zenodo_url, pudl_version) + else: + raise ValueError( + f"{source} is an invalid option for `source`. Must be 'aws' \ + or 'zenodo'." + ) -def download_pudl(zenodo_url, pudl_version): +def download_pudl_from_zenodo(zenodo_url, pudl_version): r = requests.get(zenodo_url, params={"download": "1"}, stream=True) # specify parameters for progress bar total_size_in_bytes = int(r.headers.get("content-length", 0)) @@ -130,11 +183,11 @@ def download_pudl(zenodo_url, pudl_version): with tarfile.open(downloads_folder("pudl.tgz")) as tar: tar.extractall(data_folder()) - # rename the extracted directory to pudl so that we don't have to update this for future versions - os.rename(data_folder(pudl_version), downloads_folder("pudl")) + # rename the extracted directory to pudl_zenodo + os.rename(data_folder(pudl_version), downloads_folder("pudl_zenodo")) # add a version file - with open(downloads_folder("pudl/pudl_version.txt"), "w+") as v: + with open(downloads_folder("pudl_zenodo/pudl_version.txt"), "w+") as v: v.write(pudl_version) # delete the downloaded tgz file diff --git a/src/gross_to_net_generation.py b/src/gross_to_net_generation.py index 1894cf81..7d82a43b 100644 --- a/src/gross_to_net_generation.py +++ b/src/gross_to_net_generation.py @@ -14,7 +14,7 @@ import data_cleaning import validation from column_checks import get_dtypes -from filepaths import outputs_folder +from filepaths import outputs_folder, downloads_folder from logging_util import get_logger logger = get_logger(__name__) @@ -756,7 +756,7 @@ def load_monthly_gross_and_net_generation(start_year, end_year): # load and clean EIA data # create pudl_out - pudl_db = "sqlite:///../data/downloads/pudl/pudl_data/sqlite/pudl.sqlite" + pudl_db = "sqlite:///" + downloads_folder("pudl/pudl_data/sqlite/pudl.sqlite") pudl_engine = sa.create_engine(pudl_db) pudl_out = pudl.output.pudltabl.PudlTabl( pudl_engine, diff --git a/src/load_data.py b/src/load_data.py index a1df3cfd..8d9c5e5e 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -280,7 +280,7 @@ def load_pudl_table(table_name, year=None): table: pandas dataframe containing requested query """ # specify the relative path to the sqllite database, and create an sqalchemy engine - pudl_db = f"sqlite:///{downloads_folder()}pudl/pudl_data/sqlite/pudl.sqlite" + pudl_db = "sqlite:///" + downloads_folder("pudl/pudl_data/sqlite/pudl.sqlite") pudl_engine = sa.create_engine(pudl_db) if year is not None: @@ -361,7 +361,7 @@ def initialize_pudl_out(year=None): If `year` is set to `None`, all years of data are returned. """ - pudl_db = f"sqlite:///{downloads_folder()}pudl/pudl_data/sqlite/pudl.sqlite" + pudl_db = "sqlite:///" + downloads_folder("pudl/pudl_data/sqlite/pudl.sqlite") pudl_engine = sa.create_engine(pudl_db) if year is None: From d11c09c1d62d55be5ef12bf52a4f25fa30e6d146 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 2 Dec 2023 09:58:45 -0800 Subject: [PATCH 14/85] update logging of pudl version --- src/download_data.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/download_data.py b/src/download_data.py index b8845cb0..a18ee0d0 100644 --- a/src/download_data.py +++ b/src/download_data.py @@ -118,8 +118,14 @@ def download_pudl_data(source: str = "aws"): ) # add a version file - with open(downloads_folder("pudlo/pudl_sqlite_version.txt"), "w+") as v: + with open(downloads_folder("pudl/pudl_sqlite_version.txt"), "w+") as v: v.write(datetime.date.today()) + else: + with open(downloads_folder("pudl/pudl_sqlite_version.txt"), "r") as f: + existing_version = f.readlines()[0].replace("\n", "") + logger.info( + f"Using nightly build version of PUDL sqlite database downloaded {existing_version}" + ) if not os.path.exists( downloads_folder("pudl/hourly_emissions_epacems.parquet") @@ -132,8 +138,15 @@ def download_pudl_data(source: str = "aws"): ) # add a version file - with open(downloads_folder("pudlo/epacems_parquet_version.txt"), "w+") as v: + with open(downloads_folder("pudl/epacems_parquet_version.txt"), "w+") as v: v.write(datetime.date.today()) + + else: + with open(downloads_folder("pudl/epacems_parquet_version.txt"), "r") as f: + existing_version = f.readlines()[0].replace("\n", "") + logger.info( + f"Using nightly build version of PUDL epacems parquet file downloaded {existing_version}" + ) elif source == "zenodo": # NOTE: This is the most recent available version as of 12/2/2023 zenodo_url = "https://zenodo.org/record/7472137/files/pudl-v2022.11.30.tgz" From a6d501b26218dafa3240b633f373a4c92033f4bc Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 2 Dec 2023 11:00:41 -0800 Subject: [PATCH 15/85] update epacems loading --- src/data_cleaning.py | 12 +-- src/data_pipeline.py | 4 +- src/download_data.py | 18 +++-- src/gross_to_net_generation.py | 2 +- src/load_data.py | 129 ++++++++++++++++++--------------- 5 files changed, 85 insertions(+), 80 deletions(-) diff --git a/src/data_cleaning.py b/src/data_cleaning.py index eaec2368..47eb6645 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -325,7 +325,7 @@ def connect_ids(df, id_to_update, connecting_id): def add_operating_and_retirement_dates(df, start_year, end_year): """Adds columns listing a generator's planned operating date or retirement date to a dataframe.""" - pudl_db = "sqlite:///" + downloads_folder("pudl/pudl_data/sqlite/pudl.sqlite") + pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") pudl_engine = sa.create_engine(pudl_db) # get values starting with the year prior to teh start year so that we can get proposed operating dates for the start year (which are reported in year -1) pudl_out_status = pudl.output.pudltabl.PudlTabl( @@ -387,7 +387,7 @@ def add_operating_and_retirement_dates(df, start_year, end_year): def add_prime_mover_to_subplant_crosswalk(df, year): """Adds a column identifying each generator's prime_mover to a dataframe.""" - pudl_db = "sqlite:///" + downloads_folder("pudl/pudl_data/sqlite/pudl.sqlite") + pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") pudl_engine = sa.create_engine(pudl_db) # get values starting with the year prior to teh start year so that we can get proposed operating dates for the start year (which are reported in year -1) pudl_out_pm = pudl.output.pudltabl.PudlTabl( @@ -708,7 +708,6 @@ def calculate_aggregated_primary_fuel( # we will calculate primary fuel based on the fuel with the most consumption, # generation, and capacity for source in ["fuel_consumed_for_electricity_mmbtu", "net_generation_mwh"]: - # only keep values greater than zero so that these can be filled by other # methods if non-zero primary_fuel_calc = agg_totals_by_fuel[agg_totals_by_fuel[source] > 0] @@ -1088,7 +1087,6 @@ def manually_remove_steam_units(df): def remove_incomplete_unit_months(cems): - # get a count of how many hours are reported in each month for each unit unit_hours_in_month = ( cems[["plant_id_eia", "report_date", "emissions_unit_id_epa", "datetime_utc"]] @@ -1630,7 +1628,8 @@ def identify_partial_cems_plants(all_data): Args: all_data: dataframe identifying the hourly data source for each subplant-month Returns: - all_data with updated hourly_data_source column indicating partial cems plants""" + all_data with updated hourly_data_source column indicating partial cems plants + """ # create a column that indicates EIA-only subplant data all_data = all_data.assign( @@ -1748,7 +1747,6 @@ def filter_unique_cems_data(cems, partial_cems): def aggregate_plant_data_to_ba_fuel(combined_plant_data, plant_attributes_table): - # create a table that has data for the sythetic plant attributes shaped_plant_attributes = ( plant_attributes_table[["shaped_plant_id", "ba_code", "fuel_category"]] @@ -1892,7 +1890,6 @@ def combine_plant_data( def create_plant_attributes_table(cems, eia923_allocated, year, primary_fuel_table): - # create a table with the unique plantids from both dataframes eia_plants = eia923_allocated[ ["plant_id_eia", "plant_primary_fuel"] @@ -2184,7 +2181,6 @@ def add_plant_local_timezone(df, year): def aggregate_cems_to_subplant(cems): - GROUPBY_COLUMNS = ["plant_id_eia", "subplant_id", "datetime_utc", "report_date"] cems_columns_to_aggregate = [ diff --git a/src/data_pipeline.py b/src/data_pipeline.py index ec075144..890a4439 100644 --- a/src/data_pipeline.py +++ b/src/data_pipeline.py @@ -116,9 +116,7 @@ def main(): #################################################################################### logger.info("1. Downloading data") # PUDL - download_data.download_pudl_data( - zenodo_url="https://zenodo.org/record/7472137/files/pudl-v2022.11.30.tgz" - ) + download_data.download_pudl_data(source="aws") # eGRID # the 2019 and 2020 data appear to be hosted on different urls egrid_files_to_download = [ diff --git a/src/download_data.py b/src/download_data.py index a18ee0d0..717bc1e2 100644 --- a/src/download_data.py +++ b/src/download_data.py @@ -99,6 +99,8 @@ def download_pudl_data(source: str = "aws"): Inputs: `source`: where to download pudl from, either "aws" or "zenodo" """ + os.makedirs(downloads_folder("pudl"), exist_ok=True) + if source == "aws": # define the urls pudl_db_url = ( @@ -119,13 +121,13 @@ def download_pudl_data(source: str = "aws"): # add a version file with open(downloads_folder("pudl/pudl_sqlite_version.txt"), "w+") as v: - v.write(datetime.date.today()) + v.write(f"{datetime.date.today()}") else: with open(downloads_folder("pudl/pudl_sqlite_version.txt"), "r") as f: existing_version = f.readlines()[0].replace("\n", "") - logger.info( - f"Using nightly build version of PUDL sqlite database downloaded {existing_version}" - ) + logger.info( + f"Using nightly build version of PUDL sqlite database downloaded {existing_version}" + ) if not os.path.exists( downloads_folder("pudl/hourly_emissions_epacems.parquet") @@ -139,14 +141,14 @@ def download_pudl_data(source: str = "aws"): # add a version file with open(downloads_folder("pudl/epacems_parquet_version.txt"), "w+") as v: - v.write(datetime.date.today()) + v.write(f"{datetime.date.today()}") else: with open(downloads_folder("pudl/epacems_parquet_version.txt"), "r") as f: existing_version = f.readlines()[0].replace("\n", "") - logger.info( - f"Using nightly build version of PUDL epacems parquet file downloaded {existing_version}" - ) + logger.info( + f"Using nightly build version of PUDL epacems parquet file downloaded {existing_version}" + ) elif source == "zenodo": # NOTE: This is the most recent available version as of 12/2/2023 zenodo_url = "https://zenodo.org/record/7472137/files/pudl-v2022.11.30.tgz" diff --git a/src/gross_to_net_generation.py b/src/gross_to_net_generation.py index 7d82a43b..fb456b34 100644 --- a/src/gross_to_net_generation.py +++ b/src/gross_to_net_generation.py @@ -756,7 +756,7 @@ def load_monthly_gross_and_net_generation(start_year, end_year): # load and clean EIA data # create pudl_out - pudl_db = "sqlite:///" + downloads_folder("pudl/pudl_data/sqlite/pudl.sqlite") + pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") pudl_engine = sa.create_engine(pudl_db) pudl_out = pudl.output.pudltabl.PudlTabl( pudl_engine, diff --git a/src/load_data.py b/src/load_data.py index 8d9c5e5e..0e362b39 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -17,8 +17,9 @@ def correct_epa_eia_plant_id_mapping(df): """ - The EPA's power sector data crosswalk incorrectly maps plant_id_epa 55248 to plant_id_eia 55248, - when it should be mapped to id 2847. This function is temporary until this is fixed. + The EPA's power sector data crosswalk incorrectly maps plant_id_epa 55248 to + plant_id_eia 55248, when it should be mapped to id 2847. This function is temporary + until this is fixed. """ df.loc[df["plant_id_eia"] == 55248, "plant_id_eia"] = 2847 @@ -34,8 +35,6 @@ def load_cems_data(year): Returns: cems: pandas dataframe with hourly CEMS data """ - # specify the path to the CEMS data - cems_path = downloads_folder("pudl/pudl_data/parquet/epacems/") # specify the columns to use from the CEMS database cems_columns = [ @@ -56,11 +55,22 @@ def load_cems_data(year): ] # load the CEMS data + cems = pd.read_parquet( + downloads_folder("pudl/hourly_emissions_epacems.parquet"), + filters=[["year", "==", year]], + columns=cems_columns, + ) + + ### Code to load data from zenodo version of pudl archive + # NOTE(greg): keeping for now until pudl archiving finalized + """ + cems_path = downloads_folder("pudl/pudl_data/parquet/epacems/") cems = pd.concat( pd.read_parquet((cems_path + filename), columns=cems_columns) for filename in os.listdir(cems_path) if str(year) in filename ) + """ # **** manual adjustments **** cems = correct_epa_eia_plant_id_mapping(cems) @@ -72,7 +82,7 @@ def load_cems_data(year): "steam_load_1000_lbs": "steam_load_1000_lb", "nox_mass_lbs": "nox_mass_lb", "so2_mass_lbs": "so2_mass_lb", - "gross_load_mw": "gross_generation_mwh", # we are going to convert this in a later step + "gross_load_mw": "gross_generation_mwh", # we will convert this to mwh } ) @@ -120,6 +130,20 @@ def load_cems_data(year): def load_cems_ids(start_year, end_year): """Loads CEMS ids for multiple years.""" + + # load cems data + cems = pd.read_parquet( + downloads_folder("pudl/hourly_emissions_epacems.parquet"), + filters=[["year", ">=", start_year], ["year", "<=", end_year]], + columns=["plant_id_eia", "emissions_unit_id_epa"], + ).drop_duplicates() + + # **** manual adjustments **** + cems = correct_epa_eia_plant_id_mapping(cems) + + # code pattern for loading data from pudl zenodo archive + # NOTE(greg): keeping for now until pudl archiving finalized + """ cems_all = [] for year in range(start_year, end_year + 1): @@ -150,71 +174,58 @@ def load_cems_ids(start_year, end_year): cems = pd.concat(cems_all, axis=0).reset_index() cems = cems[["plant_id_eia", "emissions_unit_id_epa"]].drop_duplicates() + """ return cems def load_cems_gross_generation(start_year, end_year): """Loads hourly CEMS gross generation data for multiple years.""" - cems_all = [] - for year in range(start_year, end_year + 1): - logger.info(f"loading {year} CEMS data") - # specify the path to the CEMS data - cems_path = downloads_folder( - "pudl/pudl_data/parquet/epacems/hourly_emissions_epacems/" - ) + # specify the columns to use from the CEMS database + cems_columns = [ + "plant_id_eia", + "emissions_unit_id_epa", + "operating_datetime_utc", + "operating_time_hours", + "gross_load_mw", + ] - # specify the columns to use from the CEMS database - cems_columns = [ - "plant_id_eia", - "emissions_unit_id_epa", - "operating_datetime_utc", - "operating_time_hours", - "gross_load_mw", - ] + # load cems data + cems = pd.read_parquet( + downloads_folder("pudl/hourly_emissions_epacems.parquet"), + filters=[["year", ">=", start_year], ["year", "<=", end_year]], + columns=cems_columns, + ) - # load the CEMS data - cems = pd.concat( - pd.read_parquet((cems_path + filename), columns=cems_columns) - for filename in os.listdir(cems_path) - if str(year) in filename - ) + # only keep values when the plant was operating + # this will help speed up calculations and allow us to add this data back later + cems = cems[(cems["gross_load_mw"] > 0) | (cems["operating_time_hours"] > 0)] - # only keep values when the plant was operating - # this will help speed up calculations and allow us to add this data back later - cems = cems[(cems["gross_load_mw"] > 0) | (cems["operating_time_hours"] > 0)] - - # rename cems plant_id_eia to plant_id_epa (PUDL simply renames the ORISPL_CODE - # column from the raw CEMS data as 'plant_id_eia' without actually crosswalking to the EIA id) - # rename the heat content column to use the convention used in the EIA data - cems = cems.rename( - columns={ - "operating_datetime_utc": "datetime_utc", - "gross_load_mw": "gross_generation_mwh", - } - ) + # rename the heat content column to use the convention used in the EIA data + cems = cems.rename( + columns={ + "operating_datetime_utc": "datetime_utc", + "gross_load_mw": "gross_generation_mwh", + } + ) - # add a report date - cems = add_report_date(cems) + # add a report date + cems = add_report_date(cems) - cems = cems[ - [ - "plant_id_eia", - "emissions_unit_id_epa", - "report_date", - "gross_generation_mwh", - ] + cems = cems[ + [ + "plant_id_eia", + "emissions_unit_id_epa", + "report_date", + "gross_generation_mwh", ] + ] - # group data by plant, unit, month - cems = cems.groupby( - ["plant_id_eia", "emissions_unit_id_epa", "report_date"], dropna=False - ).sum() - - cems_all.append(cems) - - cems = pd.concat(cems_all, axis=0).reset_index() + # group data by plant, unit, month + cems = cems.groupby( + ["plant_id_eia", "emissions_unit_id_epa", "report_date"], dropna=False + ).sum() return cems @@ -280,7 +291,7 @@ def load_pudl_table(table_name, year=None): table: pandas dataframe containing requested query """ # specify the relative path to the sqllite database, and create an sqalchemy engine - pudl_db = "sqlite:///" + downloads_folder("pudl/pudl_data/sqlite/pudl.sqlite") + pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") pudl_engine = sa.create_engine(pudl_db) if year is not None: @@ -361,13 +372,12 @@ def initialize_pudl_out(year=None): If `year` is set to `None`, all years of data are returned. """ - pudl_db = "sqlite:///" + downloads_folder("pudl/pudl_data/sqlite/pudl.sqlite") + pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") pudl_engine = sa.create_engine(pudl_db) if year is None: pudl_out = pudl.output.pudltabl.PudlTabl(pudl_engine) else: - pudl_out = pudl.output.pudltabl.PudlTabl( pudl_engine, freq="MS", @@ -600,7 +610,6 @@ def load_ipcc_gwp(): def load_raw_eia930_data(year, description): - eia_930 = pd.concat( [ pd.read_csv( From 5ad12a18f64440e20d0298e2b25776d6e4932229 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 2 Dec 2023 11:02:43 -0800 Subject: [PATCH 16/85] remove code to load zenodo version of pudl data --- src/load_data.py | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/src/load_data.py b/src/load_data.py index 0e362b39..a5d9fc6a 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -61,17 +61,6 @@ def load_cems_data(year): columns=cems_columns, ) - ### Code to load data from zenodo version of pudl archive - # NOTE(greg): keeping for now until pudl archiving finalized - """ - cems_path = downloads_folder("pudl/pudl_data/parquet/epacems/") - cems = pd.concat( - pd.read_parquet((cems_path + filename), columns=cems_columns) - for filename in os.listdir(cems_path) - if str(year) in filename - ) - """ - # **** manual adjustments **** cems = correct_epa_eia_plant_id_mapping(cems) @@ -141,41 +130,6 @@ def load_cems_ids(start_year, end_year): # **** manual adjustments **** cems = correct_epa_eia_plant_id_mapping(cems) - # code pattern for loading data from pudl zenodo archive - # NOTE(greg): keeping for now until pudl archiving finalized - """ - cems_all = [] - - for year in range(start_year, end_year + 1): - # specify the path to the CEMS data - cems_path = downloads_folder("pudl/pudl_data/parquet/epacems/") - - # load the CEMS data - cems = pd.concat( - pd.read_parquet( - (cems_path + filename), - columns=[ - "plant_id_eia", - "emissions_unit_id_epa", - ], - ) - for filename in os.listdir(cems_path) - if str(year) in filename - ) - - # **** manual adjustments **** - cems = correct_epa_eia_plant_id_mapping(cems) - - # drop duplicate ids to reduce size - cems = cems[["plant_id_eia", "emissions_unit_id_epa"]].drop_duplicates() - - cems_all.append(cems) - - cems = pd.concat(cems_all, axis=0).reset_index() - - cems = cems[["plant_id_eia", "emissions_unit_id_epa"]].drop_duplicates() - """ - return cems From af39a2886f342263b783a0e6f805c5a82da754c9 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 2 Dec 2023 12:53:51 -0800 Subject: [PATCH 17/85] remove references to pudl_out --- src/data_cleaning.py | 156 +++++++++++++++++---------------- src/emissions.py | 153 +++++++++++++++++--------------- src/gross_to_net_generation.py | 12 +-- src/load_data.py | 102 +++++++++++---------- src/validation.py | 94 +++++++++++--------- 5 files changed, 277 insertions(+), 240 deletions(-) diff --git a/src/data_cleaning.py b/src/data_cleaning.py index 47eb6645..24cd0f34 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -110,10 +110,11 @@ def generate_subplant_ids(start_year, end_year, cems_ids): # update the subplant_crosswalk to ensure completeness # prepare the subplant crosswalk by adding a complete list of generators and adding the unit_id_pudl column - pudl_out = load_data.initialize_pudl_out(year=end_year) - complete_generator_ids = pudl_out.gens_eia860()[ - ["plant_id_eia", "generator_id", "unit_id_pudl"] - ].drop_duplicates() + complete_generator_ids = load_data.load_pudl_table( + "generators_eia860", + end_year, + columns=["plant_id_eia", "generator_id", "unit_id_pudl"], + ).drop_duplicates() subplant_crosswalk_complete = crosswalk_with_subplant_ids.merge( complete_generator_ids, how="outer", @@ -325,18 +326,11 @@ def connect_ids(df, id_to_update, connecting_id): def add_operating_and_retirement_dates(df, start_year, end_year): """Adds columns listing a generator's planned operating date or retirement date to a dataframe.""" - pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") - pudl_engine = sa.create_engine(pudl_db) - # get values starting with the year prior to teh start year so that we can get proposed operating dates for the start year (which are reported in year -1) - pudl_out_status = pudl.output.pudltabl.PudlTabl( - pudl_engine, - freq="MS", - start_date=f"{start_year-1}-01-01", - end_date=f"{end_year}-12-31", - ) - generator_status = pudl_out_status.gens_eia860().loc[ - :, - [ + + generator_status = load_data.load_pudl_table( + "generators_eia860", + year=start_year, + columns=[ "plant_id_eia", "generator_id", "report_date", @@ -344,7 +338,9 @@ def add_operating_and_retirement_dates(df, start_year, end_year): "current_planned_operating_date", "retirement_date", ], - ] + end_year=end_year, + ) + # only keep values that have a planned operating date or retirement date generator_status = generator_status[ (~generator_status["current_planned_operating_date"].isna()) @@ -387,25 +383,17 @@ def add_operating_and_retirement_dates(df, start_year, end_year): def add_prime_mover_to_subplant_crosswalk(df, year): """Adds a column identifying each generator's prime_mover to a dataframe.""" - pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") - pudl_engine = sa.create_engine(pudl_db) - # get values starting with the year prior to teh start year so that we can get proposed operating dates for the start year (which are reported in year -1) - pudl_out_pm = pudl.output.pudltabl.PudlTabl( - pudl_engine, - freq="AS", - start_date=f"{year}-01-01", - end_date=f"{year}-12-31", - ) - generator_pm = pudl_out_pm.gens_eia860().loc[ - :, - [ + generator_pm = load_data.load_pudl_table( + "generators_eia860", + year, + columns=[ "plant_id_eia", "generator_id", "prime_mover_code", ], - ] + ) - # merge the dates into the crosswalk + # merge the prime movers into the crosswalk df = df.merge( generator_pm, how="left", on=["plant_id_eia", "generator_id"], validate="m:1" ) @@ -425,15 +413,13 @@ def clean_eia923( """ # Distribute net generation and heat input data reported by the three different EIA-923 tables - pudl_out = load_data.initialize_pudl_out(year=year) - # allocate net generation and heat input to each generator-fuel grouping gen_fuel_allocated = allocate_gen_fuel.allocate_gen_fuel_by_generator_energy_source( pudl_out, drop_interim_cols=True ) # test to make sure allocated totals match input totals - validation.check_allocated_gf_matches_input_gf(pudl_out, gen_fuel_allocated) + validation.check_allocated_gf_matches_input_gf(year, gen_fuel_allocated) # manually update energy source code when OTH gen_fuel_allocated = update_energy_source_codes(gen_fuel_allocated) @@ -462,7 +448,7 @@ def clean_eia923( # create a table that identifies the primary fuel of each generator and plant primary_fuel_table = create_primary_fuel_table( - gen_fuel_allocated, pudl_out, add_subplant_id, year + gen_fuel_allocated, add_subplant_id, year ) if small: @@ -480,11 +466,11 @@ def clean_eia923( # Calculate NOx and SO2 emissions if calculate_nox_emissions: gen_fuel_allocated = emissions.calculate_nox_from_fuel_consumption( - gen_fuel_allocated, pudl_out, year + gen_fuel_allocated, year ) if calculate_so2_emissions: gen_fuel_allocated = emissions.calculate_so2_from_fuel_consumption( - gen_fuel_allocated, pudl_out, year + gen_fuel_allocated, year ) # adjust total emissions for biomass @@ -539,9 +525,11 @@ def clean_eia923( validation.test_for_missing_subplant_id(gen_fuel_allocated) # add the cleaned prime mover code to the data - gen_pm = pudl_out.gens_eia860()[ - ["plant_id_eia", "generator_id", "prime_mover_code"] - ] + gen_pm = load_data.load_pudl_table( + "generators_eia860", + year, + columns=["plant_id_eia", "generator_id", "prime_mover_code"], + ) gen_fuel_allocated = gen_fuel_allocated.merge( gen_pm, how="left", on=["plant_id_eia", "generator_id"], validate="m:1" ) @@ -586,7 +574,7 @@ def update_energy_source_codes(df): return df -def create_primary_fuel_table(gen_fuel_allocated, pudl_out, add_subplant_id, year): +def create_primary_fuel_table(gen_fuel_allocated, add_subplant_id, year): """ Identifies the primary fuel for each generator and plant Gen primary fuel is identified based on the "energy source code 1" identified in EIA-860 @@ -623,7 +611,7 @@ def create_primary_fuel_table(gen_fuel_allocated, pudl_out, add_subplant_id, yea ] plant_primary_fuel = calculate_aggregated_primary_fuel( - gen_fuel_allocated, gen_primary_fuel, "plant", pudl_out, year + gen_fuel_allocated, gen_primary_fuel, "plant", year ) validation.flag_possible_primary_fuel_mismatches(plant_primary_fuel) @@ -642,7 +630,6 @@ def create_primary_fuel_table(gen_fuel_allocated, pudl_out, add_subplant_id, yea gen_fuel_allocated, gen_primary_fuel, "subplant", - pudl_out, year, ) primary_fuel_table = primary_fuel_table.merge( @@ -656,7 +643,7 @@ def create_primary_fuel_table(gen_fuel_allocated, pudl_out, add_subplant_id, yea def calculate_aggregated_primary_fuel( - gen_fuel_allocated, gen_primary_fuel, agg_level, pudl_out, year + gen_fuel_allocated, gen_primary_fuel, agg_level, year ): """ Takes generator-level fuel data and calculates primary fuel for the subplant or plant level. @@ -665,7 +652,6 @@ def calculate_aggregated_primary_fuel( gen_fuel_allocated: dataframe of allocated fuel, generation, and emissions data by generator gen_primary_fuel: dataframe of primary fuel by generator agg_level: either "plant" or "subplant" - pudl_out: for loading pudl output tables """ if agg_level == "plant": agg_keys = ["plant_id_eia"] @@ -677,7 +663,7 @@ def calculate_aggregated_primary_fuel( ) primary_fuel_from_capacity = calculate_capacity_based_primary_fuel( - pudl_out, agg_level, agg_keys, year + agg_level, agg_keys, year ) # NOTE: In some rare cases, a plant will have no fuel specified by @@ -781,11 +767,13 @@ def calculate_aggregated_primary_fuel( return agg_primary_fuel -def calculate_capacity_based_primary_fuel(pudl_out, agg_level, agg_keys, year): +def calculate_capacity_based_primary_fuel(agg_level, agg_keys, year): # create a table of primary fuel by nameplate capacity - gen_capacity = pudl_out.gens_eia860().loc[ - :, ["plant_id_eia", "generator_id", "capacity_mw", "energy_source_code_1"] - ] + gen_capacity = load_data.load_pudl_table( + "generators_eia860", + year, + columns=["plant_id_eia", "generator_id", "capacity_mw", "energy_source_code_1"], + ) if "subplant_id" in agg_keys: subplant_crosswalk = pd.read_csv( @@ -911,9 +899,9 @@ def remove_plants( if non_grid_connected: df = remove_non_grid_connected_plants(df) if len(remove_states) > 0: - plant_states = load_data.load_pudl_table("plants_entity_eia").loc[ - :, ["plant_id_eia", "state"] - ] + plant_states = load_data.load_pudl_table( + "plants_entity_eia", columns=["plant_id_eia", "state"] + ) plants_in_states_to_remove = list( plant_states[ plant_states["state"].isin(remove_states) @@ -1167,9 +1155,11 @@ def assign_fuel_type_to_cems(cems, year, primary_fuel_table): # if there are still missing fuels, the plant might be proposed and not yet in EIA-923 # in this case, load data from EIA-860 to see if the plant exists in the proposed category - gen_fuel = load_data.load_pudl_table("generators_eia860", year)[ - ["plant_id_eia", "generator_id", "energy_source_code_1"] - ].drop_duplicates() + gen_fuel = load_data.load_pudl_table( + "generators_eia860", + year, + columns=["plant_id_eia", "generator_id", "energy_source_code_1"], + ).drop_duplicates() generator_unit_map = pd.read_csv( outputs_folder(f"{year}/subplant_crosswalk_{year}.csv"), dtype=get_dtypes(), @@ -1248,9 +1238,16 @@ def fill_missing_fuel_for_single_fuel_plant_months(df, year): """ # identify plant-months for which there is a single fossil fuel type reported - gf = load_data.load_pudl_table("generation_fuel_eia923", year=year)[ - ["plant_id_eia", "report_date", "energy_source_code", "fuel_consumed_mmbtu"] - ] + gf = load_data.load_pudl_table( + "generation_fuel_eia923", + year, + columns=[ + "plant_id_eia", + "report_date", + "energy_source_code", + "fuel_consumed_mmbtu", + ], + ) # remove any rows for clean fuels gf = gf[~gf["energy_source_code"].isin(CLEAN_FUELS)] @@ -2012,19 +2009,32 @@ def create_plant_ba_table(year): """ Creates a table assigning a ba_code and physical ba code to each plant id. """ - pudl_out = load_data.initialize_pudl_out(year=year) - plant_ba = pudl_out.plants_eia860().loc[ - :, - [ + plant_ba = load_data.load_pudl_table( + "plants_eia860", + year, + columns=[ "plant_id_eia", "balancing_authority_code_eia", "balancing_authority_name_eia", - "utility_name_eia", + "utility_id_eia", "transmission_distribution_owner_name", - "state", ], - ] + ) + # merge utility name + utilities_eia = load_data.load_pudl_table( + "utilities_eia", columns=["utility_id_eia", "utility_name_eia"] + ) + plant_ba = plant_ba.merge( + utilities_eia, how="left", on="utility_id_eia", validate="m:1" + ) + # merge plant state + plant_states = load_data.load_pudl_table( + "plants_entity_eia", columns=["plant_id_eia", "state"] + ) + plant_ba = plant_ba.merge( + plant_states, how="left", on="plant_id_eia", validate="m:1" + ) # convert the dtype of the balancing authority code column from string to object # this will allow for missing values to be filled @@ -2118,11 +2128,9 @@ def identify_distribution_connected_plants(df, year, voltage_threshold_kv=60): df: with additional binary column `distribution_flag` """ # load the EIA-860 data - pudl_out = load_data.initialize_pudl_out(year=year) - - plant_voltage = pudl_out.plants_eia860().loc[ - :, ["plant_id_eia", "grid_voltage_1_kv"] - ] + plant_voltage = load_data.load_pudl_table( + "plants_eia860", year, columns=["plant_id_eia", "grid_voltage_1_kv"] + ) plant_voltage = plant_voltage.assign( distribution_flag=lambda x: np.where( @@ -2172,9 +2180,9 @@ def assign_fuel_category_to_ESC( def add_plant_local_timezone(df, year): - plant_tz = load_data.load_pudl_table("plants_entity_eia")[ - ["plant_id_eia", "timezone"] - ] + plant_tz = load_data.load_pudl_table( + "plants_entity_eia", columns=["plant_id_eia", "timezone"] + ) df = df.merge(plant_tz, how="left", on=["plant_id_eia"], validate="m:1") return df diff --git a/src/emissions.py b/src/emissions.py index 3460ad27..753433a1 100644 --- a/src/emissions.py +++ b/src/emissions.py @@ -146,9 +146,7 @@ def calculate_geothermal_emission_factors(year): def identify_geothermal_generator_geotype(year): """Identifies whether each geothermal generator is binary, flash, or dry steam""" - pudl_out = load_data.initialize_pudl_out(year) - - geothermal_geotype = pudl_out.gens_eia860() + geothermal_geotype = load_data.load_pudl_table("generators_eia860", year) geothermal_geotype = geothermal_geotype.loc[ geothermal_geotype["energy_source_code_1"] == "GEO", [ @@ -440,7 +438,7 @@ def calculate_co2e_mass(df, year, gwp_horizon=100, ar5_climate_carbon_feedback=T def calculate_nox_from_fuel_consumption( - gen_fuel_allocated: pd.DataFrame, pudl_out, year + gen_fuel_allocated: pd.DataFrame, year ) -> pd.DataFrame: """ Calculate NOx emissions from fuel consumption data. @@ -453,10 +451,10 @@ def calculate_nox_from_fuel_consumption( # calculate uncontrolled nox emission factors based on boiler design parameters uncontrolled_nox_factors = calculate_generator_nox_ef_per_unit_from_boiler_type( - gen_fuel_allocated, year, pudl_out + gen_fuel_allocated, year ) uncontrolled_nox_factors = convert_ef_to_lb_per_mmbtu( - uncontrolled_nox_factors, pudl_out, "nox" + uncontrolled_nox_factors, year, "nox" ) # merge nox efs into the gen_fuel_allocated @@ -481,8 +479,9 @@ def calculate_nox_from_fuel_consumption( if len(missing_ef) > 0: logger.warning("NOx emission factors are missing for the following records") logger.warning("Missing factors for FC prime movers are currently expected") - logger.warning("\n" + - missing_ef[ + logger.warning( + "\n" + + missing_ef[ [ "report_date", "plant_id_eia", @@ -490,7 +489,9 @@ def calculate_nox_from_fuel_consumption( "prime_mover_code", "generator_id", ] - ].drop_duplicates().to_string() + ] + .drop_duplicates() + .to_string() ) gen_fuel_allocated["nox_mass_lb"] = ( gen_fuel_allocated["fuel_consumed_mmbtu"] @@ -541,9 +542,7 @@ def calculate_nox_from_fuel_consumption( return gen_fuel_allocated -def calculate_generator_nox_ef_per_unit_from_boiler_type( - gen_fuel_allocated, year, pudl_out -): +def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, year): """Calculates a generator-specific Nox emission factor per unit fuel based on boiler firing type If a generator has multiple boilers, average the emission factor of all boilers @@ -582,10 +581,14 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type( boiler_firing_type = load_boiler_firing_type(year) # identify the boiler firing type for each generator - boiler_generator_assn = pudl_out.bga_eia860() + boiler_generator_assn = load_data.load_pudl_table( + "boiler_generator_assn_eia860", + year, + columns=["plant_id_eia", "boiler_id", "generator_id"], + ) # associate each boiler record with generator_id s boiler_firing_type = boiler_firing_type.merge( - boiler_generator_assn[["plant_id_eia", "boiler_id", "generator_id"]], + boiler_generator_assn, how="left", on=["plant_id_eia", "boiler_id"], ) @@ -687,7 +690,8 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type( ) ) if len(missing_nox_efs) > 0: - logger.warning(""" + logger.warning( + """ After filling with PM-fuel factors, NOx emission factors are still missing for the following boiler types. An emission factor of zero will be used for these boilers. Missing factors for FC prime movers are currently expected.""" @@ -717,7 +721,6 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type( def load_boiler_firing_type(year): - boiler_design_parameters_eia860 = load_data.load_boiler_design_parameters_eia860( year ) @@ -798,14 +801,13 @@ def fill_missing_factors_based_on_pm_fuel(emission_factors, gen_factors): return gen_factors -def convert_ef_to_lb_per_mmbtu(gen_emission_factors, pudl_out, pollutant): - +def convert_ef_to_lb_per_mmbtu(gen_emission_factors, year, pollutant): # get the reported fuel heat content values from EIA-923 ( plant_specific_fuel_heat_content, national_avg_fuel_heat_content, annual_avg_fuel_heat_content, - ) = return_monthly_plant_fuel_heat_content(pudl_out) + ) = return_monthly_plant_fuel_heat_content(year) # merge in plant pm specific fuel heat content values gen_emission_factors = gen_emission_factors.merge( @@ -888,26 +890,23 @@ def convert_ef_to_lb_per_mmbtu(gen_emission_factors, pudl_out, pollutant): return gen_emission_factors -def return_monthly_plant_fuel_heat_content(pudl_out): +def return_monthly_plant_fuel_heat_content(year): # load information about the monthly heat input of fuels - plant_specific_fuel_heat_content = ( - pudl_out.gf_eia923() - .loc[ - :, - [ - "plant_id_eia", - "energy_source_code", - "prime_mover_code", - "report_date", - "fuel_mmbtu_per_unit", - ], - ] - .pipe( - distribute_annually_reported_data_to_months_if_annual, - key_columns=["plant_id_eia", "energy_source_code", "prime_mover_code"], - data_column_name="fuel_mmbtu_per_unit", - freq="MS", - ) + plant_specific_fuel_heat_content = load_data.load_pudl_table( + "generation_fuel_eia923", + year, + columns=[ + "plant_id_eia", + "energy_source_code", + "prime_mover_code", + "report_date", + "fuel_mmbtu_per_unit", + ], + ).pipe( + distribute_annually_reported_data_to_months_if_annual, + key_columns=["plant_id_eia", "energy_source_code", "prime_mover_code"], + data_column_name="fuel_mmbtu_per_unit", + freq="MS", ) plant_specific_fuel_heat_content = plant_specific_fuel_heat_content[ ~plant_specific_fuel_heat_content["energy_source_code"].isin(CLEAN_FUELS) @@ -1022,10 +1021,14 @@ def calculate_weighted_nox_rates(year, nox_rates, aggregation_level): ) if aggregation_level == "generator_id": - boiler_generator_assn = load_data.initialize_pudl_out(year).bga_eia860() + boiler_generator_assn = load_data.load_pudl_table( + "boiler_generator_assn_eia860", + year, + columns=["plant_id_eia", "boiler_id", "generator_id"], + ) # associate a generator_id with each record nox_rates = nox_rates.merge( - boiler_generator_assn[["plant_id_eia", "boiler_id", "generator_id"]], + boiler_generator_assn, how="left", on=["plant_id_eia", "boiler_id"], validate="m:m", @@ -1167,7 +1170,7 @@ def calculate_non_ozone_season_nox_rate(weighted_nox_rates): return weighted_nox_rates -def calculate_so2_from_fuel_consumption(gen_fuel_allocated, pudl_out, year): +def calculate_so2_from_fuel_consumption(gen_fuel_allocated, year): """ Calculate SO2 emissions from fuel consumption data. @@ -1179,17 +1182,17 @@ def calculate_so2_from_fuel_consumption(gen_fuel_allocated, pudl_out, year): # load uncontrolled emission factors uncontrolled_so2_factors = calculate_generator_so2_ef_per_unit_from_boiler_type( - gen_fuel_allocated, year, pudl_out + gen_fuel_allocated, year ) # adjust for sulfur content uncontrolled_so2_factors = adjust_so2_efs_for_fuel_sulfur_content( - uncontrolled_so2_factors, pudl_out + uncontrolled_so2_factors, year ) # convert to mmbtu uncontrolled_so2_factors = convert_ef_to_lb_per_mmbtu( - uncontrolled_so2_factors, pudl_out, "so2" + uncontrolled_so2_factors, year, "so2" ) # merge so2 efs into the gen_fuel_allocated @@ -1214,8 +1217,9 @@ def calculate_so2_from_fuel_consumption(gen_fuel_allocated, pudl_out, year): if len(missing_ef) > 0: logger.warning("SO2 emission factors are missing for the above records") logger.warning("Missing factors for FC prime movers are currently expected") - logger.warning("\n" + - missing_ef[ + logger.warning( + "\n" + + missing_ef[ [ "report_date", "plant_id_eia", @@ -1223,7 +1227,9 @@ def calculate_so2_from_fuel_consumption(gen_fuel_allocated, pudl_out, year): "prime_mover_code", "generator_id", ] - ].drop_duplicates().to_string() + ] + .drop_duplicates() + .to_string() ) gen_fuel_allocated["so2_mass_lb"] = ( gen_fuel_allocated["fuel_consumed_mmbtu"] @@ -1265,9 +1271,7 @@ def calculate_so2_from_fuel_consumption(gen_fuel_allocated, pudl_out, year): return gen_fuel_allocated -def calculate_generator_so2_ef_per_unit_from_boiler_type( - gen_fuel_allocated, year, pudl_out -): +def calculate_generator_so2_ef_per_unit_from_boiler_type(gen_fuel_allocated, year): """Calculates a generator-specific Nox emission factor per unit fuel based on boiler firing type If a generator has multiple boilers, average the emission factor of all boilers @@ -1300,10 +1304,14 @@ def calculate_generator_so2_ef_per_unit_from_boiler_type( boiler_firing_type = boiler_firing_type.drop_duplicates() # identify the boiler firing type for each generator - boiler_generator_assn = pudl_out.bga_eia860() + boiler_generator_assn = load_data.load_pudl_table( + "boiler_generator_assn_eia860", + year, + columns=["plant_id_eia", "boiler_id", "generator_id"], + ) # associate each boiler record with generator_id s boiler_firing_type = boiler_firing_type.merge( - boiler_generator_assn[["plant_id_eia", "boiler_id", "generator_id"]], + boiler_generator_assn, how="left", on=["plant_id_eia", "boiler_id"], validate="1:m", @@ -1435,36 +1443,30 @@ def calculate_generator_so2_ef_per_unit_from_boiler_type( return gen_so2_factors -def return_monthly_plant_fuel_sulfur_content(pudl_out): +def return_monthly_plant_fuel_sulfur_content(year): """ Returns the month specific, plant average sulfur content. Sulfur content values are on a 0-100 scale (e.g. 5.2% = 5.2) """ - plant_specific_fuel_sulfur_content = pudl_out.bf_eia923().loc[ - :, - [ + plant_specific_fuel_sulfur_content = load_data.load_pudl_table( + "boiler_fuel_eia923", + year, + columns=[ "plant_id_eia", "boiler_id", + "prime_mover_code", "energy_source_code", "report_date", "fuel_consumed_units", "sulfur_content_pct", ], - ] + ) plant_specific_fuel_sulfur_content = plant_specific_fuel_sulfur_content[ ~plant_specific_fuel_sulfur_content["energy_source_code"].isin(CLEAN_FUELS) ] - # merge in the prime mover data - plant_specific_fuel_sulfur_content = plant_specific_fuel_sulfur_content.merge( - pd.read_sql("boilers_entity_eia", pudl_out.pudl_engine), - how="left", - on=["plant_id_eia", "boiler_id"], - validate="m:1", - ) - # calculate a weighted average for each generator plant_specific_fuel_sulfur_content = calculate_weighted_averages( plant_specific_fuel_sulfur_content, @@ -1511,13 +1513,13 @@ def return_monthly_plant_fuel_sulfur_content(pudl_out): ) -def adjust_so2_efs_for_fuel_sulfur_content(uncontrolled_so2_factors, pudl_out): +def adjust_so2_efs_for_fuel_sulfur_content(uncontrolled_so2_factors, year): # multiply factors by sulfur content ( plant_specific_fuel_sulfur_content, national_avg_fuel_sulfur_content, annual_avg_fuel_sulfur_content, - ) = return_monthly_plant_fuel_sulfur_content(pudl_out) + ) = return_monthly_plant_fuel_sulfur_content(year) # merge in plant pm specific fuel sulfur content values uncontrolled_so2_factors = uncontrolled_so2_factors.merge( @@ -1561,15 +1563,18 @@ def adjust_so2_efs_for_fuel_sulfur_content(uncontrolled_so2_factors, pudl_out): ] if len(missing_sulfur_content) > 0: logger.warning("Sulfur content data is missing in EIA-923 for the above units.") - logger.warning("\n" + - missing_sulfur_content[ + logger.warning( + "\n" + + missing_sulfur_content[ [ "plant_id_eia", "generator_id", "prime_mover_code", "energy_source_code", ] - ].drop_duplicates().to_string() + ] + .drop_duplicates() + .to_string() ) uncontrolled_so2_factors.loc[ uncontrolled_so2_factors["sulfur_content_pct"].isna() @@ -1650,10 +1655,14 @@ def calculate_weighted_so2_control_efficiency( ) if aggregation_level == "generator_id": - boiler_generator_assn = load_data.initialize_pudl_out(year).bga_eia860() + boiler_generator_assn = load_data.load_pudl_table( + "boiler_generator_assn_eia860", + year, + columns=["plant_id_eia", "boiler_id", "generator_id"], + ) # associate a generator_id with each record so2_control_efficiency = so2_control_efficiency.merge( - boiler_generator_assn[["plant_id_eia", "boiler_id", "generator_id"]], + boiler_generator_assn, how="left", on=["plant_id_eia", "boiler_id"], validate="m:m", diff --git a/src/gross_to_net_generation.py b/src/gross_to_net_generation.py index fb456b34..22ebbb9f 100644 --- a/src/gross_to_net_generation.py +++ b/src/gross_to_net_generation.py @@ -399,10 +399,11 @@ def calculate_gross_to_net_conversion_factors( def calculate_subplant_nameplate_capacity(year): """Calculates the total nameplate capacity and primary prime mover for each CEMS subplant.""" # load generator data - pudl_out = load_data.initialize_pudl_out(year) - gen_capacity = pudl_out.gens_eia860()[ - ["plant_id_eia", "generator_id", "prime_mover_code", "capacity_mw"] - ] + gen_capacity = load_data.load_pudl_table( + "generators_eia860", + year, + columns=["plant_id_eia", "generator_id", "prime_mover_code", "capacity_mw"], + ) # add subplant ids to the generator data subplant_crosswalk = pd.read_csv( @@ -756,7 +757,7 @@ def load_monthly_gross_and_net_generation(start_year, end_year): # load and clean EIA data # create pudl_out - pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") + pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") pudl_engine = sa.create_engine(pudl_db) pudl_out = pudl.output.pudltabl.PudlTabl( pudl_engine, @@ -779,7 +780,6 @@ def load_monthly_gross_and_net_generation(start_year, end_year): def gross_to_net_ratio(gross_gen_data, net_gen_data, agg_level, year): - if agg_level == "plant": plant_aggregation_columns = ["plant_id_eia"] elif agg_level == "subplant": diff --git a/src/load_data.py b/src/load_data.py index a5d9fc6a..b1a7e8f1 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -14,6 +14,9 @@ logger = get_logger(__name__) +# initialize the pudl_engine +PUDL_ENGINE = sa.create_engine("sqlite:///" + downloads_folder("pudl/pudl.sqlite")) + def correct_epa_eia_plant_id_mapping(df): """ @@ -193,11 +196,13 @@ def add_report_date(df): Returns: Original dataframe with 'report_date' column added """ - plants_entity_eia = load_pudl_table("plants_entity_eia") + plant_timezone = load_pudl_table( + "plants_entity_eia", columns=["plant_id_eia", "timezone"] + ) # get timezone df = df.merge( - plants_entity_eia[["plant_id_eia", "timezone"]], + plant_timezone, how="left", on="plant_id_eia", validate="m:1", @@ -236,28 +241,6 @@ def add_report_date(df): return df -def load_pudl_table(table_name, year=None): - """ - Loads a table from the PUDL SQL database. - Inputs: - sql_query: string containing table name (to retrieve entire table) or SQL query (to select part of table) - Returns: - table: pandas dataframe containing requested query - """ - # specify the relative path to the sqllite database, and create an sqalchemy engine - pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") - pudl_engine = sa.create_engine(pudl_db) - - if year is not None: - sql_query = f"SELECT * FROM {table_name} WHERE report_date >= '{year}-01-01' AND report_date <= '{year}-12-01'" - else: - sql_query = table_name - - table = pd.read_sql(sql_query, pudl_engine) - - return table - - def load_ghg_emission_factors(): """ Read in the table of emissions factors and convert to lb/mmbtu @@ -320,26 +303,52 @@ def load_so2_emission_factors(): return df -def initialize_pudl_out(year=None): +def load_pudl_table( + table_name: str, year: int = None, columns: list[str] = None, end_year: int = None +): """ - Initializes a `pudl_out` object used to create tables for EIA and FERC Form 1 analysis. + Loads a table from the pudl database. + + `table_name` must be one of the options specified in the data dictionary: + https://catalystcoop-pudl.readthedocs.io/en/latest/data_dictionaries/pudl_db.html - If `year` is set to `None`, all years of data are returned. + There are multiple options for date filtering: + - if `year` is not specified, all years will be loaded + - if `year` is specified, but not `end_year`, only a single year will be loaded + - if both `year` and `end_year` are specified, all years in that range inclusive + will be loaded. `end_year` must be >= `year`. + + If a list of `columns` is passed, only those columns will be returned. Otherwise, + all columns will be returned. """ - pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") - pudl_engine = sa.create_engine(pudl_db) + + if columns is None: + columns_to_select = "*" + else: + columns_to_select = ", ".join(columns) if year is None: - pudl_out = pudl.output.pudltabl.PudlTabl(pudl_engine) + # load the table without filtering dates + table = pd.read_sql( + f"SELECT {columns_to_select} FROM {table_name}", + PUDL_ENGINE, + ) + elif year is not None and end_year is None: + # load the table for a single year + table = pd.read_sql( + f"SELECT {columns_to_select} FROM {table_name} WHERE \ + report_date >= '{year}-01-01' AND report_date < '{year + 1}-01-01'", + PUDL_ENGINE, + ) else: - pudl_out = pudl.output.pudltabl.PudlTabl( - pudl_engine, - freq="MS", - start_date=f"{year}-01-01", - end_date=f"{year}-12-31", - fill_tech_desc=False, + # load the for the specified years + table = pd.read_sql( + f"SELECT {columns_to_select} FROM {table_name} WHERE \ + report_date >= '{year}-01-01' AND report_date < '{end_year + 1}-01-01'", + PUDL_ENGINE, ) - return pudl_out + + return table def load_epa_eia_crosswalk_from_raw(year): @@ -418,10 +427,11 @@ def load_epa_eia_crosswalk_from_raw(year): ).drop(columns=["notes"]) # load EIA-860 data - pudl_out = initialize_pudl_out(year=year) - gen_esc_860 = pudl_out.gens_eia860()[ - ["plant_id_eia", "generator_id", "energy_source_code_1"] - ] + gen_esc_860 = load_pudl_table( + "generators_eia860", + year, + columns=["plant_id_eia", "generator_id", "energy_source_code_1"], + ) # merge the energy source code from EIA-860 crosswalk_manual = crosswalk_manual.merge( @@ -475,12 +485,13 @@ def load_epa_eia_crosswalk(year): ) # load EIA-860 data - pudl_out = initialize_pudl_out(year=year) - gen_esc_860 = pudl_out.gens_eia860()[["plant_id_eia", "generator_id"]] + gen_ids = load_pudl_table( + "generators_eia860", year, columns=["plant_id_eia", "generator_id"] + ) # merge in any plants that are missing from the EPA crosswalk but appear in EIA-860 crosswalk = crosswalk.merge( - gen_esc_860, how="outer", on=["plant_id_eia", "generator_id"], validate="m:1" + gen_ids, how="outer", on=["plant_id_eia", "generator_id"], validate="m:1" ) crosswalk["plant_id_epa"] = crosswalk["plant_id_epa"].fillna( crosswalk["plant_id_eia"] @@ -865,8 +876,7 @@ def load_unit_to_boiler_associations(year): outputs_folder(f"{year}/subplant_crosswalk_{year}.csv"), dtype=get_dtypes(), ) - pudl_out = initialize_pudl_out(year=year) - boiler_generator_assn = pudl_out.bga_eia860() + boiler_generator_assn = load_pudl_table("boiler_generator_assn_eia860", year) unit_boiler_assn = subplant_crosswalk.merge( boiler_generator_assn, how="left", on=["plant_id_eia", "generator_id"] ) diff --git a/src/validation.py b/src/validation.py index 8b1042d6..c131b9f0 100644 --- a/src/validation.py +++ b/src/validation.py @@ -43,14 +43,14 @@ def validate_year(year): raise UserWarning(year_warning) -def check_allocated_gf_matches_input_gf(pudl_out, gen_fuel_allocated): +def check_allocated_gf_matches_input_gf(year, gen_fuel_allocated): """ Checks that the allocated generation and fuel from EIA-923 matches the input totals. We use np.isclose() to identify any values that are off by more than 1e-9% different from the total input generation or fuel. """ - gf = pudl_out.gf_eia923() + gf = load_data.load_pudl_table("generation_fuel_eia923", year) plant_total_gf = gf.groupby("plant_id_eia")[ [ "net_generation_mwh", @@ -110,7 +110,6 @@ def flag_possible_primary_fuel_mismatches(plant_primary_fuel): ] for esc_column in ["plant_primary_fuel_from_capacity_mw", "plant_primary_fuel"]: - # load the fuel category table energy_source_groups = pd.read_csv( manual_folder("energy_source_groups.csv"), dtype=get_dtypes() @@ -727,7 +726,8 @@ def validate_unique_datetimes(df, df_name, keys): Args: df: dataframe containing datetime columns df_name: a descriptive name for the dataframe - keys: list of column names that contain the groups within which datetimes should be unique""" + keys: list of column names that contain the groups within which datetimes should be unique + """ for datetime_column in ["datetime_utc", "datetime_local"]: if datetime_column in list(df.columns): @@ -747,14 +747,15 @@ def check_for_complete_timeseries(df, df_name, keys, period): If the `period` is a 'year', checks that the length of the timeseries is 8760 (for a non-leap year) or 8784 (for a leap year). If the `period` is a 'month', checks that the length of the timeseries is equal to the length of the complete date_range - between the earliest and latest timestamp in a month. + between the earliest and latest timestamp in a month. Args: df: dataframe containing datetime columns df_name: a descriptive name for the dataframe year keys: list of column names that contain the groups within which datetimes should be unique - period: either 'month' or 'year'. Period within which to ensure complete hourly data""" + period: either 'month' or 'year'. Period within which to ensure complete hourly data + """ if period == "year": # identify the year of the data @@ -775,7 +776,6 @@ def check_for_complete_timeseries(df, df_name, keys, period): ) logger.warning("\n" + test.to_string()) elif period == "month": - # count the number of timestamps in each group-month test = ( df.groupby(keys + ["report_date"])[["datetime_utc"]] @@ -1115,10 +1115,9 @@ def identify_reporting_frequency(eia923_allocated, year): Returns input dataframe with `eia_data_resolution` column added""" # load data about the respondent frequency for each plant and merge into the EIA-923 data - pudl_out = load_data.initialize_pudl_out(year) - plant_frequency = pudl_out.plants_eia860()[ - ["plant_id_eia", "reporting_frequency_code"] - ].copy() + plant_frequency = load_data.load_pudl_table( + "plants_eia860", year, columns=["plant_id_eia", "reporting_frequency_code"] + ) plant_frequency["reporting_frequency_code"] = plant_frequency[ "reporting_frequency_code" ].fillna("multiple") @@ -1435,7 +1434,6 @@ def validate_diba_imputation_method(hourly_profiles, year): def validate_national_imputation_method(hourly_profiles): - # only keep wind and solar data data_to_validate = hourly_profiles[ (hourly_profiles["fuel_category"].isin(["wind", "solar"])) @@ -1606,12 +1604,12 @@ def test_for_missing_data(df, columns_to_test): def test_for_missing_incorrect_prime_movers(df, year): - # cehck for incorrect PM by comparing to EIA-860 data - pudl_out = load_data.initialize_pudl_out(year) - pms_in_eia860 = pudl_out.gens_eia860()[ - ["plant_id_eia", "generator_id", "prime_mover_code"] - ] + pms_in_eia860 = load_data.load_pudl_table( + "generators_eia860", + year, + columns=["plant_id_eia", "generator_id", "prime_mover_code"], + ) incorrect_pm_test = df.copy()[["plant_id_eia", "generator_id", "prime_mover_code"]] incorrect_pm_test = incorrect_pm_test.merge( pms_in_eia860, @@ -2122,7 +2120,6 @@ def compare_plant_level_results_to_egrid( def identify_plants_missing_from_our_calculations( egrid_plant, annual_plant_results, year ): - # remove any plants that have no reported data in egrid # NOTE: it seems that egrid includes a lot of proposed projects that are not yet operating, but just has missing data for them plants_with_no_data_in_egrid = list( @@ -2154,16 +2151,18 @@ def identify_plants_missing_from_our_calculations( ] # see if any of these plants are retired - generators_eia860 = load_data.load_pudl_table("generators_eia860", year=year) + generator_status = load_data.load_pudl_table( + "generators_eia860", + year, + columns=[ + "plant_id_eia", + "operational_status", + "current_planned_operating_date", + "retirement_date", + ], + ).drop_duplicates() missing_from_calc.merge( - generators_eia860[ - [ - "plant_id_eia", - "operational_status", - "current_planned_operating_date", - "retirement_date", - ] - ].drop_duplicates(), + generator_status, how="left", on="plant_id_eia", validate="m:m", @@ -2179,9 +2178,9 @@ def identify_plants_missing_from_egrid(egrid_plant, annual_plant_results): - set(egrid_plant["plant_id_egrid"].unique()) ) - plant_names = load_data.load_pudl_table(table_name="plants_entity_eia")[ - ["plant_id_eia", "plant_name_eia"] - ] + plant_names = load_data.load_pudl_table( + "plants_entity_eia", columns=["plant_id_eia", "plant_name_eia"] + ) missing_from_egrid = annual_plant_results[ annual_plant_results["plant_id_egrid"].isin(PLANTS_MISSING_FROM_EGRID) ].merge(plant_names, how="left", on="plant_id_eia", validate="m:1") @@ -2193,7 +2192,7 @@ def segment_plants_by_known_issues( annual_plant_results, egrid_plant, eia923_allocated, - pudl_out, + year, PLANTS_MISSING_FROM_EGRID, ): annual_plant_results_segmented = annual_plant_results.copy() @@ -2217,7 +2216,7 @@ def segment_plants_by_known_issues( ] = 1 # fuel cells - gens_eia860 = pudl_out.gens_eia860() + gens_eia860 = load_data.load_pudl_table("generators_eia860", year) PLANTS_WITH_FUEL_CELLS = list( gens_eia860.loc[ gens_eia860["prime_mover_code"] == "FC", "plant_id_eia" @@ -2258,8 +2257,16 @@ def segment_plants_by_known_issues( ] = 1 # identify plants that report data to the bf or gen table - bf_reporter = list(pudl_out.bf_eia923()["plant_id_eia"].unique()) - gen_reporter = list(pudl_out.gen_original_eia923()["plant_id_eia"].unique()) + bf_reporter = list( + load_data.load_pudl_table( + "boiler_fuel_eia923", year, columns=["plant_id_eia"] + ).unique() + ) + gen_reporter = list( + load_data.load_pudl_table( + "generation_eia923", year, columns=["plant_id_eia"] + ).unique() + ) annual_plant_results_segmented["flag_bf_gen_reporter"] = 0 annual_plant_results_segmented.loc[ ( @@ -2270,9 +2277,11 @@ def segment_plants_by_known_issues( ] = 1 # identify plants with proposed generators - status = pudl_out.gens_eia860()[ - ["plant_id_eia", "generator_id", "operational_status"] - ] + status = load_data.load_pudl_table( + "generators_eia860", + year, + columns=["plant_id_eia", "generator_id", "operational_status"], + ) plants_with_proposed_gens = list( status.loc[ status["operational_status"] == "proposed", @@ -2364,7 +2373,7 @@ def compare_egrid_fuel_total(plant_data, egrid_plant_df): return compare_fuel -def identify_potential_missing_fuel_in_egrid(pudl_out, year, egrid_plant, cems): +def identify_potential_missing_fuel_in_egrid(year, egrid_plant, cems): # load the EIA generator fuel data IDX_PM_ESC = [ "report_date", @@ -2372,15 +2381,16 @@ def identify_potential_missing_fuel_in_egrid(pudl_out, year, egrid_plant, cems): "energy_source_code", "prime_mover_code", ] - gf = pudl_out.gf_eia923().loc[ - :, - IDX_PM_ESC + gf = load_data.load_pudl_table( + "generation_fuel_eia923", + year, + columns=IDX_PM_ESC + [ "net_generation_mwh", "fuel_consumed_mmbtu", "fuel_consumed_for_electricity_mmbtu", ], - ] + ) # add egrid plant ids egrid_crosswalk = pd.read_csv( From 2d263c2da4271937b6019bda04eb7588dc31a6c1 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 2 Dec 2023 14:10:37 -0800 Subject: [PATCH 18/85] update references to pudl.analysis --- notebooks/work_in_progress/sandbox.ipynb | 952 ++++++++++++++++++++++- src/column_checks.py | 4 +- src/data_cleaning.py | 31 +- src/gross_to_net_generation.py | 23 +- src/load_data.py | 29 +- src/validation.py | 4 +- 6 files changed, 979 insertions(+), 64 deletions(-) diff --git a/notebooks/work_in_progress/sandbox.ipynb b/notebooks/work_in_progress/sandbox.ipynb index 7b515fd4..528a7179 100644 --- a/notebooks/work_in_progress/sandbox.ipynb +++ b/notebooks/work_in_progress/sandbox.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -38,6 +38,954 @@ "year = 2021\n", "path_prefix = f\"{year}/\"" ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
report_yearplant_id_epaemissions_unit_id_epagenerator_id_epaplant_id_eiaboiler_idgenerator_id
02018311311
12018322322
22018333333
32018344344
42018355355
........................
12827202163688CT-9CTG-963688NoneCTG-9
12828202164854CT1GTG0164854NoneGTG01
12829202164854CT2GTG0264854NoneGTG02
12830202170454MAG1MAG154538NoneMAG1
12831202170454MAG2MAG254538NoneMAG2
\n", + "

12832 rows × 7 columns

\n", + "
" + ], + "text/plain": [ + " report_year plant_id_epa emissions_unit_id_epa generator_id_epa plant_id_eia boiler_id generator_id\n", + "0 2018 3 1 1 3 1 1\n", + "1 2018 3 2 2 3 2 2\n", + "2 2018 3 3 3 3 3 3\n", + "3 2018 3 4 4 3 4 4\n", + "4 2018 3 5 5 3 5 5\n", + "... ... ... ... ... ... ... ...\n", + "12827 2021 63688 CT-9 CTG-9 63688 None CTG-9\n", + "12828 2021 64854 CT1 GTG01 64854 None GTG01\n", + "12829 2021 64854 CT2 GTG02 64854 None GTG02\n", + "12830 2021 70454 MAG1 MAG1 54538 None MAG1\n", + "12831 2021 70454 MAG2 MAG2 54538 None MAG2\n", + "\n", + "[12832 rows x 7 columns]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "crosswalk = load_data.load_pudl_table(\"epacamd_eia\")\n", + "crosswalk" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
report_yearplant_id_epaemissions_unit_id_epagenerator_id_epaplant_id_eiaboiler_idgenerator_id
\n", + "
" + ], + "text/plain": [ + "Empty DataFrame\n", + "Columns: [report_year, plant_id_epa, emissions_unit_id_epa, generator_id_epa, plant_id_eia, boiler_id, generator_id]\n", + "Index: []" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "crosswalk[crosswalk[\"plant_id_epa\"] == 65961]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
report_yearplant_id_epaemissions_unit_id_epagenerator_id_epaplant_id_eiaboiler_idgenerator_id
02018.0311311
12021.0311311
22018.0322322
32021.0322322
42018.0333333
........................
38837NaN65961NaNNaN65961NaNGEN1
38838NaN65962NaNNaN65962NaNMS4
38839NaN65962NaNNaN65962NaNMS4B
38840NaN65963NaNNaN65963NaNMS5
38841NaN65963NaNNaN65963NaNMS5B
\n", + "

38842 rows × 7 columns

\n", + "
" + ], + "text/plain": [ + " report_year plant_id_epa emissions_unit_id_epa generator_id_epa plant_id_eia boiler_id generator_id\n", + "0 2018.0 3 1 1 3 1 1\n", + "1 2021.0 3 1 1 3 1 1\n", + "2 2018.0 3 2 2 3 2 2\n", + "3 2021.0 3 2 2 3 2 2\n", + "4 2018.0 3 3 3 3 3 3\n", + "... ... ... ... ... ... ... ...\n", + "38837 NaN 65961 NaN NaN 65961 NaN GEN1\n", + "38838 NaN 65962 NaN NaN 65962 NaN MS4\n", + "38839 NaN 65962 NaN NaN 65962 NaN MS4B\n", + "38840 NaN 65963 NaN NaN 65963 NaN MS5\n", + "38841 NaN 65963 NaN NaN 65963 NaN MS5B\n", + "\n", + "[38842 rows x 7 columns]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "oge_cw = load_data.load_epa_eia_crosswalk(year)\n", + "oge_cw" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
plant_id_eiaplant_id_epasubplant_idunit_id_pudlemissions_unit_id_epagenerator_id
011.00NaNWT2WT2
111.01NaNWT1WT1
211.02NaN5.15.1
311.03NaN55
411.04NaN33
.....................
39943880109NaN0NaNB001None
39944880110NaN0NaN1None
39945880110NaN1NaN2None
39946880110NaN2NaN3None
39947880110NaN3NaN4None
\n", + "

39948 rows × 6 columns

\n", + "
" + ], + "text/plain": [ + " plant_id_eia plant_id_epa subplant_id unit_id_pudl emissions_unit_id_epa generator_id\n", + "0 1 1.0 0 NaN WT2 WT2\n", + "1 1 1.0 1 NaN WT1 WT1\n", + "2 1 1.0 2 NaN 5.1 5.1\n", + "3 1 1.0 3 NaN 5 5\n", + "4 1 1.0 4 NaN 3 3\n", + "... ... ... ... ... ... ...\n", + "39943 880109 NaN 0 NaN B001 None\n", + "39944 880110 NaN 0 NaN 1 None\n", + "39945 880110 NaN 1 NaN 2 None\n", + "39946 880110 NaN 2 NaN 3 None\n", + "39947 880110 NaN 3 NaN 4 None\n", + "\n", + "[39948 rows x 6 columns]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pudl_subplants = load_data.load_pudl_table(\"epacamd_eia_subplant_ids\")\n", + "pudl_subplants" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
plant_id_eiaplant_id_epasubplant_idunit_id_pudlemissions_unit_id_epagenerator_id
471617321732.00NaN107
471717321732.00NaN108
471817321732.00NaN117
471917321732.00NaN127
472017321732.00NaN97
472117321732.00NaN118
472217321732.00NaN128
472317321732.00NaN98
472417321732.01NaN66
\n", + "
" + ], + "text/plain": [ + " plant_id_eia plant_id_epa subplant_id unit_id_pudl emissions_unit_id_epa generator_id\n", + "4716 1732 1732.0 0 NaN 10 7\n", + "4717 1732 1732.0 0 NaN 10 8\n", + "4718 1732 1732.0 0 NaN 11 7\n", + "4719 1732 1732.0 0 NaN 12 7\n", + "4720 1732 1732.0 0 NaN 9 7\n", + "4721 1732 1732.0 0 NaN 11 8\n", + "4722 1732 1732.0 0 NaN 12 8\n", + "4723 1732 1732.0 0 NaN 9 8\n", + "4724 1732 1732.0 1 NaN 6 6" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pudl_subplants[pudl_subplants[\"plant_id_epa\"] == 1732]" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
report_yearplant_id_epaemissions_unit_id_epagenerator_id_epaplant_id_eiaboiler_idgenerator_id
1264201817321071732107
1265201817321081732108
1266201817321171732117
1267201817321181732118
1268201817321271732127
1269201817321281732128
12702018173297173297
12712018173298173298
7683202117321071732107
7684202117321081732108
7685202117321171732117
7686202117321181732118
7687202117321271732127
7688202117321281732128
76892021173297173297
76902021173298173298
\n", + "
" + ], + "text/plain": [ + " report_year plant_id_epa emissions_unit_id_epa generator_id_epa plant_id_eia boiler_id generator_id\n", + "1264 2018 1732 10 7 1732 10 7\n", + "1265 2018 1732 10 8 1732 10 8\n", + "1266 2018 1732 11 7 1732 11 7\n", + "1267 2018 1732 11 8 1732 11 8\n", + "1268 2018 1732 12 7 1732 12 7\n", + "1269 2018 1732 12 8 1732 12 8\n", + "1270 2018 1732 9 7 1732 9 7\n", + "1271 2018 1732 9 8 1732 9 8\n", + "7683 2021 1732 10 7 1732 10 7\n", + "7684 2021 1732 10 8 1732 10 8\n", + "7685 2021 1732 11 7 1732 11 7\n", + "7686 2021 1732 11 8 1732 11 8\n", + "7687 2021 1732 12 7 1732 12 7\n", + "7688 2021 1732 12 8 1732 12 8\n", + "7689 2021 1732 9 7 1732 9 7\n", + "7690 2021 1732 9 8 1732 9 8" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "crosswalk[crosswalk[\"plant_id_epa\"] == 1732]" + ] } ], "metadata": { @@ -56,7 +1004,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.10.11" }, "orig_nbformat": 4, "vscode": { diff --git a/src/column_checks.py b/src/column_checks.py index 43eeff12..8707784c 100644 --- a/src/column_checks.py +++ b/src/column_checks.py @@ -333,8 +333,8 @@ "generator_id", "subplant_id", "unit_id_pudl", - "current_planned_operating_date", - "retirement_date", + "current_planned_generator_operating_date", + "generator_retirement_date", "prime_mover_code", }, "shaped_aggregated_plants": { diff --git a/src/data_cleaning.py b/src/data_cleaning.py index 24cd0f34..e4946f73 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -5,7 +5,6 @@ import pudl.analysis.allocate_net_gen as allocate_gen_fuel import pudl.analysis.epacamd_eia as epacamd_eia_crosswalk -import pudl.output.pudltabl import load_data import validation @@ -164,7 +163,7 @@ def generate_subplant_ids(start_year, end_year, cems_ids): ) # add proposed operating dates and retirements to the subplant id crosswalk - subplant_crosswalk_complete = add_operating_and_retirement_dates( + subplant_crosswalk_complete = add_operating_and_generator_retirement_dates( subplant_crosswalk_complete, start_year, end_year ) # add prime mover code to the crosswalk @@ -324,7 +323,7 @@ def connect_ids(df, id_to_update, connecting_id): return df -def add_operating_and_retirement_dates(df, start_year, end_year): +def add_operating_and_generator_retirement_dates(df, start_year, end_year): """Adds columns listing a generator's planned operating date or retirement date to a dataframe.""" generator_status = load_data.load_pudl_table( @@ -335,16 +334,16 @@ def add_operating_and_retirement_dates(df, start_year, end_year): "generator_id", "report_date", "operational_status", - "current_planned_operating_date", - "retirement_date", + "current_planned_generator_operating_date", + "generator_retirement_date", ], end_year=end_year, ) # only keep values that have a planned operating date or retirement date generator_status = generator_status[ - (~generator_status["current_planned_operating_date"].isna()) - | (~generator_status["retirement_date"].isna()) + (~generator_status["current_planned_generator_operating_date"].isna()) + | (~generator_status["generator_retirement_date"].isna()) ] # drop any duplicate entries generator_status = generator_status.sort_values( @@ -353,8 +352,8 @@ def add_operating_and_retirement_dates(df, start_year, end_year): subset=[ "plant_id_eia", "generator_id", - "current_planned_operating_date", - "retirement_date", + "current_planned_generator_operating_date", + "generator_retirement_date", ], keep="last", ) @@ -369,8 +368,8 @@ def add_operating_and_retirement_dates(df, start_year, end_year): [ "plant_id_eia", "generator_id", - "current_planned_operating_date", - "retirement_date", + "current_planned_generator_operating_date", + "generator_retirement_date", ] ], how="left", @@ -414,8 +413,8 @@ def clean_eia923( # Distribute net generation and heat input data reported by the three different EIA-923 tables # allocate net generation and heat input to each generator-fuel grouping - gen_fuel_allocated = allocate_gen_fuel.allocate_gen_fuel_by_generator_energy_source( - pudl_out, drop_interim_cols=True + gen_fuel_allocated = load_data.load_pudl_table( + "generation_fuel_by_generator_energy_source_monthly_eia923", year ) # test to make sure allocated totals match input totals @@ -1579,15 +1578,15 @@ def count_total_units_in_subplant(year): pd.read_csv( outputs_folder(f"{year}/subplant_crosswalk_{year}.csv"), dtype=get_dtypes(), - parse_dates=["current_planned_operating_date", "retirement_date"], - )[["plant_id_eia", "emissions_unit_id_epa", "subplant_id", "retirement_date"]] + parse_dates=["current_planned_generator_operating_date", "generator_retirement_date"], + )[["plant_id_eia", "emissions_unit_id_epa", "subplant_id", "generator_retirement_date"]] .drop_duplicates() .dropna(subset="emissions_unit_id_epa") ) # remove units that retired before the current year units_in_subplant = units_in_subplant[ - ~(units_in_subplant["retirement_date"].dt.year < year) + ~(units_in_subplant["generator_retirement_date"].dt.year < year) ] # get a count of the number of CEMS units in each subplant diff --git a/src/gross_to_net_generation.py b/src/gross_to_net_generation.py index 22ebbb9f..897bff7d 100644 --- a/src/gross_to_net_generation.py +++ b/src/gross_to_net_generation.py @@ -7,7 +7,6 @@ # import pudl packages import pudl.analysis.allocate_net_gen as allocate_gen_fuel -import pudl.output.pudltabl # import other modules import load_data @@ -755,21 +754,13 @@ def load_monthly_gross_and_net_generation(start_year, end_year): # load cems data cems_monthly = load_data.load_cems_gross_generation(start_year, end_year) - # load and clean EIA data - # create pudl_out - pudl_db = "sqlite:///" + downloads_folder("pudl/pudl.sqlite") - pudl_engine = sa.create_engine(pudl_db) - pudl_out = pudl.output.pudltabl.PudlTabl( - pudl_engine, - freq="MS", - start_date=f"{start_year}-01-01", - end_date=f"{end_year}-12-31", - ) - # allocate net generation and heat input to each generator-fuel grouping logger.info("Allocating EIA-923 generation data") - gen_fuel_allocated = allocate_gen_fuel.allocate_gen_fuel_by_generator_energy_source( - pudl_out, drop_interim_cols=True + gen_fuel_allocated = load_data.load_pudl_table( + "generation_fuel_by_generator_energy_source_monthly_eia923", + year=start_year, + columns=None, + end_year=end_year, ) # aggregate the allocated data to the generator level gen_fuel_allocated = allocate_gen_fuel.agg_by_generator( @@ -815,14 +806,14 @@ def gross_to_net_ratio(gross_gen_data, net_gen_data, agg_level, year): # drop any of these rows where the retirement date is before the report date (only applies if net generation missing) incomplete_data = incomplete_data[ - ~(incomplete_data["retirement_date"] < incomplete_data["report_date"]) + ~(incomplete_data["generator_retirement_date"] < incomplete_data["report_date"]) ] # drop any of these rows where the report date is before the planned operating date incomplete_data = incomplete_data[ ~( incomplete_data["report_date"] - < incomplete_data["current_planned_operating_date"] + < incomplete_data["current_planned_generator_operating_date"] ) ] diff --git a/src/load_data.py b/src/load_data.py index b1a7e8f1..591ed792 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -5,8 +5,6 @@ import warnings from pathlib import Path -import pudl.output.pudltabl - from column_checks import get_dtypes from filepaths import downloads_folder, manual_folder, outputs_folder from validation import validate_unique_datetimes @@ -18,18 +16,6 @@ PUDL_ENGINE = sa.create_engine("sqlite:///" + downloads_folder("pudl/pudl.sqlite")) -def correct_epa_eia_plant_id_mapping(df): - """ - The EPA's power sector data crosswalk incorrectly maps plant_id_epa 55248 to - plant_id_eia 55248, when it should be mapped to id 2847. This function is temporary - until this is fixed. - """ - - df.loc[df["plant_id_eia"] == 55248, "plant_id_eia"] = 2847 - - return df - - def load_cems_data(year): """ Loads CEMS data for the specified year from the PUDL database @@ -64,9 +50,6 @@ def load_cems_data(year): columns=cems_columns, ) - # **** manual adjustments **** - cems = correct_epa_eia_plant_id_mapping(cems) - cems = cems.rename( columns={ "operating_datetime_utc": "datetime_utc", @@ -130,9 +113,6 @@ def load_cems_ids(start_year, end_year): columns=["plant_id_eia", "emissions_unit_id_epa"], ).drop_duplicates() - # **** manual adjustments **** - cems = correct_epa_eia_plant_id_mapping(cems) - return cems @@ -354,6 +334,9 @@ def load_pudl_table( def load_epa_eia_crosswalk_from_raw(year): """ Read in the manual EPA-EIA Crosswalk table downloaded from the EPA website. + + This is only used in OGE to access the CAMD_FUEL_TYPE column, which is dropped from + the PUDL version of the table. """ crosswalk = pd.read_csv( @@ -417,9 +400,6 @@ def load_epa_eia_crosswalk_from_raw(year): crosswalk["energy_source_code_epa"] ) - # **** manual adjustments **** - crosswalk = correct_epa_eia_plant_id_mapping(crosswalk) - # load manually inputted data crosswalk_manual = pd.read_csv( manual_folder("epa_eia_crosswalk_manual.csv"), @@ -469,9 +449,6 @@ def load_epa_eia_crosswalk(year): crosswalk = load_pudl_table("epacamd_eia") - # **** manual adjustments **** - crosswalk = correct_epa_eia_plant_id_mapping(crosswalk) - # load manually inputted data crosswalk_manual = pd.read_csv( manual_folder("epa_eia_crosswalk_manual.csv"), diff --git a/src/validation.py b/src/validation.py index c131b9f0..2302762c 100644 --- a/src/validation.py +++ b/src/validation.py @@ -2157,8 +2157,8 @@ def identify_plants_missing_from_our_calculations( columns=[ "plant_id_eia", "operational_status", - "current_planned_operating_date", - "retirement_date", + "current_planned_generator_operating_date", + "generator_retirement_date", ], ).drop_duplicates() missing_from_calc.merge( From b841aa312347ae239edc2247488a3af50113b28a Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 2 Dec 2023 15:06:08 -0800 Subject: [PATCH 19/85] update nox so2 table dependencies --- data/manual/emission_factors_for_nox.csv | 882 +++---- data/manual/emission_factors_for_so2.csv | 2804 +++++++++++----------- notebooks/work_in_progress/sandbox.ipynb | 950 +------- src/column_checks.py | 22 +- src/data_cleaning.py | 14 +- src/emissions.py | 120 +- src/load_data.py | 129 +- 7 files changed, 1941 insertions(+), 2980 deletions(-) diff --git a/data/manual/emission_factors_for_nox.csv b/data/manual/emission_factors_for_nox.csv index acf9dc44..9417b07d 100644 --- a/data/manual/emission_factors_for_nox.csv +++ b/data/manual/emission_factors_for_nox.csv @@ -1,441 +1,441 @@ -prime_mover_code,energy_source_code,boiler_bottom_type,boiler_firing_type,emission_factor,emission_factor_numerator,emission_factor_denominator -ST,AB,WET,CYCLONE,1.2,lb,ton -ST,AB,N/A,N/A,1.2,lb,ton -ST,AB,DRY,STOKER,1.2,lb,ton -ST,AB,N/A,STOKER,1.2,lb,ton -OT,BFG,N/A,N/A,0.0154,lb,mcf -ST,BFG,N/A,N/A,0.0154,lb,mcf -ST,BFG,N/A,TANGENTIAL,0.0154,lb,mcf -ST,BFG,DRY,WALL,0.0154,lb,mcf -ST,BFG,N/A,WALL,0.0154,lb,mcf -CA,BIT,DRY,DUCTBURNER,12,lb,ton -CA,BIT,N/A,DUCTBURNER,12,lb,ton -CA,BIT,WET,DUCTBURNER,31,lb,ton -ST,BIT,DRY,CELLBURNER,12,lb,ton -ST,BIT,DRY,CYCLONE,33,lb,ton -ST,BIT,N/A,CYCLONE,33,lb,ton -ST,BIT,WET,CYCLONE,33,lb,ton -ST,BIT,DRY,FLUIDIZED,5,lb,ton -ST,BIT,N/A,FLUIDIZED,5,lb,ton -ST,BIT,WET,FLUIDIZED,5,lb,ton -ST,BIT,N/A,N/A,31,lb,ton -ST,BIT,DRY,N/A,12,lb,ton -ST,BIT,WET,N/A,31,lb,ton -ST,BIT,DRY,OTHER,12,lb,ton -ST,BIT,N/A,OTHER,12,lb,ton -ST,BIT,WET,OTHER,31,lb,ton -ST,BIT,DRY,STOKER,11,lb,ton -ST,BIT,N/A,STOKER,11,lb,ton -ST,BIT,WET,STOKER,11,lb,ton -ST,BIT,DRY,TANGENTIAL,10,lb,ton -ST,BIT,N/A,TANGENTIAL,10,lb,ton -ST,BIT,WET,TANGENTIAL,14,lb,ton -ST,BIT,DRY,VERTICAL,12,lb,ton -ST,BIT,WET,VERTICAL,31,lb,ton -ST,BIT,DRY,WALL,12,lb,ton -ST,BIT,N/A,WALL,12,lb,ton -ST,BIT,WET,WALL,31,lb,ton -ST,BLQ,DRY,CELLBURNER,1.5,lb,ton -ST,BLQ,N/A,CYCLONE,1.5,lb,ton -ST,BLQ,N/A,DUCTBURNER,1.5,lb,ton -ST,BLQ,DRY,FLUIDIZED,1.5,lb,ton -ST,BLQ,N/A,FLUIDIZED,1.5,lb,ton -ST,BLQ,WET,FLUIDIZED,1.5,lb,ton -ST,BLQ,N/A,N/A,1.5,lb,ton -ST,BLQ,DRY,N/A,1.5,lb,ton -ST,BLQ,WET,N/A,1.5,lb,ton -ST,BLQ,DRY,OTHER,1.5,lb,ton -ST,BLQ,N/A,OTHER,1.5,lb,ton -ST,BLQ,DRY,STOKER,1.5,lb,ton -ST,BLQ,N/A,STOKER,1.5,lb,ton -ST,BLQ,WET,STOKER,1.5,lb,ton -ST,BLQ,DRY,TANGENTIAL,1.5,lb,ton -ST,BLQ,N/A,TANGENTIAL,1.5,lb,ton -ST,BLQ,WET,TANGENTIAL,1.5,lb,ton -ST,BLQ,DRY,VERTICAL,1.5,lb,ton -ST,BLQ,DRY,WALL,1.5,lb,ton -ST,BLQ,N/A,WALL,1.5,lb,ton -ST,BLQ,WET,WALL,1.5,lb,ton -OT,COG,N/A,N/A,0.0154,lb,mcf -ST,COG,N/A,CYCLONE,0.0154,lb,mcf -ST,COG,N/A,N/A,0.0154,lb,mcf -ST,COG,N/A,WALL,0.0154,lb,mcf -CA,DFO,N/A,CELLBURNER,5.124,lb,barrels -CA,DFO,DRY,DUCTBURNER,5.124,lb,barrels -CA,DFO,N/A,DUCTBURNER,5.124,lb,barrels -CA,DFO,N/A,N/A,5.124,lb,barrels -CA,DFO,N/A,OTHER,5.124,lb,barrels -CA,DFO,DRY,OTHER,5.124,lb,barrels -CA,DFO,N/A,WALL,5.124,lb,barrels -CS,DFO,N/A,N/A,5.124,lb,barrels -CT,DFO,N/A,CC,5.124,lb,barrels -CT,DFO,N/A,CELLBURNER,5.124,lb,barrels -CT,DFO,DRY,DUCTBURNER,5.124,lb,barrels -CT,DFO,N/A,DUCTBURNER,5.124,lb,barrels -CT,DFO,N/A,N/A,5.124,lb,barrels -CT,DFO,DRY,OTHER,5.124,lb,barrels -CT,DFO,N/A,OTHER,5.124,lb,barrels -CT,DFO,N/A,TANGENTIAL,5.124,lb,barrels -CT,DFO,N/A,WALL,5.124,lb,barrels -GT,DFO,N/A,CT,5.124,lb,barrels -GT,DFO,N/A,N/A,5.124,lb,barrels -IC,DFO,N/A,N/A,18.6396,lb,barrels -ST,DFO,DRY,CELLBURNER,1.008,lb,barrels -ST,DFO,DRY,CYCLONE,1.008,lb,barrels -ST,DFO,N/A,CYCLONE,1.008,lb,barrels -ST,DFO,WET,CYCLONE,1.008,lb,barrels -ST,DFO,N/A,DUCTBURNER,1.008,lb,barrels -ST,DFO,DRY,FLUIDIZED,1.008,lb,barrels -ST,DFO,N/A,FLUIDIZED,1.008,lb,barrels -ST,DFO,WET,FLUIDIZED,1.008,lb,barrels -ST,DFO,DRY,N/A,1.008,lb,barrels -ST,DFO,N/A,N/A,1.008,lb,barrels -ST,DFO,WET,N/A,1.008,lb,barrels -ST,DFO,DRY,OTHER,1.008,lb,barrels -ST,DFO,N/A,OTHER,1.008,lb,barrels -ST,DFO,DRY,STOKER,1.008,lb,barrels -ST,DFO,DRY,TANGENTIAL,1.008,lb,barrels -ST,DFO,N/A,TANGENTIAL,1.008,lb,barrels -ST,DFO,WET,TANGENTIAL,1.008,lb,barrels -ST,DFO,DRY,VERTICAL,1.008,lb,barrels -ST,DFO,DRY,WALL,1.008,lb,barrels -ST,DFO,N/A,WALL,1.008,lb,barrels -ST,DFO,WET,WALL,1.008,lb,barrels -BT,GEO,N/A,N/A,0,lb,MMBtu -ST,GEO,N/A,N/A,0.000305,lb,MMBtu -GT,JF,N/A,CT,4.9896,lb,barrels -GT,JF,N/A,N/A,4.9896,lb,barrels -IC,JF,N/A,N/A,18.144,lb,barrels -ST,JF,N/A,N/A,1.008,lb,barrels -CA,KER,N/A,N/A,4.9896,lb,barrels -CA,KER,N/A,DUCTBURNER,4.9896,lb,barrels -CA,KER,N/A,OTHER,4.9896,lb,barrels -CT,KER,N/A,DUCTBURNER,4.9896,lb,barrels -CT,KER,N/A,N/A,4.9896,lb,barrels -CT,KER,N/A,OTHER,4.9896,lb,barrels -GT,KER,N/A,CT,4.9896,lb,barrels -GT,KER,N/A,N/A,4.9896,lb,barrels -ST,KER,N/A,N/A,1.008,lb,barrels -CA,LFG,N/A,N/A,0.144,lb,mcf -CS,LFG,N/A,N/A,0.144,lb,mcf -CT,LFG,N/A,N/A,0.144,lb,mcf -FC,LFG,N/A,N/A,,lb,mcf -GT,LFG,N/A,N/A,0.144,lb,mcf -IC,LFG,N/A,N/A,1.21522,lb,mcf -ST,LFG,N/A,N/A,0.07244,lb,mcf -ST,LFG,DRY,WALL,0.07244,lb,mcf -ST,LFG,N/A,WALL,0.07244,lb,mcf -ST,LIG,WET,CYCLONE,15,lb,ton -ST,LIG,DRY,FLUIDIZED,3.6,lb,ton -ST,LIG,N/A,FLUIDIZED,3.6,lb,ton -ST,LIG,WET,FLUIDIZED,3.6,lb,ton -ST,LIG,N/A,N/A,6.3,lb,ton -ST,LIG,DRY,STOKER,5.8,lb,ton -ST,LIG,DRY,TANGENTIAL,7.1,lb,ton -ST,LIG,N/A,TANGENTIAL,7.1,lb,ton -ST,LIG,DRY,WALL,6.3,lb,ton -ST,MSB,N/A,N/A,5,lb,ton -ST,MSB,N/A,OTHER,5,lb,ton -ST,MSN,N/A,N/A,5,lb,ton -ST,MSN,N/A,OTHER,5,lb,ton -ST,MSW,N/A,N/A,5,lb,ton -ST,MSW,N/A,OTHER,5,lb,ton -CA,NG,N/A,CELLBURNER,0.328,lb,mcf -CA,NG,WET,CELLBURNER,0.328,lb,mcf -CA,NG,DRY,DUCTBURNER,0.328,lb,mcf -CA,NG,N/A,DUCTBURNER,0.328,lb,mcf -CA,NG,WET,DUCTBURNER,0.328,lb,mcf -CA,NG,N/A,N/A,0.32,lb,MMBtu -CA,NG,DRY,OTHER,0.328,lb,mcf -CA,NG,N/A,OTHER,0.328,lb,mcf -CA,NG,N/A,TANGENTIAL,0.328,lb,mcf -CA,NG,DRY,WALL,0.328,lb,mcf -CA,NG,N/A,WALL,0.328,lb,mcf -CE,NG,N/A,N/A,0.328,lb,mcf -CS,NG,DRY,DUCTBURNER,0.328,lb,mcf -CS,NG,N/A,DUCTBURNER,0.328,lb,mcf -CS,NG,N/A,N/A,0.32,lb,MMBtu -CS,NG,DRY,OTHER,0.328,lb,mcf -CS,NG,N/A,OTHER,0.328,lb,mcf -CT,NG,N/A,CC,0.328,lb,mcf -CT,NG,N/A,CELLBURNER,0.328,lb,mcf -CT,NG,WET,CELLBURNER,0.328,lb,mcf -CT,NG,DRY,DUCTBURNER,0.328,lb,mcf -CT,NG,N/A,DUCTBURNER,0.328,lb,mcf -CT,NG,WET,DUCTBURNER,0.328,lb,mcf -CT,NG,N/A,N/A,0.328,lb,mcf -CT,NG,DRY,OTHER,0.328,lb,mcf -CT,NG,N/A,OTHER,0.328,lb,mcf -CT,NG,N/A,TANGENTIAL,0.328,lb,mcf -CT,NG,DRY,WALL,0.328,lb,mcf -CT,NG,N/A,WALL,0.328,lb,mcf -FC,NG,N/A,N/A,,lb,mcf -GT,NG,N/A,CT,0.328,lb,mcf -GT,NG,N/A,N/A,0.32,lb,MMBtu -GT,NG,N/A,TANGENTIAL,0.328,lb,mcf -IC,NG,N/A,N/A,2.768,lb,mcf -OT,NG,N/A,N/A,0.28,lb,mcf -ST,NG,DRY,CELLBURNER,0.28,lb,mcf -ST,NG,DRY,CYCLONE,0.28,lb,mcf -ST,NG,N/A,CYCLONE,0.28,lb,mcf -ST,NG,WET,CYCLONE,0.28,lb,mcf -ST,NG,DRY,DUCTBURNER,0.28,lb,mcf -ST,NG,N/A,DUCTBURNER,0.28,lb,mcf -ST,NG,WET,DUCTBURNER,0.28,lb,mcf -ST,NG,DRY,FLUIDIZED,0.28,lb,mcf -ST,NG,N/A,FLUIDIZED,0.28,lb,mcf -ST,NG,WET,FLUIDIZED,0.28,lb,mcf -ST,NG,DRY,N/A,0.28,lb,mcf -ST,NG,N/A,N/A,0.28,lb,mcf -ST,NG,WET,N/A,0.28,lb,mcf -ST,NG,DRY,OTHER,0.28,lb,mcf -ST,NG,N/A,OTHER,0.28,lb,mcf -ST,NG,WET,OTHER,0.28,lb,mcf -ST,NG,DRY,STOKER,0.28,lb,mcf -ST,NG,N/A,STOKER,0.28,lb,mcf -ST,NG,WET,STOKER,0.28,lb,mcf -ST,NG,DRY,TANGENTIAL,0.17,lb,mcf -ST,NG,N/A,TANGENTIAL,0.17,lb,mcf -ST,NG,WET,TANGENTIAL,0.17,lb,mcf -ST,NG,DRY,VERTICAL,0.28,lb,mcf -ST,NG,WET,VERTICAL,0.28,lb,mcf -ST,NG,DRY,WALL,0.28,lb,mcf -ST,NG,N/A,WALL,0.28,lb,mcf -ST,NG,WET,WALL,0.28,lb,mcf -CA,OBG,N/A,DUCTBURNER,0.3136,lb,mcf -CA,OBG,N/A,N/A,0.3136,lb,mcf -CS,OBG,N/A,N/A,0.3136,lb,mcf -CT,OBG,N/A,DUCTBURNER,0.3136,lb,mcf -CT,OBG,N/A,N/A,0.3136,lb,mcf -FC,OBG,N/A,N/A,,lb,mcf -GT,OBG,N/A,N/A,0.3136,lb,mcf -IC,OBG,N/A,N/A,2.64648,lb,mcf -ST,OBG,N/A,N/A,0.11283,lb,mcf -ST,OBG,N/A,WALL,0.11283,lb,mcf -CA,OBL,N/A,N/A,4.7166,lb,barrels -CT,OBL,N/A,N/A,4.7166,lb,barrels -GT,OBL,N/A,N/A,4.7166,lb,barrels -IC,OBL,N/A,N/A,17.1486,lb,barrels -ST,OBL,N/A,OTHER,0.798,lb,barrels -ST,OBL,DRY,TANGENTIAL,0.798,lb,barrels -ST,OBL,N/A,DUCTBURNER,0.798,lb,barrels -ST,OBL,N/A,N/A,0.798,lb,barrels -ST,OBL,DRY,WALL,0.798,lb,barrels -ST,OBS,DRY,FLUIDIZED,2,lb,ton -ST,OBS,N/A,FLUIDIZED,2,lb,ton -ST,OBS,N/A,N/A,2,lb,ton -ST,OBS,N/A,STOKER,2,lb,ton -ST,OBS,DRY,TANGENTIAL,2,lb,ton -ST,OBS,DRY,WALL,2,lb,ton -CA,OG,DRY,DUCTBURNER,0.26382,lb,mcf -CA,OG,N/A,DUCTBURNER,0.26382,lb,mcf -CA,OG,N/A,N/A,0.26382,lb,mcf -CA,OG,N/A,OTHER,0.26382,lb,mcf -CA,OG,DRY,WALL,0.26382,lb,mcf -CA,OG,N/A,WALL,0.26382,lb,mcf -CS,OG,N/A,N/A,0.26382,lb,mcf -CT,OG,DRY,DUCTBURNER,0.26382,lb,mcf -CT,OG,N/A,DUCTBURNER,0.26382,lb,mcf -CT,OG,N/A,N/A,0.26382,lb,mcf -CT,OG,N/A,OTHER,0.26382,lb,mcf -GT,OG,N/A,CT,0.26382,lb,mcf -GT,OG,N/A,N/A,0.26382,lb,mcf -IC,OG,N/A,N/A,2.22641,lb,mcf -OT,OG,N/A,N/A,0.15282,lb,mcf -ST,OG,N/A,CYCLONE,0.15282,lb,mcf -ST,OG,DRY,DUCTBURNER,0.15282,lb,mcf -ST,OG,N/A,DUCTBURNER,0.15282,lb,mcf -ST,OG,WET,DUCTBURNER,0.15282,lb,mcf -ST,OG,N/A,N/A,0.15282,lb,mcf -ST,OG,N/A,OTHER,0.15282,lb,mcf -ST,OG,DRY,STOKER,0.15282,lb,mcf -ST,OG,DRY,TANGENTIAL,0.15282,lb,mcf -ST,OG,N/A,TANGENTIAL,0.15282,lb,mcf -ST,OG,DRY,WALL,0.15282,lb,mcf -ST,OG,N/A,WALL,0.15282,lb,mcf -ST,OG,WET,WALL,0.15282,lb,mcf -CA,OTH,DRY,DUCTBURNER,0.328,lb,mcf -CA,OTH,N/A,DUCTBURNER,0.328,lb,mcf -CA,OTH,N/A,N/A,0.328,lb,mcf -CA,OTH,DRY,WALL,0.328,lb,mcf -CS,OTH,N/A,DUCTBURNER,0.328,lb,mcf -CS,OTH,N/A,N/A,0.328,lb,mcf -CT,OTH,N/A,CC,0.328,lb,mcf -CT,OTH,N/A,DUCTBURNER,0.328,lb,mcf -CT,OTH,N/A,N/A,0.328,lb,mcf -GT,OTH,N/A,CT,0.328,lb,mcf -GT,OTH,N/A,N/A,0.328,lb,mcf -GT,OTH,N/A,TANGENTIAL,0.328,lb,mcf -IC,OTH,N/A,N/A,2.768,lb,mcf -OT,OTH,N/A,N/A,0.328,lb,mcf -ST,OTH,DRY,CYCLONE,0.28,lb,mcf -ST,OTH,N/A,CYCLONE,0.28,lb,mcf -ST,OTH,WET,CYCLONE,0.28,lb,mcf -ST,OTH,DRY,DUCTBURNER,0.17,lb,mcf -ST,OTH,N/A,DUCTBURNER,0.17,lb,mcf -ST,OTH,N/A,FLUIDIZED,0.28,lb,mcf -ST,OTH,N/A,N/A,0.17,lb,mcf -ST,OTH,N/A,OTHER,0.17,lb,mcf -ST,OTH,DRY,STOKER,0.28,lb,mcf -ST,OTH,N/A,STOKER,0.28,lb,mcf -ST,OTH,DRY,TANGENTIAL,0.17,lb,mcf -ST,OTH,N/A,TANGENTIAL,0.17,lb,mcf -ST,OTH,DRY,VERTICAL,0.28,lb,mcf -ST,OTH,DRY,WALL,0.28,lb,mcf -ST,OTH,N/A,WALL,0.28,lb,mcf -CA,PC,N/A,OTHER,21,lb,ton -OT,PC,N/A,N/A,21,lb,ton -ST,PC,DRY,FLUIDIZED,5,lb,ton -ST,PC,N/A,FLUIDIZED,5,lb,ton -ST,PC,WET,FLUIDIZED,5,lb,ton -ST,PC,N/A,N/A,21,lb,ton -ST,PC,N/A,OTHER,21,lb,ton -ST,PC,DRY,TANGENTIAL,21,lb,ton -ST,PC,DRY,WALL,21,lb,ton -ST,PC,WET,WALL,21,lb,ton -ST,PC,WET,CYCLONE,21,lb,ton -ST,PC,WET,OTHER,21,lb,ton -ST,PC,WET,TANGENTIAL,21,lb,ton -ST,PC,N/A,WALL,21,lb,ton -CS,PG,N/A,N/A,0.80336,lb,mcf -CT,PG,N/A,CC,0.80336,lb,mcf -GT,PG,N/A,N/A,0.80336,lb,mcf -IC,PG,N/A,N/A,6.77957,lb,mcf -ST,PG,N/A,CYCLONE,0.52226,lb,mcf -ST,PG,DRY,FLUIDIZED,0.52226,lb,mcf -ST,PG,N/A,N/A,0.52226,lb,mcf -ST,PG,N/A,TANGENTIAL,0.52226,lb,mcf -ST,PG,DRY,WALL,0.52226,lb,mcf -ST,PG,N/A,WALL,0.52226,lb,mcf -ST,PG,DRY,TANGENTIAL,0.52226,lb,mcf -ST,PG,WET,TANGENTIAL,0.52226,lb,mcf -GT,PRG,N/A,N/A,0.17,lb,mcf -ST,PRG,N/A,DUCTBURNER,0.17,lb,mcf -ST,PRG,N/A,N/A,0.17,lb,mcf -ST,PRG,N/A,OTHER,0.17,lb,mcf -ST,PRG,N/A,TANGENTIAL,0.17,lb,mcf -ST,PRG,DRY,WALL,0.28,lb,mcf -ST,PRG,N/A,WALL,0.28,lb,mcf -ST,RC,WET,CYCLONE,33,lb,ton -ST,RC,DRY,FLUIDIZED,5,lb,ton -ST,RC,N/A,N/A,12,lb,ton -ST,RC,DRY,STOKER,11,lb,ton -ST,RC,DRY,TANGENTIAL,10,lb,ton -ST,RC,WET,TANGENTIAL,14,lb,ton -ST,RC,DRY,WALL,12,lb,ton -ST,RC,N/A,WALL,12,lb,ton -ST,RC,WET,WALL,31,lb,ton -CA,RFO,N/A,N/A,5.5314,lb,barrels -CS,RFO,N/A,N/A,5.5314,lb,barrels -CT,RFO,N/A,N/A,5.5314,lb,barrels -GT,RFO,N/A,N/A,5.5314,lb,barrels -IC,RFO,N/A,N/A,20.118,lb,barrels -ST,RFO,DRY,CYCLONE,1.974,lb,barrels -ST,RFO,N/A,DUCTBURNER,1.974,lb,barrels -ST,RFO,DRY,FLUIDIZED,1.974,lb,barrels -ST,RFO,WET,FLUIDIZED,1.974,lb,barrels -ST,RFO,N/A,N/A,1.974,lb,barrels -ST,RFO,DRY,OTHER,1.974,lb,barrels -ST,RFO,N/A,OTHER,1.974,lb,barrels -ST,RFO,DRY,STOKER,1.974,lb,barrels -ST,RFO,WET,STOKER,1.974,lb,barrels -ST,RFO,DRY,TANGENTIAL,1.344,lb,barrels -ST,RFO,N/A,TANGENTIAL,1.344,lb,barrels -ST,RFO,WET,TANGENTIAL,1.344,lb,barrels -ST,RFO,DRY,VERTICAL,1.974,lb,barrels -ST,RFO,DRY,WALL,1.974,lb,barrels -ST,RFO,N/A,WALL,1.974,lb,barrels -ST,RFO,WET,WALL,1.974,lb,barrels -CA,SGC,N/A,DUCTBURNER,0.28,lb,mcf -CA,SGC,N/A,OTHER,0.28,lb,mcf -CT,SGC,N/A,DUCTBURNER,0.328,lb,mcf -CT,SGC,N/A,OTHER,0.328,lb,mcf -ST,SGC,N/A,N/A,0.28,lb,mcf -CA,SGP,N/A,N/A,0.28,lb,mcf -CS,SGP,N/A,N/A,0.28,lb,mcf -CT,SGP,N/A,N/A,0.28,lb,mcf -ST,SLW,DRY,FLUIDIZED,5,lb,ton -ST,SLW,WET,FLUIDIZED,5,lb,ton -ST,SLW,N/A,N/A,5,lb,ton -ST,SLW,N/A,OTHER,5,lb,ton -ST,SLW,DRY,STOKER,5,lb,ton -ST,SLW,WET,STOKER,5,lb,ton -ST,SLW,DRY,TANGENTIAL,5,lb,ton -ST,SLW,DRY,WALL,5,lb,ton -ST,SLW,N/A,WALL,5,lb,ton -ST,SLW,WET,WALL,5,lb,ton -ST,SUB,N/A,CYCLONE,17,lb,ton -ST,SUB,WET,CYCLONE,17,lb,ton -ST,SUB,DRY,FLUIDIZED,5,lb,ton -ST,SUB,N/A,FLUIDIZED,5,lb,ton -ST,SUB,WET,FLUIDIZED,5,lb,ton -ST,SUB,N/A,N/A,5,lb,ton -ST,SUB,DRY,STOKER,8.8,lb,ton -ST,SUB,N/A,STOKER,8.8,lb,ton -ST,SUB,DRY,TANGENTIAL,7.2,lb,ton -ST,SUB,N/A,TANGENTIAL,7.2,lb,ton -ST,SUB,WET,TANGENTIAL,7.2,lb,ton -ST,SUB,WET,VERTICAL,24,lb,ton -ST,SUB,DRY,WALL,7.4,lb,ton -ST,SUB,N/A,WALL,7.4,lb,ton -ST,SUB,WET,WALL,24,lb,ton -ST,TDF,N/A,CYCLONE,33,lb,ton -ST,TDF,N/A,DUCTBURNER,12,lb,ton -ST,TDF,DRY,FLUIDIZED,5,lb,ton -ST,TDF,WET,FLUIDIZED,5,lb,ton -ST,TDF,N/A,N/A,5,lb,ton -ST,TDF,N/A,OTHER,5,lb,ton -ST,TDF,DRY,STOKER,11,lb,ton -ST,TDF,N/A,STOKER,11,lb,ton -ST,TDF,WET,STOKER,11,lb,ton -ST,TDF,DRY,TANGENTIAL,10,lb,ton -ST,TDF,WET,TANGENTIAL,14,lb,ton -ST,TDF,DRY,VERTICAL,12,lb,ton -ST,TDF,DRY,WALL,12,lb,ton -ST,TDF,N/A,WALL,12,lb,ton -ST,TDF,WET,CYCLONE,33,lb,ton -ST,WC,DRY,FLUIDIZED,3.6,lb,ton -ST,WC,N/A,FLUIDIZED,3.6,lb,ton -ST,WC,N/A,N/A,3.6,lb,ton -ST,WC,WET,TANGENTIAL,7.1,lb,ton -ST,WC,DRY,TANGENTIAL,7.1,lb,ton -ST,WDL,N/A,N/A,0.22806,lb,barrels -OT,WDS,N/A,N/A,2.51,lb,ton -OT,WDS,N/A,OTHER,2.51,lb,ton -ST,WDS,DRY,CELLBURNER,2.51,lb,ton -ST,WDS,N/A,CYCLONE,2.51,lb,ton -ST,WDS,N/A,DUCTBURNER,2.51,lb,ton -ST,WDS,DRY,FLUIDIZED,2,lb,ton -ST,WDS,N/A,FLUIDIZED,2,lb,ton -ST,WDS,WET,FLUIDIZED,2,lb,ton -ST,WDS,DRY,N/A,2.51,lb,ton -ST,WDS,N/A,N/A,2.51,lb,ton -ST,WDS,WET,N/A,2.51,lb,ton -ST,WDS,DRY,OTHER,2.51,lb,ton -ST,WDS,N/A,OTHER,2.51,lb,ton -ST,WDS,DRY,STOKER,1.5,lb,ton -ST,WDS,N/A,STOKER,1.5,lb,ton -ST,WDS,WET,STOKER,1.5,lb,ton -ST,WDS,DRY,TANGENTIAL,2.51,lb,ton -ST,WDS,N/A,TANGENTIAL,2.51,lb,ton -ST,WDS,WET,TANGENTIAL,2.51,lb,ton -ST,WDS,DRY,VERTICAL,2.51,lb,ton -ST,WDS,DRY,WALL,2.51,lb,ton -ST,WDS,N/A,WALL,2.51,lb,ton -ST,WDS,WET,WALL,2.51,lb,ton -CA,WO,N/A,DUCTBURNER,3.8724,lb,barrels -CA,WO,N/A,N/A,3.8724,lb,barrels -CS,WO,N/A,N/A,3.8724,lb,barrels -CT,WO,N/A,DUCTBURNER,3.8724,lb,barrels -CT,WO,N/A,N/A,3.8724,lb,barrels -GT,WO,N/A,N/A,3.8724,lb,barrels -IC,WO,N/A,N/A,14.0784,lb,barrels -ST,WO,N/A,DUCTBURNER,0.798,lb,barrels -ST,WO,DRY,FLUIDIZED,0.798,lb,barrels -ST,WO,WET,FLUIDIZED,0.798,lb,barrels -ST,WO,N/A,N/A,0.798,lb,barrels -ST,WO,DRY,TANGENTIAL,0.798,lb,barrels -ST,WO,WET,TANGENTIAL,0.798,lb,barrels -ST,WO,DRY,VERTICAL,0.798,lb,barrels -ST,WO,DRY,WALL,0.798,lb,barrels -ST,WO,N/A,WALL,0.798,lb,barrels +prime_mover_code,energy_source_code,wet_dry_bottom,boiler_firing_type,emission_factor,emission_factor_numerator,emission_factor_denominator +ST,AB,wet,cyclone_firing,1.2,lb,ton +ST,AB,none,none,1.2,lb,ton +ST,AB,dry,stoker,1.2,lb,ton +ST,AB,none,stoker,1.2,lb,ton +OT,BFG,none,none,0.0154,lb,mcf +ST,BFG,none,none,0.0154,lb,mcf +ST,BFG,none,tangential_firing,0.0154,lb,mcf +ST,BFG,dry,wall_fired,0.0154,lb,mcf +ST,BFG,none,wall_fired,0.0154,lb,mcf +CA,BIT,dry,duct_burner,12,lb,ton +CA,BIT,none,duct_burner,12,lb,ton +CA,BIT,wet,duct_burner,31,lb,ton +ST,BIT,dry,cell_burner,12,lb,ton +ST,BIT,dry,cyclone_firing,33,lb,ton +ST,BIT,none,cyclone_firing,33,lb,ton +ST,BIT,wet,cyclone_firing,33,lb,ton +ST,BIT,dry,fluidized_bed_firing,5,lb,ton +ST,BIT,none,fluidized_bed_firing,5,lb,ton +ST,BIT,wet,fluidized_bed_firing,5,lb,ton +ST,BIT,none,none,31,lb,ton +ST,BIT,dry,none,12,lb,ton +ST,BIT,wet,none,31,lb,ton +ST,BIT,dry,other,12,lb,ton +ST,BIT,none,other,12,lb,ton +ST,BIT,wet,other,31,lb,ton +ST,BIT,dry,stoker,11,lb,ton +ST,BIT,none,stoker,11,lb,ton +ST,BIT,wet,stoker,11,lb,ton +ST,BIT,dry,tangential_firing,10,lb,ton +ST,BIT,none,tangential_firing,10,lb,ton +ST,BIT,wet,tangential_firing,14,lb,ton +ST,BIT,dry,vertical_firing,12,lb,ton +ST,BIT,wet,vertical_firing,31,lb,ton +ST,BIT,dry,wall_fired,12,lb,ton +ST,BIT,none,wall_fired,12,lb,ton +ST,BIT,wet,wall_fired,31,lb,ton +ST,BLQ,dry,cell_burner,1.5,lb,ton +ST,BLQ,none,cyclone_firing,1.5,lb,ton +ST,BLQ,none,duct_burner,1.5,lb,ton +ST,BLQ,dry,fluidized_bed_firing,1.5,lb,ton +ST,BLQ,none,fluidized_bed_firing,1.5,lb,ton +ST,BLQ,wet,fluidized_bed_firing,1.5,lb,ton +ST,BLQ,none,none,1.5,lb,ton +ST,BLQ,dry,none,1.5,lb,ton +ST,BLQ,wet,none,1.5,lb,ton +ST,BLQ,dry,other,1.5,lb,ton +ST,BLQ,none,other,1.5,lb,ton +ST,BLQ,dry,stoker,1.5,lb,ton +ST,BLQ,none,stoker,1.5,lb,ton +ST,BLQ,wet,stoker,1.5,lb,ton +ST,BLQ,dry,tangential_firing,1.5,lb,ton +ST,BLQ,none,tangential_firing,1.5,lb,ton +ST,BLQ,wet,tangential_firing,1.5,lb,ton +ST,BLQ,dry,vertical_firing,1.5,lb,ton +ST,BLQ,dry,wall_fired,1.5,lb,ton +ST,BLQ,none,wall_fired,1.5,lb,ton +ST,BLQ,wet,wall_fired,1.5,lb,ton +OT,COG,none,none,0.0154,lb,mcf +ST,COG,none,cyclone_firing,0.0154,lb,mcf +ST,COG,none,none,0.0154,lb,mcf +ST,COG,none,wall_fired,0.0154,lb,mcf +CA,DFO,none,cell_burner,5.124,lb,barrels +CA,DFO,dry,duct_burner,5.124,lb,barrels +CA,DFO,none,duct_burner,5.124,lb,barrels +CA,DFO,none,none,5.124,lb,barrels +CA,DFO,none,other,5.124,lb,barrels +CA,DFO,dry,other,5.124,lb,barrels +CA,DFO,none,wall_fired,5.124,lb,barrels +CS,DFO,none,none,5.124,lb,barrels +CT,DFO,none,CC,5.124,lb,barrels +CT,DFO,none,cell_burner,5.124,lb,barrels +CT,DFO,dry,duct_burner,5.124,lb,barrels +CT,DFO,none,duct_burner,5.124,lb,barrels +CT,DFO,none,none,5.124,lb,barrels +CT,DFO,dry,other,5.124,lb,barrels +CT,DFO,none,other,5.124,lb,barrels +CT,DFO,none,tangential_firing,5.124,lb,barrels +CT,DFO,none,wall_fired,5.124,lb,barrels +GT,DFO,none,CT,5.124,lb,barrels +GT,DFO,none,none,5.124,lb,barrels +IC,DFO,none,none,18.6396,lb,barrels +ST,DFO,dry,cell_burner,1.008,lb,barrels +ST,DFO,dry,cyclone_firing,1.008,lb,barrels +ST,DFO,none,cyclone_firing,1.008,lb,barrels +ST,DFO,wet,cyclone_firing,1.008,lb,barrels +ST,DFO,none,duct_burner,1.008,lb,barrels +ST,DFO,dry,fluidized_bed_firing,1.008,lb,barrels +ST,DFO,none,fluidized_bed_firing,1.008,lb,barrels +ST,DFO,wet,fluidized_bed_firing,1.008,lb,barrels +ST,DFO,dry,none,1.008,lb,barrels +ST,DFO,none,none,1.008,lb,barrels +ST,DFO,wet,none,1.008,lb,barrels +ST,DFO,dry,other,1.008,lb,barrels +ST,DFO,none,other,1.008,lb,barrels +ST,DFO,dry,stoker,1.008,lb,barrels +ST,DFO,dry,tangential_firing,1.008,lb,barrels +ST,DFO,none,tangential_firing,1.008,lb,barrels +ST,DFO,wet,tangential_firing,1.008,lb,barrels +ST,DFO,dry,vertical_firing,1.008,lb,barrels +ST,DFO,dry,wall_fired,1.008,lb,barrels +ST,DFO,none,wall_fired,1.008,lb,barrels +ST,DFO,wet,wall_fired,1.008,lb,barrels +BT,GEO,none,none,0,lb,MMBtu +ST,GEO,none,none,0.000305,lb,MMBtu +GT,JF,none,CT,4.9896,lb,barrels +GT,JF,none,none,4.9896,lb,barrels +IC,JF,none,none,18.144,lb,barrels +ST,JF,none,none,1.008,lb,barrels +CA,KER,none,none,4.9896,lb,barrels +CA,KER,none,duct_burner,4.9896,lb,barrels +CA,KER,none,other,4.9896,lb,barrels +CT,KER,none,duct_burner,4.9896,lb,barrels +CT,KER,none,none,4.9896,lb,barrels +CT,KER,none,other,4.9896,lb,barrels +GT,KER,none,CT,4.9896,lb,barrels +GT,KER,none,none,4.9896,lb,barrels +ST,KER,none,none,1.008,lb,barrels +CA,LFG,none,none,0.144,lb,mcf +CS,LFG,none,none,0.144,lb,mcf +CT,LFG,none,none,0.144,lb,mcf +FC,LFG,none,none,,lb,mcf +GT,LFG,none,none,0.144,lb,mcf +IC,LFG,none,none,1.21522,lb,mcf +ST,LFG,none,none,0.07244,lb,mcf +ST,LFG,dry,wall_fired,0.07244,lb,mcf +ST,LFG,none,wall_fired,0.07244,lb,mcf +ST,LIG,wet,cyclone_firing,15,lb,ton +ST,LIG,dry,fluidized_bed_firing,3.6,lb,ton +ST,LIG,none,fluidized_bed_firing,3.6,lb,ton +ST,LIG,wet,fluidized_bed_firing,3.6,lb,ton +ST,LIG,none,none,6.3,lb,ton +ST,LIG,dry,stoker,5.8,lb,ton +ST,LIG,dry,tangential_firing,7.1,lb,ton +ST,LIG,none,tangential_firing,7.1,lb,ton +ST,LIG,dry,wall_fired,6.3,lb,ton +ST,MSB,none,none,5,lb,ton +ST,MSB,none,other,5,lb,ton +ST,MSN,none,none,5,lb,ton +ST,MSN,none,other,5,lb,ton +ST,MSW,none,none,5,lb,ton +ST,MSW,none,other,5,lb,ton +CA,NG,none,cell_burner,0.328,lb,mcf +CA,NG,wet,cell_burner,0.328,lb,mcf +CA,NG,dry,duct_burner,0.328,lb,mcf +CA,NG,none,duct_burner,0.328,lb,mcf +CA,NG,wet,duct_burner,0.328,lb,mcf +CA,NG,none,none,0.32,lb,MMBtu +CA,NG,dry,other,0.328,lb,mcf +CA,NG,none,other,0.328,lb,mcf +CA,NG,none,tangential_firing,0.328,lb,mcf +CA,NG,dry,wall_fired,0.328,lb,mcf +CA,NG,none,wall_fired,0.328,lb,mcf +CE,NG,none,none,0.328,lb,mcf +CS,NG,dry,duct_burner,0.328,lb,mcf +CS,NG,none,duct_burner,0.328,lb,mcf +CS,NG,none,none,0.32,lb,MMBtu +CS,NG,dry,other,0.328,lb,mcf +CS,NG,none,other,0.328,lb,mcf +CT,NG,none,CC,0.328,lb,mcf +CT,NG,none,cell_burner,0.328,lb,mcf +CT,NG,wet,cell_burner,0.328,lb,mcf +CT,NG,dry,duct_burner,0.328,lb,mcf +CT,NG,none,duct_burner,0.328,lb,mcf +CT,NG,wet,duct_burner,0.328,lb,mcf +CT,NG,none,none,0.328,lb,mcf +CT,NG,dry,other,0.328,lb,mcf +CT,NG,none,other,0.328,lb,mcf +CT,NG,none,tangential_firing,0.328,lb,mcf +CT,NG,dry,wall_fired,0.328,lb,mcf +CT,NG,none,wall_fired,0.328,lb,mcf +FC,NG,none,none,,lb,mcf +GT,NG,none,CT,0.328,lb,mcf +GT,NG,none,none,0.32,lb,MMBtu +GT,NG,none,tangential_firing,0.328,lb,mcf +IC,NG,none,none,2.768,lb,mcf +OT,NG,none,none,0.28,lb,mcf +ST,NG,dry,cell_burner,0.28,lb,mcf +ST,NG,dry,cyclone_firing,0.28,lb,mcf +ST,NG,none,cyclone_firing,0.28,lb,mcf +ST,NG,wet,cyclone_firing,0.28,lb,mcf +ST,NG,dry,duct_burner,0.28,lb,mcf +ST,NG,none,duct_burner,0.28,lb,mcf +ST,NG,wet,duct_burner,0.28,lb,mcf +ST,NG,dry,fluidized_bed_firing,0.28,lb,mcf +ST,NG,none,fluidized_bed_firing,0.28,lb,mcf +ST,NG,wet,fluidized_bed_firing,0.28,lb,mcf +ST,NG,dry,none,0.28,lb,mcf +ST,NG,none,none,0.28,lb,mcf +ST,NG,wet,none,0.28,lb,mcf +ST,NG,dry,other,0.28,lb,mcf +ST,NG,none,other,0.28,lb,mcf +ST,NG,wet,other,0.28,lb,mcf +ST,NG,dry,stoker,0.28,lb,mcf +ST,NG,none,stoker,0.28,lb,mcf +ST,NG,wet,stoker,0.28,lb,mcf +ST,NG,dry,tangential_firing,0.17,lb,mcf +ST,NG,none,tangential_firing,0.17,lb,mcf +ST,NG,wet,tangential_firing,0.17,lb,mcf +ST,NG,dry,vertical_firing,0.28,lb,mcf +ST,NG,wet,vertical_firing,0.28,lb,mcf +ST,NG,dry,wall_fired,0.28,lb,mcf +ST,NG,none,wall_fired,0.28,lb,mcf +ST,NG,wet,wall_fired,0.28,lb,mcf +CA,OBG,none,duct_burner,0.3136,lb,mcf +CA,OBG,none,none,0.3136,lb,mcf +CS,OBG,none,none,0.3136,lb,mcf +CT,OBG,none,duct_burner,0.3136,lb,mcf +CT,OBG,none,none,0.3136,lb,mcf +FC,OBG,none,none,,lb,mcf +GT,OBG,none,none,0.3136,lb,mcf +IC,OBG,none,none,2.64648,lb,mcf +ST,OBG,none,none,0.11283,lb,mcf +ST,OBG,none,wall_fired,0.11283,lb,mcf +CA,OBL,none,none,4.7166,lb,barrels +CT,OBL,none,none,4.7166,lb,barrels +GT,OBL,none,none,4.7166,lb,barrels +IC,OBL,none,none,17.1486,lb,barrels +ST,OBL,none,other,0.798,lb,barrels +ST,OBL,dry,tangential_firing,0.798,lb,barrels +ST,OBL,none,duct_burner,0.798,lb,barrels +ST,OBL,none,none,0.798,lb,barrels +ST,OBL,dry,wall_fired,0.798,lb,barrels +ST,OBS,dry,fluidized_bed_firing,2,lb,ton +ST,OBS,none,fluidized_bed_firing,2,lb,ton +ST,OBS,none,none,2,lb,ton +ST,OBS,none,stoker,2,lb,ton +ST,OBS,dry,tangential_firing,2,lb,ton +ST,OBS,dry,wall_fired,2,lb,ton +CA,OG,dry,duct_burner,0.26382,lb,mcf +CA,OG,none,duct_burner,0.26382,lb,mcf +CA,OG,none,none,0.26382,lb,mcf +CA,OG,none,other,0.26382,lb,mcf +CA,OG,dry,wall_fired,0.26382,lb,mcf +CA,OG,none,wall_fired,0.26382,lb,mcf +CS,OG,none,none,0.26382,lb,mcf +CT,OG,dry,duct_burner,0.26382,lb,mcf +CT,OG,none,duct_burner,0.26382,lb,mcf +CT,OG,none,none,0.26382,lb,mcf +CT,OG,none,other,0.26382,lb,mcf +GT,OG,none,CT,0.26382,lb,mcf +GT,OG,none,none,0.26382,lb,mcf +IC,OG,none,none,2.22641,lb,mcf +OT,OG,none,none,0.15282,lb,mcf +ST,OG,none,cyclone_firing,0.15282,lb,mcf +ST,OG,dry,duct_burner,0.15282,lb,mcf +ST,OG,none,duct_burner,0.15282,lb,mcf +ST,OG,wet,duct_burner,0.15282,lb,mcf +ST,OG,none,none,0.15282,lb,mcf +ST,OG,none,other,0.15282,lb,mcf +ST,OG,dry,stoker,0.15282,lb,mcf +ST,OG,dry,tangential_firing,0.15282,lb,mcf +ST,OG,none,tangential_firing,0.15282,lb,mcf +ST,OG,dry,wall_fired,0.15282,lb,mcf +ST,OG,none,wall_fired,0.15282,lb,mcf +ST,OG,wet,wall_fired,0.15282,lb,mcf +CA,OTH,dry,duct_burner,0.328,lb,mcf +CA,OTH,none,duct_burner,0.328,lb,mcf +CA,OTH,none,none,0.328,lb,mcf +CA,OTH,dry,wall_fired,0.328,lb,mcf +CS,OTH,none,duct_burner,0.328,lb,mcf +CS,OTH,none,none,0.328,lb,mcf +CT,OTH,none,CC,0.328,lb,mcf +CT,OTH,none,duct_burner,0.328,lb,mcf +CT,OTH,none,none,0.328,lb,mcf +GT,OTH,none,CT,0.328,lb,mcf +GT,OTH,none,none,0.328,lb,mcf +GT,OTH,none,tangential_firing,0.328,lb,mcf +IC,OTH,none,none,2.768,lb,mcf +OT,OTH,none,none,0.328,lb,mcf +ST,OTH,dry,cyclone_firing,0.28,lb,mcf +ST,OTH,none,cyclone_firing,0.28,lb,mcf +ST,OTH,wet,cyclone_firing,0.28,lb,mcf +ST,OTH,dry,duct_burner,0.17,lb,mcf +ST,OTH,none,duct_burner,0.17,lb,mcf +ST,OTH,none,fluidized_bed_firing,0.28,lb,mcf +ST,OTH,none,none,0.17,lb,mcf +ST,OTH,none,other,0.17,lb,mcf +ST,OTH,dry,stoker,0.28,lb,mcf +ST,OTH,none,stoker,0.28,lb,mcf +ST,OTH,dry,tangential_firing,0.17,lb,mcf +ST,OTH,none,tangential_firing,0.17,lb,mcf +ST,OTH,dry,vertical_firing,0.28,lb,mcf +ST,OTH,dry,wall_fired,0.28,lb,mcf +ST,OTH,none,wall_fired,0.28,lb,mcf +CA,PC,none,other,21,lb,ton +OT,PC,none,none,21,lb,ton +ST,PC,dry,fluidized_bed_firing,5,lb,ton +ST,PC,none,fluidized_bed_firing,5,lb,ton +ST,PC,wet,fluidized_bed_firing,5,lb,ton +ST,PC,none,none,21,lb,ton +ST,PC,none,other,21,lb,ton +ST,PC,dry,tangential_firing,21,lb,ton +ST,PC,dry,wall_fired,21,lb,ton +ST,PC,wet,wall_fired,21,lb,ton +ST,PC,wet,cyclone_firing,21,lb,ton +ST,PC,wet,other,21,lb,ton +ST,PC,wet,tangential_firing,21,lb,ton +ST,PC,none,wall_fired,21,lb,ton +CS,PG,none,none,0.80336,lb,mcf +CT,PG,none,CC,0.80336,lb,mcf +GT,PG,none,none,0.80336,lb,mcf +IC,PG,none,none,6.77957,lb,mcf +ST,PG,none,cyclone_firing,0.52226,lb,mcf +ST,PG,dry,fluidized_bed_firing,0.52226,lb,mcf +ST,PG,none,none,0.52226,lb,mcf +ST,PG,none,tangential_firing,0.52226,lb,mcf +ST,PG,dry,wall_fired,0.52226,lb,mcf +ST,PG,none,wall_fired,0.52226,lb,mcf +ST,PG,dry,tangential_firing,0.52226,lb,mcf +ST,PG,wet,tangential_firing,0.52226,lb,mcf +GT,PRG,none,none,0.17,lb,mcf +ST,PRG,none,duct_burner,0.17,lb,mcf +ST,PRG,none,none,0.17,lb,mcf +ST,PRG,none,other,0.17,lb,mcf +ST,PRG,none,tangential_firing,0.17,lb,mcf +ST,PRG,dry,wall_fired,0.28,lb,mcf +ST,PRG,none,wall_fired,0.28,lb,mcf +ST,RC,wet,cyclone_firing,33,lb,ton +ST,RC,dry,fluidized_bed_firing,5,lb,ton +ST,RC,none,none,12,lb,ton +ST,RC,dry,stoker,11,lb,ton +ST,RC,dry,tangential_firing,10,lb,ton +ST,RC,wet,tangential_firing,14,lb,ton +ST,RC,dry,wall_fired,12,lb,ton +ST,RC,none,wall_fired,12,lb,ton +ST,RC,wet,wall_fired,31,lb,ton +CA,RFO,none,none,5.5314,lb,barrels +CS,RFO,none,none,5.5314,lb,barrels +CT,RFO,none,none,5.5314,lb,barrels +GT,RFO,none,none,5.5314,lb,barrels +IC,RFO,none,none,20.118,lb,barrels +ST,RFO,dry,cyclone_firing,1.974,lb,barrels +ST,RFO,none,duct_burner,1.974,lb,barrels +ST,RFO,dry,fluidized_bed_firing,1.974,lb,barrels +ST,RFO,wet,fluidized_bed_firing,1.974,lb,barrels +ST,RFO,none,none,1.974,lb,barrels +ST,RFO,dry,other,1.974,lb,barrels +ST,RFO,none,other,1.974,lb,barrels +ST,RFO,dry,stoker,1.974,lb,barrels +ST,RFO,wet,stoker,1.974,lb,barrels +ST,RFO,dry,tangential_firing,1.344,lb,barrels +ST,RFO,none,tangential_firing,1.344,lb,barrels +ST,RFO,wet,tangential_firing,1.344,lb,barrels +ST,RFO,dry,vertical_firing,1.974,lb,barrels +ST,RFO,dry,wall_fired,1.974,lb,barrels +ST,RFO,none,wall_fired,1.974,lb,barrels +ST,RFO,wet,wall_fired,1.974,lb,barrels +CA,SGC,none,duct_burner,0.28,lb,mcf +CA,SGC,none,other,0.28,lb,mcf +CT,SGC,none,duct_burner,0.328,lb,mcf +CT,SGC,none,other,0.328,lb,mcf +ST,SGC,none,none,0.28,lb,mcf +CA,SGP,none,none,0.28,lb,mcf +CS,SGP,none,none,0.28,lb,mcf +CT,SGP,none,none,0.28,lb,mcf +ST,SLW,dry,fluidized_bed_firing,5,lb,ton +ST,SLW,wet,fluidized_bed_firing,5,lb,ton +ST,SLW,none,none,5,lb,ton +ST,SLW,none,other,5,lb,ton +ST,SLW,dry,stoker,5,lb,ton +ST,SLW,wet,stoker,5,lb,ton +ST,SLW,dry,tangential_firing,5,lb,ton +ST,SLW,dry,wall_fired,5,lb,ton +ST,SLW,none,wall_fired,5,lb,ton +ST,SLW,wet,wall_fired,5,lb,ton +ST,SUB,none,cyclone_firing,17,lb,ton +ST,SUB,wet,cyclone_firing,17,lb,ton +ST,SUB,dry,fluidized_bed_firing,5,lb,ton +ST,SUB,none,fluidized_bed_firing,5,lb,ton +ST,SUB,wet,fluidized_bed_firing,5,lb,ton +ST,SUB,none,none,5,lb,ton +ST,SUB,dry,stoker,8.8,lb,ton +ST,SUB,none,stoker,8.8,lb,ton +ST,SUB,dry,tangential_firing,7.2,lb,ton +ST,SUB,none,tangential_firing,7.2,lb,ton +ST,SUB,wet,tangential_firing,7.2,lb,ton +ST,SUB,wet,vertical_firing,24,lb,ton +ST,SUB,dry,wall_fired,7.4,lb,ton +ST,SUB,none,wall_fired,7.4,lb,ton +ST,SUB,wet,wall_fired,24,lb,ton +ST,TDF,none,cyclone_firing,33,lb,ton +ST,TDF,none,duct_burner,12,lb,ton +ST,TDF,dry,fluidized_bed_firing,5,lb,ton +ST,TDF,wet,fluidized_bed_firing,5,lb,ton +ST,TDF,none,none,5,lb,ton +ST,TDF,none,other,5,lb,ton +ST,TDF,dry,stoker,11,lb,ton +ST,TDF,none,stoker,11,lb,ton +ST,TDF,wet,stoker,11,lb,ton +ST,TDF,dry,tangential_firing,10,lb,ton +ST,TDF,wet,tangential_firing,14,lb,ton +ST,TDF,dry,vertical_firing,12,lb,ton +ST,TDF,dry,wall_fired,12,lb,ton +ST,TDF,none,wall_fired,12,lb,ton +ST,TDF,wet,cyclone_firing,33,lb,ton +ST,WC,dry,fluidized_bed_firing,3.6,lb,ton +ST,WC,none,fluidized_bed_firing,3.6,lb,ton +ST,WC,none,none,3.6,lb,ton +ST,WC,wet,tangential_firing,7.1,lb,ton +ST,WC,dry,tangential_firing,7.1,lb,ton +ST,WDL,none,none,0.22806,lb,barrels +OT,WDS,none,none,2.51,lb,ton +OT,WDS,none,other,2.51,lb,ton +ST,WDS,dry,cell_burner,2.51,lb,ton +ST,WDS,none,cyclone_firing,2.51,lb,ton +ST,WDS,none,duct_burner,2.51,lb,ton +ST,WDS,dry,fluidized_bed_firing,2,lb,ton +ST,WDS,none,fluidized_bed_firing,2,lb,ton +ST,WDS,wet,fluidized_bed_firing,2,lb,ton +ST,WDS,dry,none,2.51,lb,ton +ST,WDS,none,none,2.51,lb,ton +ST,WDS,wet,none,2.51,lb,ton +ST,WDS,dry,other,2.51,lb,ton +ST,WDS,none,other,2.51,lb,ton +ST,WDS,dry,stoker,1.5,lb,ton +ST,WDS,none,stoker,1.5,lb,ton +ST,WDS,wet,stoker,1.5,lb,ton +ST,WDS,dry,tangential_firing,2.51,lb,ton +ST,WDS,none,tangential_firing,2.51,lb,ton +ST,WDS,wet,tangential_firing,2.51,lb,ton +ST,WDS,dry,vertical_firing,2.51,lb,ton +ST,WDS,dry,wall_fired,2.51,lb,ton +ST,WDS,none,wall_fired,2.51,lb,ton +ST,WDS,wet,wall_fired,2.51,lb,ton +CA,WO,none,duct_burner,3.8724,lb,barrels +CA,WO,none,none,3.8724,lb,barrels +CS,WO,none,none,3.8724,lb,barrels +CT,WO,none,duct_burner,3.8724,lb,barrels +CT,WO,none,none,3.8724,lb,barrels +GT,WO,none,none,3.8724,lb,barrels +IC,WO,none,none,14.0784,lb,barrels +ST,WO,none,duct_burner,0.798,lb,barrels +ST,WO,dry,fluidized_bed_firing,0.798,lb,barrels +ST,WO,wet,fluidized_bed_firing,0.798,lb,barrels +ST,WO,none,none,0.798,lb,barrels +ST,WO,dry,tangential_firing,0.798,lb,barrels +ST,WO,wet,tangential_firing,0.798,lb,barrels +ST,WO,dry,vertical_firing,0.798,lb,barrels +ST,WO,dry,wall_fired,0.798,lb,barrels +ST,WO,none,wall_fired,0.798,lb,barrels diff --git a/data/manual/emission_factors_for_so2.csv b/data/manual/emission_factors_for_so2.csv index afdebfa4..d34ee2bd 100644 --- a/data/manual/emission_factors_for_so2.csv +++ b/data/manual/emission_factors_for_so2.csv @@ -1,1403 +1,1403 @@ prime_mover_code,energy_source_code,boiler_firing_type,emission_factor,emission_factor_numerator,emission_factor_denominator,multiply_by_sulfur_content -OT,AB,CELLBURNER,0.08,lb,short ton,0 -OT,AB,CYCLONE,0.08,lb,short ton,0 -OT,AB,DUCTBURNER,0.08,lb,short ton,0 -OT,AB,FLUIDIZED,0.01,lb,short ton,0 -OT,AB,N/A,0.08,lb,short ton,0 -OT,AB,OTHER,0.08,lb,short ton,0 -OT,AB,STOKER,0.08,lb,short ton,0 -OT,AB,TANGENTIAL,0.08,lb,short ton,0 -OT,AB,VERTICAL,0.08,lb,short ton,0 -OT,AB,WALL,0.08,lb,short ton,0 -ST,AB,CELLBURNER,0.08,lb,short ton,0 -ST,AB,CYCLONE,0.08,lb,short ton,0 -ST,AB,DUCTBURNER,0.08,lb,short ton,0 -ST,AB,FLUIDIZED,0.01,lb,short ton,0 -ST,AB,N/A,0.08,lb,short ton,0 -ST,AB,OTHER,0.08,lb,short ton,0 -ST,AB,STOKER,0.08,lb,short ton,0 -ST,AB,TANGENTIAL,0.08,lb,short ton,0 -ST,AB,VERTICAL,0.08,lb,short ton,0 -ST,AB,WALL,0.08,lb,short ton,0 -CA,BFG,CELLBURNER,0.0006,lb,Mcf,0 -CA,BFG,CYCLONE,0.0006,lb,Mcf,0 -CA,BFG,DUCTBURNER,0.0006,lb,Mcf,0 -CA,BFG,FLUIDIZED,0.0006,lb,Mcf,0 -CA,BFG,N/A,0.0006,lb,Mcf,0 -CA,BFG,OTHER,0.0006,lb,Mcf,0 -CA,BFG,STOKER,0.0006,lb,Mcf,0 -CA,BFG,TANGENTIAL,0.0006,lb,Mcf,0 -CA,BFG,VERTICAL,0.0006,lb,Mcf,0 -CA,BFG,WALL,0.0006,lb,Mcf,0 -CS,BFG,CELLBURNER,0.0006,lb,Mcf,0 -CS,BFG,CYCLONE,0.0006,lb,Mcf,0 -CS,BFG,DUCTBURNER,0.0006,lb,Mcf,0 -CS,BFG,FLUIDIZED,0.0006,lb,Mcf,0 -CS,BFG,N/A,0.0006,lb,Mcf,0 -CS,BFG,OTHER,0.0006,lb,Mcf,0 -CS,BFG,STOKER,0.0006,lb,Mcf,0 -CS,BFG,TANGENTIAL,0.0006,lb,Mcf,0 -CS,BFG,VERTICAL,0.0006,lb,Mcf,0 -CS,BFG,WALL,0.0006,lb,Mcf,0 -CT,BFG,CELLBURNER,0.0006,lb,Mcf,0 -CT,BFG,CYCLONE,0.0006,lb,Mcf,0 -CT,BFG,DUCTBURNER,0.0006,lb,Mcf,0 -CT,BFG,FLUIDIZED,0.0006,lb,Mcf,0 -CT,BFG,N/A,0.0006,lb,Mcf,0 -CT,BFG,OTHER,0.0006,lb,Mcf,0 -CT,BFG,STOKER,0.0006,lb,Mcf,0 -CT,BFG,TANGENTIAL,0.0006,lb,Mcf,0 -CT,BFG,VERTICAL,0.0006,lb,Mcf,0 -CT,BFG,WALL,0.0006,lb,Mcf,0 -GT,BFG,CELLBURNER,0.0006,lb,Mcf,0 -GT,BFG,CYCLONE,0.0006,lb,Mcf,0 -GT,BFG,DUCTBURNER,0.0006,lb,Mcf,0 -GT,BFG,FLUIDIZED,0.0006,lb,Mcf,0 -GT,BFG,N/A,0.0006,lb,Mcf,0 -GT,BFG,OTHER,0.0006,lb,Mcf,0 -GT,BFG,STOKER,0.0006,lb,Mcf,0 -GT,BFG,TANGENTIAL,0.0006,lb,Mcf,0 -GT,BFG,VERTICAL,0.0006,lb,Mcf,0 -GT,BFG,WALL,0.0006,lb,Mcf,0 -IC,BFG,CELLBURNER,0.0006,lb,Mcf,0 -IC,BFG,CYCLONE,0.0006,lb,Mcf,0 -IC,BFG,DUCTBURNER,0.0006,lb,Mcf,0 -IC,BFG,FLUIDIZED,0.0006,lb,Mcf,0 -IC,BFG,N/A,0.0006,lb,Mcf,0 -IC,BFG,OTHER,0.0006,lb,Mcf,0 -IC,BFG,STOKER,0.0006,lb,Mcf,0 -IC,BFG,TANGENTIAL,0.0006,lb,Mcf,0 -IC,BFG,VERTICAL,0.0006,lb,Mcf,0 -IC,BFG,WALL,0.0006,lb,Mcf,0 -OT,BFG,CELLBURNER,0.0006,lb,Mcf,0 -OT,BFG,CYCLONE,0.0006,lb,Mcf,0 -OT,BFG,DUCTBURNER,0.0006,lb,Mcf,0 -OT,BFG,FLUIDIZED,0.00006,lb,Mcf,0 -OT,BFG,N/A,0.0006,lb,Mcf,0 -OT,BFG,OTHER,0.0006,lb,Mcf,0 -OT,BFG,STOKER,0.0006,lb,Mcf,0 -OT,BFG,TANGENTIAL,0.0006,lb,Mcf,0 -OT,BFG,VERTICAL,0.0006,lb,Mcf,0 -OT,BFG,WALL,0.0006,lb,Mcf,0 -ST,BFG,CELLBURNER,0.0006,lb,Mcf,0 -ST,BFG,CYCLONE,0.0006,lb,Mcf,0 -ST,BFG,DUCTBURNER,0.0006,lb,Mcf,0 -ST,BFG,FLUIDIZED,0.00006,lb,Mcf,0 -ST,BFG,N/A,0.0006,lb,Mcf,0 -ST,BFG,OTHER,0.0006,lb,Mcf,0 -ST,BFG,STOKER,0.0006,lb,Mcf,0 -ST,BFG,TANGENTIAL,0.0006,lb,Mcf,0 -ST,BFG,VERTICAL,0.0006,lb,Mcf,0 -ST,BFG,WALL,0.0006,lb,Mcf,0 -CA,BIT,DUCTBURNER,38*S,lb,short ton,1 -OT,BIT,CELLBURNER,38*S,lb,short ton,1 -OT,BIT,CYCLONE,38*S,lb,short ton,1 -OT,BIT,DUCTBURNER,38*S,lb,short ton,1 -OT,BIT,FLUIDIZED,3.8*S,lb,short ton,1 -OT,BIT,N/A,38*S,lb,short ton,1 -OT,BIT,OTHER,38*S,lb,short ton,1 -OT,BIT,STOKER,38*S,lb,short ton,1 -OT,BIT,TANGENTIAL,38*S,lb,short ton,1 -OT,BIT,VERTICAL,38*S,lb,short ton,1 -OT,BIT,WALL,38*S,lb,short ton,1 -ST,BIT,CELLBURNER,38*S,lb,short ton,1 -ST,BIT,CYCLONE,38*S,lb,short ton,1 -ST,BIT,DUCTBURNER,38*S,lb,short ton,1 -ST,BIT,FLUIDIZED,3.8*S,lb,short ton,1 -ST,BIT,N/A,38*S,lb,short ton,1 -ST,BIT,OTHER,38*S,lb,short ton,1 -ST,BIT,STOKER,38*S,lb,short ton,1 -ST,BIT,TANGENTIAL,38*S,lb,short ton,1 -ST,BIT,VERTICAL,38*S,lb,short ton,1 -ST,BIT,WALL,38*S,lb,short ton,1 -OT,BLQ,CELLBURNER,7,lb,short ton,0 -OT,BLQ,CYCLONE,7,lb,short ton,0 -OT,BLQ,DUCTBURNER,7,lb,short ton,0 -OT,BLQ,FLUIDIZED,0.7,lb,short ton,0 -OT,BLQ,N/A,7,lb,short ton,0 -OT,BLQ,OTHER,7,lb,short ton,0 -OT,BLQ,STOKER,7,lb,short ton,0 -OT,BLQ,TANGENTIAL,7,lb,short ton,0 -OT,BLQ,VERTICAL,7,lb,short ton,0 -OT,BLQ,WALL,7,lb,short ton,0 -ST,BLQ,CELLBURNER,7,lb,short ton,0 -ST,BLQ,CYCLONE,7,lb,short ton,0 -ST,BLQ,DUCTBURNER,7,lb,short ton,0 -ST,BLQ,FLUIDIZED,0.7,lb,short ton,0 -ST,BLQ,N/A,7,lb,short ton,0 -ST,BLQ,OTHER,7,lb,short ton,0 -ST,BLQ,STOKER,7,lb,short ton,0 -ST,BLQ,TANGENTIAL,7,lb,short ton,0 -ST,BLQ,VERTICAL,7,lb,short ton,0 -ST,BLQ,WALL,7,lb,short ton,0 -CA,DFO,CELLBURNER,5.88*S,lb,barrel,1 -CA,DFO,CYCLONE,5.88*S,lb,barrel,1 -CA,DFO,DUCTBURNER,5.88*S,lb,barrel,1 -CA,DFO,FLUIDIZED,5.88*S,lb,barrel,1 -CA,DFO,N/A,5.88*S,lb,barrel,1 -CA,DFO,OTHER,5.88*S,lb,barrel,1 -CA,DFO,STOKER,5.88*S,lb,barrel,1 -CA,DFO,TANGENTIAL,5.88*S,lb,barrel,1 -CA,DFO,VERTICAL,5.88*S,lb,barrel,1 -CA,DFO,WALL,5.88*S,lb,barrel,1 -CS,DFO,CELLBURNER,5.88*S,lb,barrel,1 -CS,DFO,CYCLONE,5.88*S,lb,barrel,1 -CS,DFO,DUCTBURNER,5.88*S,lb,barrel,1 -CS,DFO,FLUIDIZED,5.88*S,lb,barrel,1 -CS,DFO,N/A,5.88*S,lb,barrel,1 -CS,DFO,OTHER,5.88*S,lb,barrel,1 -CS,DFO,STOKER,5.88*S,lb,barrel,1 -CS,DFO,TANGENTIAL,5.88*S,lb,barrel,1 -CS,DFO,VERTICAL,5.88*S,lb,barrel,1 -CS,DFO,WALL,5.88*S,lb,barrel,1 -CT,DFO,CELLBURNER,5.88*S,lb,barrel,1 -CT,DFO,CYCLONE,5.88*S,lb,barrel,1 -CT,DFO,DUCTBURNER,5.88*S,lb,barrel,1 -CT,DFO,FLUIDIZED,5.88*S,lb,barrel,1 -CT,DFO,N/A,5.88*S,lb,barrel,1 -CT,DFO,OTHER,5.88*S,lb,barrel,1 -CT,DFO,STOKER,5.88*S,lb,barrel,1 -CT,DFO,TANGENTIAL,5.88*S,lb,barrel,1 -CT,DFO,VERTICAL,5.88*S,lb,barrel,1 -CT,DFO,WALL,5.88*S,lb,barrel,1 -GT,DFO,CELLBURNER,5.88*S,lb,barrel,1 -GT,DFO,CYCLONE,5.88*S,lb,barrel,1 -GT,DFO,DUCTBURNER,5.88*S,lb,barrel,1 -GT,DFO,FLUIDIZED,5.88*S,lb,barrel,1 -GT,DFO,N/A,5.88*S,lb,barrel,1 -GT,DFO,OTHER,5.88*S,lb,barrel,1 -GT,DFO,STOKER,5.88*S,lb,barrel,1 -GT,DFO,TANGENTIAL,5.88*S,lb,barrel,1 -GT,DFO,VERTICAL,5.88*S,lb,barrel,1 -GT,DFO,WALL,5.88*S,lb,barrel,1 -IC,DFO,CELLBURNER,5.88*S,lb,barrel,1 -IC,DFO,CYCLONE,5.88*S,lb,barrel,1 -IC,DFO,DUCTBURNER,5.88*S,lb,barrel,1 -IC,DFO,FLUIDIZED,5.88*S,lb,barrel,1 -IC,DFO,N/A,5.88*S,lb,barrel,1 -IC,DFO,OTHER,5.88*S,lb,barrel,1 -IC,DFO,STOKER,5.88*S,lb,barrel,1 -IC,DFO,TANGENTIAL,5.88*S,lb,barrel,1 -IC,DFO,VERTICAL,5.88*S,lb,barrel,1 -IC,DFO,WALL,5.88*S,lb,barrel,1 -OT,DFO,CELLBURNER,5.964*S,lb,barrel,1 -OT,DFO,CYCLONE,5.964*S,lb,barrel,1 -OT,DFO,DUCTBURNER,5.964*S,lb,barrel,1 -OT,DFO,FLUIDIZED,0.5964*S,lb,barrel,1 -OT,DFO,N/A,5.964*S,lb,barrel,1 -OT,DFO,OTHER,5.964*S,lb,barrel,1 -OT,DFO,STOKER,5.964*S,lb,barrel,1 -OT,DFO,TANGENTIAL,5.964*S,lb,barrel,1 -OT,DFO,VERTICAL,5.964*S,lb,barrel,1 -OT,DFO,WALL,5.964*S,lb,barrel,1 -ST,DFO,CELLBURNER,5.964*S,lb,barrel,1 -ST,DFO,CYCLONE,5.964*S,lb,barrel,1 -ST,DFO,DUCTBURNER,5.964*S,lb,barrel,1 -ST,DFO,FLUIDIZED,0.5964*S,lb,barrel,1 -ST,DFO,N/A,5.964*S,lb,barrel,1 -ST,DFO,OTHER,5.964*S,lb,barrel,1 -ST,DFO,STOKER,5.964*S,lb,barrel,1 -ST,DFO,TANGENTIAL,5.964*S,lb,barrel,1 -ST,DFO,VERTICAL,5.964*S,lb,barrel,1 -ST,DFO,WALL,5.964*S,lb,barrel,1 -CA,JF,CELLBURNER,5.88*S,lb,barrel,1 -CA,JF,CYCLONE,5.88*S,lb,barrel,1 -CA,JF,DUCTBURNER,5.88*S,lb,barrel,1 -CA,JF,FLUIDIZED,5.88*S,lb,barrel,1 -CA,JF,N/A,5.88*S,lb,barrel,1 -CA,JF,OTHER,5.88*S,lb,barrel,1 -CA,JF,STOKER,5.88*S,lb,barrel,1 -CA,JF,TANGENTIAL,5.88*S,lb,barrel,1 -CA,JF,VERTICAL,5.88*S,lb,barrel,1 -CA,JF,WALL,5.88*S,lb,barrel,1 -CS,JF,CELLBURNER,5.88*S,lb,barrel,1 -CS,JF,CYCLONE,5.88*S,lb,barrel,1 -CS,JF,DUCTBURNER,5.88*S,lb,barrel,1 -CS,JF,FLUIDIZED,5.88*S,lb,barrel,1 -CS,JF,N/A,5.88*S,lb,barrel,1 -CS,JF,OTHER,5.88*S,lb,barrel,1 -CS,JF,STOKER,5.88*S,lb,barrel,1 -CS,JF,TANGENTIAL,5.88*S,lb,barrel,1 -CS,JF,VERTICAL,5.88*S,lb,barrel,1 -CS,JF,WALL,5.88*S,lb,barrel,1 -CT,JF,CELLBURNER,5.88*S,lb,barrel,1 -CT,JF,CYCLONE,5.88*S,lb,barrel,1 -CT,JF,DUCTBURNER,5.88*S,lb,barrel,1 -CT,JF,FLUIDIZED,5.88*S,lb,barrel,1 -CT,JF,N/A,5.88*S,lb,barrel,1 -CT,JF,OTHER,5.88*S,lb,barrel,1 -CT,JF,STOKER,5.88*S,lb,barrel,1 -CT,JF,TANGENTIAL,5.88*S,lb,barrel,1 -CT,JF,VERTICAL,5.88*S,lb,barrel,1 -CT,JF,WALL,5.88*S,lb,barrel,1 -GT,JF,CELLBURNER,5.88*S,lb,barrel,1 -GT,JF,CYCLONE,5.88*S,lb,barrel,1 -GT,JF,DUCTBURNER,5.88*S,lb,barrel,1 -GT,JF,FLUIDIZED,5.88*S,lb,barrel,1 -GT,JF,N/A,5.88*S,lb,barrel,1 -GT,JF,OTHER,5.88*S,lb,barrel,1 -GT,JF,STOKER,5.88*S,lb,barrel,1 -GT,JF,TANGENTIAL,5.88*S,lb,barrel,1 -GT,JF,VERTICAL,5.88*S,lb,barrel,1 -GT,JF,WALL,5.88*S,lb,barrel,1 -IC,JF,CELLBURNER,5.88*S,lb,barrel,1 -IC,JF,CYCLONE,5.88*S,lb,barrel,1 -IC,JF,DUCTBURNER,5.88*S,lb,barrel,1 -IC,JF,FLUIDIZED,5.88*S,lb,barrel,1 -IC,JF,N/A,5.88*S,lb,barrel,1 -IC,JF,OTHER,5.88*S,lb,barrel,1 -IC,JF,STOKER,5.88*S,lb,barrel,1 -IC,JF,TANGENTIAL,5.88*S,lb,barrel,1 -IC,JF,VERTICAL,5.88*S,lb,barrel,1 -IC,JF,WALL,5.88*S,lb,barrel,1 -OT,JF,CELLBURNER,5.964*S,lb,barrel,1 -OT,JF,CYCLONE,5.964*S,lb,barrel,1 -OT,JF,DUCTBURNER,5.964*S,lb,barrel,1 -OT,JF,FLUIDIZED,0.5964*S,lb,barrel,1 -OT,JF,N/A,5.964*S,lb,barrel,1 -OT,JF,OTHER,5.964*S,lb,barrel,1 -OT,JF,STOKER,5.964*S,lb,barrel,1 -OT,JF,TANGENTIAL,5.964*S,lb,barrel,1 -OT,JF,VERTICAL,5.964*S,lb,barrel,1 -OT,JF,WALL,5.964*S,lb,barrel,1 -ST,JF,CELLBURNER,5.964*S,lb,barrel,1 -ST,JF,CYCLONE,5.964*S,lb,barrel,1 -ST,JF,DUCTBURNER,5.964*S,lb,barrel,1 -ST,JF,FLUIDIZED,0.5964*S,lb,barrel,1 -ST,JF,N/A,5.964*S,lb,barrel,1 -ST,JF,OTHER,5.964*S,lb,barrel,1 -ST,JF,STOKER,5.964*S,lb,barrel,1 -ST,JF,TANGENTIAL,5.964*S,lb,barrel,1 -ST,JF,VERTICAL,5.964*S,lb,barrel,1 -ST,JF,WALL,5.964*S,lb,barrel,1 -CA,KER,CELLBURNER,5.88*S,lb,barrel,1 -CA,KER,CYCLONE,5.88*S,lb,barrel,1 -CA,KER,DUCTBURNER,5.88*S,lb,barrel,1 -CA,KER,FLUIDIZED,5.88*S,lb,barrel,1 -CA,KER,N/A,5.88*S,lb,barrel,1 -CA,KER,OTHER,5.88*S,lb,barrel,1 -CA,KER,STOKER,5.88*S,lb,barrel,1 -CA,KER,TANGENTIAL,5.88*S,lb,barrel,1 -CA,KER,VERTICAL,5.88*S,lb,barrel,1 -CA,KER,WALL,5.88*S,lb,barrel,1 -CS,KER,CELLBURNER,5.88*S,lb,barrel,1 -CS,KER,CYCLONE,5.88*S,lb,barrel,1 -CS,KER,DUCTBURNER,5.88*S,lb,barrel,1 -CS,KER,FLUIDIZED,5.88*S,lb,barrel,1 -CS,KER,N/A,5.88*S,lb,barrel,1 -CS,KER,OTHER,5.88*S,lb,barrel,1 -CS,KER,STOKER,5.88*S,lb,barrel,1 -CS,KER,TANGENTIAL,5.88*S,lb,barrel,1 -CS,KER,VERTICAL,5.88*S,lb,barrel,1 -CS,KER,WALL,5.88*S,lb,barrel,1 -CT,KER,CELLBURNER,5.88*S,lb,barrel,1 -CT,KER,CYCLONE,5.88*S,lb,barrel,1 -CT,KER,DUCTBURNER,5.88*S,lb,barrel,1 -CT,KER,FLUIDIZED,5.88*S,lb,barrel,1 -CT,KER,N/A,5.88*S,lb,barrel,1 -CT,KER,OTHER,5.88*S,lb,barrel,1 -CT,KER,STOKER,5.88*S,lb,barrel,1 -CT,KER,TANGENTIAL,5.88*S,lb,barrel,1 -CT,KER,VERTICAL,5.88*S,lb,barrel,1 -CT,KER,WALL,5.88*S,lb,barrel,1 -GT,KER,CELLBURNER,5.88*S,lb,barrel,1 -GT,KER,CYCLONE,5.88*S,lb,barrel,1 -GT,KER,DUCTBURNER,5.88*S,lb,barrel,1 -GT,KER,FLUIDIZED,5.88*S,lb,barrel,1 -GT,KER,N/A,5.88*S,lb,barrel,1 -GT,KER,OTHER,5.88*S,lb,barrel,1 -GT,KER,STOKER,5.88*S,lb,barrel,1 -GT,KER,TANGENTIAL,5.88*S,lb,barrel,1 -GT,KER,VERTICAL,5.88*S,lb,barrel,1 -GT,KER,WALL,5.88*S,lb,barrel,1 -IC,KER,CELLBURNER,5.88*S,lb,barrel,1 -IC,KER,CYCLONE,5.88*S,lb,barrel,1 -IC,KER,DUCTBURNER,5.88*S,lb,barrel,1 -IC,KER,FLUIDIZED,5.88*S,lb,barrel,1 -IC,KER,N/A,5.88*S,lb,barrel,1 -IC,KER,OTHER,5.88*S,lb,barrel,1 -IC,KER,STOKER,5.88*S,lb,barrel,1 -IC,KER,TANGENTIAL,5.88*S,lb,barrel,1 -IC,KER,VERTICAL,5.88*S,lb,barrel,1 -IC,KER,WALL,5.88*S,lb,barrel,1 -OT,KER,CELLBURNER,5.964*S,lb,barrel,1 -OT,KER,CYCLONE,5.964*S,lb,barrel,1 -OT,KER,DUCTBURNER,5.964*S,lb,barrel,1 -OT,KER,FLUIDIZED,0.5964*S,lb,barrel,1 -OT,KER,N/A,5.964*S,lb,barrel,1 -OT,KER,OTHER,5.964*S,lb,barrel,1 -OT,KER,STOKER,5.964*S,lb,barrel,1 -OT,KER,TANGENTIAL,5.964*S,lb,barrel,1 -OT,KER,VERTICAL,5.964*S,lb,barrel,1 -OT,KER,WALL,5.964*S,lb,barrel,1 -ST,KER,CELLBURNER,5.964*S,lb,barrel,1 -ST,KER,CYCLONE,5.964*S,lb,barrel,1 -ST,KER,DUCTBURNER,5.964*S,lb,barrel,1 -ST,KER,FLUIDIZED,0.5964*S,lb,barrel,1 -ST,KER,N/A,5.964*S,lb,barrel,1 -ST,KER,OTHER,5.964*S,lb,barrel,1 -ST,KER,STOKER,5.964*S,lb,barrel,1 -ST,KER,TANGENTIAL,5.964*S,lb,barrel,1 -ST,KER,VERTICAL,5.964*S,lb,barrel,1 -ST,KER,WALL,5.964*S,lb,barrel,1 -CA,LFG,CELLBURNER,0.0006,lb,Mcf,0 -CA,LFG,CYCLONE,0.0006,lb,Mcf,0 -CA,LFG,DUCTBURNER,0.0006,lb,Mcf,0 -CA,LFG,FLUIDIZED,0.0006,lb,Mcf,0 -CA,LFG,N/A,0.0006,lb,Mcf,0 -CA,LFG,OTHER,0.0006,lb,Mcf,0 -CA,LFG,STOKER,0.0006,lb,Mcf,0 -CA,LFG,TANGENTIAL,0.0006,lb,Mcf,0 -CA,LFG,VERTICAL,0.0006,lb,Mcf,0 -CA,LFG,WALL,0.0006,lb,Mcf,0 -CS,LFG,CELLBURNER,0.0006,lb,Mcf,0 -CS,LFG,CYCLONE,0.0006,lb,Mcf,0 -CS,LFG,DUCTBURNER,0.0006,lb,Mcf,0 -CS,LFG,FLUIDIZED,0.0006,lb,Mcf,0 -CS,LFG,N/A,0.0006,lb,Mcf,0 -CS,LFG,OTHER,0.0006,lb,Mcf,0 -CS,LFG,STOKER,0.0006,lb,Mcf,0 -CS,LFG,TANGENTIAL,0.0006,lb,Mcf,0 -CS,LFG,VERTICAL,0.0006,lb,Mcf,0 -CS,LFG,WALL,0.0006,lb,Mcf,0 -CT,LFG,CELLBURNER,0.0006,lb,Mcf,0 -CT,LFG,CYCLONE,0.0006,lb,Mcf,0 -CT,LFG,DUCTBURNER,0.0006,lb,Mcf,0 -CT,LFG,FLUIDIZED,0.0006,lb,Mcf,0 -CT,LFG,N/A,0.0006,lb,Mcf,0 -CT,LFG,OTHER,0.0006,lb,Mcf,0 -CT,LFG,STOKER,0.0006,lb,Mcf,0 -CT,LFG,TANGENTIAL,0.0006,lb,Mcf,0 -CT,LFG,VERTICAL,0.0006,lb,Mcf,0 -CT,LFG,WALL,0.0006,lb,Mcf,0 -GT,LFG,CELLBURNER,0.0006,lb,Mcf,0 -GT,LFG,CYCLONE,0.0006,lb,Mcf,0 -GT,LFG,DUCTBURNER,0.0006,lb,Mcf,0 -GT,LFG,FLUIDIZED,0.0006,lb,Mcf,0 -GT,LFG,N/A,0.0006,lb,Mcf,0 -GT,LFG,OTHER,0.0006,lb,Mcf,0 -GT,LFG,STOKER,0.0006,lb,Mcf,0 -GT,LFG,TANGENTIAL,0.0006,lb,Mcf,0 -GT,LFG,VERTICAL,0.0006,lb,Mcf,0 -GT,LFG,WALL,0.0006,lb,Mcf,0 -IC,LFG,CELLBURNER,0.0006,lb,Mcf,0 -IC,LFG,CYCLONE,0.0006,lb,Mcf,0 -IC,LFG,DUCTBURNER,0.0006,lb,Mcf,0 -IC,LFG,FLUIDIZED,0.00006,lb,Mcf,0 -IC,LFG,N/A,0.0006,lb,Mcf,0 -IC,LFG,OTHER,0.0006,lb,Mcf,0 -IC,LFG,STOKER,0.0006,lb,Mcf,0 -IC,LFG,TANGENTIAL,0.0006,lb,Mcf,0 -IC,LFG,VERTICAL,0.0006,lb,Mcf,0 -IC,LFG,WALL,0.0006,lb,Mcf,0 -OT,LFG,CELLBURNER,0.0006,lb,Mcf,0 -OT,LFG,CYCLONE,0.0006,lb,Mcf,0 -OT,LFG,DUCTBURNER,0.0006,lb,Mcf,0 -OT,LFG,FLUIDIZED,0.00006,lb,Mcf,0 -OT,LFG,N/A,0.0006,lb,Mcf,0 -OT,LFG,OTHER,0.0006,lb,Mcf,0 -OT,LFG,STOKER,0.0006,lb,Mcf,0 -OT,LFG,TANGENTIAL,0.0006,lb,Mcf,0 -OT,LFG,VERTICAL,0.0006,lb,Mcf,0 -OT,LFG,WALL,0.0006,lb,Mcf,0 -ST,LFG,CELLBURNER,0.0006,lb,Mcf,0 -ST,LFG,CYCLONE,0.0006,lb,Mcf,0 -ST,LFG,DUCTBURNER,0.0006,lb,Mcf,0 -ST,LFG,FLUIDIZED,0.00006,lb,Mcf,0 -ST,LFG,N/A,0.0006,lb,Mcf,0 -ST,LFG,OTHER,0.0006,lb,Mcf,0 -ST,LFG,STOKER,0.0006,lb,Mcf,0 -ST,LFG,TANGENTIAL,0.0006,lb,Mcf,0 -ST,LFG,VERTICAL,0.0006,lb,Mcf,0 -ST,LFG,WALL,0.0006,lb,Mcf,0 -OT,LIG,CELLBURNER,30*S,lb,short ton,1 -OT,LIG,CYCLONE,30*S,lb,short ton,1 -OT,LIG,DUCTBURNER,30*S,lb,short ton,1 -OT,LIG,FLUIDIZED,3*S,lb,short ton,1 -OT,LIG,N/A,30*S,lb,short ton,1 -OT,LIG,OTHER,30*S,lb,short ton,1 -OT,LIG,STOKER,30*S,lb,short ton,1 -OT,LIG,TANGENTIAL,30*S,lb,short ton,1 -OT,LIG,VERTICAL,30*S,lb,short ton,1 -OT,LIG,WALL,30*S,lb,short ton,1 -ST,LIG,CELLBURNER,30*S,lb,short ton,1 -ST,LIG,CYCLONE,30*S,lb,short ton,1 -ST,LIG,DUCTBURNER,30*S,lb,short ton,1 -ST,LIG,FLUIDIZED,3*S,lb,short ton,1 -ST,LIG,N/A,30*S,lb,short ton,1 -ST,LIG,OTHER,30*S,lb,short ton,1 -ST,LIG,STOKER,30*S,lb,short ton,1 -ST,LIG,TANGENTIAL,30*S,lb,short ton,1 -ST,LIG,VERTICAL,30*S,lb,short ton,1 -ST,LIG,WALL,30*S,lb,short ton,1 -ST,MSB,CELLBURNER,1.7,lb,short ton,0 -ST,MSB,CYCLONE,1.7,lb,short ton,0 -ST,MSB,DUCTBURNER,1.7,lb,short ton,0 -ST,MSB,FLUIDIZED,0.17,lb,short ton,0 -ST,MSB,N/A,1.7,lb,short ton,0 -ST,MSB,OTHER,1.7,lb,short ton,0 -ST,MSB,STOKER,1.7,lb,short ton,0 -ST,MSB,TANGENTIAL,1.7,lb,short ton,0 -ST,MSB,VERTICAL,1.7,lb,short ton,0 -ST,MSB,WALL,1.7,lb,short ton,0 -ST,MSN,CELLBURNER,1.7,lb,short ton,0 -ST,MSN,CYCLONE,1.7,lb,short ton,0 -ST,MSN,DUCTBURNER,1.7,lb,short ton,0 -ST,MSN,FLUIDIZED,0.17,lb,short ton,0 -ST,MSN,N/A,1.7,lb,short ton,0 -ST,MSN,OTHER,1.7,lb,short ton,0 -ST,MSN,STOKER,1.7,lb,short ton,0 -ST,MSN,TANGENTIAL,1.7,lb,short ton,0 -ST,MSN,VERTICAL,1.7,lb,short ton,0 -ST,MSN,WALL,1.7,lb,short ton,0 -OT,MSW,CELLBURNER,1.7,lb,short ton,0 -OT,MSW,CYCLONE,1.7,lb,short ton,0 -OT,MSW,DUCTBURNER,1.7,lb,short ton,0 -OT,MSW,FLUIDIZED,0.17,lb,short ton,0 -OT,MSW,N/A,1.7,lb,short ton,0 -OT,MSW,OTHER,1.7,lb,short ton,0 -OT,MSW,STOKER,1.7,lb,short ton,0 -OT,MSW,TANGENTIAL,1.7,lb,short ton,0 -OT,MSW,VERTICAL,1.7,lb,short ton,0 -OT,MSW,WALL,1.7,lb,short ton,0 -ST,MSW,CELLBURNER,1.7,lb,short ton,0 -ST,MSW,CYCLONE,1.7,lb,short ton,0 -ST,MSW,DUCTBURNER,1.7,lb,short ton,0 -ST,MSW,FLUIDIZED,0.17,lb,short ton,0 -ST,MSW,N/A,1.7,lb,short ton,0 -ST,MSW,OTHER,1.7,lb,short ton,0 -ST,MSW,STOKER,1.7,lb,short ton,0 -ST,MSW,TANGENTIAL,1.7,lb,short ton,0 -ST,MSW,VERTICAL,1.7,lb,short ton,0 -ST,MSW,WALL,1.7,lb,short ton,0 -CA,NG,CELLBURNER,0.0006,lb,Mcf,0 -CA,NG,CYCLONE,0.0006,lb,Mcf,0 -CA,NG,DUCTBURNER,0.0006,lb,Mcf,0 -CA,NG,FLUIDIZED,0.0006,lb,Mcf,0 -CA,NG,N/A,0.0006,lb,Mcf,0 -CA,NG,OTHER,0.0006,lb,Mcf,0 -CA,NG,STOKER,0.0006,lb,Mcf,0 -CA,NG,TANGENTIAL,0.0006,lb,Mcf,0 -CA,NG,VERTICAL,0.0006,lb,Mcf,0 -CA,NG,WALL,0.0006,lb,Mcf,0 -CE,NG,N/A,0.0006,lb,Mcf,0 -CS,NG,CELLBURNER,0.0006,lb,Mcf,0 -CS,NG,CYCLONE,0.0006,lb,Mcf,0 -CS,NG,DUCTBURNER,0.0006,lb,Mcf,0 -CS,NG,FLUIDIZED,0.0006,lb,Mcf,0 -CS,NG,N/A,0.0006,lb,Mcf,0 -CS,NG,OTHER,0.0006,lb,Mcf,0 -CS,NG,STOKER,0.0006,lb,Mcf,0 -CS,NG,TANGENTIAL,0.0006,lb,Mcf,0 -CS,NG,VERTICAL,0.0006,lb,Mcf,0 -CS,NG,WALL,0.0006,lb,Mcf,0 -CT,NG,CELLBURNER,0.0006,lb,Mcf,0 -CT,NG,CYCLONE,0.0006,lb,Mcf,0 -CT,NG,DUCTBURNER,0.0006,lb,Mcf,0 -CT,NG,FLUIDIZED,0.0006,lb,Mcf,0 -CT,NG,N/A,0.0006,lb,Mcf,0 -CT,NG,OTHER,0.0006,lb,Mcf,0 -CT,NG,STOKER,0.0006,lb,Mcf,0 -CT,NG,TANGENTIAL,0.0006,lb,Mcf,0 -CT,NG,VERTICAL,0.0006,lb,Mcf,0 -CT,NG,WALL,0.0006,lb,Mcf,0 -GT,NG,CELLBURNER,0.0006,lb,Mcf,0 -GT,NG,CYCLONE,0.0006,lb,Mcf,0 -GT,NG,DUCTBURNER,0.0006,lb,Mcf,0 -GT,NG,FLUIDIZED,0.0006,lb,Mcf,0 -GT,NG,N/A,0.0006,lb,Mcf,0 -GT,NG,OTHER,0.0006,lb,Mcf,0 -GT,NG,STOKER,0.0006,lb,Mcf,0 -GT,NG,TANGENTIAL,0.0006,lb,Mcf,0 -GT,NG,VERTICAL,0.0006,lb,Mcf,0 -GT,NG,WALL,0.0006,lb,Mcf,0 -IC,NG,CELLBURNER,0.0006,lb,Mcf,0 -IC,NG,CYCLONE,0.0006,lb,Mcf,0 -IC,NG,DUCTBURNER,0.0006,lb,Mcf,0 -IC,NG,FLUIDIZED,0.0006,lb,Mcf,0 -IC,NG,N/A,0.0006,lb,Mcf,0 -IC,NG,OTHER,0.0006,lb,Mcf,0 -IC,NG,STOKER,0.0006,lb,Mcf,0 -IC,NG,TANGENTIAL,0.0006,lb,Mcf,0 -IC,NG,VERTICAL,0.0006,lb,Mcf,0 -IC,NG,WALL,0.0006,lb,Mcf,0 -OT,NG,CELLBURNER,0.0006,lb,Mcf,0 -OT,NG,CYCLONE,0.0006,lb,Mcf,0 -OT,NG,DUCTBURNER,0.0006,lb,Mcf,0 -OT,NG,FLUIDIZED,0.00006,lb,Mcf,0 -OT,NG,N/A,0.0006,lb,Mcf,0 -OT,NG,OTHER,0.0006,lb,Mcf,0 -OT,NG,STOKER,0.0006,lb,Mcf,0 -OT,NG,TANGENTIAL,0.0006,lb,Mcf,0 -OT,NG,VERTICAL,0.0006,lb,Mcf,0 -OT,NG,WALL,0.0006,lb,Mcf,0 -ST,NG,CELLBURNER,0.0006,lb,Mcf,0 -ST,NG,CYCLONE,0.0006,lb,Mcf,0 -ST,NG,DUCTBURNER,0.0006,lb,Mcf,0 -ST,NG,FLUIDIZED,0.00006,lb,Mcf,0 -ST,NG,N/A,0.0006,lb,Mcf,0 -ST,NG,OTHER,0.0006,lb,Mcf,0 -ST,NG,STOKER,0.0006,lb,Mcf,0 -ST,NG,TANGENTIAL,0.0006,lb,Mcf,0 -ST,NG,VERTICAL,0.0006,lb,Mcf,0 -ST,NG,WALL,0.0006,lb,Mcf,0 -CA,OBG,CELLBURNER,0.0006,lb,Mcf,0 -CA,OBG,CYCLONE,0.0006,lb,Mcf,0 -CA,OBG,DUCTBURNER,0.0006,lb,Mcf,0 -CA,OBG,FLUIDIZED,0.0006,lb,Mcf,0 -CA,OBG,N/A,0.0006,lb,Mcf,0 -CA,OBG,OTHER,0.0006,lb,Mcf,0 -CA,OBG,STOKER,0.0006,lb,Mcf,0 -CA,OBG,TANGENTIAL,0.0006,lb,Mcf,0 -CA,OBG,VERTICAL,0.0006,lb,Mcf,0 -CA,OBG,WALL,0.0006,lb,Mcf,0 -CS,OBG,CELLBURNER,0.0006,lb,Mcf,0 -CS,OBG,CYCLONE,0.0006,lb,Mcf,0 -CS,OBG,DUCTBURNER,0.0006,lb,Mcf,0 -CS,OBG,FLUIDIZED,0.0006,lb,Mcf,0 -CS,OBG,N/A,0.0006,lb,Mcf,0 -CS,OBG,OTHER,0.0006,lb,Mcf,0 -CS,OBG,STOKER,0.0006,lb,Mcf,0 -CS,OBG,TANGENTIAL,0.0006,lb,Mcf,0 -CS,OBG,VERTICAL,0.0006,lb,Mcf,0 -CS,OBG,WALL,0.0006,lb,Mcf,0 -CT,OBG,CELLBURNER,0.0006,lb,Mcf,0 -CT,OBG,CYCLONE,0.0006,lb,Mcf,0 -CT,OBG,DUCTBURNER,0.0006,lb,Mcf,0 -CT,OBG,FLUIDIZED,0.0006,lb,Mcf,0 -CT,OBG,N/A,0.0006,lb,Mcf,0 -CT,OBG,OTHER,0.0006,lb,Mcf,0 -CT,OBG,STOKER,0.0006,lb,Mcf,0 -CT,OBG,TANGENTIAL,0.0006,lb,Mcf,0 -CT,OBG,VERTICAL,0.0006,lb,Mcf,0 -CT,OBG,WALL,0.0006,lb,Mcf,0 -GT,OBG,CELLBURNER,0.0006,lb,Mcf,0 -GT,OBG,CYCLONE,0.0006,lb,Mcf,0 -GT,OBG,DUCTBURNER,0.0006,lb,Mcf,0 -GT,OBG,FLUIDIZED,0.0006,lb,Mcf,0 -GT,OBG,N/A,0.0006,lb,Mcf,0 -GT,OBG,OTHER,0.0006,lb,Mcf,0 -GT,OBG,STOKER,0.0006,lb,Mcf,0 -GT,OBG,TANGENTIAL,0.0006,lb,Mcf,0 -GT,OBG,VERTICAL,0.0006,lb,Mcf,0 -GT,OBG,WALL,0.0006,lb,Mcf,0 -IC,OBG,CELLBURNER,0.0006,lb,Mcf,0 -IC,OBG,CYCLONE,0.0006,lb,Mcf,0 -IC,OBG,DUCTBURNER,0.0006,lb,Mcf,0 -IC,OBG,FLUIDIZED,0.0006,lb,Mcf,0 -IC,OBG,N/A,0.0006,lb,Mcf,0 -IC,OBG,OTHER,0.0006,lb,Mcf,0 -IC,OBG,STOKER,0.0006,lb,Mcf,0 -IC,OBG,TANGENTIAL,0.0006,lb,Mcf,0 -IC,OBG,VERTICAL,0.0006,lb,Mcf,0 -IC,OBG,WALL,0.0006,lb,Mcf,0 -OT,OBG,CELLBURNER,0.0006,lb,Mcf,0 -OT,OBG,CYCLONE,0.0006,lb,Mcf,0 -OT,OBG,DUCTBURNER,0.0006,lb,Mcf,0 -OT,OBG,FLUIDIZED,0.00006,lb,Mcf,0 -OT,OBG,N/A,0.0006,lb,Mcf,0 -OT,OBG,OTHER,0.0006,lb,Mcf,0 -OT,OBG,STOKER,0.0006,lb,Mcf,0 -OT,OBG,TANGENTIAL,0.0006,lb,Mcf,0 -OT,OBG,VERTICAL,0.0006,lb,Mcf,0 -OT,OBG,WALL,0.0006,lb,Mcf,0 -ST,OBG,CELLBURNER,0.0006,lb,Mcf,0 -ST,OBG,CYCLONE,0.0006,lb,Mcf,0 -ST,OBG,DUCTBURNER,0.0006,lb,Mcf,0 -ST,OBG,FLUIDIZED,0.00006,lb,Mcf,0 -ST,OBG,N/A,0.0006,lb,Mcf,0 -ST,OBG,OTHER,0.0006,lb,Mcf,0 -ST,OBG,STOKER,0.0006,lb,Mcf,0 -ST,OBG,TANGENTIAL,0.0006,lb,Mcf,0 -ST,OBG,VERTICAL,0.0006,lb,Mcf,0 -ST,OBG,WALL,0.0006,lb,Mcf,0 -CA,OBL,CELLBURNER,5.88*S,lb,barrel,1 -CA,OBL,CYCLONE,5.88*S,lb,barrel,1 -CA,OBL,DUCTBURNER,5.88*S,lb,barrel,1 -CA,OBL,FLUIDIZED,5.88*S,lb,barrel,1 -CA,OBL,N/A,5.88*S,lb,barrel,1 -CA,OBL,OTHER,5.88*S,lb,barrel,1 -CA,OBL,STOKER,5.88*S,lb,barrel,1 -CA,OBL,TANGENTIAL,5.88*S,lb,barrel,1 -CA,OBL,VERTICAL,5.88*S,lb,barrel,1 -CA,OBL,WALL,5.88*S,lb,barrel,1 -CS,OBL,CELLBURNER,5.88*S,lb,barrel,1 -CS,OBL,CYCLONE,5.88*S,lb,barrel,1 -CS,OBL,DUCTBURNER,5.88*S,lb,barrel,1 -CS,OBL,FLUIDIZED,5.88*S,lb,barrel,1 -CS,OBL,N/A,5.88*S,lb,barrel,1 -CS,OBL,OTHER,5.88*S,lb,barrel,1 -CS,OBL,STOKER,5.88*S,lb,barrel,1 -CS,OBL,TANGENTIAL,5.88*S,lb,barrel,1 -CS,OBL,VERTICAL,5.88*S,lb,barrel,1 -CS,OBL,WALL,5.88*S,lb,barrel,1 -CT,OBL,CELLBURNER,5.88*S,lb,barrel,1 -CT,OBL,CYCLONE,5.88*S,lb,barrel,1 -CT,OBL,DUCTBURNER,5.88*S,lb,barrel,1 -CT,OBL,FLUIDIZED,5.88*S,lb,barrel,1 -CT,OBL,N/A,5.88*S,lb,barrel,1 -CT,OBL,OTHER,5.88*S,lb,barrel,1 -CT,OBL,STOKER,5.88*S,lb,barrel,1 -CT,OBL,TANGENTIAL,5.88*S,lb,barrel,1 -CT,OBL,VERTICAL,5.88*S,lb,barrel,1 -CT,OBL,WALL,5.88*S,lb,barrel,1 -GT,OBL,CELLBURNER,5.88*S,lb,barrel,1 -GT,OBL,CYCLONE,5.88*S,lb,barrel,1 -GT,OBL,DUCTBURNER,5.88*S,lb,barrel,1 -GT,OBL,FLUIDIZED,5.88*S,lb,barrel,1 -GT,OBL,N/A,5.88*S,lb,barrel,1 -GT,OBL,OTHER,5.88*S,lb,barrel,1 -GT,OBL,STOKER,5.88*S,lb,barrel,1 -GT,OBL,TANGENTIAL,5.88*S,lb,barrel,1 -GT,OBL,VERTICAL,5.88*S,lb,barrel,1 -GT,OBL,WALL,5.88*S,lb,barrel,1 -IC,OBL,CELLBURNER,5.88*S,lb,barrel,1 -IC,OBL,CYCLONE,5.88*S,lb,barrel,1 -IC,OBL,DUCTBURNER,5.88*S,lb,barrel,1 -IC,OBL,FLUIDIZED,5.88*S,lb,barrel,1 -IC,OBL,N/A,5.88*S,lb,barrel,1 -IC,OBL,OTHER,5.88*S,lb,barrel,1 -IC,OBL,STOKER,5.88*S,lb,barrel,1 -IC,OBL,TANGENTIAL,5.88*S,lb,barrel,1 -IC,OBL,VERTICAL,5.88*S,lb,barrel,1 -IC,OBL,WALL,5.88*S,lb,barrel,1 -OT,OBL,CELLBURNER,5.964*S,lb,barrel,1 -OT,OBL,CYCLONE,5.964*S,lb,barrel,1 -OT,OBL,DUCTBURNER,5.964*S,lb,barrel,1 -OT,OBL,FLUIDIZED,0.5964*S,lb,barrel,1 -OT,OBL,N/A,5.964*S,lb,barrel,1 -OT,OBL,OTHER,5.964*S,lb,barrel,1 -OT,OBL,STOKER,5.964*S,lb,barrel,1 -OT,OBL,TANGENTIAL,5.964*S,lb,barrel,1 -OT,OBL,VERTICAL,5.964*S,lb,barrel,1 -OT,OBL,WALL,5.964*S,lb,barrel,1 -ST,OBL,CELLBURNER,5.964*S,lb,barrel,1 -ST,OBL,CYCLONE,5.964*S,lb,barrel,1 -ST,OBL,DUCTBURNER,5.964*S,lb,barrel,1 -ST,OBL,FLUIDIZED,0.5964*S,lb,barrel,1 -ST,OBL,N/A,5.964*S,lb,barrel,1 -ST,OBL,OTHER,5.964*S,lb,barrel,1 -ST,OBL,STOKER,5.964*S,lb,barrel,1 -ST,OBL,TANGENTIAL,5.964*S,lb,barrel,1 -ST,OBL,VERTICAL,5.964*S,lb,barrel,1 -ST,OBL,WALL,5.964*S,lb,barrel,1 -OT,OBS,CELLBURNER,0.23,lb,short ton,0 -OT,OBS,CYCLONE,0.23,lb,short ton,0 -OT,OBS,DUCTBURNER,0.23,lb,short ton,0 -OT,OBS,FLUIDIZED,0.02,lb,short ton,0 -OT,OBS,N/A,0.23,lb,short ton,0 -OT,OBS,OTHER,0.23,lb,short ton,0 -OT,OBS,STOKER,0.23,lb,short ton,0 -OT,OBS,TANGENTIAL,0.23,lb,short ton,0 -OT,OBS,VERTICAL,0.23,lb,short ton,0 -OT,OBS,WALL,0.23,lb,short ton,0 -ST,OBS,CELLBURNER,0.23,lb,short ton,0 -ST,OBS,CYCLONE,0.23,lb,short ton,0 -ST,OBS,DUCTBURNER,0.23,lb,short ton,0 -ST,OBS,FLUIDIZED,0.02,lb,short ton,0 -ST,OBS,N/A,0.23,lb,short ton,0 -ST,OBS,OTHER,0.23,lb,short ton,0 -ST,OBS,STOKER,0.23,lb,short ton,0 -ST,OBS,TANGENTIAL,0.23,lb,short ton,0 -ST,OBS,VERTICAL,0.23,lb,short ton,0 -ST,OBS,WALL,0.23,lb,short ton,0 -CA,OG,CELLBURNER,0.0006,lb,Mcf,0 -CA,OG,CYCLONE,0.0006,lb,Mcf,0 -CA,OG,DUCTBURNER,0.0006,lb,Mcf,0 -CA,OG,FLUIDIZED,0.0006,lb,Mcf,0 -CA,OG,N/A,0.0006,lb,Mcf,0 -CA,OG,OTHER,0.0006,lb,Mcf,0 -CA,OG,STOKER,0.0006,lb,Mcf,0 -CA,OG,TANGENTIAL,0.0006,lb,Mcf,0 -CA,OG,VERTICAL,0.0006,lb,Mcf,0 -CA,OG,WALL,0.0006,lb,Mcf,0 -CS,OG,CELLBURNER,0.0006,lb,Mcf,0 -CS,OG,CYCLONE,0.0006,lb,Mcf,0 -CS,OG,DUCTBURNER,0.0006,lb,Mcf,0 -CS,OG,FLUIDIZED,0.0006,lb,Mcf,0 -CS,OG,N/A,0.0006,lb,Mcf,0 -CS,OG,OTHER,0.0006,lb,Mcf,0 -CS,OG,STOKER,0.0006,lb,Mcf,0 -CS,OG,TANGENTIAL,0.0006,lb,Mcf,0 -CS,OG,VERTICAL,0.0006,lb,Mcf,0 -CS,OG,WALL,0.0006,lb,Mcf,0 -CT,OG,CELLBURNER,0.0006,lb,Mcf,0 -CT,OG,CYCLONE,0.0006,lb,Mcf,0 -CT,OG,DUCTBURNER,0.0006,lb,Mcf,0 -CT,OG,FLUIDIZED,0.0006,lb,Mcf,0 -CT,OG,N/A,0.0006,lb,Mcf,0 -CT,OG,OTHER,0.0006,lb,Mcf,0 -CT,OG,STOKER,0.0006,lb,Mcf,0 -CT,OG,TANGENTIAL,0.0006,lb,Mcf,0 -CT,OG,VERTICAL,0.0006,lb,Mcf,0 -CT,OG,WALL,0.0006,lb,Mcf,0 -GT,OG,CELLBURNER,0.0006,lb,Mcf,0 -GT,OG,CYCLONE,0.0006,lb,Mcf,0 -GT,OG,DUCTBURNER,0.0006,lb,Mcf,0 -GT,OG,FLUIDIZED,0.0006,lb,Mcf,0 -GT,OG,N/A,0.0006,lb,Mcf,0 -GT,OG,OTHER,0.0006,lb,Mcf,0 -GT,OG,STOKER,0.0006,lb,Mcf,0 -GT,OG,TANGENTIAL,0.0006,lb,Mcf,0 -GT,OG,VERTICAL,0.0006,lb,Mcf,0 -GT,OG,WALL,0.0006,lb,Mcf,0 -IC,OG,CELLBURNER,0.0006,lb,Mcf,0 -IC,OG,CYCLONE,0.0006,lb,Mcf,0 -IC,OG,DUCTBURNER,0.0006,lb,Mcf,0 -IC,OG,FLUIDIZED,0.0006,lb,Mcf,0 -IC,OG,N/A,0.0006,lb,Mcf,0 -IC,OG,OTHER,0.0006,lb,Mcf,0 -IC,OG,STOKER,0.0006,lb,Mcf,0 -IC,OG,TANGENTIAL,0.0006,lb,Mcf,0 -IC,OG,VERTICAL,0.0006,lb,Mcf,0 -IC,OG,WALL,0.0006,lb,Mcf,0 -OT,OG,CELLBURNER,0.0006,lb,Mcf,0 -OT,OG,CYCLONE,0.0006,lb,Mcf,0 -OT,OG,DUCTBURNER,0.0006,lb,Mcf,0 -OT,OG,FLUIDIZED,0.00006,lb,Mcf,0 -OT,OG,N/A,0.0006,lb,Mcf,0 -OT,OG,OTHER,0.0006,lb,Mcf,0 -OT,OG,STOKER,0.0006,lb,Mcf,0 -OT,OG,TANGENTIAL,0.0006,lb,Mcf,0 -OT,OG,VERTICAL,0.0006,lb,Mcf,0 -OT,OG,WALL,0.0006,lb,Mcf,0 -ST,OG,CELLBURNER,0.0006,lb,Mcf,0 -ST,OG,CYCLONE,0.0006,lb,Mcf,0 -ST,OG,DUCTBURNER,0.0006,lb,Mcf,0 -ST,OG,FLUIDIZED,0.00006,lb,Mcf,0 -ST,OG,N/A,0.0006,lb,Mcf,0 -ST,OG,OTHER,0.0006,lb,Mcf,0 -ST,OG,STOKER,0.0006,lb,Mcf,0 -ST,OG,TANGENTIAL,0.0006,lb,Mcf,0 -ST,OG,VERTICAL,0.0006,lb,Mcf,0 -ST,OG,WALL,0.0006,lb,Mcf,0 -CA,OTH,CELLBURNER,0.0006,lb,Mcf,0 -CA,OTH,CYCLONE,0.0006,lb,Mcf,0 -CA,OTH,DUCTBURNER,0.0006,lb,Mcf,0 -CA,OTH,FLUIDIZED,0.0006,lb,Mcf,0 -CA,OTH,N/A,0.0006,lb,Mcf,0 -CA,OTH,OTHER,0.0006,lb,Mcf,0 -CA,OTH,STOKER,0.0006,lb,Mcf,0 -CA,OTH,TANGENTIAL,0.0006,lb,Mcf,0 -CA,OTH,VERTICAL,0.0006,lb,Mcf,0 -CA,OTH,WALL,0.0006,lb,Mcf,0 -CS,OTH,CELLBURNER,0.0006,lb,Mcf,0 -CS,OTH,CYCLONE,0.0006,lb,Mcf,0 -CS,OTH,DUCTBURNER,0.0006,lb,Mcf,0 -CS,OTH,FLUIDIZED,0.0006,lb,Mcf,0 -CS,OTH,N/A,0.0006,lb,Mcf,0 -CS,OTH,OTHER,0.0006,lb,Mcf,0 -CS,OTH,STOKER,0.0006,lb,Mcf,0 -CS,OTH,TANGENTIAL,0.0006,lb,Mcf,0 -CS,OTH,VERTICAL,0.0006,lb,Mcf,0 -CS,OTH,WALL,0.0006,lb,Mcf,0 -CT,OTH,CELLBURNER,0.0006,lb,Mcf,0 -CT,OTH,CYCLONE,0.0006,lb,Mcf,0 -CT,OTH,DUCTBURNER,0.0006,lb,Mcf,0 -CT,OTH,FLUIDIZED,0.0006,lb,Mcf,0 -CT,OTH,N/A,0.0006,lb,Mcf,0 -CT,OTH,OTHER,0.0006,lb,Mcf,0 -CT,OTH,STOKER,0.0006,lb,Mcf,0 -CT,OTH,TANGENTIAL,0.0006,lb,Mcf,0 -CT,OTH,VERTICAL,0.0006,lb,Mcf,0 -CT,OTH,WALL,0.0006,lb,Mcf,0 -GT,OTH,CELLBURNER,0.0006,lb,Mcf,0 -GT,OTH,CYCLONE,0.0006,lb,Mcf,0 -GT,OTH,DUCTBURNER,0.0006,lb,Mcf,0 -GT,OTH,FLUIDIZED,0.0006,lb,Mcf,0 -GT,OTH,N/A,0.0006,lb,Mcf,0 -GT,OTH,OTHER,0.0006,lb,Mcf,0 -GT,OTH,STOKER,0.0006,lb,Mcf,0 -GT,OTH,TANGENTIAL,0.0006,lb,Mcf,0 -GT,OTH,VERTICAL,0.0006,lb,Mcf,0 -GT,OTH,WALL,0.0006,lb,Mcf,0 -IC,OTH,CELLBURNER,0.0006,lb,Mcf,0 -IC,OTH,CYCLONE,0.0006,lb,Mcf,0 -IC,OTH,DUCTBURNER,0.0006,lb,Mcf,0 -IC,OTH,FLUIDIZED,0.0006,lb,Mcf,0 -IC,OTH,N/A,0.0006,lb,Mcf,0 -IC,OTH,OTHER,0.0006,lb,Mcf,0 -IC,OTH,STOKER,0.0006,lb,Mcf,0 -IC,OTH,TANGENTIAL,0.0006,lb,Mcf,0 -IC,OTH,VERTICAL,0.0006,lb,Mcf,0 -IC,OTH,WALL,0.0006,lb,Mcf,0 -OT,OTH,CELLBURNER,0.0006,lb,Mcf,0 -OT,OTH,CYCLONE,0.0006,lb,Mcf,0 -OT,OTH,DUCTBURNER,0.0006,lb,Mcf,0 -OT,OTH,FLUIDIZED,0.00006,lb,Mcf,0 -OT,OTH,N/A,0.0006,lb,Mcf,0 -OT,OTH,OTHER,0.0006,lb,Mcf,0 -OT,OTH,STOKER,0.0006,lb,Mcf,0 -OT,OTH,TANGENTIAL,0.0006,lb,Mcf,0 -OT,OTH,VERTICAL,0.0006,lb,Mcf,0 -OT,OTH,WALL,0.0006,lb,Mcf,0 -ST,OTH,CELLBURNER,0.0006,lb,Mcf,0 -ST,OTH,CYCLONE,0.0006,lb,Mcf,0 -ST,OTH,DUCTBURNER,0.0006,lb,Mcf,0 -ST,OTH,FLUIDIZED,0.00006,lb,Mcf,0 -ST,OTH,N/A,0.0006,lb,Mcf,0 -ST,OTH,OTHER,0.0006,lb,Mcf,0 -ST,OTH,STOKER,0.0006,lb,Mcf,0 -ST,OTH,TANGENTIAL,0.0006,lb,Mcf,0 -ST,OTH,VERTICAL,0.0006,lb,Mcf,0 -ST,OTH,WALL,0.0006,lb,Mcf,0 -OT,PC,CELLBURNER,39*S,lb,short ton,1 -OT,PC,CYCLONE,39*S,lb,short ton,1 -OT,PC,DUCTBURNER,39*S,lb,short ton,1 -OT,PC,FLUIDIZED,3.9*S,lb,short ton,1 -OT,PC,N/A,39*S,lb,short ton,1 -OT,PC,OTHER,39*S,lb,short ton,1 -OT,PC,STOKER,39*S,lb,short ton,1 -OT,PC,TANGENTIAL,39*S,lb,short ton,1 -OT,PC,VERTICAL,39*S,lb,short ton,1 -OT,PC,WALL,39*S,lb,short ton,1 -ST,PC,CELLBURNER,39*S,lb,short ton,1 -ST,PC,CYCLONE,39*S,lb,short ton,1 -ST,PC,DUCTBURNER,39*S,lb,short ton,1 -ST,PC,FLUIDIZED,3.9*S,lb,short ton,1 -ST,PC,N/A,39*S,lb,short ton,1 -ST,PC,OTHER,39*S,lb,short ton,1 -ST,PC,STOKER,39*S,lb,short ton,1 -ST,PC,TANGENTIAL,39*S,lb,short ton,1 -ST,PC,VERTICAL,39*S,lb,short ton,1 -ST,PC,WALL,39*S,lb,short ton,1 -CA,PG,CELLBURNER,0.0006,lb,Mcf,0 -CA,PG,CYCLONE,0.0006,lb,Mcf,0 -CA,PG,DUCTBURNER,0.0006,lb,Mcf,0 -CA,PG,FLUIDIZED,0.0006,lb,Mcf,0 -CA,PG,N/A,0.0006,lb,Mcf,0 -CA,PG,OTHER,0.0006,lb,Mcf,0 -CA,PG,STOKER,0.0006,lb,Mcf,0 -CA,PG,TANGENTIAL,0.0006,lb,Mcf,0 -CA,PG,VERTICAL,0.0006,lb,Mcf,0 -CA,PG,WALL,0.0006,lb,Mcf,0 -CS,PG,CELLBURNER,0.0006,lb,Mcf,0 -CS,PG,CYCLONE,0.0006,lb,Mcf,0 -CS,PG,DUCTBURNER,0.0006,lb,Mcf,0 -CS,PG,FLUIDIZED,0.0006,lb,Mcf,0 -CS,PG,N/A,0.0006,lb,Mcf,0 -CS,PG,OTHER,0.0006,lb,Mcf,0 -CS,PG,STOKER,0.0006,lb,Mcf,0 -CS,PG,TANGENTIAL,0.0006,lb,Mcf,0 -CS,PG,VERTICAL,0.0006,lb,Mcf,0 -CS,PG,WALL,0.0006,lb,Mcf,0 -CT,PG,CELLBURNER,0.0006,lb,Mcf,0 -CT,PG,CYCLONE,0.0006,lb,Mcf,0 -CT,PG,DUCTBURNER,0.0006,lb,Mcf,0 -CT,PG,FLUIDIZED,0.0006,lb,Mcf,0 -CT,PG,N/A,0.0006,lb,Mcf,0 -CT,PG,OTHER,0.0006,lb,Mcf,0 -CT,PG,STOKER,0.0006,lb,Mcf,0 -CT,PG,TANGENTIAL,0.0006,lb,Mcf,0 -CT,PG,VERTICAL,0.0006,lb,Mcf,0 -CT,PG,WALL,0.0006,lb,Mcf,0 -GT,PG,CELLBURNER,0.0006,lb,Mcf,0 -GT,PG,CYCLONE,0.0006,lb,Mcf,0 -GT,PG,DUCTBURNER,0.0006,lb,Mcf,0 -GT,PG,FLUIDIZED,0.0006,lb,Mcf,0 -GT,PG,N/A,0.0006,lb,Mcf,0 -GT,PG,OTHER,0.0006,lb,Mcf,0 -GT,PG,STOKER,0.0006,lb,Mcf,0 -GT,PG,TANGENTIAL,0.0006,lb,Mcf,0 -GT,PG,VERTICAL,0.0006,lb,Mcf,0 -GT,PG,WALL,0.0006,lb,Mcf,0 -IC,PG,CELLBURNER,0.0006,lb,Mcf,0 -IC,PG,CYCLONE,0.0006,lb,Mcf,0 -IC,PG,DUCTBURNER,0.0006,lb,Mcf,0 -IC,PG,FLUIDIZED,0.0006,lb,Mcf,0 -IC,PG,N/A,0.0006,lb,Mcf,0 -IC,PG,OTHER,0.0006,lb,Mcf,0 -IC,PG,STOKER,0.0006,lb,Mcf,0 -IC,PG,TANGENTIAL,0.0006,lb,Mcf,0 -IC,PG,VERTICAL,0.0006,lb,Mcf,0 -IC,PG,WALL,0.0006,lb,Mcf,0 -OT,PG,CELLBURNER,0.0006,lb,Mcf,0 -OT,PG,CYCLONE,0.0006,lb,Mcf,0 -OT,PG,DUCTBURNER,0.0006,lb,Mcf,0 -OT,PG,FLUIDIZED,0.00006,lb,Mcf,0 -OT,PG,N/A,0.0006,lb,Mcf,0 -OT,PG,OTHER,0.0006,lb,Mcf,0 -OT,PG,STOKER,0.0006,lb,Mcf,0 -OT,PG,TANGENTIAL,0.0006,lb,Mcf,0 -OT,PG,VERTICAL,0.0006,lb,Mcf,0 -OT,PG,WALL,0.0006,lb,Mcf,0 -ST,PG,CELLBURNER,0.0006,lb,Mcf,0 -ST,PG,CYCLONE,0.0006,lb,Mcf,0 -ST,PG,DUCTBURNER,0.0006,lb,Mcf,0 -ST,PG,FLUIDIZED,0.00006,lb,Mcf,0 -ST,PG,N/A,0.0006,lb,Mcf,0 -ST,PG,OTHER,0.0006,lb,Mcf,0 -ST,PG,STOKER,0.0006,lb,Mcf,0 -ST,PG,TANGENTIAL,0.0006,lb,Mcf,0 -ST,PG,VERTICAL,0.0006,lb,Mcf,0 -ST,PG,WALL,0.0006,lb,Mcf,0 -OT,RC,CELLBURNER,38*S,lb,short ton,1 -OT,RC,CYCLONE,38*S,lb,short ton,1 -OT,RC,DUCTBURNER,38*S,lb,short ton,1 -OT,RC,FLUIDIZED,3.8*S,lb,short ton,1 -OT,RC,N/A,38*S,lb,short ton,1 -OT,RC,OTHER,38*S,lb,short ton,1 -OT,RC,STOKER,38*S,lb,short ton,1 -OT,RC,TANGENTIAL,38*S,lb,short ton,1 -OT,RC,VERTICAL,38*S,lb,short ton,1 -OT,RC,WALL,38*S,lb,short ton,1 -ST,RC,CELLBURNER,38*S,lb,short ton,1 -ST,RC,CYCLONE,38*S,lb,short ton,1 -ST,RC,DUCTBURNER,38*S,lb,short ton,1 -ST,RC,FLUIDIZED,3.8*S,lb,short ton,1 -ST,RC,N/A,38*S,lb,short ton,1 -ST,RC,OTHER,38*S,lb,short ton,1 -ST,RC,STOKER,38*S,lb,short ton,1 -ST,RC,TANGENTIAL,38*S,lb,short ton,1 -ST,RC,VERTICAL,38*S,lb,short ton,1 -ST,RC,WALL,38*S,lb,short ton,1 -CA,RFO,CELLBURNER,5.88*S,lb,barrel,1 -CA,RFO,CYCLONE,5.88*S,lb,barrel,1 -CA,RFO,DUCTBURNER,5.88*S,lb,barrel,1 -CA,RFO,FLUIDIZED,5.88*S,lb,barrel,1 -CA,RFO,N/A,5.88*S,lb,barrel,1 -CA,RFO,OTHER,5.88*S,lb,barrel,1 -CA,RFO,STOKER,5.88*S,lb,barrel,1 -CA,RFO,TANGENTIAL,5.88*S,lb,barrel,1 -CA,RFO,VERTICAL,5.88*S,lb,barrel,1 -CA,RFO,WALL,5.88*S,lb,barrel,1 -CS,RFO,CELLBURNER,5.88*S,lb,barrel,1 -CS,RFO,CYCLONE,5.88*S,lb,barrel,1 -CS,RFO,DUCTBURNER,5.88*S,lb,barrel,1 -CS,RFO,FLUIDIZED,5.88*S,lb,barrel,1 -CS,RFO,N/A,5.88*S,lb,barrel,1 -CS,RFO,OTHER,5.88*S,lb,barrel,1 -CS,RFO,STOKER,5.88*S,lb,barrel,1 -CS,RFO,TANGENTIAL,5.88*S,lb,barrel,1 -CS,RFO,VERTICAL,5.88*S,lb,barrel,1 -CS,RFO,WALL,5.88*S,lb,barrel,1 -CT,RFO,CELLBURNER,5.88*S,lb,barrel,1 -CT,RFO,CYCLONE,5.88*S,lb,barrel,1 -CT,RFO,DUCTBURNER,5.88*S,lb,barrel,1 -CT,RFO,FLUIDIZED,5.88*S,lb,barrel,1 -CT,RFO,N/A,5.88*S,lb,barrel,1 -CT,RFO,OTHER,5.88*S,lb,barrel,1 -CT,RFO,STOKER,5.88*S,lb,barrel,1 -CT,RFO,TANGENTIAL,5.88*S,lb,barrel,1 -CT,RFO,VERTICAL,5.88*S,lb,barrel,1 -CT,RFO,WALL,5.88*S,lb,barrel,1 -GT,RFO,CELLBURNER,5.88*S,lb,barrel,1 -GT,RFO,CYCLONE,5.88*S,lb,barrel,1 -GT,RFO,DUCTBURNER,5.88*S,lb,barrel,1 -GT,RFO,FLUIDIZED,5.88*S,lb,barrel,1 -GT,RFO,N/A,5.88*S,lb,barrel,1 -GT,RFO,OTHER,5.88*S,lb,barrel,1 -GT,RFO,STOKER,5.88*S,lb,barrel,1 -GT,RFO,TANGENTIAL,5.88*S,lb,barrel,1 -GT,RFO,VERTICAL,5.88*S,lb,barrel,1 -GT,RFO,WALL,5.88*S,lb,barrel,1 -IC,RFO,CELLBURNER,5.88*S,lb,barrel,1 -IC,RFO,CYCLONE,5.88*S,lb,barrel,1 -IC,RFO,DUCTBURNER,5.88*S,lb,barrel,1 -IC,RFO,FLUIDIZED,5.88*S,lb,barrel,1 -IC,RFO,N/A,5.88*S,lb,barrel,1 -IC,RFO,OTHER,5.88*S,lb,barrel,1 -IC,RFO,STOKER,5.88*S,lb,barrel,1 -IC,RFO,TANGENTIAL,5.88*S,lb,barrel,1 -IC,RFO,VERTICAL,5.88*S,lb,barrel,1 -IC,RFO,WALL,5.88*S,lb,barrel,1 -OT,RFO,CELLBURNER,6.594*S,lb,barrel,1 -OT,RFO,CYCLONE,6.594*S,lb,barrel,1 -OT,RFO,DUCTBURNER,6.594*S,lb,barrel,1 -OT,RFO,FLUIDIZED,0.6594*S,lb,barrel,1 -OT,RFO,N/A,6.594*S,lb,barrel,1 -OT,RFO,OTHER,6.594*S,lb,barrel,1 -OT,RFO,STOKER,6.594*S,lb,barrel,1 -OT,RFO,TANGENTIAL,6.594*S,lb,barrel,1 -OT,RFO,VERTICAL,6.594*S,lb,barrel,1 -OT,RFO,WALL,6.594*S,lb,barrel,1 -ST,RFO,CELLBURNER,6.594*S,lb,barrel,1 -ST,RFO,CYCLONE,6.594*S,lb,barrel,1 -ST,RFO,DUCTBURNER,6.594*S,lb,barrel,1 -ST,RFO,FLUIDIZED,0.6594*S,lb,barrel,1 -ST,RFO,N/A,6.594*S,lb,barrel,1 -ST,RFO,OTHER,6.594*S,lb,barrel,1 -ST,RFO,STOKER,6.594*S,lb,barrel,1 -ST,RFO,TANGENTIAL,6.594*S,lb,barrel,1 -ST,RFO,VERTICAL,6.594*S,lb,barrel,1 -ST,RFO,WALL,6.594*S,lb,barrel,1 -CA,SGC,CELLBURNER,0.0006,lb,Mcf,0 -CA,SGC,CYCLONE,0.0006,lb,Mcf,0 -CA,SGC,DUCTBURNER,0.0006,lb,Mcf,0 -CA,SGC,FLUIDIZED,0.0006,lb,Mcf,0 -CA,SGC,N/A,0.0006,lb,Mcf,0 -CA,SGC,OTHER,0.0006,lb,Mcf,0 -CA,SGC,STOKER,0.0006,lb,Mcf,0 -CA,SGC,TANGENTIAL,0.0006,lb,Mcf,0 -CA,SGC,VERTICAL,0.0006,lb,Mcf,0 -CA,SGC,WALL,0.0006,lb,Mcf,0 -CS,SGC,CELLBURNER,0.0006,lb,Mcf,0 -CS,SGC,CYCLONE,0.0006,lb,Mcf,0 -CS,SGC,DUCTBURNER,0.0006,lb,Mcf,0 -CS,SGC,FLUIDIZED,0.0006,lb,Mcf,0 -CS,SGC,N/A,0.0006,lb,Mcf,0 -CS,SGC,OTHER,0.0006,lb,Mcf,0 -CS,SGC,STOKER,0.0006,lb,Mcf,0 -CS,SGC,TANGENTIAL,0.0006,lb,Mcf,0 -CS,SGC,VERTICAL,0.0006,lb,Mcf,0 -CS,SGC,WALL,0.0006,lb,Mcf,0 -CT,SGC,CELLBURNER,0.0006,lb,Mcf,0 -CT,SGC,CYCLONE,0.0006,lb,Mcf,0 -CT,SGC,DUCTBURNER,0.0006,lb,Mcf,0 -CT,SGC,FLUIDIZED,0.0006,lb,Mcf,0 -CT,SGC,N/A,0.0006,lb,Mcf,0 -CT,SGC,OTHER,0.0006,lb,Mcf,0 -CT,SGC,STOKER,0.0006,lb,Mcf,0 -CT,SGC,TANGENTIAL,0.0006,lb,Mcf,0 -CT,SGC,VERTICAL,0.0006,lb,Mcf,0 -CT,SGC,WALL,0.0006,lb,Mcf,0 -GT,SGC,CELLBURNER,0.0006,lb,Mcf,0 -GT,SGC,CYCLONE,0.0006,lb,Mcf,0 -GT,SGC,DUCTBURNER,0.0006,lb,Mcf,0 -GT,SGC,FLUIDIZED,0.0006,lb,Mcf,0 -GT,SGC,N/A,0.0006,lb,Mcf,0 -GT,SGC,OTHER,0.0006,lb,Mcf,0 -GT,SGC,STOKER,0.0006,lb,Mcf,0 -GT,SGC,TANGENTIAL,0.0006,lb,Mcf,0 -GT,SGC,VERTICAL,0.0006,lb,Mcf,0 -GT,SGC,WALL,0.0006,lb,Mcf,0 -IC,SGC,CELLBURNER,0.0006,lb,Mcf,0 -IC,SGC,CYCLONE,0.0006,lb,Mcf,0 -IC,SGC,DUCTBURNER,0.0006,lb,Mcf,0 -IC,SGC,FLUIDIZED,0.0006,lb,Mcf,0 -IC,SGC,N/A,0.0006,lb,Mcf,0 -IC,SGC,OTHER,0.0006,lb,Mcf,0 -IC,SGC,STOKER,0.0006,lb,Mcf,0 -IC,SGC,TANGENTIAL,0.0006,lb,Mcf,0 -IC,SGC,VERTICAL,0.0006,lb,Mcf,0 -IC,SGC,WALL,0.0006,lb,Mcf,0 -OT,SGC,CELLBURNER,0.0006,lb,Mcf,0 -OT,SGC,CYCLONE,0.0006,lb,Mcf,0 -OT,SGC,DUCTBURNER,0.0006,lb,Mcf,0 -OT,SGC,FLUIDIZED,0.00006,lb,Mcf,0 -OT,SGC,N/A,0.0006,lb,Mcf,0 -OT,SGC,OTHER,0.0006,lb,Mcf,0 -OT,SGC,STOKER,0.0006,lb,Mcf,0 -OT,SGC,TANGENTIAL,0.0006,lb,Mcf,0 -OT,SGC,VERTICAL,0.0006,lb,Mcf,0 -OT,SGC,WALL,0.0006,lb,Mcf,0 -ST,SGC,CELLBURNER,0.0006,lb,Mcf,0 -ST,SGC,CYCLONE,0.0006,lb,Mcf,0 -ST,SGC,DUCTBURNER,0.0006,lb,Mcf,0 -ST,SGC,FLUIDIZED,0.00006,lb,Mcf,0 -ST,SGC,N/A,0.0006,lb,Mcf,0 -ST,SGC,OTHER,0.0006,lb,Mcf,0 -ST,SGC,STOKER,0.0006,lb,Mcf,0 -ST,SGC,TANGENTIAL,0.0006,lb,Mcf,0 -ST,SGC,VERTICAL,0.0006,lb,Mcf,0 -ST,SGC,WALL,0.0006,lb,Mcf,0 -CA,SGP,CELLBURNER,0.0006,lb,Mcf,0 -CA,SGP,CYCLONE,0.0006,lb,Mcf,0 -CA,SGP,DUCTBURNER,0.0006,lb,Mcf,0 -CA,SGP,FLUIDIZED,0.0006,lb,Mcf,0 -CA,SGP,N/A,0.0006,lb,Mcf,0 -CA,SGP,OTHER,0.0006,lb,Mcf,0 -CA,SGP,STOKER,0.0006,lb,Mcf,0 -CA,SGP,TANGENTIAL,0.0006,lb,Mcf,0 -CA,SGP,VERTICAL,0.0006,lb,Mcf,0 -CA,SGP,WALL,0.0006,lb,Mcf,0 -CS,SGP,CELLBURNER,0.0006,lb,Mcf,0 -CS,SGP,CYCLONE,0.0006,lb,Mcf,0 -CS,SGP,DUCTBURNER,0.0006,lb,Mcf,0 -CS,SGP,FLUIDIZED,0.0006,lb,Mcf,0 -CS,SGP,N/A,0.0006,lb,Mcf,0 -CS,SGP,OTHER,0.0006,lb,Mcf,0 -CS,SGP,STOKER,0.0006,lb,Mcf,0 -CS,SGP,TANGENTIAL,0.0006,lb,Mcf,0 -CS,SGP,VERTICAL,0.0006,lb,Mcf,0 -CS,SGP,WALL,0.0006,lb,Mcf,0 -CT,SGP,CELLBURNER,0.0006,lb,Mcf,0 -CT,SGP,CYCLONE,0.0006,lb,Mcf,0 -CT,SGP,DUCTBURNER,0.0006,lb,Mcf,0 -CT,SGP,FLUIDIZED,0.0006,lb,Mcf,0 -CT,SGP,N/A,0.0006,lb,Mcf,0 -CT,SGP,OTHER,0.0006,lb,Mcf,0 -CT,SGP,STOKER,0.0006,lb,Mcf,0 -CT,SGP,TANGENTIAL,0.0006,lb,Mcf,0 -CT,SGP,VERTICAL,0.0006,lb,Mcf,0 -CT,SGP,WALL,0.0006,lb,Mcf,0 -GT,SGP,CELLBURNER,0.0006,lb,Mcf,0 -GT,SGP,CYCLONE,0.0006,lb,Mcf,0 -GT,SGP,DUCTBURNER,0.0006,lb,Mcf,0 -GT,SGP,FLUIDIZED,0.0006,lb,Mcf,0 -GT,SGP,N/A,0.0006,lb,Mcf,0 -GT,SGP,OTHER,0.0006,lb,Mcf,0 -GT,SGP,STOKER,0.0006,lb,Mcf,0 -GT,SGP,TANGENTIAL,0.0006,lb,Mcf,0 -GT,SGP,VERTICAL,0.0006,lb,Mcf,0 -GT,SGP,WALL,0.0006,lb,Mcf,0 -IC,SGP,CELLBURNER,0.0006,lb,Mcf,0 -IC,SGP,CYCLONE,0.0006,lb,Mcf,0 -IC,SGP,DUCTBURNER,0.0006,lb,Mcf,0 -IC,SGP,FLUIDIZED,0.0006,lb,Mcf,0 -IC,SGP,N/A,0.0006,lb,Mcf,0 -IC,SGP,OTHER,0.0006,lb,Mcf,0 -IC,SGP,STOKER,0.0006,lb,Mcf,0 -IC,SGP,TANGENTIAL,0.0006,lb,Mcf,0 -IC,SGP,VERTICAL,0.0006,lb,Mcf,0 -IC,SGP,WALL,0.0006,lb,Mcf,0 -OT,SGP,CELLBURNER,0.0006,lb,Mcf,0 -OT,SGP,CYCLONE,0.0006,lb,Mcf,0 -OT,SGP,DUCTBURNER,0.0006,lb,Mcf,0 -OT,SGP,FLUIDIZED,0.00006,lb,Mcf,0 -OT,SGP,N/A,0.0006,lb,Mcf,0 -OT,SGP,OTHER,0.0006,lb,Mcf,0 -OT,SGP,STOKER,0.0006,lb,Mcf,0 -OT,SGP,TANGENTIAL,0.0006,lb,Mcf,0 -OT,SGP,VERTICAL,0.0006,lb,Mcf,0 -OT,SGP,WALL,0.0006,lb,Mcf,0 -ST,SGP,CELLBURNER,0.0006,lb,Mcf,0 -ST,SGP,CYCLONE,0.0006,lb,Mcf,0 -ST,SGP,DUCTBURNER,0.0006,lb,Mcf,0 -ST,SGP,FLUIDIZED,0.00006,lb,Mcf,0 -ST,SGP,N/A,0.0006,lb,Mcf,0 -ST,SGP,OTHER,0.0006,lb,Mcf,0 -ST,SGP,STOKER,0.0006,lb,Mcf,0 -ST,SGP,TANGENTIAL,0.0006,lb,Mcf,0 -ST,SGP,VERTICAL,0.0006,lb,Mcf,0 -ST,SGP,WALL,0.0006,lb,Mcf,0 -OT,SLW,CELLBURNER,2.8,lb,short ton,0 -OT,SLW,CYCLONE,2.8,lb,short ton,0 -OT,SLW,DUCTBURNER,2.8,lb,short ton,0 -OT,SLW,FLUIDIZED,0.28,lb,short ton,0 -OT,SLW,N/A,2.8,lb,short ton,0 -OT,SLW,OTHER,2.8,lb,short ton,0 -OT,SLW,STOKER,2.8,lb,short ton,0 -OT,SLW,TANGENTIAL,2.8,lb,short ton,0 -OT,SLW,VERTICAL,2.8,lb,short ton,0 -OT,SLW,WALL,2.8,lb,short ton,0 -ST,SLW,CELLBURNER,2.8,lb,short ton,0 -ST,SLW,CYCLONE,2.8,lb,short ton,0 -ST,SLW,DUCTBURNER,2.8,lb,short ton,0 -ST,SLW,FLUIDIZED,0.28,lb,short ton,0 -ST,SLW,N/A,2.8,lb,short ton,0 -ST,SLW,OTHER,2.8,lb,short ton,0 -ST,SLW,STOKER,2.8,lb,short ton,0 -ST,SLW,TANGENTIAL,2.8,lb,short ton,0 -ST,SLW,VERTICAL,2.8,lb,short ton,0 -ST,SLW,WALL,2.8,lb,short ton,0 -OT,SUB,CELLBURNER,35*S,lb,short ton,1 -OT,SUB,CYCLONE,35*S,lb,short ton,1 -OT,SUB,DUCTBURNER,35*S,lb,short ton,1 -OT,SUB,FLUIDIZED,3.5*S,lb,short ton,1 -OT,SUB,N/A,35*S,lb,short ton,1 -OT,SUB,OTHER,35*S,lb,short ton,1 -OT,SUB,STOKER,35*S,lb,short ton,1 -OT,SUB,TANGENTIAL,35*S,lb,short ton,1 -OT,SUB,VERTICAL,35*S,lb,short ton,1 -OT,SUB,WALL,35*S,lb,short ton,1 -ST,SUB,CELLBURNER,35*S,lb,short ton,1 -ST,SUB,CYCLONE,35*S,lb,short ton,1 -ST,SUB,DUCTBURNER,35*S,lb,short ton,1 -ST,SUB,FLUIDIZED,3.5*S,lb,short ton,1 -ST,SUB,N/A,35*S,lb,short ton,1 -ST,SUB,OTHER,35*S,lb,short ton,1 -ST,SUB,STOKER,35*S,lb,short ton,1 -ST,SUB,TANGENTIAL,35*S,lb,short ton,1 -ST,SUB,VERTICAL,35*S,lb,short ton,1 -ST,SUB,WALL,35*S,lb,short ton,1 -OT,TDF,CELLBURNER,38*S,lb,short ton,1 -OT,TDF,CYCLONE,38*S,lb,short ton,1 -OT,TDF,DUCTBURNER,38*S,lb,short ton,1 -OT,TDF,FLUIDIZED,3.8*S,lb,short ton,1 -OT,TDF,N/A,38*S,lb,short ton,1 -OT,TDF,OTHER,38*S,lb,short ton,1 -OT,TDF,STOKER,38*S,lb,short ton,1 -OT,TDF,TANGENTIAL,38*S,lb,short ton,1 -OT,TDF,VERTICAL,38*S,lb,short ton,1 -OT,TDF,WALL,38*S,lb,short ton,1 -ST,TDF,CELLBURNER,38*S,lb,short ton,1 -ST,TDF,CYCLONE,38*S,lb,short ton,1 -ST,TDF,DUCTBURNER,38*S,lb,short ton,1 -ST,TDF,FLUIDIZED,3.8*S,lb,short ton,1 -ST,TDF,N/A,38*S,lb,short ton,1 -ST,TDF,OTHER,38*S,lb,short ton,1 -ST,TDF,STOKER,38*S,lb,short ton,1 -ST,TDF,TANGENTIAL,38*S,lb,short ton,1 -ST,TDF,VERTICAL,38*S,lb,short ton,1 -ST,TDF,WALL,38*S,lb,short ton,1 -OT,WC,CELLBURNER,30*S,lb,short ton,1 -OT,WC,CYCLONE,30*S,lb,short ton,1 -OT,WC,DUCTBURNER,30*S,lb,short ton,1 -OT,WC,FLUIDIZED,3*S,lb,short ton,1 -OT,WC,N/A,30*S,lb,short ton,1 -OT,WC,OTHER,30*S,lb,short ton,1 -OT,WC,STOKER,30*S,lb,short ton,1 -OT,WC,TANGENTIAL,30*S,lb,short ton,1 -OT,WC,VERTICAL,30*S,lb,short ton,1 -OT,WC,WALL,30*S,lb,short ton,1 -ST,WC,CELLBURNER,30*S,lb,short ton,1 -ST,WC,CYCLONE,30*S,lb,short ton,1 -ST,WC,DUCTBURNER,30*S,lb,short ton,1 -ST,WC,FLUIDIZED,3*S,lb,short ton,1 -ST,WC,N/A,30*S,lb,short ton,1 -ST,WC,OTHER,30*S,lb,short ton,1 -ST,WC,STOKER,30*S,lb,short ton,1 -ST,WC,TANGENTIAL,30*S,lb,short ton,1 -ST,WC,VERTICAL,30*S,lb,short ton,1 -ST,WC,WALL,30*S,lb,short ton,1 -CA,WDL,CELLBURNER,5.88*S,lb,barrel,1 -CA,WDL,CYCLONE,5.88*S,lb,barrel,1 -CA,WDL,DUCTBURNER,5.88*S,lb,barrel,1 -CA,WDL,FLUIDIZED,5.88*S,lb,barrel,1 -CA,WDL,N/A,5.88*S,lb,barrel,1 -CA,WDL,OTHER,5.88*S,lb,barrel,1 -CA,WDL,STOKER,5.88*S,lb,barrel,1 -CA,WDL,TANGENTIAL,5.88*S,lb,barrel,1 -CA,WDL,VERTICAL,5.88*S,lb,barrel,1 -CA,WDL,WALL,5.88*S,lb,barrel,1 -CS,WDL,CELLBURNER,5.88*S,lb,barrel,1 -CS,WDL,CYCLONE,5.88*S,lb,barrel,1 -CS,WDL,DUCTBURNER,5.88*S,lb,barrel,1 -CS,WDL,FLUIDIZED,5.88*S,lb,barrel,1 -CS,WDL,N/A,5.88*S,lb,barrel,1 -CS,WDL,OTHER,5.88*S,lb,barrel,1 -CS,WDL,STOKER,5.88*S,lb,barrel,1 -CS,WDL,TANGENTIAL,5.88*S,lb,barrel,1 -CS,WDL,VERTICAL,5.88*S,lb,barrel,1 -CS,WDL,WALL,5.88*S,lb,barrel,1 -CT,WDL,CELLBURNER,5.88*S,lb,barrel,1 -CT,WDL,CYCLONE,5.88*S,lb,barrel,1 -CT,WDL,DUCTBURNER,5.88*S,lb,barrel,1 -CT,WDL,FLUIDIZED,5.88*S,lb,barrel,1 -CT,WDL,N/A,5.88*S,lb,barrel,1 -CT,WDL,OTHER,5.88*S,lb,barrel,1 -CT,WDL,STOKER,5.88*S,lb,barrel,1 -CT,WDL,TANGENTIAL,5.88*S,lb,barrel,1 -CT,WDL,VERTICAL,5.88*S,lb,barrel,1 -CT,WDL,WALL,5.88*S,lb,barrel,1 -GT,WDL,CELLBURNER,5.88*S,lb,barrel,1 -GT,WDL,CYCLONE,5.88*S,lb,barrel,1 -GT,WDL,DUCTBURNER,5.88*S,lb,barrel,1 -GT,WDL,FLUIDIZED,5.88*S,lb,barrel,1 -GT,WDL,N/A,5.88*S,lb,barrel,1 -GT,WDL,OTHER,5.88*S,lb,barrel,1 -GT,WDL,STOKER,5.88*S,lb,barrel,1 -GT,WDL,TANGENTIAL,5.88*S,lb,barrel,1 -GT,WDL,VERTICAL,5.88*S,lb,barrel,1 -GT,WDL,WALL,5.88*S,lb,barrel,1 -IC,WDL,CELLBURNER,5.88*S,lb,barrel,1 -IC,WDL,CYCLONE,5.88*S,lb,barrel,1 -IC,WDL,DUCTBURNER,5.88*S,lb,barrel,1 -IC,WDL,FLUIDIZED,5.88*S,lb,barrel,1 -IC,WDL,N/A,5.88*S,lb,barrel,1 -IC,WDL,OTHER,5.88*S,lb,barrel,1 -IC,WDL,STOKER,5.88*S,lb,barrel,1 -IC,WDL,TANGENTIAL,5.88*S,lb,barrel,1 -IC,WDL,VERTICAL,5.88*S,lb,barrel,1 -IC,WDL,WALL,5.88*S,lb,barrel,1 -OT,WDL,CELLBURNER,5.964*S,lb,barrel,1 -OT,WDL,CYCLONE,5.964*S,lb,barrel,1 -OT,WDL,DUCTBURNER,5.964*S,lb,barrel,1 -OT,WDL,FLUIDIZED,0.5964*S,lb,barrel,1 -OT,WDL,N/A,5.964*S,lb,barrel,1 -OT,WDL,OTHER,5.964*S,lb,barrel,1 -OT,WDL,STOKER,5.964*S,lb,barrel,1 -OT,WDL,TANGENTIAL,5.964*S,lb,barrel,1 -OT,WDL,VERTICAL,5.964*S,lb,barrel,1 -OT,WDL,WALL,5.964*S,lb,barrel,1 -ST,WDL,CELLBURNER,5.964*S,lb,barrel,1 -ST,WDL,CYCLONE,5.964*S,lb,barrel,1 -ST,WDL,DUCTBURNER,5.964*S,lb,barrel,1 -ST,WDL,FLUIDIZED,0.5964*S,lb,barrel,1 -ST,WDL,N/A,5.964*S,lb,barrel,1 -ST,WDL,OTHER,5.964*S,lb,barrel,1 -ST,WDL,STOKER,5.964*S,lb,barrel,1 -ST,WDL,TANGENTIAL,5.964*S,lb,barrel,1 -ST,WDL,VERTICAL,5.964*S,lb,barrel,1 -ST,WDL,WALL,5.964*S,lb,barrel,1 -OT,WDS,CELLBURNER,0.29,lb,short ton,0 -OT,WDS,CYCLONE,0.29,lb,short ton,0 -OT,WDS,DUCTBURNER,0.29,lb,short ton,0 -OT,WDS,FLUIDIZED,0.08,lb,short ton,0 -OT,WDS,N/A,0.29,lb,short ton,0 -OT,WDS,OTHER,0.29,lb,short ton,0 -OT,WDS,STOKER,0.08,lb,short ton,0 -OT,WDS,TANGENTIAL,0.29,lb,short ton,0 -OT,WDS,VERTICAL,0.29,lb,short ton,0 -OT,WDS,WALL,0.29,lb,short ton,0 -ST,WDS,CELLBURNER,0.29,lb,short ton,0 -ST,WDS,CYCLONE,0.29,lb,short ton,0 -ST,WDS,DUCTBURNER,0.29,lb,short ton,0 -ST,WDS,FLUIDIZED,0.08,lb,short ton,0 -ST,WDS,N/A,0.29,lb,short ton,0 -ST,WDS,OTHER,0.29,lb,short ton,0 -ST,WDS,STOKER,0.08,lb,short ton,0 -ST,WDS,TANGENTIAL,0.29,lb,short ton,0 -ST,WDS,VERTICAL,0.29,lb,short ton,0 -ST,WDS,WALL,0.29,lb,short ton,0 -CA,WO,CELLBURNER,5.88*S,lb,barrel,1 -CA,WO,CYCLONE,5.88*S,lb,barrel,1 -CA,WO,DUCTBURNER,5.88*S,lb,barrel,1 -CA,WO,FLUIDIZED,5.88*S,lb,barrel,1 -CA,WO,N/A,5.88*S,lb,barrel,1 -CA,WO,OTHER,5.88*S,lb,barrel,1 -CA,WO,STOKER,5.88*S,lb,barrel,1 -CA,WO,TANGENTIAL,5.88*S,lb,barrel,1 -CA,WO,VERTICAL,5.88*S,lb,barrel,1 -CA,WO,WALL,5.88*S,lb,barrel,1 -CS,WO,CELLBURNER,5.88*S,lb,barrel,1 -CS,WO,CYCLONE,5.88*S,lb,barrel,1 -CS,WO,DUCTBURNER,5.88*S,lb,barrel,1 -CS,WO,FLUIDIZED,5.88*S,lb,barrel,1 -CS,WO,N/A,5.88*S,lb,barrel,1 -CS,WO,OTHER,5.88*S,lb,barrel,1 -CS,WO,STOKER,5.88*S,lb,barrel,1 -CS,WO,TANGENTIAL,5.88*S,lb,barrel,1 -CS,WO,VERTICAL,5.88*S,lb,barrel,1 -CS,WO,WALL,5.88*S,lb,barrel,1 -CT,WO,CELLBURNER,5.88*S,lb,barrel,1 -CT,WO,CYCLONE,5.88*S,lb,barrel,1 -CT,WO,DUCTBURNER,5.88*S,lb,barrel,1 -CT,WO,FLUIDIZED,5.88*S,lb,barrel,1 -CT,WO,N/A,5.88*S,lb,barrel,1 -CT,WO,OTHER,5.88*S,lb,barrel,1 -CT,WO,STOKER,5.88*S,lb,barrel,1 -CT,WO,TANGENTIAL,5.88*S,lb,barrel,1 -CT,WO,VERTICAL,5.88*S,lb,barrel,1 -CT,WO,WALL,5.88*S,lb,barrel,1 -GT,WO,CELLBURNER,5.88*S,lb,barrel,1 -GT,WO,CYCLONE,5.88*S,lb,barrel,1 -GT,WO,DUCTBURNER,5.88*S,lb,barrel,1 -GT,WO,FLUIDIZED,5.88*S,lb,barrel,1 -GT,WO,N/A,5.88*S,lb,barrel,1 -GT,WO,OTHER,5.88*S,lb,barrel,1 -GT,WO,STOKER,5.88*S,lb,barrel,1 -GT,WO,TANGENTIAL,5.88*S,lb,barrel,1 -GT,WO,VERTICAL,5.88*S,lb,barrel,1 -GT,WO,WALL,5.88*S,lb,barrel,1 -IC,WO,CELLBURNER,5.88*S,lb,barrel,1 -IC,WO,CYCLONE,5.88*S,lb,barrel,1 -IC,WO,DUCTBURNER,5.88*S,lb,barrel,1 -IC,WO,FLUIDIZED,5.88*S,lb,barrel,1 -IC,WO,N/A,5.88*S,lb,barrel,1 -IC,WO,OTHER,5.88*S,lb,barrel,1 -IC,WO,STOKER,5.88*S,lb,barrel,1 -IC,WO,TANGENTIAL,5.88*S,lb,barrel,1 -IC,WO,VERTICAL,5.88*S,lb,barrel,1 -IC,WO,WALL,5.88*S,lb,barrel,1 -OT,WO,CELLBURNER,6.174*S,lb,barrel,1 -OT,WO,CYCLONE,6.174*S,lb,barrel,1 -OT,WO,DUCTBURNER,6.174*S,lb,barrel,1 -OT,WO,FLUIDIZED,0.6174*S,lb,barrel,1 -OT,WO,N/A,6.174*S,lb,barrel,1 -OT,WO,OTHER,6.174*S,lb,barrel,1 -OT,WO,STOKER,6.174*S,lb,barrel,1 -OT,WO,TANGENTIAL,6.174*S,lb,barrel,1 -OT,WO,VERTICAL,6.174*S,lb,barrel,1 -OT,WO,WALL,6.174*S,lb,barrel,1 -ST,WO,CELLBURNER,6.174*S,lb,barrel,1 -ST,WO,CYCLONE,6.174*S,lb,barrel,1 -ST,WO,DUCTBURNER,6.174*S,lb,barrel,1 -ST,WO,FLUIDIZED,0.6174*S,lb,barrel,1 -ST,WO,N/A,6.174*S,lb,barrel,1 -ST,WO,OTHER,6.174*S,lb,barrel,1 -ST,WO,STOKER,6.174*S,lb,barrel,1 -ST,WO,TANGENTIAL,6.174*S,lb,barrel,1 -ST,WO,VERTICAL,6.174*S,lb,barrel,1 -ST,WO,WALL,6.174*S,lb,barrel,1 +OT,AB,cell_burner,0.08,lb,short ton,0 +OT,AB,cyclone_firing,0.08,lb,short ton,0 +OT,AB,duct_burner,0.08,lb,short ton,0 +OT,AB,fluidized_bed_firing,0.01,lb,short ton,0 +OT,AB,none,0.08,lb,short ton,0 +OT,AB,other,0.08,lb,short ton,0 +OT,AB,stoker,0.08,lb,short ton,0 +OT,AB,tangential_firing,0.08,lb,short ton,0 +OT,AB,vertical_firing,0.08,lb,short ton,0 +OT,AB,wall_fired,0.08,lb,short ton,0 +ST,AB,cell_burner,0.08,lb,short ton,0 +ST,AB,cyclone_firing,0.08,lb,short ton,0 +ST,AB,duct_burner,0.08,lb,short ton,0 +ST,AB,fluidized_bed_firing,0.01,lb,short ton,0 +ST,AB,none,0.08,lb,short ton,0 +ST,AB,other,0.08,lb,short ton,0 +ST,AB,stoker,0.08,lb,short ton,0 +ST,AB,tangential_firing,0.08,lb,short ton,0 +ST,AB,vertical_firing,0.08,lb,short ton,0 +ST,AB,wall_fired,0.08,lb,short ton,0 +CA,BFG,cell_burner,0.0006,lb,Mcf,0 +CA,BFG,cyclone_firing,0.0006,lb,Mcf,0 +CA,BFG,duct_burner,0.0006,lb,Mcf,0 +CA,BFG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CA,BFG,none,0.0006,lb,Mcf,0 +CA,BFG,other,0.0006,lb,Mcf,0 +CA,BFG,stoker,0.0006,lb,Mcf,0 +CA,BFG,tangential_firing,0.0006,lb,Mcf,0 +CA,BFG,vertical_firing,0.0006,lb,Mcf,0 +CA,BFG,wall_fired,0.0006,lb,Mcf,0 +CS,BFG,cell_burner,0.0006,lb,Mcf,0 +CS,BFG,cyclone_firing,0.0006,lb,Mcf,0 +CS,BFG,duct_burner,0.0006,lb,Mcf,0 +CS,BFG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CS,BFG,none,0.0006,lb,Mcf,0 +CS,BFG,other,0.0006,lb,Mcf,0 +CS,BFG,stoker,0.0006,lb,Mcf,0 +CS,BFG,tangential_firing,0.0006,lb,Mcf,0 +CS,BFG,vertical_firing,0.0006,lb,Mcf,0 +CS,BFG,wall_fired,0.0006,lb,Mcf,0 +CT,BFG,cell_burner,0.0006,lb,Mcf,0 +CT,BFG,cyclone_firing,0.0006,lb,Mcf,0 +CT,BFG,duct_burner,0.0006,lb,Mcf,0 +CT,BFG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CT,BFG,none,0.0006,lb,Mcf,0 +CT,BFG,other,0.0006,lb,Mcf,0 +CT,BFG,stoker,0.0006,lb,Mcf,0 +CT,BFG,tangential_firing,0.0006,lb,Mcf,0 +CT,BFG,vertical_firing,0.0006,lb,Mcf,0 +CT,BFG,wall_fired,0.0006,lb,Mcf,0 +GT,BFG,cell_burner,0.0006,lb,Mcf,0 +GT,BFG,cyclone_firing,0.0006,lb,Mcf,0 +GT,BFG,duct_burner,0.0006,lb,Mcf,0 +GT,BFG,fluidized_bed_firing,0.0006,lb,Mcf,0 +GT,BFG,none,0.0006,lb,Mcf,0 +GT,BFG,other,0.0006,lb,Mcf,0 +GT,BFG,stoker,0.0006,lb,Mcf,0 +GT,BFG,tangential_firing,0.0006,lb,Mcf,0 +GT,BFG,vertical_firing,0.0006,lb,Mcf,0 +GT,BFG,wall_fired,0.0006,lb,Mcf,0 +IC,BFG,cell_burner,0.0006,lb,Mcf,0 +IC,BFG,cyclone_firing,0.0006,lb,Mcf,0 +IC,BFG,duct_burner,0.0006,lb,Mcf,0 +IC,BFG,fluidized_bed_firing,0.0006,lb,Mcf,0 +IC,BFG,none,0.0006,lb,Mcf,0 +IC,BFG,other,0.0006,lb,Mcf,0 +IC,BFG,stoker,0.0006,lb,Mcf,0 +IC,BFG,tangential_firing,0.0006,lb,Mcf,0 +IC,BFG,vertical_firing,0.0006,lb,Mcf,0 +IC,BFG,wall_fired,0.0006,lb,Mcf,0 +OT,BFG,cell_burner,0.0006,lb,Mcf,0 +OT,BFG,cyclone_firing,0.0006,lb,Mcf,0 +OT,BFG,duct_burner,0.0006,lb,Mcf,0 +OT,BFG,fluidized_bed_firing,0.00006,lb,Mcf,0 +OT,BFG,none,0.0006,lb,Mcf,0 +OT,BFG,other,0.0006,lb,Mcf,0 +OT,BFG,stoker,0.0006,lb,Mcf,0 +OT,BFG,tangential_firing,0.0006,lb,Mcf,0 +OT,BFG,vertical_firing,0.0006,lb,Mcf,0 +OT,BFG,wall_fired,0.0006,lb,Mcf,0 +ST,BFG,cell_burner,0.0006,lb,Mcf,0 +ST,BFG,cyclone_firing,0.0006,lb,Mcf,0 +ST,BFG,duct_burner,0.0006,lb,Mcf,0 +ST,BFG,fluidized_bed_firing,0.00006,lb,Mcf,0 +ST,BFG,none,0.0006,lb,Mcf,0 +ST,BFG,other,0.0006,lb,Mcf,0 +ST,BFG,stoker,0.0006,lb,Mcf,0 +ST,BFG,tangential_firing,0.0006,lb,Mcf,0 +ST,BFG,vertical_firing,0.0006,lb,Mcf,0 +ST,BFG,wall_fired,0.0006,lb,Mcf,0 +CA,BIT,duct_burner,38*S,lb,short ton,1 +OT,BIT,cell_burner,38*S,lb,short ton,1 +OT,BIT,cyclone_firing,38*S,lb,short ton,1 +OT,BIT,duct_burner,38*S,lb,short ton,1 +OT,BIT,fluidized_bed_firing,3.8*S,lb,short ton,1 +OT,BIT,none,38*S,lb,short ton,1 +OT,BIT,other,38*S,lb,short ton,1 +OT,BIT,stoker,38*S,lb,short ton,1 +OT,BIT,tangential_firing,38*S,lb,short ton,1 +OT,BIT,vertical_firing,38*S,lb,short ton,1 +OT,BIT,wall_fired,38*S,lb,short ton,1 +ST,BIT,cell_burner,38*S,lb,short ton,1 +ST,BIT,cyclone_firing,38*S,lb,short ton,1 +ST,BIT,duct_burner,38*S,lb,short ton,1 +ST,BIT,fluidized_bed_firing,3.8*S,lb,short ton,1 +ST,BIT,none,38*S,lb,short ton,1 +ST,BIT,other,38*S,lb,short ton,1 +ST,BIT,stoker,38*S,lb,short ton,1 +ST,BIT,tangential_firing,38*S,lb,short ton,1 +ST,BIT,vertical_firing,38*S,lb,short ton,1 +ST,BIT,wall_fired,38*S,lb,short ton,1 +OT,BLQ,cell_burner,7,lb,short ton,0 +OT,BLQ,cyclone_firing,7,lb,short ton,0 +OT,BLQ,duct_burner,7,lb,short ton,0 +OT,BLQ,fluidized_bed_firing,0.7,lb,short ton,0 +OT,BLQ,none,7,lb,short ton,0 +OT,BLQ,other,7,lb,short ton,0 +OT,BLQ,stoker,7,lb,short ton,0 +OT,BLQ,tangential_firing,7,lb,short ton,0 +OT,BLQ,vertical_firing,7,lb,short ton,0 +OT,BLQ,wall_fired,7,lb,short ton,0 +ST,BLQ,cell_burner,7,lb,short ton,0 +ST,BLQ,cyclone_firing,7,lb,short ton,0 +ST,BLQ,duct_burner,7,lb,short ton,0 +ST,BLQ,fluidized_bed_firing,0.7,lb,short ton,0 +ST,BLQ,none,7,lb,short ton,0 +ST,BLQ,other,7,lb,short ton,0 +ST,BLQ,stoker,7,lb,short ton,0 +ST,BLQ,tangential_firing,7,lb,short ton,0 +ST,BLQ,vertical_firing,7,lb,short ton,0 +ST,BLQ,wall_fired,7,lb,short ton,0 +CA,DFO,cell_burner,5.88*S,lb,barrel,1 +CA,DFO,cyclone_firing,5.88*S,lb,barrel,1 +CA,DFO,duct_burner,5.88*S,lb,barrel,1 +CA,DFO,fluidized_bed_firing,5.88*S,lb,barrel,1 +CA,DFO,none,5.88*S,lb,barrel,1 +CA,DFO,other,5.88*S,lb,barrel,1 +CA,DFO,stoker,5.88*S,lb,barrel,1 +CA,DFO,tangential_firing,5.88*S,lb,barrel,1 +CA,DFO,vertical_firing,5.88*S,lb,barrel,1 +CA,DFO,wall_fired,5.88*S,lb,barrel,1 +CS,DFO,cell_burner,5.88*S,lb,barrel,1 +CS,DFO,cyclone_firing,5.88*S,lb,barrel,1 +CS,DFO,duct_burner,5.88*S,lb,barrel,1 +CS,DFO,fluidized_bed_firing,5.88*S,lb,barrel,1 +CS,DFO,none,5.88*S,lb,barrel,1 +CS,DFO,other,5.88*S,lb,barrel,1 +CS,DFO,stoker,5.88*S,lb,barrel,1 +CS,DFO,tangential_firing,5.88*S,lb,barrel,1 +CS,DFO,vertical_firing,5.88*S,lb,barrel,1 +CS,DFO,wall_fired,5.88*S,lb,barrel,1 +CT,DFO,cell_burner,5.88*S,lb,barrel,1 +CT,DFO,cyclone_firing,5.88*S,lb,barrel,1 +CT,DFO,duct_burner,5.88*S,lb,barrel,1 +CT,DFO,fluidized_bed_firing,5.88*S,lb,barrel,1 +CT,DFO,none,5.88*S,lb,barrel,1 +CT,DFO,other,5.88*S,lb,barrel,1 +CT,DFO,stoker,5.88*S,lb,barrel,1 +CT,DFO,tangential_firing,5.88*S,lb,barrel,1 +CT,DFO,vertical_firing,5.88*S,lb,barrel,1 +CT,DFO,wall_fired,5.88*S,lb,barrel,1 +GT,DFO,cell_burner,5.88*S,lb,barrel,1 +GT,DFO,cyclone_firing,5.88*S,lb,barrel,1 +GT,DFO,duct_burner,5.88*S,lb,barrel,1 +GT,DFO,fluidized_bed_firing,5.88*S,lb,barrel,1 +GT,DFO,none,5.88*S,lb,barrel,1 +GT,DFO,other,5.88*S,lb,barrel,1 +GT,DFO,stoker,5.88*S,lb,barrel,1 +GT,DFO,tangential_firing,5.88*S,lb,barrel,1 +GT,DFO,vertical_firing,5.88*S,lb,barrel,1 +GT,DFO,wall_fired,5.88*S,lb,barrel,1 +IC,DFO,cell_burner,5.88*S,lb,barrel,1 +IC,DFO,cyclone_firing,5.88*S,lb,barrel,1 +IC,DFO,duct_burner,5.88*S,lb,barrel,1 +IC,DFO,fluidized_bed_firing,5.88*S,lb,barrel,1 +IC,DFO,none,5.88*S,lb,barrel,1 +IC,DFO,other,5.88*S,lb,barrel,1 +IC,DFO,stoker,5.88*S,lb,barrel,1 +IC,DFO,tangential_firing,5.88*S,lb,barrel,1 +IC,DFO,vertical_firing,5.88*S,lb,barrel,1 +IC,DFO,wall_fired,5.88*S,lb,barrel,1 +OT,DFO,cell_burner,5.964*S,lb,barrel,1 +OT,DFO,cyclone_firing,5.964*S,lb,barrel,1 +OT,DFO,duct_burner,5.964*S,lb,barrel,1 +OT,DFO,fluidized_bed_firing,0.5964*S,lb,barrel,1 +OT,DFO,none,5.964*S,lb,barrel,1 +OT,DFO,other,5.964*S,lb,barrel,1 +OT,DFO,stoker,5.964*S,lb,barrel,1 +OT,DFO,tangential_firing,5.964*S,lb,barrel,1 +OT,DFO,vertical_firing,5.964*S,lb,barrel,1 +OT,DFO,wall_fired,5.964*S,lb,barrel,1 +ST,DFO,cell_burner,5.964*S,lb,barrel,1 +ST,DFO,cyclone_firing,5.964*S,lb,barrel,1 +ST,DFO,duct_burner,5.964*S,lb,barrel,1 +ST,DFO,fluidized_bed_firing,0.5964*S,lb,barrel,1 +ST,DFO,none,5.964*S,lb,barrel,1 +ST,DFO,other,5.964*S,lb,barrel,1 +ST,DFO,stoker,5.964*S,lb,barrel,1 +ST,DFO,tangential_firing,5.964*S,lb,barrel,1 +ST,DFO,vertical_firing,5.964*S,lb,barrel,1 +ST,DFO,wall_fired,5.964*S,lb,barrel,1 +CA,JF,cell_burner,5.88*S,lb,barrel,1 +CA,JF,cyclone_firing,5.88*S,lb,barrel,1 +CA,JF,duct_burner,5.88*S,lb,barrel,1 +CA,JF,fluidized_bed_firing,5.88*S,lb,barrel,1 +CA,JF,none,5.88*S,lb,barrel,1 +CA,JF,other,5.88*S,lb,barrel,1 +CA,JF,stoker,5.88*S,lb,barrel,1 +CA,JF,tangential_firing,5.88*S,lb,barrel,1 +CA,JF,vertical_firing,5.88*S,lb,barrel,1 +CA,JF,wall_fired,5.88*S,lb,barrel,1 +CS,JF,cell_burner,5.88*S,lb,barrel,1 +CS,JF,cyclone_firing,5.88*S,lb,barrel,1 +CS,JF,duct_burner,5.88*S,lb,barrel,1 +CS,JF,fluidized_bed_firing,5.88*S,lb,barrel,1 +CS,JF,none,5.88*S,lb,barrel,1 +CS,JF,other,5.88*S,lb,barrel,1 +CS,JF,stoker,5.88*S,lb,barrel,1 +CS,JF,tangential_firing,5.88*S,lb,barrel,1 +CS,JF,vertical_firing,5.88*S,lb,barrel,1 +CS,JF,wall_fired,5.88*S,lb,barrel,1 +CT,JF,cell_burner,5.88*S,lb,barrel,1 +CT,JF,cyclone_firing,5.88*S,lb,barrel,1 +CT,JF,duct_burner,5.88*S,lb,barrel,1 +CT,JF,fluidized_bed_firing,5.88*S,lb,barrel,1 +CT,JF,none,5.88*S,lb,barrel,1 +CT,JF,other,5.88*S,lb,barrel,1 +CT,JF,stoker,5.88*S,lb,barrel,1 +CT,JF,tangential_firing,5.88*S,lb,barrel,1 +CT,JF,vertical_firing,5.88*S,lb,barrel,1 +CT,JF,wall_fired,5.88*S,lb,barrel,1 +GT,JF,cell_burner,5.88*S,lb,barrel,1 +GT,JF,cyclone_firing,5.88*S,lb,barrel,1 +GT,JF,duct_burner,5.88*S,lb,barrel,1 +GT,JF,fluidized_bed_firing,5.88*S,lb,barrel,1 +GT,JF,none,5.88*S,lb,barrel,1 +GT,JF,other,5.88*S,lb,barrel,1 +GT,JF,stoker,5.88*S,lb,barrel,1 +GT,JF,tangential_firing,5.88*S,lb,barrel,1 +GT,JF,vertical_firing,5.88*S,lb,barrel,1 +GT,JF,wall_fired,5.88*S,lb,barrel,1 +IC,JF,cell_burner,5.88*S,lb,barrel,1 +IC,JF,cyclone_firing,5.88*S,lb,barrel,1 +IC,JF,duct_burner,5.88*S,lb,barrel,1 +IC,JF,fluidized_bed_firing,5.88*S,lb,barrel,1 +IC,JF,none,5.88*S,lb,barrel,1 +IC,JF,other,5.88*S,lb,barrel,1 +IC,JF,stoker,5.88*S,lb,barrel,1 +IC,JF,tangential_firing,5.88*S,lb,barrel,1 +IC,JF,vertical_firing,5.88*S,lb,barrel,1 +IC,JF,wall_fired,5.88*S,lb,barrel,1 +OT,JF,cell_burner,5.964*S,lb,barrel,1 +OT,JF,cyclone_firing,5.964*S,lb,barrel,1 +OT,JF,duct_burner,5.964*S,lb,barrel,1 +OT,JF,fluidized_bed_firing,0.5964*S,lb,barrel,1 +OT,JF,none,5.964*S,lb,barrel,1 +OT,JF,other,5.964*S,lb,barrel,1 +OT,JF,stoker,5.964*S,lb,barrel,1 +OT,JF,tangential_firing,5.964*S,lb,barrel,1 +OT,JF,vertical_firing,5.964*S,lb,barrel,1 +OT,JF,wall_fired,5.964*S,lb,barrel,1 +ST,JF,cell_burner,5.964*S,lb,barrel,1 +ST,JF,cyclone_firing,5.964*S,lb,barrel,1 +ST,JF,duct_burner,5.964*S,lb,barrel,1 +ST,JF,fluidized_bed_firing,0.5964*S,lb,barrel,1 +ST,JF,none,5.964*S,lb,barrel,1 +ST,JF,other,5.964*S,lb,barrel,1 +ST,JF,stoker,5.964*S,lb,barrel,1 +ST,JF,tangential_firing,5.964*S,lb,barrel,1 +ST,JF,vertical_firing,5.964*S,lb,barrel,1 +ST,JF,wall_fired,5.964*S,lb,barrel,1 +CA,KER,cell_burner,5.88*S,lb,barrel,1 +CA,KER,cyclone_firing,5.88*S,lb,barrel,1 +CA,KER,duct_burner,5.88*S,lb,barrel,1 +CA,KER,fluidized_bed_firing,5.88*S,lb,barrel,1 +CA,KER,none,5.88*S,lb,barrel,1 +CA,KER,other,5.88*S,lb,barrel,1 +CA,KER,stoker,5.88*S,lb,barrel,1 +CA,KER,tangential_firing,5.88*S,lb,barrel,1 +CA,KER,vertical_firing,5.88*S,lb,barrel,1 +CA,KER,wall_fired,5.88*S,lb,barrel,1 +CS,KER,cell_burner,5.88*S,lb,barrel,1 +CS,KER,cyclone_firing,5.88*S,lb,barrel,1 +CS,KER,duct_burner,5.88*S,lb,barrel,1 +CS,KER,fluidized_bed_firing,5.88*S,lb,barrel,1 +CS,KER,none,5.88*S,lb,barrel,1 +CS,KER,other,5.88*S,lb,barrel,1 +CS,KER,stoker,5.88*S,lb,barrel,1 +CS,KER,tangential_firing,5.88*S,lb,barrel,1 +CS,KER,vertical_firing,5.88*S,lb,barrel,1 +CS,KER,wall_fired,5.88*S,lb,barrel,1 +CT,KER,cell_burner,5.88*S,lb,barrel,1 +CT,KER,cyclone_firing,5.88*S,lb,barrel,1 +CT,KER,duct_burner,5.88*S,lb,barrel,1 +CT,KER,fluidized_bed_firing,5.88*S,lb,barrel,1 +CT,KER,none,5.88*S,lb,barrel,1 +CT,KER,other,5.88*S,lb,barrel,1 +CT,KER,stoker,5.88*S,lb,barrel,1 +CT,KER,tangential_firing,5.88*S,lb,barrel,1 +CT,KER,vertical_firing,5.88*S,lb,barrel,1 +CT,KER,wall_fired,5.88*S,lb,barrel,1 +GT,KER,cell_burner,5.88*S,lb,barrel,1 +GT,KER,cyclone_firing,5.88*S,lb,barrel,1 +GT,KER,duct_burner,5.88*S,lb,barrel,1 +GT,KER,fluidized_bed_firing,5.88*S,lb,barrel,1 +GT,KER,none,5.88*S,lb,barrel,1 +GT,KER,other,5.88*S,lb,barrel,1 +GT,KER,stoker,5.88*S,lb,barrel,1 +GT,KER,tangential_firing,5.88*S,lb,barrel,1 +GT,KER,vertical_firing,5.88*S,lb,barrel,1 +GT,KER,wall_fired,5.88*S,lb,barrel,1 +IC,KER,cell_burner,5.88*S,lb,barrel,1 +IC,KER,cyclone_firing,5.88*S,lb,barrel,1 +IC,KER,duct_burner,5.88*S,lb,barrel,1 +IC,KER,fluidized_bed_firing,5.88*S,lb,barrel,1 +IC,KER,none,5.88*S,lb,barrel,1 +IC,KER,other,5.88*S,lb,barrel,1 +IC,KER,stoker,5.88*S,lb,barrel,1 +IC,KER,tangential_firing,5.88*S,lb,barrel,1 +IC,KER,vertical_firing,5.88*S,lb,barrel,1 +IC,KER,wall_fired,5.88*S,lb,barrel,1 +OT,KER,cell_burner,5.964*S,lb,barrel,1 +OT,KER,cyclone_firing,5.964*S,lb,barrel,1 +OT,KER,duct_burner,5.964*S,lb,barrel,1 +OT,KER,fluidized_bed_firing,0.5964*S,lb,barrel,1 +OT,KER,none,5.964*S,lb,barrel,1 +OT,KER,other,5.964*S,lb,barrel,1 +OT,KER,stoker,5.964*S,lb,barrel,1 +OT,KER,tangential_firing,5.964*S,lb,barrel,1 +OT,KER,vertical_firing,5.964*S,lb,barrel,1 +OT,KER,wall_fired,5.964*S,lb,barrel,1 +ST,KER,cell_burner,5.964*S,lb,barrel,1 +ST,KER,cyclone_firing,5.964*S,lb,barrel,1 +ST,KER,duct_burner,5.964*S,lb,barrel,1 +ST,KER,fluidized_bed_firing,0.5964*S,lb,barrel,1 +ST,KER,none,5.964*S,lb,barrel,1 +ST,KER,other,5.964*S,lb,barrel,1 +ST,KER,stoker,5.964*S,lb,barrel,1 +ST,KER,tangential_firing,5.964*S,lb,barrel,1 +ST,KER,vertical_firing,5.964*S,lb,barrel,1 +ST,KER,wall_fired,5.964*S,lb,barrel,1 +CA,LFG,cell_burner,0.0006,lb,Mcf,0 +CA,LFG,cyclone_firing,0.0006,lb,Mcf,0 +CA,LFG,duct_burner,0.0006,lb,Mcf,0 +CA,LFG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CA,LFG,none,0.0006,lb,Mcf,0 +CA,LFG,other,0.0006,lb,Mcf,0 +CA,LFG,stoker,0.0006,lb,Mcf,0 +CA,LFG,tangential_firing,0.0006,lb,Mcf,0 +CA,LFG,vertical_firing,0.0006,lb,Mcf,0 +CA,LFG,wall_fired,0.0006,lb,Mcf,0 +CS,LFG,cell_burner,0.0006,lb,Mcf,0 +CS,LFG,cyclone_firing,0.0006,lb,Mcf,0 +CS,LFG,duct_burner,0.0006,lb,Mcf,0 +CS,LFG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CS,LFG,none,0.0006,lb,Mcf,0 +CS,LFG,other,0.0006,lb,Mcf,0 +CS,LFG,stoker,0.0006,lb,Mcf,0 +CS,LFG,tangential_firing,0.0006,lb,Mcf,0 +CS,LFG,vertical_firing,0.0006,lb,Mcf,0 +CS,LFG,wall_fired,0.0006,lb,Mcf,0 +CT,LFG,cell_burner,0.0006,lb,Mcf,0 +CT,LFG,cyclone_firing,0.0006,lb,Mcf,0 +CT,LFG,duct_burner,0.0006,lb,Mcf,0 +CT,LFG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CT,LFG,none,0.0006,lb,Mcf,0 +CT,LFG,other,0.0006,lb,Mcf,0 +CT,LFG,stoker,0.0006,lb,Mcf,0 +CT,LFG,tangential_firing,0.0006,lb,Mcf,0 +CT,LFG,vertical_firing,0.0006,lb,Mcf,0 +CT,LFG,wall_fired,0.0006,lb,Mcf,0 +GT,LFG,cell_burner,0.0006,lb,Mcf,0 +GT,LFG,cyclone_firing,0.0006,lb,Mcf,0 +GT,LFG,duct_burner,0.0006,lb,Mcf,0 +GT,LFG,fluidized_bed_firing,0.0006,lb,Mcf,0 +GT,LFG,none,0.0006,lb,Mcf,0 +GT,LFG,other,0.0006,lb,Mcf,0 +GT,LFG,stoker,0.0006,lb,Mcf,0 +GT,LFG,tangential_firing,0.0006,lb,Mcf,0 +GT,LFG,vertical_firing,0.0006,lb,Mcf,0 +GT,LFG,wall_fired,0.0006,lb,Mcf,0 +IC,LFG,cell_burner,0.0006,lb,Mcf,0 +IC,LFG,cyclone_firing,0.0006,lb,Mcf,0 +IC,LFG,duct_burner,0.0006,lb,Mcf,0 +IC,LFG,fluidized_bed_firing,0.00006,lb,Mcf,0 +IC,LFG,none,0.0006,lb,Mcf,0 +IC,LFG,other,0.0006,lb,Mcf,0 +IC,LFG,stoker,0.0006,lb,Mcf,0 +IC,LFG,tangential_firing,0.0006,lb,Mcf,0 +IC,LFG,vertical_firing,0.0006,lb,Mcf,0 +IC,LFG,wall_fired,0.0006,lb,Mcf,0 +OT,LFG,cell_burner,0.0006,lb,Mcf,0 +OT,LFG,cyclone_firing,0.0006,lb,Mcf,0 +OT,LFG,duct_burner,0.0006,lb,Mcf,0 +OT,LFG,fluidized_bed_firing,0.00006,lb,Mcf,0 +OT,LFG,none,0.0006,lb,Mcf,0 +OT,LFG,other,0.0006,lb,Mcf,0 +OT,LFG,stoker,0.0006,lb,Mcf,0 +OT,LFG,tangential_firing,0.0006,lb,Mcf,0 +OT,LFG,vertical_firing,0.0006,lb,Mcf,0 +OT,LFG,wall_fired,0.0006,lb,Mcf,0 +ST,LFG,cell_burner,0.0006,lb,Mcf,0 +ST,LFG,cyclone_firing,0.0006,lb,Mcf,0 +ST,LFG,duct_burner,0.0006,lb,Mcf,0 +ST,LFG,fluidized_bed_firing,0.00006,lb,Mcf,0 +ST,LFG,none,0.0006,lb,Mcf,0 +ST,LFG,other,0.0006,lb,Mcf,0 +ST,LFG,stoker,0.0006,lb,Mcf,0 +ST,LFG,tangential_firing,0.0006,lb,Mcf,0 +ST,LFG,vertical_firing,0.0006,lb,Mcf,0 +ST,LFG,wall_fired,0.0006,lb,Mcf,0 +OT,LIG,cell_burner,30*S,lb,short ton,1 +OT,LIG,cyclone_firing,30*S,lb,short ton,1 +OT,LIG,duct_burner,30*S,lb,short ton,1 +OT,LIG,fluidized_bed_firing,3*S,lb,short ton,1 +OT,LIG,none,30*S,lb,short ton,1 +OT,LIG,other,30*S,lb,short ton,1 +OT,LIG,stoker,30*S,lb,short ton,1 +OT,LIG,tangential_firing,30*S,lb,short ton,1 +OT,LIG,vertical_firing,30*S,lb,short ton,1 +OT,LIG,wall_fired,30*S,lb,short ton,1 +ST,LIG,cell_burner,30*S,lb,short ton,1 +ST,LIG,cyclone_firing,30*S,lb,short ton,1 +ST,LIG,duct_burner,30*S,lb,short ton,1 +ST,LIG,fluidized_bed_firing,3*S,lb,short ton,1 +ST,LIG,none,30*S,lb,short ton,1 +ST,LIG,other,30*S,lb,short ton,1 +ST,LIG,stoker,30*S,lb,short ton,1 +ST,LIG,tangential_firing,30*S,lb,short ton,1 +ST,LIG,vertical_firing,30*S,lb,short ton,1 +ST,LIG,wall_fired,30*S,lb,short ton,1 +ST,MSB,cell_burner,1.7,lb,short ton,0 +ST,MSB,cyclone_firing,1.7,lb,short ton,0 +ST,MSB,duct_burner,1.7,lb,short ton,0 +ST,MSB,fluidized_bed_firing,0.17,lb,short ton,0 +ST,MSB,none,1.7,lb,short ton,0 +ST,MSB,other,1.7,lb,short ton,0 +ST,MSB,stoker,1.7,lb,short ton,0 +ST,MSB,tangential_firing,1.7,lb,short ton,0 +ST,MSB,vertical_firing,1.7,lb,short ton,0 +ST,MSB,wall_fired,1.7,lb,short ton,0 +ST,MSN,cell_burner,1.7,lb,short ton,0 +ST,MSN,cyclone_firing,1.7,lb,short ton,0 +ST,MSN,duct_burner,1.7,lb,short ton,0 +ST,MSN,fluidized_bed_firing,0.17,lb,short ton,0 +ST,MSN,none,1.7,lb,short ton,0 +ST,MSN,other,1.7,lb,short ton,0 +ST,MSN,stoker,1.7,lb,short ton,0 +ST,MSN,tangential_firing,1.7,lb,short ton,0 +ST,MSN,vertical_firing,1.7,lb,short ton,0 +ST,MSN,wall_fired,1.7,lb,short ton,0 +OT,MSW,cell_burner,1.7,lb,short ton,0 +OT,MSW,cyclone_firing,1.7,lb,short ton,0 +OT,MSW,duct_burner,1.7,lb,short ton,0 +OT,MSW,fluidized_bed_firing,0.17,lb,short ton,0 +OT,MSW,none,1.7,lb,short ton,0 +OT,MSW,other,1.7,lb,short ton,0 +OT,MSW,stoker,1.7,lb,short ton,0 +OT,MSW,tangential_firing,1.7,lb,short ton,0 +OT,MSW,vertical_firing,1.7,lb,short ton,0 +OT,MSW,wall_fired,1.7,lb,short ton,0 +ST,MSW,cell_burner,1.7,lb,short ton,0 +ST,MSW,cyclone_firing,1.7,lb,short ton,0 +ST,MSW,duct_burner,1.7,lb,short ton,0 +ST,MSW,fluidized_bed_firing,0.17,lb,short ton,0 +ST,MSW,none,1.7,lb,short ton,0 +ST,MSW,other,1.7,lb,short ton,0 +ST,MSW,stoker,1.7,lb,short ton,0 +ST,MSW,tangential_firing,1.7,lb,short ton,0 +ST,MSW,vertical_firing,1.7,lb,short ton,0 +ST,MSW,wall_fired,1.7,lb,short ton,0 +CA,NG,cell_burner,0.0006,lb,Mcf,0 +CA,NG,cyclone_firing,0.0006,lb,Mcf,0 +CA,NG,duct_burner,0.0006,lb,Mcf,0 +CA,NG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CA,NG,none,0.0006,lb,Mcf,0 +CA,NG,other,0.0006,lb,Mcf,0 +CA,NG,stoker,0.0006,lb,Mcf,0 +CA,NG,tangential_firing,0.0006,lb,Mcf,0 +CA,NG,vertical_firing,0.0006,lb,Mcf,0 +CA,NG,wall_fired,0.0006,lb,Mcf,0 +CE,NG,none,0.0006,lb,Mcf,0 +CS,NG,cell_burner,0.0006,lb,Mcf,0 +CS,NG,cyclone_firing,0.0006,lb,Mcf,0 +CS,NG,duct_burner,0.0006,lb,Mcf,0 +CS,NG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CS,NG,none,0.0006,lb,Mcf,0 +CS,NG,other,0.0006,lb,Mcf,0 +CS,NG,stoker,0.0006,lb,Mcf,0 +CS,NG,tangential_firing,0.0006,lb,Mcf,0 +CS,NG,vertical_firing,0.0006,lb,Mcf,0 +CS,NG,wall_fired,0.0006,lb,Mcf,0 +CT,NG,cell_burner,0.0006,lb,Mcf,0 +CT,NG,cyclone_firing,0.0006,lb,Mcf,0 +CT,NG,duct_burner,0.0006,lb,Mcf,0 +CT,NG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CT,NG,none,0.0006,lb,Mcf,0 +CT,NG,other,0.0006,lb,Mcf,0 +CT,NG,stoker,0.0006,lb,Mcf,0 +CT,NG,tangential_firing,0.0006,lb,Mcf,0 +CT,NG,vertical_firing,0.0006,lb,Mcf,0 +CT,NG,wall_fired,0.0006,lb,Mcf,0 +GT,NG,cell_burner,0.0006,lb,Mcf,0 +GT,NG,cyclone_firing,0.0006,lb,Mcf,0 +GT,NG,duct_burner,0.0006,lb,Mcf,0 +GT,NG,fluidized_bed_firing,0.0006,lb,Mcf,0 +GT,NG,none,0.0006,lb,Mcf,0 +GT,NG,other,0.0006,lb,Mcf,0 +GT,NG,stoker,0.0006,lb,Mcf,0 +GT,NG,tangential_firing,0.0006,lb,Mcf,0 +GT,NG,vertical_firing,0.0006,lb,Mcf,0 +GT,NG,wall_fired,0.0006,lb,Mcf,0 +IC,NG,cell_burner,0.0006,lb,Mcf,0 +IC,NG,cyclone_firing,0.0006,lb,Mcf,0 +IC,NG,duct_burner,0.0006,lb,Mcf,0 +IC,NG,fluidized_bed_firing,0.0006,lb,Mcf,0 +IC,NG,none,0.0006,lb,Mcf,0 +IC,NG,other,0.0006,lb,Mcf,0 +IC,NG,stoker,0.0006,lb,Mcf,0 +IC,NG,tangential_firing,0.0006,lb,Mcf,0 +IC,NG,vertical_firing,0.0006,lb,Mcf,0 +IC,NG,wall_fired,0.0006,lb,Mcf,0 +OT,NG,cell_burner,0.0006,lb,Mcf,0 +OT,NG,cyclone_firing,0.0006,lb,Mcf,0 +OT,NG,duct_burner,0.0006,lb,Mcf,0 +OT,NG,fluidized_bed_firing,0.00006,lb,Mcf,0 +OT,NG,none,0.0006,lb,Mcf,0 +OT,NG,other,0.0006,lb,Mcf,0 +OT,NG,stoker,0.0006,lb,Mcf,0 +OT,NG,tangential_firing,0.0006,lb,Mcf,0 +OT,NG,vertical_firing,0.0006,lb,Mcf,0 +OT,NG,wall_fired,0.0006,lb,Mcf,0 +ST,NG,cell_burner,0.0006,lb,Mcf,0 +ST,NG,cyclone_firing,0.0006,lb,Mcf,0 +ST,NG,duct_burner,0.0006,lb,Mcf,0 +ST,NG,fluidized_bed_firing,0.00006,lb,Mcf,0 +ST,NG,none,0.0006,lb,Mcf,0 +ST,NG,other,0.0006,lb,Mcf,0 +ST,NG,stoker,0.0006,lb,Mcf,0 +ST,NG,tangential_firing,0.0006,lb,Mcf,0 +ST,NG,vertical_firing,0.0006,lb,Mcf,0 +ST,NG,wall_fired,0.0006,lb,Mcf,0 +CA,OBG,cell_burner,0.0006,lb,Mcf,0 +CA,OBG,cyclone_firing,0.0006,lb,Mcf,0 +CA,OBG,duct_burner,0.0006,lb,Mcf,0 +CA,OBG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CA,OBG,none,0.0006,lb,Mcf,0 +CA,OBG,other,0.0006,lb,Mcf,0 +CA,OBG,stoker,0.0006,lb,Mcf,0 +CA,OBG,tangential_firing,0.0006,lb,Mcf,0 +CA,OBG,vertical_firing,0.0006,lb,Mcf,0 +CA,OBG,wall_fired,0.0006,lb,Mcf,0 +CS,OBG,cell_burner,0.0006,lb,Mcf,0 +CS,OBG,cyclone_firing,0.0006,lb,Mcf,0 +CS,OBG,duct_burner,0.0006,lb,Mcf,0 +CS,OBG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CS,OBG,none,0.0006,lb,Mcf,0 +CS,OBG,other,0.0006,lb,Mcf,0 +CS,OBG,stoker,0.0006,lb,Mcf,0 +CS,OBG,tangential_firing,0.0006,lb,Mcf,0 +CS,OBG,vertical_firing,0.0006,lb,Mcf,0 +CS,OBG,wall_fired,0.0006,lb,Mcf,0 +CT,OBG,cell_burner,0.0006,lb,Mcf,0 +CT,OBG,cyclone_firing,0.0006,lb,Mcf,0 +CT,OBG,duct_burner,0.0006,lb,Mcf,0 +CT,OBG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CT,OBG,none,0.0006,lb,Mcf,0 +CT,OBG,other,0.0006,lb,Mcf,0 +CT,OBG,stoker,0.0006,lb,Mcf,0 +CT,OBG,tangential_firing,0.0006,lb,Mcf,0 +CT,OBG,vertical_firing,0.0006,lb,Mcf,0 +CT,OBG,wall_fired,0.0006,lb,Mcf,0 +GT,OBG,cell_burner,0.0006,lb,Mcf,0 +GT,OBG,cyclone_firing,0.0006,lb,Mcf,0 +GT,OBG,duct_burner,0.0006,lb,Mcf,0 +GT,OBG,fluidized_bed_firing,0.0006,lb,Mcf,0 +GT,OBG,none,0.0006,lb,Mcf,0 +GT,OBG,other,0.0006,lb,Mcf,0 +GT,OBG,stoker,0.0006,lb,Mcf,0 +GT,OBG,tangential_firing,0.0006,lb,Mcf,0 +GT,OBG,vertical_firing,0.0006,lb,Mcf,0 +GT,OBG,wall_fired,0.0006,lb,Mcf,0 +IC,OBG,cell_burner,0.0006,lb,Mcf,0 +IC,OBG,cyclone_firing,0.0006,lb,Mcf,0 +IC,OBG,duct_burner,0.0006,lb,Mcf,0 +IC,OBG,fluidized_bed_firing,0.0006,lb,Mcf,0 +IC,OBG,none,0.0006,lb,Mcf,0 +IC,OBG,other,0.0006,lb,Mcf,0 +IC,OBG,stoker,0.0006,lb,Mcf,0 +IC,OBG,tangential_firing,0.0006,lb,Mcf,0 +IC,OBG,vertical_firing,0.0006,lb,Mcf,0 +IC,OBG,wall_fired,0.0006,lb,Mcf,0 +OT,OBG,cell_burner,0.0006,lb,Mcf,0 +OT,OBG,cyclone_firing,0.0006,lb,Mcf,0 +OT,OBG,duct_burner,0.0006,lb,Mcf,0 +OT,OBG,fluidized_bed_firing,0.00006,lb,Mcf,0 +OT,OBG,none,0.0006,lb,Mcf,0 +OT,OBG,other,0.0006,lb,Mcf,0 +OT,OBG,stoker,0.0006,lb,Mcf,0 +OT,OBG,tangential_firing,0.0006,lb,Mcf,0 +OT,OBG,vertical_firing,0.0006,lb,Mcf,0 +OT,OBG,wall_fired,0.0006,lb,Mcf,0 +ST,OBG,cell_burner,0.0006,lb,Mcf,0 +ST,OBG,cyclone_firing,0.0006,lb,Mcf,0 +ST,OBG,duct_burner,0.0006,lb,Mcf,0 +ST,OBG,fluidized_bed_firing,0.00006,lb,Mcf,0 +ST,OBG,none,0.0006,lb,Mcf,0 +ST,OBG,other,0.0006,lb,Mcf,0 +ST,OBG,stoker,0.0006,lb,Mcf,0 +ST,OBG,tangential_firing,0.0006,lb,Mcf,0 +ST,OBG,vertical_firing,0.0006,lb,Mcf,0 +ST,OBG,wall_fired,0.0006,lb,Mcf,0 +CA,OBL,cell_burner,5.88*S,lb,barrel,1 +CA,OBL,cyclone_firing,5.88*S,lb,barrel,1 +CA,OBL,duct_burner,5.88*S,lb,barrel,1 +CA,OBL,fluidized_bed_firing,5.88*S,lb,barrel,1 +CA,OBL,none,5.88*S,lb,barrel,1 +CA,OBL,other,5.88*S,lb,barrel,1 +CA,OBL,stoker,5.88*S,lb,barrel,1 +CA,OBL,tangential_firing,5.88*S,lb,barrel,1 +CA,OBL,vertical_firing,5.88*S,lb,barrel,1 +CA,OBL,wall_fired,5.88*S,lb,barrel,1 +CS,OBL,cell_burner,5.88*S,lb,barrel,1 +CS,OBL,cyclone_firing,5.88*S,lb,barrel,1 +CS,OBL,duct_burner,5.88*S,lb,barrel,1 +CS,OBL,fluidized_bed_firing,5.88*S,lb,barrel,1 +CS,OBL,none,5.88*S,lb,barrel,1 +CS,OBL,other,5.88*S,lb,barrel,1 +CS,OBL,stoker,5.88*S,lb,barrel,1 +CS,OBL,tangential_firing,5.88*S,lb,barrel,1 +CS,OBL,vertical_firing,5.88*S,lb,barrel,1 +CS,OBL,wall_fired,5.88*S,lb,barrel,1 +CT,OBL,cell_burner,5.88*S,lb,barrel,1 +CT,OBL,cyclone_firing,5.88*S,lb,barrel,1 +CT,OBL,duct_burner,5.88*S,lb,barrel,1 +CT,OBL,fluidized_bed_firing,5.88*S,lb,barrel,1 +CT,OBL,none,5.88*S,lb,barrel,1 +CT,OBL,other,5.88*S,lb,barrel,1 +CT,OBL,stoker,5.88*S,lb,barrel,1 +CT,OBL,tangential_firing,5.88*S,lb,barrel,1 +CT,OBL,vertical_firing,5.88*S,lb,barrel,1 +CT,OBL,wall_fired,5.88*S,lb,barrel,1 +GT,OBL,cell_burner,5.88*S,lb,barrel,1 +GT,OBL,cyclone_firing,5.88*S,lb,barrel,1 +GT,OBL,duct_burner,5.88*S,lb,barrel,1 +GT,OBL,fluidized_bed_firing,5.88*S,lb,barrel,1 +GT,OBL,none,5.88*S,lb,barrel,1 +GT,OBL,other,5.88*S,lb,barrel,1 +GT,OBL,stoker,5.88*S,lb,barrel,1 +GT,OBL,tangential_firing,5.88*S,lb,barrel,1 +GT,OBL,vertical_firing,5.88*S,lb,barrel,1 +GT,OBL,wall_fired,5.88*S,lb,barrel,1 +IC,OBL,cell_burner,5.88*S,lb,barrel,1 +IC,OBL,cyclone_firing,5.88*S,lb,barrel,1 +IC,OBL,duct_burner,5.88*S,lb,barrel,1 +IC,OBL,fluidized_bed_firing,5.88*S,lb,barrel,1 +IC,OBL,none,5.88*S,lb,barrel,1 +IC,OBL,other,5.88*S,lb,barrel,1 +IC,OBL,stoker,5.88*S,lb,barrel,1 +IC,OBL,tangential_firing,5.88*S,lb,barrel,1 +IC,OBL,vertical_firing,5.88*S,lb,barrel,1 +IC,OBL,wall_fired,5.88*S,lb,barrel,1 +OT,OBL,cell_burner,5.964*S,lb,barrel,1 +OT,OBL,cyclone_firing,5.964*S,lb,barrel,1 +OT,OBL,duct_burner,5.964*S,lb,barrel,1 +OT,OBL,fluidized_bed_firing,0.5964*S,lb,barrel,1 +OT,OBL,none,5.964*S,lb,barrel,1 +OT,OBL,other,5.964*S,lb,barrel,1 +OT,OBL,stoker,5.964*S,lb,barrel,1 +OT,OBL,tangential_firing,5.964*S,lb,barrel,1 +OT,OBL,vertical_firing,5.964*S,lb,barrel,1 +OT,OBL,wall_fired,5.964*S,lb,barrel,1 +ST,OBL,cell_burner,5.964*S,lb,barrel,1 +ST,OBL,cyclone_firing,5.964*S,lb,barrel,1 +ST,OBL,duct_burner,5.964*S,lb,barrel,1 +ST,OBL,fluidized_bed_firing,0.5964*S,lb,barrel,1 +ST,OBL,none,5.964*S,lb,barrel,1 +ST,OBL,other,5.964*S,lb,barrel,1 +ST,OBL,stoker,5.964*S,lb,barrel,1 +ST,OBL,tangential_firing,5.964*S,lb,barrel,1 +ST,OBL,vertical_firing,5.964*S,lb,barrel,1 +ST,OBL,wall_fired,5.964*S,lb,barrel,1 +OT,OBS,cell_burner,0.23,lb,short ton,0 +OT,OBS,cyclone_firing,0.23,lb,short ton,0 +OT,OBS,duct_burner,0.23,lb,short ton,0 +OT,OBS,fluidized_bed_firing,0.02,lb,short ton,0 +OT,OBS,none,0.23,lb,short ton,0 +OT,OBS,other,0.23,lb,short ton,0 +OT,OBS,stoker,0.23,lb,short ton,0 +OT,OBS,tangential_firing,0.23,lb,short ton,0 +OT,OBS,vertical_firing,0.23,lb,short ton,0 +OT,OBS,wall_fired,0.23,lb,short ton,0 +ST,OBS,cell_burner,0.23,lb,short ton,0 +ST,OBS,cyclone_firing,0.23,lb,short ton,0 +ST,OBS,duct_burner,0.23,lb,short ton,0 +ST,OBS,fluidized_bed_firing,0.02,lb,short ton,0 +ST,OBS,none,0.23,lb,short ton,0 +ST,OBS,other,0.23,lb,short ton,0 +ST,OBS,stoker,0.23,lb,short ton,0 +ST,OBS,tangential_firing,0.23,lb,short ton,0 +ST,OBS,vertical_firing,0.23,lb,short ton,0 +ST,OBS,wall_fired,0.23,lb,short ton,0 +CA,OG,cell_burner,0.0006,lb,Mcf,0 +CA,OG,cyclone_firing,0.0006,lb,Mcf,0 +CA,OG,duct_burner,0.0006,lb,Mcf,0 +CA,OG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CA,OG,none,0.0006,lb,Mcf,0 +CA,OG,other,0.0006,lb,Mcf,0 +CA,OG,stoker,0.0006,lb,Mcf,0 +CA,OG,tangential_firing,0.0006,lb,Mcf,0 +CA,OG,vertical_firing,0.0006,lb,Mcf,0 +CA,OG,wall_fired,0.0006,lb,Mcf,0 +CS,OG,cell_burner,0.0006,lb,Mcf,0 +CS,OG,cyclone_firing,0.0006,lb,Mcf,0 +CS,OG,duct_burner,0.0006,lb,Mcf,0 +CS,OG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CS,OG,none,0.0006,lb,Mcf,0 +CS,OG,other,0.0006,lb,Mcf,0 +CS,OG,stoker,0.0006,lb,Mcf,0 +CS,OG,tangential_firing,0.0006,lb,Mcf,0 +CS,OG,vertical_firing,0.0006,lb,Mcf,0 +CS,OG,wall_fired,0.0006,lb,Mcf,0 +CT,OG,cell_burner,0.0006,lb,Mcf,0 +CT,OG,cyclone_firing,0.0006,lb,Mcf,0 +CT,OG,duct_burner,0.0006,lb,Mcf,0 +CT,OG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CT,OG,none,0.0006,lb,Mcf,0 +CT,OG,other,0.0006,lb,Mcf,0 +CT,OG,stoker,0.0006,lb,Mcf,0 +CT,OG,tangential_firing,0.0006,lb,Mcf,0 +CT,OG,vertical_firing,0.0006,lb,Mcf,0 +CT,OG,wall_fired,0.0006,lb,Mcf,0 +GT,OG,cell_burner,0.0006,lb,Mcf,0 +GT,OG,cyclone_firing,0.0006,lb,Mcf,0 +GT,OG,duct_burner,0.0006,lb,Mcf,0 +GT,OG,fluidized_bed_firing,0.0006,lb,Mcf,0 +GT,OG,none,0.0006,lb,Mcf,0 +GT,OG,other,0.0006,lb,Mcf,0 +GT,OG,stoker,0.0006,lb,Mcf,0 +GT,OG,tangential_firing,0.0006,lb,Mcf,0 +GT,OG,vertical_firing,0.0006,lb,Mcf,0 +GT,OG,wall_fired,0.0006,lb,Mcf,0 +IC,OG,cell_burner,0.0006,lb,Mcf,0 +IC,OG,cyclone_firing,0.0006,lb,Mcf,0 +IC,OG,duct_burner,0.0006,lb,Mcf,0 +IC,OG,fluidized_bed_firing,0.0006,lb,Mcf,0 +IC,OG,none,0.0006,lb,Mcf,0 +IC,OG,other,0.0006,lb,Mcf,0 +IC,OG,stoker,0.0006,lb,Mcf,0 +IC,OG,tangential_firing,0.0006,lb,Mcf,0 +IC,OG,vertical_firing,0.0006,lb,Mcf,0 +IC,OG,wall_fired,0.0006,lb,Mcf,0 +OT,OG,cell_burner,0.0006,lb,Mcf,0 +OT,OG,cyclone_firing,0.0006,lb,Mcf,0 +OT,OG,duct_burner,0.0006,lb,Mcf,0 +OT,OG,fluidized_bed_firing,0.00006,lb,Mcf,0 +OT,OG,none,0.0006,lb,Mcf,0 +OT,OG,other,0.0006,lb,Mcf,0 +OT,OG,stoker,0.0006,lb,Mcf,0 +OT,OG,tangential_firing,0.0006,lb,Mcf,0 +OT,OG,vertical_firing,0.0006,lb,Mcf,0 +OT,OG,wall_fired,0.0006,lb,Mcf,0 +ST,OG,cell_burner,0.0006,lb,Mcf,0 +ST,OG,cyclone_firing,0.0006,lb,Mcf,0 +ST,OG,duct_burner,0.0006,lb,Mcf,0 +ST,OG,fluidized_bed_firing,0.00006,lb,Mcf,0 +ST,OG,none,0.0006,lb,Mcf,0 +ST,OG,other,0.0006,lb,Mcf,0 +ST,OG,stoker,0.0006,lb,Mcf,0 +ST,OG,tangential_firing,0.0006,lb,Mcf,0 +ST,OG,vertical_firing,0.0006,lb,Mcf,0 +ST,OG,wall_fired,0.0006,lb,Mcf,0 +CA,OTH,cell_burner,0.0006,lb,Mcf,0 +CA,OTH,cyclone_firing,0.0006,lb,Mcf,0 +CA,OTH,duct_burner,0.0006,lb,Mcf,0 +CA,OTH,fluidized_bed_firing,0.0006,lb,Mcf,0 +CA,OTH,none,0.0006,lb,Mcf,0 +CA,OTH,other,0.0006,lb,Mcf,0 +CA,OTH,stoker,0.0006,lb,Mcf,0 +CA,OTH,tangential_firing,0.0006,lb,Mcf,0 +CA,OTH,vertical_firing,0.0006,lb,Mcf,0 +CA,OTH,wall_fired,0.0006,lb,Mcf,0 +CS,OTH,cell_burner,0.0006,lb,Mcf,0 +CS,OTH,cyclone_firing,0.0006,lb,Mcf,0 +CS,OTH,duct_burner,0.0006,lb,Mcf,0 +CS,OTH,fluidized_bed_firing,0.0006,lb,Mcf,0 +CS,OTH,none,0.0006,lb,Mcf,0 +CS,OTH,other,0.0006,lb,Mcf,0 +CS,OTH,stoker,0.0006,lb,Mcf,0 +CS,OTH,tangential_firing,0.0006,lb,Mcf,0 +CS,OTH,vertical_firing,0.0006,lb,Mcf,0 +CS,OTH,wall_fired,0.0006,lb,Mcf,0 +CT,OTH,cell_burner,0.0006,lb,Mcf,0 +CT,OTH,cyclone_firing,0.0006,lb,Mcf,0 +CT,OTH,duct_burner,0.0006,lb,Mcf,0 +CT,OTH,fluidized_bed_firing,0.0006,lb,Mcf,0 +CT,OTH,none,0.0006,lb,Mcf,0 +CT,OTH,other,0.0006,lb,Mcf,0 +CT,OTH,stoker,0.0006,lb,Mcf,0 +CT,OTH,tangential_firing,0.0006,lb,Mcf,0 +CT,OTH,vertical_firing,0.0006,lb,Mcf,0 +CT,OTH,wall_fired,0.0006,lb,Mcf,0 +GT,OTH,cell_burner,0.0006,lb,Mcf,0 +GT,OTH,cyclone_firing,0.0006,lb,Mcf,0 +GT,OTH,duct_burner,0.0006,lb,Mcf,0 +GT,OTH,fluidized_bed_firing,0.0006,lb,Mcf,0 +GT,OTH,none,0.0006,lb,Mcf,0 +GT,OTH,other,0.0006,lb,Mcf,0 +GT,OTH,stoker,0.0006,lb,Mcf,0 +GT,OTH,tangential_firing,0.0006,lb,Mcf,0 +GT,OTH,vertical_firing,0.0006,lb,Mcf,0 +GT,OTH,wall_fired,0.0006,lb,Mcf,0 +IC,OTH,cell_burner,0.0006,lb,Mcf,0 +IC,OTH,cyclone_firing,0.0006,lb,Mcf,0 +IC,OTH,duct_burner,0.0006,lb,Mcf,0 +IC,OTH,fluidized_bed_firing,0.0006,lb,Mcf,0 +IC,OTH,none,0.0006,lb,Mcf,0 +IC,OTH,other,0.0006,lb,Mcf,0 +IC,OTH,stoker,0.0006,lb,Mcf,0 +IC,OTH,tangential_firing,0.0006,lb,Mcf,0 +IC,OTH,vertical_firing,0.0006,lb,Mcf,0 +IC,OTH,wall_fired,0.0006,lb,Mcf,0 +OT,OTH,cell_burner,0.0006,lb,Mcf,0 +OT,OTH,cyclone_firing,0.0006,lb,Mcf,0 +OT,OTH,duct_burner,0.0006,lb,Mcf,0 +OT,OTH,fluidized_bed_firing,0.00006,lb,Mcf,0 +OT,OTH,none,0.0006,lb,Mcf,0 +OT,OTH,other,0.0006,lb,Mcf,0 +OT,OTH,stoker,0.0006,lb,Mcf,0 +OT,OTH,tangential_firing,0.0006,lb,Mcf,0 +OT,OTH,vertical_firing,0.0006,lb,Mcf,0 +OT,OTH,wall_fired,0.0006,lb,Mcf,0 +ST,OTH,cell_burner,0.0006,lb,Mcf,0 +ST,OTH,cyclone_firing,0.0006,lb,Mcf,0 +ST,OTH,duct_burner,0.0006,lb,Mcf,0 +ST,OTH,fluidized_bed_firing,0.00006,lb,Mcf,0 +ST,OTH,none,0.0006,lb,Mcf,0 +ST,OTH,other,0.0006,lb,Mcf,0 +ST,OTH,stoker,0.0006,lb,Mcf,0 +ST,OTH,tangential_firing,0.0006,lb,Mcf,0 +ST,OTH,vertical_firing,0.0006,lb,Mcf,0 +ST,OTH,wall_fired,0.0006,lb,Mcf,0 +OT,PC,cell_burner,39*S,lb,short ton,1 +OT,PC,cyclone_firing,39*S,lb,short ton,1 +OT,PC,duct_burner,39*S,lb,short ton,1 +OT,PC,fluidized_bed_firing,3.9*S,lb,short ton,1 +OT,PC,none,39*S,lb,short ton,1 +OT,PC,other,39*S,lb,short ton,1 +OT,PC,stoker,39*S,lb,short ton,1 +OT,PC,tangential_firing,39*S,lb,short ton,1 +OT,PC,vertical_firing,39*S,lb,short ton,1 +OT,PC,wall_fired,39*S,lb,short ton,1 +ST,PC,cell_burner,39*S,lb,short ton,1 +ST,PC,cyclone_firing,39*S,lb,short ton,1 +ST,PC,duct_burner,39*S,lb,short ton,1 +ST,PC,fluidized_bed_firing,3.9*S,lb,short ton,1 +ST,PC,none,39*S,lb,short ton,1 +ST,PC,other,39*S,lb,short ton,1 +ST,PC,stoker,39*S,lb,short ton,1 +ST,PC,tangential_firing,39*S,lb,short ton,1 +ST,PC,vertical_firing,39*S,lb,short ton,1 +ST,PC,wall_fired,39*S,lb,short ton,1 +CA,PG,cell_burner,0.0006,lb,Mcf,0 +CA,PG,cyclone_firing,0.0006,lb,Mcf,0 +CA,PG,duct_burner,0.0006,lb,Mcf,0 +CA,PG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CA,PG,none,0.0006,lb,Mcf,0 +CA,PG,other,0.0006,lb,Mcf,0 +CA,PG,stoker,0.0006,lb,Mcf,0 +CA,PG,tangential_firing,0.0006,lb,Mcf,0 +CA,PG,vertical_firing,0.0006,lb,Mcf,0 +CA,PG,wall_fired,0.0006,lb,Mcf,0 +CS,PG,cell_burner,0.0006,lb,Mcf,0 +CS,PG,cyclone_firing,0.0006,lb,Mcf,0 +CS,PG,duct_burner,0.0006,lb,Mcf,0 +CS,PG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CS,PG,none,0.0006,lb,Mcf,0 +CS,PG,other,0.0006,lb,Mcf,0 +CS,PG,stoker,0.0006,lb,Mcf,0 +CS,PG,tangential_firing,0.0006,lb,Mcf,0 +CS,PG,vertical_firing,0.0006,lb,Mcf,0 +CS,PG,wall_fired,0.0006,lb,Mcf,0 +CT,PG,cell_burner,0.0006,lb,Mcf,0 +CT,PG,cyclone_firing,0.0006,lb,Mcf,0 +CT,PG,duct_burner,0.0006,lb,Mcf,0 +CT,PG,fluidized_bed_firing,0.0006,lb,Mcf,0 +CT,PG,none,0.0006,lb,Mcf,0 +CT,PG,other,0.0006,lb,Mcf,0 +CT,PG,stoker,0.0006,lb,Mcf,0 +CT,PG,tangential_firing,0.0006,lb,Mcf,0 +CT,PG,vertical_firing,0.0006,lb,Mcf,0 +CT,PG,wall_fired,0.0006,lb,Mcf,0 +GT,PG,cell_burner,0.0006,lb,Mcf,0 +GT,PG,cyclone_firing,0.0006,lb,Mcf,0 +GT,PG,duct_burner,0.0006,lb,Mcf,0 +GT,PG,fluidized_bed_firing,0.0006,lb,Mcf,0 +GT,PG,none,0.0006,lb,Mcf,0 +GT,PG,other,0.0006,lb,Mcf,0 +GT,PG,stoker,0.0006,lb,Mcf,0 +GT,PG,tangential_firing,0.0006,lb,Mcf,0 +GT,PG,vertical_firing,0.0006,lb,Mcf,0 +GT,PG,wall_fired,0.0006,lb,Mcf,0 +IC,PG,cell_burner,0.0006,lb,Mcf,0 +IC,PG,cyclone_firing,0.0006,lb,Mcf,0 +IC,PG,duct_burner,0.0006,lb,Mcf,0 +IC,PG,fluidized_bed_firing,0.0006,lb,Mcf,0 +IC,PG,none,0.0006,lb,Mcf,0 +IC,PG,other,0.0006,lb,Mcf,0 +IC,PG,stoker,0.0006,lb,Mcf,0 +IC,PG,tangential_firing,0.0006,lb,Mcf,0 +IC,PG,vertical_firing,0.0006,lb,Mcf,0 +IC,PG,wall_fired,0.0006,lb,Mcf,0 +OT,PG,cell_burner,0.0006,lb,Mcf,0 +OT,PG,cyclone_firing,0.0006,lb,Mcf,0 +OT,PG,duct_burner,0.0006,lb,Mcf,0 +OT,PG,fluidized_bed_firing,0.00006,lb,Mcf,0 +OT,PG,none,0.0006,lb,Mcf,0 +OT,PG,other,0.0006,lb,Mcf,0 +OT,PG,stoker,0.0006,lb,Mcf,0 +OT,PG,tangential_firing,0.0006,lb,Mcf,0 +OT,PG,vertical_firing,0.0006,lb,Mcf,0 +OT,PG,wall_fired,0.0006,lb,Mcf,0 +ST,PG,cell_burner,0.0006,lb,Mcf,0 +ST,PG,cyclone_firing,0.0006,lb,Mcf,0 +ST,PG,duct_burner,0.0006,lb,Mcf,0 +ST,PG,fluidized_bed_firing,0.00006,lb,Mcf,0 +ST,PG,none,0.0006,lb,Mcf,0 +ST,PG,other,0.0006,lb,Mcf,0 +ST,PG,stoker,0.0006,lb,Mcf,0 +ST,PG,tangential_firing,0.0006,lb,Mcf,0 +ST,PG,vertical_firing,0.0006,lb,Mcf,0 +ST,PG,wall_fired,0.0006,lb,Mcf,0 +OT,RC,cell_burner,38*S,lb,short ton,1 +OT,RC,cyclone_firing,38*S,lb,short ton,1 +OT,RC,duct_burner,38*S,lb,short ton,1 +OT,RC,fluidized_bed_firing,3.8*S,lb,short ton,1 +OT,RC,none,38*S,lb,short ton,1 +OT,RC,other,38*S,lb,short ton,1 +OT,RC,stoker,38*S,lb,short ton,1 +OT,RC,tangential_firing,38*S,lb,short ton,1 +OT,RC,vertical_firing,38*S,lb,short ton,1 +OT,RC,wall_fired,38*S,lb,short ton,1 +ST,RC,cell_burner,38*S,lb,short ton,1 +ST,RC,cyclone_firing,38*S,lb,short ton,1 +ST,RC,duct_burner,38*S,lb,short ton,1 +ST,RC,fluidized_bed_firing,3.8*S,lb,short ton,1 +ST,RC,none,38*S,lb,short ton,1 +ST,RC,other,38*S,lb,short ton,1 +ST,RC,stoker,38*S,lb,short ton,1 +ST,RC,tangential_firing,38*S,lb,short ton,1 +ST,RC,vertical_firing,38*S,lb,short ton,1 +ST,RC,wall_fired,38*S,lb,short ton,1 +CA,RFO,cell_burner,5.88*S,lb,barrel,1 +CA,RFO,cyclone_firing,5.88*S,lb,barrel,1 +CA,RFO,duct_burner,5.88*S,lb,barrel,1 +CA,RFO,fluidized_bed_firing,5.88*S,lb,barrel,1 +CA,RFO,none,5.88*S,lb,barrel,1 +CA,RFO,other,5.88*S,lb,barrel,1 +CA,RFO,stoker,5.88*S,lb,barrel,1 +CA,RFO,tangential_firing,5.88*S,lb,barrel,1 +CA,RFO,vertical_firing,5.88*S,lb,barrel,1 +CA,RFO,wall_fired,5.88*S,lb,barrel,1 +CS,RFO,cell_burner,5.88*S,lb,barrel,1 +CS,RFO,cyclone_firing,5.88*S,lb,barrel,1 +CS,RFO,duct_burner,5.88*S,lb,barrel,1 +CS,RFO,fluidized_bed_firing,5.88*S,lb,barrel,1 +CS,RFO,none,5.88*S,lb,barrel,1 +CS,RFO,other,5.88*S,lb,barrel,1 +CS,RFO,stoker,5.88*S,lb,barrel,1 +CS,RFO,tangential_firing,5.88*S,lb,barrel,1 +CS,RFO,vertical_firing,5.88*S,lb,barrel,1 +CS,RFO,wall_fired,5.88*S,lb,barrel,1 +CT,RFO,cell_burner,5.88*S,lb,barrel,1 +CT,RFO,cyclone_firing,5.88*S,lb,barrel,1 +CT,RFO,duct_burner,5.88*S,lb,barrel,1 +CT,RFO,fluidized_bed_firing,5.88*S,lb,barrel,1 +CT,RFO,none,5.88*S,lb,barrel,1 +CT,RFO,other,5.88*S,lb,barrel,1 +CT,RFO,stoker,5.88*S,lb,barrel,1 +CT,RFO,tangential_firing,5.88*S,lb,barrel,1 +CT,RFO,vertical_firing,5.88*S,lb,barrel,1 +CT,RFO,wall_fired,5.88*S,lb,barrel,1 +GT,RFO,cell_burner,5.88*S,lb,barrel,1 +GT,RFO,cyclone_firing,5.88*S,lb,barrel,1 +GT,RFO,duct_burner,5.88*S,lb,barrel,1 +GT,RFO,fluidized_bed_firing,5.88*S,lb,barrel,1 +GT,RFO,none,5.88*S,lb,barrel,1 +GT,RFO,other,5.88*S,lb,barrel,1 +GT,RFO,stoker,5.88*S,lb,barrel,1 +GT,RFO,tangential_firing,5.88*S,lb,barrel,1 +GT,RFO,vertical_firing,5.88*S,lb,barrel,1 +GT,RFO,wall_fired,5.88*S,lb,barrel,1 +IC,RFO,cell_burner,5.88*S,lb,barrel,1 +IC,RFO,cyclone_firing,5.88*S,lb,barrel,1 +IC,RFO,duct_burner,5.88*S,lb,barrel,1 +IC,RFO,fluidized_bed_firing,5.88*S,lb,barrel,1 +IC,RFO,none,5.88*S,lb,barrel,1 +IC,RFO,other,5.88*S,lb,barrel,1 +IC,RFO,stoker,5.88*S,lb,barrel,1 +IC,RFO,tangential_firing,5.88*S,lb,barrel,1 +IC,RFO,vertical_firing,5.88*S,lb,barrel,1 +IC,RFO,wall_fired,5.88*S,lb,barrel,1 +OT,RFO,cell_burner,6.594*S,lb,barrel,1 +OT,RFO,cyclone_firing,6.594*S,lb,barrel,1 +OT,RFO,duct_burner,6.594*S,lb,barrel,1 +OT,RFO,fluidized_bed_firing,0.6594*S,lb,barrel,1 +OT,RFO,none,6.594*S,lb,barrel,1 +OT,RFO,other,6.594*S,lb,barrel,1 +OT,RFO,stoker,6.594*S,lb,barrel,1 +OT,RFO,tangential_firing,6.594*S,lb,barrel,1 +OT,RFO,vertical_firing,6.594*S,lb,barrel,1 +OT,RFO,wall_fired,6.594*S,lb,barrel,1 +ST,RFO,cell_burner,6.594*S,lb,barrel,1 +ST,RFO,cyclone_firing,6.594*S,lb,barrel,1 +ST,RFO,duct_burner,6.594*S,lb,barrel,1 +ST,RFO,fluidized_bed_firing,0.6594*S,lb,barrel,1 +ST,RFO,none,6.594*S,lb,barrel,1 +ST,RFO,other,6.594*S,lb,barrel,1 +ST,RFO,stoker,6.594*S,lb,barrel,1 +ST,RFO,tangential_firing,6.594*S,lb,barrel,1 +ST,RFO,vertical_firing,6.594*S,lb,barrel,1 +ST,RFO,wall_fired,6.594*S,lb,barrel,1 +CA,SGC,cell_burner,0.0006,lb,Mcf,0 +CA,SGC,cyclone_firing,0.0006,lb,Mcf,0 +CA,SGC,duct_burner,0.0006,lb,Mcf,0 +CA,SGC,fluidized_bed_firing,0.0006,lb,Mcf,0 +CA,SGC,none,0.0006,lb,Mcf,0 +CA,SGC,other,0.0006,lb,Mcf,0 +CA,SGC,stoker,0.0006,lb,Mcf,0 +CA,SGC,tangential_firing,0.0006,lb,Mcf,0 +CA,SGC,vertical_firing,0.0006,lb,Mcf,0 +CA,SGC,wall_fired,0.0006,lb,Mcf,0 +CS,SGC,cell_burner,0.0006,lb,Mcf,0 +CS,SGC,cyclone_firing,0.0006,lb,Mcf,0 +CS,SGC,duct_burner,0.0006,lb,Mcf,0 +CS,SGC,fluidized_bed_firing,0.0006,lb,Mcf,0 +CS,SGC,none,0.0006,lb,Mcf,0 +CS,SGC,other,0.0006,lb,Mcf,0 +CS,SGC,stoker,0.0006,lb,Mcf,0 +CS,SGC,tangential_firing,0.0006,lb,Mcf,0 +CS,SGC,vertical_firing,0.0006,lb,Mcf,0 +CS,SGC,wall_fired,0.0006,lb,Mcf,0 +CT,SGC,cell_burner,0.0006,lb,Mcf,0 +CT,SGC,cyclone_firing,0.0006,lb,Mcf,0 +CT,SGC,duct_burner,0.0006,lb,Mcf,0 +CT,SGC,fluidized_bed_firing,0.0006,lb,Mcf,0 +CT,SGC,none,0.0006,lb,Mcf,0 +CT,SGC,other,0.0006,lb,Mcf,0 +CT,SGC,stoker,0.0006,lb,Mcf,0 +CT,SGC,tangential_firing,0.0006,lb,Mcf,0 +CT,SGC,vertical_firing,0.0006,lb,Mcf,0 +CT,SGC,wall_fired,0.0006,lb,Mcf,0 +GT,SGC,cell_burner,0.0006,lb,Mcf,0 +GT,SGC,cyclone_firing,0.0006,lb,Mcf,0 +GT,SGC,duct_burner,0.0006,lb,Mcf,0 +GT,SGC,fluidized_bed_firing,0.0006,lb,Mcf,0 +GT,SGC,none,0.0006,lb,Mcf,0 +GT,SGC,other,0.0006,lb,Mcf,0 +GT,SGC,stoker,0.0006,lb,Mcf,0 +GT,SGC,tangential_firing,0.0006,lb,Mcf,0 +GT,SGC,vertical_firing,0.0006,lb,Mcf,0 +GT,SGC,wall_fired,0.0006,lb,Mcf,0 +IC,SGC,cell_burner,0.0006,lb,Mcf,0 +IC,SGC,cyclone_firing,0.0006,lb,Mcf,0 +IC,SGC,duct_burner,0.0006,lb,Mcf,0 +IC,SGC,fluidized_bed_firing,0.0006,lb,Mcf,0 +IC,SGC,none,0.0006,lb,Mcf,0 +IC,SGC,other,0.0006,lb,Mcf,0 +IC,SGC,stoker,0.0006,lb,Mcf,0 +IC,SGC,tangential_firing,0.0006,lb,Mcf,0 +IC,SGC,vertical_firing,0.0006,lb,Mcf,0 +IC,SGC,wall_fired,0.0006,lb,Mcf,0 +OT,SGC,cell_burner,0.0006,lb,Mcf,0 +OT,SGC,cyclone_firing,0.0006,lb,Mcf,0 +OT,SGC,duct_burner,0.0006,lb,Mcf,0 +OT,SGC,fluidized_bed_firing,0.00006,lb,Mcf,0 +OT,SGC,none,0.0006,lb,Mcf,0 +OT,SGC,other,0.0006,lb,Mcf,0 +OT,SGC,stoker,0.0006,lb,Mcf,0 +OT,SGC,tangential_firing,0.0006,lb,Mcf,0 +OT,SGC,vertical_firing,0.0006,lb,Mcf,0 +OT,SGC,wall_fired,0.0006,lb,Mcf,0 +ST,SGC,cell_burner,0.0006,lb,Mcf,0 +ST,SGC,cyclone_firing,0.0006,lb,Mcf,0 +ST,SGC,duct_burner,0.0006,lb,Mcf,0 +ST,SGC,fluidized_bed_firing,0.00006,lb,Mcf,0 +ST,SGC,none,0.0006,lb,Mcf,0 +ST,SGC,other,0.0006,lb,Mcf,0 +ST,SGC,stoker,0.0006,lb,Mcf,0 +ST,SGC,tangential_firing,0.0006,lb,Mcf,0 +ST,SGC,vertical_firing,0.0006,lb,Mcf,0 +ST,SGC,wall_fired,0.0006,lb,Mcf,0 +CA,SGP,cell_burner,0.0006,lb,Mcf,0 +CA,SGP,cyclone_firing,0.0006,lb,Mcf,0 +CA,SGP,duct_burner,0.0006,lb,Mcf,0 +CA,SGP,fluidized_bed_firing,0.0006,lb,Mcf,0 +CA,SGP,none,0.0006,lb,Mcf,0 +CA,SGP,other,0.0006,lb,Mcf,0 +CA,SGP,stoker,0.0006,lb,Mcf,0 +CA,SGP,tangential_firing,0.0006,lb,Mcf,0 +CA,SGP,vertical_firing,0.0006,lb,Mcf,0 +CA,SGP,wall_fired,0.0006,lb,Mcf,0 +CS,SGP,cell_burner,0.0006,lb,Mcf,0 +CS,SGP,cyclone_firing,0.0006,lb,Mcf,0 +CS,SGP,duct_burner,0.0006,lb,Mcf,0 +CS,SGP,fluidized_bed_firing,0.0006,lb,Mcf,0 +CS,SGP,none,0.0006,lb,Mcf,0 +CS,SGP,other,0.0006,lb,Mcf,0 +CS,SGP,stoker,0.0006,lb,Mcf,0 +CS,SGP,tangential_firing,0.0006,lb,Mcf,0 +CS,SGP,vertical_firing,0.0006,lb,Mcf,0 +CS,SGP,wall_fired,0.0006,lb,Mcf,0 +CT,SGP,cell_burner,0.0006,lb,Mcf,0 +CT,SGP,cyclone_firing,0.0006,lb,Mcf,0 +CT,SGP,duct_burner,0.0006,lb,Mcf,0 +CT,SGP,fluidized_bed_firing,0.0006,lb,Mcf,0 +CT,SGP,none,0.0006,lb,Mcf,0 +CT,SGP,other,0.0006,lb,Mcf,0 +CT,SGP,stoker,0.0006,lb,Mcf,0 +CT,SGP,tangential_firing,0.0006,lb,Mcf,0 +CT,SGP,vertical_firing,0.0006,lb,Mcf,0 +CT,SGP,wall_fired,0.0006,lb,Mcf,0 +GT,SGP,cell_burner,0.0006,lb,Mcf,0 +GT,SGP,cyclone_firing,0.0006,lb,Mcf,0 +GT,SGP,duct_burner,0.0006,lb,Mcf,0 +GT,SGP,fluidized_bed_firing,0.0006,lb,Mcf,0 +GT,SGP,none,0.0006,lb,Mcf,0 +GT,SGP,other,0.0006,lb,Mcf,0 +GT,SGP,stoker,0.0006,lb,Mcf,0 +GT,SGP,tangential_firing,0.0006,lb,Mcf,0 +GT,SGP,vertical_firing,0.0006,lb,Mcf,0 +GT,SGP,wall_fired,0.0006,lb,Mcf,0 +IC,SGP,cell_burner,0.0006,lb,Mcf,0 +IC,SGP,cyclone_firing,0.0006,lb,Mcf,0 +IC,SGP,duct_burner,0.0006,lb,Mcf,0 +IC,SGP,fluidized_bed_firing,0.0006,lb,Mcf,0 +IC,SGP,none,0.0006,lb,Mcf,0 +IC,SGP,other,0.0006,lb,Mcf,0 +IC,SGP,stoker,0.0006,lb,Mcf,0 +IC,SGP,tangential_firing,0.0006,lb,Mcf,0 +IC,SGP,vertical_firing,0.0006,lb,Mcf,0 +IC,SGP,wall_fired,0.0006,lb,Mcf,0 +OT,SGP,cell_burner,0.0006,lb,Mcf,0 +OT,SGP,cyclone_firing,0.0006,lb,Mcf,0 +OT,SGP,duct_burner,0.0006,lb,Mcf,0 +OT,SGP,fluidized_bed_firing,0.00006,lb,Mcf,0 +OT,SGP,none,0.0006,lb,Mcf,0 +OT,SGP,other,0.0006,lb,Mcf,0 +OT,SGP,stoker,0.0006,lb,Mcf,0 +OT,SGP,tangential_firing,0.0006,lb,Mcf,0 +OT,SGP,vertical_firing,0.0006,lb,Mcf,0 +OT,SGP,wall_fired,0.0006,lb,Mcf,0 +ST,SGP,cell_burner,0.0006,lb,Mcf,0 +ST,SGP,cyclone_firing,0.0006,lb,Mcf,0 +ST,SGP,duct_burner,0.0006,lb,Mcf,0 +ST,SGP,fluidized_bed_firing,0.00006,lb,Mcf,0 +ST,SGP,none,0.0006,lb,Mcf,0 +ST,SGP,other,0.0006,lb,Mcf,0 +ST,SGP,stoker,0.0006,lb,Mcf,0 +ST,SGP,tangential_firing,0.0006,lb,Mcf,0 +ST,SGP,vertical_firing,0.0006,lb,Mcf,0 +ST,SGP,wall_fired,0.0006,lb,Mcf,0 +OT,SLW,cell_burner,2.8,lb,short ton,0 +OT,SLW,cyclone_firing,2.8,lb,short ton,0 +OT,SLW,duct_burner,2.8,lb,short ton,0 +OT,SLW,fluidized_bed_firing,0.28,lb,short ton,0 +OT,SLW,none,2.8,lb,short ton,0 +OT,SLW,other,2.8,lb,short ton,0 +OT,SLW,stoker,2.8,lb,short ton,0 +OT,SLW,tangential_firing,2.8,lb,short ton,0 +OT,SLW,vertical_firing,2.8,lb,short ton,0 +OT,SLW,wall_fired,2.8,lb,short ton,0 +ST,SLW,cell_burner,2.8,lb,short ton,0 +ST,SLW,cyclone_firing,2.8,lb,short ton,0 +ST,SLW,duct_burner,2.8,lb,short ton,0 +ST,SLW,fluidized_bed_firing,0.28,lb,short ton,0 +ST,SLW,none,2.8,lb,short ton,0 +ST,SLW,other,2.8,lb,short ton,0 +ST,SLW,stoker,2.8,lb,short ton,0 +ST,SLW,tangential_firing,2.8,lb,short ton,0 +ST,SLW,vertical_firing,2.8,lb,short ton,0 +ST,SLW,wall_fired,2.8,lb,short ton,0 +OT,SUB,cell_burner,35*S,lb,short ton,1 +OT,SUB,cyclone_firing,35*S,lb,short ton,1 +OT,SUB,duct_burner,35*S,lb,short ton,1 +OT,SUB,fluidized_bed_firing,3.5*S,lb,short ton,1 +OT,SUB,none,35*S,lb,short ton,1 +OT,SUB,other,35*S,lb,short ton,1 +OT,SUB,stoker,35*S,lb,short ton,1 +OT,SUB,tangential_firing,35*S,lb,short ton,1 +OT,SUB,vertical_firing,35*S,lb,short ton,1 +OT,SUB,wall_fired,35*S,lb,short ton,1 +ST,SUB,cell_burner,35*S,lb,short ton,1 +ST,SUB,cyclone_firing,35*S,lb,short ton,1 +ST,SUB,duct_burner,35*S,lb,short ton,1 +ST,SUB,fluidized_bed_firing,3.5*S,lb,short ton,1 +ST,SUB,none,35*S,lb,short ton,1 +ST,SUB,other,35*S,lb,short ton,1 +ST,SUB,stoker,35*S,lb,short ton,1 +ST,SUB,tangential_firing,35*S,lb,short ton,1 +ST,SUB,vertical_firing,35*S,lb,short ton,1 +ST,SUB,wall_fired,35*S,lb,short ton,1 +OT,TDF,cell_burner,38*S,lb,short ton,1 +OT,TDF,cyclone_firing,38*S,lb,short ton,1 +OT,TDF,duct_burner,38*S,lb,short ton,1 +OT,TDF,fluidized_bed_firing,3.8*S,lb,short ton,1 +OT,TDF,none,38*S,lb,short ton,1 +OT,TDF,other,38*S,lb,short ton,1 +OT,TDF,stoker,38*S,lb,short ton,1 +OT,TDF,tangential_firing,38*S,lb,short ton,1 +OT,TDF,vertical_firing,38*S,lb,short ton,1 +OT,TDF,wall_fired,38*S,lb,short ton,1 +ST,TDF,cell_burner,38*S,lb,short ton,1 +ST,TDF,cyclone_firing,38*S,lb,short ton,1 +ST,TDF,duct_burner,38*S,lb,short ton,1 +ST,TDF,fluidized_bed_firing,3.8*S,lb,short ton,1 +ST,TDF,none,38*S,lb,short ton,1 +ST,TDF,other,38*S,lb,short ton,1 +ST,TDF,stoker,38*S,lb,short ton,1 +ST,TDF,tangential_firing,38*S,lb,short ton,1 +ST,TDF,vertical_firing,38*S,lb,short ton,1 +ST,TDF,wall_fired,38*S,lb,short ton,1 +OT,WC,cell_burner,30*S,lb,short ton,1 +OT,WC,cyclone_firing,30*S,lb,short ton,1 +OT,WC,duct_burner,30*S,lb,short ton,1 +OT,WC,fluidized_bed_firing,3*S,lb,short ton,1 +OT,WC,none,30*S,lb,short ton,1 +OT,WC,other,30*S,lb,short ton,1 +OT,WC,stoker,30*S,lb,short ton,1 +OT,WC,tangential_firing,30*S,lb,short ton,1 +OT,WC,vertical_firing,30*S,lb,short ton,1 +OT,WC,wall_fired,30*S,lb,short ton,1 +ST,WC,cell_burner,30*S,lb,short ton,1 +ST,WC,cyclone_firing,30*S,lb,short ton,1 +ST,WC,duct_burner,30*S,lb,short ton,1 +ST,WC,fluidized_bed_firing,3*S,lb,short ton,1 +ST,WC,none,30*S,lb,short ton,1 +ST,WC,other,30*S,lb,short ton,1 +ST,WC,stoker,30*S,lb,short ton,1 +ST,WC,tangential_firing,30*S,lb,short ton,1 +ST,WC,vertical_firing,30*S,lb,short ton,1 +ST,WC,wall_fired,30*S,lb,short ton,1 +CA,WDL,cell_burner,5.88*S,lb,barrel,1 +CA,WDL,cyclone_firing,5.88*S,lb,barrel,1 +CA,WDL,duct_burner,5.88*S,lb,barrel,1 +CA,WDL,fluidized_bed_firing,5.88*S,lb,barrel,1 +CA,WDL,none,5.88*S,lb,barrel,1 +CA,WDL,other,5.88*S,lb,barrel,1 +CA,WDL,stoker,5.88*S,lb,barrel,1 +CA,WDL,tangential_firing,5.88*S,lb,barrel,1 +CA,WDL,vertical_firing,5.88*S,lb,barrel,1 +CA,WDL,wall_fired,5.88*S,lb,barrel,1 +CS,WDL,cell_burner,5.88*S,lb,barrel,1 +CS,WDL,cyclone_firing,5.88*S,lb,barrel,1 +CS,WDL,duct_burner,5.88*S,lb,barrel,1 +CS,WDL,fluidized_bed_firing,5.88*S,lb,barrel,1 +CS,WDL,none,5.88*S,lb,barrel,1 +CS,WDL,other,5.88*S,lb,barrel,1 +CS,WDL,stoker,5.88*S,lb,barrel,1 +CS,WDL,tangential_firing,5.88*S,lb,barrel,1 +CS,WDL,vertical_firing,5.88*S,lb,barrel,1 +CS,WDL,wall_fired,5.88*S,lb,barrel,1 +CT,WDL,cell_burner,5.88*S,lb,barrel,1 +CT,WDL,cyclone_firing,5.88*S,lb,barrel,1 +CT,WDL,duct_burner,5.88*S,lb,barrel,1 +CT,WDL,fluidized_bed_firing,5.88*S,lb,barrel,1 +CT,WDL,none,5.88*S,lb,barrel,1 +CT,WDL,other,5.88*S,lb,barrel,1 +CT,WDL,stoker,5.88*S,lb,barrel,1 +CT,WDL,tangential_firing,5.88*S,lb,barrel,1 +CT,WDL,vertical_firing,5.88*S,lb,barrel,1 +CT,WDL,wall_fired,5.88*S,lb,barrel,1 +GT,WDL,cell_burner,5.88*S,lb,barrel,1 +GT,WDL,cyclone_firing,5.88*S,lb,barrel,1 +GT,WDL,duct_burner,5.88*S,lb,barrel,1 +GT,WDL,fluidized_bed_firing,5.88*S,lb,barrel,1 +GT,WDL,none,5.88*S,lb,barrel,1 +GT,WDL,other,5.88*S,lb,barrel,1 +GT,WDL,stoker,5.88*S,lb,barrel,1 +GT,WDL,tangential_firing,5.88*S,lb,barrel,1 +GT,WDL,vertical_firing,5.88*S,lb,barrel,1 +GT,WDL,wall_fired,5.88*S,lb,barrel,1 +IC,WDL,cell_burner,5.88*S,lb,barrel,1 +IC,WDL,cyclone_firing,5.88*S,lb,barrel,1 +IC,WDL,duct_burner,5.88*S,lb,barrel,1 +IC,WDL,fluidized_bed_firing,5.88*S,lb,barrel,1 +IC,WDL,none,5.88*S,lb,barrel,1 +IC,WDL,other,5.88*S,lb,barrel,1 +IC,WDL,stoker,5.88*S,lb,barrel,1 +IC,WDL,tangential_firing,5.88*S,lb,barrel,1 +IC,WDL,vertical_firing,5.88*S,lb,barrel,1 +IC,WDL,wall_fired,5.88*S,lb,barrel,1 +OT,WDL,cell_burner,5.964*S,lb,barrel,1 +OT,WDL,cyclone_firing,5.964*S,lb,barrel,1 +OT,WDL,duct_burner,5.964*S,lb,barrel,1 +OT,WDL,fluidized_bed_firing,0.5964*S,lb,barrel,1 +OT,WDL,none,5.964*S,lb,barrel,1 +OT,WDL,other,5.964*S,lb,barrel,1 +OT,WDL,stoker,5.964*S,lb,barrel,1 +OT,WDL,tangential_firing,5.964*S,lb,barrel,1 +OT,WDL,vertical_firing,5.964*S,lb,barrel,1 +OT,WDL,wall_fired,5.964*S,lb,barrel,1 +ST,WDL,cell_burner,5.964*S,lb,barrel,1 +ST,WDL,cyclone_firing,5.964*S,lb,barrel,1 +ST,WDL,duct_burner,5.964*S,lb,barrel,1 +ST,WDL,fluidized_bed_firing,0.5964*S,lb,barrel,1 +ST,WDL,none,5.964*S,lb,barrel,1 +ST,WDL,other,5.964*S,lb,barrel,1 +ST,WDL,stoker,5.964*S,lb,barrel,1 +ST,WDL,tangential_firing,5.964*S,lb,barrel,1 +ST,WDL,vertical_firing,5.964*S,lb,barrel,1 +ST,WDL,wall_fired,5.964*S,lb,barrel,1 +OT,WDS,cell_burner,0.29,lb,short ton,0 +OT,WDS,cyclone_firing,0.29,lb,short ton,0 +OT,WDS,duct_burner,0.29,lb,short ton,0 +OT,WDS,fluidized_bed_firing,0.08,lb,short ton,0 +OT,WDS,none,0.29,lb,short ton,0 +OT,WDS,other,0.29,lb,short ton,0 +OT,WDS,stoker,0.08,lb,short ton,0 +OT,WDS,tangential_firing,0.29,lb,short ton,0 +OT,WDS,vertical_firing,0.29,lb,short ton,0 +OT,WDS,wall_fired,0.29,lb,short ton,0 +ST,WDS,cell_burner,0.29,lb,short ton,0 +ST,WDS,cyclone_firing,0.29,lb,short ton,0 +ST,WDS,duct_burner,0.29,lb,short ton,0 +ST,WDS,fluidized_bed_firing,0.08,lb,short ton,0 +ST,WDS,none,0.29,lb,short ton,0 +ST,WDS,other,0.29,lb,short ton,0 +ST,WDS,stoker,0.08,lb,short ton,0 +ST,WDS,tangential_firing,0.29,lb,short ton,0 +ST,WDS,vertical_firing,0.29,lb,short ton,0 +ST,WDS,wall_fired,0.29,lb,short ton,0 +CA,WO,cell_burner,5.88*S,lb,barrel,1 +CA,WO,cyclone_firing,5.88*S,lb,barrel,1 +CA,WO,duct_burner,5.88*S,lb,barrel,1 +CA,WO,fluidized_bed_firing,5.88*S,lb,barrel,1 +CA,WO,none,5.88*S,lb,barrel,1 +CA,WO,other,5.88*S,lb,barrel,1 +CA,WO,stoker,5.88*S,lb,barrel,1 +CA,WO,tangential_firing,5.88*S,lb,barrel,1 +CA,WO,vertical_firing,5.88*S,lb,barrel,1 +CA,WO,wall_fired,5.88*S,lb,barrel,1 +CS,WO,cell_burner,5.88*S,lb,barrel,1 +CS,WO,cyclone_firing,5.88*S,lb,barrel,1 +CS,WO,duct_burner,5.88*S,lb,barrel,1 +CS,WO,fluidized_bed_firing,5.88*S,lb,barrel,1 +CS,WO,none,5.88*S,lb,barrel,1 +CS,WO,other,5.88*S,lb,barrel,1 +CS,WO,stoker,5.88*S,lb,barrel,1 +CS,WO,tangential_firing,5.88*S,lb,barrel,1 +CS,WO,vertical_firing,5.88*S,lb,barrel,1 +CS,WO,wall_fired,5.88*S,lb,barrel,1 +CT,WO,cell_burner,5.88*S,lb,barrel,1 +CT,WO,cyclone_firing,5.88*S,lb,barrel,1 +CT,WO,duct_burner,5.88*S,lb,barrel,1 +CT,WO,fluidized_bed_firing,5.88*S,lb,barrel,1 +CT,WO,none,5.88*S,lb,barrel,1 +CT,WO,other,5.88*S,lb,barrel,1 +CT,WO,stoker,5.88*S,lb,barrel,1 +CT,WO,tangential_firing,5.88*S,lb,barrel,1 +CT,WO,vertical_firing,5.88*S,lb,barrel,1 +CT,WO,wall_fired,5.88*S,lb,barrel,1 +GT,WO,cell_burner,5.88*S,lb,barrel,1 +GT,WO,cyclone_firing,5.88*S,lb,barrel,1 +GT,WO,duct_burner,5.88*S,lb,barrel,1 +GT,WO,fluidized_bed_firing,5.88*S,lb,barrel,1 +GT,WO,none,5.88*S,lb,barrel,1 +GT,WO,other,5.88*S,lb,barrel,1 +GT,WO,stoker,5.88*S,lb,barrel,1 +GT,WO,tangential_firing,5.88*S,lb,barrel,1 +GT,WO,vertical_firing,5.88*S,lb,barrel,1 +GT,WO,wall_fired,5.88*S,lb,barrel,1 +IC,WO,cell_burner,5.88*S,lb,barrel,1 +IC,WO,cyclone_firing,5.88*S,lb,barrel,1 +IC,WO,duct_burner,5.88*S,lb,barrel,1 +IC,WO,fluidized_bed_firing,5.88*S,lb,barrel,1 +IC,WO,none,5.88*S,lb,barrel,1 +IC,WO,other,5.88*S,lb,barrel,1 +IC,WO,stoker,5.88*S,lb,barrel,1 +IC,WO,tangential_firing,5.88*S,lb,barrel,1 +IC,WO,vertical_firing,5.88*S,lb,barrel,1 +IC,WO,wall_fired,5.88*S,lb,barrel,1 +OT,WO,cell_burner,6.174*S,lb,barrel,1 +OT,WO,cyclone_firing,6.174*S,lb,barrel,1 +OT,WO,duct_burner,6.174*S,lb,barrel,1 +OT,WO,fluidized_bed_firing,0.6174*S,lb,barrel,1 +OT,WO,none,6.174*S,lb,barrel,1 +OT,WO,other,6.174*S,lb,barrel,1 +OT,WO,stoker,6.174*S,lb,barrel,1 +OT,WO,tangential_firing,6.174*S,lb,barrel,1 +OT,WO,vertical_firing,6.174*S,lb,barrel,1 +OT,WO,wall_fired,6.174*S,lb,barrel,1 +ST,WO,cell_burner,6.174*S,lb,barrel,1 +ST,WO,cyclone_firing,6.174*S,lb,barrel,1 +ST,WO,duct_burner,6.174*S,lb,barrel,1 +ST,WO,fluidized_bed_firing,0.6174*S,lb,barrel,1 +ST,WO,none,6.174*S,lb,barrel,1 +ST,WO,other,6.174*S,lb,barrel,1 +ST,WO,stoker,6.174*S,lb,barrel,1 +ST,WO,tangential_firing,6.174*S,lb,barrel,1 +ST,WO,vertical_firing,6.174*S,lb,barrel,1 +ST,WO,wall_fired,6.174*S,lb,barrel,1 diff --git a/notebooks/work_in_progress/sandbox.ipynb b/notebooks/work_in_progress/sandbox.ipynb index 528a7179..c373176c 100644 --- a/notebooks/work_in_progress/sandbox.ipynb +++ b/notebooks/work_in_progress/sandbox.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -38,954 +38,6 @@ "year = 2021\n", "path_prefix = f\"{year}/\"" ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
report_yearplant_id_epaemissions_unit_id_epagenerator_id_epaplant_id_eiaboiler_idgenerator_id
02018311311
12018322322
22018333333
32018344344
42018355355
........................
12827202163688CT-9CTG-963688NoneCTG-9
12828202164854CT1GTG0164854NoneGTG01
12829202164854CT2GTG0264854NoneGTG02
12830202170454MAG1MAG154538NoneMAG1
12831202170454MAG2MAG254538NoneMAG2
\n", - "

12832 rows × 7 columns

\n", - "
" - ], - "text/plain": [ - " report_year plant_id_epa emissions_unit_id_epa generator_id_epa plant_id_eia boiler_id generator_id\n", - "0 2018 3 1 1 3 1 1\n", - "1 2018 3 2 2 3 2 2\n", - "2 2018 3 3 3 3 3 3\n", - "3 2018 3 4 4 3 4 4\n", - "4 2018 3 5 5 3 5 5\n", - "... ... ... ... ... ... ... ...\n", - "12827 2021 63688 CT-9 CTG-9 63688 None CTG-9\n", - "12828 2021 64854 CT1 GTG01 64854 None GTG01\n", - "12829 2021 64854 CT2 GTG02 64854 None GTG02\n", - "12830 2021 70454 MAG1 MAG1 54538 None MAG1\n", - "12831 2021 70454 MAG2 MAG2 54538 None MAG2\n", - "\n", - "[12832 rows x 7 columns]" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "crosswalk = load_data.load_pudl_table(\"epacamd_eia\")\n", - "crosswalk" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
report_yearplant_id_epaemissions_unit_id_epagenerator_id_epaplant_id_eiaboiler_idgenerator_id
\n", - "
" - ], - "text/plain": [ - "Empty DataFrame\n", - "Columns: [report_year, plant_id_epa, emissions_unit_id_epa, generator_id_epa, plant_id_eia, boiler_id, generator_id]\n", - "Index: []" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "crosswalk[crosswalk[\"plant_id_epa\"] == 65961]" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
report_yearplant_id_epaemissions_unit_id_epagenerator_id_epaplant_id_eiaboiler_idgenerator_id
02018.0311311
12021.0311311
22018.0322322
32021.0322322
42018.0333333
........................
38837NaN65961NaNNaN65961NaNGEN1
38838NaN65962NaNNaN65962NaNMS4
38839NaN65962NaNNaN65962NaNMS4B
38840NaN65963NaNNaN65963NaNMS5
38841NaN65963NaNNaN65963NaNMS5B
\n", - "

38842 rows × 7 columns

\n", - "
" - ], - "text/plain": [ - " report_year plant_id_epa emissions_unit_id_epa generator_id_epa plant_id_eia boiler_id generator_id\n", - "0 2018.0 3 1 1 3 1 1\n", - "1 2021.0 3 1 1 3 1 1\n", - "2 2018.0 3 2 2 3 2 2\n", - "3 2021.0 3 2 2 3 2 2\n", - "4 2018.0 3 3 3 3 3 3\n", - "... ... ... ... ... ... ... ...\n", - "38837 NaN 65961 NaN NaN 65961 NaN GEN1\n", - "38838 NaN 65962 NaN NaN 65962 NaN MS4\n", - "38839 NaN 65962 NaN NaN 65962 NaN MS4B\n", - "38840 NaN 65963 NaN NaN 65963 NaN MS5\n", - "38841 NaN 65963 NaN NaN 65963 NaN MS5B\n", - "\n", - "[38842 rows x 7 columns]" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "oge_cw = load_data.load_epa_eia_crosswalk(year)\n", - "oge_cw" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
plant_id_eiaplant_id_epasubplant_idunit_id_pudlemissions_unit_id_epagenerator_id
011.00NaNWT2WT2
111.01NaNWT1WT1
211.02NaN5.15.1
311.03NaN55
411.04NaN33
.....................
39943880109NaN0NaNB001None
39944880110NaN0NaN1None
39945880110NaN1NaN2None
39946880110NaN2NaN3None
39947880110NaN3NaN4None
\n", - "

39948 rows × 6 columns

\n", - "
" - ], - "text/plain": [ - " plant_id_eia plant_id_epa subplant_id unit_id_pudl emissions_unit_id_epa generator_id\n", - "0 1 1.0 0 NaN WT2 WT2\n", - "1 1 1.0 1 NaN WT1 WT1\n", - "2 1 1.0 2 NaN 5.1 5.1\n", - "3 1 1.0 3 NaN 5 5\n", - "4 1 1.0 4 NaN 3 3\n", - "... ... ... ... ... ... ...\n", - "39943 880109 NaN 0 NaN B001 None\n", - "39944 880110 NaN 0 NaN 1 None\n", - "39945 880110 NaN 1 NaN 2 None\n", - "39946 880110 NaN 2 NaN 3 None\n", - "39947 880110 NaN 3 NaN 4 None\n", - "\n", - "[39948 rows x 6 columns]" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "pudl_subplants = load_data.load_pudl_table(\"epacamd_eia_subplant_ids\")\n", - "pudl_subplants" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
plant_id_eiaplant_id_epasubplant_idunit_id_pudlemissions_unit_id_epagenerator_id
471617321732.00NaN107
471717321732.00NaN108
471817321732.00NaN117
471917321732.00NaN127
472017321732.00NaN97
472117321732.00NaN118
472217321732.00NaN128
472317321732.00NaN98
472417321732.01NaN66
\n", - "
" - ], - "text/plain": [ - " plant_id_eia plant_id_epa subplant_id unit_id_pudl emissions_unit_id_epa generator_id\n", - "4716 1732 1732.0 0 NaN 10 7\n", - "4717 1732 1732.0 0 NaN 10 8\n", - "4718 1732 1732.0 0 NaN 11 7\n", - "4719 1732 1732.0 0 NaN 12 7\n", - "4720 1732 1732.0 0 NaN 9 7\n", - "4721 1732 1732.0 0 NaN 11 8\n", - "4722 1732 1732.0 0 NaN 12 8\n", - "4723 1732 1732.0 0 NaN 9 8\n", - "4724 1732 1732.0 1 NaN 6 6" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "pudl_subplants[pudl_subplants[\"plant_id_epa\"] == 1732]" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
report_yearplant_id_epaemissions_unit_id_epagenerator_id_epaplant_id_eiaboiler_idgenerator_id
1264201817321071732107
1265201817321081732108
1266201817321171732117
1267201817321181732118
1268201817321271732127
1269201817321281732128
12702018173297173297
12712018173298173298
7683202117321071732107
7684202117321081732108
7685202117321171732117
7686202117321181732118
7687202117321271732127
7688202117321281732128
76892021173297173297
76902021173298173298
\n", - "
" - ], - "text/plain": [ - " report_year plant_id_epa emissions_unit_id_epa generator_id_epa plant_id_eia boiler_id generator_id\n", - "1264 2018 1732 10 7 1732 10 7\n", - "1265 2018 1732 10 8 1732 10 8\n", - "1266 2018 1732 11 7 1732 11 7\n", - "1267 2018 1732 11 8 1732 11 8\n", - "1268 2018 1732 12 7 1732 12 7\n", - "1269 2018 1732 12 8 1732 12 8\n", - "1270 2018 1732 9 7 1732 9 7\n", - "1271 2018 1732 9 8 1732 9 8\n", - "7683 2021 1732 10 7 1732 10 7\n", - "7684 2021 1732 10 8 1732 10 8\n", - "7685 2021 1732 11 7 1732 11 7\n", - "7686 2021 1732 11 8 1732 11 8\n", - "7687 2021 1732 12 7 1732 12 7\n", - "7688 2021 1732 12 8 1732 12 8\n", - "7689 2021 1732 9 7 1732 9 7\n", - "7690 2021 1732 9 8 1732 9 8" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "crosswalk[crosswalk[\"plant_id_epa\"] == 1732]" - ] } ], "metadata": { diff --git a/src/column_checks.py b/src/column_checks.py index 8707784c..3085e9a1 100644 --- a/src/column_checks.py +++ b/src/column_checks.py @@ -437,7 +437,7 @@ def get_dtypes(): "net_generation_mwh": "float64", "prime_mover_code": "str", "hourly_data_source": "category", - "nox_control_id": "str", + "nox_control_id_eia": "str", "fuel_category": "str", "ba_code": "str", "ba_code_physical": "str", @@ -458,28 +458,28 @@ def get_dtypes(): "profile_method": "str", "data_availability": "category", "equipment_tech_description": "str", - "pm_control_id": "str", - "so2_control_id": "str", - "nox_control_id": "str", - "hg_control_id": "str", + "particulate_control_id_eia": "str", + "so2_control_id_eia": "str", + "nox_control_id_eia": "str", + "mercury_control_id_eia": "str", "operational_status": "str", "hours_in_service": "float64", "annual_nox_emission_rate_lb_per_mmbtu": "float64", "ozone_season_nox_emission_rate_lb_per_mmbtu": "float64", - "pm_emission_rate_lb_per_mmbtu": "float64", - "pm_removal_efficiency_annual": "float64", - "pm_removal_efficiency_at_full_load": "float64", + "particulate_emission_rate_lb_per_mmbtu": "float64", + "particulate_removal_efficiency_annual": "float64", + "particulate_removal_efficiency_at_full_load": "float64", "so2_removal_efficiency_annual": "float64", "so2_removal_efficiency_at_full_load": "float64", "fgd_sorbent_consumption_1000_tons": "float64", "fgd_electricity_consumption_mwh": "float64", - "hg_removal_efficiency": "float64", - "hg_emission_rate_lb_per_trillion_btu": "float64", + "mercury_removal_efficiency": "float64", + "mercury_emission_rate_lb_per_trillion_btu": "float64", "acid_gas_removal_efficiency": "float64", "firing_type_1": "str", "firing_type_2": "str", "firing_type_3": "str", - "boiler_bottom_type": "str", + "wet_dry_bottom": "str", } return dtypes_to_use diff --git a/src/data_cleaning.py b/src/data_cleaning.py index e4946f73..e9febcca 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -1578,8 +1578,18 @@ def count_total_units_in_subplant(year): pd.read_csv( outputs_folder(f"{year}/subplant_crosswalk_{year}.csv"), dtype=get_dtypes(), - parse_dates=["current_planned_generator_operating_date", "generator_retirement_date"], - )[["plant_id_eia", "emissions_unit_id_epa", "subplant_id", "generator_retirement_date"]] + parse_dates=[ + "current_planned_generator_operating_date", + "generator_retirement_date", + ], + )[ + [ + "plant_id_eia", + "emissions_unit_id_epa", + "subplant_id", + "generator_retirement_date", + ] + ] .drop_duplicates() .dropna(subset="emissions_unit_id_epa") ) diff --git a/src/emissions.py b/src/emissions.py index 753433a1..cce3b614 100644 --- a/src/emissions.py +++ b/src/emissions.py @@ -572,7 +572,7 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea subset=[ "prime_mover_code", "energy_source_code", - "boiler_bottom_type", + "wet_dry_bottom", "boiler_firing_type", ] ) @@ -608,7 +608,7 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea on=[ "prime_mover_code", "energy_source_code", - "boiler_bottom_type", + "wet_dry_bottom", "boiler_firing_type", ], validate="m:1", @@ -644,7 +644,7 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea [ "prime_mover_code", "energy_source_code", - "boiler_bottom_type", + "wet_dry_bottom", "boiler_firing_type", ], ] @@ -654,7 +654,7 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea "energy_source_code", "prime_mover_code", "boiler_firing_type", - "boiler_bottom_type", + "wet_dry_bottom", ] ) ) @@ -675,7 +675,7 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea [ "prime_mover_code", "energy_source_code", - "boiler_bottom_type", + "wet_dry_bottom", "boiler_firing_type", ], ] @@ -685,7 +685,7 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea "energy_source_code", "prime_mover_code", "boiler_firing_type", - "boiler_bottom_type", + "wet_dry_bottom", ] ) ) @@ -721,38 +721,34 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea def load_boiler_firing_type(year): - boiler_design_parameters_eia860 = load_data.load_boiler_design_parameters_eia860( - year - ) - - firing_type_description = { - "CB": "CELLBURNER", - "CY": "CYCLONE", - "DB": "DUCTBURNER", - "FB": "FLUIDIZED", - "SS": "STOKER", - "TF": "TANGENTIAL", - "VF": "VERTICAL", - "WF": "WALL", - "OT": "OTHER", - } - - # only keep boilers that are operational - boiler_firing_type = boiler_design_parameters_eia860.copy()[ - boiler_design_parameters_eia860["operational_status"] == "OP" - ] + boiler_firing_type = load_data.load_pudl_table( + "boilers_eia860", + year, + columns=[ + "plant_id_eia", + "boiler_id", + "firing_type_1", + "wet_dry_bottom", + ], + ) - boiler_firing_type["boiler_firing_type"] = boiler_firing_type["firing_type_1"].map( - firing_type_description + firing_types_eia = load_data.load_pudl_table("firing_types_eia") + + boiler_firing_type["boiler_firing_type"] = ( + boiler_firing_type["firing_type_1"] + .map(dict(zip(firing_types_eia["code"], firing_types_eia["label"]))) + .fillna("none") ) - boiler_firing_type["boiler_bottom_type"] = boiler_firing_type[ - "boiler_bottom_type" - ].replace({"D": "DRY", "W": "WET"}) + boiler_firing_type["wet_dry_bottom"] = ( + boiler_firing_type["wet_dry_bottom"] + .replace({"D": "dry", "W": "wet"}) + .fillna("none") + ) boiler_firing_type = boiler_firing_type[ - ["plant_id_eia", "boiler_id", "boiler_bottom_type", "boiler_firing_type"] - ].dropna(subset=["boiler_bottom_type", "boiler_firing_type"], thresh=1) + ["plant_id_eia", "boiler_id", "wet_dry_bottom", "boiler_firing_type"] + ].dropna(subset=["wet_dry_bottom", "boiler_firing_type"], thresh=1) return boiler_firing_type @@ -992,10 +988,10 @@ def load_controlled_nox_emission_rates(year): nox_rates = nox_rates[ [ "plant_id_eia", - "nox_control_id", - "pm_control_id", - "so2_control_id", - "hg_control_id", + "nox_control_id_eia", + "particulate_control_id_eia", + "so2_control_id_eia", + "mercury_control_id_eia", "hours_in_service", "annual_nox_emission_rate_lb_per_mmbtu", "ozone_season_nox_emission_rate_lb_per_mmbtu", @@ -1066,64 +1062,68 @@ def associate_control_ids_with_boiler_id(df, year, pollutant): in the order specified by `id_order` """ - all_pollutants = ["pm", "so2", "nox", "hg"] + all_pollutants = ["particulate", "so2", "nox", "mercury"] # reorder the pollutant list to make the primary pollutant first all_pollutants.remove(pollutant) pollutant_order = [pollutant] + all_pollutants + boiler_association_eia860 = load_data.load_pudl_table( + "boiler_emissions_control_equipment_assn_eia860", year + ) + counter = 1 for pol in pollutant_order: + pol_control_id_assn = ( + boiler_association_eia860[ + boiler_association_eia860["emission_control_id_type"] == pol + ] + .copy() + .rename(columns={"emission_control_id_eia": f"{pol}_control_id_eia"}) + ) + # if this is the first time through the loop if counter == 1: # load the association table and rename the boiler id column to specify which table it came from - boiler_association_eia860 = ( - load_data.load_boiler_control_id_association_eia860(year, pol) - ) df = df.merge( - boiler_association_eia860[ + pol_control_id_assn[ [ "plant_id_eia", - f"{pol}_control_id", + f"{pol}_control_id_eia", "boiler_id", ] ], how="left", - on=["plant_id_eia", f"{pol}_control_id"], + on=["plant_id_eia", f"{pol}_control_id_eia"], validate="m:m", ) counter += 1 else: # split out the data that is still missing a boiler_id missing_boiler_id = df[ - df["boiler_id"].isna() & ~df[f"{pol}_control_id"].isna() + df["boiler_id"].isna() & ~df[f"{pol}_control_id_eia"].isna() ].drop(columns=["boiler_id"]) # remove this data from the original dataframe - df = df[~(df["boiler_id"].isna() & ~df[f"{pol}_control_id"].isna())] - - # load the association for the new pol - boiler_association_eia860 = ( - load_data.load_boiler_control_id_association_eia860(year, pol) - ) + df = df[~(df["boiler_id"].isna() & ~df[f"{pol}_control_id_eia"].isna())] missing_boiler_id = missing_boiler_id.merge( - boiler_association_eia860[ + pol_control_id_assn[ [ "plant_id_eia", - f"{pol}_control_id", + f"{pol}_control_id_eia", "boiler_id", ] ], how="left", - on=["plant_id_eia", f"{pol}_control_id"], + on=["plant_id_eia", f"{pol}_control_id_eia"], validate="m:m", ) # add this data back to the original dataframe df = pd.concat([df, missing_boiler_id], axis=0) # if there are any missing boiler_ids, fill using the nox_control_id, which is likely to match a boiler - df["boiler_id"] = df["boiler_id"].fillna(df[f"{pollutant}_control_id"]) + df["boiler_id"] = df["boiler_id"].fillna(df[f"{pollutant}_control_id_eia"]) return df @@ -1300,7 +1300,7 @@ def calculate_generator_so2_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea # load the boiler firing type info boiler_firing_type = load_boiler_firing_type(year) # drop the boiler bottom type data - boiler_firing_type = boiler_firing_type.drop(columns="boiler_bottom_type") + boiler_firing_type = boiler_firing_type.drop(columns="wet_dry_bottom") boiler_firing_type = boiler_firing_type.drop_duplicates() # identify the boiler firing type for each generator @@ -1621,10 +1621,10 @@ def load_so2_control_efficiencies(year): so2_efficiency = so2_efficiency[ [ "plant_id_eia", - "so2_control_id", - "nox_control_id", - "pm_control_id", - "hg_control_id", + "so2_control_id_eia", + "nox_control_id_eia", + "particulate_control_id_eia", + "mercury_control_id_eia", "hours_in_service", "so2_removal_efficiency_annual", "so2_removal_efficiency_at_full_load", diff --git a/src/load_data.py b/src/load_data.py index 591ed792..3e2d7881 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -659,32 +659,34 @@ def load_emissions_controls_eia923(year: int): "report_date", "plant_id_eia", "equipment_tech_description", - "pm_control_id", - "so2_control_id", - "nox_control_id", - "hg_control_id", + "particulate_control_id_eia", + "so2_control_id_eia", + "nox_control_id_eia", + "mercury_control_id_eia", "operational_status", "hours_in_service", "annual_nox_emission_rate_lb_per_mmbtu", "ozone_season_nox_emission_rate_lb_per_mmbtu", - "pm_emission_rate_lb_per_mmbtu", - "pm_removal_efficiency_annual", - "pm_removal_efficiency_at_full_load", - "pm_test_date", + "particulate_emission_rate_lb_per_mmbtu", + "particulate_removal_efficiency_annual", + "particulate_removal_efficiency_at_full_load", + "particulate_test_date", "so2_removal_efficiency_annual", "so2_removal_efficiency_at_full_load", "so2_test_date", "fgd_sorbent_consumption_1000_tons", "fgd_electricity_consumption_mwh", - "hg_removal_efficiency", - "hg_emission_rate_lb_per_trillion_btu", + "mercury_removal_efficiency", + "mercury_emission_rate_lb_per_trillion_btu", "acid_gas_removal_efficiency", ] # For 2012-2015 and earlier, mercury emission rate is not reported in EIA923, so we need # to remove that column to avoid an error. if year <= 2015: - emissions_controls_eia923_names.remove("hg_emission_rate_lb_per_trillion_btu") + emissions_controls_eia923_names.remove( + "mercury_emission_rate_lb_per_trillion_btu" + ) if year >= 2012: # Handle filename changes across years. @@ -728,7 +730,7 @@ def load_emissions_controls_eia923(year: int): names=emissions_controls_eia923_names, dtype=get_dtypes(), na_values=".", - parse_dates=["report_date", "pm_test_date", "so2_test_date"], + parse_dates=["report_date", "particulate_test_date", "so2_test_date"], ) else: logger.warning( @@ -744,109 +746,6 @@ def load_emissions_controls_eia923(year: int): return emissions_controls_eia923 -def load_boiler_control_id_association_eia860(year, pollutant): - """Generic function for loading the EIA-860 tables that associate boiler_id with a pollutant-specific control id. - - the `pollutant` parameter could be any of the following: ['pm','so2','nox','hg'] - """ - pollutant_abbreviation_to_name = { - "pm": "Particulate Matter", - "so2": "SO2", - "nox": "NOx", - "hg": "Mercury", - } - boiler_association_eia860_names = [ - "utility_id_eia", - "utility_name_eia", - "plant_id_eia", - "plant_name_eia", - "boiler_id", - f"{pollutant}_control_id", - "steam_plant_type", - ] - - if year <= 2013: - # This column isn't included in 2013 and earlier. - boiler_association_eia860_names.remove("steam_plant_type") - - # NOTE: Pre-2013, the EIA-860 file format changes, so this load function will not work - # The environmental association data is available pre-2013, but would require additional work to format - if year >= 2013: - boiler_control_id_association_eia860 = pd.read_excel( - io=downloads_folder(f"eia860/eia860{year}/6_1_EnviroAssoc_Y{year}.xlsx"), - sheet_name=f"Boiler {pollutant_abbreviation_to_name[pollutant]}", - header=1, - names=boiler_association_eia860_names, - dtype=get_dtypes(), - na_values=".", - skipfooter=1, - ) - # return a blank dataframe if the data is not available - else: - logger.warning( - "Environmental association data prior to 2013 have not been integrated into the data pipeline." - ) - logger.warning( - "This may result in less accurate pollutant emissions calculations." - ) - boiler_control_id_association_eia860 = pd.DataFrame( - columns=boiler_association_eia860_names - ) - - return boiler_control_id_association_eia860 - - -def load_boiler_design_parameters_eia860(year): - raw_column_names = [ - "Plant Code", - "Boiler ID", - "Boiler Status", - "Firing Type 1", - "Firing Type 2", - "Firing Type 3", - "Wet Dry Bottom", - ] - - boiler_design_parameters_eia860_names = { - "Plant Code": "plant_id_eia", - "Boiler ID": "boiler_id", - "Boiler Status": "operational_status", - "Firing Type 1": "firing_type_1", - "Firing Type 2": "firing_type_2", - "Firing Type 3": "firing_type_3", - "Wet Dry Bottom": "boiler_bottom_type", - } - - # NOTE: Pre-2013, the EIA-860 file format changes, so this load function will not work - # The boiler design data is available pre-2013, but would require a lot of work to find the correct format - if year >= 2013: - boiler_design_parameters_eia860 = pd.read_excel( - io=(downloads_folder(f"eia860/eia860{year}/6_2_EnviroEquip_Y{year}.xlsx")), - sheet_name="Boiler Info & Design Parameters", - header=1, - usecols=raw_column_names, # "C,F,H,N:P,AE", - na_values=".", - skipfooter=1, - ) - - boiler_design_parameters_eia860 = boiler_design_parameters_eia860.rename( - columns=boiler_design_parameters_eia860_names - ) - # return a blank dataframe if the data is not available - else: - logger.warning( - "Boiler Design data prior to 2013 have not been integrated into the data pipeline." - ) - logger.warning( - "This may result in less accurate NOx and SO2 emissions calculations." - ) - boiler_design_parameters_eia860 = pd.DataFrame( - columns=list(boiler_design_parameters_eia860_names.values()) - ) - - return boiler_design_parameters_eia860 - - def load_unit_to_boiler_associations(year): """Creates a table that associates EPA units with EIA boilers""" subplant_crosswalk = pd.read_csv( From 729b98bfa34684161ce9ae03ad6a81eecce38c68 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 2 Dec 2023 16:06:08 -0800 Subject: [PATCH 20/85] apply dtypes --- notebooks/work_in_progress/sandbox.ipynb | 251 ++++++++++++++++++++++- src/column_checks.py | 134 ++++++------ src/data_cleaning.py | 2 +- src/emissions.py | 11 + src/load_data.py | 4 + 5 files changed, 334 insertions(+), 68 deletions(-) diff --git a/notebooks/work_in_progress/sandbox.ipynb b/notebooks/work_in_progress/sandbox.ipynb index c373176c..4814bb6f 100644 --- a/notebooks/work_in_progress/sandbox.ipynb +++ b/notebooks/work_in_progress/sandbox.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -38,6 +38,255 @@ "year = 2021\n", "path_prefix = f\"{year}/\"" ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "dtypes_to_use = {\n", + " \"plant_id_eia\": \"Int32\",\n", + " \"plant_id_epa\": \"Int32\",\n", + " \"subplant_id\": \"Int16\",\n", + " \"generator_id\": \"str\",\n", + " \"emissions_unit_id_epa\": \"str\",\n", + " \"boiler_id\": \"str\",\n", + " \"operating_time_hours\": \"float16\",\n", + " \"gross_generation_mwh\": \"float64\",\n", + " \"steam_load_1000_lb\": \"float64\",\n", + " \"fuel_consumed_mmbtu\": \"float64\",\n", + " \"co2_mass_lb\": \"float64\",\n", + " \"co2_mass_measurement_code\": \"category\",\n", + " \"nox_mass_lb\": \"float64\",\n", + " \"nox_mass_measurement_code\": \"category\",\n", + " \"so2_mass_lb\": \"float64\",\n", + " \"so2_mass_measurement_code\": \"category\",\n", + " \"energy_source_code\": \"str\",\n", + " \"ch4_mass_lb\": \"float64\",\n", + " \"n2o_mass_lb\": \"float64\",\n", + " \"fuel_consumed_for_electricity_mmbtu\": \"float64\",\n", + " \"co2_mass_lb_for_electricity\": \"float64\",\n", + " \"ch4_mass_lb_for_electricity\": \"float64\",\n", + " \"n2o_mass_lb_for_electricity\": \"float64\",\n", + " \"nox_mass_lb_for_electricity\": \"float64\",\n", + " \"so2_mass_lb_for_electricity\": \"float64\",\n", + " \"co2_mass_lb_adjusted\": \"float64\",\n", + " \"ch4_mass_lb_adjusted\": \"float64\",\n", + " \"n2o_mass_lb_adjusted\": \"float64\",\n", + " \"nox_mass_lb_adjusted\": \"float64\",\n", + " \"so2_mass_lb_adjusted\": \"float64\",\n", + " \"co2_mass_lb_for_electricity_adjusted\": \"float64\",\n", + " \"ch4_mass_lb_for_electricity_adjusted\": \"float64\",\n", + " \"n2o_mass_lb_for_electricity_adjusted\": \"float64\",\n", + " \"nox_mass_lb_for_electricity_adjusted\": \"float64\",\n", + " \"so2_mass_lb_for_electricity_adjusted\": \"float64\",\n", + " \"co2e_mass_lb\": \"float64\",\n", + " \"co2e_mass_lb_for_electricity\": \"float64\",\n", + " \"co2e_mass_lb_adjusted\": \"float64\",\n", + " \"co2e_mass_lb_for_electricity_adjusted\": \"float64\",\n", + " \"gtn_method\": \"category\",\n", + " \"net_generation_mwh\": \"float64\",\n", + " \"prime_mover_code\": \"str\",\n", + " \"hourly_data_source\": \"category\",\n", + " \"nox_control_id_eia\": \"str\",\n", + " \"fuel_category\": \"str\",\n", + " \"ba_code\": \"str\",\n", + " \"ba_code_physical\": \"str\",\n", + " \"plant_primary_fuel\": \"str\",\n", + " \"subplant_primary_fuel\": \"str\",\n", + " \"fuel_category_eia930\": \"str\",\n", + " \"state\": \"str\",\n", + " \"distribution_flag\": \"bool\",\n", + " \"timezone\": \"str\",\n", + " \"eia930_profile\": \"float64\",\n", + " \"cems_profile\": \"float64\",\n", + " \"residual_profile\": \"float64\",\n", + " \"scaled_residual_profile\": \"float64\",\n", + " \"shifted_residual_profile\": \"float64\",\n", + " \"imputed_profile\": \"float64\",\n", + " \"profile\": \"float64\",\n", + " \"flat_profile\": \"float32\",\n", + " \"profile_method\": \"str\",\n", + " \"data_availability\": \"category\",\n", + " \"equipment_tech_description\": \"str\",\n", + " \"particulate_control_id_eia\": \"str\",\n", + " \"so2_control_id_eia\": \"str\",\n", + " \"nox_control_id_eia\": \"str\",\n", + " \"mercury_control_id_eia\": \"str\",\n", + " \"operational_status\": \"str\",\n", + " \"hours_in_service\": \"float64\",\n", + " \"annual_nox_emission_rate_lb_per_mmbtu\": \"float64\",\n", + " \"ozone_season_nox_emission_rate_lb_per_mmbtu\": \"float64\",\n", + " \"particulate_emission_rate_lb_per_mmbtu\": \"float64\",\n", + " \"particulate_removal_efficiency_annual\": \"float64\",\n", + " \"particulate_removal_efficiency_at_full_load\": \"float64\",\n", + " \"so2_removal_efficiency_annual\": \"float64\",\n", + " \"so2_removal_efficiency_at_full_load\": \"float64\",\n", + " \"fgd_sorbent_consumption_1000_tons\": \"float64\",\n", + " \"fgd_electricity_consumption_mwh\": \"float64\",\n", + " \"mercury_removal_efficiency\": \"float64\",\n", + " \"mercury_emission_rate_lb_per_trillion_btu\": \"float64\",\n", + " \"acid_gas_removal_efficiency\": \"float64\",\n", + " \"firing_type_1\": \"str\",\n", + " \"firing_type_2\": \"str\",\n", + " \"firing_type_3\": \"str\",\n", + " \"wet_dry_bottom\": \"str\",\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'acid_gas_removal_efficiency': 'float64',\n", + " 'annual_nox_emission_rate_lb_per_mmbtu': 'float64',\n", + " 'ba_code': 'str',\n", + " 'ba_code_physical': 'str',\n", + " 'boiler_id': 'str',\n", + " 'cems_profile': 'float64',\n", + " 'ch4_mass_lb': 'float64',\n", + " 'ch4_mass_lb_adjusted': 'float64',\n", + " 'ch4_mass_lb_for_electricity': 'float64',\n", + " 'ch4_mass_lb_for_electricity_adjusted': 'float64',\n", + " 'co2_mass_lb': 'float64',\n", + " 'co2_mass_lb_adjusted': 'float64',\n", + " 'co2_mass_lb_for_electricity': 'float64',\n", + " 'co2_mass_lb_for_electricity_adjusted': 'float64',\n", + " 'co2_mass_measurement_code': 'category',\n", + " 'co2e_mass_lb': 'float64',\n", + " 'co2e_mass_lb_adjusted': 'float64',\n", + " 'co2e_mass_lb_for_electricity': 'float64',\n", + " 'co2e_mass_lb_for_electricity_adjusted': 'float64',\n", + " 'data_availability': 'category',\n", + " 'distribution_flag': 'bool',\n", + " 'eia930_profile': 'float64',\n", + " 'emissions_unit_id_epa': 'str',\n", + " 'energy_source_code': 'str',\n", + " 'equipment_tech_description': 'str',\n", + " 'fgd_electricity_consumption_mwh': 'float64',\n", + " 'fgd_sorbent_consumption_1000_tons': 'float64',\n", + " 'firing_type_1': 'str',\n", + " 'firing_type_2': 'str',\n", + " 'firing_type_3': 'str',\n", + " 'flat_profile': 'float32',\n", + " 'fuel_category': 'str',\n", + " 'fuel_category_eia930': 'str',\n", + " 'fuel_consumed_for_electricity_mmbtu': 'float64',\n", + " 'fuel_consumed_mmbtu': 'float64',\n", + " 'generator_id': 'str',\n", + " 'gross_generation_mwh': 'float64',\n", + " 'gtn_method': 'category',\n", + " 'hourly_data_source': 'category',\n", + " 'hours_in_service': 'float64',\n", + " 'imputed_profile': 'float64',\n", + " 'mercury_control_id_eia': 'str',\n", + " 'mercury_emission_rate_lb_per_trillion_btu': 'float64',\n", + " 'mercury_removal_efficiency': 'float64',\n", + " 'n2o_mass_lb': 'float64',\n", + " 'n2o_mass_lb_adjusted': 'float64',\n", + " 'n2o_mass_lb_for_electricity': 'float64',\n", + " 'n2o_mass_lb_for_electricity_adjusted': 'float64',\n", + " 'net_generation_mwh': 'float64',\n", + " 'nox_control_id_eia': 'str',\n", + " 'nox_mass_lb': 'float64',\n", + " 'nox_mass_lb_adjusted': 'float64',\n", + " 'nox_mass_lb_for_electricity': 'float64',\n", + " 'nox_mass_lb_for_electricity_adjusted': 'float64',\n", + " 'nox_mass_measurement_code': 'category',\n", + " 'operating_time_hours': 'float16',\n", + " 'operational_status': 'str',\n", + " 'ozone_season_nox_emission_rate_lb_per_mmbtu': 'float64',\n", + " 'particulate_control_id_eia': 'str',\n", + " 'particulate_emission_rate_lb_per_mmbtu': 'float64',\n", + " 'particulate_removal_efficiency_annual': 'float64',\n", + " 'particulate_removal_efficiency_at_full_load': 'float64',\n", + " 'plant_id_eia': 'Int32',\n", + " 'plant_id_epa': 'Int32',\n", + " 'plant_primary_fuel': 'str',\n", + " 'prime_mover_code': 'str',\n", + " 'profile': 'float64',\n", + " 'profile_method': 'str',\n", + " 'residual_profile': 'float64',\n", + " 'scaled_residual_profile': 'float64',\n", + " 'shifted_residual_profile': 'float64',\n", + " 'so2_control_id_eia': 'str',\n", + " 'so2_mass_lb': 'float64',\n", + " 'so2_mass_lb_adjusted': 'float64',\n", + " 'so2_mass_lb_for_electricity': 'float64',\n", + " 'so2_mass_lb_for_electricity_adjusted': 'float64',\n", + " 'so2_mass_measurement_code': 'category',\n", + " 'so2_removal_efficiency_annual': 'float64',\n", + " 'so2_removal_efficiency_at_full_load': 'float64',\n", + " 'state': 'str',\n", + " 'steam_load_1000_lb': 'float64',\n", + " 'subplant_id': 'Int16',\n", + " 'subplant_primary_fuel': 'str',\n", + " 'timezone': 'str',\n", + " 'wet_dry_bottom': 'str'}" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dict(sorted(dtypes_to_use.items()))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "boiler_firing_type = load_data.load_pudl_table(\n", + " \"boilers_eia860\",\n", + " year,\n", + " columns=[\n", + " \"plant_id_eia\",\n", + " \"boiler_id\",\n", + " \"firing_type_1\",\n", + " \"wet_dry_bottom\",\n", + " ],\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0 none\n", + "1 d\n", + "2 d\n", + "3 w\n", + "4 w\n", + " ... \n", + "5828 d\n", + "5829 d\n", + "5830 d\n", + "5831 d\n", + "5832 d\n", + "Name: wet_dry_bottom, Length: 5833, dtype: object" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "boiler_firing_type[\"wet_dry_bottom\"].str.lower()" + ] } ], "metadata": { diff --git a/src/column_checks.py b/src/column_checks.py index 3085e9a1..f7bf65e6 100644 --- a/src/column_checks.py +++ b/src/column_checks.py @@ -394,91 +394,93 @@ def check_columns(df, file_name): def get_dtypes(): """Returns a dictionary of dtypes that should be used for each column name.""" dtypes_to_use = { - "plant_id_eia": "Int32", - "plant_id_epa": "Int32", - "subplant_id": "Int16", - "generator_id": "str", - "emissions_unit_id_epa": "str", + "acid_gas_removal_efficiency": "float64", + "annual_nox_emission_rate_lb_per_mmbtu": "float64", + "ba_code": "str", + "ba_code_physical": "str", "boiler_id": "str", - "operating_time_hours": "float16", - "gross_generation_mwh": "float64", - "steam_load_1000_lb": "float64", - "fuel_consumed_mmbtu": "float64", - "co2_mass_lb": "float64", - "co2_mass_measurement_code": "category", - "nox_mass_lb": "float64", - "nox_mass_measurement_code": "category", - "so2_mass_lb": "float64", - "so2_mass_measurement_code": "category", - "energy_source_code": "str", + "capacity_mw": "float64", + "cems_profile": "float64", "ch4_mass_lb": "float64", - "n2o_mass_lb": "float64", - "fuel_consumed_for_electricity_mmbtu": "float64", - "co2_mass_lb_for_electricity": "float64", + "ch4_mass_lb_adjusted": "float64", "ch4_mass_lb_for_electricity": "float64", - "n2o_mass_lb_for_electricity": "float64", - "nox_mass_lb_for_electricity": "float64", - "so2_mass_lb_for_electricity": "float64", + "ch4_mass_lb_for_electricity_adjusted": "float64", + "co2_mass_lb": "float64", "co2_mass_lb_adjusted": "float64", - "ch4_mass_lb_adjusted": "float64", - "n2o_mass_lb_adjusted": "float64", - "nox_mass_lb_adjusted": "float64", - "so2_mass_lb_adjusted": "float64", + "co2_mass_lb_for_electricity": "float64", "co2_mass_lb_for_electricity_adjusted": "float64", - "ch4_mass_lb_for_electricity_adjusted": "float64", - "n2o_mass_lb_for_electricity_adjusted": "float64", - "nox_mass_lb_for_electricity_adjusted": "float64", - "so2_mass_lb_for_electricity_adjusted": "float64", + "co2_mass_measurement_code": "category", "co2e_mass_lb": "float64", - "co2e_mass_lb_for_electricity": "float64", "co2e_mass_lb_adjusted": "float64", + "co2e_mass_lb_for_electricity": "float64", "co2e_mass_lb_for_electricity_adjusted": "float64", - "gtn_method": "category", - "net_generation_mwh": "float64", - "prime_mover_code": "str", - "hourly_data_source": "category", - "nox_control_id_eia": "str", - "fuel_category": "str", - "ba_code": "str", - "ba_code_physical": "str", - "plant_primary_fuel": "str", - "subplant_primary_fuel": "str", - "fuel_category_eia930": "str", - "state": "str", + "data_availability": "category", "distribution_flag": "bool", - "timezone": "str", "eia930_profile": "float64", - "cems_profile": "float64", - "residual_profile": "float64", - "scaled_residual_profile": "float64", - "shifted_residual_profile": "float64", - "imputed_profile": "float64", - "profile": "float64", - "flat_profile": "float32", - "profile_method": "str", - "data_availability": "category", + "emissions_unit_id_epa": "str", + "energy_source_code": "str", + "energy_source_code_1":"str", "equipment_tech_description": "str", - "particulate_control_id_eia": "str", - "so2_control_id_eia": "str", - "nox_control_id_eia": "str", + "fgd_electricity_consumption_mwh": "float64", + "fgd_sorbent_consumption_1000_tons": "float64", + "firing_type_1": "str", + "firing_type_2": "str", + "firing_type_3": "str", + "flat_profile": "float32", + "fuel_category": "str", + "fuel_category_eia930": "str", + "fuel_consumed_for_electricity_mmbtu": "float64", + "fuel_consumed_mmbtu": "float64", + "fuel_mmbtu_per_unit": "float64", + "generator_id": "str", + "gross_generation_mwh": "float64", + "gtn_method": "category", + "hourly_data_source": "category", + "hours_in_service": "float64", + "imputed_profile": "float64", "mercury_control_id_eia": "str", + "mercury_emission_rate_lb_per_trillion_btu": "float64", + "mercury_removal_efficiency": "float64", + "n2o_mass_lb": "float64", + "n2o_mass_lb_adjusted": "float64", + "n2o_mass_lb_for_electricity": "float64", + "n2o_mass_lb_for_electricity_adjusted": "float64", + "net_generation_mwh": "float64", + "nox_control_id_eia": "str", + "nox_mass_lb": "float64", + "nox_mass_lb_adjusted": "float64", + "nox_mass_lb_for_electricity": "float64", + "nox_mass_lb_for_electricity_adjusted": "float64", + "nox_mass_measurement_code": "category", + "operating_time_hours": "float16", "operational_status": "str", - "hours_in_service": "float64", - "annual_nox_emission_rate_lb_per_mmbtu": "float64", "ozone_season_nox_emission_rate_lb_per_mmbtu": "float64", + "particulate_control_id_eia": "str", "particulate_emission_rate_lb_per_mmbtu": "float64", "particulate_removal_efficiency_annual": "float64", "particulate_removal_efficiency_at_full_load": "float64", + "plant_id_eia": "Int32", + "plant_id_epa": "Int32", + "plant_primary_fuel": "str", + "prime_mover_code": "str", + "profile": "float64", + "profile_method": "str", + "residual_profile": "float64", + "scaled_residual_profile": "float64", + "shifted_residual_profile": "float64", + "so2_control_id_eia": "str", + "so2_mass_lb": "float64", + "so2_mass_lb_adjusted": "float64", + "so2_mass_lb_for_electricity": "float64", + "so2_mass_lb_for_electricity_adjusted": "float64", + "so2_mass_measurement_code": "category", "so2_removal_efficiency_annual": "float64", "so2_removal_efficiency_at_full_load": "float64", - "fgd_sorbent_consumption_1000_tons": "float64", - "fgd_electricity_consumption_mwh": "float64", - "mercury_removal_efficiency": "float64", - "mercury_emission_rate_lb_per_trillion_btu": "float64", - "acid_gas_removal_efficiency": "float64", - "firing_type_1": "str", - "firing_type_2": "str", - "firing_type_3": "str", + "state": "str", + "steam_load_1000_lb": "float64", + "subplant_id": "Int16", + "subplant_primary_fuel": "str", + "timezone": "str", "wet_dry_bottom": "str", } diff --git a/src/data_cleaning.py b/src/data_cleaning.py index e9febcca..7f36e76a 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -110,7 +110,7 @@ def generate_subplant_ids(start_year, end_year, cems_ids): # update the subplant_crosswalk to ensure completeness # prepare the subplant crosswalk by adding a complete list of generators and adding the unit_id_pudl column complete_generator_ids = load_data.load_pudl_table( - "generators_eia860", + "boiler_generator_assn_eia860", end_year, columns=["plant_id_eia", "generator_id", "unit_id_pudl"], ).drop_duplicates() diff --git a/src/emissions.py b/src/emissions.py index cce3b614..9d1355b0 100644 --- a/src/emissions.py +++ b/src/emissions.py @@ -601,6 +601,11 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea validate="m:m", ) + gen_nox_factors["wet_dry_bottom"] = gen_nox_factors["wet_dry_bottom"].fillna("none") + gen_nox_factors["boiler_firing_type"] = gen_nox_factors[ + "boiler_firing_type" + ].fillna("none") + # merge in the emission factors for spedcific boiler types gen_nox_factors = gen_nox_factors.merge( nox_emission_factors, @@ -738,12 +743,14 @@ def load_boiler_firing_type(year): boiler_firing_type["firing_type_1"] .map(dict(zip(firing_types_eia["code"], firing_types_eia["label"]))) .fillna("none") + .str.lower() ) boiler_firing_type["wet_dry_bottom"] = ( boiler_firing_type["wet_dry_bottom"] .replace({"D": "dry", "W": "wet"}) .fillna("none") + .str.lower() ) boiler_firing_type = boiler_firing_type[ @@ -1325,6 +1332,10 @@ def calculate_generator_so2_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea validate="m:m", ) + gen_so2_factors["boiler_firing_type"] = gen_so2_factors[ + "boiler_firing_type" + ].fillna("none") + # merge in the emission factors for specific boiler types gen_so2_factors = gen_so2_factors.merge( so2_emission_factors, diff --git a/src/load_data.py b/src/load_data.py index 3e2d7881..a0f50df2 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -10,6 +10,8 @@ from validation import validate_unique_datetimes from logging_util import get_logger +from pudl.metadata.fields import apply_pudl_dtypes + logger = get_logger(__name__) # initialize the pudl_engine @@ -328,6 +330,8 @@ def load_pudl_table( PUDL_ENGINE, ) + table = apply_pudl_dtypes(table) + return table From 8ed58af8c525ce34ddaf8494bba17d768a9840e2 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Tue, 5 Dec 2023 14:31:24 -0800 Subject: [PATCH 21/85] update function name --- src/data_cleaning.py | 4 ++-- src/emissions.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/data_cleaning.py b/src/data_cleaning.py index 7f36e76a..097b3312 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -163,7 +163,7 @@ def generate_subplant_ids(start_year, end_year, cems_ids): ) # add proposed operating dates and retirements to the subplant id crosswalk - subplant_crosswalk_complete = add_operating_and_generator_retirement_dates( + subplant_crosswalk_complete = add_generator_operating_and_retirement_dates( subplant_crosswalk_complete, start_year, end_year ) # add prime mover code to the crosswalk @@ -323,7 +323,7 @@ def connect_ids(df, id_to_update, connecting_id): return df -def add_operating_and_generator_retirement_dates(df, start_year, end_year): +def add_generator_operating_and_retirement_dates(df, start_year, end_year): """Adds columns listing a generator's planned operating date or retirement date to a dataframe.""" generator_status = load_data.load_pudl_table( diff --git a/src/emissions.py b/src/emissions.py index 9d1355b0..01673085 100644 --- a/src/emissions.py +++ b/src/emissions.py @@ -591,6 +591,7 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea boiler_generator_assn, how="left", on=["plant_id_eia", "boiler_id"], + validate="1:m" ) # merge the gen keys with the boiler firing types From 3e5eb16b33a8a8fb8ecb86bc9578909d7ccbf571 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Tue, 5 Dec 2023 15:11:46 -0800 Subject: [PATCH 22/85] fix subplant issue --- notebooks/work_in_progress/sandbox.ipynb | 249 ----------------------- src/data_cleaning.py | 14 +- src/load_data.py | 2 +- 3 files changed, 10 insertions(+), 255 deletions(-) diff --git a/notebooks/work_in_progress/sandbox.ipynb b/notebooks/work_in_progress/sandbox.ipynb index 4814bb6f..d74eb261 100644 --- a/notebooks/work_in_progress/sandbox.ipynb +++ b/notebooks/work_in_progress/sandbox.ipynb @@ -38,255 +38,6 @@ "year = 2021\n", "path_prefix = f\"{year}/\"" ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "dtypes_to_use = {\n", - " \"plant_id_eia\": \"Int32\",\n", - " \"plant_id_epa\": \"Int32\",\n", - " \"subplant_id\": \"Int16\",\n", - " \"generator_id\": \"str\",\n", - " \"emissions_unit_id_epa\": \"str\",\n", - " \"boiler_id\": \"str\",\n", - " \"operating_time_hours\": \"float16\",\n", - " \"gross_generation_mwh\": \"float64\",\n", - " \"steam_load_1000_lb\": \"float64\",\n", - " \"fuel_consumed_mmbtu\": \"float64\",\n", - " \"co2_mass_lb\": \"float64\",\n", - " \"co2_mass_measurement_code\": \"category\",\n", - " \"nox_mass_lb\": \"float64\",\n", - " \"nox_mass_measurement_code\": \"category\",\n", - " \"so2_mass_lb\": \"float64\",\n", - " \"so2_mass_measurement_code\": \"category\",\n", - " \"energy_source_code\": \"str\",\n", - " \"ch4_mass_lb\": \"float64\",\n", - " \"n2o_mass_lb\": \"float64\",\n", - " \"fuel_consumed_for_electricity_mmbtu\": \"float64\",\n", - " \"co2_mass_lb_for_electricity\": \"float64\",\n", - " \"ch4_mass_lb_for_electricity\": \"float64\",\n", - " \"n2o_mass_lb_for_electricity\": \"float64\",\n", - " \"nox_mass_lb_for_electricity\": \"float64\",\n", - " \"so2_mass_lb_for_electricity\": \"float64\",\n", - " \"co2_mass_lb_adjusted\": \"float64\",\n", - " \"ch4_mass_lb_adjusted\": \"float64\",\n", - " \"n2o_mass_lb_adjusted\": \"float64\",\n", - " \"nox_mass_lb_adjusted\": \"float64\",\n", - " \"so2_mass_lb_adjusted\": \"float64\",\n", - " \"co2_mass_lb_for_electricity_adjusted\": \"float64\",\n", - " \"ch4_mass_lb_for_electricity_adjusted\": \"float64\",\n", - " \"n2o_mass_lb_for_electricity_adjusted\": \"float64\",\n", - " \"nox_mass_lb_for_electricity_adjusted\": \"float64\",\n", - " \"so2_mass_lb_for_electricity_adjusted\": \"float64\",\n", - " \"co2e_mass_lb\": \"float64\",\n", - " \"co2e_mass_lb_for_electricity\": \"float64\",\n", - " \"co2e_mass_lb_adjusted\": \"float64\",\n", - " \"co2e_mass_lb_for_electricity_adjusted\": \"float64\",\n", - " \"gtn_method\": \"category\",\n", - " \"net_generation_mwh\": \"float64\",\n", - " \"prime_mover_code\": \"str\",\n", - " \"hourly_data_source\": \"category\",\n", - " \"nox_control_id_eia\": \"str\",\n", - " \"fuel_category\": \"str\",\n", - " \"ba_code\": \"str\",\n", - " \"ba_code_physical\": \"str\",\n", - " \"plant_primary_fuel\": \"str\",\n", - " \"subplant_primary_fuel\": \"str\",\n", - " \"fuel_category_eia930\": \"str\",\n", - " \"state\": \"str\",\n", - " \"distribution_flag\": \"bool\",\n", - " \"timezone\": \"str\",\n", - " \"eia930_profile\": \"float64\",\n", - " \"cems_profile\": \"float64\",\n", - " \"residual_profile\": \"float64\",\n", - " \"scaled_residual_profile\": \"float64\",\n", - " \"shifted_residual_profile\": \"float64\",\n", - " \"imputed_profile\": \"float64\",\n", - " \"profile\": \"float64\",\n", - " \"flat_profile\": \"float32\",\n", - " \"profile_method\": \"str\",\n", - " \"data_availability\": \"category\",\n", - " \"equipment_tech_description\": \"str\",\n", - " \"particulate_control_id_eia\": \"str\",\n", - " \"so2_control_id_eia\": \"str\",\n", - " \"nox_control_id_eia\": \"str\",\n", - " \"mercury_control_id_eia\": \"str\",\n", - " \"operational_status\": \"str\",\n", - " \"hours_in_service\": \"float64\",\n", - " \"annual_nox_emission_rate_lb_per_mmbtu\": \"float64\",\n", - " \"ozone_season_nox_emission_rate_lb_per_mmbtu\": \"float64\",\n", - " \"particulate_emission_rate_lb_per_mmbtu\": \"float64\",\n", - " \"particulate_removal_efficiency_annual\": \"float64\",\n", - " \"particulate_removal_efficiency_at_full_load\": \"float64\",\n", - " \"so2_removal_efficiency_annual\": \"float64\",\n", - " \"so2_removal_efficiency_at_full_load\": \"float64\",\n", - " \"fgd_sorbent_consumption_1000_tons\": \"float64\",\n", - " \"fgd_electricity_consumption_mwh\": \"float64\",\n", - " \"mercury_removal_efficiency\": \"float64\",\n", - " \"mercury_emission_rate_lb_per_trillion_btu\": \"float64\",\n", - " \"acid_gas_removal_efficiency\": \"float64\",\n", - " \"firing_type_1\": \"str\",\n", - " \"firing_type_2\": \"str\",\n", - " \"firing_type_3\": \"str\",\n", - " \"wet_dry_bottom\": \"str\",\n", - " }" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'acid_gas_removal_efficiency': 'float64',\n", - " 'annual_nox_emission_rate_lb_per_mmbtu': 'float64',\n", - " 'ba_code': 'str',\n", - " 'ba_code_physical': 'str',\n", - " 'boiler_id': 'str',\n", - " 'cems_profile': 'float64',\n", - " 'ch4_mass_lb': 'float64',\n", - " 'ch4_mass_lb_adjusted': 'float64',\n", - " 'ch4_mass_lb_for_electricity': 'float64',\n", - " 'ch4_mass_lb_for_electricity_adjusted': 'float64',\n", - " 'co2_mass_lb': 'float64',\n", - " 'co2_mass_lb_adjusted': 'float64',\n", - " 'co2_mass_lb_for_electricity': 'float64',\n", - " 'co2_mass_lb_for_electricity_adjusted': 'float64',\n", - " 'co2_mass_measurement_code': 'category',\n", - " 'co2e_mass_lb': 'float64',\n", - " 'co2e_mass_lb_adjusted': 'float64',\n", - " 'co2e_mass_lb_for_electricity': 'float64',\n", - " 'co2e_mass_lb_for_electricity_adjusted': 'float64',\n", - " 'data_availability': 'category',\n", - " 'distribution_flag': 'bool',\n", - " 'eia930_profile': 'float64',\n", - " 'emissions_unit_id_epa': 'str',\n", - " 'energy_source_code': 'str',\n", - " 'equipment_tech_description': 'str',\n", - " 'fgd_electricity_consumption_mwh': 'float64',\n", - " 'fgd_sorbent_consumption_1000_tons': 'float64',\n", - " 'firing_type_1': 'str',\n", - " 'firing_type_2': 'str',\n", - " 'firing_type_3': 'str',\n", - " 'flat_profile': 'float32',\n", - " 'fuel_category': 'str',\n", - " 'fuel_category_eia930': 'str',\n", - " 'fuel_consumed_for_electricity_mmbtu': 'float64',\n", - " 'fuel_consumed_mmbtu': 'float64',\n", - " 'generator_id': 'str',\n", - " 'gross_generation_mwh': 'float64',\n", - " 'gtn_method': 'category',\n", - " 'hourly_data_source': 'category',\n", - " 'hours_in_service': 'float64',\n", - " 'imputed_profile': 'float64',\n", - " 'mercury_control_id_eia': 'str',\n", - " 'mercury_emission_rate_lb_per_trillion_btu': 'float64',\n", - " 'mercury_removal_efficiency': 'float64',\n", - " 'n2o_mass_lb': 'float64',\n", - " 'n2o_mass_lb_adjusted': 'float64',\n", - " 'n2o_mass_lb_for_electricity': 'float64',\n", - " 'n2o_mass_lb_for_electricity_adjusted': 'float64',\n", - " 'net_generation_mwh': 'float64',\n", - " 'nox_control_id_eia': 'str',\n", - " 'nox_mass_lb': 'float64',\n", - " 'nox_mass_lb_adjusted': 'float64',\n", - " 'nox_mass_lb_for_electricity': 'float64',\n", - " 'nox_mass_lb_for_electricity_adjusted': 'float64',\n", - " 'nox_mass_measurement_code': 'category',\n", - " 'operating_time_hours': 'float16',\n", - " 'operational_status': 'str',\n", - " 'ozone_season_nox_emission_rate_lb_per_mmbtu': 'float64',\n", - " 'particulate_control_id_eia': 'str',\n", - " 'particulate_emission_rate_lb_per_mmbtu': 'float64',\n", - " 'particulate_removal_efficiency_annual': 'float64',\n", - " 'particulate_removal_efficiency_at_full_load': 'float64',\n", - " 'plant_id_eia': 'Int32',\n", - " 'plant_id_epa': 'Int32',\n", - " 'plant_primary_fuel': 'str',\n", - " 'prime_mover_code': 'str',\n", - " 'profile': 'float64',\n", - " 'profile_method': 'str',\n", - " 'residual_profile': 'float64',\n", - " 'scaled_residual_profile': 'float64',\n", - " 'shifted_residual_profile': 'float64',\n", - " 'so2_control_id_eia': 'str',\n", - " 'so2_mass_lb': 'float64',\n", - " 'so2_mass_lb_adjusted': 'float64',\n", - " 'so2_mass_lb_for_electricity': 'float64',\n", - " 'so2_mass_lb_for_electricity_adjusted': 'float64',\n", - " 'so2_mass_measurement_code': 'category',\n", - " 'so2_removal_efficiency_annual': 'float64',\n", - " 'so2_removal_efficiency_at_full_load': 'float64',\n", - " 'state': 'str',\n", - " 'steam_load_1000_lb': 'float64',\n", - " 'subplant_id': 'Int16',\n", - " 'subplant_primary_fuel': 'str',\n", - " 'timezone': 'str',\n", - " 'wet_dry_bottom': 'str'}" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "dict(sorted(dtypes_to_use.items()))" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "boiler_firing_type = load_data.load_pudl_table(\n", - " \"boilers_eia860\",\n", - " year,\n", - " columns=[\n", - " \"plant_id_eia\",\n", - " \"boiler_id\",\n", - " \"firing_type_1\",\n", - " \"wet_dry_bottom\",\n", - " ],\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0 none\n", - "1 d\n", - "2 d\n", - "3 w\n", - "4 w\n", - " ... \n", - "5828 d\n", - "5829 d\n", - "5830 d\n", - "5831 d\n", - "5832 d\n", - "Name: wet_dry_bottom, Length: 5833, dtype: object" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "boiler_firing_type[\"wet_dry_bottom\"].str.lower()" - ] } ], "metadata": { diff --git a/src/data_cleaning.py b/src/data_cleaning.py index 097b3312..085724a5 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -109,11 +109,15 @@ def generate_subplant_ids(start_year, end_year, cems_ids): # update the subplant_crosswalk to ensure completeness # prepare the subplant crosswalk by adding a complete list of generators and adding the unit_id_pudl column - complete_generator_ids = load_data.load_pudl_table( - "boiler_generator_assn_eia860", - end_year, - columns=["plant_id_eia", "generator_id", "unit_id_pudl"], - ).drop_duplicates() + complete_generator_ids = ( + load_data.load_pudl_table( + "plant_parts_eia", + end_year, + columns=["plant_id_eia", "generator_id", "unit_id_pudl"], + ) + .drop_duplicates() + .dropna(subset="generator_id") + ) subplant_crosswalk_complete = crosswalk_with_subplant_ids.merge( complete_generator_ids, how="outer", diff --git a/src/load_data.py b/src/load_data.py index a0f50df2..b0a9bb6d 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -723,7 +723,7 @@ def load_emissions_controls_eia923(year: int): f"eia923/f923_{year}/EIA923_Schedule_8_Annual_Environmental_Information_{year}_Final_Revision.xlsx" ), 2021: downloads_folder( - f"eia923/f923_{year}/EIA923_Schedule_8_Annual_Environmental_Information_{year}_Final.xlsx" + f"eia923/f923_{year}/EIA923_Schedule_8_Annual_Environmental_Information_{year}_Final_Revision.xlsx" ), }[year] From e1559c3517b35588b4bf7125cc91ffad8fecb197 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Tue, 28 Nov 2023 13:40:16 -0800 Subject: [PATCH 23/85] chore: create requirements.txt file --- requirements.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..be4504ab --- /dev/null +++ b/requirements.txt @@ -0,0 +1,21 @@ +cvxopt +cvxpy +osqp +ipykernel +notebook +numpy +openpyxl +pandas +plotly +pyarrow +pytest +ruff +python-snappy +qdldl +requests +seaborn +sqlalchemy +statsmodels +coloredlogs +git+https://github.com/grgmiller/pudl.git@oge_release#egg=catalystcoop.pudl +git+https://github.com/gailin-p/gridemissions#egg=gridemissions From 95081514236850d244819a24dd1c90d72fcf81c1 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Tue, 28 Nov 2023 13:40:58 -0800 Subject: [PATCH 24/85] chore: generate Pipfile and Pipfile.lock files --- Pipfile | 32 + Pipfile.lock | 3569 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 3601 insertions(+) create mode 100644 Pipfile create mode 100644 Pipfile.lock diff --git a/Pipfile b/Pipfile new file mode 100644 index 00000000..aee73054 --- /dev/null +++ b/Pipfile @@ -0,0 +1,32 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +cvxopt = "*" +cvxpy = "*" +osqp = "*" +ipykernel = "*" +notebook = "*" +numpy = "*" +openpyxl = "*" +pandas = "*" +plotly = "*" +pyarrow = "*" +python-snappy = "*" +qdldl = "*" +requests = "*" +seaborn = "*" +sqlalchemy = "*" +statsmodels = "*" +coloredlogs = "*" +"catalystcoop.pudl" = {ref = "oge_release", git = "git+https://github.com/grgmiller/pudl.git"} +gridemissions = {git = "git+https://github.com/gailin-p/gridemissions#egg=gridemissions"} + +[dev-packages] +ruff = "*" +pytest = "*" + +[requires] +python_version = "3.10" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 00000000..b86f85dd --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,3569 @@ +{ + "_meta": { + "hash": { + "sha256": "2f23e9aa264c7984e601aec4ee398a680f642a79085827f0ce0d67ab582a0f29" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.10" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "addfips": { + "hashes": [ + "sha256:63a6f933012c6ecb988d43dad707c92498dca6b50161289ef0df253508c7d8f6", + "sha256:71008c3937add36670d2a7d301213dbee301941662c5ebe673639677eedb7053" + ], + "markers": "python_version >= '3.7'", + "version": "==0.4.0" + }, + "aiohttp": { + "hashes": [ + "sha256:02ab6006ec3c3463b528374c4cdce86434e7b89ad355e7bf29e2f16b46c7dd6f", + "sha256:04fa38875e53eb7e354ece1607b1d2fdee2d175ea4e4d745f6ec9f751fe20c7c", + "sha256:0b0a6a36ed7e164c6df1e18ee47afbd1990ce47cb428739d6c99aaabfaf1b3af", + "sha256:0d406b01a9f5a7e232d1b0d161b40c05275ffbcbd772dc18c1d5a570961a1ca4", + "sha256:0e49b08eafa4f5707ecfb321ab9592717a319e37938e301d462f79b4e860c32a", + "sha256:0e7ba7ff228c0d9a2cd66194e90f2bca6e0abca810b786901a569c0de082f489", + "sha256:11cb254e397a82efb1805d12561e80124928e04e9c4483587ce7390b3866d213", + "sha256:11ff168d752cb41e8492817e10fb4f85828f6a0142b9726a30c27c35a1835f01", + "sha256:176df045597e674fa950bf5ae536be85699e04cea68fa3a616cf75e413737eb5", + "sha256:219a16763dc0294842188ac8a12262b5671817042b35d45e44fd0a697d8c8361", + "sha256:22698f01ff5653fe66d16ffb7658f582a0ac084d7da1323e39fd9eab326a1f26", + "sha256:237533179d9747080bcaad4d02083ce295c0d2eab3e9e8ce103411a4312991a0", + "sha256:289ba9ae8e88d0ba16062ecf02dd730b34186ea3b1e7489046fc338bdc3361c4", + "sha256:2c59e0076ea31c08553e868cec02d22191c086f00b44610f8ab7363a11a5d9d8", + "sha256:2c9376e2b09895c8ca8b95362283365eb5c03bdc8428ade80a864160605715f1", + "sha256:3135713c5562731ee18f58d3ad1bf41e1d8883eb68b363f2ffde5b2ea4b84cc7", + "sha256:3b9c7426923bb7bd66d409da46c41e3fb40f5caf679da624439b9eba92043fa6", + "sha256:3c0266cd6f005e99f3f51e583012de2778e65af6b73860038b968a0a8888487a", + "sha256:41473de252e1797c2d2293804e389a6d6986ef37cbb4a25208de537ae32141dd", + "sha256:4831df72b053b1eed31eb00a2e1aff6896fb4485301d4ccb208cac264b648db4", + "sha256:49f0c1b3c2842556e5de35f122fc0f0b721334ceb6e78c3719693364d4af8499", + "sha256:4b4c452d0190c5a820d3f5c0f3cd8a28ace48c54053e24da9d6041bf81113183", + "sha256:4ee8caa925aebc1e64e98432d78ea8de67b2272252b0a931d2ac3bd876ad5544", + "sha256:500f1c59906cd142d452074f3811614be04819a38ae2b3239a48b82649c08821", + "sha256:5216b6082c624b55cfe79af5d538e499cd5f5b976820eac31951fb4325974501", + "sha256:54311eb54f3a0c45efb9ed0d0a8f43d1bc6060d773f6973efd90037a51cd0a3f", + "sha256:54631fb69a6e44b2ba522f7c22a6fb2667a02fd97d636048478db2fd8c4e98fe", + "sha256:565760d6812b8d78d416c3c7cfdf5362fbe0d0d25b82fed75d0d29e18d7fc30f", + "sha256:598db66eaf2e04aa0c8900a63b0101fdc5e6b8a7ddd805c56d86efb54eb66672", + "sha256:5c4fa235d534b3547184831c624c0b7c1e262cd1de847d95085ec94c16fddcd5", + "sha256:69985d50a2b6f709412d944ffb2e97d0be154ea90600b7a921f95a87d6f108a2", + "sha256:69da0f3ed3496808e8cbc5123a866c41c12c15baaaead96d256477edf168eb57", + "sha256:6c93b7c2e52061f0925c3382d5cb8980e40f91c989563d3d32ca280069fd6a87", + "sha256:70907533db712f7aa791effb38efa96f044ce3d4e850e2d7691abd759f4f0ae0", + "sha256:81b77f868814346662c96ab36b875d7814ebf82340d3284a31681085c051320f", + "sha256:82eefaf1a996060602f3cc1112d93ba8b201dbf5d8fd9611227de2003dddb3b7", + "sha256:85c3e3c9cb1d480e0b9a64c658cd66b3cfb8e721636ab8b0e746e2d79a7a9eed", + "sha256:8a22a34bc594d9d24621091d1b91511001a7eea91d6652ea495ce06e27381f70", + "sha256:8cef8710fb849d97c533f259103f09bac167a008d7131d7b2b0e3a33269185c0", + "sha256:8d44e7bf06b0c0a70a20f9100af9fcfd7f6d9d3913e37754c12d424179b4e48f", + "sha256:8d7f98fde213f74561be1d6d3fa353656197f75d4edfbb3d94c9eb9b0fc47f5d", + "sha256:8d8e4450e7fe24d86e86b23cc209e0023177b6d59502e33807b732d2deb6975f", + "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d", + "sha256:90ec72d231169b4b8d6085be13023ece8fa9b1bb495e4398d847e25218e0f431", + "sha256:91c742ca59045dce7ba76cab6e223e41d2c70d79e82c284a96411f8645e2afff", + "sha256:9b05d33ff8e6b269e30a7957bd3244ffbce2a7a35a81b81c382629b80af1a8bf", + "sha256:9b05d5cbe9dafcdc733262c3a99ccf63d2f7ce02543620d2bd8db4d4f7a22f83", + "sha256:9c5857612c9813796960c00767645cb5da815af16dafb32d70c72a8390bbf690", + "sha256:a34086c5cc285be878622e0a6ab897a986a6e8bf5b67ecb377015f06ed316587", + "sha256:ab221850108a4a063c5b8a70f00dd7a1975e5a1713f87f4ab26a46e5feac5a0e", + "sha256:b796b44111f0cab6bbf66214186e44734b5baab949cb5fb56154142a92989aeb", + "sha256:b8c3a67eb87394386847d188996920f33b01b32155f0a94f36ca0e0c635bf3e3", + "sha256:bcb6532b9814ea7c5a6a3299747c49de30e84472fa72821b07f5a9818bce0f66", + "sha256:bcc0ea8d5b74a41b621ad4a13d96c36079c81628ccc0b30cfb1603e3dfa3a014", + "sha256:bea94403a21eb94c93386d559bce297381609153e418a3ffc7d6bf772f59cc35", + "sha256:bff7e2811814fa2271be95ab6e84c9436d027a0e59665de60edf44e529a42c1f", + "sha256:c72444d17777865734aa1a4d167794c34b63e5883abb90356a0364a28904e6c0", + "sha256:c7b5d5d64e2a14e35a9240b33b89389e0035e6de8dbb7ffa50d10d8b65c57449", + "sha256:c7e939f1ae428a86e4abbb9a7c4732bf4706048818dfd979e5e2839ce0159f23", + "sha256:c88a15f272a0ad3d7773cf3a37cc7b7d077cbfc8e331675cf1346e849d97a4e5", + "sha256:c9110c06eaaac7e1f5562caf481f18ccf8f6fdf4c3323feab28a93d34cc646bd", + "sha256:ca7ca5abfbfe8d39e653870fbe8d7710be7a857f8a8386fc9de1aae2e02ce7e4", + "sha256:cae4c0c2ca800c793cae07ef3d40794625471040a87e1ba392039639ad61ab5b", + "sha256:cdefe289681507187e375a5064c7599f52c40343a8701761c802c1853a504558", + "sha256:cf2a0ac0615842b849f40c4d7f304986a242f1e68286dbf3bd7a835e4f83acfd", + "sha256:cfeadf42840c1e870dc2042a232a8748e75a36b52d78968cda6736de55582766", + "sha256:d737e69d193dac7296365a6dcb73bbbf53bb760ab25a3727716bbd42022e8d7a", + "sha256:d7481f581251bb5558ba9f635db70908819caa221fc79ee52a7f58392778c636", + "sha256:df9cf74b9bc03d586fc53ba470828d7b77ce51b0582d1d0b5b2fb673c0baa32d", + "sha256:e1f80197f8b0b846a8d5cf7b7ec6084493950d0882cc5537fb7b96a69e3c8590", + "sha256:ecca113f19d5e74048c001934045a2b9368d77b0b17691d905af18bd1c21275e", + "sha256:ee2527134f95e106cc1653e9ac78846f3a2ec1004cf20ef4e02038035a74544d", + "sha256:f27fdaadce22f2ef950fc10dcdf8048407c3b42b73779e48a4e76b3c35bca26c", + "sha256:f694dc8a6a3112059258a725a4ebe9acac5fe62f11c77ac4dcf896edfa78ca28", + "sha256:f800164276eec54e0af5c99feb9494c295118fc10a11b997bbb1348ba1a52065", + "sha256:ffcd828e37dc219a72c9012ec44ad2e7e3066bec6ff3aaa19e7d435dbf4032ca" + ], + "markers": "python_version >= '3.8'", + "version": "==3.9.1" + }, + "aiosignal": { + "hashes": [ + "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", + "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.1" + }, + "anyio": { + "hashes": [ + "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f", + "sha256:5a0bec7085176715be77df87fc66d6c9d70626bd752fcc85f57cdbee5b3760da" + ], + "markers": "python_version >= '3.8'", + "version": "==4.1.0" + }, + "appnope": { + "hashes": [ + "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24", + "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e" + ], + "markers": "platform_system == 'Darwin'", + "version": "==0.1.3" + }, + "arelle-release": { + "hashes": [ + "sha256:1ad3655dc73c15b866c027d4c28a23bc6ee23992b6092b43bffd6f783aa0f1ca", + "sha256:cd30cab5835192e5eff8eb5853a9655765da0d89396304f789f45979b265e074" + ], + "markers": "python_version >= '3.7'", + "version": "==2.3.4" + }, + "argon2-cffi": { + "hashes": [ + "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08", + "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1.0" + }, + "argon2-cffi-bindings": { + "hashes": [ + "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670", + "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f", + "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583", + "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194", + "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c", + "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a", + "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082", + "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5", + "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f", + "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7", + "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d", + "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f", + "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae", + "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3", + "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86", + "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367", + "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d", + "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93", + "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb", + "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e", + "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351" + ], + "markers": "python_version >= '3.6'", + "version": "==21.2.0" + }, + "arrow": { + "hashes": [ + "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80", + "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85" + ], + "markers": "python_version >= '3.8'", + "version": "==1.3.0" + }, + "asttokens": { + "hashes": [ + "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", + "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0" + ], + "version": "==2.4.1" + }, + "async-lru": { + "hashes": [ + "sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627", + "sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224" + ], + "markers": "python_version >= '3.8'", + "version": "==2.0.4" + }, + "async-timeout": { + "hashes": [ + "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", + "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028" + ], + "markers": "python_version < '3.11'", + "version": "==4.0.3" + }, + "attrs": { + "hashes": [ + "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04", + "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1.0" + }, + "babel": { + "hashes": [ + "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900", + "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed" + ], + "markers": "python_version >= '3.7'", + "version": "==2.13.1" + }, + "beautifulsoup4": { + "hashes": [ + "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da", + "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a" + ], + "markers": "python_full_version >= '3.6.0'", + "version": "==4.12.2" + }, + "bleach": { + "hashes": [ + "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe", + "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6" + ], + "markers": "python_version >= '3.8'", + "version": "==6.1.0" + }, + "boto3": { + "hashes": [ + "sha256:70626598dd6698d6da8f2854a1ae5010f175572e2a465b2aa86685c745c1013c", + "sha256:fc7c0dd5fa74ae0d57e11747695bdba4ad164e62dee35db15b43762c392fbd92" + ], + "markers": "python_version >= '3.7'", + "version": "==1.33.2" + }, + "botocore": { + "hashes": [ + "sha256:16a30faac6e6f17961c009defb74ab1a3508b8abc58fab98e7cf96af0d91ea84", + "sha256:5c46b7e8450efbf7ddc2a0016eee7225a5564583122e25a20ca92a29a105225c" + ], + "markers": "python_version >= '3.7'", + "version": "==1.33.2" + }, + "cached-property": { + "hashes": [ + "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130", + "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0" + ], + "version": "==1.5.2" + }, + "cachetools": { + "hashes": [ + "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2", + "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1" + ], + "markers": "python_version >= '3.7'", + "version": "==5.3.2" + }, + "catalystcoop.dbfread": { + "hashes": [ + "sha256:e79dc93ec2e5e4dc4f9a8daac2edc5b411026301fc80bd6ceb41b453d9c7ea36", + "sha256:f6502402a619ac580aa35ca9d00160fbd7e6c9bac928acfbf3f7d333835ea5b6" + ], + "markers": "python_version >= '3.6'", + "version": "==3.0.0" + }, + "catalystcoop.ferc-xbrl-extractor": { + "hashes": [ + "sha256:331b3a8a24ad21f7a2598ef511f5e08d3aef03cbb616d33af9ef178ded8adeed", + "sha256:5f347804a6b419933d287c7eff397aec0ff9aa4f11fe549256d6efb8fee73aec" + ], + "markers": "python_version >= '3.10' and python_version < '3.12'", + "version": "==0.8.1" + }, + "catalystcoop.pudl": { + "git": "git+https://github.com/grgmiller/pudl.git", + "markers": "python_version >= '3.10' and python_version < '3.11'", + "ref": "81a7a5137aeeec4d4741b2867f82bbc4f7de75a6" + }, + "certifi": { + "hashes": [ + "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1", + "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474" + ], + "markers": "python_version >= '3.6'", + "version": "==2023.11.17" + }, + "cffi": { + "hashes": [ + "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc", + "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a", + "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417", + "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab", + "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520", + "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36", + "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743", + "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8", + "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed", + "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684", + "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56", + "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324", + "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d", + "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235", + "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e", + "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088", + "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000", + "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7", + "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e", + "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673", + "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c", + "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe", + "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2", + "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098", + "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8", + "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a", + "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0", + "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b", + "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896", + "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e", + "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9", + "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2", + "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b", + "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6", + "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404", + "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f", + "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0", + "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4", + "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc", + "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936", + "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba", + "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872", + "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb", + "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614", + "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1", + "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d", + "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969", + "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b", + "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4", + "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627", + "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", + "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" + ], + "markers": "python_version >= '3.8'", + "version": "==1.16.0" + }, + "chardet": { + "hashes": [ + "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", + "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970" + ], + "markers": "python_version >= '3.7'", + "version": "==5.2.0" + }, + "charset-normalizer": { + "hashes": [ + "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", + "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087", + "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786", + "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", + "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", + "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185", + "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", + "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", + "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519", + "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898", + "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269", + "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", + "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", + "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6", + "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8", + "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a", + "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", + "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", + "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714", + "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2", + "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", + "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", + "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d", + "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", + "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", + "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", + "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", + "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d", + "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a", + "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", + "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", + "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", + "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0", + "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", + "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", + "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac", + "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25", + "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", + "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", + "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", + "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2", + "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", + "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", + "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", + "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99", + "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c", + "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", + "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811", + "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", + "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", + "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", + "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", + "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04", + "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c", + "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", + "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458", + "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", + "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99", + "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985", + "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", + "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238", + "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f", + "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d", + "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796", + "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a", + "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", + "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8", + "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", + "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5", + "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5", + "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711", + "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4", + "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", + "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c", + "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", + "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4", + "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", + "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", + "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", + "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c", + "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", + "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8", + "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", + "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b", + "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", + "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", + "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", + "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33", + "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", + "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==3.3.2" + }, + "clarabel": { + "hashes": [ + "sha256:2e0b1891d8e507eb0bfc7e0b981584c388b2ab28658056e600997dbbc23f1ab4", + "sha256:4f366de79b8bc66bef8dc170987840b672ccab9222e710c09536d78ef47f606d", + "sha256:5a6be4df9fed98b6f73f034836def913a1ecd52e8b79ca230ddf7cd66ebcdee7", + "sha256:73ed408c975a8ea021c3d8262d5d023a18e1ac3f6bb59a37cd69a11dba8f86ed", + "sha256:9946d3b5db346421b6d839d868e7b1151b590f871344fe95113bfd55b5be2433", + "sha256:e737d2818b9ca10e92ccd3fa9ad1a805b039976016415a0c45adef3427d70792", + "sha256:edcebbfc14073cd32bfb664317fd2555716c96be8b2a54efdb2b728453582bea", + "sha256:ef909a393e72981ca10b1d866d9cc7fb6295ece20ae035def764338894961184" + ], + "markers": "python_version >= '3.7'", + "version": "==0.6.0" + }, + "click": { + "hashes": [ + "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.7" + }, + "click-plugins": { + "hashes": [ + "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b", + "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8" + ], + "version": "==1.1.1" + }, + "cligj": { + "hashes": [ + "sha256:a4bc13d623356b373c2c27c53dbd9c68cae5d526270bfa71f6c6fa69669c6b27", + "sha256:c1ca117dbce1fe20a5809dc96f01e1c2840f6dcc939b3ddbb1111bf330ba82df" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' and python_version < '4'", + "version": "==0.7.2" + }, + "cloudpickle": { + "hashes": [ + "sha256:246ee7d0c295602a036e86369c77fecda4ab17b506496730f2f576d9016fd9c7", + "sha256:996d9a482c6fb4f33c1a35335cf8afd065d2a56e973270364840712d9131a882" + ], + "markers": "python_version >= '3.8'", + "version": "==3.0.0" + }, + "colorama": { + "hashes": [ + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" + ], + "version": "==0.4.6" + }, + "coloredlogs": { + "hashes": [ + "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", + "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0" + ], + "index": "pypi", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==15.0.1" + }, + "comm": { + "hashes": [ + "sha256:2da8d9ebb8dd7bfc247adaff99f24dce705638a8042b85cb995066793e391001", + "sha256:a517ea2ca28931c7007a7a99c562a0fa5883cfb48963140cf642c41c948498be" + ], + "markers": "python_version >= '3.8'", + "version": "==0.2.0" + }, + "contourpy": { + "hashes": [ + "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8", + "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956", + "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5", + "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063", + "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286", + "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a", + "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686", + "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9", + "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f", + "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4", + "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e", + "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0", + "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e", + "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488", + "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399", + "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431", + "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779", + "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9", + "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab", + "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0", + "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd", + "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e", + "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc", + "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6", + "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316", + "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808", + "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0", + "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f", + "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843", + "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9", + "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95", + "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9", + "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de", + "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4", + "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4", + "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa", + "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8", + "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776", + "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41", + "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108", + "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e", + "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8", + "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727", + "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a" + ], + "markers": "python_version >= '3.9'", + "version": "==1.2.0" + }, + "cvxopt": { + "hashes": [ + "sha256:098abd1d648d9e44f7ad55542b3b7f978b82280f4332ad80a937db6fbe274600", + "sha256:0c45f663e40b3ed2e2320e7ae8d50fcf09b5ac72c5af4c66aa523e0045453311", + "sha256:22d12b88190e047c0cedde165711222aa0dcdc325a229b876c36f746dd4a6f12", + "sha256:3461fa42c1b2240ba4da1d985ca73503914157fc4c77417327ed6d7d85acdbe6", + "sha256:45e702d4649d2d4e73fcd8f244aa5734a04d2b1a3fa3e7c0bff1ab578bf5061e", + "sha256:6874e1b9aa002f9d796da9d02bdca76b15aa3d4b2f83ca5064ac4c7894b92ece", + "sha256:6e14c47766b39e97142b163ba218b955cd5c47d19d9bd01b01e0909102b43384", + "sha256:8157ef551c80b4745b786d0d8ae5cc222824482fb8596ce271bf49b707d38577", + "sha256:8ae730ebc130461f743922f11d00c2d59a79492e57a1f5d245d4a6c731b7e334", + "sha256:994dab68c193bea405a3a89a88b8703dd2c79bb790a330c8d459f0454cca71ef", + "sha256:a075e333916da7fc941b36a4f189b88acd291f1d861d97ba876626c277b3e575", + "sha256:a459b6ee9f99fc34861cbcf679a196af2d930ec70d95018a94f2e6dbe46c8c24", + "sha256:c237b57845b1e4ac00c012581cde099cd71a91434c117fec763bb4bf5b22601b", + "sha256:cd4a1bba537a34808b92f1e793e3499029d339a7a2ab6d989f82e395b7b740ff", + "sha256:dcc0c091977b9211ad5086d0dfcc8748a4be3a37b0456c93d11a5d8fe15219e8", + "sha256:e2ec16afa3e953159e148b7470159e415108aadb8bb1815baaea2e37ad7e1d8c", + "sha256:e3cd2db913b1cf64d84cdb7bc467a8a15adbd1f0f83a7a45a7167ad590f79408", + "sha256:f4ae2bc20a7d44657cc3ab1e2b80fa07ff3ebe0c1e0fa1f0b27b2ba693eb5072", + "sha256:f88dd546d91eb9e0974eee477b76077d001eeeb7b819d8801eb6065376d7d527" + ], + "index": "pypi", + "markers": "python_version >= '3' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.3.2" + }, + "cvxpy": { + "hashes": [ + "sha256:03588055b660c043848f5281fe24dbd21f005b34bd8bd3b56906d8ad457c14ae", + "sha256:0f1482558b785f2db51c76b9c6e91cc85dbd146675b126a799e7d7aab5b15354", + "sha256:163caffd7f7f27b6cb151f4ccff283068e063c3673158793048761690cbe4bbe", + "sha256:2f84687d15d11f9b49ca902f20103a2076efd47773c399cace71237ef53cdadc", + "sha256:315609ff96adeda4970471b349bc19d44ff4043e15630cf5ac70c029658fe8fc", + "sha256:372c0825cc6e6bb03ecc550d83718761a1bbdbbb48010fec6f9718581ebd45b5", + "sha256:41cfaecf86f85162ca53c7be7377b4143e316204fb9b6a7df8b7a08c826e3806", + "sha256:55e08ffb973d62b3fabc675ad464cb6013ea5ce69799f330b33a084a2e580d8d", + "sha256:57593a852c563ce77bdb075a3e75f23d36d4b3162ebf3199b54cc7fe75088ef2", + "sha256:5a3ec054279880a9ebf5fd9d2ac4109acf944b8c45ea8b24e461680e34f3d7b5", + "sha256:6b0f17dca85b2a410e73f5d84b28f35f57a20cfec1b0adc9b16f0f8aabff9961", + "sha256:71a95aaccf22431fd25a63bcb12d583e1b0baeaeb4fafa3e25857cec03b9e2f3", + "sha256:7a46ef722c8d1590875e86360d5781703dfcbd08be73eb98a2fc91a280870064", + "sha256:7a9ef34e3c57ff8c844d86f0a3834fb5575af19233947639de0ba577c6122e3e", + "sha256:9318c4e679b3db470e76e7f23cce362b038bd2d68c4a7326a7c21577ddbdc542", + "sha256:9d3bae3bf31e4eb6ed6407f78c6bc3c7bc4b4145cdbbb9ba8c61c3fc541d7067", + "sha256:d220a7ee55907da9b55b98e5238d03735118d03b82855ba87b872cb2e6977367", + "sha256:d6bfbd535fdaabc5fa55f28de7a1d40f3a803a27fe3fec86e90700fa159a3afc", + "sha256:db89b55025514bad821b1f1781bed373cbb6aa22fe84420431efd510dbe7f858", + "sha256:edf66010e49b64d3f2dd1a7abde8fa3e615ce7a2b3eb185ab744b0beb3a6adb9", + "sha256:f24067c54979b09910aea0a03256247121d8a8169538facf087c1923e9e2701a" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==1.4.1" + }, + "cycler": { + "hashes": [ + "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", + "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.1" + }, + "dask": { + "hashes": [ + "sha256:397b07a0de718f7c87d12ceb1700048aa085a14059847a33ecbdc57132c01eed", + "sha256:ea313767b3d11e0610fbe7c57f7a01b1f8990bb6c699456ba910d9b31da2c9c0" + ], + "markers": "python_version >= '3.8'", + "version": "==2023.1.0" + }, + "datapackage": { + "hashes": [ + "sha256:1e91a18c866914dea0acfe2aec785e6ec583c33766b0682c740b30bb7de88c58", + "sha256:5d429d566482ddb5e2424a4f6ac80782340fd2eb707595d601511d077d6caaba" + ], + "version": "==1.15.2" + }, + "debugpy": { + "hashes": [ + "sha256:125b9a637e013f9faac0a3d6a82bd17c8b5d2c875fb6b7e2772c5aba6d082332", + "sha256:12af2c55b419521e33d5fb21bd022df0b5eb267c3e178f1d374a63a2a6bdccd0", + "sha256:3c6fb41c98ec51dd010d7ed650accfd07a87fe5e93eca9d5f584d0578f28f35f", + "sha256:46ab6780159eeabb43c1495d9c84cf85d62975e48b6ec21ee10c95767c0590aa", + "sha256:57161629133113c97b387382045649a2b985a348f0c9366e22217c87b68b73c6", + "sha256:5d9de202f5d42e62f932507ee8b21e30d49aae7e46d5b1dd5c908db1d7068637", + "sha256:60009b132c91951354f54363f8ebdf7457aeb150e84abba5ae251b8e9f29a8a6", + "sha256:61eab4a4c8b6125d41a34bad4e5fe3d2cc145caecd63c3fe953be4cc53e65bf8", + "sha256:7fb95ca78f7ac43393cd0e0f2b6deda438ec7c5e47fa5d38553340897d2fbdfb", + "sha256:8cd0197141eb9e8a4566794550cfdcdb8b3db0818bdf8c49a8e8f8053e56e38b", + "sha256:9c9b0ac1ce2a42888199df1a1906e45e6f3c9555497643a85e0bf2406e3ffbc4", + "sha256:a64093656c4c64dc6a438e11d59369875d200bd5abb8f9b26c1f5f723622e153", + "sha256:a8b7a2fd27cd9f3553ac112f356ad4ca93338feadd8910277aff71ab24d8775f", + "sha256:b05a6b503ed520ad58c8dc682749113d2fd9f41ffd45daec16e558ca884008cd", + "sha256:bdc5ef99d14b9c0fcb35351b4fbfc06ac0ee576aeab6b2511702e5a648a2e595", + "sha256:e3412f9faa9ade82aa64a50b602544efcba848c91384e9f93497a458767e6926", + "sha256:ef54404365fae8d45cf450d0544ee40cefbcb9cb85ea7afe89a963c27028261e", + "sha256:ef9ab7df0b9a42ed9c878afd3eaaff471fce3fa73df96022e1f5c9f8f8c87ada" + ], + "markers": "python_version >= '3.8'", + "version": "==1.8.0" + }, + "decorator": { + "hashes": [ + "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", + "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" + ], + "markers": "python_version >= '3.5'", + "version": "==5.1.1" + }, + "defusedxml": { + "hashes": [ + "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", + "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.7.1" + }, + "dnspython": { + "hashes": [ + "sha256:57c6fbaaeaaf39c891292012060beb141791735dbb4004798328fc2c467402d8", + "sha256:8dcfae8c7460a2f84b4072e26f1c9f4101ca20c071649cb7c34e8b6a93d58984" + ], + "markers": "python_version >= '3.8' and python_version < '4.0'", + "version": "==2.4.2" + }, + "ecos": { + "hashes": [ + "sha256:29d00164eaea66ed54697a3b361c575284a8bca54f2623381a0635806c7303a7", + "sha256:3e42bd4c19af6e04f76ccc85d941b1f1adc7faeee4d06d482395a6beb7bec895", + "sha256:4979dc2d1cb6667e371a45a61887068505c1305437eef104ed6ef16f4b6aa0e3", + "sha256:4e86671397d1d2cd7cccff8a9c45be0541b0c60af8b92a0ff3581c9ed869db67", + "sha256:5184a9d8521ad1af90ffcd9902a6fa75c7bc473f37d30d86f97beda1033dfca2", + "sha256:528b02f53835bd1baeb2e23f8153b8d6cc2b3704e1768be6a1a972f542241670", + "sha256:608bc822ee8e070927ab3519169b13a1a0fe88f3d562212d6b5dbb1039776360", + "sha256:617be25d74222849622b0f82b94a11abcf1fae78ccaf69977b328321ee6ffa0b", + "sha256:6def54336a15b5a49bc3bfcaa36035e8557cae8a4853b17ca84f5a29c93bcaea", + "sha256:7af08941552fce108bd80145cdb6be7fa74477a20bacdac170800442cc7027d4", + "sha256:835298a299c88c207b3402fba60ad9b5688b59bbbf2ac34a46de5b37165d773a", + "sha256:858a4dd3177bdc8cc6e362031732f5177b62138a1e4ef91c0dc3c6bd7d2d1248", + "sha256:da8fbbca3feb83a9e27075d29b3765417d0c80af8ea83cbdc4a558cae7b564af", + "sha256:eba07599084724eedc20b2862d5580eebebb09609f4740baadc78401cb99827c", + "sha256:f48816d73b87ae325556ea537b7c8743187311403c80e3832035224156337c4e", + "sha256:f70e4547966f530fd7715756f7a65d5b9b90b312b9d37f243ef9356c05e7d74c" + ], + "version": "==2.0.12" + }, + "email-validator": { + "hashes": [ + "sha256:a4b0bd1cf55f073b924258d19321b1f3aa74b4b5a71a42c305575dba920e1a44", + "sha256:c973053efbeddfef924dc0bd93f6e77a1ea7ee0fce935aea7103c7a3d6d2d637" + ], + "version": "==2.1.0.post1" + }, + "et-xmlfile": { + "hashes": [ + "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c", + "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada" + ], + "markers": "python_version >= '3.6'", + "version": "==1.1.0" + }, + "exceptiongroup": { + "hashes": [ + "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14", + "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68" + ], + "markers": "python_version < '3.11'", + "version": "==1.2.0" + }, + "executing": { + "hashes": [ + "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147", + "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc" + ], + "markers": "python_version >= '3.5'", + "version": "==2.0.1" + }, + "fastjsonschema": { + "hashes": [ + "sha256:b9fd1a2dd6971dbc7fee280a95bd199ae0dd9ce22beb91cc75e9c1c528a5170e", + "sha256:e25df6647e1bc4a26070b700897b07b542ec898dd4f1f6ea013e7f6a88417225" + ], + "version": "==2.19.0" + }, + "fiona": { + "hashes": [ + "sha256:35dae4b0308eb44617cdc4461ceb91f891d944fdebbcba5479efe524ec5db8de", + "sha256:374efe749143ecb5cfdd79b585d83917d2bf8ecfbfc6953c819586b336ce9c63", + "sha256:3ea04ec2d8c57b5f81a31200fb352cb3242aa106fc3e328963f30ffbdf0ff7c8", + "sha256:4877cc745d9e82b12b3eafce3719db75759c27bd8a695521202135b36b58c2e7", + "sha256:4df21906235928faad856c288cfea0298e9647f09c9a69a230535cbc8eadfa21", + "sha256:5b4c6a3df53bee8f85bb46685562b21b43346be1fe96419f18f70fa1ab8c561c", + "sha256:5f40a40529ecfca5294260316cf987a0420c77a2f0cf0849f529d1afbccd093e", + "sha256:6ad04c1877b9fd742871b11965606c6a52f40706f56a48d66a87cc3073943828", + "sha256:6d9f29e9bcbb33232ff7fa98b4a3c2234db910c1dc6c4147fc36c0b8b930f2e0", + "sha256:7ede8ddc798f3d447536080c6db9a5fb73733ad8bdb190cb65eed4e289dd4c50", + "sha256:81d502369493687746cb8d3cd77e5ada4447fb71d513721c9a1826e4fb32b23a", + "sha256:8b098054a27c12afac4f819f98cb4d4bf2db9853f70b0c588d7d97d26e128c39", + "sha256:8b53ce8de773fcd5e2e102e833c8c58479edd8796a522f3d83ef9e08b62bfeea", + "sha256:99e2604332caa7692855c2ae6ed91e1fffdf9b59449aa8032dd18e070e59a2f7", + "sha256:9a2da52f865db1aff0eaf41cdd4c87a7c079b3996514e8e7a1ca38457309e825", + "sha256:9fb9a24a8046c724787719e20557141b33049466145fc3e665764ac7caf5748c", + "sha256:ac2c250f509ec19fad7959d75b531984776517ef3c1222d1cc5b4f962825880b", + "sha256:bd2355e859a1cd24a3e485c6dc5003129f27a2051629def70036535ffa7e16a4", + "sha256:c521e1135c78dec0d7774303e5a1b4c62e0efb0e602bb8f167550ef95e0a2691", + "sha256:ce3b29230ef70947ead4e701f3f82be81082b7f37fd4899009b1445cc8fc276a", + "sha256:cfef6db5b779d463298b1113b50daa6c5b55f26f834dc9e37752116fa17277c1", + "sha256:d722d7f01a66f4ab6cd08d156df3fdb92f0669cf5f8708ddcb209352f416f241", + "sha256:f1af08da4ecea5036cb81c9131946be4404245d1b434b5b24fd3871a1d4030d9", + "sha256:fce4b1dd98810cabccdaa1828430c7402d283295c2ae31bea4f34188ea9e88d7" + ], + "markers": "python_version >= '3.7'", + "version": "==1.9.5" + }, + "fonttools": { + "hashes": [ + "sha256:03ed3bda541e86725f6b4e1b94213f13ed1ae51a5a1f167028534cedea38c010", + "sha256:0dc7617d96b1e668eea9250e1c1fe62d0c78c3f69573ce7e3332cc40e6d84356", + "sha256:105099968b58a5b4cef6f3eb409db8ea8578b302a9d05e23fecba1b8b0177b5f", + "sha256:1b9e9ad2bcded9a1431afaa57c8d3c39143ac1f050862d66bddd863c515464a2", + "sha256:1f53a19dcdd5737440839b8394eeebb35da9ec8109f7926cb6456639b5b58e47", + "sha256:21e96b99878348c74aa58059b8578d7586f9519cbcdadacf56486737038aa043", + "sha256:2c980d60cd6ec1376206fe55013d166e5627ad0b149b5c81e74eaa913ab6134f", + "sha256:316cec50581e844c3ab69d7c82455b54c7cf18236b2f09e722faf665fbfcac58", + "sha256:37cd1ced6efb3dd6fe82e9f9bf92fd74ac58a5aefc284045f59ecd517a5fb9ab", + "sha256:392d0e3cc23daee910193625f7cf1b387aff9dd5b6f1a5f4a925680acb6dcbc2", + "sha256:3bdd7dfca8f6c9f4779384064027e8477ad6a037d6a327b09381f43e0247c6f3", + "sha256:43a3d267334109ff849c37cf3629476b5feb392ef1d2e464a167b83de8cd599c", + "sha256:45fa321c458ea29224067700954ec44493ae869b47e7c5485a350a149a19fb53", + "sha256:46eabddec12066829b8a1efe45ae552ba2f1796981ecf538d5f68284c354c589", + "sha256:4b9544b1346d99848ac0e9b05b5d45ee703d7562fc4c9c48cf4b781de9632e57", + "sha256:4ba17822a6681d06849078daaf6e03eccc9f467efe7c4c60280e28a78e8e5df9", + "sha256:5a17706b9cc24b27721613fe5773d93331ab7f0ecaca9955aead89c6b843d3a7", + "sha256:5cbf02cda8465b69769d07385f5d11e7bba19954e7787792f46fe679ec755ebb", + "sha256:6e441286d55fe7ec7c4fb36812bf914924813776ff514b744b510680fc2733f2", + "sha256:6eb2c54f7a07c92108daabcf02caf31df97825738db02a28270633946bcda4d0", + "sha256:777ba42b94a27bb7fb2b4082522fccfd345667c32a56011e1c3e105979af5b79", + "sha256:794de93e83297db7b4943f2431e206d8b1ea69cb3ae14638a49cc50332bf0db8", + "sha256:800e354e0c3afaeb8d9552769773d02f228e98c37b8cb03041157c3d0687cffc", + "sha256:847f3f49dd3423e5a678c098e2ba92c7f4955d4aab3044f6a507b0bb0ecb07e0", + "sha256:8717db3e4895e4820ade64ea379187738827ee60748223cb0438ef044ee208c6", + "sha256:8b07b857d4f9de3199a8c3d1b1bf2078c0f37447891ca1a8d9234106b9a27aff", + "sha256:8e1aefc2bf3c43e0f33f995f828a7bbeff4adc9393a7760b11456dbcf14388f6", + "sha256:a12dee6523c02ca78aeedd0a5e12bfa9b7b29896350edd5241542897b072ae23", + "sha256:a3c11d9687479f01eddef729aa737abcdea0a44fdaffb62a930a18892f186c9b", + "sha256:b6de2f0fcd3302fb82f94801002cb473959e998c14c24ec28234adb674aed345", + "sha256:ba299f1fbaa2a1e33210aaaf6fa816d4059e4d3cfe2ae9871368d4ab548c1c6a", + "sha256:ba6c23591427844dfb0a13658f1718489de75de6a46b64234584c0d17573162d", + "sha256:c4f4a5870e3b56788fb196da8cf30d0dfd51a76dc3b907861d018165f76ae4c2", + "sha256:cb472905da3049960e80fc1cf808231880d79727a8410e156bf3e5063a1c574f", + "sha256:cebcddbe9351b67166292b4f71ffdbfcce01ba4b07d4267824eb46b277aeb19a", + "sha256:e2277cba9f0b525e30de2a9ad3cb4219aa4bc697230c1645666b0deee9f914f0", + "sha256:e29d5f298d616a93a4c5963682dc6cc8cc09f6d89cad2c29019fc5fb3b4d9472", + "sha256:e3d24248221bd7151dfff0d88b1b5da02dccd7134bd576ce8888199827bbaa19", + "sha256:e50f794d09df0675da8d9dbd7c66bfcab2f74a708343aabcad41936d26556891", + "sha256:f22eb69996a0bd49f76bdefb30be54ce8dbb89a0d1246874d610f05c2aa2e69e", + "sha256:fb36e5f40191274a95938b40c0a1fa7f895e36935aea8709e1d6deff0b2d0d4f", + "sha256:ff6a698bdd435d24c379f6e8a54908cd9bb7dda23719084d56bf8c87709bf3bd" + ], + "markers": "python_version >= '3.8'", + "version": "==4.45.1" + }, + "fqdn": { + "hashes": [ + "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", + "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014" + ], + "version": "==1.5.1" + }, + "frictionless": { + "hashes": [ + "sha256:5b2bbb3779d5e2ecfe99add2458a7b2bcb61eae6173696ea57ef0b28c085d976", + "sha256:e7d83d82cd3273820c74ac715e8d78285697f1eceda49a2417a72f839420d42e" + ], + "version": "==4.40.11" + }, + "frozenlist": { + "hashes": [ + "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6", + "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01", + "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251", + "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9", + "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b", + "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87", + "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf", + "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f", + "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0", + "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2", + "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b", + "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc", + "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c", + "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467", + "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9", + "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1", + "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a", + "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79", + "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167", + "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300", + "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf", + "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea", + "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2", + "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab", + "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3", + "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb", + "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087", + "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc", + "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8", + "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62", + "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f", + "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326", + "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c", + "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431", + "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963", + "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7", + "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef", + "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3", + "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956", + "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781", + "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472", + "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc", + "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839", + "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672", + "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3", + "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503", + "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d", + "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8", + "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b", + "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc", + "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f", + "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559", + "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b", + "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95", + "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb", + "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963", + "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919", + "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f", + "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3", + "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1", + "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e" + ], + "markers": "python_version >= '3.8'", + "version": "==1.4.0" + }, + "fsspec": { + "hashes": [ + "sha256:b833e2e541e9e8cde0ab549414187871243177feb3d344f9d27b25a93f5d8139", + "sha256:fbae7f20ff801eb5f7d0bedf81f25c787c0dfac5e982d98fa3884a9cde2b5411" + ], + "markers": "python_version >= '3.7'", + "version": "==2023.1.0" + }, + "gcsfs": { + "hashes": [ + "sha256:0a7b7ca8c1affa126a14ba35d7b7dff81c49e2aaceedda9732c7f159a4837a26", + "sha256:62c491b9e2a8e9e58b8a899eec2ce111f827718a65539019ff3cadf447e48f41" + ], + "markers": "python_version >= '3.7'", + "version": "==2023.1.0" + }, + "geopandas": { + "hashes": [ + "sha256:0a470e4bf6f5367e6fd83ab6b40405e0b805c8174665bbcb7c4077ed90202912", + "sha256:0acdacddefa176525e4da6d9aeeece225da26055c4becdc6e97cf40fa97c27f4" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.2" + }, + "google-api-core": { + "hashes": [ + "sha256:5368a4502b793d9bbf812a5912e13e4e69f9bd87f6efb508460c43f5bbd1ce41", + "sha256:de2fb50ed34d47ddbb2bd2dcf680ee8fead46279f4ed6b16de362aca23a18952" + ], + "markers": "python_version >= '3.7'", + "version": "==2.14.0" + }, + "google-auth": { + "hashes": [ + "sha256:79905d6b1652187def79d491d6e23d0cbb3a21d3c7ba0dbaa9c8a01906b13ff3", + "sha256:d4bbc92fe4b8bfd2f3e8d88e5ba7085935da208ee38a134fc280e7ce682a05f2" + ], + "markers": "python_version >= '3.7'", + "version": "==2.23.4" + }, + "google-auth-oauthlib": { + "hashes": [ + "sha256:089c6e587d36f4803ac7e0720c045c6a8b1fd1790088b8424975b90d0ee61c12", + "sha256:83ea8c3b0881e453790baff4448e8a6112ac8778d1de9da0b68010b843937afb" + ], + "markers": "python_version >= '3.6'", + "version": "==1.1.0" + }, + "google-cloud-core": { + "hashes": [ + "sha256:37b80273c8d7eee1ae816b3a20ae43585ea50506cb0e60f3cf5be5f87f1373cb", + "sha256:fbd11cad3e98a7e5b0343dc07cb1039a5ffd7a5bb96e1f1e27cee4bda4a90863" + ], + "markers": "python_version >= '3.7'", + "version": "==2.3.3" + }, + "google-cloud-storage": { + "hashes": [ + "sha256:ab0bf2e1780a1b74cf17fccb13788070b729f50c252f0c94ada2aae0ca95437d", + "sha256:f62dc4c7b6cd4360d072e3deb28035fbdad491ac3d9b0b1815a12daea10f37c7" + ], + "markers": "python_version >= '3.7'", + "version": "==2.13.0" + }, + "google-crc32c": { + "hashes": [ + "sha256:024894d9d3cfbc5943f8f230e23950cd4906b2fe004c72e29b209420a1e6b05a", + "sha256:02c65b9817512edc6a4ae7c7e987fea799d2e0ee40c53ec573a692bee24de876", + "sha256:02ebb8bf46c13e36998aeaad1de9b48f4caf545e91d14041270d9dca767b780c", + "sha256:07eb3c611ce363c51a933bf6bd7f8e3878a51d124acfc89452a75120bc436289", + "sha256:1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298", + "sha256:116a7c3c616dd14a3de8c64a965828b197e5f2d121fedd2f8c5585c547e87b02", + "sha256:19e0a019d2c4dcc5e598cd4a4bc7b008546b0358bd322537c74ad47a5386884f", + "sha256:1c7abdac90433b09bad6c43a43af253e688c9cfc1c86d332aed13f9a7c7f65e2", + "sha256:1e986b206dae4476f41bcec1faa057851f3889503a70e1bdb2378d406223994a", + "sha256:272d3892a1e1a2dbc39cc5cde96834c236d5327e2122d3aaa19f6614531bb6eb", + "sha256:278d2ed7c16cfc075c91378c4f47924c0625f5fc84b2d50d921b18b7975bd210", + "sha256:2ad40e31093a4af319dadf503b2467ccdc8f67c72e4bcba97f8c10cb078207b5", + "sha256:2e920d506ec85eb4ba50cd4228c2bec05642894d4c73c59b3a2fe20346bd00ee", + "sha256:3359fc442a743e870f4588fcf5dcbc1bf929df1fad8fb9905cd94e5edb02e84c", + "sha256:37933ec6e693e51a5b07505bd05de57eee12f3e8c32b07da7e73669398e6630a", + "sha256:398af5e3ba9cf768787eef45c803ff9614cc3e22a5b2f7d7ae116df8b11e3314", + "sha256:3b747a674c20a67343cb61d43fdd9207ce5da6a99f629c6e2541aa0e89215bcd", + "sha256:461665ff58895f508e2866824a47bdee72497b091c730071f2b7575d5762ab65", + "sha256:4c6fdd4fccbec90cc8a01fc00773fcd5fa28db683c116ee3cb35cd5da9ef6c37", + "sha256:5829b792bf5822fd0a6f6eb34c5f81dd074f01d570ed7f36aa101d6fc7a0a6e4", + "sha256:596d1f98fc70232fcb6590c439f43b350cb762fb5d61ce7b0e9db4539654cc13", + "sha256:5ae44e10a8e3407dbe138984f21e536583f2bba1be9491239f942c2464ac0894", + "sha256:635f5d4dd18758a1fbd1049a8e8d2fee4ffed124462d837d1a02a0e009c3ab31", + "sha256:64e52e2b3970bd891309c113b54cf0e4384762c934d5ae56e283f9a0afcd953e", + "sha256:66741ef4ee08ea0b2cc3c86916ab66b6aef03768525627fd6a1b34968b4e3709", + "sha256:67b741654b851abafb7bc625b6d1cdd520a379074e64b6a128e3b688c3c04740", + "sha256:6ac08d24c1f16bd2bf5eca8eaf8304812f44af5cfe5062006ec676e7e1d50afc", + "sha256:6f998db4e71b645350b9ac28a2167e6632c239963ca9da411523bb439c5c514d", + "sha256:72218785ce41b9cfd2fc1d6a017dc1ff7acfc4c17d01053265c41a2c0cc39b8c", + "sha256:74dea7751d98034887dbd821b7aae3e1d36eda111d6ca36c206c44478035709c", + "sha256:759ce4851a4bb15ecabae28f4d2e18983c244eddd767f560165563bf9aefbc8d", + "sha256:77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906", + "sha256:7c074fece789b5034b9b1404a1f8208fc2d4c6ce9decdd16e8220c5a793e6f61", + "sha256:7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57", + "sha256:7f57f14606cd1dd0f0de396e1e53824c371e9544a822648cd76c034d209b559c", + "sha256:83c681c526a3439b5cf94f7420471705bbf96262f49a6fe546a6db5f687a3d4a", + "sha256:8485b340a6a9e76c62a7dce3c98e5f102c9219f4cfbf896a00cf48caf078d438", + "sha256:84e6e8cd997930fc66d5bb4fde61e2b62ba19d62b7abd7a69920406f9ecca946", + "sha256:89284716bc6a5a415d4eaa11b1726d2d60a0cd12aadf5439828353662ede9dd7", + "sha256:8b87e1a59c38f275c0e3676fc2ab6d59eccecfd460be267ac360cc31f7bcde96", + "sha256:8f24ed114432de109aa9fd317278518a5af2d31ac2ea6b952b2f7782b43da091", + "sha256:98cb4d057f285bd80d8778ebc4fde6b4d509ac3f331758fb1528b733215443ae", + "sha256:998679bf62b7fb599d2878aa3ed06b9ce688b8974893e7223c60db155f26bd8d", + "sha256:9ba053c5f50430a3fcfd36f75aff9caeba0440b2d076afdb79a318d6ca245f88", + "sha256:9c99616c853bb585301df6de07ca2cadad344fd1ada6d62bb30aec05219c45d2", + "sha256:a1fd716e7a01f8e717490fbe2e431d2905ab8aa598b9b12f8d10abebb36b04dd", + "sha256:a2355cba1f4ad8b6988a4ca3feed5bff33f6af2d7f134852cf279c2aebfde541", + "sha256:b1f8133c9a275df5613a451e73f36c2aea4fe13c5c8997e22cf355ebd7bd0728", + "sha256:b8667b48e7a7ef66afba2c81e1094ef526388d35b873966d8a9a447974ed9178", + "sha256:ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968", + "sha256:be82c3c8cfb15b30f36768797a640e800513793d6ae1724aaaafe5bf86f8f346", + "sha256:c02ec1c5856179f171e032a31d6f8bf84e5a75c45c33b2e20a3de353b266ebd8", + "sha256:c672d99a345849301784604bfeaeba4db0c7aae50b95be04dd651fd2a7310b93", + "sha256:c6c777a480337ac14f38564ac88ae82d4cd238bf293f0a22295b66eb89ffced7", + "sha256:cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273", + "sha256:cd67cf24a553339d5062eff51013780a00d6f97a39ca062781d06b3a73b15462", + "sha256:d3515f198eaa2f0ed49f8819d5732d70698c3fa37384146079b3799b97667a94", + "sha256:d5280312b9af0976231f9e317c20e4a61cd2f9629b7bfea6a693d1878a264ebd", + "sha256:de06adc872bcd8c2a4e0dc51250e9e65ef2ca91be023b9d13ebd67c2ba552e1e", + "sha256:e1674e4307fa3024fc897ca774e9c7562c957af85df55efe2988ed9056dc4e57", + "sha256:e2096eddb4e7c7bdae4bd69ad364e55e07b8316653234a56552d9c988bd2d61b", + "sha256:e560628513ed34759456a416bf86b54b2476c59144a9138165c9a1575801d0d9", + "sha256:edfedb64740750e1a3b16152620220f51d58ff1b4abceb339ca92e934775c27a", + "sha256:f13cae8cc389a440def0c8c52057f37359014ccbc9dc1f0827936bcd367c6100", + "sha256:f314013e7dcd5cf45ab1945d92e713eec788166262ae8deb2cfacd53def27325", + "sha256:f583edb943cf2e09c60441b910d6a20b4d9d626c75a36c8fcac01a6c96c01183", + "sha256:fd8536e902db7e365f49e7d9029283403974ccf29b13fc7028b97e2295b33556", + "sha256:fe70e325aa68fa4b5edf7d1a4b6f691eb04bbccac0ace68e34820d283b5f80d4" + ], + "markers": "python_version >= '3.7'", + "version": "==1.5.0" + }, + "google-resumable-media": { + "hashes": [ + "sha256:972852f6c65f933e15a4a210c2b96930763b47197cdf4aa5f5bea435efb626e7", + "sha256:fc03d344381970f79eebb632a3c18bb1828593a2dc5572b5f90115ef7d11e81b" + ], + "markers": "python_version >= '3.7'", + "version": "==2.6.0" + }, + "googleapis-common-protos": { + "hashes": [ + "sha256:22f1915393bb3245343f6efe87f6fe868532efc12aa26b391b15132e1279f1c0", + "sha256:8a64866a97f6304a7179873a465d6eee97b7a24ec6cfd78e0f575e96b821240b" + ], + "markers": "python_version >= '3.7'", + "version": "==1.61.0" + }, + "gridemissions": { + "git": "git+https://github.com/gailin-p/gridemissions#egg=gridemissions", + "ref": "0cbe7620620f02ab91227940ef107b53bd1f9bb4" + }, + "h3": { + "hashes": [ + "sha256:02faa911f2d8425c641a1f7c08f3dc9c10a5a3d81408832afa40748534b999c8", + "sha256:0724d4645c1da59e02b3305050c52b93ce1d8971d1d139433d464fcc103249a6", + "sha256:1471ff4d3875b25b521eeec5c2b72abe27b8e6af10ab99b7da5c0de545b0e832", + "sha256:198718ab20a06ebe52f0aaafc02469e4a51964e5ba7990c3cc1d2fc32e7a54d9", + "sha256:1b4db92ceaeb9a51cc875c302cdc5e1aa27eed776d95943ee55c941bc2f219a3", + "sha256:1bdc790d91138e781973dcaade5231db7fe8a876330939e0903f602acc4fb64c", + "sha256:1cd4f07c49721023c5fef401a4de03c47000705dfd116579dc6b61cad821305d", + "sha256:1d3b93e3f38eb6c8fc5051d1b289b74614fb5f2415d272fea18085dea260d6b0", + "sha256:211ef3317dcf7863e2d01a97ab6da319b8451d78cd1633dd28faaf69e66bc321", + "sha256:231959dceb4cc4ae86fe4fe2c385b176ed81712549e787b889dfa66f583676df", + "sha256:26f3175bd3ea3ee528dbf49308e7215a58351ce425e1c3a9838ae22526663311", + "sha256:36ea935833c37fdfd7ffbfc000d7cd20addcdf67f30b26a6b9bccb9210b03704", + "sha256:3bae8b95f21f20f04141a35f15c8caa74f2046eb01ef49e35fc45e6a8edfc8df", + "sha256:4810ddb3d91411a6cbf87a28108fe31712f618ef223c349e1f6675602af2c473", + "sha256:495e37b1dee0ec46ccd88b278e571234b0d0d30648f161799d65a8d7f390b3f2", + "sha256:6ca9dd410e250d37f24a87c4ecb0615bb6d44a3f90eb5dbbf1b5e3d4489b8703", + "sha256:76abc02f14a8df42fb5d80e6045023fb756c49d3cb08d69a8ceb9362b95d4bec", + "sha256:783b2ca4448360c5a184fd43b84fc5554e3a8fd02738ff31349506189c5b4b49", + "sha256:7d7b69015f5bab2525914fad370b96dc386437e19a14cfed3eb13868589263db", + "sha256:8bf1e080b9a47774754834e7f10155f3d2e3542bf895488a0519b2ae7d5b15db", + "sha256:98c3951c3b67ca3de06ef70aa74a9752640a3eca9b4d68e0d5d8e4fc6fa72337", + "sha256:991ee991f2ae41f629feb1cd32fa677b8512c72696eb0ad94fcf359d61184b2e", + "sha256:99b81620608378fc9910a5c630b0f17eb939156fa13e1adc55229d31f8c3f5ca", + "sha256:9bbd3dbac99532fa521d7d2e288ff55877bea3223b070f659ed7b5f8f1f213eb", + "sha256:a2872f695168c4700c73edd6eab9c6181387d7ea177de13b130ae61e613ff7de", + "sha256:b1b1bce0dee05175f8d422e50ffa1afacb9a7e78ae0963059aebfbef50e10175", + "sha256:b2e2c4808b7691b176c89ebf23c173b3b23dd4ce42f8f494b32c6e31ceee49af", + "sha256:b58b1298bf1068704c6d9426749c8ae6021b53d982d5153cc4161c7042ecd810", + "sha256:b9de9da755c90bbc90d6c041396a20c91816cd86a0bafa3b8899681cfdc2c4c6", + "sha256:cd4a5103a86a7d98cffa3be77eb82080aa2e9d676bbd1661f3db9ecad7a4ef2b", + "sha256:cda9a427b0de0d4069115ec765118888f180d0db915b5bc0dba52f5ae957b789", + "sha256:d0c2890fa10fa8695c020569c8d55da79e2c552a39533de4ae6991c7acb122e1", + "sha256:e1f6ec0f2246381ce3a7f72da1ce825a5474eb7c8fb25a2ea1f16c6606ce34a7", + "sha256:eb96f2caae519d0ed17acde625af528476dca121b0336d3eb776429d40284ef6", + "sha256:eddf10d1d2139b3ea3ad1618c2074e1c47d3d36bddb5359e4955f5fd0b089d93", + "sha256:f8d1db3dcd8f6ce7f54e061e6c9fbecbb5c3978b9e54e44af05a53787c4f99b3", + "sha256:fc8030968586a7810aa192397ad9a4f7d7a963f57c9b3e210fc38de0aa5c2533", + "sha256:fcbfff87d223279f8e38bbee3ebf52b1b96ae280e9e7de24674d3c284373d946" + ], + "version": "==3.7.6" + }, + "humanfriendly": { + "hashes": [ + "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", + "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==10.0" + }, + "idna": { + "hashes": [ + "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", + "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" + ], + "markers": "python_version >= '3.5'", + "version": "==3.6" + }, + "ijson": { + "hashes": [ + "sha256:055b71bbc37af5c3c5861afe789e15211d2d3d06ac51ee5a647adf4def19c0ea", + "sha256:0567e8c833825b119e74e10a7c29761dc65fcd155f5d4cb10f9d3b8916ef9912", + "sha256:06f9707da06a19b01013f8c65bf67db523662a9b4a4ff027e946e66c261f17f0", + "sha256:0974444c1f416e19de1e9f567a4560890095e71e81623c509feff642114c1e53", + "sha256:0a4ae076bf97b0430e4e16c9cb635a6b773904aec45ed8dcbc9b17211b8569ba", + "sha256:0b9d1141cfd1e6d6643aa0b4876730d0d28371815ce846d2e4e84a2d4f471cf3", + "sha256:0e0243d166d11a2a47c17c7e885debf3b19ed136be2af1f5d1c34212850236ac", + "sha256:10294e9bf89cb713da05bc4790bdff616610432db561964827074898e174f917", + "sha256:105c314fd624e81ed20f925271ec506523b8dd236589ab6c0208b8707d652a0e", + "sha256:1844c5b57da21466f255a0aeddf89049e730d7f3dfc4d750f0e65c36e6a61a7c", + "sha256:211124cff9d9d139dd0dfced356f1472860352c055d2481459038b8205d7d742", + "sha256:2a80c0bb1053055d1599e44dc1396f713e8b3407000e6390add72d49633ff3bb", + "sha256:2cc04fc0a22bb945cd179f614845c8b5106c0b3939ee0d84ce67c7a61ac1a936", + "sha256:2ec3e5ff2515f1c40ef6a94983158e172f004cd643b9e4b5302017139b6c96e4", + "sha256:35194e0b8a2bda12b4096e2e792efa5d4801a0abb950c48ade351d479cd22ba5", + "sha256:396338a655fb9af4ac59dd09c189885b51fa0eefc84d35408662031023c110d1", + "sha256:39f551a6fbeed4433c85269c7c8778e2aaea2501d7ebcb65b38f556030642c17", + "sha256:3b14d322fec0de7af16f3ef920bf282f0dd747200b69e0b9628117f381b7775b", + "sha256:3c0d526ccb335c3c13063c273637d8611f32970603dfb182177b232d01f14c23", + "sha256:3dcc33ee56f92a77f48776014ddb47af67c33dda361e84371153c4f1ed4434e1", + "sha256:4252e48c95cd8ceefc2caade310559ab61c37d82dfa045928ed05328eb5b5f65", + "sha256:455d7d3b7a6aacfb8ab1ebcaf697eedf5be66e044eac32508fccdc633d995f0e", + "sha256:457f8a5fc559478ac6b06b6d37ebacb4811f8c5156e997f0d87d708b0d8ab2ae", + "sha256:46bafb1b9959872a1f946f8dd9c6f1a30a970fc05b7bfae8579da3f1f988e598", + "sha256:4a3a6a2fbbe7550ffe52d151cf76065e6b89cfb3e9d0463e49a7e322a25d0426", + "sha256:4b2ec8c2a3f1742cbd5f36b65e192028e541b5fd8c7fd97c1fc0ca6c427c704a", + "sha256:4fc35d569eff3afa76bfecf533f818ecb9390105be257f3f83c03204661ace70", + "sha256:545a30b3659df2a3481593d30d60491d1594bc8005f99600e1bba647bb44cbb5", + "sha256:644f4f03349ff2731fd515afd1c91b9e439e90c9f8c28292251834154edbffca", + "sha256:674e585361c702fad050ab4c153fd168dc30f5980ef42b64400bc84d194e662d", + "sha256:6a4db2f7fb9acfb855c9ae1aae602e4648dd1f88804a0d5cfb78c3639bcf156c", + "sha256:6bd3e7e91d031f1e8cea7ce53f704ab74e61e505e8072467e092172422728b22", + "sha256:6c32c18a934c1dc8917455b0ce478fd7a26c50c364bd52c5a4fb0fc6bb516af7", + "sha256:6f662dc44362a53af3084d3765bb01cd7b4734d1f484a6095cad4cb0cbfe5374", + "sha256:713a919e0220ac44dab12b5fed74f9130f3480e55e90f9d80f58de129ea24f83", + "sha256:7596b42f38c3dcf9d434dddd50f46aeb28e96f891444c2b4b1266304a19a2c09", + "sha256:7851a341429b12d4527ca507097c959659baf5106c7074d15c17c387719ffbcd", + "sha256:7b8064a85ec1b0beda7dd028e887f7112670d574db606f68006c72dd0bb0e0e2", + "sha256:7ce4c70c23521179d6da842bb9bc2e36bb9fad1e0187e35423ff0f282890c9ca", + "sha256:7dc357da4b4ebd8903e77dbcc3ce0555ee29ebe0747c3c7f56adda423df8ec89", + "sha256:81815b4184b85ce124bfc4c446d5f5e5e643fc119771c5916f035220ada29974", + "sha256:85afdb3f3a5d0011584d4fa8e6dccc5936be51c27e84cd2882fe904ca3bd04c5", + "sha256:86b3c91fdcb8ffb30556c9669930f02b7642de58ca2987845b04f0d7fe46d9a8", + "sha256:904f77dd3d87736ff668884fe5197a184748eb0c3e302ded61706501d0327465", + "sha256:916acdc5e504f8b66c3e287ada5d4b39a3275fc1f2013c4b05d1ab9933671a6c", + "sha256:923131f5153c70936e8bd2dd9dcfcff43c67a3d1c789e9c96724747423c173eb", + "sha256:92dc4d48e9f6a271292d6079e9fcdce33c83d1acf11e6e12696fb05c5889fe74", + "sha256:96190d59f015b5a2af388a98446e411f58ecc6a93934e036daa75f75d02386a0", + "sha256:9680e37a10fedb3eab24a4a7e749d8a73f26f1a4c901430e7aa81b5da15f7307", + "sha256:9788f0c915351f41f0e69ec2618b81ebfcf9f13d9d67c6d404c7f5afda3e4afb", + "sha256:98c6799925a5d1988da4cd68879b8eeab52c6e029acc45e03abb7921a4715c4b", + "sha256:9c2a12dcdb6fa28f333bf10b3a0f80ec70bc45280d8435be7e19696fab2bc706", + "sha256:9e0a27db6454edd6013d40a956d008361aac5bff375a9c04ab11fc8c214250b5", + "sha256:a2973ce57afb142d96f35a14e9cfec08308ef178a2c76b8b5e1e98f3960438bf", + "sha256:a4d7fe3629de3ecb088bff6dfe25f77be3e8261ed53d5e244717e266f8544305", + "sha256:a729b0c8fb935481afe3cf7e0dadd0da3a69cc7f145dbab8502e2f1e01d85a7c", + "sha256:ab4db9fee0138b60e31b3c02fff8a4c28d7b152040553b6a91b60354aebd4b02", + "sha256:ac44781de5e901ce8339352bb5594fcb3b94ced315a34dbe840b4cff3450e23b", + "sha256:b49fd5fe1cd9c1c8caf6c59f82b08117dd6bea2ec45b641594e25948f48f4169", + "sha256:b4eb2304573c9fdf448d3fa4a4fdcb727b93002b5c5c56c14a5ffbbc39f64ae4", + "sha256:ba33c764afa9ecef62801ba7ac0319268a7526f50f7601370d9f8f04e77fc02b", + "sha256:bcc51c84bb220ac330122468fe526a7777faa6464e3b04c15b476761beea424f", + "sha256:bdd0dc5da4f9dc6d12ab6e8e0c57d8b41d3c8f9ceed31a99dae7b2baf9ea769a", + "sha256:be8495f7c13fa1f622a2c6b64e79ac63965b89caf664cc4e701c335c652d15f2", + "sha256:c075a547de32f265a5dd139ab2035900fef6653951628862e5cdce0d101af557", + "sha256:c1a4b8eb69b6d7b4e94170aa991efad75ba156b05f0de2a6cd84f991def12ff9", + "sha256:c63f3d57dbbac56cead05b12b81e8e1e259f14ce7f233a8cbe7fa0996733b628", + "sha256:c6beb80df19713e39e68dc5c337b5c76d36ccf69c30b79034634e5e4c14d6904", + "sha256:ccd6be56335cbb845f3d3021b1766299c056c70c4c9165fb2fbe2d62258bae3f", + "sha256:cfced0a6ec85916eb8c8e22415b7267ae118eaff2a860c42d2cc1261711d0d31", + "sha256:d052417fd7ce2221114f8d3b58f05a83c1a2b6b99cafe0b86ac9ed5e2fc889df", + "sha256:d1053fb5f0b010ee76ca515e6af36b50d26c1728ad46be12f1f147a835341083", + "sha256:d31e0d771d82def80cd4663a66de277c3b44ba82cd48f630526b52f74663c639", + "sha256:d34e049992d8a46922f96483e96b32ac4c9cffd01a5c33a928e70a283710cd58", + "sha256:d6ea7c7e3ec44742e867c72fd750c6a1e35b112f88a917615332c4476e718d40", + "sha256:db2d6341f9cb538253e7fe23311d59252f124f47165221d3c06a7ed667ecd595", + "sha256:db3bf1b42191b5cc9b6441552fdcb3b583594cb6b19e90d1578b7cbcf80d0fae", + "sha256:e641814793a037175f7ec1b717ebb68f26d89d82cfd66f36e588f32d7e488d5f", + "sha256:e84d27d1acb60d9102728d06b9650e5b7e5cb0631bd6e3dfadba8fb6a80d6c2f", + "sha256:e9fd906f0c38e9f0bfd5365e1bed98d649f506721f76bb1a9baa5d7374f26f19", + "sha256:eaac293853f1342a8d2a45ac1f723c860f700860e7743fb97f7b76356df883a8", + "sha256:eeb286639649fb6bed37997a5e30eefcacddac79476d24128348ec890b2a0ccb", + "sha256:f05ed49f434ce396ddcf99e9fd98245328e99f991283850c309f5e3182211a79", + "sha256:f4bc87e69d1997c6a55fff5ee2af878720801ff6ab1fb3b7f94adda050651e37", + "sha256:f8d54b624629f9903005c58d9321a036c72f5c212701bbb93d1a520ecd15e370", + "sha256:fa234ab7a6a33ed51494d9d2197fb96296f9217ecae57f5551a55589091e7853", + "sha256:fa8b98be298efbb2588f883f9953113d8a0023ab39abe77fe734b71b46b1220a", + "sha256:fbac4e9609a1086bbad075beb2ceec486a3b138604e12d2059a33ce2cba93051", + "sha256:fd12e42b9cb9c0166559a3ffa276b4f9fc9d5b4c304e5a13668642d34b48b634" + ], + "version": "==3.2.3" + }, + "iniconfig": { + "hashes": [ + "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", + "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.0" + }, + "ipykernel": { + "hashes": [ + "sha256:7d5d594b6690654b4d299edba5e872dc17bb7396a8d0609c97cb7b8a1c605de6", + "sha256:dab88b47f112f9f7df62236511023c9bdeef67abc73af7c652e4ce4441601686" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==6.27.1" + }, + "ipython": { + "hashes": [ + "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27", + "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397" + ], + "markers": "python_version >= '3.9'", + "version": "==8.18.1" + }, + "isodate": { + "hashes": [ + "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96", + "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9" + ], + "version": "==0.6.1" + }, + "isoduration": { + "hashes": [ + "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", + "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042" + ], + "version": "==20.11.0" + }, + "jedi": { + "hashes": [ + "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd", + "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0" + ], + "markers": "python_version >= '3.6'", + "version": "==0.19.1" + }, + "jinja2": { + "hashes": [ + "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", + "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.2" + }, + "jmespath": { + "hashes": [ + "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", + "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.1" + }, + "joblib": { + "hashes": [ + "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1", + "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.2" + }, + "json5": { + "hashes": [ + "sha256:740c7f1b9e584a468dbb2939d8d458db3427f2c93ae2139d05f47e453eae964f", + "sha256:9ed66c3a6ca3510a976a9ef9b8c0787de24802724ab1860bc0153c7fdd589b02" + ], + "version": "==0.9.14" + }, + "jsonlines": { + "hashes": [ + "sha256:0c6d2c09117550c089995247f605ae4cf77dd1533041d366351f6f298822ea74", + "sha256:185b334ff2ca5a91362993f42e83588a360cf95ce4b71a73548502bda52a7c55" + ], + "markers": "python_version >= '3.8'", + "version": "==4.0.0" + }, + "jsonpointer": { + "hashes": [ + "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a", + "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==2.4" + }, + "jsonschema": { + "extras": [ + "format-nongpl" + ], + "hashes": [ + "sha256:4f614fd46d8d61258610998997743ec5492a648b33cf478c1ddc23ed4598a5fa", + "sha256:ed6231f0429ecf966f5bc8dfef245998220549cbbcf140f913b7464c52c3b6b3" + ], + "markers": "python_version >= '3.8'", + "version": "==4.20.0" + }, + "jsonschema-specifications": { + "hashes": [ + "sha256:c9b234904ffe02f079bf91b14d79987faa685fd4b39c377a0996954c0090b9ca", + "sha256:f596778ab612b3fd29f72ea0d990393d0540a5aab18bf0407a46632eab540779" + ], + "markers": "python_version >= '3.8'", + "version": "==2023.11.1" + }, + "jupyter-client": { + "hashes": [ + "sha256:0642244bb83b4764ae60d07e010e15f0e2d275ec4e918a8f7b80fbbef3ca60c7", + "sha256:909c474dbe62582ae62b758bca86d6518c85234bdee2d908c778db6d72f39d99" + ], + "markers": "python_version >= '3.8'", + "version": "==8.6.0" + }, + "jupyter-core": { + "hashes": [ + "sha256:880b86053bf298a8724994f95e99b99130659022a4f7f45f563084b6223861d3", + "sha256:e11e02cd8ae0a9de5c6c44abf5727df9f2581055afe00b22183f621ba3585805" + ], + "markers": "python_version >= '3.8'", + "version": "==5.5.0" + }, + "jupyter-events": { + "hashes": [ + "sha256:81ad2e4bc710881ec274d31c6c50669d71bbaa5dd9d01e600b56faa85700d399", + "sha256:d853b3c10273ff9bc8bb8b30076d65e2c9685579db736873de6c2232dde148bf" + ], + "markers": "python_version >= '3.8'", + "version": "==0.9.0" + }, + "jupyter-lsp": { + "hashes": [ + "sha256:17a689910c5e4ae5e7d334b02f31d08ffbe98108f6f658fb05e4304b4345368b", + "sha256:b17fab6d70fe83c8896b0cff59237640038247c196056b43684a0902b6a9e0fb" + ], + "markers": "python_version >= '3.8'", + "version": "==2.2.1" + }, + "jupyter-server": { + "hashes": [ + "sha256:4b3a16e3ed16fd202588890f10b8ca589bd3e29405d128beb95935f059441373", + "sha256:fe80bab96493acf5f7d6cd9a1575af8fbd253dc2591aa4d015131a1e03b5799a" + ], + "markers": "python_version >= '3.8'", + "version": "==2.11.1" + }, + "jupyter-server-terminals": { + "hashes": [ + "sha256:57ab779797c25a7ba68e97bcfb5d7740f2b5e8a83b5e8102b10438041a7eac5d", + "sha256:75779164661cec02a8758a5311e18bb8eb70c4e86c6b699403100f1585a12a36" + ], + "markers": "python_version >= '3.8'", + "version": "==0.4.4" + }, + "jupyterlab": { + "hashes": [ + "sha256:9ebada41d52651f623c0c9f069ddb8a21d6848e4c887d8e5ddc0613166ed5c0b", + "sha256:9f6f8e36d543fdbcc3df961a1d6a3f524b4a4001be0327a398f68fa4e534107c" + ], + "markers": "python_version >= '3.8'", + "version": "==4.0.9" + }, + "jupyterlab-pygments": { + "hashes": [ + "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d", + "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780" + ], + "markers": "python_version >= '3.8'", + "version": "==0.3.0" + }, + "jupyterlab-server": { + "hashes": [ + "sha256:5b1798c9cc6a44f65c757de9f97fc06fc3d42535afbf47d2ace5e964ab447aaf", + "sha256:bd0ec7a99ebcedc8bcff939ef86e52c378e44c2707e053fcd81d046ce979ee63" + ], + "markers": "python_version >= '3.8'", + "version": "==2.25.2" + }, + "kiwisolver": { + "hashes": [ + "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf", + "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e", + "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af", + "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f", + "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046", + "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3", + "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5", + "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71", + "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee", + "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3", + "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9", + "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b", + "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985", + "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea", + "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16", + "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89", + "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c", + "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9", + "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712", + "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342", + "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a", + "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958", + "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d", + "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a", + "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130", + "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff", + "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898", + "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b", + "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f", + "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265", + "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93", + "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929", + "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635", + "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709", + "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b", + "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb", + "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a", + "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920", + "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e", + "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544", + "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45", + "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390", + "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77", + "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355", + "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff", + "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4", + "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7", + "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20", + "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c", + "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162", + "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228", + "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437", + "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc", + "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a", + "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901", + "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4", + "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770", + "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525", + "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad", + "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a", + "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29", + "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90", + "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250", + "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d", + "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3", + "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54", + "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f", + "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1", + "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da", + "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238", + "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa", + "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523", + "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0", + "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205", + "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3", + "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4", + "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac", + "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9", + "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb", + "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced", + "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd", + "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0", + "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da", + "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18", + "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9", + "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276", + "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333", + "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b", + "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db", + "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126", + "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9", + "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09", + "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0", + "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec", + "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7", + "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff", + "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9", + "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192", + "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8", + "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d", + "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6", + "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797", + "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892", + "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f" + ], + "markers": "python_version >= '3.7'", + "version": "==1.4.5" + }, + "linear-tsv": { + "hashes": [ + "sha256:b504d78f4075615ae75de86a16e5680701a441fc84da2a2cf9f94351ab1ccbf5" + ], + "version": "==1.1.0" + }, + "locket": { + "hashes": [ + "sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632", + "sha256:b6c819a722f7b6bd955b80781788e4a66a55628b858d347536b7e81325a3a5e3" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.0.0" + }, + "lxml": { + "hashes": [ + "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3", + "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d", + "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a", + "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120", + "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305", + "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287", + "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23", + "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52", + "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f", + "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4", + "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584", + "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f", + "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693", + "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef", + "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5", + "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02", + "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc", + "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7", + "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da", + "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a", + "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40", + "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8", + "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd", + "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601", + "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c", + "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be", + "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2", + "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c", + "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129", + "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc", + "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2", + "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1", + "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7", + "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d", + "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477", + "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d", + "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e", + "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7", + "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2", + "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574", + "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf", + "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b", + "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98", + "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12", + "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42", + "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35", + "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d", + "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce", + "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d", + "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f", + "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db", + "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4", + "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694", + "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac", + "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2", + "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7", + "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96", + "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d", + "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b", + "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a", + "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13", + "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340", + "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6", + "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458", + "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c", + "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c", + "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9", + "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432", + "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991", + "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69", + "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf", + "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb", + "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b", + "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833", + "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76", + "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85", + "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e", + "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50", + "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8", + "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4", + "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b", + "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5", + "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190", + "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7", + "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa", + "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0", + "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9", + "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0", + "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b", + "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5", + "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7", + "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==4.9.3" + }, + "markdown-it-py": { + "hashes": [ + "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", + "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb" + ], + "markers": "python_version >= '3.8'", + "version": "==3.0.0" + }, + "marko": { + "hashes": [ + "sha256:2ebd448ac82636765db49777e735923c799a6d66c75bc4997a922bb4c12e4563", + "sha256:502df6d827139ea7265d819f4fe3664589f4774997eff758dc38bea4f52350e6" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.2" + }, + "markupsafe": { + "hashes": [ + "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e", + "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e", + "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431", + "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686", + "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c", + "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559", + "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc", + "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb", + "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939", + "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c", + "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0", + "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4", + "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9", + "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575", + "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba", + "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d", + "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd", + "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3", + "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00", + "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155", + "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac", + "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52", + "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f", + "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8", + "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b", + "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007", + "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24", + "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea", + "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198", + "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0", + "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee", + "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be", + "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2", + "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1", + "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707", + "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6", + "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c", + "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58", + "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823", + "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779", + "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636", + "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c", + "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad", + "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee", + "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc", + "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2", + "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48", + "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7", + "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e", + "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b", + "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa", + "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5", + "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e", + "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb", + "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9", + "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57", + "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc", + "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc", + "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2", + "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11" + ], + "markers": "python_version >= '3.7'", + "version": "==2.1.3" + }, + "matplotlib": { + "hashes": [ + "sha256:01b7f521a9a73c383825813af255f8c4485d1706e4f3e2ed5ae771e4403a40ab", + "sha256:11011c97d62c1db7bc20509572557842dbb8c2a2ddd3dd7f20501aa1cde3e54e", + "sha256:1183877d008c752d7d535396096c910f4663e4b74a18313adee1213328388e1e", + "sha256:12f999661589981e74d793ee2f41b924b3b87d65fd929f6153bf0f30675c59b1", + "sha256:1c235bf9be052347373f589e018988cad177abb3f997ab1a2e2210c41562cc0c", + "sha256:1f4d69707b1677560cd952544ee4962f68ff07952fb9069ff8c12b56353cb8c9", + "sha256:1fcc4cad498533d3c393a160975acc9b36ffa224d15a6b90ae579eacee5d8579", + "sha256:2787a16df07370dcba385fe20cdd0cc3cfaabd3c873ddabca78c10514c799721", + "sha256:29f17b7f2e068dc346687cbdf80b430580bab42346625821c2d3abf3a1ec5417", + "sha256:38d38cb1ea1d80ee0f6351b65c6f76cad6060bbbead015720ba001348ae90f0c", + "sha256:3f56a7252eee8f3438447f75f5e1148a1896a2756a92285fe5d73bed6deebff4", + "sha256:5223affa21050fb6118353c1380c15e23aedfb436bf3e162c26dc950617a7519", + "sha256:57ad1aee29043163374bfa8990e1a2a10ff72c9a1bfaa92e9c46f6ea59269121", + "sha256:59400cc9451094b7f08cc3f321972e6e1db4cd37a978d4e8a12824bf7fd2f03b", + "sha256:68d94a436f62b8a861bf3ace82067a71bafb724b4e4f9133521e4d8012420dd7", + "sha256:6adc441b5b2098a4b904bbf9d9e92fb816fef50c55aa2ea6a823fc89b94bb838", + "sha256:6d81b11ede69e3a751424b98dc869c96c10256b2206bfdf41f9c720eee86844c", + "sha256:73b93af33634ed919e72811c9703e1105185cd3fb46d76f30b7f4cfbbd063f89", + "sha256:77b384cee7ab8cf75ffccbfea351a09b97564fc62d149827a5e864bec81526e5", + "sha256:79e501eb847f4a489eb7065bb8d3187117f65a4c02d12ea3a19d6c5bef173bcc", + "sha256:809119d1cba3ece3c9742eb01827fe7a0e781ea3c5d89534655a75e07979344f", + "sha256:80c166a0e28512e26755f69040e6bf2f946a02ffdb7c00bf6158cca3d2b146e6", + "sha256:81b409b2790cf8d7c1ef35920f01676d2ae7afa8241844e7aa5484fdf493a9a0", + "sha256:994637e2995b0342699b396a320698b07cd148bbcf2dd2fa2daba73f34dd19f2", + "sha256:9ceebaf73f1a3444fa11014f38b9da37ff7ea328d6efa1652241fe3777bfdab9", + "sha256:9fb8fb19d03abf3c5dab89a8677e62c4023632f919a62b6dd1d6d2dbf42cd9f5", + "sha256:acc3b1a4bddbf56fe461e36fb9ef94c2cb607fc90d24ccc650040bfcc7610de4", + "sha256:bbddfeb1495484351fb5b30cf5bdf06b3de0bc4626a707d29e43dfd61af2a780", + "sha256:bbf269e1d24bc25247095d71c7a969813f7080e2a7c6fa28931a603f747ab012", + "sha256:bebcff4c3ed02c6399d47329f3554193abd824d3d53b5ca02cf583bcd94470e2", + "sha256:c3f08df2ac4636249b8bc7a85b8b82c983bef1441595936f62c2918370ca7e1d", + "sha256:ca94f0362f6b6f424b555b956971dcb94b12d0368a6c3e07dc7a40d32d6d873d", + "sha256:d00c248ab6b92bea3f8148714837937053a083ff03b4c5e30ed37e28fc0e7e56", + "sha256:d2cfaa7fd62294d945b8843ea24228a27c8e7c5b48fa634f3c168153b825a21b", + "sha256:d5f18430f5cfa5571ab8f4c72c89af52aa0618e864c60028f11a857d62200cba", + "sha256:debeab8e2ab07e5e3dac33e12456da79c7e104270d2b2d1df92b9e40347cca75", + "sha256:dfba7057609ca9567b9704626756f0142e97ec8c5ba2c70c6e7bd1c25ef99f06", + "sha256:e0a64d7cc336b52e90f59e6d638ae847b966f68582a7af041e063d568e814740", + "sha256:eb9421c403ffd387fbe729de6d9a03005bf42faba5e8432f4e51e703215b49fc", + "sha256:faff486b36530a836a6b4395850322e74211cd81fc17f28b4904e1bd53668e3e", + "sha256:ff2aa84e74f80891e6bcf292ebb1dd57714ffbe13177642d65fee25384a30894" + ], + "markers": "python_version >= '3.8'", + "version": "==3.6.3" + }, + "matplotlib-inline": { + "hashes": [ + "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311", + "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304" + ], + "markers": "python_version >= '3.5'", + "version": "==0.1.6" + }, + "mdurl": { + "hashes": [ + "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", + "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" + ], + "markers": "python_version >= '3.7'", + "version": "==0.1.2" + }, + "mistune": { + "hashes": [ + "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205", + "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8" + ], + "markers": "python_version >= '3.7'", + "version": "==3.0.2" + }, + "multidict": { + "hashes": [ + "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9", + "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8", + "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03", + "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710", + "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161", + "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664", + "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569", + "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067", + "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313", + "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706", + "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2", + "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636", + "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49", + "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93", + "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603", + "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0", + "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60", + "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4", + "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e", + "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1", + "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60", + "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951", + "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc", + "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe", + "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95", + "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d", + "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8", + "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed", + "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2", + "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775", + "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87", + "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c", + "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2", + "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98", + "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3", + "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe", + "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78", + "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660", + "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176", + "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e", + "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988", + "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c", + "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c", + "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0", + "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449", + "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f", + "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde", + "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5", + "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d", + "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac", + "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a", + "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9", + "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca", + "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11", + "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35", + "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063", + "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b", + "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982", + "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258", + "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1", + "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52", + "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480", + "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7", + "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461", + "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d", + "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc", + "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779", + "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a", + "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547", + "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0", + "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171", + "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf", + "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d", + "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba" + ], + "markers": "python_version >= '3.7'", + "version": "==6.0.4" + }, + "nbclient": { + "hashes": [ + "sha256:4b28c207877cf33ef3a9838cdc7a54c5ceff981194a82eac59d558f05487295e", + "sha256:a3a1ddfb34d4a9d17fc744d655962714a866639acd30130e9be84191cd97cd15" + ], + "markers": "python_full_version >= '3.8.0'", + "version": "==0.9.0" + }, + "nbconvert": { + "hashes": [ + "sha256:abedc01cf543177ffde0bfc2a69726d5a478f6af10a332fc1bf29fcb4f0cf000", + "sha256:d1d417b7f34a4e38887f8da5bdfd12372adf3b80f995d57556cb0972c68909fe" + ], + "markers": "python_version >= '3.8'", + "version": "==7.11.0" + }, + "nbformat": { + "hashes": [ + "sha256:1c5172d786a41b82bcfd0c23f9e6b6f072e8fb49c39250219e4acfff1efe89e9", + "sha256:5f98b5ba1997dff175e77e0c17d5c10a96eaed2cbd1de3533d1fc35d5e111192" + ], + "markers": "python_version >= '3.8'", + "version": "==5.9.2" + }, + "nest-asyncio": { + "hashes": [ + "sha256:25aa2ca0d2a5b5531956b9e273b45cf664cae2b145101d73b86b199978d48fdb", + "sha256:accda7a339a70599cb08f9dd09a67e0c2ef8d8d6f4c07f96ab203f2ae254e48d" + ], + "markers": "python_version >= '3.5'", + "version": "==1.5.8" + }, + "networkx": { + "hashes": [ + "sha256:58058d66b1818043527244fab9d41a51fcd7dcc271748015f3c181b8a90c8e2e", + "sha256:9a9992345353618ae98339c2b63d8201c381c2944f38a2ab49cb45a4c667e412" + ], + "markers": "python_version >= '3.8'", + "version": "==3.0" + }, + "notebook": { + "hashes": [ + "sha256:0fe8f67102fea3744fedf652e4c15339390902ca70c5a31c4f547fa23da697cc", + "sha256:ec6113b06529019f7f287819af06c97a2baf7a95ac21a8f6e32192898e9f9a58" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==7.0.6" + }, + "notebook-shim": { + "hashes": [ + "sha256:a83496a43341c1674b093bfcebf0fe8e74cbe7eda5fd2bbc56f8e39e1486c0c7", + "sha256:f69388ac283ae008cd506dda10d0288b09a017d822d5e8c7129a152cbd3ce7e9" + ], + "markers": "python_version >= '3.7'", + "version": "==0.2.3" + }, + "numpy": { + "hashes": [ + "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f", + "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61", + "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7", + "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400", + "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef", + "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2", + "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d", + "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc", + "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835", + "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706", + "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5", + "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4", + "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6", + "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463", + "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a", + "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f", + "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e", + "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e", + "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694", + "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8", + "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64", + "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d", + "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc", + "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254", + "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2", + "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1", + "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810", + "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==1.24.4" + }, + "oauthlib": { + "hashes": [ + "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", + "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918" + ], + "markers": "python_version >= '3.6'", + "version": "==3.2.2" + }, + "openpyxl": { + "hashes": [ + "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184", + "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5" + ], + "index": "pypi", + "markers": "python_version >= '3.6'", + "version": "==3.1.2" + }, + "osqp": { + "hashes": [ + "sha256:0084e3d733c75687d68bc133bc380ce471dfe6f7724af2718a43491782eec8d6", + "sha256:03e460e683ec2ce0f839353ddfa3c4c8ffa509ab8cf6a2b2afbb586fa453e180", + "sha256:0441c10f7fe5f46692a9b44a57138977bb112ae3f8127151671968c5d9ec5dbb", + "sha256:146b89f2cfbf59eaeb2c47e3a312f2034138df78d80ce052364810dc0ef70fc4", + "sha256:1b2049b2c42565dcaa63ddca1c4028b1fb20aab141453f5d77e8ff5b1a99a2cf", + "sha256:1b573fe1cd0e82239a279c58817c1d365187ef862e928b2b9c828c3c516ad3c2", + "sha256:1c548a0b3691850e7e22f3624a128d8af33416d70a9b5976a47d4d832028dcd8", + "sha256:30fbc3b3c028c06a6c5f1e66be7b7106ad48a29e0dc5bd82393f82dd68235ef8", + "sha256:387e7abd737dfe32c9ec00ad74af25328cdd0d0f634d79530655c040a5cb9590", + "sha256:3cbb6efdaffb7387dc0037dfe3259d4803e5ad7217e6f20fb605c92953214b9d", + "sha256:3f3a3c6d2708868e5e3fe2da300d6523cbf68a3d8734ce9c5043db37391969f5", + "sha256:41f304d1d7f91af07d8f0b01e5af29ec3bb8824f0102c7fd8b13b497be120da4", + "sha256:60abec3593870990b16f00bd5017096a7091fb00b68d0db3383fc048ca8e55c9", + "sha256:6c3951ef505177b858c6cd34de980346014cae3d2234c93db960b12c5885f9a2", + "sha256:71d9f611823af4a8b241c86805920e5382cd65c7f94fd3615b4eef999ed94c7c", + "sha256:7eafa3f3e82dd36c52f3f4ef19a95142405c807c272c4b53c5971c53535d7804", + "sha256:b15e65a307fbbabf60248bb9bc204e61d5d4ae64e00427a69e2dad9622f4c29d", + "sha256:b73bdd9589901841af83c5ed6a4092b4fac5a0beff9e32682d8526d1f16a728c", + "sha256:c07b1a4b538aab629b0fae69f644b7e76f81f94d65230014d482e296dacd046b", + "sha256:dc18f87c9549032c163ce590a5e32079df94ee656c8fb357ba607aa9d78fab81", + "sha256:e1445e10a94e01698e13c87a7debf6ac1a15f3acd1f8f6340cb1ad945db4732b", + "sha256:e1dfda08c38c3521012740a73ef782f97dfc54a41deae4b0bc4afd18d0e74da0", + "sha256:e6b7d923c836f1d07115057e595245ccc1694ecae730a1affda78fc6f3c8d239", + "sha256:ea7d8c92bcdf4fef98d777f13d39060d425ef2e8778ed487c96a6fa10848cdea", + "sha256:fe57e4bde071b388518ecb068f26319506dd9cb107363d3d80c12d2e59fc1e81" + ], + "index": "pypi", + "version": "==0.6.3" + }, + "overrides": { + "hashes": [ + "sha256:3ad24583f86d6d7a49049695efe9933e67ba62f0c7625d53c59fa832ce4b8b7d", + "sha256:9502a3cca51f4fac40b5feca985b6703a5c1f6ad815588a7ca9e285b9dca6757" + ], + "markers": "python_version >= '3.6'", + "version": "==7.4.0" + }, + "packaging": { + "hashes": [ + "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", + "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" + ], + "markers": "python_version >= '3.7'", + "version": "==23.2" + }, + "pandas": { + "hashes": [ + "sha256:14e45300521902689a81f3f41386dc86f19b8ba8dd5ac5a3c7010ef8d2932813", + "sha256:26d9c71772c7afb9d5046e6e9cf42d83dd147b5cf5bcb9d97252077118543792", + "sha256:3749077d86e3a2f0ed51367f30bf5b82e131cc0f14260c4d3e499186fccc4406", + "sha256:41179ce559943d83a9b4bbacb736b04c928b095b5f25dd2b7389eda08f46f373", + "sha256:478ff646ca42b20376e4ed3fa2e8d7341e8a63105586efe54fa2508ee087f328", + "sha256:50869a35cbb0f2e0cd5ec04b191e7b12ed688874bd05dd777c19b28cbea90996", + "sha256:565fa34a5434d38e9d250af3c12ff931abaf88050551d9fbcdfafca50d62babf", + "sha256:5f2b952406a1588ad4cad5b3f55f520e82e902388a6d5a4a91baa8d38d23c7f6", + "sha256:5fbcb19d6fceb9e946b3e23258757c7b225ba450990d9ed63ccceeb8cae609f7", + "sha256:6973549c01ca91ec96199e940495219c887ea815b2083722821f1d7abfa2b4dc", + "sha256:74a3fd7e5a7ec052f183273dc7b0acd3a863edf7520f5d3a1765c04ffdb3b0b1", + "sha256:7a0a56cef15fd1586726dace5616db75ebcfec9179a3a55e78f72c5639fa2a23", + "sha256:7cec0bee9f294e5de5bbfc14d0573f65526071029d036b753ee6507d2a21480a", + "sha256:87bd9c03da1ac870a6d2c8902a0e1fd4267ca00f13bc494c9e5a9020920e1d51", + "sha256:972d8a45395f2a2d26733eb8d0f629b2f90bebe8e8eddbb8829b180c09639572", + "sha256:9842b6f4b8479e41968eced654487258ed81df7d1c9b7b870ceea24ed9459b31", + "sha256:9f69c4029613de47816b1bb30ff5ac778686688751a5e9c99ad8c7031f6508e5", + "sha256:a50d9a4336a9621cab7b8eb3fb11adb82de58f9b91d84c2cd526576b881a0c5a", + "sha256:bc4c368f42b551bf72fac35c5128963a171b40dce866fb066540eeaf46faa003", + "sha256:c39a8da13cede5adcd3be1182883aea1c925476f4e84b2807a46e2775306305d", + "sha256:c3ac844a0fe00bfaeb2c9b51ab1424e5c8744f89860b138434a363b1f620f354", + "sha256:c4c00e0b0597c8e4f59e8d461f797e5d70b4d025880516a8261b2817c47759ee", + "sha256:c74a62747864ed568f5a82a49a23a8d7fe171d0c69038b38cedf0976831296fa", + "sha256:dd05f7783b3274aa206a1af06f0ceed3f9b412cf665b7247eacd83be41cf7bf0", + "sha256:dfd681c5dc216037e0b0a2c821f5ed99ba9f03ebcf119c7dac0e9a7b960b9ec9", + "sha256:e474390e60ed609cec869b0da796ad94f420bb057d86784191eefc62b65819ae", + "sha256:f76d097d12c82a535fda9dfe5e8dd4127952b45fea9b0276cb30cca5ea313fbc" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==1.5.3" + }, + "pandocfilters": { + "hashes": [ + "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38", + "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.5.0" + }, + "parso": { + "hashes": [ + "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0", + "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75" + ], + "markers": "python_version >= '3.6'", + "version": "==0.8.3" + }, + "partd": { + "hashes": [ + "sha256:27e766663d36c161e2827aa3e28541c992f0b9527d3cca047e13fb3acdb989e6", + "sha256:56c25dd49e6fea5727e731203c466c6e092f308d8f0024e199d02f6aa2167f67" + ], + "markers": "python_version >= '3.7'", + "version": "==1.4.1" + }, + "patsy": { + "hashes": [ + "sha256:7eb5349754ed6aa982af81f636479b1b8db9d5b1a6e957a6016ec0534b5c86b7", + "sha256:bdc18001875e319bc91c812c1eb6a10be4bb13cb81eb763f466179dca3b67277" + ], + "version": "==0.5.3" + }, + "petl": { + "hashes": [ + "sha256:d4802e3c4804bf85f2267a0102fcad35c61e6a37c90d9e1a1674331f35a90a7f" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.7.14" + }, + "pexpect": { + "hashes": [ + "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", + "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f" + ], + "markers": "sys_platform != 'win32'", + "version": "==4.9.0" + }, + "pillow": { + "hashes": [ + "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d", + "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de", + "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616", + "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839", + "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099", + "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a", + "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219", + "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106", + "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b", + "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412", + "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b", + "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7", + "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2", + "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7", + "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14", + "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f", + "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27", + "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57", + "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262", + "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28", + "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610", + "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172", + "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273", + "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e", + "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d", + "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818", + "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f", + "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9", + "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01", + "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7", + "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651", + "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312", + "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80", + "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666", + "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061", + "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b", + "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992", + "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593", + "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4", + "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db", + "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba", + "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd", + "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e", + "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212", + "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb", + "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2", + "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34", + "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256", + "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f", + "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2", + "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38", + "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996", + "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a", + "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793" + ], + "markers": "python_version >= '3.8'", + "version": "==10.1.0" + }, + "platformdirs": { + "hashes": [ + "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b", + "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731" + ], + "markers": "python_version >= '3.7'", + "version": "==4.0.0" + }, + "plotly": { + "hashes": [ + "sha256:23aa8ea2f4fb364a20d34ad38235524bd9d691bf5299e800bca608c31e8db8de", + "sha256:360a31e6fbb49d12b007036eb6929521343d6bee2236f8459915821baefa2cbb" + ], + "index": "pypi", + "markers": "python_version >= '3.6'", + "version": "==5.18.0" + }, + "pluggy": { + "hashes": [ + "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12", + "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7" + ], + "markers": "python_version >= '3.8'", + "version": "==1.3.0" + }, + "prometheus-client": { + "hashes": [ + "sha256:4585b0d1223148c27a225b10dbec5ae9bc4c81a99a3fa80774fa6209935324e1", + "sha256:c88b1e6ecf6b41cd8fb5731c7ae919bf66df6ec6fafa555cd6c0e16ca169ae92" + ], + "markers": "python_version >= '3.8'", + "version": "==0.19.0" + }, + "prompt-toolkit": { + "hashes": [ + "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0", + "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==3.0.41" + }, + "protobuf": { + "hashes": [ + "sha256:0bf384e75b92c42830c0a679b0cd4d6e2b36ae0cf3dbb1e1dfdda48a244f4bcd", + "sha256:0f881b589ff449bf0b931a711926e9ddaad3b35089cc039ce1af50b21a4ae8cb", + "sha256:1484f9e692091450e7edf418c939e15bfc8fc68856e36ce399aed6889dae8bb0", + "sha256:193f50a6ab78a970c9b4f148e7c750cfde64f59815e86f686c22e26b4fe01ce7", + "sha256:3497c1af9f2526962f09329fd61a36566305e6c72da2590ae0d7d1322818843b", + "sha256:57d65074b4f5baa4ab5da1605c02be90ac20c8b40fb137d6a8df9f416b0d0ce2", + "sha256:8bdbeaddaac52d15c6dce38c71b03038ef7772b977847eb6d374fc86636fa510", + "sha256:a19731d5e83ae4737bb2a089605e636077ac001d18781b3cf489b9546c7c80d6", + "sha256:abc0525ae2689a8000837729eef7883b9391cd6aa7950249dcf5a4ede230d5dd", + "sha256:becc576b7e6b553d22cbdf418686ee4daa443d7217999125c045ad56322dda10", + "sha256:ca37bf6a6d0046272c152eea90d2e4ef34593aaa32e8873fc14c16440f22d4b7" + ], + "markers": "python_version >= '3.8'", + "version": "==4.25.1" + }, + "psutil": { + "hashes": [ + "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28", + "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017", + "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602", + "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac", + "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a", + "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9", + "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4", + "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c", + "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c", + "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c", + "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a", + "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c", + "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57", + "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a", + "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d", + "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==5.9.6" + }, + "ptyprocess": { + "hashes": [ + "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", + "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" + ], + "version": "==0.7.0" + }, + "pure-eval": { + "hashes": [ + "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", + "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3" + ], + "version": "==0.2.2" + }, + "pyarrow": { + "hashes": [ + "sha256:0ec7587d759153f452d5263dbc8b1af318c4609b607be2bd5127dcda6708cdb1", + "sha256:1765a18205eb1e02ccdedb66049b0ec148c2a0cb52ed1fb3aac322dfc086a6ee", + "sha256:1a14f57a5f472ce8234f2964cd5184cccaa8df7e04568c64edc33b23eb285dd5", + "sha256:254017ca43c45c5098b7f2a00e995e1f8346b0fb0be225f042838323bb55283c", + "sha256:42ba7c5347ce665338f2bc64685d74855900200dac81a972d49fe127e8132f75", + "sha256:443eb9409b0cf78df10ced326490e1a300205a458fbeb0767b6b31ab3ebae6b2", + "sha256:61f4c37d82fe00d855d0ab522c685262bdeafd3fbcb5fe596fe15025fbc7341b", + "sha256:668e00e3b19f183394388a687d29c443eb000fb3fe25599c9b4762a0afd37775", + "sha256:6f7a7dbe2f7f65ac1d0bd3163f756deb478a9e9afc2269557ed75b1b25ab3610", + "sha256:70acca1ece4322705652f48db65145b5028f2c01c7e426c5d16a30ba5d739c24", + "sha256:7b4ede715c004b6fc535de63ef79fa29740b4080639a5ff1ea9ca84e9282f349", + "sha256:94fb4a0c12a2ac1ed8e7e2aa52aade833772cf2d3de9dde685401b22cec30002", + "sha256:abb57334f2c57979a49b7be2792c31c23430ca02d24becd0b511cbe7b6b08649", + "sha256:b069602eb1fc09f1adec0a7bdd7897f4d25575611dfa43543c8b8a75d99d6874", + "sha256:b1fc226d28c7783b52a84d03a66573d5a22e63f8a24b841d5fc68caeed6784d4", + "sha256:ba71e6fc348c92477586424566110d332f60d9a35cb85278f42e3473bc1373da", + "sha256:bf26f809926a9d74e02d76593026f0aaeac48a65b64f1bb17eed9964bfe7ae1a", + "sha256:cb627673cb98708ef00864e2e243f51ba7b4c1b9f07a1d821f98043eccd3f585", + "sha256:d1bc6e4d5d6f69e0861d5d7f6cf4d061cf1069cb9d490040129877acf16d4c2a", + "sha256:db0c5986bf0808927f49640582d2032a07aa49828f14e51f362075f03747d198", + "sha256:e00174764a8b4e9d8d5909b6d19ee0c217a6cf0232c5682e31fdfbd5a9f0ae52", + "sha256:e141a65705ac98fa52a9113fe574fdaf87fe0316cde2dffe6b94841d3c61544c", + "sha256:e3fe5049d2e9ca661d8e43fab6ad5a4c571af12d20a57dffc392a014caebef65", + "sha256:efa59933b20183c1c13efc34bd91efc6b2997377c4c6ad9272da92d224e3beb1", + "sha256:f2d00aa481becf57098e85d99e34a25dba5a9ade2f44eb0b7d80c80f2984fc03" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==10.0.1" + }, + "pyasn1": { + "hashes": [ + "sha256:4439847c58d40b1d0a573d07e3856e95333f1976294494c325775aeca506eb58", + "sha256:6d391a96e59b23130a5cfa74d6fd7f388dbbe26cc8f1edf39fdddf08d9d6676c" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==0.5.1" + }, + "pyasn1-modules": { + "hashes": [ + "sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c", + "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==0.3.0" + }, + "pybind11": { + "hashes": [ + "sha256:00cd59116a6e8155aecd9174f37ba299d1d397ed4a6b86ac1dfe01b3e40f2cc4", + "sha256:33cdd02a6453380dd71cc70357ce388ad1ee8d32bd0e38fc22b273d050aa29b3" + ], + "markers": "python_version >= '3.6'", + "version": "==2.11.1" + }, + "pycparser": { + "hashes": [ + "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", + "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" + ], + "version": "==2.21" + }, + "pydantic": { + "extras": [ + "email" + ], + "hashes": [ + "sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548", + "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80", + "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340", + "sha256:3ecea2b9d80e5333303eeb77e180b90e95eea8f765d08c3d278cd56b00345d01", + "sha256:4b03e42ec20286f052490423682016fd80fda830d8e4119f8ab13ec7464c0132", + "sha256:4c5370a7edaac06daee3af1c8b1192e305bc102abcbf2a92374b5bc793818599", + "sha256:56e3ff861c3b9c6857579de282ce8baabf443f42ffba355bf070770ed63e11e1", + "sha256:5a1f9f747851338933942db7af7b6ee8268568ef2ed86c4185c6ef4402e80ba8", + "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe", + "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0", + "sha256:654db58ae399fe6434e55325a2c3e959836bd17a6f6a0b6ca8107ea0571d2e17", + "sha256:678bcf5591b63cc917100dc50ab6caebe597ac67e8c9ccb75e698f66038ea953", + "sha256:6cf25c1a65c27923a17b3da28a0bdb99f62ee04230c931d83e888012851f4e7f", + "sha256:75ac15385a3534d887a99c713aa3da88a30fbd6204a5cd0dc4dab3d770b9bd2f", + "sha256:75b297827b59bc229cac1a23a2f7a4ac0031068e5be0ce385be1462e7e17a35d", + "sha256:7d6f6e7305244bddb4414ba7094ce910560c907bdfa3501e9db1a7fd7eaea127", + "sha256:84bafe2e60b5e78bc64a2941b4c071a4b7404c5c907f5f5a99b0139781e69ed8", + "sha256:854223752ba81e3abf663d685f105c64150873cc6f5d0c01d3e3220bcff7d36f", + "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580", + "sha256:8ef467901d7a41fa0ca6db9ae3ec0021e3f657ce2c208e98cd511f3161c762c6", + "sha256:968ac42970f57b8344ee08837b62f6ee6f53c33f603547a55571c954a4225691", + "sha256:97cce3ae7341f7620a0ba5ef6cf043975cd9d2b81f3aa5f4ea37928269bc1b87", + "sha256:9849f031cf8a2f0a928fe885e5a04b08006d6d41876b8bbd2fc68a18f9f2e3fd", + "sha256:9f00790179497767aae6bcdc36355792c79e7bbb20b145ff449700eb076c5f96", + "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687", + "sha256:b97c1fac8c49be29486df85968682b0afa77e1b809aff74b83081cc115e52f33", + "sha256:bc0898c12f8e9c97f6cd44c0ed70d55749eaf783716896960b4ecce2edfd2d69", + "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653", + "sha256:c636925f38b8db208e09d344c7aa4f29a86bb9947495dd6b6d376ad10334fb78", + "sha256:c958d053453a1c4b1c2062b05cd42d9d5c8eb67537b8d5a7e3c3032943ecd261", + "sha256:d3a3c792a58e1622667a2837512099eac62490cdfd63bd407993aaf200a4cf1f", + "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9", + "sha256:e70ca129d2053fb8b728ee7d1af8e553a928d7e301a311094b8a0501adc8763d", + "sha256:efff03cc7a4f29d9009d1c96ceb1e7a70a65cfe86e89d34e4a5f2ab1e5693737", + "sha256:f59ef915cac80275245824e9d771ee939133be38215555e9dc90c6cb148aaeb5", + "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0" + ], + "markers": "python_version >= '3.7'", + "version": "==1.10.13" + }, + "pygments": { + "hashes": [ + "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", + "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367" + ], + "markers": "python_version >= '3.7'", + "version": "==2.17.2" + }, + "pyparsing": { + "hashes": [ + "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb", + "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db" + ], + "markers": "python_full_version >= '3.6.8'", + "version": "==3.1.1" + }, + "pyproj": { + "hashes": [ + "sha256:18faa54a3ca475bfe6255156f2f2874e9a1c8917b0004eee9f664b86ccc513d3", + "sha256:1e9fbaf920f0f9b4ee62aab832be3ae3968f33f24e2e3f7fbb8c6728ef1d9746", + "sha256:2d6ff73cc6dbbce3766b6c0bce70ce070193105d8de17aa2470009463682a8eb", + "sha256:36b64c2cb6ea1cc091f329c5bd34f9c01bb5da8c8e4492c709bda6a09f96808f", + "sha256:38a3361941eb72b82bd9a18f60c78b0df8408416f9340521df442cebfc4306e2", + "sha256:447db19c7efad70ff161e5e46a54ab9cc2399acebb656b6ccf63e4bc4a04b97a", + "sha256:44aa7c704c2b7d8fb3d483bbf75af6cb2350d30a63b144279a09b75fead501bf", + "sha256:4ba1f9b03d04d8cab24d6375609070580a26ce76eaed54631f03bab00a9c737b", + "sha256:4bc0472302919e59114aa140fd7213c2370d848a7249d09704f10f5b062031fe", + "sha256:50100b2726a3ca946906cbaa789dd0749f213abf0cbb877e6de72ca7aa50e1ae", + "sha256:5279586013b8d6582e22b6f9e30c49796966770389a9d5b85e25a4223286cd3f", + "sha256:6420ea8e7d2a88cb148b124429fba8cd2e0fae700a2d96eab7083c0928a85110", + "sha256:65ad699e0c830e2b8565afe42bd58cc972b47d829b2e0e48ad9638386d994915", + "sha256:6d227a865356f225591b6732430b1d1781e946893789a609bb34f59d09b8b0f8", + "sha256:7a27151ddad8e1439ba70c9b4b2b617b290c39395fa9ddb7411ebb0eb86d6fb0", + "sha256:80fafd1f3eb421694857f254a9bdbacd1eb22fc6c24ca74b136679f376f97d35", + "sha256:83039e5ae04e5afc974f7d25ee0870a80a6bd6b7957c3aca5613ccbe0d3e72bf", + "sha256:8b8acc31fb8702c54625f4d5a2a6543557bec3c28a0ef638778b7ab1d1772132", + "sha256:9274880263256f6292ff644ca92c46d96aa7e57a75c6df3f11d636ce845a1877", + "sha256:ab7aa4d9ff3c3acf60d4b285ccec134167a948df02347585fdd934ebad8811b4", + "sha256:c41e80ddee130450dcb8829af7118f1ab69eaf8169c4bf0ee8d52b72f098dc2f", + "sha256:db3aedd458e7f7f21d8176f0a1d924f1ae06d725228302b872885a1c34f3119e", + "sha256:e7e13c40183884ec7f94eb8e0f622f08f1d5716150b8d7a134de48c6110fee85", + "sha256:ebfbdbd0936e178091309f6cd4fcb4decd9eab12aa513cdd9add89efa3ec2882", + "sha256:fd43bd9a9b9239805f406fd82ba6b106bf4838d9ef37c167d3ed70383943ade1", + "sha256:fd93c1a0c6c4aedc77c0fe275a9f2aba4d59b8acf88cebfc19fe3c430cfabf4f", + "sha256:fffb059ba3bced6f6725961ba758649261d85ed6ce670d3e3b0a26e81cf1aa8d" + ], + "markers": "python_version >= '3.9'", + "version": "==3.6.1" + }, + "pytest": { + "hashes": [ + "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac", + "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==7.4.3" + }, + "python-dateutil": { + "hashes": [ + "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", + "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==2.8.2" + }, + "python-json-logger": { + "hashes": [ + "sha256:23e7ec02d34237c5aa1e29a070193a4ea87583bb4e7f8fd06d3de8264c4b2e1c", + "sha256:f380b826a991ebbe3de4d897aeec42760035ac760345e57b812938dc8b35e2bd" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.7" + }, + "python-slugify": { + "hashes": [ + "sha256:70ca6ea68fe63ecc8fa4fcf00ae651fc8a5d02d93dcd12ae6d4fc7ca46c4d395", + "sha256:ce0d46ddb668b3be82f4ed5e503dbc33dd815d83e2eb6824211310d3fb172a27" + ], + "markers": "python_version >= '3.7'", + "version": "==8.0.1" + }, + "python-snappy": { + "hashes": [ + "sha256:03bb511380fca2a13325b6f16fe8234c8e12da9660f0258cd45d9a02ffc916af", + "sha256:0bdb6942180660bda7f7d01f4c0def3cfc72b1c6d99aad964801775a3e379aba", + "sha256:0d489b50f49433494160c45048fe806de6b3aeab0586e497ebd22a0bab56e427", + "sha256:1a993dc8aadd901915a510fe6af5f20ae4256f527040066c22a154db8946751f", + "sha256:1d029f7051ec1bbeaa3e03030b6d8ed47ceb69cae9016f493c802a08af54e026", + "sha256:277757d5dad4e239dc1417438a0871b65b1b155beb108888e7438c27ffc6a8cc", + "sha256:2a7e528ab6e09c0d67dcb61a1730a292683e5ff9bb088950638d3170cf2a0a54", + "sha256:2aaaf618c68d8c9daebc23a20436bd01b09ee70d7fbf7072b7f38b06d2fab539", + "sha256:2be4f4550acd484912441f5f1209ba611ac399aac9355fee73611b9a0d4f949c", + "sha256:39692bedbe0b717001a99915ac0eb2d9d0bad546440d392a2042b96d813eede1", + "sha256:3fb9a88a4dd6336488f3de67ce75816d0d796dce53c2c6e4d70e0b565633c7fd", + "sha256:4038019b1bcaadde726a57430718394076c5a21545ebc5badad2c045a09546cf", + "sha256:463fd340a499d47b26ca42d2f36a639188738f6e2098c6dbf80aef0e60f461e1", + "sha256:4d3cafdf454354a621c8ab7408e45aa4e9d5c0b943b61ff4815f71ca6bdf0130", + "sha256:4ec533a8c1f8df797bded662ec3e494d225b37855bb63eb0d75464a07947477c", + "sha256:530bfb9efebcc1aab8bb4ebcbd92b54477eed11f6cf499355e882970a6d3aa7d", + "sha256:546c1a7470ecbf6239101e9aff0f709b68ca0f0268b34d9023019a55baa1f7c6", + "sha256:5843feb914796b1f0405ccf31ea0fb51034ceb65a7588edfd5a8250cb369e3b2", + "sha256:586724a0276d7a6083a17259d0b51622e492289a9998848a1b01b6441ca12b2f", + "sha256:59e975be4206cc54d0a112ef72fa3970a57c2b1bcc2c97ed41d6df0ebe518228", + "sha256:5a453c45178d7864c1bdd6bfe0ee3ed2883f63b9ba2c9bb967c6b586bf763f96", + "sha256:5bb05c28298803a74add08ba496879242ef159c75bc86a5406fac0ffc7dd021b", + "sha256:5e973e637112391f05581f427659c05b30b6843bc522a65be35ac7b18ce3dedd", + "sha256:66c80e9b366012dbee262bb1869e4fc5ba8786cda85928481528bc4a72ec2ee8", + "sha256:6a7620404da966f637b9ce8d4d3d543d363223f7a12452a575189c5355fc2d25", + "sha256:6f8bf4708a11b47517baf962f9a02196478bbb10fdb9582add4aa1459fa82380", + "sha256:735cd4528c55dbe4516d6d2b403331a99fc304f8feded8ae887cf97b67d589bb", + "sha256:7778c224efc38a40d274da4eb82a04cac27aae20012372a7db3c4bbd8926c4d4", + "sha256:8277d1f6282463c40761f802b742f833f9f2449fcdbb20a96579aa05c8feb614", + "sha256:88b6ea78b83d2796f330b0af1b70cdd3965dbdab02d8ac293260ec2c8fe340ee", + "sha256:8c07220408d3268e8268c9351c5c08041bc6f8c6172e59d398b71020df108541", + "sha256:8d0c019ee7dcf2c60e240877107cddbd95a5b1081787579bf179938392d66480", + "sha256:90b0186516b7a101c14764b0c25931b741fb0102f21253eff67847b4742dfc72", + "sha256:9837ac1650cc68d22a3cf5f15fb62c6964747d16cecc8b22431f113d6e39555d", + "sha256:9eac51307c6a1a38d5f86ebabc26a889fddf20cbba7a116ccb54ba1446601d5b", + "sha256:9f0c0d88b84259f93c3aa46398680646f2c23e43394779758d9f739c34e15295", + "sha256:a0ad38bc98d0b0497a0b0dbc29409bcabfcecff4511ed7063403c86de16927bc", + "sha256:b265cde49774752aec9ca7f5d272e3f98718164afc85521622a8a5394158a2b5", + "sha256:b6a107ab06206acc5359d4c5632bd9b22d448702a79b3169b0c62e0fb808bb2a", + "sha256:b7f920eaf46ebf41bd26f9df51c160d40f9e00b7b48471c3438cb8d027f7fb9b", + "sha256:c20498bd712b6e31a4402e1d027a1cd64f6a4a0066a3fe3c7344475886d07fdf", + "sha256:cb18d9cd7b3f35a2f5af47bb8ed6a5bdbf4f3ddee37f3daade4ab7864c292f5b", + "sha256:cf5bb9254e1c38aacf253d510d3d9be631bba21f3d068b17672b38b5cbf2fff5", + "sha256:d017775851a778ec9cc32651c4464079d06d927303c2dde9ae9830ccf6fe94e1", + "sha256:dc96668d9c7cc656609764275c5f8da58ef56d89bdd6810f6923d36497468ff7", + "sha256:e066a0586833d610c4bbddba0be5ba0e3e4f8e0bc5bb6d82103d8f8fc47bb59a", + "sha256:e3a013895c64352b49d0d8e107a84f99631b16dbab156ded33ebf0becf56c8b2", + "sha256:eaf905a580f2747c4a474040a5063cd5e0cc3d1d2d6edb65f28196186493ad4a" + ], + "index": "pypi", + "version": "==0.6.1" + }, + "pytz": { + "hashes": [ + "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b", + "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7" + ], + "version": "==2023.3.post1" + }, + "pyyaml": { + "hashes": [ + "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", + "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", + "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", + "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", + "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", + "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", + "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", + "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", + "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", + "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", + "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", + "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", + "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", + "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", + "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", + "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", + "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", + "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", + "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", + "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", + "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", + "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", + "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", + "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", + "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", + "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", + "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", + "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", + "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", + "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", + "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", + "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", + "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", + "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", + "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", + "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", + "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", + "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", + "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", + "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", + "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", + "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", + "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", + "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", + "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", + "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", + "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", + "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", + "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", + "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" + ], + "markers": "python_version >= '3.6'", + "version": "==6.0.1" + }, + "pyzmq": { + "hashes": [ + "sha256:019e59ef5c5256a2c7378f2fb8560fc2a9ff1d315755204295b2eab96b254d0a", + "sha256:034239843541ef7a1aee0c7b2cb7f6aafffb005ede965ae9cbd49d5ff4ff73cf", + "sha256:03b3f49b57264909aacd0741892f2aecf2f51fb053e7d8ac6767f6c700832f45", + "sha256:047a640f5c9c6ade7b1cc6680a0e28c9dd5a0825135acbd3569cc96ea00b2505", + "sha256:04ccbed567171579ec2cebb9c8a3e30801723c575601f9a990ab25bcac6b51e2", + "sha256:057e824b2aae50accc0f9a0570998adc021b372478a921506fddd6c02e60308e", + "sha256:11baebdd5fc5b475d484195e49bae2dc64b94a5208f7c89954e9e354fc609d8f", + "sha256:11c1d2aed9079c6b0c9550a7257a836b4a637feb334904610f06d70eb44c56d2", + "sha256:11d58723d44d6ed4dd677c5615b2ffb19d5c426636345567d6af82be4dff8a55", + "sha256:12720a53e61c3b99d87262294e2b375c915fea93c31fc2336898c26d7aed34cd", + "sha256:17ef5f01d25b67ca8f98120d5fa1d21efe9611604e8eb03a5147360f517dd1e2", + "sha256:18d43df3f2302d836f2a56f17e5663e398416e9dd74b205b179065e61f1a6edf", + "sha256:1a5d26fe8f32f137e784f768143728438877d69a586ddeaad898558dc971a5ae", + "sha256:1af379b33ef33757224da93e9da62e6471cf4a66d10078cf32bae8127d3d0d4a", + "sha256:1ccf825981640b8c34ae54231b7ed00271822ea1c6d8ba1090ebd4943759abf5", + "sha256:21eb4e609a154a57c520e3d5bfa0d97e49b6872ea057b7c85257b11e78068222", + "sha256:2243700cc5548cff20963f0ca92d3e5e436394375ab8a354bbea2b12911b20b0", + "sha256:255ca2b219f9e5a3a9ef3081512e1358bd4760ce77828e1028b818ff5610b87b", + "sha256:259c22485b71abacdfa8bf79720cd7bcf4b9d128b30ea554f01ae71fdbfdaa23", + "sha256:25f0e6b78220aba09815cd1f3a32b9c7cb3e02cb846d1cfc526b6595f6046618", + "sha256:273bc3959bcbff3f48606b28229b4721716598d76b5aaea2b4a9d0ab454ec062", + "sha256:292fe3fc5ad4a75bc8df0dfaee7d0babe8b1f4ceb596437213821f761b4589f9", + "sha256:2ca57a5be0389f2a65e6d3bb2962a971688cbdd30b4c0bd188c99e39c234f414", + "sha256:2d163a18819277e49911f7461567bda923461c50b19d169a062536fffe7cd9d2", + "sha256:2d81f1ddae3858b8299d1da72dd7d19dd36aab654c19671aa8a7e7fb02f6638a", + "sha256:2f957ce63d13c28730f7fd6b72333814221c84ca2421298f66e5143f81c9f91f", + "sha256:330f9e188d0d89080cde66dc7470f57d1926ff2fb5576227f14d5be7ab30b9fa", + "sha256:34c850ce7976d19ebe7b9d4b9bb8c9dfc7aac336c0958e2651b88cbd46682123", + "sha256:35b5ab8c28978fbbb86ea54958cd89f5176ce747c1fb3d87356cf698048a7790", + "sha256:3669cf8ee3520c2f13b2e0351c41fea919852b220988d2049249db10046a7afb", + "sha256:381469297409c5adf9a0e884c5eb5186ed33137badcbbb0560b86e910a2f1e76", + "sha256:3d0a409d3b28607cc427aa5c30a6f1e4452cc44e311f843e05edb28ab5e36da0", + "sha256:44e58a0554b21fc662f2712814a746635ed668d0fbc98b7cb9d74cb798d202e6", + "sha256:458dea649f2f02a0b244ae6aef8dc29325a2810aa26b07af8374dc2a9faf57e3", + "sha256:48e466162a24daf86f6b5ca72444d2bf39a5e58da5f96370078be67c67adc978", + "sha256:49d238cf4b69652257db66d0c623cd3e09b5d2e9576b56bc067a396133a00d4a", + "sha256:4ca1ed0bb2d850aa8471387882247c68f1e62a4af0ce9c8a1dbe0d2bf69e41fb", + "sha256:52533489f28d62eb1258a965f2aba28a82aa747202c8fa5a1c7a43b5db0e85c1", + "sha256:548d6482dc8aadbe7e79d1b5806585c8120bafa1ef841167bc9090522b610fa6", + "sha256:5619f3f5a4db5dbb572b095ea3cb5cc035335159d9da950830c9c4db2fbb6995", + "sha256:57459b68e5cd85b0be8184382cefd91959cafe79ae019e6b1ae6e2ba8a12cda7", + "sha256:5a34d2395073ef862b4032343cf0c32a712f3ab49d7ec4f42c9661e0294d106f", + "sha256:61706a6b6c24bdece85ff177fec393545a3191eeda35b07aaa1458a027ad1304", + "sha256:724c292bb26365659fc434e9567b3f1adbdb5e8d640c936ed901f49e03e5d32e", + "sha256:73461eed88a88c866656e08f89299720a38cb4e9d34ae6bf5df6f71102570f2e", + "sha256:76705c9325d72a81155bb6ab48d4312e0032bf045fb0754889133200f7a0d849", + "sha256:76c1c8efb3ca3a1818b837aea423ff8a07bbf7aafe9f2f6582b61a0458b1a329", + "sha256:77a41c26205d2353a4c94d02be51d6cbdf63c06fbc1295ea57dad7e2d3381b71", + "sha256:79986f3b4af059777111409ee517da24a529bdbd46da578b33f25580adcff728", + "sha256:7cff25c5b315e63b07a36f0c2bab32c58eafbe57d0dce61b614ef4c76058c115", + "sha256:7f7e58effd14b641c5e4dec8c7dab02fb67a13df90329e61c869b9cc607ef752", + "sha256:820c4a08195a681252f46926de10e29b6bbf3e17b30037bd4250d72dd3ddaab8", + "sha256:87e34f31ca8f168c56d6fbf99692cc8d3b445abb5bfd08c229ae992d7547a92a", + "sha256:8f03d3f0d01cb5a018debeb412441996a517b11c5c17ab2001aa0597c6d6882c", + "sha256:90f26dc6d5f241ba358bef79be9ce06de58d477ca8485e3291675436d3827cf8", + "sha256:955215ed0604dac5b01907424dfa28b40f2b2292d6493445dd34d0dfa72586a8", + "sha256:985bbb1316192b98f32e25e7b9958088431d853ac63aca1d2c236f40afb17c83", + "sha256:a382372898a07479bd34bda781008e4a954ed8750f17891e794521c3e21c2e1c", + "sha256:a882ac0a351288dd18ecae3326b8a49d10c61a68b01419f3a0b9a306190baf69", + "sha256:aa8d6cdc8b8aa19ceb319aaa2b660cdaccc533ec477eeb1309e2a291eaacc43a", + "sha256:abc719161780932c4e11aaebb203be3d6acc6b38d2f26c0f523b5b59d2fc1996", + "sha256:abf34e43c531bbb510ae7e8f5b2b1f2a8ab93219510e2b287a944432fad135f3", + "sha256:ade6d25bb29c4555d718ac6d1443a7386595528c33d6b133b258f65f963bb0f6", + "sha256:afea96f64efa98df4da6958bae37f1cbea7932c35878b185e5982821bc883369", + "sha256:b1579413ae492b05de5a6174574f8c44c2b9b122a42015c5292afa4be2507f28", + "sha256:b3451108ab861040754fa5208bca4a5496c65875710f76789a9ad27c801a0075", + "sha256:b9af3757495c1ee3b5c4e945c1df7be95562277c6e5bccc20a39aec50f826cd0", + "sha256:bc16ac425cc927d0a57d242589f87ee093884ea4804c05a13834d07c20db203c", + "sha256:c2910967e6ab16bf6fbeb1f771c89a7050947221ae12a5b0b60f3bca2ee19bca", + "sha256:c2b92812bd214018e50b6380ea3ac0c8bb01ac07fcc14c5f86a5bb25e74026e9", + "sha256:c2f20ce161ebdb0091a10c9ca0372e023ce24980d0e1f810f519da6f79c60800", + "sha256:c56d748ea50215abef7030c72b60dd723ed5b5c7e65e7bc2504e77843631c1a6", + "sha256:c7c133e93b405eb0d36fa430c94185bdd13c36204a8635470cccc200723c13bb", + "sha256:c9c6c9b2c2f80747a98f34ef491c4d7b1a8d4853937bb1492774992a120f475d", + "sha256:cbc8df5c6a88ba5ae385d8930da02201165408dde8d8322072e3e5ddd4f68e22", + "sha256:cff084c6933680d1f8b2f3b4ff5bbb88538a4aac00d199ac13f49d0698727ecb", + "sha256:d2045d6d9439a0078f2a34b57c7b18c4a6aef0bee37f22e4ec9f32456c852c71", + "sha256:d20a0ddb3e989e8807d83225a27e5c2eb2260eaa851532086e9e0fa0d5287d83", + "sha256:d457aed310f2670f59cc5b57dcfced452aeeed77f9da2b9763616bd57e4dbaae", + "sha256:d89528b4943d27029a2818f847c10c2cecc79fa9590f3cb1860459a5be7933eb", + "sha256:db0b2af416ba735c6304c47f75d348f498b92952f5e3e8bff449336d2728795d", + "sha256:deee9ca4727f53464daf089536e68b13e6104e84a37820a88b0a057b97bba2d2", + "sha256:df27ffddff4190667d40de7beba4a950b5ce78fe28a7dcc41d6f8a700a80a3c0", + "sha256:e0c95ddd4f6e9fca4e9e3afaa4f9df8552f0ba5d1004e89ef0a68e1f1f9807c7", + "sha256:e1c1be77bc5fb77d923850f82e55a928f8638f64a61f00ff18a67c7404faf008", + "sha256:e1ffa1c924e8c72778b9ccd386a7067cddf626884fd8277f503c48bb5f51c762", + "sha256:e2400a94f7dd9cb20cd012951a0cbf8249e3d554c63a9c0cdfd5cbb6c01d2dec", + "sha256:e61f091c3ba0c3578411ef505992d356a812fb200643eab27f4f70eed34a29ef", + "sha256:e8a701123029cc240cea61dd2d16ad57cab4691804143ce80ecd9286b464d180", + "sha256:eadbefd5e92ef8a345f0525b5cfd01cf4e4cc651a2cffb8f23c0dd184975d787", + "sha256:f32260e556a983bc5c7ed588d04c942c9a8f9c2e99213fec11a031e316874c7e", + "sha256:f8115e303280ba09f3898194791a153862cbf9eef722ad8f7f741987ee2a97c7", + "sha256:fedbdc753827cf014c01dbbee9c3be17e5a208dcd1bf8641ce2cd29580d1f0d4" + ], + "markers": "python_version >= '3.6'", + "version": "==25.1.1" + }, + "qdldl": { + "hashes": [ + "sha256:092f6606690a2b9bd3c939f3147887e02de13bb068fbed5ffdc7459034def623", + "sha256:0e3f06e8a49ddd834b24fc3d7afbba4fec0923101045aa2666e18d2a9980e329", + "sha256:26aa3d6f0da7779265d72e8f418094003e75fa53c515a53bc03fd8b9bcfbf7de", + "sha256:3a81c46522dd6b3042e2348fa98128bb5c0e466f42bce214e80cfb766ff40930", + "sha256:40e5d6753310377451ed4dc09b1ef28faf40108b713e7f55c8a8ae94d679a672", + "sha256:4a86155f3de66c5db0e21544b7a2421c671028fa20da407686d2a8d0e9b57e51", + "sha256:717cb1892b033c01a0aae84ededcfa1f05bcb97013095d779c497e6c32f90dac", + "sha256:718d8e141832e96ba71ca1807a74813836c6403110faaa3d33a67de1af3b29c4", + "sha256:8ab02e8b9ff86bd644a1935718387c82fbe04c31e3309cf9f7a121d02b1deda8", + "sha256:8fc35432913085d94b2327242cf51388467ef7a37ac0d71eb31b594b575dd498", + "sha256:981ca8672e9506976c663552c1eb6f6daf9726d62650b3bf5900260946156166", + "sha256:aa208703b44337a7e77f6f2663f7a452144becb4421970d534ff8297b92e1e10", + "sha256:ae161342529852b6248ace4642bc4ee371a7c1e0707b7bc43a43ef7e73c06ca3", + "sha256:b42649484f7c0d8ee659224ecaac0a3e97f12531018207f4d7323e4071320eb1", + "sha256:b8ec670d97cf756f9159dc0a11de5cf054e88aefe84bea1c7282f00334642843", + "sha256:c1dd0e570e65aaf35e10b7fb345f7ac763fd05a2227b9c06ce65e07993fc4984", + "sha256:e55bcd6962178029faf543addd49db145302dd51e19855fefa71b5fd55840eea", + "sha256:f346a114c8342ee6d4dbd6471eef314199fb268d3bf7b95885ca351fde2b023f", + "sha256:fd5cfd8c50f33ddacb830594a63b8c1093a24aea45312b9d2ed826cea5ece08a" + ], + "index": "pypi", + "version": "==0.1.7.post0" + }, + "referencing": { + "hashes": [ + "sha256:381b11e53dd93babb55696c71cf42aef2d36b8a150c49bf0bc301e36d536c882", + "sha256:cc28f2c88fbe7b961a7817a0abc034c09a1e36358f82fedb4ffdf29a25398863" + ], + "markers": "python_version >= '3.8'", + "version": "==0.31.0" + }, + "regex": { + "hashes": [ + "sha256:00ba3c9818e33f1fa974693fb55d24cdc8ebafcb2e4207680669d8f8d7cca79a", + "sha256:00e871d83a45eee2f8688d7e6849609c2ca2a04a6d48fba3dff4deef35d14f07", + "sha256:06e9abc0e4c9ab4779c74ad99c3fc10d3967d03114449acc2c2762ad4472b8ca", + "sha256:0b9ac09853b2a3e0d0082104036579809679e7715671cfbf89d83c1cb2a30f58", + "sha256:0d47840dc05e0ba04fe2e26f15126de7c755496d5a8aae4a08bda4dd8d646c54", + "sha256:0f649fa32fe734c4abdfd4edbb8381c74abf5f34bc0b3271ce687b23729299ed", + "sha256:107ac60d1bfdc3edb53be75e2a52aff7481b92817cfdddd9b4519ccf0e54a6ff", + "sha256:11175910f62b2b8c055f2b089e0fedd694fe2be3941b3e2633653bc51064c528", + "sha256:12bd4bc2c632742c7ce20db48e0d99afdc05e03f0b4c1af90542e05b809a03d9", + "sha256:16f8740eb6dbacc7113e3097b0a36065a02e37b47c936b551805d40340fb9971", + "sha256:1c0e8fae5b27caa34177bdfa5a960c46ff2f78ee2d45c6db15ae3f64ecadde14", + "sha256:2c54e23836650bdf2c18222c87f6f840d4943944146ca479858404fedeb9f9af", + "sha256:3367007ad1951fde612bf65b0dffc8fd681a4ab98ac86957d16491400d661302", + "sha256:36362386b813fa6c9146da6149a001b7bd063dabc4d49522a1f7aa65b725c7ec", + "sha256:39807cbcbe406efca2a233884e169d056c35aa7e9f343d4e78665246a332f597", + "sha256:39cdf8d141d6d44e8d5a12a8569d5a227f645c87df4f92179bd06e2e2705e76b", + "sha256:3b2c3502603fab52d7619b882c25a6850b766ebd1b18de3df23b2f939360e1bd", + "sha256:3ccf2716add72f80714b9a63899b67fa711b654be3fcdd34fa391d2d274ce767", + "sha256:3fef4f844d2290ee0ba57addcec17eec9e3df73f10a2748485dfd6a3a188cc0f", + "sha256:4023e2efc35a30e66e938de5aef42b520c20e7eda7bb5fb12c35e5d09a4c43f6", + "sha256:4a3ee019a9befe84fa3e917a2dd378807e423d013377a884c1970a3c2792d293", + "sha256:4a8bf76e3182797c6b1afa5b822d1d5802ff30284abe4599e1247be4fd6b03be", + "sha256:4a992f702c9be9c72fa46f01ca6e18d131906a7180950958f766c2aa294d4b41", + "sha256:4c34d4f73ea738223a094d8e0ffd6d2c1a1b4c175da34d6b0de3d8d69bee6bcc", + "sha256:4cd1bccf99d3ef1ab6ba835308ad85be040e6a11b0977ef7ea8c8005f01a3c29", + "sha256:4ef80829117a8061f974b2fda8ec799717242353bff55f8a29411794d635d964", + "sha256:58837f9d221744d4c92d2cf7201c6acd19623b50c643b56992cbd2b745485d3d", + "sha256:5a8f91c64f390ecee09ff793319f30a0f32492e99f5dc1c72bc361f23ccd0a9a", + "sha256:5addc9d0209a9afca5fc070f93b726bf7003bd63a427f65ef797a931782e7edc", + "sha256:6239d4e2e0b52c8bd38c51b760cd870069f0bdf99700a62cd509d7a031749a55", + "sha256:66e2fe786ef28da2b28e222c89502b2af984858091675044d93cb50e6f46d7af", + "sha256:69c0771ca5653c7d4b65203cbfc5e66db9375f1078689459fe196fe08b7b4930", + "sha256:6ac965a998e1388e6ff2e9781f499ad1eaa41e962a40d11c7823c9952c77123e", + "sha256:6c56c3d47da04f921b73ff9415fbaa939f684d47293f071aa9cbb13c94afc17d", + "sha256:6f85739e80d13644b981a88f529d79c5bdf646b460ba190bffcaf6d57b2a9863", + "sha256:706e7b739fdd17cb89e1fbf712d9dc21311fc2333f6d435eac2d4ee81985098c", + "sha256:741ba2f511cc9626b7561a440f87d658aabb3d6b744a86a3c025f866b4d19e7f", + "sha256:7434a61b158be563c1362d9071358f8ab91b8d928728cd2882af060481244c9e", + "sha256:76066d7ff61ba6bf3cb5efe2428fc82aac91802844c022d849a1f0f53820502d", + "sha256:7979b834ec7a33aafae34a90aad9f914c41fd6eaa8474e66953f3f6f7cbd4368", + "sha256:7eece6fbd3eae4a92d7c748ae825cbc1ee41a89bb1c3db05b5578ed3cfcfd7cb", + "sha256:7ef1e014eed78ab650bef9a6a9cbe50b052c0aebe553fb2881e0453717573f52", + "sha256:81dce2ddc9f6e8f543d94b05d56e70d03a0774d32f6cca53e978dc01e4fc75b8", + "sha256:82fcc1f1cc3ff1ab8a57ba619b149b907072e750815c5ba63e7aa2e1163384a4", + "sha256:8d1f21af4c1539051049796a0f50aa342f9a27cde57318f2fc41ed50b0dbc4ac", + "sha256:90a79bce019c442604662d17bf69df99090e24cdc6ad95b18b6725c2988a490e", + "sha256:9145f092b5d1977ec8c0ab46e7b3381b2fd069957b9862a43bd383e5c01d18c2", + "sha256:91dc1d531f80c862441d7b66c4505cd6ea9d312f01fb2f4654f40c6fdf5cc37a", + "sha256:979c24cbefaf2420c4e377ecd1f165ea08cc3d1fbb44bdc51bccbbf7c66a2cb4", + "sha256:994645a46c6a740ee8ce8df7911d4aee458d9b1bc5639bc968226763d07f00fa", + "sha256:9b98b7681a9437262947f41c7fac567c7e1f6eddd94b0483596d320092004533", + "sha256:9c6b4d23c04831e3ab61717a707a5d763b300213db49ca680edf8bf13ab5d91b", + "sha256:9c6d0ced3c06d0f183b73d3c5920727268d2201aa0fe6d55c60d68c792ff3588", + "sha256:9fd88f373cb71e6b59b7fa597e47e518282455c2734fd4306a05ca219a1991b0", + "sha256:a8f4e49fc3ce020f65411432183e6775f24e02dff617281094ba6ab079ef0915", + "sha256:a9e908ef5889cda4de038892b9accc36d33d72fb3e12c747e2799a0e806ec841", + "sha256:ad08a69728ff3c79866d729b095872afe1e0557251da4abb2c5faff15a91d19a", + "sha256:adbccd17dcaff65704c856bd29951c58a1bd4b2b0f8ad6b826dbd543fe740988", + "sha256:b0c7d2f698e83f15228ba41c135501cfe7d5740181d5903e250e47f617eb4292", + "sha256:b3ab05a182c7937fb374f7e946f04fb23a0c0699c0450e9fb02ef567412d2fa3", + "sha256:b6104f9a46bd8743e4f738afef69b153c4b8b592d35ae46db07fc28ae3d5fb7c", + "sha256:ba7cd6dc4d585ea544c1412019921570ebd8a597fabf475acc4528210d7c4a6f", + "sha256:bc72c231f5449d86d6c7d9cc7cd819b6eb30134bb770b8cfdc0765e48ef9c420", + "sha256:bce8814b076f0ce5766dc87d5a056b0e9437b8e0cd351b9a6c4e1134a7dfbda9", + "sha256:be5e22bbb67924dea15039c3282fa4cc6cdfbe0cbbd1c0515f9223186fc2ec5f", + "sha256:be6b7b8d42d3090b6c80793524fa66c57ad7ee3fe9722b258aec6d0672543fd0", + "sha256:bfe50b61bab1b1ec260fa7cd91106fa9fece57e6beba05630afe27c71259c59b", + "sha256:bff507ae210371d4b1fe316d03433ac099f184d570a1a611e541923f78f05037", + "sha256:c148bec483cc4b421562b4bcedb8e28a3b84fcc8f0aa4418e10898f3c2c0eb9b", + "sha256:c15ad0aee158a15e17e0495e1e18741573d04eb6da06d8b84af726cfc1ed02ee", + "sha256:c2169b2dcabf4e608416f7f9468737583ce5f0a6e8677c4efbf795ce81109d7c", + "sha256:c55853684fe08d4897c37dfc5faeff70607a5f1806c8be148f1695be4a63414b", + "sha256:c65a3b5330b54103e7d21cac3f6bf3900d46f6d50138d73343d9e5b2900b2353", + "sha256:c7964c2183c3e6cce3f497e3a9f49d182e969f2dc3aeeadfa18945ff7bdd7051", + "sha256:cc3f1c053b73f20c7ad88b0d1d23be7e7b3901229ce89f5000a8399746a6e039", + "sha256:ce615c92d90df8373d9e13acddd154152645c0dc060871abf6bd43809673d20a", + "sha256:d29338556a59423d9ff7b6eb0cb89ead2b0875e08fe522f3e068b955c3e7b59b", + "sha256:d8a993c0a0ffd5f2d3bda23d0cd75e7086736f8f8268de8a82fbc4bd0ac6791e", + "sha256:d9c727bbcf0065cbb20f39d2b4f932f8fa1631c3e01fcedc979bd4f51fe051c5", + "sha256:dac37cf08fcf2094159922edc7a2784cfcc5c70f8354469f79ed085f0328ebdf", + "sha256:dd829712de97753367153ed84f2de752b86cd1f7a88b55a3a775eb52eafe8a94", + "sha256:e54ddd0bb8fb626aa1f9ba7b36629564544954fff9669b15da3610c22b9a0991", + "sha256:e77c90ab5997e85901da85131fd36acd0ed2221368199b65f0d11bca44549711", + "sha256:ebedc192abbc7fd13c5ee800e83a6df252bec691eb2c4bedc9f8b2e2903f5e2a", + "sha256:ef71561f82a89af6cfcbee47f0fabfdb6e63788a9258e913955d89fdd96902ab", + "sha256:f0a47efb1dbef13af9c9a54a94a0b814902e547b7f21acb29434504d18f36e3a", + "sha256:f4f2ca6df64cbdd27f27b34f35adb640b5d2d77264228554e68deda54456eb11", + "sha256:fb02e4257376ae25c6dd95a5aec377f9b18c09be6ebdefa7ad209b9137b73d48" + ], + "markers": "python_version >= '3.7'", + "version": "==2023.10.3" + }, + "requests": { + "hashes": [ + "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", + "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==2.31.0" + }, + "requests-oauthlib": { + "hashes": [ + "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5", + "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.3.1" + }, + "rfc3339-validator": { + "hashes": [ + "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", + "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.1.4" + }, + "rfc3986": { + "hashes": [ + "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", + "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.0" + }, + "rfc3986-validator": { + "hashes": [ + "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", + "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.1.1" + }, + "rich": { + "hashes": [ + "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa", + "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235" + ], + "version": "==13.7.0" + }, + "rpds-py": { + "hashes": [ + "sha256:0290712eb5603a725769b5d857f7cf15cf6ca93dda3128065bbafe6fdb709beb", + "sha256:032c242a595629aacace44128f9795110513ad27217b091e834edec2fb09e800", + "sha256:08832078767545c5ee12561ce980714e1e4c6619b5b1e9a10248de60cddfa1fd", + "sha256:08b335fb0c45f0a9e2478a9ece6a1bfb00b6f4c4780f9be3cf36479c5d8dd374", + "sha256:0b70c1f800059c92479dc94dda41288fd6607f741f9b1b8f89a21a86428f6383", + "sha256:0d9f8930092558fd15c9e07198625efb698f7cc00b3dc311c83eeec2540226a8", + "sha256:181ee352691c4434eb1c01802e9daa5edcc1007ff15023a320e2693fed6a661b", + "sha256:19f5aa7f5078d35ed8e344bcba40f35bc95f9176dddb33fc4f2084e04289fa63", + "sha256:1a3b2583c86bbfbf417304eeb13400ce7f8725376dc7d3efbf35dc5d7052ad48", + "sha256:1c9a1dc5e898ce30e2f9c0aa57181cddd4532b22b7780549441d6429d22d3b58", + "sha256:1f36a1e80ef4ed1996445698fd91e0d3e54738bf597c9995118b92da537d7a28", + "sha256:20147996376be452cd82cd6c17701daba69a849dc143270fa10fe067bb34562a", + "sha256:249c8e0055ca597707d71c5ad85fd2a1c8fdb99386a8c6c257e1b47b67a9bec1", + "sha256:2647192facf63be9ed2d7a49ceb07efe01dc6cfb083bd2cc53c418437400cb99", + "sha256:264f3a5906c62b9df3a00ad35f6da1987d321a053895bd85f9d5c708de5c0fbf", + "sha256:2abd669a39be69cdfe145927c7eb53a875b157740bf1e2d49e9619fc6f43362e", + "sha256:2b2415d5a7b7ee96aa3a54d4775c1fec140476a17ee12353806297e900eaeddc", + "sha256:2c173f529666bab8e3f948b74c6d91afa22ea147e6ebae49a48229d9020a47c4", + "sha256:2da81c1492291c1a90987d76a47c7b2d310661bf7c93a9de0511e27b796a8b46", + "sha256:2eca04a365be380ca1f8fa48b334462e19e3382c0bb7386444d8ca43aa01c481", + "sha256:37b08df45f02ff1866043b95096cbe91ac99de05936dd09d6611987a82a3306a", + "sha256:37f79f4f1f06cc96151f4a187528c3fd4a7e1065538a4af9eb68c642365957f7", + "sha256:3dd5fb7737224e1497c886fb3ca681c15d9c00c76171f53b3c3cc8d16ccfa7fb", + "sha256:3e3ac5b602fea378243f993d8b707189f9061e55ebb4e56cb9fdef8166060f28", + "sha256:3f55ae773abd96b1de25fc5c3fb356f491bd19116f8f854ba705beffc1ddc3c5", + "sha256:4011d5c854aa804c833331d38a2b6f6f2fe58a90c9f615afdb7aa7cf9d31f721", + "sha256:4145172ab59b6c27695db6d78d040795f635cba732cead19c78cede74800949a", + "sha256:42b9535aa22ab023704cfc6533e968f7e420affe802d85e956d8a7b4c0b0b5ea", + "sha256:46a07a258bda12270de02b34c4884f200f864bba3dcd6e3a37fef36a168b859d", + "sha256:4f13d3f6585bd07657a603780e99beda96a36c86acaba841f131e81393958336", + "sha256:528e2afaa56d815d2601b857644aeb395afe7e59212ab0659906dc29ae68d9a6", + "sha256:545e94c84575057d3d5c62634611858dac859702b1519b6ffc58eca7fb1adfcf", + "sha256:577d40a72550eac1386b77b43836151cb61ff6700adacda2ad4d883ca5a0b6f2", + "sha256:5967fa631d0ed9f8511dede08bc943a9727c949d05d1efac4ac82b2938024fb7", + "sha256:5b769396eb358d6b55dbf78f3f7ca631ca1b2fe02136faad5af74f0111b4b6b7", + "sha256:63c9e2794329ef070844ff9bfc012004aeddc0468dc26970953709723f76c8a5", + "sha256:6574f619e8734140d96c59bfa8a6a6e7a3336820ccd1bfd95ffa610673b650a2", + "sha256:6bfe72b249264cc1ff2f3629be240d7d2fdc778d9d298087cdec8524c91cd11f", + "sha256:736817dbbbd030a69a1faf5413a319976c9c8ba8cdcfa98c022d3b6b2e01eca6", + "sha256:74a2044b870df7c9360bb3ce7e12f9ddf8e72e49cd3a353a1528cbf166ad2383", + "sha256:74be3b215a5695690a0f1a9f68b1d1c93f8caad52e23242fcb8ba56aaf060281", + "sha256:76a8374b294e4ccb39ccaf11d39a0537ed107534139c00b4393ca3b542cc66e5", + "sha256:7ba239bb37663b2b4cd08e703e79e13321512dccd8e5f0e9451d9e53a6b8509a", + "sha256:7c40851b659d958c5245c1236e34f0d065cc53dca8d978b49a032c8e0adfda6e", + "sha256:7cf241dbb50ea71c2e628ab2a32b5bfcd36e199152fc44e5c1edb0b773f1583e", + "sha256:7cfae77da92a20f56cf89739a557b76e5c6edc094f6ad5c090b9e15fbbfcd1a4", + "sha256:7d152ec7bb431040af2500e01436c9aa0d993f243346f0594a15755016bf0be1", + "sha256:80080972e1d000ad0341c7cc58b6855c80bd887675f92871221451d13a975072", + "sha256:82dbcd6463e580bcfb7561cece35046aaabeac5a9ddb775020160b14e6c58a5d", + "sha256:8308a8d49d1354278d5c068c888a58d7158a419b2e4d87c7839ed3641498790c", + "sha256:839676475ac2ccd1532d36af3d10d290a2ca149b702ed464131e450a767550df", + "sha256:83feb0f682d75a09ddc11aa37ba5c07dd9b824b22915207f6176ea458474ff75", + "sha256:88956c993a20201744282362e3fd30962a9d86dc4f1dcf2bdb31fab27821b61f", + "sha256:8a6ad8429340e0a4de89353447c6441329def3632e7b2293a7d6e873217d3c2b", + "sha256:8ba9fbc5d6e36bfeb5292530321cc56c4ef3f98048647fabd8f57543c34174ec", + "sha256:8c1f6c8df23be165eb0cb78f305483d00c6827a191e3a38394c658d5b9c80bbd", + "sha256:91276caef95556faeb4b8f09fe4439670d3d6206fee78d47ddb6e6de837f0b4d", + "sha256:960e7e460fda2d0af18c75585bbe0c99f90b8f09963844618a621b804f8c3abe", + "sha256:9656a09653b18b80764647d585750df2dff8928e03a706763ab40ec8c4872acc", + "sha256:9cd935c0220d012a27c20135c140f9cdcbc6249d5954345c81bfb714071b985c", + "sha256:a2b3c79586636f1fa69a7bd59c87c15fca80c0d34b5c003d57f2f326e5276575", + "sha256:a4b9d3f5c48bbe8d9e3758e498b3c34863f2c9b1ac57a4e6310183740e59c980", + "sha256:a8c2bf286e5d755a075e5e97ba56b3de08cccdad6b323ab0b21cc98875176b03", + "sha256:a90031658805c63fe488f8e9e7a88b260ea121ba3ee9cdabcece9c9ddb50da39", + "sha256:ad666a904212aa9a6c77da7dce9d5170008cda76b7776e6731928b3f8a0d40fa", + "sha256:af2d1648eb625a460eee07d3e1ea3a4a6e84a1fb3a107f6a8e95ac19f7dcce67", + "sha256:b3d4b390ee70ca9263b331ccfaf9819ee20e90dfd0201a295e23eb64a005dbef", + "sha256:ba4432301ad7eeb1b00848cf46fae0e5fecfd18a8cb5fdcf856c67985f79ecc7", + "sha256:bc3179e0815827cf963e634095ae5715ee73a5af61defbc8d6ca79f1bdae1d1d", + "sha256:c5fd099acaee2325f01281a130a39da08d885e4dedf01b84bf156ec2737d78fe", + "sha256:c797ea56f36c6f248656f0223b11307fdf4a1886f3555eba371f34152b07677f", + "sha256:cd4ea56c9542ad0091dfdef3e8572ae7a746e1e91eb56c9e08b8d0808b40f1d1", + "sha256:cdd6f8738e1f1d9df5b1603bb03cb30e442710e5672262b95d0f9fcb4edb0dab", + "sha256:d0580faeb9def6d0beb7aa666294d5604e569c4e24111ada423cf9936768d95c", + "sha256:d11afdc5992bbd7af60ed5eb519873690d921425299f51d80aa3099ed49f2bcc", + "sha256:d1d388d2f5f5a6065cf83c54dd12112b7389095669ff395e632003ae8999c6b8", + "sha256:d20da6b4c7aa9ee75ad0730beaba15d65157f5beeaca54a038bb968f92bf3ce3", + "sha256:d22e0660de24bd8e9ac82f4230a22a5fe4e397265709289d61d5fb333839ba50", + "sha256:d22f2cb82e0b40e427a74a93c9a4231335bbc548aed79955dde0b64ea7f88146", + "sha256:d4fa1eeb9bea6d9b64ac91ec51ee94cc4fc744955df5be393e1c923c920db2b0", + "sha256:d9793d46d3e6522ae58e9321032827c9c0df1e56cbe5d3de965facb311aed6aa", + "sha256:dab979662da1c9fbb464e310c0b06cb5f1d174d09a462553af78f0bfb3e01920", + "sha256:db8d0f0ad92f74feb61c4e4a71f1d573ef37c22ef4dc19cab93e501bfdad8cbd", + "sha256:df2af1180b8eeececf4f819d22cc0668bfadadfd038b19a90bd2fb2ee419ec6f", + "sha256:dfb5d2ab183c0efe5e7b8917e4eaa2e837aacafad8a69b89aa6bc81550eed857", + "sha256:e04f8c76b8d5c70695b4e8f1d0b391d8ef91df00ef488c6c1ffb910176459bc6", + "sha256:e4a45ba34f904062c63049a760790c6a2fa7a4cc4bd160d8af243b12371aaa05", + "sha256:e9be1f7c5f9673616f875299339984da9447a40e3aea927750c843d6e5e2e029", + "sha256:edc91c50e17f5cd945d821f0f1af830522dba0c10267c3aab186dc3dbaab8def", + "sha256:ee70ee5f4144a45a9e6169000b5b525d82673d5dab9f7587eccc92794814e7ac", + "sha256:f1059ca9a51c936c9a8d46fbc2c9a6b4c15ab3f13a97f1ad32f024b39666ba85", + "sha256:f47eef55297799956464efc00c74ae55c48a7b68236856d56183fe1ddf866205", + "sha256:f4ae6f423cb7d1c6256b7482025ace2825728f53b7ac58bcd574de6ee9d242c2", + "sha256:f4b15a163448ec79241fb2f1bc5a8ae1a4a304f7a48d948d208a2935b26bf8a5", + "sha256:f55601fb58f92e4f4f1d05d80c24cb77505dc42103ddfd63ddfdc51d3da46fa2", + "sha256:fa84bbe22ffa108f91631935c28a623001e335d66e393438258501e618fb0dde", + "sha256:faa12a9f34671a30ea6bb027f04ec4e1fb8fa3fb3ed030893e729d4d0f3a9791", + "sha256:fcfd5f91b882eedf8d9601bd21261d6ce0e61a8c66a7152d1f5df08d3f643ab1", + "sha256:fe30ef31172bdcf946502a945faad110e8fff88c32c4bec9a593df0280e64d8a" + ], + "markers": "python_version >= '3.8'", + "version": "==0.13.1" + }, + "rsa": { + "hashes": [ + "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7", + "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21" + ], + "markers": "python_version >= '3.6' and python_version < '4'", + "version": "==4.9" + }, + "ruff": { + "hashes": [ + "sha256:03910e81df0d8db0e30050725a5802441c2022ea3ae4fe0609b76081731accbc", + "sha256:05991ee20d4ac4bb78385360c684e4b417edd971030ab12a4fbd075ff535050e", + "sha256:137852105586dcbf80c1717facb6781555c4e99f520c9c827bd414fac67ddfb6", + "sha256:1610e14750826dfc207ccbcdd7331b6bd285607d4181df9c1c6ae26646d6848a", + "sha256:1b09f29b16c6ead5ea6b097ef2764b42372aebe363722f1605ecbcd2b9207184", + "sha256:1cf5f701062e294f2167e66d11b092bba7af6a057668ed618a9253e1e90cfd76", + "sha256:3a0cd909d25f227ac5c36d4e7e681577275fb74ba3b11d288aff7ec47e3ae745", + "sha256:4558b3e178145491e9bc3b2ee3c4b42f19d19384eaa5c59d10acf6e8f8b57e33", + "sha256:491262006e92f825b145cd1e52948073c56560243b55fb3b4ecb142f6f0e9543", + "sha256:5c549ed437680b6105a1299d2cd30e4964211606eeb48a0ff7a93ef70b902248", + "sha256:683aa5bdda5a48cb8266fcde8eea2a6af4e5700a392c56ea5fb5f0d4bfdc0240", + "sha256:87455a0c1f739b3c069e2f4c43b66479a54dea0276dd5d4d67b091265f6fd1dc", + "sha256:88b8cdf6abf98130991cbc9f6438f35f6e8d41a02622cc5ee130a02a0ed28703", + "sha256:bd98138a98d48a1c36c394fd6b84cd943ac92a08278aa8ac8c0fdefcf7138f35", + "sha256:e8fd1c62a47aa88a02707b5dd20c5ff20d035d634aa74826b42a1da77861b5ff", + "sha256:ea284789861b8b5ca9d5443591a92a397ac183d4351882ab52f6296b4fdd5462", + "sha256:fd89b45d374935829134a082617954120d7a1470a9f0ec0e7f3ead983edc48cc" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==0.1.6" + }, + "s3transfer": { + "hashes": [ + "sha256:d1c52af7bceca1650d0f27728b29bb4925184aead7b55bccacf893b79a108604", + "sha256:e6cafd5643fc7b44fddfba1e5b521005675b0e07533ddad958a3554bc87d7330" + ], + "markers": "python_version >= '3.7'", + "version": "==0.8.1" + }, + "scikit-learn": { + "hashes": [ + "sha256:065e9673e24e0dc5113e2dd2b4ca30c9d8aa2fa90f4c0597241c93b63130d233", + "sha256:2dd3ffd3950e3d6c0c0ef9033a9b9b32d910c61bd06cb8206303fb4514b88a49", + "sha256:2e2642baa0ad1e8f8188917423dd73994bf25429f8893ddbe115be3ca3183584", + "sha256:44b47a305190c28dd8dd73fc9445f802b6ea716669cfc22ab1eb97b335d238b1", + "sha256:6477eed40dbce190f9f9e9d0d37e020815825b300121307942ec2110302b66a3", + "sha256:6fe83b676f407f00afa388dd1fdd49e5c6612e551ed84f3b1b182858f09e987d", + "sha256:7d5312d9674bed14f73773d2acf15a3272639b981e60b72c9b190a0cffed5bad", + "sha256:7f69313884e8eb311460cc2f28676d5e400bd929841a2c8eb8742ae78ebf7c20", + "sha256:8156db41e1c39c69aa2d8599ab7577af53e9e5e7a57b0504e116cc73c39138dd", + "sha256:8429aea30ec24e7a8c7ed8a3fa6213adf3814a6efbea09e16e0a0c71e1a1a3d7", + "sha256:8b0670d4224a3c2d596fd572fb4fa673b2a0ccfb07152688ebd2ea0b8c61025c", + "sha256:953236889928d104c2ef14027539f5f2609a47ebf716b8cbe4437e85dce42744", + "sha256:99cc01184e347de485bf253d19fcb3b1a3fb0ee4cea5ee3c43ec0cc429b6d29f", + "sha256:9c710ff9f9936ba8a3b74a455ccf0dcf59b230caa1e9ba0223773c490cab1e51", + "sha256:ad66c3848c0a1ec13464b2a95d0a484fd5b02ce74268eaa7e0c697b904f31d6c", + "sha256:bf036ea7ef66115e0d49655f16febfa547886deba20149555a41d28f56fd6d3c", + "sha256:dfeaf8be72117eb61a164ea6fc8afb6dfe08c6f90365bde2dc16456e4bc8e45f", + "sha256:e6e574db9914afcb4e11ade84fab084536a895ca60aadea3041e85b8ac963edb", + "sha256:ea061bf0283bf9a9f36ea3c5d3231ba2176221bbd430abd2603b1c3b2ed85c89", + "sha256:fe0aa1a7029ed3e1dcbf4a5bc675aa3b1bc468d9012ecf6c6f081251ca47f590", + "sha256:fe175ee1dab589d2e1033657c5b6bec92a8a3b69103e3dd361b58014729975c3" + ], + "markers": "python_version >= '3.8'", + "version": "==1.2.2" + }, + "scipy": { + "hashes": [ + "sha256:049a8bbf0ad95277ffba9b3b7d23e5369cc39e66406d60422c8cfef40ccc8415", + "sha256:07c3457ce0b3ad5124f98a86533106b643dd811dd61b548e78cf4c8786652f6f", + "sha256:0f1564ea217e82c1bbe75ddf7285ba0709ecd503f048cb1236ae9995f64217bd", + "sha256:1553b5dcddd64ba9a0d95355e63fe6c3fc303a8fd77c7bc91e77d61363f7433f", + "sha256:15a35c4242ec5f292c3dd364a7c71a61be87a3d4ddcc693372813c0b73c9af1d", + "sha256:1b4735d6c28aad3cdcf52117e0e91d6b39acd4272f3f5cd9907c24ee931ad601", + "sha256:2cf9dfb80a7b4589ba4c40ce7588986d6d5cebc5457cad2c2880f6bc2d42f3a5", + "sha256:39becb03541f9e58243f4197584286e339029e8908c46f7221abeea4b749fa88", + "sha256:43b8e0bcb877faf0abfb613d51026cd5cc78918e9530e375727bf0625c82788f", + "sha256:4b3f429188c66603a1a5c549fb414e4d3bdc2a24792e061ffbd607d3d75fd84e", + "sha256:4c0ff64b06b10e35215abce517252b375e580a6125fd5fdf6421b98efbefb2d2", + "sha256:51af417a000d2dbe1ec6c372dfe688e041a7084da4fdd350aeb139bd3fb55353", + "sha256:5678f88c68ea866ed9ebe3a989091088553ba12c6090244fdae3e467b1139c35", + "sha256:79c8e5a6c6ffaf3a2262ef1be1e108a035cf4f05c14df56057b64acc5bebffb6", + "sha256:7ff7f37b1bf4417baca958d254e8e2875d0cc23aaadbe65b3d5b3077b0eb23ea", + "sha256:aaea0a6be54462ec027de54fca511540980d1e9eea68b2d5c1dbfe084797be35", + "sha256:bce5869c8d68cf383ce240e44c1d9ae7c06078a9396df68ce88a1230f93a30c1", + "sha256:cd9f1027ff30d90618914a64ca9b1a77a431159df0e2a195d8a9e8a04c78abf9", + "sha256:d925fa1c81b772882aa55bcc10bf88324dadb66ff85d548c71515f6689c6dac5", + "sha256:e7354fd7527a4b0377ce55f286805b34e8c54b91be865bac273f527e1b839019", + "sha256:fae8a7b898c42dffe3f7361c40d5952b6bf32d10c4569098d276b4c547905ee1" + ], + "markers": "python_version < '3.12' and python_version >= '3.8'", + "version": "==1.10.1" + }, + "scs": { + "hashes": [ + "sha256:18788befa5284bb1f49149bac7f813703de60ef5b6bf7698a9f1c3a5a49b78e4", + "sha256:2a2337acb0604770b6df1473254065a51c210ff9c82fc7c4490595510287a337", + "sha256:37c23b4299ab77ff5f654573d5667dc982292a8ef2b979053b38c40663919f13", + "sha256:40294e22bfe509bdf7fd65a6b77c38cec22dcb3567ff5a75f3c41a1faf2ef1d5", + "sha256:424710bc19b0506feee7e05e6d2b7af98acf09af5bd5353126164cbd46ac923f", + "sha256:4b5259137c263304effa2b28d0125437ac23569e6e7753c115ae1206ec5033fd", + "sha256:51fed30d2a4a1e6fbfc1e52b4cb3adeecbe89d7c47f3539b49afbb852415fe19", + "sha256:534519819eea96f18902a9fce15c4ec562b99d23b38dc843a48cb137b5641613", + "sha256:7015d7a56d1d5b53264fd277289ea169949309e26101677ff88cd0e5030d032f", + "sha256:8689e75a57e59846e65d1c4b9d57e9964b00fcbb8e67fc77f98cf6e0a0530abd", + "sha256:8b3a622cf2120ae765f0f3ad5c6f4f86796d317e29132bab2ad4af3c14d9bf4d", + "sha256:8d04ee4d19ac6d0f5053663bc48fcd5c5faed534272f13b10a4e173c814eea69", + "sha256:a28af160a44268e726a59d6cf340629b82940c1a643c4c87fe777e9cbe550d75", + "sha256:ad991b00d0a87c85db57bf2f1863c21bdc4e2f13837f6c35e809f5936bc6f165", + "sha256:ae4624938d3e3a8b7e508029275c6ad7a978fd48c158d0818f69f4ae764bf945", + "sha256:cea0f7e9473f43f7edf1641d020ead7e39653a81c540fbdba8f3b7b8480038c9", + "sha256:e21bdc8046648846e2c204a6c5cf24eaaedd2b8f5e0a2ab41a647b0247b8d592", + "sha256:eb0524c0b9c3ed0d65dae161475accf3efa8e170938eb93251a60e9709b156ee", + "sha256:f6126f1d7ed5ff368cb8c1836715b17a50074314579eefc6d511995a3ab93d70", + "sha256:f6283f725f3fee63d4631c2532d01a5b2ea65883b04d3da3be06084b1c60171b" + ], + "markers": "python_version >= '3.7'", + "version": "==3.2.4.post1" + }, + "seaborn": { + "hashes": [ + "sha256:0e76abd2ec291c655b516703c6a022f0fd5afed26c8e714e8baef48150f73598", + "sha256:70d740828c48de0f402bb17234e475eda687e3c65f4383ea25d0cc4728f7772e" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==0.13.0" + }, + "send2trash": { + "hashes": [ + "sha256:a384719d99c07ce1eefd6905d2decb6f8b7ed054025bb0e618919f945de4f679", + "sha256:c132d59fa44b9ca2b1699af5c86f57ce9f4c5eb56629d5d55fbb7a35f84e2312" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.8.2" + }, + "setuptools": { + "hashes": [ + "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2", + "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6" + ], + "markers": "python_version >= '3.8'", + "version": "==69.0.2" + }, + "shapely": { + "hashes": [ + "sha256:03e63a99dfe6bd3beb8d5f41ec2086585bb969991d603f9aeac335ad396a06d4", + "sha256:0521d76d1e8af01e712db71da9096b484f081e539d4f4a8c97342e7971d5e1b4", + "sha256:06f193091a7c6112fc08dfd195a1e3846a64306f890b151fa8c63b3e3624202c", + "sha256:084b023dae8ad3d5b98acee9d3bf098fdf688eb0bb9b1401e8b075f6a627b611", + "sha256:1713cc04c171baffc5b259ba8531c58acc2a301707b7f021d88a15ed090649e7", + "sha256:1f217d28ecb48e593beae20a0082a95bd9898d82d14b8fcb497edf6bff9a44d7", + "sha256:2d217e56ae067e87b4e1731d0dc62eebe887ced729ba5c2d4590e9e3e9fdbd88", + "sha256:34eac2337cbd67650248761b140d2535855d21b969d76d76123317882d3a0c1a", + "sha256:36480e32c434d168cdf2f5e9862c84aaf4d714a43a8465ae3ce8ff327f0affb7", + "sha256:394e5085b49334fd5b94fa89c086edfb39c3ecab7f669e8b2a4298b9d523b3a5", + "sha256:42997ac806e4583dad51c80a32d38570fd9a3d4778f5e2c98f9090aa7db0fe91", + "sha256:45ac6906cff0765455a7b49c1670af6e230c419507c13e2f75db638c8fc6f3bd", + "sha256:4ef753200cbffd4f652efb2c528c5474e5a14341a473994d90ad0606522a46a2", + "sha256:5324be299d4c533ecfcfd43424dfd12f9428fd6f12cda38a4316da001d6ef0ea", + "sha256:5b0c052709c8a257c93b0d4943b0b7a3035f87e2d6a8ac9407b6a992d206422f", + "sha256:6a21353d28209fb0d8cc083e08ca53c52666e0d8a1f9bbe23b6063967d89ed24", + "sha256:6ca8cffbe84ddde8f52b297b53f8e0687bd31141abb2c373fd8a9f032df415d6", + "sha256:72b5997272ae8c25f0fd5b3b967b3237e87fab7978b8d6cd5fa748770f0c5d68", + "sha256:737dba15011e5a9b54a8302f1748b62daa207c9bc06f820cd0ad32a041f1c6f2", + "sha256:78128357a0cee573257a0c2c388d4b7bf13cb7dbe5b3fe5d26d45ebbe2a39e25", + "sha256:794affd80ca0f2c536fc948a3afa90bd8fb61ebe37fe873483ae818e7f21def4", + "sha256:7e92e7c255f89f5cdf777690313311f422aa8ada9a3205b187113274e0135cd8", + "sha256:87dc2be34ac3a3a4a319b963c507ac06682978a5e6c93d71917618b14f13066e", + "sha256:94ac128ae2ab4edd0bffcd4e566411ea7bdc738aeaf92c32a8a836abad725f9f", + "sha256:a5533a925d8e211d07636ffc2fdd9a7f9f13d54686d00577eeb11d16f00be9c4", + "sha256:a9a41ff4323fc9d6257759c26eb1cf3a61ebc7e611e024e6091f42977303fd3a", + "sha256:b8eb0a92f7b8c74f9d8fdd1b40d395113f59bd8132ca1348ebcc1f5aece94b96", + "sha256:baa14fc27771e180c06b499a0a7ba697c7988c7b2b6cba9a929a19a4d2762de3", + "sha256:be46d5509b9251dd9087768eaf35a71360de6afac82ce87c636990a0871aa18b", + "sha256:c6fd29fbd9cd76350bd5cc14c49de394a31770aed02d74203e23b928f3d2f1aa", + "sha256:ccfd5fa10a37e67dbafc601c1ddbcbbfef70d34c3f6b0efc866ddbdb55893a6c", + "sha256:d41a116fcad58048d7143ddb01285e1a8780df6dc1f56c3b1e1b7f12ed296651", + "sha256:dc9342fc82e374130db86a955c3c4525bfbf315a248af8277a913f30911bed9e", + "sha256:dea9a0651333cf96ef5bb2035044e3ad6a54f87d90e50fe4c2636debf1b77abc", + "sha256:e7c95d3379ae3abb74058938a9fcbc478c6b2e28d20dace38f8b5c587dde90aa", + "sha256:e7d897e6bdc6bc64f7f65155dbbb30e49acaabbd0d9266b9b4041f87d6e52b3a", + "sha256:ea84d1cdbcf31e619d672b53c4532f06253894185ee7acb8ceb78f5f33cbe033", + "sha256:ed1e99702125e7baccf401830a3b94d810d5c70b329b765fe93451fe14cf565b", + "sha256:eebe544df5c018134f3c23b6515877f7e4cd72851f88a8d0c18464f414d141a2", + "sha256:fa3ee28f5e63a130ec5af4dc3c4cb9c21c5788bb13c15e89190d163b14f9fb89", + "sha256:fd3ad17b64466a033848c26cb5b509625c87d07dcf39a1541461cacdb8f7e91c" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.2" + }, + "shellingham": { + "hashes": [ + "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", + "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de" + ], + "version": "==1.5.4" + }, + "simpleeval": { + "hashes": [ + "sha256:22a2701a5006e4188d125d34accf2405c2c37c93f6b346f2484b6422415ae54a", + "sha256:4a30f9cc01825fe4c719c785e3762623e350c4840d5e6855c2a8496baaa65fac" + ], + "version": "==0.9.13" + }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==1.16.0" + }, + "sniffio": { + "hashes": [ + "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101", + "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0" + }, + "soupsieve": { + "hashes": [ + "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690", + "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7" + ], + "markers": "python_version >= '3.8'", + "version": "==2.5" + }, + "sqlalchemy": { + "hashes": [ + "sha256:0b7dbe6369677a2bea68fe9812c6e4bbca06ebfa4b5cde257b2b0bf208709131", + "sha256:128a948bd40780667114b0297e2cc6d657b71effa942e0a368d8cc24293febb3", + "sha256:14b0cacdc8a4759a1e1bd47dc3ee3f5db997129eb091330beda1da5a0e9e5bd7", + "sha256:1fb9cb60e0f33040e4f4681e6658a7eb03b5cb4643284172f91410d8c493dace", + "sha256:273505fcad22e58cc67329cefab2e436006fc68e3c5423056ee0513e6523268a", + "sha256:2e70e0673d7d12fa6cd363453a0d22dac0d9978500aa6b46aa96e22690a55eab", + "sha256:34e1c5d9cd3e6bf3d1ce56971c62a40c06bfc02861728f368dcfec8aeedb2814", + "sha256:3b97ddf509fc21e10b09403b5219b06c5b558b27fc2453150274fa4e70707dbf", + "sha256:3f6997da81114daef9203d30aabfa6b218a577fc2bd797c795c9c88c9eb78d49", + "sha256:82dd4131d88395df7c318eeeef367ec768c2a6fe5bd69423f7720c4edb79473c", + "sha256:85292ff52ddf85a39367057c3d7968a12ee1fb84565331a36a8fead346f08796", + "sha256:8a7a66297e46f85a04d68981917c75723e377d2e0599d15fbe7a56abed5e2d75", + "sha256:8b881ac07d15fb3e4f68c5a67aa5cdaf9eb8f09eb5545aaf4b0a5f5f4659be18", + "sha256:a3257a6e09626d32b28a0c5b4f1a97bced585e319cfa90b417f9ab0f6145c33c", + "sha256:a9bddb60566dc45c57fd0a5e14dd2d9e5f106d2241e0a2dc0c1da144f9444516", + "sha256:bdb77e1789e7596b77fd48d99ec1d2108c3349abd20227eea0d48d3f8cf398d9", + "sha256:c1db0221cb26d66294f4ca18c533e427211673ab86c1fbaca8d6d9ff78654293", + "sha256:c4cb501d585aa74a0f86d0ea6263b9c5e1d1463f8f9071392477fd401bd3c7cc", + "sha256:d00665725063692c42badfd521d0c4392e83c6c826795d38eb88fb108e5660e5", + "sha256:d0fed0f791d78e7767c2db28d34068649dfeea027b83ed18c45a423f741425cb", + "sha256:d69738d582e3a24125f0c246ed8d712b03bd21e148268421e4a4d09c34f521a5", + "sha256:db4db3c08ffbb18582f856545f058a7a5e4ab6f17f75795ca90b3c38ee0a8ba4", + "sha256:f1fcee5a2c859eecb4ed179edac5ffbc7c84ab09a5420219078ccc6edda45436", + "sha256:f2d526aeea1bd6a442abc7c9b4b00386fd70253b80d54a0930c0a216230a35be", + "sha256:fbaf6643a604aa17e7a7afd74f665f9db882df5c297bdd86c38368f2c471f37d" + ], + "index": "pypi", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.4.50" + }, + "stack-data": { + "hashes": [ + "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", + "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695" + ], + "version": "==0.6.3" + }, + "statsmodels": { + "hashes": [ + "sha256:0eea4a0b761aebf0c355b726ac5616b9a8b618bd6e81a96b9f998a61f4fd7484", + "sha256:0ef7fa4813c7a73b0d8a0c830250f021c102c71c95e9fe0d6877bcfb56d38b8c", + "sha256:16bfe0c96a53b20fa19067e3b6bd2f1d39e30d4891ea0d7bc20734a0ae95942d", + "sha256:1c7724ad573af26139a98393ae64bc318d1b19762b13442d96c7a3e793f495c3", + "sha256:229b2f676b4a45cb62d132a105c9c06ca8a09ffba060abe34935391eb5d9ba87", + "sha256:3757542c95247e4ab025291a740efa5da91dc11a05990c033d40fce31c450dc9", + "sha256:3b0a135f3bfdeec987e36e3b3b4c53e0bb87a8d91464d2fcc4d169d176f46fdb", + "sha256:4c815ce7a699047727c65a7c179bff4031cff9ae90c78ca730cfd5200eb025dd", + "sha256:575f61337c8e406ae5fa074d34bc6eb77b5a57c544b2d4ee9bc3da6a0a084cf1", + "sha256:582f9e41092e342aaa04920d17cc3f97240e3ee198672f194719b5a3d08657d6", + "sha256:5a6a0a1a06ff79be8aa89c8494b33903442859add133f0dda1daf37c3c71682e", + "sha256:6875c7d689e966d948f15eb816ab5616f4928706b180cf470fd5907ab6f647a4", + "sha256:68b1c768dd94cc5ba8398121a632b673c625491aa7ed627b82cb4c880a25563f", + "sha256:6f7d762df4e04d1dde8127d07e91aff230eae643aa7078543e60e83e7d5b40db", + "sha256:71054f9dbcead56def14e3c9db6f66f943110fdfb19713caf0eb0f08c1ec03fd", + "sha256:76e290f4718177bffa8823a780f3b882d56dd64ad1c18cfb4bc8b5558f3f5757", + "sha256:77b3cd3a5268ef966a0a08582c591bd29c09c88b4566c892a7c087935234f285", + "sha256:7ebe885ccaa64b4bc5ad49ac781c246e7a594b491f08ab4cfd5aa456c363a6f6", + "sha256:8be53cdeb82f49c4cb0fda6d7eeeb2d67dbd50179b3e1033510e061863720d93", + "sha256:8d1e3e10dfbfcd58119ba5a4d3c7d519182b970a2aebaf0b6f539f55ae16058d", + "sha256:9c64ebe9cf376cba0c31aed138e15ed179a1d128612dd241cdf299d159e5e882", + "sha256:a6ad7b8aadccd4e4dd7f315a07bef1bca41d194eeaf4ec600d20dea02d242fce", + "sha256:afe80544ef46730ea1b11cc655da27038bbaa7159dc5af4bc35bbc32982262f2", + "sha256:b587ee5d23369a0e881da6e37f78371dce4238cf7638a455db4b633a1a1c62d6", + "sha256:ce28eb1c397dba437ec39b9ab18f2101806f388c7a0cf9cdfd8f09294ad1c799", + "sha256:d7fda067837df94e0a614d93d3a38fb6868958d37f7f50afe2a534524f2660cb", + "sha256:de489e3ed315bdba55c9d1554a2e89faa65d212e365ab81bc323fa52681fc60e", + "sha256:fb471f757fc45102a87e5d86e87dc2c8c78b34ad4f203679a46520f1d863b9da", + "sha256:fc2c7931008a911e3060c77ea8933f63f7367c0f3af04f82db3a04808ad2cd2c" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==0.14.0" + }, + "stringcase": { + "hashes": [ + "sha256:48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008" + ], + "version": "==1.2.0" + }, + "tableschema": { + "hashes": [ + "sha256:676948747ec8964c6e27e12ce45e203201191bb7e81a26f2eb09a1fdbe130d5c", + "sha256:cfa3b0aa1c0941002384c6288794f9488cb5ea9188cf84ac700d17758cb036e7" + ], + "version": "==1.20.2" + }, + "tabulate": { + "hashes": [ + "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", + "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f" + ], + "markers": "python_version >= '3.7'", + "version": "==0.9.0" + }, + "tabulator": { + "hashes": [ + "sha256:0e2887d0b36483a292e75b118d7f03e710c1337435553b5f62d2a7a891b7fe55", + "sha256:6de83026f9dc8ac34dbc9e60cced1785ed2f4022ae0250eeaa59e92b5090f477" + ], + "version": "==1.53.5" + }, + "tenacity": { + "hashes": [ + "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a", + "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c" + ], + "markers": "python_version >= '3.7'", + "version": "==8.2.3" + }, + "terminado": { + "hashes": [ + "sha256:1ea08a89b835dd1b8c0c900d92848147cef2537243361b2e3f4dc15df9b6fded", + "sha256:87b0d96642d0fe5f5abd7783857b9cab167f221a39ff98e3b9619a788a3c0f2e" + ], + "markers": "python_version >= '3.8'", + "version": "==0.18.0" + }, + "text-unidecode": { + "hashes": [ + "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", + "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93" + ], + "version": "==1.3" + }, + "threadpoolctl": { + "hashes": [ + "sha256:2b7818516e423bdaebb97c723f86a7c6b0a83d3f3b0970328d66f4d9104dc032", + "sha256:c96a0ba3bdddeaca37dc4cc7344aafad41cdb8c313f74fdfe387a867bba93355" + ], + "markers": "python_version >= '3.8'", + "version": "==3.2.0" + }, + "timezonefinder": { + "hashes": [ + "sha256:024d5422016fc807ca253cba9395bf5176d9efcc5f65d526ef125ea36e808775", + "sha256:a7df1aa559789b42bc9a4187ded03668b43221b8f9019d5e66156512b891902a" + ], + "markers": "python_version >= '3.8' and python_version < '4'", + "version": "==6.1.10" + }, + "tinycss2": { + "hashes": [ + "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847", + "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627" + ], + "markers": "python_version >= '3.7'", + "version": "==1.2.1" + }, + "tomli": { + "hashes": [ + "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" + ], + "markers": "python_version < '3.11'", + "version": "==2.0.1" + }, + "toolz": { + "hashes": [ + "sha256:2059bd4148deb1884bb0eb770a3cde70e7f954cfbbdc2285f1f2de01fd21eb6f", + "sha256:88c570861c440ee3f2f6037c4654613228ff40c93a6c25e0eba70d17282c6194" + ], + "markers": "python_version >= '3.5'", + "version": "==0.12.0" + }, + "tornado": { + "hashes": [ + "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f", + "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5", + "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d", + "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3", + "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2", + "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a", + "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16", + "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a", + "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17", + "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0", + "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe" + ], + "markers": "python_version >= '3.8'", + "version": "==6.3.3" + }, + "traitlets": { + "hashes": [ + "sha256:f14949d23829023013c47df20b4a76ccd1a85effb786dc060f34de7948361b33", + "sha256:fcdaa8ac49c04dfa0ed3ee3384ef6dfdb5d6f3741502be247279407679296772" + ], + "markers": "python_version >= '3.8'", + "version": "==5.14.0" + }, + "typer": { + "extras": [ + "all" + ], + "hashes": [ + "sha256:50922fd79aea2f4751a8e0408ff10d2662bd0c8bbfa84755a699f3bada2978b2", + "sha256:5d96d986a21493606a358cae4461bd8cdf83cbf33a5aa950ae629ca3b51467ee" + ], + "markers": "python_version >= '3.6'", + "version": "==0.9.0" + }, + "types-python-dateutil": { + "hashes": [ + "sha256:1f4f10ac98bb8b16ade9dbee3518d9ace017821d94b057a425b069f834737f4b", + "sha256:f977b8de27787639986b4e28963263fd0e5158942b3ecef91b9335c130cb1ce9" + ], + "version": "==2.8.19.14" + }, + "typing-extensions": { + "hashes": [ + "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0", + "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef" + ], + "markers": "python_version >= '3.8'", + "version": "==4.8.0" + }, + "unicodecsv": { + "hashes": [ + "sha256:018c08037d48649a0412063ff4eda26eaa81eff1546dbffa51fa5293276ff7fc" + ], + "version": "==0.14.1" + }, + "uri-template": { + "hashes": [ + "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", + "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363" + ], + "version": "==1.3.0" + }, + "urllib3": { + "hashes": [ + "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84", + "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.7" + }, + "validators": { + "hashes": [ + "sha256:61cf7d4a62bbae559f2e54aed3b000cea9ff3e2fdbe463f51179b92c58c9585a", + "sha256:77b2689b172eeeb600d9605ab86194641670cdb73b60afd577142a9397873370" + ], + "markers": "python_version >= '3.8'", + "version": "==0.22.0" + }, + "wcwidth": { + "hashes": [ + "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02", + "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c" + ], + "version": "==0.2.12" + }, + "webcolors": { + "hashes": [ + "sha256:29bc7e8752c0a1bd4a1f03c14d6e6a72e93d82193738fa860cbff59d0fcc11bf", + "sha256:c225b674c83fa923be93d235330ce0300373d02885cef23238813b0d5668304a" + ], + "version": "==1.13" + }, + "webencodings": { + "hashes": [ + "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", + "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" + ], + "version": "==0.5.1" + }, + "websocket-client": { + "hashes": [ + "sha256:084072e0a7f5f347ef2ac3d8698a5e0b4ffbfcab607628cadabc650fc9a83a24", + "sha256:b3324019b3c28572086c4a319f91d1dcd44e6e11cd340232978c684a7650d0df" + ], + "markers": "python_version >= '3.8'", + "version": "==1.6.4" + }, + "xlrd": { + "hashes": [ + "sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd", + "sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==2.0.1" + }, + "xlsxwriter": { + "hashes": [ + "sha256:5eaaf3c6f791cba1dd1c3065147c35982180f693436093aabe5b7d6c16148e95", + "sha256:7216d39a2075afac7a28cad81f6ac31b0b16d8976bf1b775577d157346f891dd" + ], + "markers": "python_version >= '3.6'", + "version": "==3.0.9" + }, + "yarl": { + "hashes": [ + "sha256:09c19e5f4404574fcfb736efecf75844ffe8610606f3fccc35a1515b8b6712c4", + "sha256:0ab5baaea8450f4a3e241ef17e3d129b2143e38a685036b075976b9c415ea3eb", + "sha256:0d155a092bf0ebf4a9f6f3b7a650dc5d9a5bbb585ef83a52ed36ba46f55cc39d", + "sha256:126638ab961633f0940a06e1c9d59919003ef212a15869708dcb7305f91a6732", + "sha256:1a0a4f3aaa18580038cfa52a7183c8ffbbe7d727fe581300817efc1e96d1b0e9", + "sha256:1d93461e2cf76c4796355494f15ffcb50a3c198cc2d601ad8d6a96219a10c363", + "sha256:26a1a8443091c7fbc17b84a0d9f38de34b8423b459fb853e6c8cdfab0eacf613", + "sha256:271d63396460b6607b588555ea27a1a02b717ca2e3f2cf53bdde4013d7790929", + "sha256:28a108cb92ce6cf867690a962372996ca332d8cda0210c5ad487fe996e76b8bb", + "sha256:29beac86f33d6c7ab1d79bd0213aa7aed2d2f555386856bb3056d5fdd9dab279", + "sha256:2c757f64afe53a422e45e3e399e1e3cf82b7a2f244796ce80d8ca53e16a49b9f", + "sha256:2dad8166d41ebd1f76ce107cf6a31e39801aee3844a54a90af23278b072f1ccf", + "sha256:2dc72e891672343b99db6d497024bf8b985537ad6c393359dc5227ef653b2f17", + "sha256:2f3c8822bc8fb4a347a192dd6a28a25d7f0ea3262e826d7d4ef9cc99cd06d07e", + "sha256:32435d134414e01d937cd9d6cc56e8413a8d4741dea36af5840c7750f04d16ab", + "sha256:3cfa4dbe17b2e6fca1414e9c3bcc216f6930cb18ea7646e7d0d52792ac196808", + "sha256:3d5434b34100b504aabae75f0622ebb85defffe7b64ad8f52b8b30ec6ef6e4b9", + "sha256:4003f380dac50328c85e85416aca6985536812c082387255c35292cb4b41707e", + "sha256:44e91a669c43f03964f672c5a234ae0d7a4d49c9b85d1baa93dec28afa28ffbd", + "sha256:4a14907b597ec55740f63e52d7fee0e9ee09d5b9d57a4f399a7423268e457b57", + "sha256:4ce77d289f8d40905c054b63f29851ecbfd026ef4ba5c371a158cfe6f623663e", + "sha256:4d6d74a97e898c1c2df80339aa423234ad9ea2052f66366cef1e80448798c13d", + "sha256:51382c72dd5377861b573bd55dcf680df54cea84147c8648b15ac507fbef984d", + "sha256:525cd69eff44833b01f8ef39aa33a9cc53a99ff7f9d76a6ef6a9fb758f54d0ff", + "sha256:53ec65f7eee8655bebb1f6f1607760d123c3c115a324b443df4f916383482a67", + "sha256:5f74b015c99a5eac5ae589de27a1201418a5d9d460e89ccb3366015c6153e60a", + "sha256:6280353940f7e5e2efaaabd686193e61351e966cc02f401761c4d87f48c89ea4", + "sha256:632c7aeb99df718765adf58eacb9acb9cbc555e075da849c1378ef4d18bf536a", + "sha256:6465d36381af057d0fab4e0f24ef0e80ba61f03fe43e6eeccbe0056e74aadc70", + "sha256:66a6dbf6ca7d2db03cc61cafe1ee6be838ce0fbc97781881a22a58a7c5efef42", + "sha256:6d350388ba1129bc867c6af1cd17da2b197dff0d2801036d2d7d83c2d771a682", + "sha256:7217234b10c64b52cc39a8d82550342ae2e45be34f5bff02b890b8c452eb48d7", + "sha256:721ee3fc292f0d069a04016ef2c3a25595d48c5b8ddc6029be46f6158d129c92", + "sha256:72a57b41a0920b9a220125081c1e191b88a4cdec13bf9d0649e382a822705c65", + "sha256:73cc83f918b69110813a7d95024266072d987b903a623ecae673d1e71579d566", + "sha256:778df71c8d0c8c9f1b378624b26431ca80041660d7be7c3f724b2c7a6e65d0d6", + "sha256:79e1df60f7c2b148722fb6cafebffe1acd95fd8b5fd77795f56247edaf326752", + "sha256:7c86d0d0919952d05df880a1889a4f0aeb6868e98961c090e335671dea5c0361", + "sha256:7eaf13af79950142ab2bbb8362f8d8d935be9aaf8df1df89c86c3231e4ff238a", + "sha256:828235a2a169160ee73a2fcfb8a000709edf09d7511fccf203465c3d5acc59e4", + "sha256:8535e111a064f3bdd94c0ed443105934d6f005adad68dd13ce50a488a0ad1bf3", + "sha256:88d2c3cc4b2f46d1ba73d81c51ec0e486f59cc51165ea4f789677f91a303a9a7", + "sha256:8a2538806be846ea25e90c28786136932ec385c7ff3bc1148e45125984783dc6", + "sha256:8dab30b21bd6fb17c3f4684868c7e6a9e8468078db00f599fb1c14e324b10fca", + "sha256:8f18a7832ff85dfcd77871fe677b169b1bc60c021978c90c3bb14f727596e0ae", + "sha256:946db4511b2d815979d733ac6a961f47e20a29c297be0d55b6d4b77ee4b298f6", + "sha256:96758e56dceb8a70f8a5cff1e452daaeff07d1cc9f11e9b0c951330f0a2396a7", + "sha256:9a172c3d5447b7da1680a1a2d6ecdf6f87a319d21d52729f45ec938a7006d5d8", + "sha256:9a5211de242754b5e612557bca701f39f8b1a9408dff73c6db623f22d20f470e", + "sha256:9df9a0d4c5624790a0dea2e02e3b1b3c69aed14bcb8650e19606d9df3719e87d", + "sha256:aa4643635f26052401750bd54db911b6342eb1a9ac3e74f0f8b58a25d61dfe41", + "sha256:aed37db837ecb5962469fad448aaae0f0ee94ffce2062cf2eb9aed13328b5196", + "sha256:af52725c7c39b0ee655befbbab5b9a1b209e01bb39128dce0db226a10014aacc", + "sha256:b0b8c06afcf2bac5a50b37f64efbde978b7f9dc88842ce9729c020dc71fae4ce", + "sha256:b61e64b06c3640feab73fa4ff9cb64bd8182de52e5dc13038e01cfe674ebc321", + "sha256:b7831566595fe88ba17ea80e4b61c0eb599f84c85acaa14bf04dd90319a45b90", + "sha256:b8bc5b87a65a4e64bc83385c05145ea901b613d0d3a434d434b55511b6ab0067", + "sha256:b8d51817cf4b8d545963ec65ff06c1b92e5765aa98831678d0e2240b6e9fd281", + "sha256:b9f9cafaf031c34d95c1528c16b2fa07b710e6056b3c4e2e34e9317072da5d1a", + "sha256:bb72d2a94481e7dc7a0c522673db288f31849800d6ce2435317376a345728225", + "sha256:c25ec06e4241e162f5d1f57c370f4078797ade95c9208bd0c60f484834f09c96", + "sha256:c405d482c320a88ab53dcbd98d6d6f32ada074f2d965d6e9bf2d823158fa97de", + "sha256:c4472fe53ebf541113e533971bd8c32728debc4c6d8cc177f2bff31d011ec17e", + "sha256:c4b1efb11a8acd13246ffb0bee888dd0e8eb057f8bf30112e3e21e421eb82d4a", + "sha256:c5f3faeb8100a43adf3e7925d556801d14b5816a0ac9e75e22948e787feec642", + "sha256:c6f034386e5550b5dc8ded90b5e2ff7db21f0f5c7de37b6efc5dac046eb19c10", + "sha256:c99ddaddb2fbe04953b84d1651149a0d85214780e4d0ee824e610ab549d98d92", + "sha256:ca6b66f69e30f6e180d52f14d91ac854b8119553b524e0e28d5291a724f0f423", + "sha256:cccdc02e46d2bd7cb5f38f8cc3d9db0d24951abd082b2f242c9e9f59c0ab2af3", + "sha256:cd49a908cb6d387fc26acee8b7d9fcc9bbf8e1aca890c0b2fdfd706057546080", + "sha256:cf7a4e8de7f1092829caef66fd90eaf3710bc5efd322a816d5677b7664893c93", + "sha256:cfd77e8e5cafba3fb584e0f4b935a59216f352b73d4987be3af51f43a862c403", + "sha256:d34c4f80956227f2686ddea5b3585e109c2733e2d4ef12eb1b8b4e84f09a2ab6", + "sha256:d61a0ca95503867d4d627517bcfdc28a8468c3f1b0b06c626f30dd759d3999fd", + "sha256:d81657b23e0edb84b37167e98aefb04ae16cbc5352770057893bd222cdc6e45f", + "sha256:d92d897cb4b4bf915fbeb5e604c7911021a8456f0964f3b8ebbe7f9188b9eabb", + "sha256:dd318e6b75ca80bff0b22b302f83a8ee41c62b8ac662ddb49f67ec97e799885d", + "sha256:dd952b9c64f3b21aedd09b8fe958e4931864dba69926d8a90c90d36ac4e28c9a", + "sha256:e0e7e83f31e23c5d00ff618045ddc5e916f9e613d33c5a5823bc0b0a0feb522f", + "sha256:e0f17d1df951336a02afc8270c03c0c6e60d1f9996fcbd43a4ce6be81de0bd9d", + "sha256:e2a16ef5fa2382af83bef4a18c1b3bcb4284c4732906aa69422cf09df9c59f1f", + "sha256:e36021db54b8a0475805acc1d6c4bca5d9f52c3825ad29ae2d398a9d530ddb88", + "sha256:e73db54c967eb75037c178a54445c5a4e7461b5203b27c45ef656a81787c0c1b", + "sha256:e741bd48e6a417bdfbae02e088f60018286d6c141639359fb8df017a3b69415a", + "sha256:f7271d6bd8838c49ba8ae647fc06469137e1c161a7ef97d778b72904d9b68696", + "sha256:fc391e3941045fd0987c77484b2799adffd08e4b6735c4ee5f054366a2e1551d", + "sha256:fc94441bcf9cb8c59f51f23193316afefbf3ff858460cb47b5758bf66a14d130", + "sha256:fe34befb8c765b8ce562f0200afda3578f8abb159c76de3ab354c80b72244c41", + "sha256:fe8080b4f25dfc44a86bedd14bc4f9d469dfc6456e6f3c5d9077e81a5fedfba7", + "sha256:ff34cb09a332832d1cf38acd0f604c068665192c6107a439a92abfd8acf90fe2" + ], + "markers": "python_version >= '3.7'", + "version": "==1.9.3" + } + }, + "develop": {} +} From 632514893a19951b49b53d77bf2e1b6303b58c3c Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Tue, 28 Nov 2023 14:12:51 -0800 Subject: [PATCH 25/85] fix: point to correct file --- src/load_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/load_data.py b/src/load_data.py index a1df3cfd..b8fedf4f 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -766,7 +766,7 @@ def load_emissions_controls_eia923(year: int): f"eia923/f923_{year}/EIA923_Schedule_8_Annual_Environmental_Information_{year}_Final_Revision.xlsx" ), 2021: downloads_folder( - f"eia923/f923_{year}/EIA923_Schedule_8_Annual_Environmental_Information_{year}_Final.xlsx" + f"eia923/f923_{year}/EIA923_Schedule_8_Annual_Environmental_Information_{year}_Final_Revision.xlsx" ), }[year] From 4fbcf4ad8c16590d8e66dd8a3e188d3fe5c2645a Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Tue, 28 Nov 2023 14:13:13 -0800 Subject: [PATCH 26/85] docs: update README --- README.md | 122 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 199448aa..d408e827 100644 --- a/README.md +++ b/README.md @@ -10,24 +10,39 @@ Please check out [our documentation](https://docs.singularity.energy/docs/open-g The Open Grid Emissions Dataset can be [downloaded here](https://singularity.energy/open-grid-emissions). An archive of previous versions of the dataset and intermediate data outputs (for research and validation purposes) can be found on [Zenodo](https://zenodo.org/communities/singularity-energy?page=1&size=20). ## Installing and running the data pipeline +A couple of installation methods are available. First, navigate to the folder where you want to save the repository and run the following commands: -To install and run the pipeline on your computer, open anaconda prompt, navigate to the folder where you want to save the repository, and run the following commands: - -``` +### If you are using conda +```bash conda install git git clone https://github.com/singularity-energy/open-grid-emissions.git conda update conda cd open-grid-emissions conda env create -f environment.yml conda activate open_grid_emissions +``` + +### If you are using pipenv +Note that this option requires to have Python and git installed on your machine. +```bash +pip install pipenv +git clone https://github.com/singularity-energy/open-grid-emissions.git +cd open-grid-emissions +pipenv sync +pipenv shell +``` + +The pipeline can be run as follows: +```bash cd src python data_pipeline.py --year 2021 ``` +independently of the installation method you chose. -A more detailed walkthough of these steps can be found below in the "Development Setup" section. +A more detailed walkthrough of these steps can be found below in the "Development Setup" section. ## Data Availability and Release Schedule -The latest release includes data for year 2019-2021 covering the contiguous United States, Alaska, and Hawaii. In future releases, we plan to expand the geographic coverage to additional U.S. territories (dependent on data availability), and to expand the historical coverage of the data. +The latest release includes data for year 2019-2021 covering the contiguous United States, Alaska, and Hawaii. In future releases, we plan to expand the geographic coverage to additional U.S. territories (dependent on data availability), and to expand the historical coverage of the data. Parts of the input data used for the Open Grid Emissions dataset is released by the U.S. Energy Information Administration in the Autumn following the end of each year (2022 data should be available Autumn 2023). Each release will include the most recent year of available data as well as updates of all previous available years based on any updates to the OGEI methodology. All previous versions of the data will be archived on Zenodo. @@ -43,7 +58,7 @@ There are many ways that you can contribute! - Contribute your subject matter expertise to the discussion about [open issues and questions](https://github.com/singularity-energy/open-grid-emissions/issues?q=is%3Aissue+is%3Aopen+label%3Aquestion) - Submit a pull request to help us fix open issues -# Repository Structure +## Repository Structure ### Modules - `column_checks`: functions that check that all data outputs have the correct column names - `data_pipeline`: main script for running the data pipeline from start to finish @@ -74,66 +89,73 @@ Notebooks are organized into five directories based on their purpose - `data/outputs` contains intermediate outputs from the data pipeline... any files created by our code that are not final results - `data/results` contains all final output files that will be published -# Development Setup - +## Development Setup If you would like to run the code on your own computer and/or contribute updates to the code, the following steps can help get you started. -## Users unfamiliar with git / python - -### Install conda and python - +### Setup with conda +This installation is recommended if you are unfamiliar with git and Python. +#### Install conda and python We suggest using miniconda or Anaconda to manage the packages needed to run the Open Grid Emissions code. Anaconda and Miniconda install a similar environment, but Anaconda installs more packages by default and Miniconda installs them as needed. These can be downloaded from [miniconda](https://docs.conda.io/en/latest/miniconda.html) or [Anaconda](https://www.anaconda.com/products/distribution) -### Install a code editor - -If you want to edit the code and do not already have an integrated development environment (IDE) installed, one good option is Visual Studio Code (download: https://code.visualstudio.com/). - -### Install and setup git software manager - -In order to download the repository, you will need to use git. You can either install Git Bash from https://git-scm.com/downloads, or you can install it using conda. To do so, fter installing Anaconda or Miniconda, open an Anaconda Command Prompt (Windows) or Terminal.app (Mac) and type the following command: - -``` +#### Install and setup git software manager +In order to download the repository, you will need to use git. You can either install Git Bash from https://git-scm.com/downloads, or you can install it using conda. To do so, after installing Anaconda or Miniconda, open an Anaconda Command Prompt (Windows) or Terminal.app (Mac) and type the following command: +```bash conda install git ``` - Then you will need set up git following these instructions: https://docs.github.com/en/get-started/quickstart/set-up-git -## Once you have git and conda installed - -### Download the codebase to a local repository - +#### Download the codebase to a local repository Using Anaconda command prompt or Git Bash, use the `cd` and `mkdir` commands to create and/or enter the directory where you would like to download the code (e.g. "Users/myusername/GitHub"). Then run: - -``` +```bash git clone https://github.com/singularity-energy/open-grid-emissions.git ``` -### Setup the conda environment - +#### Setup the conda environment Open anaconda prompt, use `cd` to navigate to the directory where your local files are stored (e.g. "GitHub/open-grid-emissions"), and then run: - -``` +```bash conda update conda conda env create -f environment.yml ``` +and activate the environment: +```bash +conda activate open_grid_emissions +``` +Installation requires that the conda channel-priority be set to "flexible". This is the default behavior, so if you've never manually changed this, you shouldn't have to worry about this. However, if you receive an error message like "Found conflicts!" when trying to install the environment, try setting your channel priority to flexible by running the following command:`conda config --set channel_priority flexible` and then re-running the above commands. -Installation requires that the conda channel-priority be set to "flexible". This is the default behavior, -so if you've never manually changed this, you shouldn't have to worry about this. However, -if you receive an error message like "Found conflicts!" when trying to install the environment, -try setting your channel priority to flexible by running the following command: -`conda config --set channel_priority flexible` and then re-running the above commands. +### Setup with pipenv +#### Install python and git +We recommend that you use Python 3.10. If you don't have Python installed, we recommend that you use [**pyenv**](https://github.com/pyenv/pyenv). It lets you easily switch between multiple versions of Python. You will also need to use git to clone the repository. It can be installed from https://git-scm.com/downloads, -## Running the complete data pipeline +#### Install pipenv +This can be done via: +```bash +pip install pipenv +``` -If you would like to run the full data pipeline to generate all intermediate outputs and results files, open anaconda prompt, navigate to `open-grid-emissions/src`, and run the following (replacing 2021 with whichever year you want to run): +#### Download the codebase +As mentioned previously, clone the repository with: +```bash +git clone https://github.com/singularity-energy/open-grid-emissions.git +``` +and navigate to the root of the directory: +```bash +cd open-grid-emissions +``` +#### Setup the environment +In the root of the directory, create and activate the environment with: +```bash +pipenv sync +pipenv shell +``` + +### Running the complete data pipeline +If you would like to run the full data pipeline to generate all intermediate outputs and results files, navigate to `open-grid-emissions/src`, and run the following (replacing 2021 with whichever year you want to run): ``` -conda activate open_grid_emissions python data_pipeline.py --year 2021 ``` -## Keeping the code updated - +### Keeping the code updated From time to time, the code will be updated on GitHub. To ensure that you are keeping your local version of the code up to date, open git bash and follow these steps: ``` # change the directory to where ever your local git repository is saved @@ -147,16 +169,18 @@ git add . git pull origin main ``` -# Contribution Guidelines +### Install a code editor +If you want to edit the code and do not already have an integrated development environment (IDE) installed, one good option is Visual Studio Code (download: https://code.visualstudio.com/). +## Contribution Guidelines If you plan on contributing edits to the codebase that will be merged into the main branch, please follow these best practices: 1. Please do not make edits directly to the main branch. Any new features or edits should be completed in a new branch. To do so, open git bash, navigate to your local repo (e.g. `cd GitHub/open-grid-emissions`), and create a new branch, giving it a descriptive name related to the edit you will be doing: `git checkout -b branch_name` -2. As you code, it is a good practice to 'save' your work frequently by opening git bash, navigating to your local repo (`cd GitHub/open-grid-emissions`), making sure that your current feature branch is active (you should see the feature name in parentheses next to the command line), and running - +2. As you code, it is a good practice to 'save' your work frequently by opening git bash, navigating to your local repo (`cd GitHub/open-grid-emissions`), making sure that your current feature branch is active (you should see the feature name in parentheses next to the command line), and running + `git add .` 3. You should commit your work to the branch whenever you have working code or whenever you stop working on it using: @@ -168,9 +192,9 @@ If you plan on contributing edits to the codebase that will be merged into the m `git push` -5. Now open the GitHub repo web page. You should see the branch you pushed up in a yellow bar at the top of the page with a button to "Compare & pull request". - - Click "Compare & pull request". This will take you to the "Open a pull request" page. - - From here, you should write a brief description of what you actually changed. +5. Now open the GitHub repo web page. You should see the branch you pushed up in a yellow bar at the top of the page with a button to "Compare & pull request". + - Click "Compare & pull request". This will take you to the "Open a pull request" page. + - From here, you should write a brief description of what you actually changed. - Click "Create pull request" - The changes will be reviewed and discussed. Once any edits have been made, the code will be merged into the main branch. @@ -180,5 +204,5 @@ If you plan on contributing edits to the codebase that will be merged into the m - All pandas merge operations should include the `validate` parameter to ensure that unintentional duplicate entries are not created (https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.merge.html) - All pandas groupby operations should include the `dropna=False` parameter so that data with missing groupby keys are not unintentionally dropped from the data. - All code should be formatted using `black` -- Clear all outputs from notebooks before committing your work. +- Clear all outputs from notebooks before committing your work. - Any manual changes to reported categorical data, conversion factors, or manual data mappings should be loaded from a .csv file `data/manual` rather than stored in a dictionary or variable in the code. From 21f273f74909b293baadd2695d0603684d2bb931 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Tue, 5 Dec 2023 19:20:17 -0800 Subject: [PATCH 27/85] drop zero fuels from eia923 allocated --- notebooks/work_in_progress/sandbox.ipynb | 4 ++-- src/data_cleaning.py | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/notebooks/work_in_progress/sandbox.ipynb b/notebooks/work_in_progress/sandbox.ipynb index d74eb261..b69f7db2 100644 --- a/notebooks/work_in_progress/sandbox.ipynb +++ b/notebooks/work_in_progress/sandbox.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -35,7 +35,7 @@ "logger = get_logger(\"test\")\n", "\n", "\n", - "year = 2021\n", + "year = 2020\n", "path_prefix = f\"{year}/\"" ] } diff --git a/src/data_cleaning.py b/src/data_cleaning.py index 085724a5..82afa241 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -421,6 +421,25 @@ def clean_eia923( "generation_fuel_by_generator_energy_source_monthly_eia923", year ) + # drop rows where all allocated data is missing + gen_fuel_allocated = gen_fuel_allocated.dropna( + subset=[ + "net_generation_mwh", + "fuel_consumed_mmbtu", + "fuel_consumed_for_electricity_mmbtu", + ], + how="all", + ) + + # drop rows where all allocated data is zero + gen_fuel_allocated = gen_fuel_allocated[ + ~( + (gen_fuel_allocated["net_generation_mwh"] == 0) + & (gen_fuel_allocated["fuel_consumed_mmbtu"] == 0) + & (gen_fuel_allocated["fuel_consumed_for_electricity_mmbtu"] == 0) + ) + ] + # test to make sure allocated totals match input totals validation.check_allocated_gf_matches_input_gf(year, gen_fuel_allocated) From b4088b7b4cc406537969aec04df0e77c8f846d40 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Wed, 6 Dec 2023 15:36:09 -0800 Subject: [PATCH 28/85] fix merge issues --- src/data_cleaning.py | 37 +++++++++++++------- src/emissions.py | 81 ++++++++++++++++++++++---------------------- 2 files changed, 65 insertions(+), 53 deletions(-) diff --git a/src/data_cleaning.py b/src/data_cleaning.py index 82afa241..ef2ad652 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -617,20 +617,31 @@ def create_primary_fuel_table(gen_fuel_allocated, add_subplant_id, year): ) validation.test_for_missing_subplant_id(gen_fuel_allocated) - # get a table of primary energy source codes - gen_primary_fuel = gen_fuel_allocated[ - gen_fuel_allocated["energy_source_code_num"] == "energy_source_code_1" - ].drop_duplicates(subset=["plant_id_eia", "generator_id"])[ - ["plant_id_eia", "generator_id", "subplant_id", "energy_source_code"] - ] + # get a table of primary energy source codes by generator + # this will be used in `calculate_aggregated_primary_fuel()` to determine the + # mode of energy source codes by plant + # sum the fuel consumption by ESC within each generator + gen_primary_fuel = ( + gen_fuel_allocated.groupby( + ["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"], + dropna=False, + )["fuel_consumed_mmbtu"] + .sum() + .reset_index() + ) - else: - # get a table of primary energy source codes - gen_primary_fuel = gen_fuel_allocated[ - gen_fuel_allocated["energy_source_code_num"] == "energy_source_code_1" - ].drop_duplicates(subset=["plant_id_eia", "generator_id"])[ - ["plant_id_eia", "generator_id", "energy_source_code"] - ] + # only keep the ESC associated with the highest fuel consumption for each gen + gen_primary_fuel = gen_primary_fuel.sort_values( + by=["plant_id_eia", "subplant_id", "generator_id", "fuel_consumed_mmbtu"], + ascending=True, + ).drop_duplicates( + subset=["plant_id_eia", "subplant_id", "generator_id"], keep="last" + )[ + ["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"] + ] + + if not add_subplant_id: + gen_primary_fuel = gen_primary_fuel.drop(columns=["subplant_id"]) plant_primary_fuel = calculate_aggregated_primary_fuel( gen_fuel_allocated, gen_primary_fuel, "plant", year diff --git a/src/emissions.py b/src/emissions.py index 01673085..4ee75242 100644 --- a/src/emissions.py +++ b/src/emissions.py @@ -453,10 +453,30 @@ def calculate_nox_from_fuel_consumption( uncontrolled_nox_factors = calculate_generator_nox_ef_per_unit_from_boiler_type( gen_fuel_allocated, year ) + # convert all EFs to a standardized unit based on fuel heat content uncontrolled_nox_factors = convert_ef_to_lb_per_mmbtu( uncontrolled_nox_factors, year, "nox" ) + # For generators associated with multiple boilers, average all nox factors together + # to have a single factor per generator + # TODO: In the future, these factors should be weighed by the boiler fuel allocation + # factors, and not just a straight average. + uncontrolled_nox_factors = ( + uncontrolled_nox_factors.groupby( + [ + "report_date", + "plant_id_eia", + "generator_id", + "prime_mover_code", + "energy_source_code", + ], + dropna=False, + )["nox_ef_lb_per_mmbtu"] + .mean() + .reset_index() + ) + # merge nox efs into the gen_fuel_allocated gen_fuel_allocated = gen_fuel_allocated.merge( uncontrolled_nox_factors, @@ -543,9 +563,9 @@ def calculate_nox_from_fuel_consumption( def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, year): - """Calculates a generator-specific Nox emission factor per unit fuel based on boiler firing type - - If a generator has multiple boilers, average the emission factor of all boilers + """ + Calculates a boiler-specific NOx emission factor per unit fuel based on boiler + firing type, and associates with each generator. """ # get a dataframe with all unique generator-pm-esc combinations for emitting energy source types with data reported @@ -591,7 +611,7 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea boiler_generator_assn, how="left", on=["plant_id_eia", "boiler_id"], - validate="1:m" + validate="1:m", ) # merge the gen keys with the boiler firing types @@ -607,7 +627,7 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea "boiler_firing_type" ].fillna("none") - # merge in the emission factors for spedcific boiler types + # merge in the emission factors for specific boiler types gen_nox_factors = gen_nox_factors.merge( nox_emission_factors, how="left", @@ -706,23 +726,6 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea gen_nox_factors["emission_factor"] = gen_nox_factors["emission_factor"].fillna(0) - # average the emission factors for all boilers associated with each generator - gen_nox_factors = ( - gen_nox_factors.groupby( - [ - "report_date", - "plant_id_eia", - "generator_id", - "prime_mover_code", - "energy_source_code", - "emission_factor_denominator", - ], - dropna=False, - )["emission_factor"] - .mean() - .reset_index() - ) - return gen_nox_factors @@ -1203,6 +1206,22 @@ def calculate_so2_from_fuel_consumption(gen_fuel_allocated, year): uncontrolled_so2_factors, year, "so2" ) + # average the emission factors for all boilers associated with each generator + uncontrolled_so2_factors = ( + uncontrolled_so2_factors.groupby( + [ + "report_date", + "plant_id_eia", + "generator_id", + "prime_mover_code", + "energy_source_code", + ], + dropna=False, + )["so2_ef_lb_per_mmbtu"] + .mean() + .reset_index() + ) + # merge so2 efs into the gen_fuel_allocated gen_fuel_allocated = gen_fuel_allocated.merge( uncontrolled_so2_factors, @@ -1434,24 +1453,6 @@ def calculate_generator_so2_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea "multiply_by_sulfur_content" ].fillna(0) - # average the emission factors for all boilers associated with each generator - gen_so2_factors = ( - gen_so2_factors.groupby( - [ - "report_date", - "plant_id_eia", - "generator_id", - "prime_mover_code", - "energy_source_code", - "emission_factor_denominator", - "multiply_by_sulfur_content", - ], - dropna=False, - )["emission_factor"] - .mean() - .reset_index() - ) - return gen_so2_factors From 7804691fbb6aaf0a86dd20f765f001e3162ecb23 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Wed, 6 Dec 2023 16:25:54 -0800 Subject: [PATCH 29/85] update pudl dependency --- environment.yml | 7 ++++--- src/column_checks.py | 10 +++++++++- src/data_cleaning.py | 2 +- src/emissions.py | 2 +- src/gross_to_net_generation.py | 2 +- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/environment.yml b/environment.yml index 6b6ca3f8..01dd6d3f 100644 --- a/environment.yml +++ b/environment.yml @@ -1,4 +1,4 @@ -name: open_grid_emissions +name: open_grid_emissions_test channels: - defaults - conda-forge @@ -18,10 +18,11 @@ dependencies: - plotly - pyarrow - pytest - - python>=3.10,<3.11 # require 3.10.x for compatibility with pudl + - python>=3.11,<3.12 # require 3.11.x for compatibility with pudl - python-snappy # used for pudl - qdldl-python==0.1.5,!=0.1.5.post2 # used for gridemissions, newer version not working as of 12/12/2022 - requests>=2.28.1 + - ruff - seaborn # used by gridemissions - setuptools # used for pudl - sqlalchemy @@ -31,6 +32,6 @@ dependencies: - pip: # --editable ../pudl #NOTE: this is for development use - - git+https://github.com/grgmiller/pudl.git@oge_release#egg=catalystcoop.pudl + - git+https://github.com/singularity-energy/pudl.git@main#egg=catalystcoop.pudl #- --editable ../gridemissions # NOTE: this is for development use - git+https://github.com/gailin-p/gridemissions#egg=gridemissions diff --git a/src/column_checks.py b/src/column_checks.py index f7bf65e6..c2ae36ff 100644 --- a/src/column_checks.py +++ b/src/column_checks.py @@ -419,7 +419,7 @@ def get_dtypes(): "eia930_profile": "float64", "emissions_unit_id_epa": "str", "energy_source_code": "str", - "energy_source_code_1":"str", + "energy_source_code_1": "str", "equipment_tech_description": "str", "fgd_electricity_consumption_mwh": "float64", "fgd_sorbent_consumption_1000_tons": "float64", @@ -462,6 +462,10 @@ def get_dtypes(): "plant_id_eia": "Int32", "plant_id_epa": "Int32", "plant_primary_fuel": "str", + "plant_primary_fuel_from_capacity_mw": "str", + "plant_primary_fuel_from_fuel_consumed_for_electricity_mmbtu": "str", + "plant_primary_fuel_from_mode": "str", + "plant_primary_fuel_from_net_generation_mwh": "str", "prime_mover_code": "str", "profile": "float64", "profile_method": "str", @@ -480,6 +484,10 @@ def get_dtypes(): "steam_load_1000_lb": "float64", "subplant_id": "Int16", "subplant_primary_fuel": "str", + "subplant_primary_fuel_from_capacity_mw": "str", + "subplant_primary_fuel_from_fuel_consumed_for_electricity_mmbtu": "str", + "subplant_primary_fuel_from_mode": "str", + "subplant_primary_fuel_from_net_generation_mwh": "str", "timezone": "str", "wet_dry_bottom": "str", } diff --git a/src/data_cleaning.py b/src/data_cleaning.py index ef2ad652..717f0dde 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -3,7 +3,7 @@ import os import sqlalchemy as sa -import pudl.analysis.allocate_net_gen as allocate_gen_fuel +import pudl.analysis.allocate_gen_fuel as allocate_gen_fuel import pudl.analysis.epacamd_eia as epacamd_eia_crosswalk import load_data diff --git a/src/emissions.py b/src/emissions.py index 4ee75242..d7c8cfd9 100644 --- a/src/emissions.py +++ b/src/emissions.py @@ -7,7 +7,7 @@ from filepaths import manual_folder from logging_util import get_logger -from pudl.analysis.allocate_net_gen import ( +from pudl.analysis.allocate_gen_fuel import ( distribute_annually_reported_data_to_months_if_annual, ) diff --git a/src/gross_to_net_generation.py b/src/gross_to_net_generation.py index 897bff7d..2264faad 100644 --- a/src/gross_to_net_generation.py +++ b/src/gross_to_net_generation.py @@ -6,7 +6,7 @@ import warnings # import pudl packages -import pudl.analysis.allocate_net_gen as allocate_gen_fuel +import pudl.analysis.allocate_gen_fuel as allocate_gen_fuel # import other modules import load_data From 18220e3a4b02e17be3e7ed2e4db46d2a2ceb065b Mon Sep 17 00:00:00 2001 From: grgmiller Date: Wed, 6 Dec 2023 16:29:40 -0800 Subject: [PATCH 30/85] update requirements for pudl --- Pipfile | 4 ++-- requirements.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Pipfile b/Pipfile index aee73054..66ae2a98 100644 --- a/Pipfile +++ b/Pipfile @@ -21,7 +21,7 @@ seaborn = "*" sqlalchemy = "*" statsmodels = "*" coloredlogs = "*" -"catalystcoop.pudl" = {ref = "oge_release", git = "git+https://github.com/grgmiller/pudl.git"} +"catalystcoop.pudl" = {git = "git+https://github.com/singularity-energy/pudl.git"} gridemissions = {git = "git+https://github.com/gailin-p/gridemissions#egg=gridemissions"} [dev-packages] @@ -29,4 +29,4 @@ ruff = "*" pytest = "*" [requires] -python_version = "3.10" +python_version = "3.11" diff --git a/requirements.txt b/requirements.txt index be4504ab..e32eb4d1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,5 +17,5 @@ seaborn sqlalchemy statsmodels coloredlogs -git+https://github.com/grgmiller/pudl.git@oge_release#egg=catalystcoop.pudl +git+https://github.com/singularity-energy/pudl.git#egg=catalystcoop.pudl git+https://github.com/gailin-p/gridemissions#egg=gridemissions From 03fb506fb47137eb903e514fd8babf8025f1c343 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Wed, 6 Dec 2023 17:15:52 -0800 Subject: [PATCH 31/85] update pipfile --- Pipfile | 5 +- Pipfile.lock | 3305 +++++++++++++++++++++++++++++++++++----------- README.md | 2 +- requirements.txt | 1 - 4 files changed, 2527 insertions(+), 786 deletions(-) diff --git a/Pipfile b/Pipfile index 66ae2a98..58e7ce71 100644 --- a/Pipfile +++ b/Pipfile @@ -13,8 +13,7 @@ numpy = "*" openpyxl = "*" pandas = "*" plotly = "*" -pyarrow = "*" -python-snappy = "*" +pyarrow = "pip*" qdldl = "*" requests = "*" seaborn = "*" @@ -22,7 +21,7 @@ sqlalchemy = "*" statsmodels = "*" coloredlogs = "*" "catalystcoop.pudl" = {git = "git+https://github.com/singularity-energy/pudl.git"} -gridemissions = {git = "git+https://github.com/gailin-p/gridemissions#egg=gridemissions"} +gridemissions = {git = "git+https://github.com/gailin-p/gridemissions"} [dev-packages] ruff = "*" diff --git a/Pipfile.lock b/Pipfile.lock index b86f85dd..99d8df37 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,11 +1,11 @@ { "_meta": { "hash": { - "sha256": "2f23e9aa264c7984e601aec4ee398a680f642a79085827f0ce0d67ab582a0f29" + "sha256": "7249563398d2518deb9e27b91ad7cfea052a50a07efcb91354fd7b3f5691dade" }, "pipfile-spec": 6, "requires": { - "python_version": "3.10" + "python_version": "3.11" }, "sources": [ { @@ -24,6 +24,14 @@ "markers": "python_version >= '3.7'", "version": "==0.4.0" }, + "aiofiles": { + "hashes": [ + "sha256:19297512c647d4b27a2cf7c34caa7e405c0d60b5560618a29a9fe027b18b0107", + "sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a" + ], + "markers": "python_version >= '3.7'", + "version": "==23.2.1" + }, "aiohttp": { "hashes": [ "sha256:02ab6006ec3c3463b528374c4cdce86434e7b89ad355e7bf29e2f16b46c7dd6f", @@ -114,6 +122,38 @@ "markers": "python_version >= '3.7'", "version": "==1.3.1" }, + "alabaster": { + "hashes": [ + "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3", + "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2" + ], + "markers": "python_version >= '3.6'", + "version": "==0.7.13" + }, + "alembic": { + "hashes": [ + "sha256:a23974ea301c3ee52705db809c7413cecd165290c6679b9998dd6c74342ca23a", + "sha256:ab4b3b94d2e1e5f81e34be8a9b7b7575fc9dd5398fccb0bef351ec9b14872623" + ], + "markers": "python_version >= '3.8'", + "version": "==1.13.0" + }, + "annotated-types": { + "hashes": [ + "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43", + "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d" + ], + "markers": "python_version >= '3.8'", + "version": "==0.6.0" + }, + "anyascii": { + "hashes": [ + "sha256:3b3beef6fc43d9036d3b0529050b0c48bfad8bc960e9e562d7223cfb94fe45d4", + "sha256:9d5d32ef844fe225b8bc7cba7f950534fae4da27a9bf3a6bea2cb0ea46ce4730" + ], + "markers": "python_version >= '3.3'", + "version": "==0.3.2" + }, "anyio": { "hashes": [ "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f", @@ -122,21 +162,20 @@ "markers": "python_version >= '3.8'", "version": "==4.1.0" }, - "appnope": { + "appdirs": { "hashes": [ - "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24", - "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e" + "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", + "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" ], - "markers": "platform_system == 'Darwin'", - "version": "==0.1.3" + "version": "==1.4.4" }, "arelle-release": { "hashes": [ - "sha256:1ad3655dc73c15b866c027d4c28a23bc6ee23992b6092b43bffd6f783aa0f1ca", - "sha256:cd30cab5835192e5eff8eb5853a9655765da0d89396304f789f45979b265e074" + "sha256:359b403a9b621668af21c3c249651580a44052a7b669075d512adb5fa18ef590", + "sha256:8b9db9108de1c714e794a0d5f827609ef524a6b2dd1204a298d7ced0ba220079" ], - "markers": "python_version >= '3.7'", - "version": "==2.3.4" + "markers": "python_version >= '3.8'", + "version": "==2.18.0" }, "argon2-cffi": { "hashes": [ @@ -181,6 +220,29 @@ "markers": "python_version >= '3.8'", "version": "==1.3.0" }, + "asgi-csrf": { + "hashes": [ + "sha256:6e9d3bddaeac1a8fd33b188fe2abc8271f9085ab7be6e1a7f4d3c9df5d7f741a", + "sha256:e974cffb8a4ab84a28a0088acbf7a4ecc5be4a64f08dcbe19c60dea103da01c0" + ], + "version": "==0.9" + }, + "asgiref": { + "hashes": [ + "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e", + "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed" + ], + "markers": "python_version >= '3.7'", + "version": "==3.7.2" + }, + "astroid": { + "hashes": [ + "sha256:7d5895c9825e18079c5aeac0572bc2e4c83205c95d416e0b4fee8bc361d2d9ca", + "sha256:86b0bb7d7da0be1a7c4aedb7974e391b32d4ed89e33de6ed6902b4b15c97577e" + ], + "markers": "python_version < '3.12'", + "version": "==3.0.1" + }, "asttokens": { "hashes": [ "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", @@ -196,14 +258,6 @@ "markers": "python_version >= '3.8'", "version": "==2.0.4" }, - "async-timeout": { - "hashes": [ - "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", - "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028" - ], - "markers": "python_version < '3.11'", - "version": "==4.0.3" - }, "attrs": { "hashes": [ "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04", @@ -238,19 +292,86 @@ }, "boto3": { "hashes": [ - "sha256:70626598dd6698d6da8f2854a1ae5010f175572e2a465b2aa86685c745c1013c", - "sha256:fc7c0dd5fa74ae0d57e11747695bdba4ad164e62dee35db15b43762c392fbd92" + "sha256:9486f66f9a89f66d64d25cb4baa55aad323a1734ef9815b7a2c4c0787a3fc1fb", + "sha256:baa6ea61527bcc82365a4ef365aa8f34126483ff8533d01274f3cdb340c22d73" ], "markers": "python_version >= '3.7'", - "version": "==1.33.2" + "version": "==1.33.9" }, "botocore": { "hashes": [ - "sha256:16a30faac6e6f17961c009defb74ab1a3508b8abc58fab98e7cf96af0d91ea84", - "sha256:5c46b7e8450efbf7ddc2a0016eee7225a5564583122e25a20ca92a29a105225c" + "sha256:07ff4eea62f546da540310887000c81fca802c788eb374fef06eda28009dcafd", + "sha256:1b90be11dd9a9a25290c995a6b713e76b9e2bf7bf86ba9036e0d28f2ceb2edfc" + ], + "markers": "python_version >= '3.7'", + "version": "==1.33.9" + }, + "bottleneck": { + "hashes": [ + "sha256:01e61a512d645193cf4cf4fdacf98d3140c26ace0fcf4c4ed8fdfa366c57e0d1", + "sha256:1045f9b199bba2675bd7642c25dec5daa21a03a5f0444eb863f2790af52b00b0", + "sha256:175ae3d92142769a5acd169ac2d7df22107b72f6d4c932ff56f5afcef39d5877", + "sha256:2a39049aa1cb798538f96150098f50badb37417c41cecfa8a441c0c4e6433c7e", + "sha256:4d2ae3e1ac0626107c6916783befc39473900bb22a9b275e21550c99abe8283c", + "sha256:54fc579445688c5309a0af7634db3be4e17659c6b664f9332ec404738e847894", + "sha256:5977f1fd02f01035176a99c01b3fb0eefdaff002c30a4710f7279215b0a317f5", + "sha256:5af0c679da9dc41d6a3c436785c664fff41b4c1178d46afaa630620ab31e970f", + "sha256:6311ee47641ed5fbc543d2e49cbfa90bd9ece208a0c1bdc2c2b14b9132982b2a", + "sha256:64ef9ad7187282745205b735e8c33307ec14c7be39f9971bc3f375104355cfb9", + "sha256:685812254238c2059810f8e25c8215b09795b974f5b1a89f0accda3d93cc8734", + "sha256:68d0f9d32d45f62028ab27d2b51d1a2af72a5ca6a7c3b1f86e9115fedb266300", + "sha256:699fb76ef50cf85be8f8d644b533488de3cec4c6ddf00fd770f73cc5caac9938", + "sha256:752c97d64ebebdc10a5568d97b81b4971238fa4b53533248d227c4ea759aee4e", + "sha256:752f4c3fc5b7cc49814d41e9ecf6f228f33ea407bdb8c889da53716b5628abc7", + "sha256:79160e49a5a0438468b970967e29addde2d9c6a6ce930144de7ccd8151077603", + "sha256:83d71c49dd9d6b99def958b6ccba3c8b5aac7b90849a5a9fe935648436dd46b9", + "sha256:8d6865327ebbea5578f99b073538789df2123cf9009e99fe94efc4d25a4b888b", + "sha256:9170ebee4cff423c92b3760afec179bded90eaede7c70dd27cf5f406cc00a1e7", + "sha256:92fc5d3ecfedde3b28c56ca686cff70a8125d1ddc281eb468b5e9d6a61269802", + "sha256:955df78713ff58cf815c0a1fa4782b2dc51a8787c0971688472c64b267303855", + "sha256:a09fa97df2f572aed5da487d3fe467829c2212c97b1d63c768ec9be9fd1c57a9", + "sha256:a1e50fb506693186a4b8f85ac79df1a5af1ab1f774bf20004280e0658a731a89", + "sha256:a477101ee12155a0d2f9a82cd3e2a44b9b1aa53afe5b20acc065c91cf35c3106", + "sha256:abfc22762640cc7716c1bd9a409bde0f834167a2584775eb644c6afe7bae3319", + "sha256:ada1a9ff93fd6b1b19f12398a6761940372b00e53d86db98bd4613a751c60043", + "sha256:b3c65a9aedada04872cba450676d132d7af8b9da47f58b82f20ffe9b9ff77a46", + "sha256:b4a47f972e919d22c1725ff7262d209e6ea3a4d9bcfea71fb454a18e166515ec", + "sha256:b5ec31e0b52cbfd716255695ec5fe87662a5961d2b8b49936f3608e36a04d926", + "sha256:b624023f173332d209ed5bd4134fae43d2432d61c6b17a49a6b7c5591caa7cc4", + "sha256:bbda2b27e81a47b7578bce6a8cb2f5eb899279c828d8efb5a154d8ede785093d", + "sha256:bd69b1844c90f6bcf1b679a608fb2c0909be5e045f91674d61a0e4c3596644be", + "sha256:c65d0a9498b2ccda236b28b1b36bc35402e81ebc4575b6cf44033b7e4460f067", + "sha256:c8fa2d85298cdd0f88f51fb46604039abe9a5a2b57e00acfe2b64f546754c053", + "sha256:cfe5f3010e9ad8ae54871d1e8fd61109c5981ed8d9d14e8496a1c37fe2050a04", + "sha256:d982e1e3f72cc7ca4f558e9ef7db7a97ce68a915b1db8249fe088b3e78974b21", + "sha256:e1467e373ad469da340ed0ff283214d6531cc08bfdca2083361a3aa6470681f8", + "sha256:e26c655736701365d66c64056fc272952d0e2a52718c637254d7dd9a7efa97a8", + "sha256:e2a290dcb148c0ddf182052e333892e46730c7d39a1f251af87e3d81a43cdde3", + "sha256:f239ba0d992c013564979cff4fecf2b251614de3730641e79d05ecc09268c00c", + "sha256:f2c8b631552908b11905cf87b4a90dd4af332b0726dd9b49d26d6a0fbb38e6d4", + "sha256:f5409cf6db5e60256626a7c110b2b4c80d9f6b0d1ec0b66565bbab978f96b7a6", + "sha256:fa80c318b5164e39e4f2d5abf95f5ff42744e3d8535a4c85ede94ccc5fca8f9b" + ], + "version": "==1.3.7" + }, + "build": { + "hashes": [ + "sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b", + "sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.3" + }, + "cachecontrol": { + "extras": [ + "filecache" + ], + "hashes": [ + "sha256:95dedbec849f46dda3137866dc28b9d133fc9af55f5b805ab1291833e4457aa4", + "sha256:f012366b79d2243a6118309ce73151bf52a38d4a5dac8ea57f09bd29087e506b" ], "markers": "python_version >= '3.7'", - "version": "==1.33.2" + "version": "==0.13.1" }, "cached-property": { "hashes": [ @@ -267,6 +388,14 @@ "markers": "python_version >= '3.7'", "version": "==5.3.2" }, + "cachy": { + "hashes": [ + "sha256:186581f4ceb42a0bbe040c407da73c14092379b1e4c0e327fdb72ae4a9b269b1", + "sha256:338ca09c8860e76b275aff52374330efedc4d5a5e45dc1c5b539c1ead0786fe7" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.3.0" + }, "catalystcoop.dbfread": { "hashes": [ "sha256:e79dc93ec2e5e4dc4f9a8daac2edc5b411026301fc80bd6ceb41b453d9c7ea36", @@ -277,16 +406,16 @@ }, "catalystcoop.ferc-xbrl-extractor": { "hashes": [ - "sha256:331b3a8a24ad21f7a2598ef511f5e08d3aef03cbb616d33af9ef178ded8adeed", - "sha256:5f347804a6b419933d287c7eff397aec0ff9aa4f11fe549256d6efb8fee73aec" + "sha256:78b58aa5bf38c7cc46e6a955dbf839dcf34bb29d265a48b6ccb2af33cc75058b", + "sha256:9756c19117907acb80b09e6051a1d3fa254a03101db4cf9184289d2e697ef2b2" ], - "markers": "python_version >= '3.10' and python_version < '3.12'", - "version": "==0.8.1" + "markers": "python_version >= '3.10' and python_version < '3.13'", + "version": "==1.3.1" }, "catalystcoop.pudl": { - "git": "git+https://github.com/grgmiller/pudl.git", - "markers": "python_version >= '3.10' and python_version < '3.11'", - "ref": "81a7a5137aeeec4d4741b2867f82bbc4f7de75a6" + "git": "git+https://github.com/singularity-energy/pudl.git", + "markers": "python_version >= '3.11' and python_version < '3.12'", + "ref": "5a7e03795158a8cf75d309f75265e2dc80afe7c8" }, "certifi": { "hashes": [ @@ -354,6 +483,14 @@ "markers": "python_version >= '3.8'", "version": "==1.16.0" }, + "cfgv": { + "hashes": [ + "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", + "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560" + ], + "markers": "python_version >= '3.8'", + "version": "==3.4.0" + }, "chardet": { "hashes": [ "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", @@ -480,6 +617,14 @@ "markers": "python_version >= '3.7'", "version": "==8.1.7" }, + "click-default-group": { + "hashes": [ + "sha256:9b60486923720e7fc61731bdb32b617039aba820e22e1c88766b1125592eaa5f", + "sha256:eb3f3c99ec0d456ca6cd2a7f08f7d4e91771bef51b01bdd9580cc6450fe1251e" + ], + "markers": "python_version >= '2.7'", + "version": "==1.2.4" + }, "click-plugins": { "hashes": [ "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b", @@ -492,9 +637,17 @@ "sha256:a4bc13d623356b373c2c27c53dbd9c68cae5d526270bfa71f6c6fa69669c6b27", "sha256:c1ca117dbce1fe20a5809dc96f01e1c2840f6dcc939b3ddbb1111bf330ba82df" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' and python_version < '4'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' and python_version < '4'", "version": "==0.7.2" }, + "clikit": { + "hashes": [ + "sha256:442ee5db9a14120635c5990bcdbfe7c03ada5898291f0c802f77be71569ded59", + "sha256:71268e074e68082306e23d7369a7b99f824a0ef926e55ba2665e911f7208489e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.6.2" + }, "cloudpickle": { "hashes": [ "sha256:246ee7d0c295602a036e86369c77fecda4ab17b506496730f2f576d9016fd9c7", @@ -508,16 +661,17 @@ "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" ], + "markers": "os_name == 'nt'", "version": "==0.4.6" }, "coloredlogs": { "hashes": [ - "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", - "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0" + "sha256:346f58aad6afd48444c2468618623638dadab76e4e70d5e10822676f2d32226a", + "sha256:a1fab193d2053aa6c0a97608c4342d031f1f93a3d1218432c59322441d31a505" ], "index": "pypi", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==15.0.1" + "version": "==14.0" }, "comm": { "hashes": [ @@ -527,6 +681,14 @@ "markers": "python_version >= '3.8'", "version": "==0.2.0" }, + "conda-lock": { + "hashes": [ + "sha256:e554b14cb426116cdc9cf419baa099d11e9b576dcb0b4d9454cea419a8b4ac7c", + "sha256:efa5e86b2e1e0400f75ed4eae7b67a99cc6cdf66ef00b4b00809a85446453d21" + ], + "markers": "python_version >= '3.8'", + "version": "==2.5.1" + }, "contourpy": { "hashes": [ "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8", @@ -577,6 +739,83 @@ "markers": "python_version >= '3.9'", "version": "==1.2.0" }, + "coverage": { + "extras": [ + "toml" + ], + "hashes": [ + "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1", + "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63", + "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9", + "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312", + "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3", + "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb", + "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25", + "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92", + "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda", + "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148", + "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6", + "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216", + "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a", + "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640", + "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836", + "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c", + "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f", + "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2", + "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901", + "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed", + "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a", + "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074", + "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc", + "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84", + "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083", + "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f", + "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c", + "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c", + "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637", + "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2", + "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82", + "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f", + "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce", + "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef", + "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f", + "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611", + "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c", + "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76", + "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9", + "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce", + "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9", + "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf", + "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf", + "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9", + "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6", + "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2", + "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a", + "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a", + "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf", + "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738", + "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a", + "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4" + ], + "markers": "python_version >= '3.8'", + "version": "==7.3.2" + }, + "crashtest": { + "hashes": [ + "sha256:300f4b0825f57688b47b6d70c6a31de33512eb2fa1ac614f780939aa0cf91680", + "sha256:42ca7b6ce88b6c7433e2ce47ea884e91ec93104a4b754998be498a8e6c3d37dd" + ], + "markers": "python_version >= '3.6' and python_version < '4.0'", + "version": "==0.3.1" + }, + "croniter": { + "hashes": [ + "sha256:4cb064ce2d8f695b3b078be36ff50115cf8ac306c10a7e8653ee2a5b534673d7", + "sha256:d199b2ec3ea5e82988d1f72022433c5f9302b3b3ea9e6bfd6a1518f6ea5e700a" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.0.1" + }, "cvxopt": { "hashes": [ "sha256:098abd1d648d9e44f7ad55542b3b7f978b82280f4332ad80a937db6fbe274600", @@ -639,13 +878,34 @@ "markers": "python_version >= '3.8'", "version": "==0.12.1" }, + "dagster": { + "hashes": [ + "sha256:6fb1a26bc4b345c3b71aea7f629656f9f37b578bce11293b554fbaa9d655c6b9", + "sha256:80f7f90e54893573b3939562f7282cb6ddfa3ad033a5c09c286819f9d7f95907" + ], + "version": "==1.5.10" + }, + "dagster-pipes": { + "hashes": [ + "sha256:5c34c7788b29414d1d855125a122a6c3e2d5af7af17f542bd9e53bd1b46aef2e", + "sha256:c305e09de6b467394c9c2d5977fa66ded2cf3d7d41a297fd316db3bcb8200c37" + ], + "version": "==1.5.10" + }, + "dagster-postgres": { + "hashes": [ + "sha256:1ee17fe04db39f726c4cee219144cfe777a948c29e0949188230e9615ee54fe7", + "sha256:8bd21d904baffd8373912c9ea1f60f087d43c81bcb563679889fca6d48a7815f" + ], + "version": "==0.21.10" + }, "dask": { "hashes": [ - "sha256:397b07a0de718f7c87d12ceb1700048aa085a14059847a33ecbdc57132c01eed", - "sha256:ea313767b3d11e0610fbe7c57f7a01b1f8990bb6c699456ba910d9b31da2c9c0" + "sha256:3f687e647ced0d3f2cadbef113c730b6555b9499b62e3a220535438841001c91", + "sha256:6cef2fa43815adc8fe895dd3ea473a311249ba0e15e1f7eb9b1b68302339d998" ], - "markers": "python_version >= '3.8'", - "version": "==2023.1.0" + "markers": "python_version >= '3.9'", + "version": "==2023.12.0" }, "datapackage": { "hashes": [ @@ -654,6 +914,14 @@ ], "version": "==1.15.2" }, + "datasette": { + "hashes": [ + "sha256:a7370d832a656ff0804e262d79fe16080c2bcba56be5e2873a0b64f465542404", + "sha256:df917896f181ce57e26c6b3b78ff7fdfdc46c322c46673b2276fae1d8e7f19e2" + ], + "markers": "python_version >= '3.7'", + "version": "==0.64.5" + }, "debugpy": { "hashes": [ "sha256:125b9a637e013f9faac0a3d6a82bd17c8b5d2c875fb6b7e2772c5aba6d082332", @@ -694,6 +962,13 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==0.7.1" }, + "distlib": { + "hashes": [ + "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057", + "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8" + ], + "version": "==0.3.7" + }, "dnspython": { "hashes": [ "sha256:57c6fbaaeaaf39c891292012060beb141791735dbb4004798328fc2c467402d8", @@ -702,6 +977,30 @@ "markers": "python_version >= '3.8' and python_version < '4.0'", "version": "==2.4.2" }, + "doc8": { + "hashes": [ + "sha256:d97a93e8f5a2efc4713a0804657dedad83745cca4cd1d88de9186f77f9776004", + "sha256:e493aa3f36820197c49f407583521bb76a0fde4fffbcd0e092be946ff95931ac" + ], + "markers": "python_version >= '3.8'", + "version": "==1.1.1" + }, + "docstring-parser": { + "hashes": [ + "sha256:48ddc093e8b1865899956fcc03b03e66bb7240c310fac5af81814580c55bf682", + "sha256:d1679b86250d269d06a99670924d6bce45adc00b08069dae8c47d98e89b667a9" + ], + "markers": "python_version >= '3.6' and python_version < '4.0'", + "version": "==0.15" + }, + "docutils": { + "hashes": [ + "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6", + "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b" + ], + "markers": "python_version >= '3.7'", + "version": "==0.20.1" + }, "ecos": { "hashes": [ "sha256:29d00164eaea66ed54697a3b361c575284a8bca54f2623381a0635806c7303a7", @@ -728,8 +1027,17 @@ "sha256:a4b0bd1cf55f073b924258d19321b1f3aa74b4b5a71a42c305575dba920e1a44", "sha256:c973053efbeddfef924dc0bd93f6e77a1ea7ee0fce935aea7103c7a3d6d2d637" ], + "markers": "python_version >= '3.8'", "version": "==2.1.0.post1" }, + "ensureconda": { + "hashes": [ + "sha256:a746630675e8d5a6a3fc1e8d2ec9c80459e1e722df94365a5099eec0079572a8", + "sha256:e04ae2e2f872869df7e7da22dcca9bd7c42f839a55155dddb249bcdc9e6aae48" + ], + "markers": "python_version >= '3.7'", + "version": "==1.4.3" + }, "et-xmlfile": { "hashes": [ "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c", @@ -738,13 +1046,13 @@ "markers": "python_version >= '3.6'", "version": "==1.1.0" }, - "exceptiongroup": { + "execnet": { "hashes": [ - "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14", - "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68" + "sha256:88256416ae766bc9e8895c76a87928c0012183da3cc4fc18016e6f050e025f41", + "sha256:cc59bc4423742fd71ad227122eb0dd44db51efb3dc4095b45ac9a08c770096af" ], - "markers": "python_version < '3.11'", - "version": "==1.2.0" + "markers": "python_version >= '3.7'", + "version": "==2.0.2" }, "executing": { "hashes": [ @@ -761,6 +1069,13 @@ ], "version": "==2.19.0" }, + "filelock": { + "hashes": [ + "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e", + "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c" + ], + "version": "==3.13.1" + }, "fiona": { "hashes": [ "sha256:35dae4b0308eb44617cdc4461ceb91f891d944fdebbcba5479efe524ec5db8de", @@ -793,51 +1108,51 @@ }, "fonttools": { "hashes": [ - "sha256:03ed3bda541e86725f6b4e1b94213f13ed1ae51a5a1f167028534cedea38c010", - "sha256:0dc7617d96b1e668eea9250e1c1fe62d0c78c3f69573ce7e3332cc40e6d84356", - "sha256:105099968b58a5b4cef6f3eb409db8ea8578b302a9d05e23fecba1b8b0177b5f", - "sha256:1b9e9ad2bcded9a1431afaa57c8d3c39143ac1f050862d66bddd863c515464a2", - "sha256:1f53a19dcdd5737440839b8394eeebb35da9ec8109f7926cb6456639b5b58e47", - "sha256:21e96b99878348c74aa58059b8578d7586f9519cbcdadacf56486737038aa043", - "sha256:2c980d60cd6ec1376206fe55013d166e5627ad0b149b5c81e74eaa913ab6134f", - "sha256:316cec50581e844c3ab69d7c82455b54c7cf18236b2f09e722faf665fbfcac58", - "sha256:37cd1ced6efb3dd6fe82e9f9bf92fd74ac58a5aefc284045f59ecd517a5fb9ab", - "sha256:392d0e3cc23daee910193625f7cf1b387aff9dd5b6f1a5f4a925680acb6dcbc2", - "sha256:3bdd7dfca8f6c9f4779384064027e8477ad6a037d6a327b09381f43e0247c6f3", - "sha256:43a3d267334109ff849c37cf3629476b5feb392ef1d2e464a167b83de8cd599c", - "sha256:45fa321c458ea29224067700954ec44493ae869b47e7c5485a350a149a19fb53", - "sha256:46eabddec12066829b8a1efe45ae552ba2f1796981ecf538d5f68284c354c589", - "sha256:4b9544b1346d99848ac0e9b05b5d45ee703d7562fc4c9c48cf4b781de9632e57", - "sha256:4ba17822a6681d06849078daaf6e03eccc9f467efe7c4c60280e28a78e8e5df9", - "sha256:5a17706b9cc24b27721613fe5773d93331ab7f0ecaca9955aead89c6b843d3a7", - "sha256:5cbf02cda8465b69769d07385f5d11e7bba19954e7787792f46fe679ec755ebb", - "sha256:6e441286d55fe7ec7c4fb36812bf914924813776ff514b744b510680fc2733f2", - "sha256:6eb2c54f7a07c92108daabcf02caf31df97825738db02a28270633946bcda4d0", - "sha256:777ba42b94a27bb7fb2b4082522fccfd345667c32a56011e1c3e105979af5b79", - "sha256:794de93e83297db7b4943f2431e206d8b1ea69cb3ae14638a49cc50332bf0db8", - "sha256:800e354e0c3afaeb8d9552769773d02f228e98c37b8cb03041157c3d0687cffc", - "sha256:847f3f49dd3423e5a678c098e2ba92c7f4955d4aab3044f6a507b0bb0ecb07e0", - "sha256:8717db3e4895e4820ade64ea379187738827ee60748223cb0438ef044ee208c6", - "sha256:8b07b857d4f9de3199a8c3d1b1bf2078c0f37447891ca1a8d9234106b9a27aff", - "sha256:8e1aefc2bf3c43e0f33f995f828a7bbeff4adc9393a7760b11456dbcf14388f6", - "sha256:a12dee6523c02ca78aeedd0a5e12bfa9b7b29896350edd5241542897b072ae23", - "sha256:a3c11d9687479f01eddef729aa737abcdea0a44fdaffb62a930a18892f186c9b", - "sha256:b6de2f0fcd3302fb82f94801002cb473959e998c14c24ec28234adb674aed345", - "sha256:ba299f1fbaa2a1e33210aaaf6fa816d4059e4d3cfe2ae9871368d4ab548c1c6a", - "sha256:ba6c23591427844dfb0a13658f1718489de75de6a46b64234584c0d17573162d", - "sha256:c4f4a5870e3b56788fb196da8cf30d0dfd51a76dc3b907861d018165f76ae4c2", - "sha256:cb472905da3049960e80fc1cf808231880d79727a8410e156bf3e5063a1c574f", - "sha256:cebcddbe9351b67166292b4f71ffdbfcce01ba4b07d4267824eb46b277aeb19a", - "sha256:e2277cba9f0b525e30de2a9ad3cb4219aa4bc697230c1645666b0deee9f914f0", - "sha256:e29d5f298d616a93a4c5963682dc6cc8cc09f6d89cad2c29019fc5fb3b4d9472", - "sha256:e3d24248221bd7151dfff0d88b1b5da02dccd7134bd576ce8888199827bbaa19", - "sha256:e50f794d09df0675da8d9dbd7c66bfcab2f74a708343aabcad41936d26556891", - "sha256:f22eb69996a0bd49f76bdefb30be54ce8dbb89a0d1246874d610f05c2aa2e69e", - "sha256:fb36e5f40191274a95938b40c0a1fa7f895e36935aea8709e1d6deff0b2d0d4f", - "sha256:ff6a698bdd435d24c379f6e8a54908cd9bb7dda23719084d56bf8c87709bf3bd" - ], - "markers": "python_version >= '3.8'", - "version": "==4.45.1" + "sha256:13ac0cba2fc63fa4b232f2a7971f35f35c6eaf10bd1271fa96d4ce6253a8acfd", + "sha256:156ae342a1ed1fe38e180de471e98fbf5b2b6ae280fa3323138569c4ca215844", + "sha256:1a9f9cdd7ef63d1b8ac90db335762451452426b3207abd79f60da510cea62da5", + "sha256:1c9937c4dd1061afd22643389445fabda858af5e805860ec3082a4bc07c7a720", + "sha256:25852f0c63df0af022f698464a4a80f7d1d5bd974bcd22f995f6b4ad198e32dd", + "sha256:2ae45716c27a41807d58a9f3f59983bdc8c0a46cb259e4450ab7e196253a9853", + "sha256:2c23c59d321d62588620f2255cf951270bf637d88070f38ed8b5e5558775b86c", + "sha256:2cf923a4a556ab4cc4c52f69a4a2db624cf5a2cf360394368b40c5152fe3321e", + "sha256:2d0eba685938c603f2f648dfc0aadbf8c6a4fe1c7ca608c2970a6ef39e00f254", + "sha256:3033b55f401a622de2630b3982234d97219d89b058607b87927eccb0f922313c", + "sha256:49ea0983e55fd7586a809787cd4644a7ae471e53ab8ddc016f9093b400e32646", + "sha256:5200b01f463d97cc2b7ff8a1e3584151f4413e98cb8419da5f17d1dbb84cc214", + "sha256:5b627ed142398ea9202bd752c04311592558964d1a765fb2f78dc441a05633f4", + "sha256:6d4a4ebcc76e30898ff3296ea786491c70e183f738319ae2629e0d44f17ece42", + "sha256:795150d5edc595e1a2cfb3d65e8f4f3d027704fc2579f8990d381bef6b188eb6", + "sha256:7b460720ce81773da1a3e7cc964c48e1e11942b280619582a897fa0117b56a62", + "sha256:7b5636f5706d49f13b6d610fe54ee662336cdf56b5a6f6683c0b803e23d826d2", + "sha256:8485cc468288e213f31afdaf1fdda3c79010f542559fbba936a54f4644df2570", + "sha256:87c214197712cc14fd2a4621efce2a9c501a77041232b789568149a8a3161517", + "sha256:87c3299da7da55394fb324349db0ede38114a46aafd0e7dfcabfecd28cdd94c3", + "sha256:89c2c520f9492844ecd6316d20c6c7a157b5c0cb73a1411b3db28ee304f30122", + "sha256:8be6adfa4e15977075278dd0a0bae74dec59be7b969b5ceed93fb86af52aa5be", + "sha256:8bee9f4fc8c99824a424ae45c789ee8c67cb84f8e747afa7f83b7d3cef439c3b", + "sha256:982f69855ac258260f51048d9e0c53c5f19881138cc7ca06deb38dc4b97404b6", + "sha256:9e6aeb5c340416d11a3209d75c48d13e72deea9e1517837dd1522c1fd1f17c11", + "sha256:a0e94244ec24a940ecfbe5b31c975c8a575d5ed2d80f9a280ce3b21fa5dc9c34", + "sha256:a4a50a1dfad7f7ba5ca3f99cc73bf5cdac67ceade8e4b355a877521f20ad1b63", + "sha256:a9fa52ef8fd14d7eb3d813e1451e7ace3e1eebfa9b7237d3f81fee8f3de6a114", + "sha256:adab73618d0a328b203a0e242b3eba60a2b5662d9cb2bd16ed9c52af8a7d86af", + "sha256:c506e3d3a9e898caee4dc094f34b49c5566870d5a2d1ca2125f0a9f35ecc2205", + "sha256:c779f8701deedf41908f287aeb775b8a6f59875ad1002b98ac6034ae4ddc1b7b", + "sha256:c94564b1f3b5dd87e73577610d85115b1936edcc596deaf84a31bbe70e17456b", + "sha256:c9a0e422ab79e5cb2b47913be6a4b5fd20c4c7ac34a24f3691a4e099e965e0b8", + "sha256:ca9eceebe70035b057ce549e2054cad73e95cac3fe91a9d827253d1c14618204", + "sha256:ce199227ce7921eaafdd4f96536f16b232d6b580ce74ce337de544bf06cb2752", + "sha256:d00fc63131dcac6b25f50a5a129758438317e54e3ce5587163f7058de4b0e933", + "sha256:d3d7b96aba96e05e8c911ce2dfc5acc6a178b8f44f6aa69371ab91aa587563da", + "sha256:d4e69e2c7f93b695d2e6f18f709d501d945f65c1d237dafaabdd23cd935a5276", + "sha256:e26e7fb908ae4f622813e7cb32cd2db6c24e3122bb3b98f25e832a2fe0e7e228", + "sha256:e5b7905fd68eacb7cc56a13139da5c312c45baae6950dd00b02563c54508a041", + "sha256:f5f1423a504ccc329efb5aa79738de83d38c072be5308788dde6bd419969d7f5", + "sha256:f8bc3973ed58893c4107993e0a7ae34901cb572b5e798249cbef35d30801ffd4" + ], + "markers": "python_version >= '3.8'", + "version": "==4.46.0" }, "fqdn": { "hashes": [ @@ -922,27 +1237,51 @@ }, "fsspec": { "hashes": [ - "sha256:b833e2e541e9e8cde0ab549414187871243177feb3d344f9d27b25a93f5d8139", - "sha256:fbae7f20ff801eb5f7d0bedf81f25c787c0dfac5e982d98fa3884a9cde2b5411" + "sha256:6271f1d3075a378bfe432f6f42bf7e1d2a6ba74f78dd9b512385474c579146a0", + "sha256:c4da01a35ac65c853f833e43f67802c25213f560820d54ddf248f92eddd5e990" ], - "markers": "python_version >= '3.7'", - "version": "==2023.1.0" + "markers": "python_version >= '3.8'", + "version": "==2023.12.1" + }, + "furo": { + "hashes": [ + "sha256:513092538537dc5c596691da06e3c370714ec99bc438680edc1debffb73e5bfc", + "sha256:5707530a476d2a63b8cad83b4f961f3739a69f4b058bcf38a03a39fa537195b2" + ], + "markers": "python_version >= '3.8'", + "version": "==2023.9.10" }, "gcsfs": { "hashes": [ - "sha256:0a7b7ca8c1affa126a14ba35d7b7dff81c49e2aaceedda9732c7f159a4837a26", - "sha256:62c491b9e2a8e9e58b8a899eec2ce111f827718a65539019ff3cadf447e48f41" + "sha256:c1ccfa9f84dca019cd334aaf7eb03cc1dc13c296717346927a9fd40255348f9c", + "sha256:e86cc583fdf879e5ea2f87bab61738d26ec7e8972762a1e6c6ab758b1e1af99c" ], - "markers": "python_version >= '3.7'", - "version": "==2023.1.0" + "markers": "python_version >= '3.8'", + "version": "==2023.12.1" }, "geopandas": { "hashes": [ - "sha256:0a470e4bf6f5367e6fd83ab6b40405e0b805c8174665bbcb7c4077ed90202912", - "sha256:0acdacddefa176525e4da6d9aeeece225da26055c4becdc6e97cf40fa97c27f4" + "sha256:4853ff89ecb6d1cfc43e7b3671092c8160e8a46a3dd7368f25906283314e42bb", + "sha256:ed5a7cae7874bfc3238fb05e0501cc1760e1b7b11e5b76ecad29da644ca305da" ], - "markers": "python_version >= '3.8'", - "version": "==0.12.2" + "markers": "python_version >= '3.9'", + "version": "==0.14.1" + }, + "gitdb": { + "hashes": [ + "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4", + "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b" + ], + "markers": "python_version >= '3.7'", + "version": "==4.0.11" + }, + "gitpython": { + "hashes": [ + "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4", + "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.40" }, "google-api-core": { "hashes": [ @@ -954,11 +1293,11 @@ }, "google-auth": { "hashes": [ - "sha256:79905d6b1652187def79d491d6e23d0cbb3a21d3c7ba0dbaa9c8a01906b13ff3", - "sha256:d4bbc92fe4b8bfd2f3e8d88e5ba7085935da208ee38a134fc280e7ce682a05f2" + "sha256:d5d66b8f4f6e3273740d7bb73ddefa6c2d1ff691704bd407d51c6b5800e7c97b", + "sha256:dfd7b44935d498e106c08883b2dac0ad36d8aa10402a6412e9a1c9d74b4773f1" ], "markers": "python_version >= '3.7'", - "version": "==2.23.4" + "version": "==2.25.1" }, "google-auth-oauthlib": { "hashes": [ @@ -1074,10 +1413,157 @@ "markers": "python_version >= '3.7'", "version": "==1.61.0" }, + "greenlet": { + "hashes": [ + "sha256:0a02d259510b3630f330c86557331a3b0e0c79dac3d166e449a39363beaae174", + "sha256:0b6f9f8ca7093fd4433472fd99b5650f8a26dcd8ba410e14094c1e44cd3ceddd", + "sha256:100f78a29707ca1525ea47388cec8a049405147719f47ebf3895e7509c6446aa", + "sha256:1757936efea16e3f03db20efd0cd50a1c86b06734f9f7338a90c4ba85ec2ad5a", + "sha256:19075157a10055759066854a973b3d1325d964d498a805bb68a1f9af4aaef8ec", + "sha256:19bbdf1cce0346ef7341705d71e2ecf6f41a35c311137f29b8a2dc2341374565", + "sha256:20107edf7c2c3644c67c12205dc60b1bb11d26b2610b276f97d666110d1b511d", + "sha256:22f79120a24aeeae2b4471c711dcf4f8c736a2bb2fabad2a67ac9a55ea72523c", + "sha256:2847e5d7beedb8d614186962c3d774d40d3374d580d2cbdab7f184580a39d234", + "sha256:28e89e232c7593d33cac35425b58950789962011cc274aa43ef8865f2e11f46d", + "sha256:329c5a2e5a0ee942f2992c5e3ff40be03e75f745f48847f118a3cfece7a28546", + "sha256:337322096d92808f76ad26061a8f5fccb22b0809bea39212cd6c406f6a7060d2", + "sha256:3fcc780ae8edbb1d050d920ab44790201f027d59fdbd21362340a85c79066a74", + "sha256:41bdeeb552d814bcd7fb52172b304898a35818107cc8778b5101423c9017b3de", + "sha256:4eddd98afc726f8aee1948858aed9e6feeb1758889dfd869072d4465973f6bfd", + "sha256:52e93b28db27ae7d208748f45d2db8a7b6a380e0d703f099c949d0f0d80b70e9", + "sha256:55d62807f1c5a1682075c62436702aaba941daa316e9161e4b6ccebbbf38bda3", + "sha256:5805e71e5b570d490938d55552f5a9e10f477c19400c38bf1d5190d760691846", + "sha256:599daf06ea59bfedbec564b1692b0166a0045f32b6f0933b0dd4df59a854caf2", + "sha256:60d5772e8195f4e9ebf74046a9121bbb90090f6550f81d8956a05387ba139353", + "sha256:696d8e7d82398e810f2b3622b24e87906763b6ebfd90e361e88eb85b0e554dc8", + "sha256:6e6061bf1e9565c29002e3c601cf68569c450be7fc3f7336671af7ddb4657166", + "sha256:80ac992f25d10aaebe1ee15df45ca0d7571d0f70b645c08ec68733fb7a020206", + "sha256:816bd9488a94cba78d93e1abb58000e8266fa9cc2aa9ccdd6eb0696acb24005b", + "sha256:85d2b77e7c9382f004b41d9c72c85537fac834fb141b0296942d52bf03fe4a3d", + "sha256:87c8ceb0cf8a5a51b8008b643844b7f4a8264a2c13fcbcd8a8316161725383fe", + "sha256:89ee2e967bd7ff85d84a2de09df10e021c9b38c7d91dead95b406ed6350c6997", + "sha256:8bef097455dea90ffe855286926ae02d8faa335ed8e4067326257cb571fc1445", + "sha256:8d11ebbd679e927593978aa44c10fc2092bc454b7d13fdc958d3e9d508aba7d0", + "sha256:91e6c7db42638dc45cf2e13c73be16bf83179f7859b07cfc139518941320be96", + "sha256:97e7ac860d64e2dcba5c5944cfc8fa9ea185cd84061c623536154d5a89237884", + "sha256:990066bff27c4fcf3b69382b86f4c99b3652bab2a7e685d968cd4d0cfc6f67c6", + "sha256:9fbc5b8f3dfe24784cee8ce0be3da2d8a79e46a276593db6868382d9c50d97b1", + "sha256:ac4a39d1abae48184d420aa8e5e63efd1b75c8444dd95daa3e03f6c6310e9619", + "sha256:b2c02d2ad98116e914d4f3155ffc905fd0c025d901ead3f6ed07385e19122c94", + "sha256:b2d3337dcfaa99698aa2377c81c9ca72fcd89c07e7eb62ece3f23a3fe89b2ce4", + "sha256:b489c36d1327868d207002391f662a1d163bdc8daf10ab2e5f6e41b9b96de3b1", + "sha256:b641161c302efbb860ae6b081f406839a8b7d5573f20a455539823802c655f63", + "sha256:b8ba29306c5de7717b5761b9ea74f9c72b9e2b834e24aa984da99cbfc70157fd", + "sha256:b9934adbd0f6e476f0ecff3c94626529f344f57b38c9a541f87098710b18af0a", + "sha256:ce85c43ae54845272f6f9cd8320d034d7a946e9773c693b27d620edec825e376", + "sha256:cf868e08690cb89360eebc73ba4be7fb461cfbc6168dd88e2fbbe6f31812cd57", + "sha256:d2905ce1df400360463c772b55d8e2518d0e488a87cdea13dd2c71dcb2a1fa16", + "sha256:d57e20ba591727da0c230ab2c3f200ac9d6d333860d85348816e1dca4cc4792e", + "sha256:d6a8c9d4f8692917a3dc7eb25a6fb337bff86909febe2f793ec1928cd97bedfc", + "sha256:d923ff276f1c1f9680d32832f8d6c040fe9306cbfb5d161b0911e9634be9ef0a", + "sha256:daa7197b43c707462f06d2c693ffdbb5991cbb8b80b5b984007de431493a319c", + "sha256:dbd4c177afb8a8d9ba348d925b0b67246147af806f0b104af4d24f144d461cd5", + "sha256:dc4d815b794fd8868c4d67602692c21bf5293a75e4b607bb92a11e821e2b859a", + "sha256:e9d21aaa84557d64209af04ff48e0ad5e28c5cca67ce43444e939579d085da72", + "sha256:ea6b8aa9e08eea388c5f7a276fabb1d4b6b9d6e4ceb12cc477c3d352001768a9", + "sha256:eabe7090db68c981fca689299c2d116400b553f4b713266b130cfc9e2aa9c5a9", + "sha256:f2f6d303f3dee132b322a14cd8765287b8f86cdc10d2cb6a6fae234ea488888e", + "sha256:f33f3258aae89da191c6ebaa3bc517c6c4cbc9b9f689e5d8452f7aedbb913fa8", + "sha256:f7bfb769f7efa0eefcd039dd19d843a4fbfbac52f1878b1da2ed5793ec9b1a65", + "sha256:f89e21afe925fcfa655965ca8ea10f24773a1791400989ff32f467badfe4a064", + "sha256:fa24255ae3c0ab67e613556375a4341af04a084bd58764731972bcbc8baeba36" + ], + "markers": "platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))", + "version": "==3.0.1" + }, "gridemissions": { - "git": "git+https://github.com/gailin-p/gridemissions#egg=gridemissions", + "git": "git+https://github.com/gailin-p/gridemissions", "ref": "0cbe7620620f02ab91227940ef107b53bd1f9bb4" }, + "grpcio": { + "hashes": [ + "sha256:023088764012411affe7db183d1ada3ad9daf2e23ddc719ff46d7061de661340", + "sha256:08d77e682f2bf730a4961eea330e56d2f423c6a9b91ca222e5b1eb24a357b19f", + "sha256:0a4a3833c0e067f3558538727235cd8a49709bff1003200bbdefa2f09334e4b1", + "sha256:0a754aff9e3af63bdc4c75c234b86b9d14e14a28a30c4e324aed1a9b873d755f", + "sha256:11168ef43e4a43ff1b1a65859f3e0ef1a173e277349e7fb16923ff108160a8cd", + "sha256:128e20f57c5f27cb0157e73756d1586b83c1b513ebecc83ea0ac37e4b0e4e758", + "sha256:1f9524d1d701e399462d2c90ba7c193e49d1711cf429c0d3d97c966856e03d00", + "sha256:1ff16d68bf453275466a9a46739061a63584d92f18a0f5b33d19fc97eb69867c", + "sha256:2067274c88bc6de89c278a672a652b4247d088811ece781a4858b09bdf8448e3", + "sha256:2171c39f355ba5b551c5d5928d65aa6c69807fae195b86ef4a7d125bcdb860a9", + "sha256:242adc47725b9a499ee77c6a2e36688fa6c96484611f33b1be4c57ab075a92dd", + "sha256:27f879ae604a7fcf371e59fba6f3ff4635a4c2a64768bd83ff0cac503142fef4", + "sha256:2b230028a008ae1d0f430acb227d323ff8a619017415cf334c38b457f814119f", + "sha256:3059668df17627f0e0fa680e9ef8c995c946c792612e9518f5cc1503be14e90b", + "sha256:31176aa88f36020055ace9adff2405a33c8bdbfa72a9c4980e25d91b2f196873", + "sha256:36f53c2b3449c015880e7d55a89c992c357f176327b0d2873cdaaf9628a37c69", + "sha256:3b4368b33908f683a363f376dfb747d40af3463a6e5044afee07cf9436addf96", + "sha256:3c61d641d4f409c5ae46bfdd89ea42ce5ea233dcf69e74ce9ba32b503c727e29", + "sha256:4abb717e320e74959517dc8e84a9f48fbe90e9abe19c248541e9418b1ce60acd", + "sha256:4c93f4abbb54321ee6471e04a00139c80c754eda51064187963ddf98f5cf36a4", + "sha256:535561990e075fa6bd4b16c4c3c1096b9581b7bb35d96fac4650f1181e428268", + "sha256:53c9aa5ddd6857c0a1cd0287225a2a25873a8e09727c2e95c4aebb1be83a766a", + "sha256:5d573e70a6fe77555fb6143c12d3a7d3fa306632a3034b4e7c59ca09721546f8", + "sha256:6009386a2df66159f64ac9f20425ae25229b29b9dd0e1d3dd60043f037e2ad7e", + "sha256:686e975a5d16602dc0982c7c703948d17184bd1397e16c8ee03511ecb8c4cdda", + "sha256:6959fb07e8351e20501ffb8cc4074c39a0b7ef123e1c850a7f8f3afdc3a3da01", + "sha256:6b25ed37c27e652db01be341af93fbcea03d296c024d8a0e680017a268eb85dd", + "sha256:6da6dea3a1bacf99b3c2187e296db9a83029ed9c38fd4c52b7c9b7326d13c828", + "sha256:72ca2399097c0b758198f2ff30f7178d680de8a5cfcf3d9b73a63cf87455532e", + "sha256:73abb8584b0cf74d37f5ef61c10722adc7275502ab71789a8fe3cb7ef04cf6e2", + "sha256:74100fecaec8a535e380cf5f2fb556ff84957d481c13e54051c52e5baac70541", + "sha256:75c6ecb70e809cf1504465174343113f51f24bc61e22a80ae1c859f3f7034c6d", + "sha256:7cf05053242f61ba94014dd3a986e11a083400a32664058f80bf4cf817c0b3a1", + "sha256:9411e24328a2302e279e70cae6e479f1fddde79629fcb14e03e6d94b3956eabf", + "sha256:a213acfbf186b9f35803b52e4ca9addb153fc0b67f82a48f961be7000ecf6721", + "sha256:bb7e0fe6ad73b7f06d7e2b689c19a71cf5cc48f0c2bf8608469e51ffe0bd2867", + "sha256:c2504eed520958a5b77cc99458297cb7906308cb92327f35fb7fbbad4e9b2188", + "sha256:c35aa9657f5d5116d23b934568e0956bd50c615127810fffe3ac356a914c176a", + "sha256:c5f09cffa619adfb44799fa4a81c2a1ad77c887187613fb0a8f201ab38d89ba1", + "sha256:c978f864b35f2261e0819f5cd88b9830b04dc51bcf055aac3c601e525a10d2ba", + "sha256:cbe946b3e6e60a7b4618f091e62a029cb082b109a9d6b53962dd305087c6e4fd", + "sha256:cc3e4cd087f07758b16bef8f31d88dbb1b5da5671d2f03685ab52dece3d7a16e", + "sha256:cf0dead5a2c5a3347af2cfec7131d4f2a2e03c934af28989c9078f8241a491fa", + "sha256:d2794f0e68b3085d99b4f6ff9c089f6fdd02b32b9d3efdfbb55beac1bf22d516", + "sha256:d2fa68a96a30dd240be80bbad838a0ac81a61770611ff7952b889485970c4c71", + "sha256:d6f70406695e3220f09cd7a2f879333279d91aa4a8a1d34303b56d61a8180137", + "sha256:d8f9cd4ad1be90b0cf350a2f04a38a36e44a026cac1e036ac593dc48efe91d52", + "sha256:da2d94c15f88cd40d7e67f7919d4f60110d2b9d5b1e08cf354c2be773ab13479", + "sha256:e1727c1c0e394096bb9af185c6923e8ea55a5095b8af44f06903bcc0e06800a2", + "sha256:e420ced29b5904cdf9ee5545e23f9406189d8acb6750916c2db4793dada065c6", + "sha256:e82c5cf1495244adf5252f925ac5932e5fd288b3e5ab6b70bec5593074b7236c", + "sha256:f1ef0d39bc1feb420caf549b3c657c871cad4ebbcf0580c4d03816b0590de0cf", + "sha256:f8753a6c88d1d0ba64302309eecf20f70d2770f65ca02d83c2452279085bfcd3", + "sha256:f93dbf58f03146164048be5426ffde298b237a5e059144847e4940f5b80172c3" + ], + "markers": "python_version >= '3.7'", + "version": "==1.59.2" + }, + "grpcio-health-checking": { + "hashes": [ + "sha256:7855830a404c8683cc16ff0348443a1a60919a0d2e7265d2bc801071053602da", + "sha256:e0c544ef4219f9698c94ebd598d3a738fddb56a4032c10f2d2b883543006d091" + ], + "markers": "python_version >= '3.6'", + "version": "==1.59.2" + }, + "grpcio-status": { + "hashes": [ + "sha256:24bdf3b3b83b9112f43bd0626f82510d12cc1d919a45028ac20eb6919218e508", + "sha256:a2c2b146e66b73ba80d021ab34fce5db4dd9be67ca4566cda40d36b185ce54f4" + ], + "markers": "python_version >= '3.6'", + "version": "==1.59.2" + }, + "h11": { + "hashes": [ + "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", + "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761" + ], + "markers": "python_version >= '3.7'", + "version": "==0.14.0" + }, "h3": { "hashes": [ "sha256:02faa911f2d8425c641a1f7c08f3dc9c10a5a3d81408832afa40748534b999c8", @@ -1121,6 +1607,30 @@ ], "version": "==3.7.6" }, + "html5lib": { + "hashes": [ + "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", + "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.1" + }, + "httpcore": { + "hashes": [ + "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7", + "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535" + ], + "markers": "python_version >= '3.8'", + "version": "==1.0.2" + }, + "httpx": { + "hashes": [ + "sha256:8b8fcaa0c8ea7b05edd69a094e63a2094c4efcb48129fb757361bc423c0ad9e8", + "sha256:a05d3d052d9b2dfce0e3896636467f8a5342fb2b902c819428e1ac65413ca118" + ], + "markers": "python_version >= '3.8'", + "version": "==0.25.2" + }, "humanfriendly": { "hashes": [ "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", @@ -1129,6 +1639,30 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==10.0" }, + "hupper": { + "hashes": [ + "sha256:18b1653d9832c9f8e7d3401986c7e7af2ae6783616be0bc406bfe0b14134a5c6", + "sha256:b8bc41bb75939e816f30f118026d0ba99544af4d6992583df3b4813765af27ef" + ], + "markers": "python_version >= '3.7'", + "version": "==1.12" + }, + "hypothesis": { + "hashes": [ + "sha256:316e06d6f7d5f8ab87bcc7417fca750a2b082ed3ce902b979816b413276680b3", + "sha256:a9f61a2bcfc342febcc1d04b80a99e789c57b700f91cbd43bbdb5d651af385cd" + ], + "markers": "python_version >= '3.8'", + "version": "==6.91.0" + }, + "identify": { + "hashes": [ + "sha256:0b7656ef6cba81664b783352c73f8c24b39cf82f926f78f4550eda928e5e0545", + "sha256:5d9979348ec1a21c768ae07e0a652924538e8bce67313a73cb0f681cf08ba407" + ], + "markers": "python_version >= '3.8'", + "version": "==2.5.32" + }, "idna": { "hashes": [ "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", @@ -1231,6 +1765,22 @@ ], "version": "==3.2.3" }, + "imagesize": { + "hashes": [ + "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", + "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.4.1" + }, + "importlib-metadata": { + "hashes": [ + "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7", + "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67" + ], + "markers": "python_version >= '3.8'", + "version": "==7.0.0" + }, "iniconfig": { "hashes": [ "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", @@ -1256,6 +1806,14 @@ "markers": "python_version >= '3.9'", "version": "==8.18.1" }, + "ipywidgets": { + "hashes": [ + "sha256:2b88d728656aea3bbfd05d32c747cfd0078f9d7e159cf982433b58ad717eed7f", + "sha256:40211efb556adec6fa450ccc2a77d59ca44a060f4f9f136833df59c9f538e6e8" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.1" + }, "isodate": { "hashes": [ "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96", @@ -1270,6 +1828,30 @@ ], "version": "==20.11.0" }, + "itsdangerous": { + "hashes": [ + "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", + "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a" + ], + "markers": "python_version >= '3.7'", + "version": "==2.1.2" + }, + "janus": { + "hashes": [ + "sha256:2596ea5482711c1ee3ef2df6c290aaf370a13c55a007826e8f7c32d696d1d00a", + "sha256:df976f2cdcfb034b147a2d51edfc34ff6bfb12d4e2643d3ad0e10de058cb1612" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.0" + }, + "jaraco.classes": { + "hashes": [ + "sha256:10afa92b6743f25c0cf5f37c6bb6e18e2c5bb84a16527ccfc0040ea377e7aaeb", + "sha256:c063dd08e89217cee02c8d5e5ec560f2c8ce6cdc2fcdc2e68f7b2e5547ed3621" + ], + "markers": "python_version >= '3.8'", + "version": "==3.3.0" + }, "jedi": { "hashes": [ "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd", @@ -1278,6 +1860,77 @@ "markers": "python_version >= '3.6'", "version": "==0.19.1" }, + "jellyfish": { + "hashes": [ + "sha256:004f6ab661ae4c591be1aed604fbf5976415f1bd771274d29ecdd59b82ef0518", + "sha256:024d58f45d24565a0ccd129a1a90bb85f9e3fa4ddd4f50dbbd3ac39feac0bb7b", + "sha256:0271686a4e0cfa67a62ae151e71ef556df1b562373a29d107c3bff4f2308d3ec", + "sha256:0281e85aaa1a6edead83a66801a3ad24da27f80bee1efc6ff85ac7fa10069270", + "sha256:06d75c438a735a689986ba6a199daa60da30515dd99696b08c10c800b08a8725", + "sha256:0a5fff421ec821d37ad316f1f8e7706c5868d662d1dadcdbefd38ba1df45152d", + "sha256:0ad15b58b808c76082b19c606a7a32d4c2c92520bbcb3a5c637e36520248e18b", + "sha256:11f98c3041dbc80229916809b7a4aa9cc27142f385b6f334d9d8215b217fe87a", + "sha256:141665836bb227e6c7e16195b292c8e0624ad6ba48471984c7d5a593876ba16b", + "sha256:1472d4dc90b9af65c7ebeea846535f507c693411bacfd5ec954ea65454211e19", + "sha256:1c3be01748738812d4674eb6badcd7e42a885700a4a50c8872683bd3687b58ec", + "sha256:2f581d9b5b9e4f1967b980a31c584f01e62fc6ab24f94834a55d343bd438ccee", + "sha256:318169ed003949a177536f9d6ee240997056caef75e37a66e7ade1e7d6e9fa4a", + "sha256:335f9798c5e7d03d1af748347d69cda740b71baf23a7f03275bf7b8b13d87fba", + "sha256:36e5b76447f91f08af1eda5c880aec00533e49517e206ea1b856e956f2a721bc", + "sha256:3ce7aeb268acecec02f8f863a8343641064cb83d3d2fc44f4b2ca9fb31a1395d", + "sha256:4351398fee07578d232625deb8fdadf7949c322e68ffd9e50b374ff0429d4071", + "sha256:45a20a9ab3bfbc7983f60548aa5aff02408bb64de959a765636f8e1b5167266a", + "sha256:484051e6eaa55063e8683dca4336acff5d66c794b8517d569f4055e3df38a789", + "sha256:488f7174aeb759c92c9deadf393f81b38178f9397690d8692fd319fe943b313f", + "sha256:48dd2b6165dae690d051a9b39f92cf37f8e583c7ac64c83718d07ba7dc68a7f8", + "sha256:54c862cbc866aa45521d9a01100c1a3d7b305ebde2b4d7606cbd6c82350fdfa0", + "sha256:553f195f2d24702b8586c6bd73a938c028d417f58ca4aaf735d827db7e21e827", + "sha256:5932f7d0643db9deb09de50770fa7fd872f4e76d39686568d2a63bd3e4af16bb", + "sha256:5aea474cf64998eb102d622944fde3d9198b17a2ec36ed1cae34fdb1887015fb", + "sha256:5b957602492ae611e052bc945693b91e9ab2bf1c11273c731f5ac718721d6e6e", + "sha256:61f0317789d139456c678f7a68a93130d3c0227e76d200cbeedf156719747d8f", + "sha256:643315eb140af1bbfffb6d38b0371920c875ca3ec3fa0403b851bd50b9a9603c", + "sha256:65e4256c44963337fcc63897f01f4a754bdc17e4d740bceb55c04ab94ca9c07e", + "sha256:66ea8a7fe23f7794be55e36aac538c37ddb9cd21282779ac21afb06b280d6a96", + "sha256:6e827f40d976a04502c21d20f8b788ef585f8a04a3c1b8b9b896492b463c5f94", + "sha256:70afd781d99e04e9749991a2e5f8c78a0b2fc28076b9e30d7ff71ac421327747", + "sha256:70d9bf2fec251dcfa96443ec6710e845ebdeabf254252090c2614843a56753dd", + "sha256:7432c1d5c37563f913537716473b59466d2e8494aaf15bcd80f1778aa87365f2", + "sha256:7bf482b872dea6267fd486957bb018c69f11618130f0e2e2cd04a9dd64be32f5", + "sha256:80b0330071a52a33a1d816f7058798196d613916258565ee5f1cf9d1165c95bc", + "sha256:8299663d497c0357b92023cf457b485d43d2e969da287f345ab128d145e9f73d", + "sha256:8909ada3ca12e327b10e46e63b4db7d59a2ebea489dc6d1f7f7569fc89a728cf", + "sha256:8b25acc9df837be60f72841a3c658bb74fdacb108631d67cb4c92eebf6bb2729", + "sha256:92e17def9f6a3f6d6e7bc49040907a969ab6c1acd5bbc5db92fd65662f509ee4", + "sha256:9a52bbd1d71f6de4fd0f24e2673deffcd93289eea6b973887ebd5d45edc865c6", + "sha256:9af1447ebff6e8429ccd09ae632becb5612a0ea6bd9eb3aa8c2069a5586b0455", + "sha256:9ffdec3137b4fbeadcf3ba49b75139e3271bd0fb3fa947ebb39c9d5a3af1db9e", + "sha256:a2ce180fd087425e9a6f94979c84657cd91f331c3811b146c83605465d78130c", + "sha256:a53b8636935f169bf928140ff09207c3cb24cbd76d87a1fd11785061cc7c57d3", + "sha256:abd8388161df3ec6469b7b6fdad1066efb3958d885b7390ed105824c7e4ac68f", + "sha256:b9dc71748365e9de24cca05920d17ef709a31a37c791105e049e37cfbccac3f5", + "sha256:bb10db8375fec009fd5880de8158d6c4e43f09333297e53301a4579f526b39a6", + "sha256:bbc5e8285bc38b10fba020154f0ba4b0a7af8e5bd95d28a48ff9bedca0a32bbe", + "sha256:bbfd54e277ee4c72c383b9feeb8e1596466a17299508864892d76ba6a41a8d03", + "sha256:c53895523a7a911621c4f46ffafb234ddbcd467a0e63782304c68652ba8dea41", + "sha256:c59f5cdc04b62f8f4ff4575dcda66c3def012ede0049d8e199981cd155cb74c5", + "sha256:c5aa3b4775c9eb7c814eb0eab5632b5ff476fdfea2be83b10d40bb821e01aa05", + "sha256:cad69bc4174757abfc232c2741e3a6e08ad2050be9d84d91f58ff0936a8cce40", + "sha256:d5d01941cd21ff57e41713c77786654f513cca2ace73f7ad53aefdf952600d06", + "sha256:d606654953309a37b2f0ceaa3bfb26eeecc50d05577a037ac1f55f96f963e4a2", + "sha256:da254a29f9ea2c5548fe02e42d0d361de566a92c6e7aef991eb6640d18b6f4b5", + "sha256:ddb22b7155f208e088352283ee78cb4ef2d2067a76e148a8bb43d177f32b37d2", + "sha256:e162ab1c140a6ceb44a7d13e53b94a0ad5f796a4b1389bb91dc6448f7cfecd73", + "sha256:e164002d9171a3c1dc6e256a6ab7c3c61f9e0dcb5a1eec77846e664cc1b10e6d", + "sha256:ee1a1db7bb5c240031d7769301fd5291a40997df76e68d322a2aa9b4f3fd7ba4", + "sha256:f56a005e0bbbb45e465904db014e76020edc12ebe042bf5b4705089e14a07480", + "sha256:fab07dedd2d30af9da37c1b80c0a44bde8e2dbff240064beaf33bb6d6d6b3228", + "sha256:face52972a7c8d2538aec5bdbc4c863a7f2b3c5def88a6e6977fcaec8acefc92", + "sha256:fafbc56ceaf88563aaf40b00c90b3a75d2d115a01082170091cab77fb14ca8d5" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.3" + }, "jinja2": { "hashes": [ "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", @@ -1338,11 +1991,19 @@ }, "jsonschema-specifications": { "hashes": [ - "sha256:c9b234904ffe02f079bf91b14d79987faa685fd4b39c377a0996954c0090b9ca", - "sha256:f596778ab612b3fd29f72ea0d990393d0540a5aab18bf0407a46632eab540779" + "sha256:9472fc4fea474cd74bea4a2b190daeccb5a9e4db2ea80efcf7a1b582fc9a81b8", + "sha256:e74ba7c0a65e8cb49dc26837d6cfe576557084a8b423ed16a420984228104f93" ], "markers": "python_version >= '3.8'", - "version": "==2023.11.1" + "version": "==2023.11.2" + }, + "jupyter": { + "hashes": [ + "sha256:3e1f86076bbb7c8c207829390305a2b1fe836d471ed54be66a3b8c41e7f46cc7", + "sha256:5b290f93b98ffbc21c0c7e749f054b3267782166d72fa5e3ed1ed4eaf34a2b78", + "sha256:d9dc4b3318f310e34c82951ea5d6683f67bed7def4b259fafbfe4f1beb1d8e5f" + ], + "version": "==1.0.0" }, "jupyter-client": { "hashes": [ @@ -1352,6 +2013,14 @@ "markers": "python_version >= '3.8'", "version": "==8.6.0" }, + "jupyter-console": { + "hashes": [ + "sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485", + "sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539" + ], + "markers": "python_version >= '3.7'", + "version": "==6.6.3" + }, "jupyter-core": { "hashes": [ "sha256:880b86053bf298a8724994f95e99b99130659022a4f7f45f563084b6223861d3", @@ -1378,11 +2047,11 @@ }, "jupyter-server": { "hashes": [ - "sha256:4b3a16e3ed16fd202588890f10b8ca589bd3e29405d128beb95935f059441373", - "sha256:fe80bab96493acf5f7d6cd9a1575af8fbd253dc2591aa4d015131a1e03b5799a" + "sha256:dc77b7dcc5fc0547acba2b2844f01798008667201eea27c6319ff9257d700a6d", + "sha256:fd030dd7be1ca572e4598203f718df6630c12bd28a599d7f1791c4d7938e1010" ], "markers": "python_version >= '3.8'", - "version": "==2.11.1" + "version": "==2.12.1" }, "jupyter-server-terminals": { "hashes": [ @@ -1416,6 +2085,22 @@ "markers": "python_version >= '3.8'", "version": "==2.25.2" }, + "jupyterlab-widgets": { + "hashes": [ + "sha256:3cf5bdf5b897bf3bccf1c11873aa4afd776d7430200f765e0686bd352487b58d", + "sha256:6005a4e974c7beee84060fdfba341a3218495046de8ae3ec64888e5fe19fdb4c" + ], + "markers": "python_version >= '3.7'", + "version": "==3.0.9" + }, + "keyring": { + "hashes": [ + "sha256:4446d35d636e6a10b8bce7caa66913dd9eca5fd222ca03a3d42c38608ac30836", + "sha256:e730ecffd309658a08ee82535a3b5ec4b4c8669a9be11efb66249d8e0aeb9a25" + ], + "markers": "python_version >= '3.8'", + "version": "==24.3.0" + }, "kiwisolver": { "hashes": [ "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf", @@ -1526,12 +2211,50 @@ "markers": "python_version >= '3.7'", "version": "==1.4.5" }, + "latexcodec": { + "hashes": [ + "sha256:2aa2551c373261cefe2ad3a8953a6d6533e68238d180eb4bb91d7964adb3fe9a", + "sha256:c277a193638dc7683c4c30f6684e3db728a06efb0dc9cf346db8bd0aa6c5d271" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.0.1" + }, "linear-tsv": { "hashes": [ "sha256:b504d78f4075615ae75de86a16e5680701a441fc84da2a2cf9f94351ab1ccbf5" ], "version": "==1.1.0" }, + "llvmlite": { + "hashes": [ + "sha256:04725975e5b2af416d685ea0769f4ecc33f97be541e301054c9f741003085802", + "sha256:0dd0338da625346538f1173a17cabf21d1e315cf387ca21b294ff209d176e244", + "sha256:150d0bc275a8ac664a705135e639178883293cf08c1a38de3bbaa2f693a0a867", + "sha256:1eee5cf17ec2b4198b509272cf300ee6577229d237c98cc6e63861b08463ddc6", + "sha256:210e458723436b2469d61b54b453474e09e12a94453c97ea3fbb0742ba5a83d8", + "sha256:2181bb63ef3c607e6403813421b46982c3ac6bfc1f11fa16a13eaafb46f578e6", + "sha256:24091a6b31242bcdd56ae2dbea40007f462260bc9bdf947953acc39dffd54f8f", + "sha256:2b76acee82ea0e9304be6be9d4b3840208d050ea0dcad75b1635fa06e949a0ae", + "sha256:2d92c51e6e9394d503033ffe3292f5bef1566ab73029ec853861f60ad5c925d0", + "sha256:5940bc901fb0325970415dbede82c0b7f3e35c2d5fd1d5e0047134c2c46b3281", + "sha256:8454c1133ef701e8c050a59edd85d238ee18bb9a0eb95faf2fca8b909ee3c89a", + "sha256:855f280e781d49e0640aef4c4af586831ade8f1a6c4df483fb901cbe1a48d127", + "sha256:880cb57ca49e862e1cd077104375b9d1dfdc0622596dfa22105f470d7bacb309", + "sha256:8b0a9a47c28f67a269bb62f6256e63cef28d3c5f13cbae4fab587c3ad506778b", + "sha256:92c32356f669e036eb01016e883b22add883c60739bc1ebee3a1cc0249a50828", + "sha256:92f093986ab92e71c9ffe334c002f96defc7986efda18397d0f08534f3ebdc4d", + "sha256:9564c19b31a0434f01d2025b06b44c7ed422f51e719ab5d24ff03b7560066c9a", + "sha256:b67340c62c93a11fae482910dc29163a50dff3dfa88bc874872d28ee604a83be", + "sha256:bf14aa0eb22b58c231243dccf7e7f42f7beec48970f2549b3a6acc737d1a4ba4", + "sha256:c1e1029d47ee66d3a0c4d6088641882f75b93db82bd0e6178f7bd744ebce42b9", + "sha256:df75594e5a4702b032684d5481db3af990b69c249ccb1d32687b8501f0689432", + "sha256:f19f767a018e6ec89608e1f6b13348fa2fcde657151137cb64e56d48598a92db", + "sha256:f8afdfa6da33f0b4226af8e64cfc2b28986e005528fbf944d0a24a72acfc9432", + "sha256:fa1469901a2e100c17eb8fe2678e34bd4255a3576d1a543421356e9c14d6e2ae" + ], + "markers": "python_version >= '3.8'", + "version": "==0.41.1" + }, "locket": { "hashes": [ "sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632", @@ -1638,6 +2361,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==4.9.3" }, + "mako": { + "hashes": [ + "sha256:57d4e997349f1a92035aa25c17ace371a4213f2ca42f99bee9a602500cfd54d9", + "sha256:e3a9d388fd00e87043edbe8792f45880ac0114e9c4adc69f6e9bfb2c55e3b11b" + ], + "markers": "python_version >= '3.8'", + "version": "==1.3.0" + }, "markdown-it-py": { "hashes": [ "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", @@ -1722,50 +2453,37 @@ }, "matplotlib": { "hashes": [ - "sha256:01b7f521a9a73c383825813af255f8c4485d1706e4f3e2ed5ae771e4403a40ab", - "sha256:11011c97d62c1db7bc20509572557842dbb8c2a2ddd3dd7f20501aa1cde3e54e", - "sha256:1183877d008c752d7d535396096c910f4663e4b74a18313adee1213328388e1e", - "sha256:12f999661589981e74d793ee2f41b924b3b87d65fd929f6153bf0f30675c59b1", - "sha256:1c235bf9be052347373f589e018988cad177abb3f997ab1a2e2210c41562cc0c", - "sha256:1f4d69707b1677560cd952544ee4962f68ff07952fb9069ff8c12b56353cb8c9", - "sha256:1fcc4cad498533d3c393a160975acc9b36ffa224d15a6b90ae579eacee5d8579", - "sha256:2787a16df07370dcba385fe20cdd0cc3cfaabd3c873ddabca78c10514c799721", - "sha256:29f17b7f2e068dc346687cbdf80b430580bab42346625821c2d3abf3a1ec5417", - "sha256:38d38cb1ea1d80ee0f6351b65c6f76cad6060bbbead015720ba001348ae90f0c", - "sha256:3f56a7252eee8f3438447f75f5e1148a1896a2756a92285fe5d73bed6deebff4", - "sha256:5223affa21050fb6118353c1380c15e23aedfb436bf3e162c26dc950617a7519", - "sha256:57ad1aee29043163374bfa8990e1a2a10ff72c9a1bfaa92e9c46f6ea59269121", - "sha256:59400cc9451094b7f08cc3f321972e6e1db4cd37a978d4e8a12824bf7fd2f03b", - "sha256:68d94a436f62b8a861bf3ace82067a71bafb724b4e4f9133521e4d8012420dd7", - "sha256:6adc441b5b2098a4b904bbf9d9e92fb816fef50c55aa2ea6a823fc89b94bb838", - "sha256:6d81b11ede69e3a751424b98dc869c96c10256b2206bfdf41f9c720eee86844c", - "sha256:73b93af33634ed919e72811c9703e1105185cd3fb46d76f30b7f4cfbbd063f89", - "sha256:77b384cee7ab8cf75ffccbfea351a09b97564fc62d149827a5e864bec81526e5", - "sha256:79e501eb847f4a489eb7065bb8d3187117f65a4c02d12ea3a19d6c5bef173bcc", - "sha256:809119d1cba3ece3c9742eb01827fe7a0e781ea3c5d89534655a75e07979344f", - "sha256:80c166a0e28512e26755f69040e6bf2f946a02ffdb7c00bf6158cca3d2b146e6", - "sha256:81b409b2790cf8d7c1ef35920f01676d2ae7afa8241844e7aa5484fdf493a9a0", - "sha256:994637e2995b0342699b396a320698b07cd148bbcf2dd2fa2daba73f34dd19f2", - "sha256:9ceebaf73f1a3444fa11014f38b9da37ff7ea328d6efa1652241fe3777bfdab9", - "sha256:9fb8fb19d03abf3c5dab89a8677e62c4023632f919a62b6dd1d6d2dbf42cd9f5", - "sha256:acc3b1a4bddbf56fe461e36fb9ef94c2cb607fc90d24ccc650040bfcc7610de4", - "sha256:bbddfeb1495484351fb5b30cf5bdf06b3de0bc4626a707d29e43dfd61af2a780", - "sha256:bbf269e1d24bc25247095d71c7a969813f7080e2a7c6fa28931a603f747ab012", - "sha256:bebcff4c3ed02c6399d47329f3554193abd824d3d53b5ca02cf583bcd94470e2", - "sha256:c3f08df2ac4636249b8bc7a85b8b82c983bef1441595936f62c2918370ca7e1d", - "sha256:ca94f0362f6b6f424b555b956971dcb94b12d0368a6c3e07dc7a40d32d6d873d", - "sha256:d00c248ab6b92bea3f8148714837937053a083ff03b4c5e30ed37e28fc0e7e56", - "sha256:d2cfaa7fd62294d945b8843ea24228a27c8e7c5b48fa634f3c168153b825a21b", - "sha256:d5f18430f5cfa5571ab8f4c72c89af52aa0618e864c60028f11a857d62200cba", - "sha256:debeab8e2ab07e5e3dac33e12456da79c7e104270d2b2d1df92b9e40347cca75", - "sha256:dfba7057609ca9567b9704626756f0142e97ec8c5ba2c70c6e7bd1c25ef99f06", - "sha256:e0a64d7cc336b52e90f59e6d638ae847b966f68582a7af041e063d568e814740", - "sha256:eb9421c403ffd387fbe729de6d9a03005bf42faba5e8432f4e51e703215b49fc", - "sha256:faff486b36530a836a6b4395850322e74211cd81fc17f28b4904e1bd53668e3e", - "sha256:ff2aa84e74f80891e6bcf292ebb1dd57714ffbe13177642d65fee25384a30894" - ], - "markers": "python_version >= '3.8'", - "version": "==3.6.3" + "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1", + "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0", + "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4", + "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7", + "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630", + "sha256:172f4d0fbac3383d39164c6caafd3255ce6fa58f08fc392513a0b1d3b89c4f89", + "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d", + "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717", + "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a", + "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627", + "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31", + "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213", + "sha256:5864bdd7da445e4e5e011b199bb67168cdad10b501750367c496420f2ad00843", + "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788", + "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367", + "sha256:7c48d9e221b637c017232e3760ed30b4e8d5dfd081daf327e829bf2a72c731b4", + "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a", + "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8", + "sha256:aa11b3c6928a1e496c1a79917d51d4cd5d04f8a2e75f21df4949eeefdf697f4b", + "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18", + "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6", + "sha256:bddfb1db89bfaa855912261c805bd0e10218923cc262b9159a49c29a7a1c1afa", + "sha256:c7d36c2209d9136cd8e02fab1c0ddc185ce79bc914c45054a9f514e44c787917", + "sha256:d1095fecf99eeb7384dabad4bf44b965f929a5f6079654b681193edf7169ec20", + "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331", + "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63", + "sha256:deaed9ad4da0b1aea77fe0aa0cebb9ef611c70b3177be936a95e5d01fa05094f", + "sha256:ef8345b48e95cee45ff25192ed1f4857273117917a4dcd48e3905619bcd9c9b8" + ], + "markers": "python_version >= '3.9'", + "version": "==3.8.2" }, "matplotlib-inline": { "hashes": [ @@ -1783,6 +2501,14 @@ "markers": "python_version >= '3.7'", "version": "==0.1.2" }, + "mergedeep": { + "hashes": [ + "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", + "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307" + ], + "markers": "python_version >= '3.6'", + "version": "==1.3.4" + }, "mistune": { "hashes": [ "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205", @@ -1791,6 +2517,76 @@ "markers": "python_version >= '3.7'", "version": "==3.0.2" }, + "more-itertools": { + "hashes": [ + "sha256:626c369fa0eb37bac0291bce8259b332fd59ac792fa5497b59837309cd5b114a", + "sha256:64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6" + ], + "markers": "python_version >= '3.8'", + "version": "==10.1.0" + }, + "msgpack": { + "hashes": [ + "sha256:04ad6069c86e531682f9e1e71b71c1c3937d6014a7c3e9edd2aa81ad58842862", + "sha256:0bfdd914e55e0d2c9e1526de210f6fe8ffe9705f2b1dfcc4aecc92a4cb4b533d", + "sha256:1dc93e8e4653bdb5910aed79f11e165c85732067614f180f70534f056da97db3", + "sha256:1e2d69948e4132813b8d1131f29f9101bc2c915f26089a6d632001a5c1349672", + "sha256:235a31ec7db685f5c82233bddf9858748b89b8119bf4538d514536c485c15fe0", + "sha256:27dcd6f46a21c18fa5e5deed92a43d4554e3df8d8ca5a47bf0615d6a5f39dbc9", + "sha256:28efb066cde83c479dfe5a48141a53bc7e5f13f785b92ddde336c716663039ee", + "sha256:3476fae43db72bd11f29a5147ae2f3cb22e2f1a91d575ef130d2bf49afd21c46", + "sha256:36e17c4592231a7dbd2ed09027823ab295d2791b3b1efb2aee874b10548b7524", + "sha256:384d779f0d6f1b110eae74cb0659d9aa6ff35aaf547b3955abf2ab4c901c4819", + "sha256:38949d30b11ae5f95c3c91917ee7a6b239f5ec276f271f28638dec9156f82cfc", + "sha256:3967e4ad1aa9da62fd53e346ed17d7b2e922cba5ab93bdd46febcac39be636fc", + "sha256:3e7bf4442b310ff154b7bb9d81eb2c016b7d597e364f97d72b1acc3817a0fdc1", + "sha256:3f0c8c6dfa6605ab8ff0611995ee30d4f9fcff89966cf562733b4008a3d60d82", + "sha256:484ae3240666ad34cfa31eea7b8c6cd2f1fdaae21d73ce2974211df099a95d81", + "sha256:4a7b4f35de6a304b5533c238bee86b670b75b03d31b7797929caa7a624b5dda6", + "sha256:4cb14ce54d9b857be9591ac364cb08dc2d6a5c4318c1182cb1d02274029d590d", + "sha256:4e71bc4416de195d6e9b4ee93ad3f2f6b2ce11d042b4d7a7ee00bbe0358bd0c2", + "sha256:52700dc63a4676669b341ba33520f4d6e43d3ca58d422e22ba66d1736b0a6e4c", + "sha256:572efc93db7a4d27e404501975ca6d2d9775705c2d922390d878fcf768d92c87", + "sha256:576eb384292b139821c41995523654ad82d1916da6a60cff129c715a6223ea84", + "sha256:5b0bf0effb196ed76b7ad883848143427a73c355ae8e569fa538365064188b8e", + "sha256:5b6ccc0c85916998d788b295765ea0e9cb9aac7e4a8ed71d12e7d8ac31c23c95", + "sha256:5ed82f5a7af3697b1c4786053736f24a0efd0a1b8a130d4c7bfee4b9ded0f08f", + "sha256:6d4c80667de2e36970ebf74f42d1088cc9ee7ef5f4e8c35eee1b40eafd33ca5b", + "sha256:730076207cb816138cf1af7f7237b208340a2c5e749707457d70705715c93b93", + "sha256:7687e22a31e976a0e7fc99c2f4d11ca45eff652a81eb8c8085e9609298916dcf", + "sha256:822ea70dc4018c7e6223f13affd1c5c30c0f5c12ac1f96cd8e9949acddb48a61", + "sha256:84b0daf226913133f899ea9b30618722d45feffa67e4fe867b0b5ae83a34060c", + "sha256:85765fdf4b27eb5086f05ac0491090fc76f4f2b28e09d9350c31aac25a5aaff8", + "sha256:8dd178c4c80706546702c59529ffc005681bd6dc2ea234c450661b205445a34d", + "sha256:8f5b234f567cf76ee489502ceb7165c2a5cecec081db2b37e35332b537f8157c", + "sha256:98bbd754a422a0b123c66a4c341de0474cad4a5c10c164ceed6ea090f3563db4", + "sha256:993584fc821c58d5993521bfdcd31a4adf025c7d745bbd4d12ccfecf695af5ba", + "sha256:a40821a89dc373d6427e2b44b572efc36a2778d3f543299e2f24eb1a5de65415", + "sha256:b291f0ee7961a597cbbcc77709374087fa2a9afe7bdb6a40dbbd9b127e79afee", + "sha256:b573a43ef7c368ba4ea06050a957c2a7550f729c31f11dd616d2ac4aba99888d", + "sha256:b610ff0f24e9f11c9ae653c67ff8cc03c075131401b3e5ef4b82570d1728f8a9", + "sha256:bdf38ba2d393c7911ae989c3bbba510ebbcdf4ecbdbfec36272abe350c454075", + "sha256:bfef2bb6ef068827bbd021017a107194956918ab43ce4d6dc945ffa13efbc25f", + "sha256:cab3db8bab4b7e635c1c97270d7a4b2a90c070b33cbc00c99ef3f9be03d3e1f7", + "sha256:cb70766519500281815dfd7a87d3a178acf7ce95390544b8c90587d76b227681", + "sha256:cca1b62fe70d761a282496b96a5e51c44c213e410a964bdffe0928e611368329", + "sha256:ccf9a39706b604d884d2cb1e27fe973bc55f2890c52f38df742bc1d79ab9f5e1", + "sha256:dc43f1ec66eb8440567186ae2f8c447d91e0372d793dfe8c222aec857b81a8cf", + "sha256:dd632777ff3beaaf629f1ab4396caf7ba0bdd075d948a69460d13d44357aca4c", + "sha256:e45ae4927759289c30ccba8d9fdce62bb414977ba158286b5ddaf8df2cddb5c5", + "sha256:e50ebce52f41370707f1e21a59514e3375e3edd6e1832f5e5235237db933c98b", + "sha256:ebbbba226f0a108a7366bf4b59bf0f30a12fd5e75100c630267d94d7f0ad20e5", + "sha256:ec79ff6159dffcc30853b2ad612ed572af86c92b5168aa3fc01a67b0fa40665e", + "sha256:f0936e08e0003f66bfd97e74ee530427707297b0d0361247e9b4f59ab78ddc8b", + "sha256:f26a07a6e877c76a88e3cecac8531908d980d3d5067ff69213653649ec0f60ad", + "sha256:f64e376cd20d3f030190e8c32e1c64582eba56ac6dc7d5b0b49a9d44021b52fd", + "sha256:f6ffbc252eb0d229aeb2f9ad051200668fc3a9aaa8994e49f0cb2ffe2b7867e7", + "sha256:f9a7c509542db4eceed3dcf21ee5267ab565a83555c9b88a8109dcecc4709002", + "sha256:ff1d0899f104f3921d94579a5638847f783c9b04f2d5f229392ca77fba5b82fc" + ], + "markers": "python_version >= '3.8'", + "version": "==1.0.7" + }, "multidict": { "hashes": [ "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9", @@ -1871,9 +2667,25 @@ "markers": "python_version >= '3.7'", "version": "==6.0.4" }, - "nbclient": { + "multimethod": { "hashes": [ - "sha256:4b28c207877cf33ef3a9838cdc7a54c5ceff981194a82eac59d558f05487295e", + "sha256:afd84da9c3d0445c84f827e4d63ad42d17c6d29b122427c6dee9032ac2d2a0d4", + "sha256:daa45af3fe257f73abb69673fd54ddeaf31df0eb7363ad6e1251b7c9b192d8c5" + ], + "markers": "python_version >= '3.8'", + "version": "==1.10" + }, + "mypy-extensions": { + "hashes": [ + "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", + "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.0" + }, + "nbclient": { + "hashes": [ + "sha256:4b28c207877cf33ef3a9838cdc7a54c5ceff981194a82eac59d558f05487295e", "sha256:a3a1ddfb34d4a9d17fc744d655962714a866639acd30130e9be84191cd97cd15" ], "markers": "python_full_version >= '3.8.0'", @@ -1881,11 +2693,11 @@ }, "nbconvert": { "hashes": [ - "sha256:abedc01cf543177ffde0bfc2a69726d5a478f6af10a332fc1bf29fcb4f0cf000", - "sha256:d1d417b7f34a4e38887f8da5bdfd12372adf3b80f995d57556cb0972c68909fe" + "sha256:5b6c848194d270cc55fb691169202620d7b52a12fec259508d142ecbe4219310", + "sha256:b1564bd89f69a74cd6398b0362da94db07aafb991b7857216a766204a71612c0" ], "markers": "python_version >= '3.8'", - "version": "==7.11.0" + "version": "==7.12.0" }, "nbformat": { "hashes": [ @@ -1905,11 +2717,19 @@ }, "networkx": { "hashes": [ - "sha256:58058d66b1818043527244fab9d41a51fcd7dcc271748015f3c181b8a90c8e2e", - "sha256:9a9992345353618ae98339c2b63d8201c381c2944f38a2ab49cb45a4c667e412" + "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6", + "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2" ], - "markers": "python_version >= '3.8'", - "version": "==3.0" + "markers": "python_version >= '3.9'", + "version": "==3.2.1" + }, + "nodeenv": { + "hashes": [ + "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2", + "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==1.8.0" }, "notebook": { "hashes": [ @@ -1928,40 +2748,110 @@ "markers": "python_version >= '3.7'", "version": "==0.2.3" }, + "numba": { + "hashes": [ + "sha256:07f2fa7e7144aa6f275f27260e73ce0d808d3c62b30cff8906ad1dec12d87bbe", + "sha256:240e7a1ae80eb6b14061dc91263b99dc8d6af9ea45d310751b780888097c1aaa", + "sha256:45698b995914003f890ad839cfc909eeb9c74921849c712a05405d1a79c50f68", + "sha256:487ded0633efccd9ca3a46364b40006dbdaca0f95e99b8b83e778d1195ebcbaa", + "sha256:4e79b6cc0d2bf064a955934a2e02bf676bc7995ab2db929dbbc62e4c16551be6", + "sha256:55a01e1881120e86d54efdff1be08381886fe9f04fc3006af309c602a72bc44d", + "sha256:5c765aef472a9406a97ea9782116335ad4f9ef5c9f93fc05fd44aab0db486954", + "sha256:6fe7a9d8e3bd996fbe5eac0683227ccef26cba98dae6e5cee2c1894d4b9f16c1", + "sha256:7bf1ddd4f7b9c2306de0384bf3854cac3edd7b4d8dffae2ec1b925e4c436233f", + "sha256:811305d5dc40ae43c3ace5b192c670c358a89a4d2ae4f86d1665003798ea7a1a", + "sha256:81fe5b51532478149b5081311b0fd4206959174e660c372b94ed5364cfb37c82", + "sha256:898af055b03f09d33a587e9425500e5be84fc90cd2f80b3fb71c6a4a17a7e354", + "sha256:9e9356e943617f5e35a74bf56ff6e7cc83e6b1865d5e13cee535d79bf2cae954", + "sha256:a1eaa744f518bbd60e1f7ccddfb8002b3d06bd865b94a5d7eac25028efe0e0ff", + "sha256:bc2d904d0319d7a5857bd65062340bed627f5bfe9ae4a495aef342f072880d50", + "sha256:bcecd3fb9df36554b342140a4d77d938a549be635d64caf8bd9ef6c47a47f8aa", + "sha256:bd3dda77955be03ff366eebbfdb39919ce7c2620d86c906203bed92124989032", + "sha256:bf68df9c307fb0aa81cacd33faccd6e419496fdc621e83f1efce35cdc5e79cac", + "sha256:d3e2fe81fe9a59fcd99cc572002101119059d64d31eb6324995ee8b0f144a306", + "sha256:e63d6aacaae1ba4ef3695f1c2122b30fa3d8ba039c8f517784668075856d79e2", + "sha256:ea5bfcf7d641d351c6a80e8e1826eb4a145d619870016eeaf20bbd71ef5caa22" + ], + "markers": "python_version >= '3.8'", + "version": "==0.58.1" + }, + "numexpr": { + "hashes": [ + "sha256:0983052f308ea75dd232eb7f4729eed839db8fe8d82289940342b32cc55b15d0", + "sha256:11121b14ee3179bade92e823f25f1b94e18716d33845db5081973331188c3338", + "sha256:32934d51b5bc8a6636436326da79ed380e2f151989968789cf65b1210572cb46", + "sha256:3a84284e0a407ca52980fd20962e89aff671c84cd6e73458f2e29ea2aa206356", + "sha256:47a249cecd1382d482a5bf1fac0d11392fb2ed0f7d415ebc4cd901959deb1ec9", + "sha256:4ecaa5be24cf8fa0f00108e9dfa1021b7510e9dd9d159b8d8bc7c7ddbb995b31", + "sha256:5340d2c86d83f52e1a3e7fd97c37d358ae99af9de316bdeeab2565b9b1e622ca", + "sha256:5496fc9e3ae214637cbca1ab556b0e602bd3afe9ff4c943a29c482430972cda8", + "sha256:56ec95f8d1db0819e64987dcf1789acd500fa4ea396eeabe4af6efdcb8902d07", + "sha256:596eeb3bbfebc912f4b6eaaf842b61ba722cebdb8bc42dfefa657d3a74953849", + "sha256:81451962d4145a46dba189df65df101d4d1caddb6efe6ebfe05982cd9f62b2cf", + "sha256:8bf005acd7f1985c71b1b247aaac8950d6ea05a0fe0bbbbf3f96cd398b136daa", + "sha256:a371cfc1670a18eea2d5c70abaa95a0e8824b70d28da884bad11931266e3a0ca", + "sha256:a4546416004ff2e7eb9cf52c2d7ab82732b1b505593193ee9f93fa770edc5230", + "sha256:b8a5b2c21c26b62875bf819d375d798b96a32644e3c28bd4ce7789ed1fb489da", + "sha256:c7bf60fc1a9c90a9cb21c4c235723e579bff70c8d5362228cb2cf34426104ba2", + "sha256:cb2f473fdfd09d17db3038e34818d05b6bc561a36785aa927d6c0e06bccc9911", + "sha256:cf5f112bce5c5966c47cc33700bc14ce745c8351d437ed57a9574fff581f341a", + "sha256:d43f1f0253a6f2db2f76214e6f7ae9611b422cba3f7d4c86415d7a78bbbd606f", + "sha256:d46c47e361fa60966a3339cb4f463ae6151ce7d78ed38075f06e8585d2c8929f", + "sha256:d88531ffea3ea9287e8a1665c6a2d0206d3f4660d5244423e2a134a7f0ce5fba", + "sha256:da55ba845b847cc33c4bf81cee4b1bddfb0831118cabff8db62888ab8697ec34", + "sha256:db1065ba663a854115cf1f493afd7206e2efcef6643129e8061e97a51ad66ebb", + "sha256:dccf572763517db6562fb7b17db46aacbbf62a9ca0a66672872f4f71aee7b186", + "sha256:e838289e3b7bbe100b99e35496e6cc4cc0541c2207078941ee5a1d46e6b925ae", + "sha256:f021ac93cb3dd5d8ba2882627b615b1f58cb089dcc85764c6fbe7a549ed21b0c", + "sha256:f29f4d08d9b0ed6fa5d32082971294b2f9131b8577c2b7c36432ed670924313f", + "sha256:f3bdf8cbc00c77a46230c765d242f92d35905c239b20c256c48dbac91e49f253", + "sha256:fd93b88d5332069916fa00829ea1b972b7e73abcb1081eee5c905a514b8b59e3" + ], + "markers": "python_version >= '3.9'", + "version": "==2.8.7" + }, "numpy": { "hashes": [ - "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f", - "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61", - "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7", - "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400", - "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef", - "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2", - "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d", - "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc", - "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835", - "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706", - "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5", - "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4", - "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6", - "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463", - "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a", - "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f", - "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e", - "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e", - "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694", - "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8", - "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64", - "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d", - "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc", - "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254", - "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2", - "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1", - "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810", - "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9" + "sha256:06fa1ed84aa60ea6ef9f91ba57b5ed963c3729534e6e54055fc151fad0423f0a", + "sha256:174a8880739c16c925799c018f3f55b8130c1f7c8e75ab0a6fa9d41cab092fd6", + "sha256:1a13860fdcd95de7cf58bd6f8bc5a5ef81c0b0625eb2c9a783948847abbef2c2", + "sha256:1cc3d5029a30fb5f06704ad6b23b35e11309491c999838c31f124fee32107c79", + "sha256:22f8fc02fdbc829e7a8c578dd8d2e15a9074b630d4da29cda483337e300e3ee9", + "sha256:26c9d33f8e8b846d5a65dd068c14e04018d05533b348d9eaeef6c1bd787f9919", + "sha256:2b3fca8a5b00184828d12b073af4d0fc5fdd94b1632c2477526f6bd7842d700d", + "sha256:2beef57fb031dcc0dc8fa4fe297a742027b954949cabb52a2a376c144e5e6060", + "sha256:36340109af8da8805d8851ef1d74761b3b88e81a9bd80b290bbfed61bd2b4f75", + "sha256:3703fc9258a4a122d17043e57b35e5ef1c5a5837c3db8be396c82e04c1cf9b0f", + "sha256:3ced40d4e9e18242f70dd02d739e44698df3dcb010d31f495ff00a31ef6014fe", + "sha256:4a06263321dfd3598cacb252f51e521a8cb4b6df471bb12a7ee5cbab20ea9167", + "sha256:4eb8df4bf8d3d90d091e0146f6c28492b0be84da3e409ebef54349f71ed271ef", + "sha256:5d5244aabd6ed7f312268b9247be47343a654ebea52a60f002dc70c769048e75", + "sha256:64308ebc366a8ed63fd0bf426b6a9468060962f1a4339ab1074c228fa6ade8e3", + "sha256:6a3cdb4d9c70e6b8c0814239ead47da00934666f668426fc6e94cce869e13fd7", + "sha256:854ab91a2906ef29dc3925a064fcd365c7b4da743f84b123002f6139bcb3f8a7", + "sha256:94cc3c222bb9fb5a12e334d0479b97bb2df446fbe622b470928f5284ffca3f8d", + "sha256:96ca5482c3dbdd051bcd1fce8034603d6ebfc125a7bd59f55b40d8f5d246832b", + "sha256:a2bbc29fcb1771cd7b7425f98b05307776a6baf43035d3b80c4b0f29e9545186", + "sha256:a4cd6ed4a339c21f1d1b0fdf13426cb3b284555c27ac2f156dfdaaa7e16bfab0", + "sha256:aa18428111fb9a591d7a9cc1b48150097ba6a7e8299fb56bdf574df650e7d1f1", + "sha256:aa317b2325f7aa0a9471663e6093c210cb2ae9c0ad824732b307d2c51983d5b6", + "sha256:b04f5dc6b3efdaab541f7857351aac359e6ae3c126e2edb376929bd3b7f92d7e", + "sha256:b272d4cecc32c9e19911891446b72e986157e6a1809b7b56518b4f3755267523", + "sha256:b361d369fc7e5e1714cf827b731ca32bff8d411212fccd29ad98ad622449cc36", + "sha256:b96e7b9c624ef3ae2ae0e04fa9b460f6b9f17ad8b4bec6d7756510f1f6c0c841", + "sha256:baf8aab04a2c0e859da118f0b38617e5ee65d75b83795055fb66c0d5e9e9b818", + "sha256:bcc008217145b3d77abd3e4d5ef586e3bdfba8fe17940769f8aa09b99e856c00", + "sha256:bd3f0091e845164a20bd5a326860c840fe2af79fa12e0469a12768a3ec578d80", + "sha256:cc392fdcbd21d4be6ae1bb4475a03ce3b025cd49a9be5345d76d7585aea69440", + "sha256:d73a3abcac238250091b11caef9ad12413dab01669511779bc9b29261dd50210", + "sha256:f43740ab089277d403aa07567be138fc2a89d4d9892d113b76153e0e412409f8", + "sha256:f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea", + "sha256:f79b231bf5c16b1f39c7f4875e1ded36abee1591e98742b05d8a0fb55d8a3eec", + "sha256:fe6b44fb8fcdf7eda4ef4461b97b3f63c466b27ab151bec2366db8b197387841" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.24.4" + "markers": "python_version >= '3.9'", + "version": "==1.26.2" }, "oauthlib": { "hashes": [ @@ -2029,37 +2919,43 @@ }, "pandas": { "hashes": [ - "sha256:14e45300521902689a81f3f41386dc86f19b8ba8dd5ac5a3c7010ef8d2932813", - "sha256:26d9c71772c7afb9d5046e6e9cf42d83dd147b5cf5bcb9d97252077118543792", - "sha256:3749077d86e3a2f0ed51367f30bf5b82e131cc0f14260c4d3e499186fccc4406", - "sha256:41179ce559943d83a9b4bbacb736b04c928b095b5f25dd2b7389eda08f46f373", - "sha256:478ff646ca42b20376e4ed3fa2e8d7341e8a63105586efe54fa2508ee087f328", - "sha256:50869a35cbb0f2e0cd5ec04b191e7b12ed688874bd05dd777c19b28cbea90996", - "sha256:565fa34a5434d38e9d250af3c12ff931abaf88050551d9fbcdfafca50d62babf", - "sha256:5f2b952406a1588ad4cad5b3f55f520e82e902388a6d5a4a91baa8d38d23c7f6", - "sha256:5fbcb19d6fceb9e946b3e23258757c7b225ba450990d9ed63ccceeb8cae609f7", - "sha256:6973549c01ca91ec96199e940495219c887ea815b2083722821f1d7abfa2b4dc", - "sha256:74a3fd7e5a7ec052f183273dc7b0acd3a863edf7520f5d3a1765c04ffdb3b0b1", - "sha256:7a0a56cef15fd1586726dace5616db75ebcfec9179a3a55e78f72c5639fa2a23", - "sha256:7cec0bee9f294e5de5bbfc14d0573f65526071029d036b753ee6507d2a21480a", - "sha256:87bd9c03da1ac870a6d2c8902a0e1fd4267ca00f13bc494c9e5a9020920e1d51", - "sha256:972d8a45395f2a2d26733eb8d0f629b2f90bebe8e8eddbb8829b180c09639572", - "sha256:9842b6f4b8479e41968eced654487258ed81df7d1c9b7b870ceea24ed9459b31", - "sha256:9f69c4029613de47816b1bb30ff5ac778686688751a5e9c99ad8c7031f6508e5", - "sha256:a50d9a4336a9621cab7b8eb3fb11adb82de58f9b91d84c2cd526576b881a0c5a", - "sha256:bc4c368f42b551bf72fac35c5128963a171b40dce866fb066540eeaf46faa003", - "sha256:c39a8da13cede5adcd3be1182883aea1c925476f4e84b2807a46e2775306305d", - "sha256:c3ac844a0fe00bfaeb2c9b51ab1424e5c8744f89860b138434a363b1f620f354", - "sha256:c4c00e0b0597c8e4f59e8d461f797e5d70b4d025880516a8261b2817c47759ee", - "sha256:c74a62747864ed568f5a82a49a23a8d7fe171d0c69038b38cedf0976831296fa", - "sha256:dd05f7783b3274aa206a1af06f0ceed3f9b412cf665b7247eacd83be41cf7bf0", - "sha256:dfd681c5dc216037e0b0a2c821f5ed99ba9f03ebcf119c7dac0e9a7b960b9ec9", - "sha256:e474390e60ed609cec869b0da796ad94f420bb057d86784191eefc62b65819ae", - "sha256:f76d097d12c82a535fda9dfe5e8dd4127952b45fea9b0276cb30cca5ea313fbc" + "sha256:0296a66200dee556850d99b24c54c7dfa53a3264b1ca6f440e42bad424caea03", + "sha256:04d4c58e1f112a74689da707be31cf689db086949c71828ef5da86727cfe3f82", + "sha256:08637041279b8981a062899da0ef47828df52a1838204d2b3761fbd3e9fcb549", + "sha256:11a771450f36cebf2a4c9dbd3a19dfa8c46c4b905a3ea09dc8e556626060fe71", + "sha256:1329dbe93a880a3d7893149979caa82d6ba64a25e471682637f846d9dbc10dd2", + "sha256:1f539e113739a3e0cc15176bf1231a553db0239bfa47a2c870283fd93ba4f683", + "sha256:22929f84bca106921917eb73c1521317ddd0a4c71b395bcf767a106e3494209f", + "sha256:321ecdb117bf0f16c339cc6d5c9a06063854f12d4d9bc422a84bb2ed3207380a", + "sha256:35172bff95f598cc5866c047f43c7f4df2c893acd8e10e6653a4b792ed7f19bb", + "sha256:3cc4469ff0cf9aa3a005870cb49ab8969942b7156e0a46cc3f5abd6b11051dfb", + "sha256:4441ac94a2a2613e3982e502ccec3bdedefe871e8cea54b8775992485c5660ef", + "sha256:465571472267a2d6e00657900afadbe6097c8e1dc43746917db4dfc862e8863e", + "sha256:59dfe0e65a2f3988e940224e2a70932edc964df79f3356e5f2997c7d63e758b4", + "sha256:72c84ec1b1d8e5efcbff5312abe92bfb9d5b558f11e0cf077f5496c4f4a3c99e", + "sha256:7cf4cf26042476e39394f1f86868d25b265ff787c9b2f0d367280f11afbdee6d", + "sha256:7fa2ad4ff196768ae63a33f8062e6838efed3a319cf938fdf8b95e956c813042", + "sha256:a5d53c725832e5f1645e7674989f4c106e4b7249c1d57549023ed5462d73b140", + "sha256:acf08a73b5022b479c1be155d4988b72f3020f308f7a87c527702c5f8966d34f", + "sha256:b99c4e51ef2ed98f69099c72c75ec904dd610eb41a32847c4fcbc1a975f2d2b8", + "sha256:d5ded6ff28abbf0ea7689f251754d3789e1edb0c4d0d91028f0b980598418a58", + "sha256:de21e12bf1511190fc1e9ebc067f14ca09fccfb189a813b38d63211d54832f5f", + "sha256:f7ea8ae8004de0381a2376662c0505bb0a4f679f4c61fbfd122aa3d1b0e5f09d", + "sha256:fc77309da3b55732059e484a1efc0897f6149183c522390772d3561f9bf96c00", + "sha256:fca5680368a5139d4920ae3dc993eb5106d49f814ff24018b64d8850a52c6ed2", + "sha256:fcd76d67ca2d48f56e2db45833cf9d58f548f97f61eecd3fdc74268417632b8a" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.5.3" + "markers": "python_version >= '3.9'", + "version": "==2.1.3" + }, + "pandera": { + "hashes": [ + "sha256:67515984f855ba14d12443f893b5ff90ae6796f613d5f3df43abad406a48c373", + "sha256:8e4e7b279c62f6d4b5109801544bf8d46e1c9fdf7ceceb8fedd5f3dad0c1bea1" + ], + "markers": "python_version >= '3.7'", + "version": "==0.17.2" }, "pandocfilters": { "hashes": [ @@ -2085,12 +2981,55 @@ "markers": "python_version >= '3.7'", "version": "==1.4.1" }, + "pastel": { + "hashes": [ + "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364", + "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.2.1" + }, "patsy": { "hashes": [ - "sha256:7eb5349754ed6aa982af81f636479b1b8db9d5b1a6e957a6016ec0534b5c86b7", - "sha256:bdc18001875e319bc91c812c1eb6a10be4bb13cb81eb763f466179dca3b67277" + "sha256:0486413077a527db51ddea8fa94a5234d0feb17a4f4dc01b59b6086c58a70f80", + "sha256:7dabc527597308de0e8f188faa20af7e06a89bdaa306756dfc7783693ea16af4" + ], + "version": "==0.5.4" + }, + "pbr": { + "hashes": [ + "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda", + "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9" + ], + "markers": "python_version >= '2.6'", + "version": "==6.0.0" + }, + "pendulum": { + "hashes": [ + "sha256:0731f0c661a3cb779d398803655494893c9f581f6488048b3fb629c2342b5394", + "sha256:1245cd0075a3c6d889f581f6325dd8404aca5884dea7223a5566c38aab94642b", + "sha256:29c40a6f2942376185728c9a0347d7c0f07905638c83007e1d262781f1e6953a", + "sha256:2d1619a721df661e506eff8db8614016f0720ac171fe80dda1333ee44e684087", + "sha256:318f72f62e8e23cd6660dbafe1e346950281a9aed144b5c596b2ddabc1d19739", + "sha256:33fb61601083f3eb1d15edeb45274f73c63b3c44a8524703dc143f4212bf3269", + "sha256:3481fad1dc3f6f6738bd575a951d3c15d4b4ce7c82dce37cf8ac1483fde6e8b0", + "sha256:4c9c689747f39d0d02a9f94fcee737b34a5773803a64a5fdb046ee9cac7442c5", + "sha256:7c5ec650cb4bec4c63a89a0242cc8c3cebcec92fcfe937c417ba18277d8560be", + "sha256:94b1fc947bfe38579b28e1cccb36f7e28a15e841f30384b5ad6c5e31055c85d7", + "sha256:9702069c694306297ed362ce7e3c1ef8404ac8ede39f9b28b7c1a7ad8c3959e3", + "sha256:b06a0ca1bfe41c990bbf0c029f0b6501a7f2ec4e38bfec730712015e8860f207", + "sha256:b6c352f4bd32dff1ea7066bd31ad0f71f8d8100b9ff709fb343f3b86cee43efe", + "sha256:c501749fdd3d6f9e726086bf0cd4437281ed47e7bca132ddb522f86a1645d360", + "sha256:c807a578a532eeb226150d5006f156632df2cc8c5693d778324b43ff8c515dd0", + "sha256:db0a40d8bcd27b4fb46676e8eb3c732c67a5a5e6bfab8927028224fbced0b40b", + "sha256:de42ea3e2943171a9e95141f2eecf972480636e8e484ccffaf1e833929e9e052", + "sha256:e95d329384717c7bf627bf27e204bc3b15c8238fa8d9d9781d93712776c14002", + "sha256:f5e236e7730cab1644e1b87aca3d2ff3e375a608542e90fe25685dae46310116", + "sha256:f888f2d2909a414680a29ae74d0592758f2b9fcdee3549887779cd4055e975db", + "sha256:fb53ffa0085002ddd43b6ca61a7b34f2d4d7c3ed66f931fe599e1a531b42af9b" ], - "version": "==0.5.3" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.1.2" }, "petl": { "hashes": [ @@ -2099,14 +3038,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.7.14" }, - "pexpect": { - "hashes": [ - "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", - "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f" - ], - "markers": "sys_platform != 'win32'", - "version": "==4.9.0" - }, "pillow": { "hashes": [ "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d", @@ -2167,13 +3098,37 @@ "markers": "python_version >= '3.8'", "version": "==10.1.0" }, - "platformdirs": { + "pint": { + "hashes": [ + "sha256:2d139f6abbcf3016cad7d3cec05707fe908ac4f99cf59aedfd6ee667b7a64433", + "sha256:6e2b3c5c2b4d9b516608bc860a417a39d66eb99c958f36540cf931d2c2e9f80f" + ], + "markers": "python_version >= '3.9'", + "version": "==0.22" + }, + "pip": { "hashes": [ - "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b", - "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731" + "sha256:1fcaa041308d01f14575f6d0d2ea4b75a3e2871fe4f9c694976f908768e14174", + "sha256:55eb67bb6171d37447e82213be585b75fe2b12b359e993773aca4de9247a052b" ], "markers": "python_version >= '3.7'", - "version": "==4.0.0" + "version": "==23.3.1" + }, + "pkginfo": { + "hashes": [ + "sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546", + "sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046" + ], + "markers": "python_version >= '3.6'", + "version": "==1.9.6" + }, + "platformdirs": { + "hashes": [ + "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380", + "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420" + ], + "markers": "python_version >= '3.8'", + "version": "==4.1.0" }, "plotly": { "hashes": [ @@ -2192,6 +3147,14 @@ "markers": "python_version >= '3.8'", "version": "==1.3.0" }, + "pre-commit": { + "hashes": [ + "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32", + "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660" + ], + "markers": "python_version >= '3.8'", + "version": "==3.5.0" + }, "prometheus-client": { "hashes": [ "sha256:4585b0d1223148c27a225b10dbec5ae9bc4c81a99a3fa80774fa6209935324e1", @@ -2247,12 +3210,83 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==5.9.6" }, - "ptyprocess": { - "hashes": [ - "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", - "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" + "psycopg2-binary": { + "hashes": [ + "sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9", + "sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77", + "sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e", + "sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84", + "sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3", + "sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2", + "sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67", + "sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876", + "sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152", + "sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f", + "sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a", + "sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6", + "sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503", + "sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f", + "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493", + "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996", + "sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f", + "sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e", + "sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59", + "sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94", + "sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7", + "sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682", + "sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420", + "sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae", + "sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291", + "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe", + "sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980", + "sha256:64cf30263844fa208851ebb13b0732ce674d8ec6a0c86a4e160495d299ba3c93", + "sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692", + "sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119", + "sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716", + "sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472", + "sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b", + "sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2", + "sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc", + "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c", + "sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5", + "sha256:81ff62668af011f9a48787564ab7eded4e9fb17a4a6a74af5ffa6a457400d2ab", + "sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984", + "sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9", + "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf", + "sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0", + "sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f", + "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212", + "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb", + "sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be", + "sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90", + "sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041", + "sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7", + "sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860", + "sha256:b0605eaed3eb239e87df0d5e3c6489daae3f7388d455d0c0b4df899519c6a38d", + "sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245", + "sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27", + "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417", + "sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359", + "sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202", + "sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0", + "sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7", + "sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba", + "sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1", + "sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd", + "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07", + "sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98", + "sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55", + "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d", + "sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972", + "sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f", + "sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e", + "sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26", + "sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957", + "sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53", + "sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52" ], - "version": "==0.7.0" + "markers": "python_version >= '3.7'", + "version": "==2.9.9" }, "pure-eval": { "hashes": [ @@ -2263,35 +3297,46 @@ }, "pyarrow": { "hashes": [ - "sha256:0ec7587d759153f452d5263dbc8b1af318c4609b607be2bd5127dcda6708cdb1", - "sha256:1765a18205eb1e02ccdedb66049b0ec148c2a0cb52ed1fb3aac322dfc086a6ee", - "sha256:1a14f57a5f472ce8234f2964cd5184cccaa8df7e04568c64edc33b23eb285dd5", - "sha256:254017ca43c45c5098b7f2a00e995e1f8346b0fb0be225f042838323bb55283c", - "sha256:42ba7c5347ce665338f2bc64685d74855900200dac81a972d49fe127e8132f75", - "sha256:443eb9409b0cf78df10ced326490e1a300205a458fbeb0767b6b31ab3ebae6b2", - "sha256:61f4c37d82fe00d855d0ab522c685262bdeafd3fbcb5fe596fe15025fbc7341b", - "sha256:668e00e3b19f183394388a687d29c443eb000fb3fe25599c9b4762a0afd37775", - "sha256:6f7a7dbe2f7f65ac1d0bd3163f756deb478a9e9afc2269557ed75b1b25ab3610", - "sha256:70acca1ece4322705652f48db65145b5028f2c01c7e426c5d16a30ba5d739c24", - "sha256:7b4ede715c004b6fc535de63ef79fa29740b4080639a5ff1ea9ca84e9282f349", - "sha256:94fb4a0c12a2ac1ed8e7e2aa52aade833772cf2d3de9dde685401b22cec30002", - "sha256:abb57334f2c57979a49b7be2792c31c23430ca02d24becd0b511cbe7b6b08649", - "sha256:b069602eb1fc09f1adec0a7bdd7897f4d25575611dfa43543c8b8a75d99d6874", - "sha256:b1fc226d28c7783b52a84d03a66573d5a22e63f8a24b841d5fc68caeed6784d4", - "sha256:ba71e6fc348c92477586424566110d332f60d9a35cb85278f42e3473bc1373da", - "sha256:bf26f809926a9d74e02d76593026f0aaeac48a65b64f1bb17eed9964bfe7ae1a", - "sha256:cb627673cb98708ef00864e2e243f51ba7b4c1b9f07a1d821f98043eccd3f585", - "sha256:d1bc6e4d5d6f69e0861d5d7f6cf4d061cf1069cb9d490040129877acf16d4c2a", - "sha256:db0c5986bf0808927f49640582d2032a07aa49828f14e51f362075f03747d198", - "sha256:e00174764a8b4e9d8d5909b6d19ee0c217a6cf0232c5682e31fdfbd5a9f0ae52", - "sha256:e141a65705ac98fa52a9113fe574fdaf87fe0316cde2dffe6b94841d3c61544c", - "sha256:e3fe5049d2e9ca661d8e43fab6ad5a4c571af12d20a57dffc392a014caebef65", - "sha256:efa59933b20183c1c13efc34bd91efc6b2997377c4c6ad9272da92d224e3beb1", - "sha256:f2d00aa481becf57098e85d99e34a25dba5a9ade2f44eb0b7d80c80f2984fc03" + "sha256:0140c7e2b740e08c5a459439d87acd26b747fc408bde0a8806096ee0baaa0c15", + "sha256:01e44de9749cddc486169cb632f3c99962318e9dacac7778315a110f4bf8a450", + "sha256:05fe7994745b634c5fb16ce5717e39a1ac1fac3e2b0795232841660aa76647cd", + "sha256:06ca79080ef89d6529bb8e5074d4b4f6086143b2520494fcb7cf8a99079cde93", + "sha256:097828b55321897db0e1dbfc606e3ff8101ae5725673498cbfa7754ee0da80e4", + "sha256:0f6f053cb66dc24091f5511e5920e45c83107f954a21032feadc7b9e3a8e7851", + "sha256:11e045dfa09855b6d3e7705a37c42e2dc2c71d608fab34d3c23df2e02df9aec3", + "sha256:1a8ae88c0038d1bc362a682320112ee6774f006134cd5afc291591ee4bc06505", + "sha256:1daab52050a1c48506c029e6fa0944a7b2436334d7e44221c16f6f1b2cc9c510", + "sha256:2a145dab9ed7849fc1101bf03bcdc69913547f10513fdf70fc3ab6c0a50c7eee", + "sha256:30d8494870d9916bb53b2a4384948491444741cb9a38253c590e21f836b01222", + "sha256:323cbe60210173ffd7db78bfd50b80bdd792c4c9daca8843ef3cd70b186649db", + "sha256:32542164d905002c42dff896efdac79b3bdd7291b1b74aa292fac8450d0e4dcd", + "sha256:33c1f6110c386464fd2e5e4ea3624466055bbe681ff185fd6c9daa98f30a3f9a", + "sha256:3c76807540989fe8fcd02285dd15e4f2a3da0b09d27781abec3adc265ddbeba1", + "sha256:3f6d5faf4f1b0d5a7f97be987cf9e9f8cd39902611e818fe134588ee99bf0283", + "sha256:450e4605e3c20e558485f9161a79280a61c55efe585d51513c014de9ae8d393f", + "sha256:470ae0194fbfdfbf4a6b65b4f9e0f6e1fa0ea5b90c1ee6b65b38aecee53508c8", + "sha256:4756a2b373a28f6166c42711240643fb8bd6322467e9aacabd26b488fa41ec23", + "sha256:58c889851ca33f992ea916b48b8540735055201b177cb0dcf0596a495a667b00", + "sha256:6263cffd0c3721c1e348062997babdf0151301f7353010c9c9a8ed47448f82ab", + "sha256:78d4a77a46a7de9388b653af1c4ce539350726cd9af62e0831e4f2bd0c95a2f4", + "sha256:7a8089d7e77d1455d529dbd7cff08898bbb2666ee48bc4085203af1d826a33cc", + "sha256:906b0dc25f2be12e95975722f1e60e162437023f490dbd80d0deb7375baf3171", + "sha256:922e8b49b88da8633d6cac0e1b5a690311b6758d6f5d7c2be71acb0f1e14cd61", + "sha256:96d64e5ba7dceb519a955e5eeb5c9adcfd63f73a56aea4722e2cc81364fc567a", + "sha256:981670b4ce0110d8dcb3246410a4aabf5714db5d8ea63b15686bce1c914b1f83", + "sha256:a8eeef015ae69d104c4c3117a6011e7e3ecd1abec79dc87fd2fac6e442f666ee", + "sha256:b8b3f4fe8d4ec15e1ef9b599b94683c5216adaed78d5cb4c606180546d1e2ee1", + "sha256:be28e1a07f20391bb0b15ea03dcac3aade29fc773c5eb4bee2838e9b2cdde0cb", + "sha256:c7331b4ed3401b7ee56f22c980608cf273f0380f77d0f73dd3c185f78f5a6220", + "sha256:cf87e2cec65dd5cf1aa4aba918d523ef56ef95597b545bbaad01e6433851aa10", + "sha256:d0351fecf0e26e152542bc164c22ea2a8e8c682726fce160ce4d459ea802d69c", + "sha256:d264ad13605b61959f2ae7c1d25b1a5b8505b112715c961418c8396433f213ad", + "sha256:e592e482edd9f1ab32f18cd6a716c45b2c0f2403dc2af782f4e9674952e6dd27", + "sha256:fada8396bc739d958d0b81d291cfd201126ed5e7913cb73de6bc606befc30226" ], "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==10.0.1" + "markers": "python_version >= '3.8'", + "version": "==14.0.1" }, "pyasn1": { "hashes": [ @@ -2317,6 +3362,22 @@ "markers": "python_version >= '3.6'", "version": "==2.11.1" }, + "pybtex": { + "hashes": [ + "sha256:818eae35b61733e5c007c3fcd2cfb75ed1bc8b4173c1f70b56cc4c0802d34755", + "sha256:e1e0c8c69998452fea90e9179aa2a98ab103f3eed894405b7264e517cc2fcc0f" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.24.0" + }, + "pybtex-docutils": { + "hashes": [ + "sha256:3a7ebdf92b593e00e8c1c538aa9a20bca5d92d84231124715acc964d51d93c6b", + "sha256:8fd290d2ae48e32fcb54d86b0efb8d573198653c7e2447d5bec5847095f430b9" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.3" + }, "pycparser": { "hashes": [ "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", @@ -2329,45 +3390,130 @@ "email" ], "hashes": [ - "sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548", - "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80", - "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340", - "sha256:3ecea2b9d80e5333303eeb77e180b90e95eea8f765d08c3d278cd56b00345d01", - "sha256:4b03e42ec20286f052490423682016fd80fda830d8e4119f8ab13ec7464c0132", - "sha256:4c5370a7edaac06daee3af1c8b1192e305bc102abcbf2a92374b5bc793818599", - "sha256:56e3ff861c3b9c6857579de282ce8baabf443f42ffba355bf070770ed63e11e1", - "sha256:5a1f9f747851338933942db7af7b6ee8268568ef2ed86c4185c6ef4402e80ba8", - "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe", - "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0", - "sha256:654db58ae399fe6434e55325a2c3e959836bd17a6f6a0b6ca8107ea0571d2e17", - "sha256:678bcf5591b63cc917100dc50ab6caebe597ac67e8c9ccb75e698f66038ea953", - "sha256:6cf25c1a65c27923a17b3da28a0bdb99f62ee04230c931d83e888012851f4e7f", - "sha256:75ac15385a3534d887a99c713aa3da88a30fbd6204a5cd0dc4dab3d770b9bd2f", - "sha256:75b297827b59bc229cac1a23a2f7a4ac0031068e5be0ce385be1462e7e17a35d", - "sha256:7d6f6e7305244bddb4414ba7094ce910560c907bdfa3501e9db1a7fd7eaea127", - "sha256:84bafe2e60b5e78bc64a2941b4c071a4b7404c5c907f5f5a99b0139781e69ed8", - "sha256:854223752ba81e3abf663d685f105c64150873cc6f5d0c01d3e3220bcff7d36f", - "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580", - "sha256:8ef467901d7a41fa0ca6db9ae3ec0021e3f657ce2c208e98cd511f3161c762c6", - "sha256:968ac42970f57b8344ee08837b62f6ee6f53c33f603547a55571c954a4225691", - "sha256:97cce3ae7341f7620a0ba5ef6cf043975cd9d2b81f3aa5f4ea37928269bc1b87", - "sha256:9849f031cf8a2f0a928fe885e5a04b08006d6d41876b8bbd2fc68a18f9f2e3fd", - "sha256:9f00790179497767aae6bcdc36355792c79e7bbb20b145ff449700eb076c5f96", - "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687", - "sha256:b97c1fac8c49be29486df85968682b0afa77e1b809aff74b83081cc115e52f33", - "sha256:bc0898c12f8e9c97f6cd44c0ed70d55749eaf783716896960b4ecce2edfd2d69", - "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653", - "sha256:c636925f38b8db208e09d344c7aa4f29a86bb9947495dd6b6d376ad10334fb78", - "sha256:c958d053453a1c4b1c2062b05cd42d9d5c8eb67537b8d5a7e3c3032943ecd261", - "sha256:d3a3c792a58e1622667a2837512099eac62490cdfd63bd407993aaf200a4cf1f", - "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9", - "sha256:e70ca129d2053fb8b728ee7d1af8e553a928d7e301a311094b8a0501adc8763d", - "sha256:efff03cc7a4f29d9009d1c96ceb1e7a70a65cfe86e89d34e4a5f2ab1e5693737", - "sha256:f59ef915cac80275245824e9d771ee939133be38215555e9dc90c6cb148aaeb5", - "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0" - ], - "markers": "python_version >= '3.7'", - "version": "==1.10.13" + "sha256:80c50fb8e3dcecfddae1adbcc00ec5822918490c99ab31f6cf6140ca1c1429f0", + "sha256:ff177ba64c6faf73d7afa2e8cad38fd456c0dbe01c9954e71038001cd15a6edd" + ], + "markers": "python_version >= '3.7'", + "version": "==2.5.2" + }, + "pydantic-core": { + "hashes": [ + "sha256:038c9f763e650712b899f983076ce783175397c848da04985658e7628cbe873b", + "sha256:074f3d86f081ce61414d2dc44901f4f83617329c6f3ab49d2bc6c96948b2c26b", + "sha256:079206491c435b60778cf2b0ee5fd645e61ffd6e70c47806c9ed51fc75af078d", + "sha256:09b0e985fbaf13e6b06a56d21694d12ebca6ce5414b9211edf6f17738d82b0f8", + "sha256:0f6116a558fd06d1b7c2902d1c4cf64a5bd49d67c3540e61eccca93f41418124", + "sha256:103ef8d5b58596a731b690112819501ba1db7a36f4ee99f7892c40da02c3e189", + "sha256:16e29bad40bcf97aac682a58861249ca9dcc57c3f6be22f506501833ddb8939c", + "sha256:206ed23aecd67c71daf5c02c3cd19c0501b01ef3cbf7782db9e4e051426b3d0d", + "sha256:2248485b0322c75aee7565d95ad0e16f1c67403a470d02f94da7344184be770f", + "sha256:27548e16c79702f1e03f5628589c6057c9ae17c95b4c449de3c66b589ead0520", + "sha256:2d0ae0d8670164e10accbeb31d5ad45adb71292032d0fdb9079912907f0085f4", + "sha256:3128e0bbc8c091ec4375a1828d6118bc20404883169ac95ffa8d983b293611e6", + "sha256:3387277f1bf659caf1724e1afe8ee7dbc9952a82d90f858ebb931880216ea955", + "sha256:34708cc82c330e303f4ce87758828ef6e457681b58ce0e921b6e97937dd1e2a3", + "sha256:35613015f0ba7e14c29ac6c2483a657ec740e5ac5758d993fdd5870b07a61d8b", + "sha256:3ad873900297bb36e4b6b3f7029d88ff9829ecdc15d5cf20161775ce12306f8a", + "sha256:40180930807ce806aa71eda5a5a5447abb6b6a3c0b4b3b1b1962651906484d68", + "sha256:439c9afe34638ace43a49bf72d201e0ffc1a800295bed8420c2a9ca8d5e3dbb3", + "sha256:45e95333b8418ded64745f14574aa9bfc212cb4fbeed7a687b0c6e53b5e188cd", + "sha256:4641e8ad4efb697f38a9b64ca0523b557c7931c5f84e0fd377a9a3b05121f0de", + "sha256:49b08aae5013640a3bfa25a8eebbd95638ec3f4b2eaf6ed82cf0c7047133f03b", + "sha256:4bc536201426451f06f044dfbf341c09f540b4ebdb9fd8d2c6164d733de5e634", + "sha256:4ce601907e99ea5b4adb807ded3570ea62186b17f88e271569144e8cca4409c7", + "sha256:4e40f2bd0d57dac3feb3a3aed50f17d83436c9e6b09b16af271b6230a2915459", + "sha256:4e47a76848f92529879ecfc417ff88a2806438f57be4a6a8bf2961e8f9ca9ec7", + "sha256:513b07e99c0a267b1d954243845d8a833758a6726a3b5d8948306e3fe14675e3", + "sha256:531f4b4252fac6ca476fbe0e6f60f16f5b65d3e6b583bc4d87645e4e5ddde331", + "sha256:57d52fa717ff445cb0a5ab5237db502e6be50809b43a596fb569630c665abddf", + "sha256:59986de5710ad9613ff61dd9b02bdd2f615f1a7052304b79cc8fa2eb4e336d2d", + "sha256:5baab5455c7a538ac7e8bf1feec4278a66436197592a9bed538160a2e7d11e36", + "sha256:5c7d5b5005f177764e96bd584d7bf28d6e26e96f2a541fdddb934c486e36fd59", + "sha256:60b7607753ba62cf0739177913b858140f11b8af72f22860c28eabb2f0a61937", + "sha256:615a0a4bff11c45eb3c1996ceed5bdaa2f7b432425253a7c2eed33bb86d80abc", + "sha256:61ea96a78378e3bd5a0be99b0e5ed00057b71f66115f5404d0dae4819f495093", + "sha256:652c1988019752138b974c28f43751528116bcceadad85f33a258869e641d753", + "sha256:6637560562134b0e17de333d18e69e312e0458ee4455bdad12c37100b7cad706", + "sha256:678265f7b14e138d9a541ddabbe033012a2953315739f8cfa6d754cc8063e8ca", + "sha256:699156034181e2ce106c89ddb4b6504c30db8caa86e0c30de47b3e0654543260", + "sha256:6b9ff467ffbab9110e80e8c8de3bcfce8e8b0fd5661ac44a09ae5901668ba997", + "sha256:6c327e9cd849b564b234da821236e6bcbe4f359a42ee05050dc79d8ed2a91588", + "sha256:6d30226dfc816dd0fdf120cae611dd2215117e4f9b124af8c60ab9093b6e8e71", + "sha256:6e227c40c02fd873c2a73a98c1280c10315cbebe26734c196ef4514776120aeb", + "sha256:6e4d090e73e0725b2904fdbdd8d73b8802ddd691ef9254577b708d413bf3006e", + "sha256:70f4b4851dbb500129681d04cc955be2a90b2248d69273a787dda120d5cf1f69", + "sha256:70f947628e074bb2526ba1b151cee10e4c3b9670af4dbb4d73bc8a89445916b5", + "sha256:774de879d212db5ce02dfbf5b0da9a0ea386aeba12b0b95674a4ce0593df3d07", + "sha256:77fa384d8e118b3077cccfcaf91bf83c31fe4dc850b5e6ee3dc14dc3d61bdba1", + "sha256:79e0a2cdbdc7af3f4aee3210b1172ab53d7ddb6a2d8c24119b5706e622b346d0", + "sha256:7e88f5696153dc516ba6e79f82cc4747e87027205f0e02390c21f7cb3bd8abfd", + "sha256:7f8210297b04e53bc3da35db08b7302a6a1f4889c79173af69b72ec9754796b8", + "sha256:81982d78a45d1e5396819bbb4ece1fadfe5f079335dd28c4ab3427cd95389944", + "sha256:823fcc638f67035137a5cd3f1584a4542d35a951c3cc68c6ead1df7dac825c26", + "sha256:853a2295c00f1d4429db4c0fb9475958543ee80cfd310814b5c0ef502de24dda", + "sha256:88e74ab0cdd84ad0614e2750f903bb0d610cc8af2cc17f72c28163acfcf372a4", + "sha256:8aa1768c151cf562a9992462239dfc356b3d1037cc5a3ac829bb7f3bda7cc1f9", + "sha256:8c8a8812fe6f43a3a5b054af6ac2d7b8605c7bcab2804a8a7d68b53f3cd86e00", + "sha256:95b15e855ae44f0c6341ceb74df61b606e11f1087e87dcb7482377374aac6abe", + "sha256:96581cfefa9123accc465a5fd0cc833ac4d75d55cc30b633b402e00e7ced00a6", + "sha256:9bd18fee0923ca10f9a3ff67d4851c9d3e22b7bc63d1eddc12f439f436f2aada", + "sha256:a33324437018bf6ba1bb0f921788788641439e0ed654b233285b9c69704c27b4", + "sha256:a6a16f4a527aae4f49c875da3cdc9508ac7eef26e7977952608610104244e1b7", + "sha256:a717aef6971208f0851a2420b075338e33083111d92041157bbe0e2713b37325", + "sha256:a71891847f0a73b1b9eb86d089baee301477abef45f7eaf303495cd1473613e4", + "sha256:aae7ea3a1c5bb40c93cad361b3e869b180ac174656120c42b9fadebf685d121b", + "sha256:ab1cdb0f14dc161ebc268c09db04d2c9e6f70027f3b42446fa11c153521c0e88", + "sha256:ab4ea451082e684198636565224bbb179575efc1658c48281b2c866bfd4ddf04", + "sha256:abf058be9517dc877227ec3223f0300034bd0e9f53aebd63cf4456c8cb1e0863", + "sha256:af36f36538418f3806048f3b242a1777e2540ff9efaa667c27da63d2749dbce0", + "sha256:b53e9ad053cd064f7e473a5f29b37fc4cc9dc6d35f341e6afc0155ea257fc911", + "sha256:b7851992faf25eac90bfcb7bfd19e1f5ffa00afd57daec8a0042e63c74a4551b", + "sha256:b9b759b77f5337b4ea024f03abc6464c9f35d9718de01cfe6bae9f2e139c397e", + "sha256:ba39688799094c75ea8a16a6b544eb57b5b0f3328697084f3f2790892510d144", + "sha256:ba6b6b3846cfc10fdb4c971980a954e49d447cd215ed5a77ec8190bc93dd7bc5", + "sha256:bb4c2eda937a5e74c38a41b33d8c77220380a388d689bcdb9b187cf6224c9720", + "sha256:c0b97ec434041827935044bbbe52b03d6018c2897349670ff8fe11ed24d1d4ab", + "sha256:c1452a1acdf914d194159439eb21e56b89aa903f2e1c65c60b9d874f9b950e5d", + "sha256:c2027d05c8aebe61d898d4cffd774840a9cb82ed356ba47a90d99ad768f39789", + "sha256:c2adbe22ab4babbca99c75c5d07aaf74f43c3195384ec07ccbd2f9e3bddaecec", + "sha256:c2d97e906b4ff36eb464d52a3bc7d720bd6261f64bc4bcdbcd2c557c02081ed2", + "sha256:c339dabd8ee15f8259ee0f202679b6324926e5bc9e9a40bf981ce77c038553db", + "sha256:c6eae413494a1c3f89055da7a5515f32e05ebc1a234c27674a6956755fb2236f", + "sha256:c949f04ecad823f81b1ba94e7d189d9dfb81edbb94ed3f8acfce41e682e48cef", + "sha256:c97bee68898f3f4344eb02fec316db93d9700fb1e6a5b760ffa20d71d9a46ce3", + "sha256:ca61d858e4107ce5e1330a74724fe757fc7135190eb5ce5c9d0191729f033209", + "sha256:cb4679d4c2b089e5ef89756bc73e1926745e995d76e11925e3e96a76d5fa51fc", + "sha256:cb774298da62aea5c80a89bd58c40205ab4c2abf4834453b5de207d59d2e1651", + "sha256:ccd4d5702bb90b84df13bd491be8d900b92016c5a455b7e14630ad7449eb03f8", + "sha256:cf9d3fe53b1ee360e2421be95e62ca9b3296bf3f2fb2d3b83ca49ad3f925835e", + "sha256:d2ae91f50ccc5810b2f1b6b858257c9ad2e08da70bf890dee02de1775a387c66", + "sha256:d37f8ec982ead9ba0a22a996129594938138a1503237b87318392a48882d50b7", + "sha256:d81e6987b27bc7d101c8597e1cd2bcaa2fee5e8e0f356735c7ed34368c471550", + "sha256:dcf4e6d85614f7a4956c2de5a56531f44efb973d2fe4a444d7251df5d5c4dcfd", + "sha256:de790a3b5aa2124b8b78ae5faa033937a72da8efe74b9231698b5a1dd9be3405", + "sha256:e47e9a08bcc04d20975b6434cc50bf82665fbc751bcce739d04a3120428f3e27", + "sha256:e60f112ac88db9261ad3a52032ea46388378034f3279c643499edb982536a093", + "sha256:e87fc540c6cac7f29ede02e0f989d4233f88ad439c5cdee56f693cc9c1c78077", + "sha256:eac5c82fc632c599f4639a5886f96867ffced74458c7db61bc9a66ccb8ee3113", + "sha256:ebb4e035e28f49b6f1a7032920bb9a0c064aedbbabe52c543343d39341a5b2a3", + "sha256:ec1e72d6412f7126eb7b2e3bfca42b15e6e389e1bc88ea0069d0cc1742f477c6", + "sha256:ef98ca7d5995a82f43ec0ab39c4caf6a9b994cb0b53648ff61716370eadc43cf", + "sha256:f0cbc7fff06a90bbd875cc201f94ef0ee3929dfbd5c55a06674b60857b8b85ed", + "sha256:f4791cf0f8c3104ac668797d8c514afb3431bc3305f5638add0ba1a5a37e0d88", + "sha256:f5e412d717366e0677ef767eac93566582518fe8be923361a5c204c1a62eaafe", + "sha256:fb2ed8b3fe4bf4506d6dab3b93b83bbc22237e230cba03866d561c3577517d18", + "sha256:fe0a5a1025eb797752136ac8b4fa21aa891e3d74fd340f864ff982d649691867" + ], + "markers": "python_version >= '3.7'", + "version": "==2.14.5" + }, + "pydantic-settings": { + "hashes": [ + "sha256:26b1492e0a24755626ac5e6d715e9077ab7ad4fb5f19a8b7ed7011d52f36141c", + "sha256:7621c0cb5d90d1140d2f0ef557bdf03573aac7035948109adf2574770b77605a" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.0" }, "pygments": { "hashes": [ @@ -2377,6 +3523,13 @@ "markers": "python_version >= '3.7'", "version": "==2.17.2" }, + "pylev": { + "hashes": [ + "sha256:7b2e2aa7b00e05bb3f7650eb506fc89f474f70493271a35c242d9a92188ad3dd", + "sha256:9e77e941042ad3a4cc305dcdf2b2dec1aec2fbe3dd9015d2698ad02b173006d1" + ], + "version": "==1.4.0" + }, "pyparsing": { "hashes": [ "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb", @@ -2418,23 +3571,78 @@ "markers": "python_version >= '3.9'", "version": "==3.6.1" }, + "pyproject-hooks": { + "hashes": [ + "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8", + "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.0" + }, + "pyreadline3": { + "hashes": [ + "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae", + "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb" + ], + "markers": "python_version >= '3.8' and sys_platform == 'win32'", + "version": "==3.4.1" + }, "pytest": { "hashes": [ "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac", "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5" ], - "index": "pypi", "markers": "python_version >= '3.7'", "version": "==7.4.3" }, + "pytest-console-scripts": { + "hashes": [ + "sha256:5a826ed84cc0afa202eb9e44381d7d762f7bdda8e0c23f9f79a7f1f44cf4a895", + "sha256:ad860a951a90eca4bd3bd1159b8f5428633ba4ea01abd5c9526b67a95f65437a" + ], + "markers": "python_version >= '3.8'", + "version": "==1.4.1" + }, + "pytest-cov": { + "hashes": [ + "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6", + "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a" + ], + "markers": "python_version >= '3.7'", + "version": "==4.1.0" + }, + "pytest-mock": { + "hashes": [ + "sha256:0972719a7263072da3a21c7f4773069bcc7486027d7e8e1f81d98a47e701bc4f", + "sha256:31a40f038c22cad32287bb43932054451ff5583ff094bca6f675df2f8bc1a6e9" + ], + "markers": "python_version >= '3.8'", + "version": "==3.12.0" + }, + "pytest-xdist": { + "hashes": [ + "sha256:cbb36f3d67e0c478baa57fa4edc8843887e0f6cfc42d677530a36d7472b32d8a", + "sha256:d075629c7e00b611df89f490a5063944bee7a4362a5ff11c7cc7824a03dfce24" + ], + "markers": "python_version >= '3.7'", + "version": "==3.5.0" + }, "python-dateutil": { "hashes": [ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.2" }, + "python-dotenv": { + "hashes": [ + "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba", + "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a" + ], + "markers": "python_version >= '3.8'", + "version": "==1.0.0" + }, "python-json-logger": { "hashes": [ "sha256:23e7ec02d34237c5aa1e29a070193a4ea87583bb4e7f8fd06d3de8264c4b2e1c", @@ -2443,6 +3651,14 @@ "markers": "python_version >= '3.6'", "version": "==2.0.7" }, + "python-multipart": { + "hashes": [ + "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132", + "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18" + ], + "markers": "python_version >= '3.7'", + "version": "==0.0.6" + }, "python-slugify": { "hashes": [ "sha256:70ca6ea68fe63ecc8fa4fcf00ae651fc8a5d02d93dcd12ae6d4fc7ca46c4d395", @@ -2451,60 +3667,6 @@ "markers": "python_version >= '3.7'", "version": "==8.0.1" }, - "python-snappy": { - "hashes": [ - "sha256:03bb511380fca2a13325b6f16fe8234c8e12da9660f0258cd45d9a02ffc916af", - "sha256:0bdb6942180660bda7f7d01f4c0def3cfc72b1c6d99aad964801775a3e379aba", - "sha256:0d489b50f49433494160c45048fe806de6b3aeab0586e497ebd22a0bab56e427", - "sha256:1a993dc8aadd901915a510fe6af5f20ae4256f527040066c22a154db8946751f", - "sha256:1d029f7051ec1bbeaa3e03030b6d8ed47ceb69cae9016f493c802a08af54e026", - "sha256:277757d5dad4e239dc1417438a0871b65b1b155beb108888e7438c27ffc6a8cc", - "sha256:2a7e528ab6e09c0d67dcb61a1730a292683e5ff9bb088950638d3170cf2a0a54", - "sha256:2aaaf618c68d8c9daebc23a20436bd01b09ee70d7fbf7072b7f38b06d2fab539", - "sha256:2be4f4550acd484912441f5f1209ba611ac399aac9355fee73611b9a0d4f949c", - "sha256:39692bedbe0b717001a99915ac0eb2d9d0bad546440d392a2042b96d813eede1", - "sha256:3fb9a88a4dd6336488f3de67ce75816d0d796dce53c2c6e4d70e0b565633c7fd", - "sha256:4038019b1bcaadde726a57430718394076c5a21545ebc5badad2c045a09546cf", - "sha256:463fd340a499d47b26ca42d2f36a639188738f6e2098c6dbf80aef0e60f461e1", - "sha256:4d3cafdf454354a621c8ab7408e45aa4e9d5c0b943b61ff4815f71ca6bdf0130", - "sha256:4ec533a8c1f8df797bded662ec3e494d225b37855bb63eb0d75464a07947477c", - "sha256:530bfb9efebcc1aab8bb4ebcbd92b54477eed11f6cf499355e882970a6d3aa7d", - "sha256:546c1a7470ecbf6239101e9aff0f709b68ca0f0268b34d9023019a55baa1f7c6", - "sha256:5843feb914796b1f0405ccf31ea0fb51034ceb65a7588edfd5a8250cb369e3b2", - "sha256:586724a0276d7a6083a17259d0b51622e492289a9998848a1b01b6441ca12b2f", - "sha256:59e975be4206cc54d0a112ef72fa3970a57c2b1bcc2c97ed41d6df0ebe518228", - "sha256:5a453c45178d7864c1bdd6bfe0ee3ed2883f63b9ba2c9bb967c6b586bf763f96", - "sha256:5bb05c28298803a74add08ba496879242ef159c75bc86a5406fac0ffc7dd021b", - "sha256:5e973e637112391f05581f427659c05b30b6843bc522a65be35ac7b18ce3dedd", - "sha256:66c80e9b366012dbee262bb1869e4fc5ba8786cda85928481528bc4a72ec2ee8", - "sha256:6a7620404da966f637b9ce8d4d3d543d363223f7a12452a575189c5355fc2d25", - "sha256:6f8bf4708a11b47517baf962f9a02196478bbb10fdb9582add4aa1459fa82380", - "sha256:735cd4528c55dbe4516d6d2b403331a99fc304f8feded8ae887cf97b67d589bb", - "sha256:7778c224efc38a40d274da4eb82a04cac27aae20012372a7db3c4bbd8926c4d4", - "sha256:8277d1f6282463c40761f802b742f833f9f2449fcdbb20a96579aa05c8feb614", - "sha256:88b6ea78b83d2796f330b0af1b70cdd3965dbdab02d8ac293260ec2c8fe340ee", - "sha256:8c07220408d3268e8268c9351c5c08041bc6f8c6172e59d398b71020df108541", - "sha256:8d0c019ee7dcf2c60e240877107cddbd95a5b1081787579bf179938392d66480", - "sha256:90b0186516b7a101c14764b0c25931b741fb0102f21253eff67847b4742dfc72", - "sha256:9837ac1650cc68d22a3cf5f15fb62c6964747d16cecc8b22431f113d6e39555d", - "sha256:9eac51307c6a1a38d5f86ebabc26a889fddf20cbba7a116ccb54ba1446601d5b", - "sha256:9f0c0d88b84259f93c3aa46398680646f2c23e43394779758d9f739c34e15295", - "sha256:a0ad38bc98d0b0497a0b0dbc29409bcabfcecff4511ed7063403c86de16927bc", - "sha256:b265cde49774752aec9ca7f5d272e3f98718164afc85521622a8a5394158a2b5", - "sha256:b6a107ab06206acc5359d4c5632bd9b22d448702a79b3169b0c62e0fb808bb2a", - "sha256:b7f920eaf46ebf41bd26f9df51c160d40f9e00b7b48471c3438cb8d027f7fb9b", - "sha256:c20498bd712b6e31a4402e1d027a1cd64f6a4a0066a3fe3c7344475886d07fdf", - "sha256:cb18d9cd7b3f35a2f5af47bb8ed6a5bdbf4f3ddee37f3daade4ab7864c292f5b", - "sha256:cf5bb9254e1c38aacf253d510d3d9be631bba21f3d068b17672b38b5cbf2fff5", - "sha256:d017775851a778ec9cc32651c4464079d06d927303c2dde9ae9830ccf6fe94e1", - "sha256:dc96668d9c7cc656609764275c5f8da58ef56d89bdd6810f6923d36497468ff7", - "sha256:e066a0586833d610c4bbddba0be5ba0e3e4f8e0bc5bb6d82103d8f8fc47bb59a", - "sha256:e3a013895c64352b49d0d8e107a84f99631b16dbab156ded33ebf0becf56c8b2", - "sha256:eaf905a580f2747c4a474040a5063cd5e0cc3d1d2d6edb65f28196186493ad4a" - ], - "index": "pypi", - "version": "==0.6.1" - }, "pytz": { "hashes": [ "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b", @@ -2512,6 +3674,61 @@ ], "version": "==2023.3.post1" }, + "pytzdata": { + "hashes": [ + "sha256:3efa13b335a00a8de1d345ae41ec78dd11c9f8807f522d39850f2dd828681540", + "sha256:e1e14750bcf95016381e4d472bad004eef710f2d6417240904070b3d6654485f" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2020.1" + }, + "pywin32": { + "hashes": [ + "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d", + "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65", + "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e", + "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b", + "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4", + "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040", + "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a", + "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36", + "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8", + "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e", + "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802", + "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a", + "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407", + "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0" + ], + "markers": "platform_system == 'Windows'", + "version": "==306" + }, + "pywin32-ctypes": { + "hashes": [ + "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60", + "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7" + ], + "markers": "sys_platform == 'win32'", + "version": "==0.2.2" + }, + "pywinpty": { + "hashes": [ + "sha256:1617b729999eb6713590e17665052b1a6ae0ad76ee31e60b444147c5b6a35dca", + "sha256:189380469ca143d06e19e19ff3fba0fcefe8b4a8cc942140a6b863aed7eebb2d", + "sha256:21319cd1d7c8844fb2c970fb3a55a3db5543f112ff9cfcd623746b9c47501575", + "sha256:7520575b6546db23e693cbd865db2764097bd6d4ef5dc18c92555904cd62c3d4", + "sha256:8197de460ae8ebb7f5d1701dfa1b5df45b157bb832e92acba316305e18ca00dd", + "sha256:853985a8f48f4731a716653170cd735da36ffbdc79dcb4c7b7140bce11d8c722" + ], + "markers": "os_name == 'nt'", + "version": "==2.0.12" + }, + "pyxlsb": { + "hashes": [ + "sha256:8062d1ea8626d3f1980e8b1cfe91a4483747449242ecb61013bc2df85435f685", + "sha256:87c122a9a622e35ca5e741d2e541201d28af00fb46bec492cfa9586890b120b4" + ], + "version": "==1.0.10" + }, "pyyaml": { "hashes": [ "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", @@ -2570,102 +3787,102 @@ }, "pyzmq": { "hashes": [ - "sha256:019e59ef5c5256a2c7378f2fb8560fc2a9ff1d315755204295b2eab96b254d0a", - "sha256:034239843541ef7a1aee0c7b2cb7f6aafffb005ede965ae9cbd49d5ff4ff73cf", - "sha256:03b3f49b57264909aacd0741892f2aecf2f51fb053e7d8ac6767f6c700832f45", - "sha256:047a640f5c9c6ade7b1cc6680a0e28c9dd5a0825135acbd3569cc96ea00b2505", - "sha256:04ccbed567171579ec2cebb9c8a3e30801723c575601f9a990ab25bcac6b51e2", - "sha256:057e824b2aae50accc0f9a0570998adc021b372478a921506fddd6c02e60308e", - "sha256:11baebdd5fc5b475d484195e49bae2dc64b94a5208f7c89954e9e354fc609d8f", - "sha256:11c1d2aed9079c6b0c9550a7257a836b4a637feb334904610f06d70eb44c56d2", - "sha256:11d58723d44d6ed4dd677c5615b2ffb19d5c426636345567d6af82be4dff8a55", - "sha256:12720a53e61c3b99d87262294e2b375c915fea93c31fc2336898c26d7aed34cd", - "sha256:17ef5f01d25b67ca8f98120d5fa1d21efe9611604e8eb03a5147360f517dd1e2", - "sha256:18d43df3f2302d836f2a56f17e5663e398416e9dd74b205b179065e61f1a6edf", - "sha256:1a5d26fe8f32f137e784f768143728438877d69a586ddeaad898558dc971a5ae", - "sha256:1af379b33ef33757224da93e9da62e6471cf4a66d10078cf32bae8127d3d0d4a", - "sha256:1ccf825981640b8c34ae54231b7ed00271822ea1c6d8ba1090ebd4943759abf5", - "sha256:21eb4e609a154a57c520e3d5bfa0d97e49b6872ea057b7c85257b11e78068222", - "sha256:2243700cc5548cff20963f0ca92d3e5e436394375ab8a354bbea2b12911b20b0", - "sha256:255ca2b219f9e5a3a9ef3081512e1358bd4760ce77828e1028b818ff5610b87b", - "sha256:259c22485b71abacdfa8bf79720cd7bcf4b9d128b30ea554f01ae71fdbfdaa23", - "sha256:25f0e6b78220aba09815cd1f3a32b9c7cb3e02cb846d1cfc526b6595f6046618", - "sha256:273bc3959bcbff3f48606b28229b4721716598d76b5aaea2b4a9d0ab454ec062", - "sha256:292fe3fc5ad4a75bc8df0dfaee7d0babe8b1f4ceb596437213821f761b4589f9", - "sha256:2ca57a5be0389f2a65e6d3bb2962a971688cbdd30b4c0bd188c99e39c234f414", - "sha256:2d163a18819277e49911f7461567bda923461c50b19d169a062536fffe7cd9d2", - "sha256:2d81f1ddae3858b8299d1da72dd7d19dd36aab654c19671aa8a7e7fb02f6638a", - "sha256:2f957ce63d13c28730f7fd6b72333814221c84ca2421298f66e5143f81c9f91f", - "sha256:330f9e188d0d89080cde66dc7470f57d1926ff2fb5576227f14d5be7ab30b9fa", - "sha256:34c850ce7976d19ebe7b9d4b9bb8c9dfc7aac336c0958e2651b88cbd46682123", - "sha256:35b5ab8c28978fbbb86ea54958cd89f5176ce747c1fb3d87356cf698048a7790", - "sha256:3669cf8ee3520c2f13b2e0351c41fea919852b220988d2049249db10046a7afb", - "sha256:381469297409c5adf9a0e884c5eb5186ed33137badcbbb0560b86e910a2f1e76", - "sha256:3d0a409d3b28607cc427aa5c30a6f1e4452cc44e311f843e05edb28ab5e36da0", - "sha256:44e58a0554b21fc662f2712814a746635ed668d0fbc98b7cb9d74cb798d202e6", - "sha256:458dea649f2f02a0b244ae6aef8dc29325a2810aa26b07af8374dc2a9faf57e3", - "sha256:48e466162a24daf86f6b5ca72444d2bf39a5e58da5f96370078be67c67adc978", - "sha256:49d238cf4b69652257db66d0c623cd3e09b5d2e9576b56bc067a396133a00d4a", - "sha256:4ca1ed0bb2d850aa8471387882247c68f1e62a4af0ce9c8a1dbe0d2bf69e41fb", - "sha256:52533489f28d62eb1258a965f2aba28a82aa747202c8fa5a1c7a43b5db0e85c1", - "sha256:548d6482dc8aadbe7e79d1b5806585c8120bafa1ef841167bc9090522b610fa6", - "sha256:5619f3f5a4db5dbb572b095ea3cb5cc035335159d9da950830c9c4db2fbb6995", - "sha256:57459b68e5cd85b0be8184382cefd91959cafe79ae019e6b1ae6e2ba8a12cda7", - "sha256:5a34d2395073ef862b4032343cf0c32a712f3ab49d7ec4f42c9661e0294d106f", - "sha256:61706a6b6c24bdece85ff177fec393545a3191eeda35b07aaa1458a027ad1304", - "sha256:724c292bb26365659fc434e9567b3f1adbdb5e8d640c936ed901f49e03e5d32e", - "sha256:73461eed88a88c866656e08f89299720a38cb4e9d34ae6bf5df6f71102570f2e", - "sha256:76705c9325d72a81155bb6ab48d4312e0032bf045fb0754889133200f7a0d849", - "sha256:76c1c8efb3ca3a1818b837aea423ff8a07bbf7aafe9f2f6582b61a0458b1a329", - "sha256:77a41c26205d2353a4c94d02be51d6cbdf63c06fbc1295ea57dad7e2d3381b71", - "sha256:79986f3b4af059777111409ee517da24a529bdbd46da578b33f25580adcff728", - "sha256:7cff25c5b315e63b07a36f0c2bab32c58eafbe57d0dce61b614ef4c76058c115", - "sha256:7f7e58effd14b641c5e4dec8c7dab02fb67a13df90329e61c869b9cc607ef752", - "sha256:820c4a08195a681252f46926de10e29b6bbf3e17b30037bd4250d72dd3ddaab8", - "sha256:87e34f31ca8f168c56d6fbf99692cc8d3b445abb5bfd08c229ae992d7547a92a", - "sha256:8f03d3f0d01cb5a018debeb412441996a517b11c5c17ab2001aa0597c6d6882c", - "sha256:90f26dc6d5f241ba358bef79be9ce06de58d477ca8485e3291675436d3827cf8", - "sha256:955215ed0604dac5b01907424dfa28b40f2b2292d6493445dd34d0dfa72586a8", - "sha256:985bbb1316192b98f32e25e7b9958088431d853ac63aca1d2c236f40afb17c83", - "sha256:a382372898a07479bd34bda781008e4a954ed8750f17891e794521c3e21c2e1c", - "sha256:a882ac0a351288dd18ecae3326b8a49d10c61a68b01419f3a0b9a306190baf69", - "sha256:aa8d6cdc8b8aa19ceb319aaa2b660cdaccc533ec477eeb1309e2a291eaacc43a", - "sha256:abc719161780932c4e11aaebb203be3d6acc6b38d2f26c0f523b5b59d2fc1996", - "sha256:abf34e43c531bbb510ae7e8f5b2b1f2a8ab93219510e2b287a944432fad135f3", - "sha256:ade6d25bb29c4555d718ac6d1443a7386595528c33d6b133b258f65f963bb0f6", - "sha256:afea96f64efa98df4da6958bae37f1cbea7932c35878b185e5982821bc883369", - "sha256:b1579413ae492b05de5a6174574f8c44c2b9b122a42015c5292afa4be2507f28", - "sha256:b3451108ab861040754fa5208bca4a5496c65875710f76789a9ad27c801a0075", - "sha256:b9af3757495c1ee3b5c4e945c1df7be95562277c6e5bccc20a39aec50f826cd0", - "sha256:bc16ac425cc927d0a57d242589f87ee093884ea4804c05a13834d07c20db203c", - "sha256:c2910967e6ab16bf6fbeb1f771c89a7050947221ae12a5b0b60f3bca2ee19bca", - "sha256:c2b92812bd214018e50b6380ea3ac0c8bb01ac07fcc14c5f86a5bb25e74026e9", - "sha256:c2f20ce161ebdb0091a10c9ca0372e023ce24980d0e1f810f519da6f79c60800", - "sha256:c56d748ea50215abef7030c72b60dd723ed5b5c7e65e7bc2504e77843631c1a6", - "sha256:c7c133e93b405eb0d36fa430c94185bdd13c36204a8635470cccc200723c13bb", - "sha256:c9c6c9b2c2f80747a98f34ef491c4d7b1a8d4853937bb1492774992a120f475d", - "sha256:cbc8df5c6a88ba5ae385d8930da02201165408dde8d8322072e3e5ddd4f68e22", - "sha256:cff084c6933680d1f8b2f3b4ff5bbb88538a4aac00d199ac13f49d0698727ecb", - "sha256:d2045d6d9439a0078f2a34b57c7b18c4a6aef0bee37f22e4ec9f32456c852c71", - "sha256:d20a0ddb3e989e8807d83225a27e5c2eb2260eaa851532086e9e0fa0d5287d83", - "sha256:d457aed310f2670f59cc5b57dcfced452aeeed77f9da2b9763616bd57e4dbaae", - "sha256:d89528b4943d27029a2818f847c10c2cecc79fa9590f3cb1860459a5be7933eb", - "sha256:db0b2af416ba735c6304c47f75d348f498b92952f5e3e8bff449336d2728795d", - "sha256:deee9ca4727f53464daf089536e68b13e6104e84a37820a88b0a057b97bba2d2", - "sha256:df27ffddff4190667d40de7beba4a950b5ce78fe28a7dcc41d6f8a700a80a3c0", - "sha256:e0c95ddd4f6e9fca4e9e3afaa4f9df8552f0ba5d1004e89ef0a68e1f1f9807c7", - "sha256:e1c1be77bc5fb77d923850f82e55a928f8638f64a61f00ff18a67c7404faf008", - "sha256:e1ffa1c924e8c72778b9ccd386a7067cddf626884fd8277f503c48bb5f51c762", - "sha256:e2400a94f7dd9cb20cd012951a0cbf8249e3d554c63a9c0cdfd5cbb6c01d2dec", - "sha256:e61f091c3ba0c3578411ef505992d356a812fb200643eab27f4f70eed34a29ef", - "sha256:e8a701123029cc240cea61dd2d16ad57cab4691804143ce80ecd9286b464d180", - "sha256:eadbefd5e92ef8a345f0525b5cfd01cf4e4cc651a2cffb8f23c0dd184975d787", - "sha256:f32260e556a983bc5c7ed588d04c942c9a8f9c2e99213fec11a031e316874c7e", - "sha256:f8115e303280ba09f3898194791a153862cbf9eef722ad8f7f741987ee2a97c7", - "sha256:fedbdc753827cf014c01dbbee9c3be17e5a208dcd1bf8641ce2cd29580d1f0d4" + "sha256:004ff469d21e86f0ef0369717351073e0e577428e514c47c8480770d5e24a565", + "sha256:00a06faa7165634f0cac1abb27e54d7a0b3b44eb9994530b8ec73cf52e15353b", + "sha256:00c48ae2fd81e2a50c3485de1b9d5c7c57cd85dc8ec55683eac16846e57ac979", + "sha256:01171fc48542348cd1a360a4b6c3e7d8f46cdcf53a8d40f84db6707a6768acc1", + "sha256:019744b99da30330798bb37df33549d59d380c78e516e3bab9c9b84f87a9592f", + "sha256:02bbc1a87b76e04fd780b45e7f695471ae6de747769e540da909173d50ff8e2d", + "sha256:02c9087b109070c5ab0b383079fa1b5f797f8d43e9a66c07a4b8b8bdecfd88ee", + "sha256:07cd61a20a535524906595e09344505a9bd46f1da7a07e504b315d41cd42eb07", + "sha256:0806175f2ae5ad4b835ecd87f5f85583316b69f17e97786f7443baaf54b9bb98", + "sha256:09dfe949e83087da88c4a76767df04b22304a682d6154de2c572625c62ad6886", + "sha256:0dabfb10ef897f3b7e101cacba1437bd3a5032ee667b7ead32bbcdd1a8422fe7", + "sha256:0ddd6d71d4ef17ba5a87becf7ddf01b371eaba553c603477679ae817a8d84d75", + "sha256:0f513130c4c361201da9bc69df25a086487250e16b5571ead521b31ff6b02220", + "sha256:0f97bc2f1f13cb16905a5f3e1fbdf100e712d841482b2237484360f8bc4cb3d7", + "sha256:11e70516688190e9c2db14fcf93c04192b02d457b582a1f6190b154691b4c93a", + "sha256:146b9b1f29ead41255387fb07be56dc29639262c0f7344f570eecdcd8d683314", + "sha256:16b726c1f6c2e7625706549f9dbe9b06004dfbec30dbed4bf50cbdfc73e5b32a", + "sha256:1b3cbba2f47062b85fe0ef9de5b987612140a9ba3a9c6d2543c6dec9f7c2ab27", + "sha256:1b9b1f2ad6498445a941d9a4fee096d387fee436e45cc660e72e768d3d8ee611", + "sha256:1ec23bd7b3a893ae676d0e54ad47d18064e6c5ae1fadc2f195143fb27373f7f6", + "sha256:246747b88917e4867e2367b005fc8eefbb4a54b7db363d6c92f89d69abfff4b6", + "sha256:25c2dbb97d38b5ac9fd15586e048ec5eb1e38f3d47fe7d92167b0c77bb3584e9", + "sha256:2c6441e0398c2baacfe5ba30c937d274cfc2dc5b55e82e3749e333aabffde561", + "sha256:2c9a79f1d2495b167119d02be7448bfba57fad2a4207c4f68abc0bab4b92925b", + "sha256:2e2713ef44be5d52dd8b8e2023d706bf66cb22072e97fc71b168e01d25192755", + "sha256:313c3794d650d1fccaaab2df942af9f2c01d6217c846177cfcbc693c7410839e", + "sha256:3516e0b6224cf6e43e341d56da15fd33bdc37fa0c06af4f029f7d7dfceceabbc", + "sha256:359f7f74b5d3c65dae137f33eb2bcfa7ad9ebefd1cab85c935f063f1dbb245cc", + "sha256:39b1067f13aba39d794a24761e385e2eddc26295826530a8c7b6c6c341584289", + "sha256:3c00c9b7d1ca8165c610437ca0c92e7b5607b2f9076f4eb4b095c85d6e680a1d", + "sha256:3c53687dde4d9d473c587ae80cc328e5b102b517447456184b485587ebd18b62", + "sha256:3e124e6b1dd3dfbeb695435dff0e383256655bb18082e094a8dd1f6293114642", + "sha256:4345c9a27f4310afbb9c01750e9461ff33d6fb74cd2456b107525bbeebcb5be3", + "sha256:45999e7f7ed5c390f2e87ece7f6c56bf979fb213550229e711e45ecc7d42ccb8", + "sha256:49151b0efece79f6a79d41a461d78535356136ee70084a1c22532fc6383f4ad0", + "sha256:4cb8fc1f8d69b411b8ec0b5f1ffbcaf14c1db95b6bccea21d83610987435f1a4", + "sha256:4e5837af3e5aaa99a091302df5ee001149baff06ad22b722d34e30df5f0d9097", + "sha256:4e6f689880d5ad87918430957297c975203a082d9a036cc426648fcbedae769b", + "sha256:5074adeacede5f810b7ef39607ee59d94e948b4fd954495bdb072f8c54558181", + "sha256:518efd91c3d8ac9f9b4f7dd0e2b7b8bf1a4fe82a308009016b07eaa48681af82", + "sha256:55875492f820d0eb3417b51d96fea549cde77893ae3790fd25491c5754ea2f68", + "sha256:5a68d491fc20762b630e5db2191dd07ff89834086740f70e978bb2ef2668be08", + "sha256:5dde6751e857910c1339890f3524de74007958557593b9e7e8c5f01cd919f8a7", + "sha256:5e319ed7d6b8f5fad9b76daa0a68497bc6f129858ad956331a5835785761e003", + "sha256:5edac3f57c7ddaacdb4d40f6ef2f9e299471fc38d112f4bc6d60ab9365445fb0", + "sha256:6cc0020b74b2e410287e5942e1e10886ff81ac77789eb20bec13f7ae681f0fdd", + "sha256:6dd0d50bbf9dca1d0bdea219ae6b40f713a3fb477c06ca3714f208fd69e16fd8", + "sha256:7598d2ba821caa37a0f9d54c25164a4fa351ce019d64d0b44b45540950458840", + "sha256:759cfd391a0996345ba94b6a5110fca9c557ad4166d86a6e81ea526c376a01e8", + "sha256:7ae8f354b895cbd85212da245f1a5ad8159e7840e37d78b476bb4f4c3f32a9fe", + "sha256:7b6d09a8962a91151f0976008eb7b29b433a560fde056ec7a3db9ec8f1075438", + "sha256:7c61e346ac34b74028ede1c6b4bcecf649d69b707b3ff9dc0fab453821b04d1e", + "sha256:7f51a7b4ead28d3fca8dda53216314a553b0f7a91ee8fc46a72b402a78c3e43d", + "sha256:82544e0e2d0c1811482d37eef297020a040c32e0687c1f6fc23a75b75db8062c", + "sha256:8807c87fa893527ae8a524c15fc505d9950d5e856f03dae5921b5e9aa3b8783b", + "sha256:889370d5174a741a62566c003ee8ddba4b04c3f09a97b8000092b7ca83ec9c49", + "sha256:8b14c75979ce932c53b79976a395cb2a8cd3aaf14aef75e8c2cb55a330b9b49d", + "sha256:8c5f80e578427d4695adac6fdf4370c14a2feafdc8cb35549c219b90652536ae", + "sha256:8e9f3fabc445d0ce320ea2c59a75fe3ea591fdbdeebec5db6de530dd4b09412e", + "sha256:93f1aa311e8bb912e34f004cf186407a4e90eec4f0ecc0efd26056bf7eda0226", + "sha256:94504ff66f278ab4b7e03e4cba7e7e400cb73bfa9d3d71f58d8972a8dc67e7a6", + "sha256:967668420f36878a3c9ecb5ab33c9d0ff8d054f9c0233d995a6d25b0e95e1b6b", + "sha256:9880078f683466b7f567b8624bfc16cad65077be046b6e8abb53bed4eeb82dd3", + "sha256:99a6b36f95c98839ad98f8c553d8507644c880cf1e0a57fe5e3a3f3969040882", + "sha256:9a18fff090441a40ffda8a7f4f18f03dc56ae73f148f1832e109f9bffa85df15", + "sha256:9add2e5b33d2cd765ad96d5eb734a5e795a0755f7fc49aa04f76d7ddda73fd70", + "sha256:a793ac733e3d895d96f865f1806f160696422554e46d30105807fdc9841b9f7d", + "sha256:a86c2dd76ef71a773e70551a07318b8e52379f58dafa7ae1e0a4be78efd1ff16", + "sha256:a8c1d566344aee826b74e472e16edae0a02e2a044f14f7c24e123002dcff1c05", + "sha256:ac170e9e048b40c605358667aca3d94e98f604a18c44bdb4c102e67070f3ac9b", + "sha256:b264bf2cc96b5bc43ce0e852be995e400376bd87ceb363822e2cb1964fcdc737", + "sha256:b8c8a419dfb02e91b453615c69568442e897aaf77561ee0064d789705ff37a92", + "sha256:bc69c96735ab501419c432110016329bf0dea8898ce16fab97c6d9106dc0b348", + "sha256:bef02cfcbded83473bdd86dd8d3729cd82b2e569b75844fb4ea08fee3c26ae41", + "sha256:c0b5ca88a8928147b7b1e2dfa09f3b6c256bc1135a1338536cbc9ea13d3b7add", + "sha256:cc69949484171cc961e6ecd4a8911b9ce7a0d1f738fcae717177c231bf77437b", + "sha256:ced111c2e81506abd1dc142e6cd7b68dd53747b3b7ae5edbea4578c5eeff96b7", + "sha256:d1299d7e964c13607efd148ca1f07dcbf27c3ab9e125d1d0ae1d580a1682399d", + "sha256:d1b604734bec94f05f81b360a272fc824334267426ae9905ff32dc2be433ab96", + "sha256:d9a5f194cf730f2b24d6af1f833c14c10f41023da46a7f736f48b6d35061e76e", + "sha256:db36c27baed588a5a8346b971477b718fdc66cf5b80cbfbd914b4d6d355e44e2", + "sha256:df0c7a16ebb94452d2909b9a7b3337940e9a87a824c4fc1c7c36bb4404cb0cde", + "sha256:e10a4b5a4b1192d74853cc71a5e9fd022594573926c2a3a4802020360aa719d8", + "sha256:e624c789359f1a16f83f35e2c705d07663ff2b4d4479bad35621178d8f0f6ea4", + "sha256:e690145a8c0c273c28d3b89d6fb32c45e0d9605b2293c10e650265bf5c11cfec", + "sha256:ea1608dd169da230a0ad602d5b1ebd39807ac96cae1845c3ceed39af08a5c6df", + "sha256:ea253b368eb41116011add00f8d5726762320b1bda892f744c91997b65754d73", + "sha256:eb7e49a17fb8c77d3119d41a4523e432eb0c6932187c37deb6fbb00cc3028088", + "sha256:ef12e259e7bc317c7597d4f6ef59b97b913e162d83b421dd0db3d6410f17a244", + "sha256:f8429b17cbb746c3e043cb986328da023657e79d5ed258b711c06a70c2ea7537", + "sha256:fa99973d2ed20417744fca0073390ad65ce225b546febb0580358e36aa90dba6", + "sha256:faf79a302f834d9e8304fafdc11d0d042266667ac45209afa57e5efc998e3872", + "sha256:fc31baa0c32a2ca660784d5af3b9487e13b61b3032cb01a115fce6588e1bed30" ], "markers": "python_version >= '3.6'", - "version": "==25.1.1" + "version": "==25.1.2" }, "qdldl": { "hashes": [ @@ -2692,13 +3909,44 @@ "index": "pypi", "version": "==0.1.7.post0" }, + "qtconsole": { + "hashes": [ + "sha256:8c75fa3e9b4ed884880ff7cea90a1b67451219279ec33deaee1d59e3df1a5d2b", + "sha256:a0e806c6951db9490628e4df80caec9669b65149c7ba40f9bf033c025a5b56bc" + ], + "markers": "python_version >= '3.8'", + "version": "==5.5.1" + }, + "qtpy": { + "hashes": [ + "sha256:1c1d8c4fa2c884ae742b069151b0abe15b3f70491f3972698c683b8e38de839b", + "sha256:a5a15ffd519550a1361bdc56ffc07fda56a6af7292f17c7b395d4083af632987" + ], + "markers": "python_version >= '3.7'", + "version": "==2.4.1" + }, + "readthedocs-sphinx-ext": { + "hashes": [ + "sha256:6583c26791a5853ee9e57ce9db864e2fb06808ba470f805d74d53fc50811e012", + "sha256:e9d911792789b88ae12e2be94d88c619f89a4fa1fe9e42c1505c9930a07163d8" + ], + "version": "==2.2.3" + }, + "recordlinkage": { + "hashes": [ + "sha256:7ca404ab30435ea4b0ae2eda411f8dcc3c48186e152d3ca91fb525e8f6c0fd63", + "sha256:ecda0c10dff138b1706815de332b1285f670ae7e8cce92596213501d589e6aa4" + ], + "markers": "python_version >= '3.8'", + "version": "==0.16" + }, "referencing": { "hashes": [ - "sha256:381b11e53dd93babb55696c71cf42aef2d36b8a150c49bf0bc301e36d536c882", - "sha256:cc28f2c88fbe7b961a7817a0abc034c09a1e36358f82fedb4ffdf29a25398863" + "sha256:81a1471c68c9d5e3831c30ad1dd9815c45b558e596653db751a2bfdd17b3b9ec", + "sha256:c19c4d006f1757e3dd75c4f784d38f8698d87b649c54f9ace14e5e8c9667c01d" ], "markers": "python_version >= '3.8'", - "version": "==0.31.0" + "version": "==0.31.1" }, "regex": { "hashes": [ @@ -2811,6 +4059,20 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.3.1" }, + "responses": { + "hashes": [ + "sha256:a2b43f4c08bfb9c9bd242568328c65a34b318741d3fab884ac843c5ceeb543f9", + "sha256:b127c6ca3f8df0eb9cc82fd93109a3007a86acb24871834c47b77765152ecf8c" + ], + "markers": "python_version >= '3.8'", + "version": "==0.24.1" + }, + "restructuredtext-lint": { + "hashes": [ + "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45" + ], + "version": "==1.4.0" + }, "rfc3339-validator": { "hashes": [ "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", @@ -2844,108 +4106,108 @@ }, "rpds-py": { "hashes": [ - "sha256:0290712eb5603a725769b5d857f7cf15cf6ca93dda3128065bbafe6fdb709beb", - "sha256:032c242a595629aacace44128f9795110513ad27217b091e834edec2fb09e800", - "sha256:08832078767545c5ee12561ce980714e1e4c6619b5b1e9a10248de60cddfa1fd", - "sha256:08b335fb0c45f0a9e2478a9ece6a1bfb00b6f4c4780f9be3cf36479c5d8dd374", - "sha256:0b70c1f800059c92479dc94dda41288fd6607f741f9b1b8f89a21a86428f6383", - "sha256:0d9f8930092558fd15c9e07198625efb698f7cc00b3dc311c83eeec2540226a8", - "sha256:181ee352691c4434eb1c01802e9daa5edcc1007ff15023a320e2693fed6a661b", - "sha256:19f5aa7f5078d35ed8e344bcba40f35bc95f9176dddb33fc4f2084e04289fa63", - "sha256:1a3b2583c86bbfbf417304eeb13400ce7f8725376dc7d3efbf35dc5d7052ad48", - "sha256:1c9a1dc5e898ce30e2f9c0aa57181cddd4532b22b7780549441d6429d22d3b58", - "sha256:1f36a1e80ef4ed1996445698fd91e0d3e54738bf597c9995118b92da537d7a28", - "sha256:20147996376be452cd82cd6c17701daba69a849dc143270fa10fe067bb34562a", - "sha256:249c8e0055ca597707d71c5ad85fd2a1c8fdb99386a8c6c257e1b47b67a9bec1", - "sha256:2647192facf63be9ed2d7a49ceb07efe01dc6cfb083bd2cc53c418437400cb99", - "sha256:264f3a5906c62b9df3a00ad35f6da1987d321a053895bd85f9d5c708de5c0fbf", - "sha256:2abd669a39be69cdfe145927c7eb53a875b157740bf1e2d49e9619fc6f43362e", - "sha256:2b2415d5a7b7ee96aa3a54d4775c1fec140476a17ee12353806297e900eaeddc", - "sha256:2c173f529666bab8e3f948b74c6d91afa22ea147e6ebae49a48229d9020a47c4", - "sha256:2da81c1492291c1a90987d76a47c7b2d310661bf7c93a9de0511e27b796a8b46", - "sha256:2eca04a365be380ca1f8fa48b334462e19e3382c0bb7386444d8ca43aa01c481", - "sha256:37b08df45f02ff1866043b95096cbe91ac99de05936dd09d6611987a82a3306a", - "sha256:37f79f4f1f06cc96151f4a187528c3fd4a7e1065538a4af9eb68c642365957f7", - "sha256:3dd5fb7737224e1497c886fb3ca681c15d9c00c76171f53b3c3cc8d16ccfa7fb", - "sha256:3e3ac5b602fea378243f993d8b707189f9061e55ebb4e56cb9fdef8166060f28", - "sha256:3f55ae773abd96b1de25fc5c3fb356f491bd19116f8f854ba705beffc1ddc3c5", - "sha256:4011d5c854aa804c833331d38a2b6f6f2fe58a90c9f615afdb7aa7cf9d31f721", - "sha256:4145172ab59b6c27695db6d78d040795f635cba732cead19c78cede74800949a", - "sha256:42b9535aa22ab023704cfc6533e968f7e420affe802d85e956d8a7b4c0b0b5ea", - "sha256:46a07a258bda12270de02b34c4884f200f864bba3dcd6e3a37fef36a168b859d", - "sha256:4f13d3f6585bd07657a603780e99beda96a36c86acaba841f131e81393958336", - "sha256:528e2afaa56d815d2601b857644aeb395afe7e59212ab0659906dc29ae68d9a6", - "sha256:545e94c84575057d3d5c62634611858dac859702b1519b6ffc58eca7fb1adfcf", - "sha256:577d40a72550eac1386b77b43836151cb61ff6700adacda2ad4d883ca5a0b6f2", - "sha256:5967fa631d0ed9f8511dede08bc943a9727c949d05d1efac4ac82b2938024fb7", - "sha256:5b769396eb358d6b55dbf78f3f7ca631ca1b2fe02136faad5af74f0111b4b6b7", - "sha256:63c9e2794329ef070844ff9bfc012004aeddc0468dc26970953709723f76c8a5", - "sha256:6574f619e8734140d96c59bfa8a6a6e7a3336820ccd1bfd95ffa610673b650a2", - "sha256:6bfe72b249264cc1ff2f3629be240d7d2fdc778d9d298087cdec8524c91cd11f", - "sha256:736817dbbbd030a69a1faf5413a319976c9c8ba8cdcfa98c022d3b6b2e01eca6", - "sha256:74a2044b870df7c9360bb3ce7e12f9ddf8e72e49cd3a353a1528cbf166ad2383", - "sha256:74be3b215a5695690a0f1a9f68b1d1c93f8caad52e23242fcb8ba56aaf060281", - "sha256:76a8374b294e4ccb39ccaf11d39a0537ed107534139c00b4393ca3b542cc66e5", - "sha256:7ba239bb37663b2b4cd08e703e79e13321512dccd8e5f0e9451d9e53a6b8509a", - "sha256:7c40851b659d958c5245c1236e34f0d065cc53dca8d978b49a032c8e0adfda6e", - "sha256:7cf241dbb50ea71c2e628ab2a32b5bfcd36e199152fc44e5c1edb0b773f1583e", - "sha256:7cfae77da92a20f56cf89739a557b76e5c6edc094f6ad5c090b9e15fbbfcd1a4", - "sha256:7d152ec7bb431040af2500e01436c9aa0d993f243346f0594a15755016bf0be1", - "sha256:80080972e1d000ad0341c7cc58b6855c80bd887675f92871221451d13a975072", - "sha256:82dbcd6463e580bcfb7561cece35046aaabeac5a9ddb775020160b14e6c58a5d", - "sha256:8308a8d49d1354278d5c068c888a58d7158a419b2e4d87c7839ed3641498790c", - "sha256:839676475ac2ccd1532d36af3d10d290a2ca149b702ed464131e450a767550df", - "sha256:83feb0f682d75a09ddc11aa37ba5c07dd9b824b22915207f6176ea458474ff75", - "sha256:88956c993a20201744282362e3fd30962a9d86dc4f1dcf2bdb31fab27821b61f", - "sha256:8a6ad8429340e0a4de89353447c6441329def3632e7b2293a7d6e873217d3c2b", - "sha256:8ba9fbc5d6e36bfeb5292530321cc56c4ef3f98048647fabd8f57543c34174ec", - "sha256:8c1f6c8df23be165eb0cb78f305483d00c6827a191e3a38394c658d5b9c80bbd", - "sha256:91276caef95556faeb4b8f09fe4439670d3d6206fee78d47ddb6e6de837f0b4d", - "sha256:960e7e460fda2d0af18c75585bbe0c99f90b8f09963844618a621b804f8c3abe", - "sha256:9656a09653b18b80764647d585750df2dff8928e03a706763ab40ec8c4872acc", - "sha256:9cd935c0220d012a27c20135c140f9cdcbc6249d5954345c81bfb714071b985c", - "sha256:a2b3c79586636f1fa69a7bd59c87c15fca80c0d34b5c003d57f2f326e5276575", - "sha256:a4b9d3f5c48bbe8d9e3758e498b3c34863f2c9b1ac57a4e6310183740e59c980", - "sha256:a8c2bf286e5d755a075e5e97ba56b3de08cccdad6b323ab0b21cc98875176b03", - "sha256:a90031658805c63fe488f8e9e7a88b260ea121ba3ee9cdabcece9c9ddb50da39", - "sha256:ad666a904212aa9a6c77da7dce9d5170008cda76b7776e6731928b3f8a0d40fa", - "sha256:af2d1648eb625a460eee07d3e1ea3a4a6e84a1fb3a107f6a8e95ac19f7dcce67", - "sha256:b3d4b390ee70ca9263b331ccfaf9819ee20e90dfd0201a295e23eb64a005dbef", - "sha256:ba4432301ad7eeb1b00848cf46fae0e5fecfd18a8cb5fdcf856c67985f79ecc7", - "sha256:bc3179e0815827cf963e634095ae5715ee73a5af61defbc8d6ca79f1bdae1d1d", - "sha256:c5fd099acaee2325f01281a130a39da08d885e4dedf01b84bf156ec2737d78fe", - "sha256:c797ea56f36c6f248656f0223b11307fdf4a1886f3555eba371f34152b07677f", - "sha256:cd4ea56c9542ad0091dfdef3e8572ae7a746e1e91eb56c9e08b8d0808b40f1d1", - "sha256:cdd6f8738e1f1d9df5b1603bb03cb30e442710e5672262b95d0f9fcb4edb0dab", - "sha256:d0580faeb9def6d0beb7aa666294d5604e569c4e24111ada423cf9936768d95c", - "sha256:d11afdc5992bbd7af60ed5eb519873690d921425299f51d80aa3099ed49f2bcc", - "sha256:d1d388d2f5f5a6065cf83c54dd12112b7389095669ff395e632003ae8999c6b8", - "sha256:d20da6b4c7aa9ee75ad0730beaba15d65157f5beeaca54a038bb968f92bf3ce3", - "sha256:d22e0660de24bd8e9ac82f4230a22a5fe4e397265709289d61d5fb333839ba50", - "sha256:d22f2cb82e0b40e427a74a93c9a4231335bbc548aed79955dde0b64ea7f88146", - "sha256:d4fa1eeb9bea6d9b64ac91ec51ee94cc4fc744955df5be393e1c923c920db2b0", - "sha256:d9793d46d3e6522ae58e9321032827c9c0df1e56cbe5d3de965facb311aed6aa", - "sha256:dab979662da1c9fbb464e310c0b06cb5f1d174d09a462553af78f0bfb3e01920", - "sha256:db8d0f0ad92f74feb61c4e4a71f1d573ef37c22ef4dc19cab93e501bfdad8cbd", - "sha256:df2af1180b8eeececf4f819d22cc0668bfadadfd038b19a90bd2fb2ee419ec6f", - "sha256:dfb5d2ab183c0efe5e7b8917e4eaa2e837aacafad8a69b89aa6bc81550eed857", - "sha256:e04f8c76b8d5c70695b4e8f1d0b391d8ef91df00ef488c6c1ffb910176459bc6", - "sha256:e4a45ba34f904062c63049a760790c6a2fa7a4cc4bd160d8af243b12371aaa05", - "sha256:e9be1f7c5f9673616f875299339984da9447a40e3aea927750c843d6e5e2e029", - "sha256:edc91c50e17f5cd945d821f0f1af830522dba0c10267c3aab186dc3dbaab8def", - "sha256:ee70ee5f4144a45a9e6169000b5b525d82673d5dab9f7587eccc92794814e7ac", - "sha256:f1059ca9a51c936c9a8d46fbc2c9a6b4c15ab3f13a97f1ad32f024b39666ba85", - "sha256:f47eef55297799956464efc00c74ae55c48a7b68236856d56183fe1ddf866205", - "sha256:f4ae6f423cb7d1c6256b7482025ace2825728f53b7ac58bcd574de6ee9d242c2", - "sha256:f4b15a163448ec79241fb2f1bc5a8ae1a4a304f7a48d948d208a2935b26bf8a5", - "sha256:f55601fb58f92e4f4f1d05d80c24cb77505dc42103ddfd63ddfdc51d3da46fa2", - "sha256:fa84bbe22ffa108f91631935c28a623001e335d66e393438258501e618fb0dde", - "sha256:faa12a9f34671a30ea6bb027f04ec4e1fb8fa3fb3ed030893e729d4d0f3a9791", - "sha256:fcfd5f91b882eedf8d9601bd21261d6ce0e61a8c66a7152d1f5df08d3f643ab1", - "sha256:fe30ef31172bdcf946502a945faad110e8fff88c32c4bec9a593df0280e64d8a" + "sha256:06d218e4464d31301e943b65b2c6919318ea6f69703a351961e1baaf60347276", + "sha256:12ecf89bd54734c3c2c79898ae2021dca42750c7bcfb67f8fb3315453738ac8f", + "sha256:15253fff410873ebf3cfba1cc686a37711efcd9b8cb30ea21bb14a973e393f60", + "sha256:188435794405c7f0573311747c85a96b63c954a5f2111b1df8018979eca0f2f0", + "sha256:1ceebd0ae4f3e9b2b6b553b51971921853ae4eebf3f54086be0565d59291e53d", + "sha256:244e173bb6d8f3b2f0c4d7370a1aa341f35da3e57ffd1798e5b2917b91731fd3", + "sha256:25b28b3d33ec0a78e944aaaed7e5e2a94ac811bcd68b557ca48a0c30f87497d2", + "sha256:25ea41635d22b2eb6326f58e608550e55d01df51b8a580ea7e75396bafbb28e9", + "sha256:29d311e44dd16d2434d5506d57ef4d7036544fc3c25c14b6992ef41f541b10fb", + "sha256:2a1472956c5bcc49fb0252b965239bffe801acc9394f8b7c1014ae9258e4572b", + "sha256:2a7bef6977043673750a88da064fd513f89505111014b4e00fbdd13329cd4e9a", + "sha256:2ac26f50736324beb0282c819668328d53fc38543fa61eeea2c32ea8ea6eab8d", + "sha256:2e72f750048b32d39e87fc85c225c50b2a6715034848dbb196bf3348aa761fa1", + "sha256:31e220a040b89a01505128c2f8a59ee74732f666439a03e65ccbf3824cdddae7", + "sha256:35f53c76a712e323c779ca39b9a81b13f219a8e3bc15f106ed1e1462d56fcfe9", + "sha256:38d4f822ee2f338febcc85aaa2547eb5ba31ba6ff68d10b8ec988929d23bb6b4", + "sha256:38f9bf2ad754b4a45b8210a6c732fe876b8a14e14d5992a8c4b7c1ef78740f53", + "sha256:3a44c8440183b43167fd1a0819e8356692bf5db1ad14ce140dbd40a1485f2dea", + "sha256:3ab96754d23372009638a402a1ed12a27711598dd49d8316a22597141962fe66", + "sha256:3c55d7f2d817183d43220738270efd3ce4e7a7b7cbdaefa6d551ed3d6ed89190", + "sha256:46e1ed994a0920f350a4547a38471217eb86f57377e9314fbaaa329b71b7dfe3", + "sha256:4a5375c5fff13f209527cd886dc75394f040c7d1ecad0a2cb0627f13ebe78a12", + "sha256:4c2d26aa03d877c9730bf005621c92da263523a1e99247590abbbe252ccb7824", + "sha256:4c4e314d36d4f31236a545696a480aa04ea170a0b021e9a59ab1ed94d4c3ef27", + "sha256:4d0c10d803549427f427085ed7aebc39832f6e818a011dcd8785e9c6a1ba9b3e", + "sha256:4dcc5ee1d0275cb78d443fdebd0241e58772a354a6d518b1d7af1580bbd2c4e8", + "sha256:51967a67ea0d7b9b5cd86036878e2d82c0b6183616961c26d825b8c994d4f2c8", + "sha256:530190eb0cd778363bbb7596612ded0bb9fef662daa98e9d92a0419ab27ae914", + "sha256:5379e49d7e80dca9811b36894493d1c1ecb4c57de05c36f5d0dd09982af20211", + "sha256:5493569f861fb7b05af6d048d00d773c6162415ae521b7010197c98810a14cab", + "sha256:5a4c1058cdae6237d97af272b326e5f78ee7ee3bbffa6b24b09db4d828810468", + "sha256:5d75d6d220d55cdced2f32cc22f599475dbe881229aeddba6c79c2e9df35a2b3", + "sha256:5d97e9ae94fb96df1ee3cb09ca376c34e8a122f36927230f4c8a97f469994bff", + "sha256:5feae2f9aa7270e2c071f488fab256d768e88e01b958f123a690f1cc3061a09c", + "sha256:603d5868f7419081d616dab7ac3cfa285296735e7350f7b1e4f548f6f953ee7d", + "sha256:61d42d2b08430854485135504f672c14d4fc644dd243a9c17e7c4e0faf5ed07e", + "sha256:61dbc1e01dc0c5875da2f7ae36d6e918dc1b8d2ce04e871793976594aad8a57a", + "sha256:65cfed9c807c27dee76407e8bb29e6f4e391e436774bcc769a037ff25ad8646e", + "sha256:67a429520e97621a763cf9b3ba27574779c4e96e49a27ff8a1aa99ee70beb28a", + "sha256:6aadae3042f8e6db3376d9e91f194c606c9a45273c170621d46128f35aef7cd0", + "sha256:6ba8858933f0c1a979781272a5f65646fca8c18c93c99c6ddb5513ad96fa54b1", + "sha256:6bc568b05e02cd612be53900c88aaa55012e744930ba2eeb56279db4c6676eb3", + "sha256:729408136ef8d45a28ee9a7411917c9e3459cf266c7e23c2f7d4bb8ef9e0da42", + "sha256:751758d9dd04d548ec679224cc00e3591f5ebf1ff159ed0d4aba6a0746352452", + "sha256:76d59d4d451ba77f08cb4cd9268dec07be5bc65f73666302dbb5061989b17198", + "sha256:79bf58c08f0756adba691d480b5a20e4ad23f33e1ae121584cf3a21717c36dfa", + "sha256:7de12b69d95072394998c622cfd7e8cea8f560db5fca6a62a148f902a1029f8b", + "sha256:7f55cd9cf1564b7b03f238e4c017ca4794c05b01a783e9291065cb2858d86ce4", + "sha256:80e5acb81cb49fd9f2d5c08f8b74ffff14ee73b10ca88297ab4619e946bcb1e1", + "sha256:87a90f5545fd61f6964e65eebde4dc3fa8660bb7d87adb01d4cf17e0a2b484ad", + "sha256:881df98f0a8404d32b6de0fd33e91c1b90ed1516a80d4d6dc69d414b8850474c", + "sha256:8a776a29b77fe0cc28fedfd87277b0d0f7aa930174b7e504d764e0b43a05f381", + "sha256:8c2a61c0e4811012b0ba9f6cdcb4437865df5d29eab5d6018ba13cee1c3064a0", + "sha256:8fa6bd071ec6d90f6e7baa66ae25820d57a8ab1b0a3c6d3edf1834d4b26fafa2", + "sha256:96f2975fb14f39c5fe75203f33dd3010fe37d1c4e33177feef1107b5ced750e3", + "sha256:96fb0899bb2ab353f42e5374c8f0789f54e0a94ef2f02b9ac7149c56622eaf31", + "sha256:97163a1ab265a1073a6372eca9f4eeb9f8c6327457a0b22ddfc4a17dcd613e74", + "sha256:9c95a1a290f9acf7a8f2ebbdd183e99215d491beea52d61aa2a7a7d2c618ddc6", + "sha256:9d94d78418203904730585efa71002286ac4c8ac0689d0eb61e3c465f9e608ff", + "sha256:a6ba2cb7d676e9415b9e9ac7e2aae401dc1b1e666943d1f7bc66223d3d73467b", + "sha256:aa0379c1935c44053c98826bc99ac95f3a5355675a297ac9ce0dfad0ce2d50ca", + "sha256:ac96d67b37f28e4b6ecf507c3405f52a40658c0a806dffde624a8fcb0314d5fd", + "sha256:ade2ccb937060c299ab0dfb2dea3d2ddf7e098ed63ee3d651ebfc2c8d1e8632a", + "sha256:aefbdc934115d2f9278f153952003ac52cd2650e7313750390b334518c589568", + "sha256:b07501b720cf060c5856f7b5626e75b8e353b5f98b9b354a21eb4bfa47e421b1", + "sha256:b5267feb19070bef34b8dea27e2b504ebd9d31748e3ecacb3a4101da6fcb255c", + "sha256:b5f6328e8e2ae8238fc767703ab7b95785521c42bb2b8790984e3477d7fa71ad", + "sha256:b8996ffb60c69f677245f5abdbcc623e9442bcc91ed81b6cd6187129ad1fa3e7", + "sha256:b981a370f8f41c4024c170b42fbe9e691ae2dbc19d1d99151a69e2c84a0d194d", + "sha256:b9d121be0217787a7d59a5c6195b0842d3f701007333426e5154bf72346aa658", + "sha256:bcef4f2d3dc603150421de85c916da19471f24d838c3c62a4f04c1eb511642c1", + "sha256:bed0252c85e21cf73d2d033643c945b460d6a02fc4a7d644e3b2d6f5f2956c64", + "sha256:bfdfbe6a36bc3059fff845d64c42f2644cf875c65f5005db54f90cdfdf1df815", + "sha256:c0095b8aa3e432e32d372e9a7737e65b58d5ed23b9620fea7cb81f17672f1fa1", + "sha256:c1f41d32a2ddc5a94df4b829b395916a4b7f103350fa76ba6de625fcb9e773ac", + "sha256:c45008ca79bad237cbc03c72bc5205e8c6f66403773929b1b50f7d84ef9e4d07", + "sha256:c82bbf7e03748417c3a88c1b0b291288ce3e4887a795a3addaa7a1cfd9e7153e", + "sha256:c918621ee0a3d1fe61c313f2489464f2ae3d13633e60f520a8002a5e910982ee", + "sha256:d204957169f0b3511fb95395a9da7d4490fb361763a9f8b32b345a7fe119cb45", + "sha256:d329896c40d9e1e5c7715c98529e4a188a1f2df51212fd65102b32465612b5dc", + "sha256:d3a61e928feddc458a55110f42f626a2a20bea942ccedb6fb4cee70b4830ed41", + "sha256:d48db29bd47814671afdd76c7652aefacc25cf96aad6daefa82d738ee87461e2", + "sha256:d5593855b5b2b73dd8413c3fdfa5d95b99d657658f947ba2c4318591e745d083", + "sha256:d79c159adea0f1f4617f54aa156568ac69968f9ef4d1e5fefffc0a180830308e", + "sha256:db09b98c7540df69d4b47218da3fbd7cb466db0fb932e971c321f1c76f155266", + "sha256:ddf23960cb42b69bce13045d5bc66f18c7d53774c66c13f24cf1b9c144ba3141", + "sha256:e06cfea0ece444571d24c18ed465bc93afb8c8d8d74422eb7026662f3d3f779b", + "sha256:e7c564c58cf8f248fe859a4f0fe501b050663f3d7fbc342172f259124fb59933", + "sha256:e86593bf8637659e6a6ed58854b6c87ec4e9e45ee8a4adfd936831cef55c2d21", + "sha256:eaffbd8814bb1b5dc3ea156a4c5928081ba50419f9175f4fc95269e040eff8f0", + "sha256:ee353bb51f648924926ed05e0122b6a0b1ae709396a80eb583449d5d477fcdf7", + "sha256:ee6faebb265e28920a6f23a7d4c362414b3f4bb30607141d718b991669e49ddc", + "sha256:efe093acc43e869348f6f2224df7f452eab63a2c60a6c6cd6b50fd35c4e075ba", + "sha256:f03a1b3a4c03e3e0161642ac5367f08479ab29972ea0ffcd4fa18f729cd2be0a", + "sha256:f0d320e70b6b2300ff6029e234e79fe44e9dbbfc7b98597ba28e054bd6606a57", + "sha256:f252dfb4852a527987a9156cbcae3022a30f86c9d26f4f17b8c967d7580d65d2", + "sha256:f5f4424cb87a20b016bfdc157ff48757b89d2cc426256961643d443c6c277007", + "sha256:f8eae66a1304de7368932b42d801c67969fd090ddb1a7a24f27b435ed4bed68f", + "sha256:fdb82eb60d31b0c033a8e8ee9f3fc7dfbaa042211131c29da29aea8531b4f18f" ], "markers": "python_version >= '3.8'", - "version": "==0.13.1" + "version": "==0.13.2" }, "rsa": { "hashes": [ @@ -2955,91 +4217,163 @@ "markers": "python_version >= '3.6' and python_version < '4'", "version": "==4.9" }, + "ruamel-yaml": { + "hashes": [ + "sha256:61917e3a35a569c1133a8f772e1226961bf5a1198bea7e23f06a0841dea1ab0e", + "sha256:a013ac02f99a69cdd6277d9664689eb1acba07069f912823177c5eced21a6ada" + ], + "markers": "python_version >= '3.7'", + "version": "==0.18.5" + }, + "ruamel.yaml.clib": { + "hashes": [ + "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d", + "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001", + "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462", + "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9", + "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe", + "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b", + "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b", + "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615", + "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62", + "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15", + "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b", + "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1", + "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9", + "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675", + "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899", + "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7", + "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7", + "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312", + "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa", + "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91", + "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b", + "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6", + "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3", + "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334", + "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5", + "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3", + "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe", + "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c", + "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed", + "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337", + "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880", + "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f", + "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d", + "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248", + "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d", + "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf", + "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512", + "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069", + "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb", + "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942", + "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d", + "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31", + "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92", + "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5", + "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28", + "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d", + "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1", + "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2", + "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875", + "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412" + ], + "markers": "python_version < '3.13' and platform_python_implementation == 'CPython'", + "version": "==0.2.8" + }, "ruff": { "hashes": [ - "sha256:03910e81df0d8db0e30050725a5802441c2022ea3ae4fe0609b76081731accbc", - "sha256:05991ee20d4ac4bb78385360c684e4b417edd971030ab12a4fbd075ff535050e", - "sha256:137852105586dcbf80c1717facb6781555c4e99f520c9c827bd414fac67ddfb6", - "sha256:1610e14750826dfc207ccbcdd7331b6bd285607d4181df9c1c6ae26646d6848a", - "sha256:1b09f29b16c6ead5ea6b097ef2764b42372aebe363722f1605ecbcd2b9207184", - "sha256:1cf5f701062e294f2167e66d11b092bba7af6a057668ed618a9253e1e90cfd76", - "sha256:3a0cd909d25f227ac5c36d4e7e681577275fb74ba3b11d288aff7ec47e3ae745", - "sha256:4558b3e178145491e9bc3b2ee3c4b42f19d19384eaa5c59d10acf6e8f8b57e33", - "sha256:491262006e92f825b145cd1e52948073c56560243b55fb3b4ecb142f6f0e9543", - "sha256:5c549ed437680b6105a1299d2cd30e4964211606eeb48a0ff7a93ef70b902248", - "sha256:683aa5bdda5a48cb8266fcde8eea2a6af4e5700a392c56ea5fb5f0d4bfdc0240", - "sha256:87455a0c1f739b3c069e2f4c43b66479a54dea0276dd5d4d67b091265f6fd1dc", - "sha256:88b8cdf6abf98130991cbc9f6438f35f6e8d41a02622cc5ee130a02a0ed28703", - "sha256:bd98138a98d48a1c36c394fd6b84cd943ac92a08278aa8ac8c0fdefcf7138f35", - "sha256:e8fd1c62a47aa88a02707b5dd20c5ff20d035d634aa74826b42a1da77861b5ff", - "sha256:ea284789861b8b5ca9d5443591a92a397ac183d4351882ab52f6296b4fdd5462", - "sha256:fd89b45d374935829134a082617954120d7a1470a9f0ec0e7f3ead983edc48cc" + "sha256:0683b7bfbb95e6df3c7c04fe9d78f631f8e8ba4868dfc932d43d690698057e2e", + "sha256:1ea109bdb23c2a4413f397ebd8ac32cb498bee234d4191ae1a310af760e5d287", + "sha256:276a89bcb149b3d8c1b11d91aa81898fe698900ed553a08129b38d9d6570e717", + "sha256:290ecab680dce94affebefe0bbca2322a6277e83d4f29234627e0f8f6b4fa9ce", + "sha256:416dfd0bd45d1a2baa3b1b07b1b9758e7d993c256d3e51dc6e03a5e7901c7d80", + "sha256:45b38c3f8788a65e6a2cab02e0f7adfa88872696839d9882c13b7e2f35d64c5f", + "sha256:4af95fd1d3b001fc41325064336db36e3d27d2004cdb6d21fd617d45a172dd96", + "sha256:69a4bed13bc1d5dabf3902522b5a2aadfebe28226c6269694283c3b0cecb45fd", + "sha256:6b05e3b123f93bb4146a761b7a7d57af8cb7384ccb2502d29d736eaade0db519", + "sha256:6c64cb67b2025b1ac6d58e5ffca8f7b3f7fd921f35e78198411237e4f0db8e73", + "sha256:7f80496854fdc65b6659c271d2c26e90d4d401e6a4a31908e7e334fab4645aac", + "sha256:8b0c2de9dd9daf5e07624c24add25c3a490dbf74b0e9bca4145c632457b3b42a", + "sha256:90c958fe950735041f1c80d21b42184f1072cc3975d05e736e8d66fc377119ea", + "sha256:9dcc6bb2f4df59cb5b4b40ff14be7d57012179d69c6565c1da0d1f013d29951b", + "sha256:de02ca331f2143195a712983a57137c5ec0f10acc4aa81f7c1f86519e52b92a1", + "sha256:df2bb4bb6bbe921f6b4f5b6fdd8d8468c940731cb9406f274ae8c5ed7a78c478", + "sha256:dffd699d07abf54833e5f6cc50b85a6ff043715da8788c4a79bcd4ab4734d306" ], - "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==0.1.6" + "version": "==0.1.7" }, "s3transfer": { "hashes": [ - "sha256:d1c52af7bceca1650d0f27728b29bb4925184aead7b55bccacf893b79a108604", - "sha256:e6cafd5643fc7b44fddfba1e5b521005675b0e07533ddad958a3554bc87d7330" + "sha256:368ac6876a9e9ed91f6bc86581e319be08188dc60d50e0d56308ed5765446283", + "sha256:c9e56cbe88b28d8e197cf841f1f0c130f246595e77ae5b5a05b69fe7cb83de76" ], "markers": "python_version >= '3.7'", - "version": "==0.8.1" + "version": "==0.8.2" }, "scikit-learn": { "hashes": [ - "sha256:065e9673e24e0dc5113e2dd2b4ca30c9d8aa2fa90f4c0597241c93b63130d233", - "sha256:2dd3ffd3950e3d6c0c0ef9033a9b9b32d910c61bd06cb8206303fb4514b88a49", - "sha256:2e2642baa0ad1e8f8188917423dd73994bf25429f8893ddbe115be3ca3183584", - "sha256:44b47a305190c28dd8dd73fc9445f802b6ea716669cfc22ab1eb97b335d238b1", - "sha256:6477eed40dbce190f9f9e9d0d37e020815825b300121307942ec2110302b66a3", - "sha256:6fe83b676f407f00afa388dd1fdd49e5c6612e551ed84f3b1b182858f09e987d", - "sha256:7d5312d9674bed14f73773d2acf15a3272639b981e60b72c9b190a0cffed5bad", - "sha256:7f69313884e8eb311460cc2f28676d5e400bd929841a2c8eb8742ae78ebf7c20", - "sha256:8156db41e1c39c69aa2d8599ab7577af53e9e5e7a57b0504e116cc73c39138dd", - "sha256:8429aea30ec24e7a8c7ed8a3fa6213adf3814a6efbea09e16e0a0c71e1a1a3d7", - "sha256:8b0670d4224a3c2d596fd572fb4fa673b2a0ccfb07152688ebd2ea0b8c61025c", - "sha256:953236889928d104c2ef14027539f5f2609a47ebf716b8cbe4437e85dce42744", - "sha256:99cc01184e347de485bf253d19fcb3b1a3fb0ee4cea5ee3c43ec0cc429b6d29f", - "sha256:9c710ff9f9936ba8a3b74a455ccf0dcf59b230caa1e9ba0223773c490cab1e51", - "sha256:ad66c3848c0a1ec13464b2a95d0a484fd5b02ce74268eaa7e0c697b904f31d6c", - "sha256:bf036ea7ef66115e0d49655f16febfa547886deba20149555a41d28f56fd6d3c", - "sha256:dfeaf8be72117eb61a164ea6fc8afb6dfe08c6f90365bde2dc16456e4bc8e45f", - "sha256:e6e574db9914afcb4e11ade84fab084536a895ca60aadea3041e85b8ac963edb", - "sha256:ea061bf0283bf9a9f36ea3c5d3231ba2176221bbd430abd2603b1c3b2ed85c89", - "sha256:fe0aa1a7029ed3e1dcbf4a5bc675aa3b1bc468d9012ecf6c6f081251ca47f590", - "sha256:fe175ee1dab589d2e1033657c5b6bec92a8a3b69103e3dd361b58014729975c3" - ], - "markers": "python_version >= '3.8'", - "version": "==1.2.2" + "sha256:0402638c9a7c219ee52c94cbebc8fcb5eb9fe9c773717965c1f4185588ad3107", + "sha256:0ee107923a623b9f517754ea2f69ea3b62fc898a3641766cb7deb2f2ce450161", + "sha256:1215e5e58e9880b554b01187b8c9390bf4dc4692eedeaf542d3273f4785e342c", + "sha256:15e1e94cc23d04d39da797ee34236ce2375ddea158b10bee3c343647d615581d", + "sha256:18424efee518a1cde7b0b53a422cde2f6625197de6af36da0b57ec502f126157", + "sha256:1d08ada33e955c54355d909b9c06a4789a729977f165b8bae6f225ff0a60ec4a", + "sha256:3271552a5eb16f208a6f7f617b8cc6d1f137b52c8a1ef8edf547db0259b2c9fb", + "sha256:35a22e8015048c628ad099da9df5ab3004cdbf81edc75b396fd0cff8699ac58c", + "sha256:535805c2a01ccb40ca4ab7d081d771aea67e535153e35a1fd99418fcedd1648a", + "sha256:5b2de18d86f630d68fe1f87af690d451388bb186480afc719e5f770590c2ef6c", + "sha256:61a6efd384258789aa89415a410dcdb39a50e19d3d8410bd29be365bcdd512d5", + "sha256:64381066f8aa63c2710e6b56edc9f0894cc7bf59bd71b8ce5613a4559b6145e0", + "sha256:67f37d708f042a9b8d59551cf94d30431e01374e00dc2645fa186059c6c5d78b", + "sha256:6c43290337f7a4b969d207e620658372ba3c1ffb611f8bc2b6f031dc5c6d1d03", + "sha256:6fb6bc98f234fda43163ddbe36df8bcde1d13ee176c6dc9b92bb7d3fc842eb66", + "sha256:763f0ae4b79b0ff9cca0bf3716bcc9915bdacff3cebea15ec79652d1cc4fa5c9", + "sha256:785a2213086b7b1abf037aeadbbd6d67159feb3e30263434139c98425e3dcfcf", + "sha256:8db94cd8a2e038b37a80a04df8783e09caac77cbe052146432e67800e430c028", + "sha256:a19f90f95ba93c1a7f7924906d0576a84da7f3b2282ac3bfb7a08a32801add93", + "sha256:a2f54c76accc15a34bfb9066e6c7a56c1e7235dda5762b990792330b52ccfb05", + "sha256:b8692e395a03a60cd927125eef3a8e3424d86dde9b2370d544f0ea35f78a8073", + "sha256:cb06f8dce3f5ddc5dee1715a9b9f19f20d295bed8e3cd4fa51e1d050347de525", + "sha256:dc9002fc200bed597d5d34e90c752b74df516d592db162f756cc52836b38fe0e", + "sha256:e326c0eb5cf4d6ba40f93776a20e9a7a69524c4db0757e7ce24ba222471ee8a1", + "sha256:ed932ea780517b00dae7431e031faae6b49b20eb6950918eb83bd043237950e0", + "sha256:fc4144a5004a676d5022b798d9e573b05139e77f271253a4703eed295bde0433" + ], + "markers": "python_version >= '3.8'", + "version": "==1.3.2" }, "scipy": { "hashes": [ - "sha256:049a8bbf0ad95277ffba9b3b7d23e5369cc39e66406d60422c8cfef40ccc8415", - "sha256:07c3457ce0b3ad5124f98a86533106b643dd811dd61b548e78cf4c8786652f6f", - "sha256:0f1564ea217e82c1bbe75ddf7285ba0709ecd503f048cb1236ae9995f64217bd", - "sha256:1553b5dcddd64ba9a0d95355e63fe6c3fc303a8fd77c7bc91e77d61363f7433f", - "sha256:15a35c4242ec5f292c3dd364a7c71a61be87a3d4ddcc693372813c0b73c9af1d", - "sha256:1b4735d6c28aad3cdcf52117e0e91d6b39acd4272f3f5cd9907c24ee931ad601", - "sha256:2cf9dfb80a7b4589ba4c40ce7588986d6d5cebc5457cad2c2880f6bc2d42f3a5", - "sha256:39becb03541f9e58243f4197584286e339029e8908c46f7221abeea4b749fa88", - "sha256:43b8e0bcb877faf0abfb613d51026cd5cc78918e9530e375727bf0625c82788f", - "sha256:4b3f429188c66603a1a5c549fb414e4d3bdc2a24792e061ffbd607d3d75fd84e", - "sha256:4c0ff64b06b10e35215abce517252b375e580a6125fd5fdf6421b98efbefb2d2", - "sha256:51af417a000d2dbe1ec6c372dfe688e041a7084da4fdd350aeb139bd3fb55353", - "sha256:5678f88c68ea866ed9ebe3a989091088553ba12c6090244fdae3e467b1139c35", - "sha256:79c8e5a6c6ffaf3a2262ef1be1e108a035cf4f05c14df56057b64acc5bebffb6", - "sha256:7ff7f37b1bf4417baca958d254e8e2875d0cc23aaadbe65b3d5b3077b0eb23ea", - "sha256:aaea0a6be54462ec027de54fca511540980d1e9eea68b2d5c1dbfe084797be35", - "sha256:bce5869c8d68cf383ce240e44c1d9ae7c06078a9396df68ce88a1230f93a30c1", - "sha256:cd9f1027ff30d90618914a64ca9b1a77a431159df0e2a195d8a9e8a04c78abf9", - "sha256:d925fa1c81b772882aa55bcc10bf88324dadb66ff85d548c71515f6689c6dac5", - "sha256:e7354fd7527a4b0377ce55f286805b34e8c54b91be865bac273f527e1b839019", - "sha256:fae8a7b898c42dffe3f7361c40d5952b6bf32d10c4569098d276b4c547905ee1" - ], - "markers": "python_version < '3.12' and python_version >= '3.8'", - "version": "==1.10.1" + "sha256:00150c5eae7b610c32589dda259eacc7c4f1665aedf25d921907f4d08a951b1c", + "sha256:028eccd22e654b3ea01ee63705681ee79933652b2d8f873e7949898dda6d11b6", + "sha256:1b7c3dca977f30a739e0409fb001056484661cb2541a01aba0bb0029f7b68db8", + "sha256:2c6ff6ef9cc27f9b3db93a6f8b38f97387e6e0591600369a297a50a8e96e835d", + "sha256:36750b7733d960d7994888f0d148d31ea3017ac15eef664194b4ef68d36a4a97", + "sha256:530f9ad26440e85766509dbf78edcfe13ffd0ab7fec2560ee5c36ff74d6269ff", + "sha256:5e347b14fe01003d3b78e196e84bd3f48ffe4c8a7b8a1afbcb8f5505cb710993", + "sha256:6550466fbeec7453d7465e74d4f4b19f905642c89a7525571ee91dd7adabb5a3", + "sha256:6df1468153a31cf55ed5ed39647279beb9cfb5d3f84369453b49e4b8502394fd", + "sha256:6e619aba2df228a9b34718efb023966da781e89dd3d21637b27f2e54db0410d7", + "sha256:8fce70f39076a5aa62e92e69a7f62349f9574d8405c0a5de6ed3ef72de07f446", + "sha256:90a2b78e7f5733b9de748f589f09225013685f9b218275257f8a8168ededaeaa", + "sha256:91af76a68eeae0064887a48e25c4e616fa519fa0d38602eda7e0f97d65d57937", + "sha256:933baf588daa8dc9a92c20a0be32f56d43faf3d1a60ab11b3f08c356430f6e56", + "sha256:acf8ed278cc03f5aff035e69cb511741e0418681d25fbbb86ca65429c4f4d9cd", + "sha256:ad669df80528aeca5f557712102538f4f37e503f0c5b9541655016dd0932ca79", + "sha256:b030c6674b9230d37c5c60ab456e2cf12f6784596d15ce8da9365e70896effc4", + "sha256:b9999c008ccf00e8fbcce1236f85ade5c569d13144f77a1946bef8863e8f6eb4", + "sha256:bc9a714581f561af0848e6b69947fda0614915f072dfd14142ed1bfe1b806710", + "sha256:ce7fff2e23ab2cc81ff452a9444c215c28e6305f396b2ba88343a567feec9660", + "sha256:cf00bd2b1b0211888d4dc75656c0412213a8b25e80d73898083f402b50f47e41", + "sha256:d10e45a6c50211fe256da61a11c34927c68f277e03138777bdebedd933712fea", + "sha256:ee410e6de8f88fd5cf6eadd73c135020bfbbbdfcd0f6162c36a7638a1ea8cc65", + "sha256:f313b39a7e94f296025e3cffc2c567618174c0b1dde173960cf23808f9fae4be", + "sha256:f3cd9e7b3c2c1ec26364856f9fbe78695fe631150f94cd1c22228456404cf1ec" + ], + "markers": "python_version >= '3.9'", + "version": "==1.11.4" }, "scs": { "hashes": [ @@ -3158,9 +4492,17 @@ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, + "smmap": { + "hashes": [ + "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62", + "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da" + ], + "markers": "python_version >= '3.7'", + "version": "==5.0.1" + }, "sniffio": { "hashes": [ "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101", @@ -3169,6 +4511,20 @@ "markers": "python_version >= '3.7'", "version": "==1.3.0" }, + "snowballstemmer": { + "hashes": [ + "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", + "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a" + ], + "version": "==2.2.0" + }, + "sortedcontainers": { + "hashes": [ + "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", + "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0" + ], + "version": "==2.4.0" + }, "soupsieve": { "hashes": [ "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690", @@ -3177,37 +4533,157 @@ "markers": "python_version >= '3.8'", "version": "==2.5" }, + "sphinx": { + "hashes": [ + "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560", + "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5" + ], + "markers": "python_version >= '3.9'", + "version": "==7.2.6" + }, + "sphinx-autoapi": { + "hashes": [ + "sha256:09ebd674a32b44467222b0fb8a917b97c89523f20dbf05b52cb8a3f0e15714de", + "sha256:ea207793cba1feff7b2ded0e29364f2995a4d157303a98603cee0ce94cea2688" + ], + "markers": "python_version >= '3.8'", + "version": "==3.0.0" + }, + "sphinx-basic-ng": { + "hashes": [ + "sha256:9ec55a47c90c8c002b5960c57492ec3021f5193cb26cebc2dc4ea226848651c9", + "sha256:eb09aedbabfb650607e9b4b68c9d240b90b1e1be221d6ad71d61c52e29f7932b" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.0b2" + }, + "sphinx-issues": { + "hashes": [ + "sha256:8b25dc0301159375468f563b3699af7a63720fd84caf81c1442036fcd418b20c", + "sha256:b7c1dc1f4808563c454d11c1112796f8c176cdecfee95f0fd2302ef98e21e3d6" + ], + "markers": "python_version >= '3.6'", + "version": "==3.0.1" + }, + "sphinx-reredirects": { + "hashes": [ + "sha256:02c53437c467cf9ed89863eff3addedc01d129624b2f03ab6302518fb77a2c89", + "sha256:56e222d285f76c944fd370f36ad3a1a66103a88b552e97d3d24a622bb9465de8" + ], + "markers": "python_version >= '3.5'", + "version": "==0.1.3" + }, + "sphinxcontrib-applehelp": { + "hashes": [ + "sha256:094c4d56209d1734e7d252f6e0b3ccc090bd52ee56807a5d9315b19c122ab15d", + "sha256:39fdc8d762d33b01a7d8f026a3b7d71563ea3b72787d5f00ad8465bd9d6dfbfa" + ], + "markers": "python_version >= '3.9'", + "version": "==1.0.7" + }, + "sphinxcontrib-bibtex": { + "hashes": [ + "sha256:046b49f070ae5276af34c1b8ddb9bc9562ef6de2f7a52d37a91cb8e53f54b863", + "sha256:094c772098fe6b030cda8618c45722b2957cad0c04f328ba2b154aa08dfe720a" + ], + "markers": "python_version >= '3.7'", + "version": "==2.6.1" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:63b41e0d38207ca40ebbeabcf4d8e51f76c03e78cd61abe118cf4435c73d4212", + "sha256:fe8009aed765188f08fcaadbb3ea0d90ce8ae2d76710b7e29ea7d047177dae2f" + ], + "markers": "python_version >= '3.9'", + "version": "==1.0.5" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:6c26a118a05b76000738429b724a0568dbde5b72391a688577da08f11891092a", + "sha256:8001661c077a73c29beaf4a79968d0726103c5605e27db92b9ebed8bab1359e9" + ], + "markers": "python_version >= '3.9'", + "version": "==2.0.4" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.1" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:62b9d1a186ab7f5ee3356d906f648cacb7a6bdb94d201ee7adf26db55092982d", + "sha256:bf76886ee7470b934e363da7a954ea2825650013d367728588732c7350f49ea4" + ], + "markers": "python_version >= '3.9'", + "version": "==1.0.6" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54", + "sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1" + ], + "markers": "python_version >= '3.9'", + "version": "==1.1.9" + }, "sqlalchemy": { "hashes": [ - "sha256:0b7dbe6369677a2bea68fe9812c6e4bbca06ebfa4b5cde257b2b0bf208709131", - "sha256:128a948bd40780667114b0297e2cc6d657b71effa942e0a368d8cc24293febb3", - "sha256:14b0cacdc8a4759a1e1bd47dc3ee3f5db997129eb091330beda1da5a0e9e5bd7", - "sha256:1fb9cb60e0f33040e4f4681e6658a7eb03b5cb4643284172f91410d8c493dace", - "sha256:273505fcad22e58cc67329cefab2e436006fc68e3c5423056ee0513e6523268a", - "sha256:2e70e0673d7d12fa6cd363453a0d22dac0d9978500aa6b46aa96e22690a55eab", - "sha256:34e1c5d9cd3e6bf3d1ce56971c62a40c06bfc02861728f368dcfec8aeedb2814", - "sha256:3b97ddf509fc21e10b09403b5219b06c5b558b27fc2453150274fa4e70707dbf", - "sha256:3f6997da81114daef9203d30aabfa6b218a577fc2bd797c795c9c88c9eb78d49", - "sha256:82dd4131d88395df7c318eeeef367ec768c2a6fe5bd69423f7720c4edb79473c", - "sha256:85292ff52ddf85a39367057c3d7968a12ee1fb84565331a36a8fead346f08796", - "sha256:8a7a66297e46f85a04d68981917c75723e377d2e0599d15fbe7a56abed5e2d75", - "sha256:8b881ac07d15fb3e4f68c5a67aa5cdaf9eb8f09eb5545aaf4b0a5f5f4659be18", - "sha256:a3257a6e09626d32b28a0c5b4f1a97bced585e319cfa90b417f9ab0f6145c33c", - "sha256:a9bddb60566dc45c57fd0a5e14dd2d9e5f106d2241e0a2dc0c1da144f9444516", - "sha256:bdb77e1789e7596b77fd48d99ec1d2108c3349abd20227eea0d48d3f8cf398d9", - "sha256:c1db0221cb26d66294f4ca18c533e427211673ab86c1fbaca8d6d9ff78654293", - "sha256:c4cb501d585aa74a0f86d0ea6263b9c5e1d1463f8f9071392477fd401bd3c7cc", - "sha256:d00665725063692c42badfd521d0c4392e83c6c826795d38eb88fb108e5660e5", - "sha256:d0fed0f791d78e7767c2db28d34068649dfeea027b83ed18c45a423f741425cb", - "sha256:d69738d582e3a24125f0c246ed8d712b03bd21e148268421e4a4d09c34f521a5", - "sha256:db4db3c08ffbb18582f856545f058a7a5e4ab6f17f75795ca90b3c38ee0a8ba4", - "sha256:f1fcee5a2c859eecb4ed179edac5ffbc7c84ab09a5420219078ccc6edda45436", - "sha256:f2d526aeea1bd6a442abc7c9b4b00386fd70253b80d54a0930c0a216230a35be", - "sha256:fbaf6643a604aa17e7a7afd74f665f9db882df5c297bdd86c38368f2c471f37d" + "sha256:0666031df46b9badba9bed00092a1ffa3aa063a5e68fa244acd9f08070e936d3", + "sha256:0a8c6aa506893e25a04233bc721c6b6cf844bafd7250535abb56cb6cc1368884", + "sha256:0e680527245895aba86afbd5bef6c316831c02aa988d1aad83c47ffe92655e74", + "sha256:14aebfe28b99f24f8a4c1346c48bc3d63705b1f919a24c27471136d2f219f02d", + "sha256:1e018aba8363adb0599e745af245306cb8c46b9ad0a6fc0a86745b6ff7d940fc", + "sha256:227135ef1e48165f37590b8bfc44ed7ff4c074bf04dc8d6f8e7f1c14a94aa6ca", + "sha256:31952bbc527d633b9479f5f81e8b9dfada00b91d6baba021a869095f1a97006d", + "sha256:3e983fa42164577d073778d06d2cc5d020322425a509a08119bdcee70ad856bf", + "sha256:42d0b0290a8fb0165ea2c2781ae66e95cca6e27a2fbe1016ff8db3112ac1e846", + "sha256:42ede90148b73fe4ab4a089f3126b2cfae8cfefc955c8174d697bb46210c8306", + "sha256:4895a63e2c271ffc7a81ea424b94060f7b3b03b4ea0cd58ab5bb676ed02f4221", + "sha256:4af79c06825e2836de21439cb2a6ce22b2ca129bad74f359bddd173f39582bf5", + "sha256:5f94aeb99f43729960638e7468d4688f6efccb837a858b34574e01143cf11f89", + "sha256:616fe7bcff0a05098f64b4478b78ec2dfa03225c23734d83d6c169eb41a93e55", + "sha256:62d9e964870ea5ade4bc870ac4004c456efe75fb50404c03c5fd61f8bc669a72", + "sha256:638c2c0b6b4661a4fd264f6fb804eccd392745c5887f9317feb64bb7cb03b3ea", + "sha256:63bfc3acc970776036f6d1d0e65faa7473be9f3135d37a463c5eba5efcdb24c8", + "sha256:6463aa765cf02b9247e38b35853923edbf2f6fd1963df88706bc1d02410a5577", + "sha256:64ac935a90bc479fee77f9463f298943b0e60005fe5de2aa654d9cdef46c54df", + "sha256:683ef58ca8eea4747737a1c35c11372ffeb84578d3aab8f3e10b1d13d66f2bc4", + "sha256:75eefe09e98043cff2fb8af9796e20747ae870c903dc61d41b0c2e55128f958d", + "sha256:787af80107fb691934a01889ca8f82a44adedbf5ef3d6ad7d0f0b9ac557e0c34", + "sha256:7c424983ab447dab126c39d3ce3be5bee95700783204a72549c3dceffe0fc8f4", + "sha256:7e0dc9031baa46ad0dd5a269cb7a92a73284d1309228be1d5935dac8fb3cae24", + "sha256:87a3d6b53c39cd173990de2f5f4b83431d534a74f0e2f88bd16eabb5667e65c6", + "sha256:89a01238fcb9a8af118eaad3ffcc5dedaacbd429dc6fdc43fe430d3a941ff965", + "sha256:9585b646ffb048c0250acc7dad92536591ffe35dba624bb8fd9b471e25212a35", + "sha256:964971b52daab357d2c0875825e36584d58f536e920f2968df8d581054eada4b", + "sha256:967c0b71156f793e6662dd839da54f884631755275ed71f1539c95bbada9aaab", + "sha256:9ca922f305d67605668e93991aaf2c12239c78207bca3b891cd51a4515c72e22", + "sha256:a86cb7063e2c9fb8e774f77fbf8475516d270a3e989da55fa05d08089d77f8c4", + "sha256:aeb397de65a0a62f14c257f36a726945a7f7bb60253462e8602d9b97b5cbe204", + "sha256:b41f5d65b54cdf4934ecede2f41b9c60c9f785620416e8e6c48349ab18643855", + "sha256:bd45a5b6c68357578263d74daab6ff9439517f87da63442d244f9f23df56138d", + "sha256:c14eba45983d2f48f7546bb32b47937ee2cafae353646295f0e99f35b14286ab", + "sha256:c1bda93cbbe4aa2aa0aa8655c5aeda505cd219ff3e8da91d1d329e143e4aff69", + "sha256:c4722f3bc3c1c2fcc3702dbe0016ba31148dd6efcd2a2fd33c1b4897c6a19693", + "sha256:c80c38bd2ea35b97cbf7c21aeb129dcbebbf344ee01a7141016ab7b851464f8e", + "sha256:cabafc7837b6cec61c0e1e5c6d14ef250b675fa9c3060ed8a7e38653bd732ff8", + "sha256:cc1d21576f958c42d9aec68eba5c1a7d715e5fc07825a629015fe8e3b0657fb0", + "sha256:d0f7fb0c7527c41fa6fcae2be537ac137f636a41b4c5a4c58914541e2f436b45", + "sha256:d4041ad05b35f1f4da481f6b811b4af2f29e83af253bf37c3c4582b2c68934ab", + "sha256:d5578e6863eeb998980c212a39106ea139bdc0b3f73291b96e27c929c90cd8e1", + "sha256:e3b5036aa326dc2df50cba3c958e29b291a80f604b1afa4c8ce73e78e1c9f01d", + "sha256:e599a51acf3cc4d31d1a0cf248d8f8d863b6386d2b6782c5074427ebb7803bda", + "sha256:f3420d00d2cb42432c1d0e44540ae83185ccbbc67a6054dcc8ab5387add6620b", + "sha256:f48ed89dd11c3c586f45e9eec1e437b355b3b6f6884ea4a4c3111a3358fd0c18", + "sha256:f508ba8f89e0a5ecdfd3761f82dda2a3d7b678a626967608f4273e0dba8f07ac", + "sha256:fd54601ef9cc455a0c61e5245f690c8a3ad67ddb03d3b91c361d076def0b4c60" ], "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.4.50" + "markers": "python_version >= '3.7'", + "version": "==2.0.23" }, "stack-data": { "hashes": [ @@ -3252,6 +4728,14 @@ "markers": "python_version >= '3.8'", "version": "==0.14.0" }, + "stevedore": { + "hashes": [ + "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d", + "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c" + ], + "markers": "python_version >= '3.8'", + "version": "==5.1.0" + }, "stringcase": { "hashes": [ "sha256:48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008" @@ -3313,11 +4797,11 @@ }, "timezonefinder": { "hashes": [ - "sha256:024d5422016fc807ca253cba9395bf5176d9efcc5f65d526ef125ea36e808775", - "sha256:a7df1aa559789b42bc9a4187ded03668b43221b8f9019d5e66156512b891902a" + "sha256:06aa5926ed31687ea9eb00ab53203631f09a78f307285b4929da4ac4e2889240", + "sha256:d41fd2650bb4221fae5a61f9c2767158f9727c4aaca95e24da86394feb704220" ], "markers": "python_version >= '3.8' and python_version < '4'", - "version": "==6.1.10" + "version": "==6.2.0" }, "tinycss2": { "hashes": [ @@ -3332,9 +4816,17 @@ "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" ], - "markers": "python_version < '3.11'", + "markers": "python_version >= '3.7'", "version": "==2.0.1" }, + "tomlkit": { + "hashes": [ + "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4", + "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba" + ], + "markers": "python_version >= '3.7'", + "version": "==0.12.3" + }, "toolz": { "hashes": [ "sha256:2059bd4148deb1884bb0eb770a3cde70e7f954cfbbdc2285f1f2de01fd21eb6f", @@ -3343,22 +4835,37 @@ "markers": "python_version >= '3.5'", "version": "==0.12.0" }, + "toposort": { + "hashes": [ + "sha256:bfbb479c53d0a696ea7402601f4e693c97b0367837c8898bc6471adfca37a6bd", + "sha256:cbdbc0d0bee4d2695ab2ceec97fe0679e9c10eab4b2a87a9372b929e70563a87" + ], + "version": "==1.10" + }, "tornado": { "hashes": [ - "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f", - "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5", - "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d", - "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3", - "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2", - "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a", - "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16", - "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a", - "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17", - "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0", - "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe" + "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0", + "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63", + "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263", + "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052", + "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f", + "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee", + "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78", + "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579", + "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212", + "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e", + "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2" ], "markers": "python_version >= '3.8'", - "version": "==6.3.3" + "version": "==6.4" + }, + "tqdm": { + "hashes": [ + "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386", + "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7" + ], + "markers": "python_version >= '3.7'", + "version": "==4.66.1" }, "traitlets": { "hashes": [ @@ -3368,6 +4875,14 @@ "markers": "python_version >= '3.8'", "version": "==5.14.0" }, + "typeguard": { + "hashes": [ + "sha256:8923e55f8873caec136c892c3bed1f676eae7be57cdb94819281b3d3bc9c0953", + "sha256:ea0a113bbc111bcffc90789ebb215625c963411f7096a7e9062d4e4630c155fd" + ], + "markers": "python_version >= '3.8'", + "version": "==4.1.5" + }, "typer": { "extras": [ "all" @@ -3394,12 +4909,35 @@ "markers": "python_version >= '3.8'", "version": "==4.8.0" }, + "typing-inspect": { + "hashes": [ + "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f", + "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78" + ], + "version": "==0.9.0" + }, + "tzdata": { + "hashes": [ + "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a", + "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda" + ], + "markers": "python_version >= '2'", + "version": "==2023.3" + }, "unicodecsv": { "hashes": [ "sha256:018c08037d48649a0412063ff4eda26eaa81eff1546dbffa51fa5293276ff7fc" ], "version": "==0.14.1" }, + "universal-pathlib": { + "hashes": [ + "sha256:82e5d86d16a27e0ea1adc7d88acbcba9d02d5a45488163174f96d9ac289db2e4", + "sha256:f99186cf950bde1262de9a590bb019613ef84f9fabd9f276e8b019722201943a" + ], + "markers": "python_version >= '3.8'", + "version": "==0.1.4" + }, "uri-template": { "hashes": [ "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", @@ -3409,11 +4947,19 @@ }, "urllib3": { "hashes": [ - "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84", - "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e" + "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07", + "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0" ], - "markers": "python_version >= '3.7'", - "version": "==2.0.7" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.26.18" + }, + "uvicorn": { + "hashes": [ + "sha256:09c8e5a79dc466bdf28dead50093957db184de356fcdc48697bad3bde4c2588e", + "sha256:7c84fea70c619d4a710153482c0d230929af7bcf76c7bfa6de151f0a3a80121e" + ], + "markers": "python_version >= '3.8'", + "version": "==0.24.0.post1" }, "validators": { "hashes": [ @@ -3423,6 +4969,47 @@ "markers": "python_version >= '3.8'", "version": "==0.22.0" }, + "virtualenv": { + "hashes": [ + "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3", + "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b" + ], + "markers": "python_version >= '3.7'", + "version": "==20.25.0" + }, + "watchdog": { + "hashes": [ + "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a", + "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100", + "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8", + "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc", + "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae", + "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41", + "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0", + "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f", + "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c", + "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9", + "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3", + "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709", + "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83", + "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759", + "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9", + "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3", + "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7", + "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f", + "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346", + "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674", + "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397", + "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96", + "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d", + "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a", + "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64", + "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44", + "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33" + ], + "markers": "python_version >= '3.7'", + "version": "==3.0.0" + }, "wcwidth": { "hashes": [ "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02", @@ -3446,11 +5033,95 @@ }, "websocket-client": { "hashes": [ - "sha256:084072e0a7f5f347ef2ac3d8698a5e0b4ffbfcab607628cadabc650fc9a83a24", - "sha256:b3324019b3c28572086c4a319f91d1dcd44e6e11cd340232978c684a7650d0df" + "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6", + "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588" ], "markers": "python_version >= '3.8'", - "version": "==1.6.4" + "version": "==1.7.0" + }, + "widgetsnbextension": { + "hashes": [ + "sha256:3c1f5e46dc1166dfd40a42d685e6a51396fd34ff878742a3e47c6f0cc4a2a385", + "sha256:91452ca8445beb805792f206e560c1769284267a30ceb1cec9f5bcc887d15175" + ], + "markers": "python_version >= '3.7'", + "version": "==4.0.9" + }, + "wrapt": { + "hashes": [ + "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc", + "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81", + "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09", + "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e", + "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca", + "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0", + "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb", + "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487", + "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40", + "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c", + "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060", + "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202", + "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41", + "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9", + "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b", + "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664", + "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d", + "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362", + "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00", + "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc", + "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1", + "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267", + "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956", + "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966", + "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1", + "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228", + "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72", + "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d", + "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292", + "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0", + "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0", + "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36", + "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c", + "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5", + "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f", + "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73", + "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b", + "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2", + "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593", + "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39", + "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389", + "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf", + "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf", + "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89", + "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c", + "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c", + "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f", + "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440", + "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465", + "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136", + "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b", + "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8", + "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3", + "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8", + "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6", + "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e", + "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f", + "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c", + "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e", + "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8", + "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2", + "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020", + "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35", + "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d", + "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3", + "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537", + "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809", + "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d", + "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a", + "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4" + ], + "markers": "python_version >= '3.6'", + "version": "==1.16.0" }, "xlrd": { "hashes": [ @@ -3462,108 +5133,180 @@ }, "xlsxwriter": { "hashes": [ - "sha256:5eaaf3c6f791cba1dd1c3065147c35982180f693436093aabe5b7d6c16148e95", - "sha256:7216d39a2075afac7a28cad81f6ac31b0b16d8976bf1b775577d157346f891dd" + "sha256:b61c1a0c786f82644936c0936ec96ee96cd3afb9440094232f7faef9b38689f0", + "sha256:de810bf328c6a4550f4ffd6b0b34972aeb7ffcf40f3d285a0413734f9b63a929" ], "markers": "python_version >= '3.6'", - "version": "==3.0.9" + "version": "==3.1.9" }, "yarl": { "hashes": [ - "sha256:09c19e5f4404574fcfb736efecf75844ffe8610606f3fccc35a1515b8b6712c4", - "sha256:0ab5baaea8450f4a3e241ef17e3d129b2143e38a685036b075976b9c415ea3eb", - "sha256:0d155a092bf0ebf4a9f6f3b7a650dc5d9a5bbb585ef83a52ed36ba46f55cc39d", - "sha256:126638ab961633f0940a06e1c9d59919003ef212a15869708dcb7305f91a6732", - "sha256:1a0a4f3aaa18580038cfa52a7183c8ffbbe7d727fe581300817efc1e96d1b0e9", - "sha256:1d93461e2cf76c4796355494f15ffcb50a3c198cc2d601ad8d6a96219a10c363", - "sha256:26a1a8443091c7fbc17b84a0d9f38de34b8423b459fb853e6c8cdfab0eacf613", - "sha256:271d63396460b6607b588555ea27a1a02b717ca2e3f2cf53bdde4013d7790929", - "sha256:28a108cb92ce6cf867690a962372996ca332d8cda0210c5ad487fe996e76b8bb", - "sha256:29beac86f33d6c7ab1d79bd0213aa7aed2d2f555386856bb3056d5fdd9dab279", - "sha256:2c757f64afe53a422e45e3e399e1e3cf82b7a2f244796ce80d8ca53e16a49b9f", - "sha256:2dad8166d41ebd1f76ce107cf6a31e39801aee3844a54a90af23278b072f1ccf", - "sha256:2dc72e891672343b99db6d497024bf8b985537ad6c393359dc5227ef653b2f17", - "sha256:2f3c8822bc8fb4a347a192dd6a28a25d7f0ea3262e826d7d4ef9cc99cd06d07e", - "sha256:32435d134414e01d937cd9d6cc56e8413a8d4741dea36af5840c7750f04d16ab", - "sha256:3cfa4dbe17b2e6fca1414e9c3bcc216f6930cb18ea7646e7d0d52792ac196808", - "sha256:3d5434b34100b504aabae75f0622ebb85defffe7b64ad8f52b8b30ec6ef6e4b9", - "sha256:4003f380dac50328c85e85416aca6985536812c082387255c35292cb4b41707e", - "sha256:44e91a669c43f03964f672c5a234ae0d7a4d49c9b85d1baa93dec28afa28ffbd", - "sha256:4a14907b597ec55740f63e52d7fee0e9ee09d5b9d57a4f399a7423268e457b57", - "sha256:4ce77d289f8d40905c054b63f29851ecbfd026ef4ba5c371a158cfe6f623663e", - "sha256:4d6d74a97e898c1c2df80339aa423234ad9ea2052f66366cef1e80448798c13d", - "sha256:51382c72dd5377861b573bd55dcf680df54cea84147c8648b15ac507fbef984d", - "sha256:525cd69eff44833b01f8ef39aa33a9cc53a99ff7f9d76a6ef6a9fb758f54d0ff", - "sha256:53ec65f7eee8655bebb1f6f1607760d123c3c115a324b443df4f916383482a67", - "sha256:5f74b015c99a5eac5ae589de27a1201418a5d9d460e89ccb3366015c6153e60a", - "sha256:6280353940f7e5e2efaaabd686193e61351e966cc02f401761c4d87f48c89ea4", - "sha256:632c7aeb99df718765adf58eacb9acb9cbc555e075da849c1378ef4d18bf536a", - "sha256:6465d36381af057d0fab4e0f24ef0e80ba61f03fe43e6eeccbe0056e74aadc70", - "sha256:66a6dbf6ca7d2db03cc61cafe1ee6be838ce0fbc97781881a22a58a7c5efef42", - "sha256:6d350388ba1129bc867c6af1cd17da2b197dff0d2801036d2d7d83c2d771a682", - "sha256:7217234b10c64b52cc39a8d82550342ae2e45be34f5bff02b890b8c452eb48d7", - "sha256:721ee3fc292f0d069a04016ef2c3a25595d48c5b8ddc6029be46f6158d129c92", - "sha256:72a57b41a0920b9a220125081c1e191b88a4cdec13bf9d0649e382a822705c65", - "sha256:73cc83f918b69110813a7d95024266072d987b903a623ecae673d1e71579d566", - "sha256:778df71c8d0c8c9f1b378624b26431ca80041660d7be7c3f724b2c7a6e65d0d6", - "sha256:79e1df60f7c2b148722fb6cafebffe1acd95fd8b5fd77795f56247edaf326752", - "sha256:7c86d0d0919952d05df880a1889a4f0aeb6868e98961c090e335671dea5c0361", - "sha256:7eaf13af79950142ab2bbb8362f8d8d935be9aaf8df1df89c86c3231e4ff238a", - "sha256:828235a2a169160ee73a2fcfb8a000709edf09d7511fccf203465c3d5acc59e4", - "sha256:8535e111a064f3bdd94c0ed443105934d6f005adad68dd13ce50a488a0ad1bf3", - "sha256:88d2c3cc4b2f46d1ba73d81c51ec0e486f59cc51165ea4f789677f91a303a9a7", - "sha256:8a2538806be846ea25e90c28786136932ec385c7ff3bc1148e45125984783dc6", - "sha256:8dab30b21bd6fb17c3f4684868c7e6a9e8468078db00f599fb1c14e324b10fca", - "sha256:8f18a7832ff85dfcd77871fe677b169b1bc60c021978c90c3bb14f727596e0ae", - "sha256:946db4511b2d815979d733ac6a961f47e20a29c297be0d55b6d4b77ee4b298f6", - "sha256:96758e56dceb8a70f8a5cff1e452daaeff07d1cc9f11e9b0c951330f0a2396a7", - "sha256:9a172c3d5447b7da1680a1a2d6ecdf6f87a319d21d52729f45ec938a7006d5d8", - "sha256:9a5211de242754b5e612557bca701f39f8b1a9408dff73c6db623f22d20f470e", - "sha256:9df9a0d4c5624790a0dea2e02e3b1b3c69aed14bcb8650e19606d9df3719e87d", - "sha256:aa4643635f26052401750bd54db911b6342eb1a9ac3e74f0f8b58a25d61dfe41", - "sha256:aed37db837ecb5962469fad448aaae0f0ee94ffce2062cf2eb9aed13328b5196", - "sha256:af52725c7c39b0ee655befbbab5b9a1b209e01bb39128dce0db226a10014aacc", - "sha256:b0b8c06afcf2bac5a50b37f64efbde978b7f9dc88842ce9729c020dc71fae4ce", - "sha256:b61e64b06c3640feab73fa4ff9cb64bd8182de52e5dc13038e01cfe674ebc321", - "sha256:b7831566595fe88ba17ea80e4b61c0eb599f84c85acaa14bf04dd90319a45b90", - "sha256:b8bc5b87a65a4e64bc83385c05145ea901b613d0d3a434d434b55511b6ab0067", - "sha256:b8d51817cf4b8d545963ec65ff06c1b92e5765aa98831678d0e2240b6e9fd281", - "sha256:b9f9cafaf031c34d95c1528c16b2fa07b710e6056b3c4e2e34e9317072da5d1a", - "sha256:bb72d2a94481e7dc7a0c522673db288f31849800d6ce2435317376a345728225", - "sha256:c25ec06e4241e162f5d1f57c370f4078797ade95c9208bd0c60f484834f09c96", - "sha256:c405d482c320a88ab53dcbd98d6d6f32ada074f2d965d6e9bf2d823158fa97de", - "sha256:c4472fe53ebf541113e533971bd8c32728debc4c6d8cc177f2bff31d011ec17e", - "sha256:c4b1efb11a8acd13246ffb0bee888dd0e8eb057f8bf30112e3e21e421eb82d4a", - "sha256:c5f3faeb8100a43adf3e7925d556801d14b5816a0ac9e75e22948e787feec642", - "sha256:c6f034386e5550b5dc8ded90b5e2ff7db21f0f5c7de37b6efc5dac046eb19c10", - "sha256:c99ddaddb2fbe04953b84d1651149a0d85214780e4d0ee824e610ab549d98d92", - "sha256:ca6b66f69e30f6e180d52f14d91ac854b8119553b524e0e28d5291a724f0f423", - "sha256:cccdc02e46d2bd7cb5f38f8cc3d9db0d24951abd082b2f242c9e9f59c0ab2af3", - "sha256:cd49a908cb6d387fc26acee8b7d9fcc9bbf8e1aca890c0b2fdfd706057546080", - "sha256:cf7a4e8de7f1092829caef66fd90eaf3710bc5efd322a816d5677b7664893c93", - "sha256:cfd77e8e5cafba3fb584e0f4b935a59216f352b73d4987be3af51f43a862c403", - "sha256:d34c4f80956227f2686ddea5b3585e109c2733e2d4ef12eb1b8b4e84f09a2ab6", - "sha256:d61a0ca95503867d4d627517bcfdc28a8468c3f1b0b06c626f30dd759d3999fd", - "sha256:d81657b23e0edb84b37167e98aefb04ae16cbc5352770057893bd222cdc6e45f", - "sha256:d92d897cb4b4bf915fbeb5e604c7911021a8456f0964f3b8ebbe7f9188b9eabb", - "sha256:dd318e6b75ca80bff0b22b302f83a8ee41c62b8ac662ddb49f67ec97e799885d", - "sha256:dd952b9c64f3b21aedd09b8fe958e4931864dba69926d8a90c90d36ac4e28c9a", - "sha256:e0e7e83f31e23c5d00ff618045ddc5e916f9e613d33c5a5823bc0b0a0feb522f", - "sha256:e0f17d1df951336a02afc8270c03c0c6e60d1f9996fcbd43a4ce6be81de0bd9d", - "sha256:e2a16ef5fa2382af83bef4a18c1b3bcb4284c4732906aa69422cf09df9c59f1f", - "sha256:e36021db54b8a0475805acc1d6c4bca5d9f52c3825ad29ae2d398a9d530ddb88", - "sha256:e73db54c967eb75037c178a54445c5a4e7461b5203b27c45ef656a81787c0c1b", - "sha256:e741bd48e6a417bdfbae02e088f60018286d6c141639359fb8df017a3b69415a", - "sha256:f7271d6bd8838c49ba8ae647fc06469137e1c161a7ef97d778b72904d9b68696", - "sha256:fc391e3941045fd0987c77484b2799adffd08e4b6735c4ee5f054366a2e1551d", - "sha256:fc94441bcf9cb8c59f51f23193316afefbf3ff858460cb47b5758bf66a14d130", - "sha256:fe34befb8c765b8ce562f0200afda3578f8abb159c76de3ab354c80b72244c41", - "sha256:fe8080b4f25dfc44a86bedd14bc4f9d469dfc6456e6f3c5d9077e81a5fedfba7", - "sha256:ff34cb09a332832d1cf38acd0f604c068665192c6107a439a92abfd8acf90fe2" - ], - "markers": "python_version >= '3.7'", - "version": "==1.9.3" + "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51", + "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce", + "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559", + "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0", + "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81", + "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc", + "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4", + "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c", + "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130", + "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136", + "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e", + "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec", + "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7", + "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1", + "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455", + "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099", + "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129", + "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10", + "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142", + "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98", + "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa", + "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7", + "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525", + "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c", + "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9", + "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c", + "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8", + "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b", + "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf", + "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23", + "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd", + "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27", + "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f", + "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece", + "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434", + "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec", + "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff", + "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78", + "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d", + "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863", + "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53", + "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31", + "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15", + "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5", + "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b", + "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57", + "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3", + "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1", + "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f", + "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad", + "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c", + "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7", + "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2", + "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b", + "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2", + "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b", + "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9", + "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be", + "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e", + "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984", + "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4", + "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074", + "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2", + "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392", + "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91", + "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541", + "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf", + "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572", + "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66", + "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575", + "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14", + "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5", + "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1", + "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e", + "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551", + "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17", + "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead", + "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0", + "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe", + "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234", + "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0", + "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7", + "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34", + "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42", + "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385", + "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78", + "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be", + "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958", + "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749", + "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec" + ], + "markers": "python_version >= '3.7'", + "version": "==1.9.4" + }, + "zipp": { + "hashes": [ + "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31", + "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0" + ], + "markers": "python_version >= '3.8'", + "version": "==3.17.0" } }, - "develop": {} + "develop": { + "colorama": { + "hashes": [ + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" + ], + "markers": "os_name == 'nt'", + "version": "==0.4.6" + }, + "iniconfig": { + "hashes": [ + "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", + "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.0" + }, + "packaging": { + "hashes": [ + "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", + "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" + ], + "markers": "python_version >= '3.7'", + "version": "==23.2" + }, + "pluggy": { + "hashes": [ + "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12", + "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7" + ], + "markers": "python_version >= '3.8'", + "version": "==1.3.0" + }, + "pytest": { + "hashes": [ + "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac", + "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5" + ], + "markers": "python_version >= '3.7'", + "version": "==7.4.3" + }, + "ruff": { + "hashes": [ + "sha256:0683b7bfbb95e6df3c7c04fe9d78f631f8e8ba4868dfc932d43d690698057e2e", + "sha256:1ea109bdb23c2a4413f397ebd8ac32cb498bee234d4191ae1a310af760e5d287", + "sha256:276a89bcb149b3d8c1b11d91aa81898fe698900ed553a08129b38d9d6570e717", + "sha256:290ecab680dce94affebefe0bbca2322a6277e83d4f29234627e0f8f6b4fa9ce", + "sha256:416dfd0bd45d1a2baa3b1b07b1b9758e7d993c256d3e51dc6e03a5e7901c7d80", + "sha256:45b38c3f8788a65e6a2cab02e0f7adfa88872696839d9882c13b7e2f35d64c5f", + "sha256:4af95fd1d3b001fc41325064336db36e3d27d2004cdb6d21fd617d45a172dd96", + "sha256:69a4bed13bc1d5dabf3902522b5a2aadfebe28226c6269694283c3b0cecb45fd", + "sha256:6b05e3b123f93bb4146a761b7a7d57af8cb7384ccb2502d29d736eaade0db519", + "sha256:6c64cb67b2025b1ac6d58e5ffca8f7b3f7fd921f35e78198411237e4f0db8e73", + "sha256:7f80496854fdc65b6659c271d2c26e90d4d401e6a4a31908e7e334fab4645aac", + "sha256:8b0c2de9dd9daf5e07624c24add25c3a490dbf74b0e9bca4145c632457b3b42a", + "sha256:90c958fe950735041f1c80d21b42184f1072cc3975d05e736e8d66fc377119ea", + "sha256:9dcc6bb2f4df59cb5b4b40ff14be7d57012179d69c6565c1da0d1f013d29951b", + "sha256:de02ca331f2143195a712983a57137c5ec0f10acc4aa81f7c1f86519e52b92a1", + "sha256:df2bb4bb6bbe921f6b4f5b6fdd8d8468c940731cb9406f274ae8c5ed7a78c478", + "sha256:dffd699d07abf54833e5f6cc50b85a6ff043715da8788c4a79bcd4ab4734d306" + ], + "markers": "python_version >= '3.7'", + "version": "==0.1.7" + } + } } diff --git a/README.md b/README.md index d408e827..2106af2e 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Installation requires that the conda channel-priority be set to "flexible". This ### Setup with pipenv #### Install python and git -We recommend that you use Python 3.10. If you don't have Python installed, we recommend that you use [**pyenv**](https://github.com/pyenv/pyenv). It lets you easily switch between multiple versions of Python. You will also need to use git to clone the repository. It can be installed from https://git-scm.com/downloads, +We recommend that you use Python 3.11. If you don't have Python installed, we recommend that you use [**pyenv**](https://github.com/pyenv/pyenv). It lets you easily switch between multiple versions of Python. You will also need to use git to clone the repository. It can be installed from https://git-scm.com/downloads, #### Install pipenv This can be done via: diff --git a/requirements.txt b/requirements.txt index e32eb4d1..8c0e81e7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,6 @@ plotly pyarrow pytest ruff -python-snappy qdldl requests seaborn From 6f3943538e5cbf5f8d8651812afbca1994bfc339 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Wed, 6 Dec 2023 17:22:21 -0800 Subject: [PATCH 32/85] update make_subplant_id dependency --- src/data_cleaning.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/data_cleaning.py b/src/data_cleaning.py index 717f0dde..1eca8bb0 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -4,7 +4,8 @@ import sqlalchemy as sa import pudl.analysis.allocate_gen_fuel as allocate_gen_fuel -import pudl.analysis.epacamd_eia as epacamd_eia_crosswalk +import pudl.analysis.epacamd_eia as epacamd_eia +from pudl.etl.glue_assets import make_subplant_ids import load_data import validation @@ -84,10 +85,10 @@ def generate_subplant_ids(start_year, end_year, cems_ids): crosswalk = load_data.load_epa_eia_crosswalk(end_year) # filter the crosswalk to drop any units that don't exist in CEMS - filtered_crosswalk = epacamd_eia_crosswalk.filter_crosswalk(crosswalk, cems_ids) + filtered_crosswalk = epacamd_eia.filter_crosswalk(crosswalk, cems_ids) # use graph analysis to identify subplants - crosswalk_with_subplant_ids = epacamd_eia_crosswalk.make_subplant_ids( + crosswalk_with_subplant_ids = make_subplant_ids( filtered_crosswalk ) @@ -200,7 +201,7 @@ def update_subplant_ids(subplant_crosswalk): Ensures a complete and accurate subplant_id mapping for all generators. NOTE: - 1. This function is a temporary placeholder until the `pudl.analysis.epacamd_eia_crosswalk` code is updated. + 1. This function is a temporary placeholder until the `pudl.analysis.epacamd_eia` code is updated. 2. This function is meant to be applied using a .groupby("plant_id_eia").apply() function. This function will only properly work when applied to a single plant_id_eia at a time. @@ -243,7 +244,7 @@ def update_subplant_ids(subplant_crosswalk): data, we assign these units to a single subplant. Args: - subplant_crosswalk: a dataframe containing the output of `epacamd_eia_crosswalk.make_subplant_ids` with + subplant_crosswalk: a dataframe containing the output of `pudl.etl.glue_assets.make_subplant_ids` with """ # Step 1: Create corrected versions of subplant_id and unit_id_pudl # if multiple unit_id_pudl are connected by a single subplant_id, unit_id_pudl_connected groups these unit_id_pudl together From eede70edfa52c3ecedb7e2294f1b10e32d6ef74f Mon Sep 17 00:00:00 2001 From: grgmiller Date: Wed, 6 Dec 2023 17:28:53 -0800 Subject: [PATCH 33/85] remove accidental text --- Pipfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pipfile b/Pipfile index 58e7ce71..0bb3992e 100644 --- a/Pipfile +++ b/Pipfile @@ -13,7 +13,7 @@ numpy = "*" openpyxl = "*" pandas = "*" plotly = "*" -pyarrow = "pip*" +pyarrow = "*" qdldl = "*" requests = "*" seaborn = "*" From 201c98de70c8b4bb1d7ef2d521c836b932241a18 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 7 Dec 2023 10:45:24 -0800 Subject: [PATCH 34/85] update datetime dtype --- src/data_cleaning.py | 2 +- src/eia930.py | 3 +-- src/emissions.py | 8 ++++---- src/gross_to_net_generation.py | 2 +- src/impute_hourly_profiles.py | 14 +++++++------- src/load_data.py | 27 ++++++++++++++++++++++++--- src/output_data.py | 3 +-- 7 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/data_cleaning.py b/src/data_cleaning.py index 1eca8bb0..e5c70a14 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -1316,7 +1316,7 @@ def fill_missing_fuel_for_single_fuel_plant_months(df, year): gf = gf.rename(columns={"energy_source_code": "energy_source_code_single"}).drop( columns=["num_fuels", "fuel_consumed_mmbtu"] ) - gf["report_date"] = pd.to_datetime(gf["report_date"]) + gf["report_date"] = pd.to_datetime(gf["report_date"]).astype("datetime64[s]") # merge this data into the df df = df.merge(gf, how="left", on=["plant_id_eia", "report_date"], validate="m:1") diff --git a/src/eia930.py b/src/eia930.py index 59843e05..a4892f64 100644 --- a/src/eia930.py +++ b/src/eia930.py @@ -250,7 +250,7 @@ def load_chalendar_for_pipeline(cleaned_data_filepath, year): # create a report date column data["report_date"] = data["datetime_local"].str[:7] - data["report_date"] = pd.to_datetime(data["report_date"]) + data["report_date"] = pd.to_datetime(data["report_date"]).astype("datetime64[s]") # rename the fuel categories using format in # data/manual/energy_source_groups @@ -285,7 +285,6 @@ def load_chalendar_for_pipeline(cleaned_data_filepath, year): def remove_imputed_ones(eia930_data): - filter = eia930_data["net_generation_mwh_930"].abs() < 1.5 # replace all 1.0 values with zero diff --git a/src/emissions.py b/src/emissions.py index d7c8cfd9..da8aca7f 100644 --- a/src/emissions.py +++ b/src/emissions.py @@ -944,10 +944,10 @@ def return_monthly_plant_fuel_heat_content(year): # change the report date columns back to datetimes plant_specific_fuel_heat_content["report_date"] = pd.to_datetime( plant_specific_fuel_heat_content["report_date"] - ) + ).astype("datetime64[s]") national_avg_fuel_heat_content["report_date"] = pd.to_datetime( national_avg_fuel_heat_content["report_date"] - ) + ).astype("datetime64[s]") return ( plant_specific_fuel_heat_content, @@ -1512,10 +1512,10 @@ def return_monthly_plant_fuel_sulfur_content(year): # change the report date columns back to datetimes plant_specific_fuel_sulfur_content["report_date"] = pd.to_datetime( plant_specific_fuel_sulfur_content["report_date"] - ) + ).astype("datetime64[s]") national_avg_fuel_sulfur_content["report_date"] = pd.to_datetime( national_avg_fuel_sulfur_content["report_date"] - ) + ).astype("datetime64[s]") plant_specific_fuel_sulfur_content diff --git a/src/gross_to_net_generation.py b/src/gross_to_net_generation.py index 2264faad..ad5aae58 100644 --- a/src/gross_to_net_generation.py +++ b/src/gross_to_net_generation.py @@ -426,7 +426,7 @@ def calculate_subplant_nameplate_capacity(year): subplant_prime_mover = gen_capacity[ gen_capacity.groupby(["plant_id_eia", "subplant_id"], dropna=False)[ "capacity_mw" - ].transform(max) + ].transform("max") == gen_capacity["capacity_mw"] ][["plant_id_eia", "subplant_id", "prime_mover_code"]].drop_duplicates( subset=["plant_id_eia", "subplant_id"], keep="first" diff --git a/src/impute_hourly_profiles.py b/src/impute_hourly_profiles.py index 10e2e031..506222ce 100644 --- a/src/impute_hourly_profiles.py +++ b/src/impute_hourly_profiles.py @@ -334,7 +334,6 @@ def aggregate_for_residual( def aggregate_non_930_fuel_categories(cems, plant_attributes): - # get a list of the fuel categories not in EIA-930 fuel_categories_not_in_eia930 = list( set(plant_attributes.fuel_category.unique()) @@ -573,7 +572,9 @@ def create_flat_profile(report_date, ba, fuel): # create a report date column df_temporary["report_date"] = df_temporary["datetime_local"].str[:7] - df_temporary["report_date"] = pd.to_datetime(df_temporary["report_date"]) + df_temporary["report_date"] = pd.to_datetime(df_temporary["report_date"]).astype( + "datetime64[s]" + ) # only keep the report dates that match df_temporary = df_temporary[df_temporary["report_date"] == report_date] @@ -664,7 +665,7 @@ def impute_missing_hourly_profiles( hourly_profiles["datetime_utc"] = pd.to_datetime( hourly_profiles["datetime_utc"], utc=True - ) + ).astype("datetime64[s]") validation.validate_unique_datetimes( hourly_profiles, "hourly_profiles", ["ba_code", "fuel_category"] ) @@ -712,7 +713,6 @@ def identify_missing_profiles( def average_diba_wind_solar_profiles( residual_profiles, ba, fuel, report_date, ba_dibas, validation_run=False ): - # calculate the average generation profile for the fuel in all neighboring DIBAs df_temporary = residual_profiles.copy()[ (residual_profiles["ba_code"].isin(ba_dibas)) @@ -764,7 +764,9 @@ def average_national_wind_solar_profiles(residual_profiles, ba, fuel, report_dat # re-localize the datetime_local local_tz = load_data.ba_timezone(ba, "local") - df_temporary["datetime_local"] = pd.to_datetime(df_temporary["datetime_local"]) + df_temporary["datetime_local"] = pd.to_datetime( + df_temporary["datetime_local"] + ).astype("datetime64[s]") df_temporary["datetime_local"] = ( df_temporary["datetime_local"] .dt.tz_localize(local_tz, nonexistent="NaT", ambiguous="NaT") @@ -1022,7 +1024,6 @@ def combine_and_export_hourly_plant_data( # for each region, shape the EIA-only data, combine with CEMS data, and export for region in list(plant_attributes[region_to_group].unique()): - # filter each of the data sources to the region eia_region = monthly_eia_data_to_shape_agg[ monthly_eia_data_to_shape_agg[region_to_group] == region @@ -1257,7 +1258,6 @@ def shape_partial_cems_plants(cems, eia923_allocated): # if there is no data in the partial cems dataframe, skip. if len(eia_data_to_shape) > 0: - # group the eia data by subplant eia_data_to_shape = ( eia_data_to_shape.groupby(SUBPLANT_KEYS, dropna=False)[DATA_COLUMNS] diff --git a/src/load_data.py b/src/load_data.py index b0a9bb6d..b1f9725e 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -51,6 +51,12 @@ def load_cems_data(year): filters=[["year", "==", year]], columns=cems_columns, ) + # convert to tz-naive datetime to allow for dtype application + cems["operating_datetime_utc"] = cems["operating_datetime_utc"].dt.tz_localize(None) + cems = apply_pudl_dtypes(cems) + cems["operating_datetime_utc"] = cems["operating_datetime_utc"].dt.tz_localize( + "UTC" + ) cems = cems.rename( columns={ @@ -114,6 +120,7 @@ def load_cems_ids(start_year, end_year): filters=[["year", ">=", start_year], ["year", "<=", end_year]], columns=["plant_id_eia", "emissions_unit_id_epa"], ).drop_duplicates() + cems = apply_pudl_dtypes(cems) return cems @@ -136,6 +143,12 @@ def load_cems_gross_generation(start_year, end_year): filters=[["year", ">=", start_year], ["year", "<=", end_year]], columns=cems_columns, ) + # convert to tz-naive datetime to allow for dtype application + cems["operating_datetime_utc"] = cems["operating_datetime_utc"].dt.tz_localize(None) + cems = apply_pudl_dtypes(cems) + cems["operating_datetime_utc"] = cems["operating_datetime_utc"].dt.tz_localize( + "UTC" + ) # only keep values when the plant was operating # this will help speed up calculations and allow us to add this data back later @@ -215,7 +228,7 @@ def add_report_date(df): .dt.to_timestamp() # convert to a YYYY-MM-01 stamp ) - df["report_date"] = pd.to_datetime(df["report_date"]) + df["report_date"] = pd.to_datetime(df["report_date"]).astype("datetime64[s]") # drop the operating_datetime_local column df = df.drop(columns=["timezone"]) @@ -545,7 +558,9 @@ def load_gross_to_net_data( # make sure the report date column is a datetime if loading ratios if conversion_type == "ratio": - gtn_data["report_date"] = pd.to_datetime(gtn_data["report_date"]) + gtn_data["report_date"] = pd.to_datetime(gtn_data["report_date"]).astype( + "datetime64[s]" + ) return gtn_data @@ -685,6 +700,8 @@ def load_emissions_controls_eia923(year: int): "acid_gas_removal_efficiency", ] + datetime_columns = ["report_date", "particulate_test_date", "so2_test_date"] + # For 2012-2015 and earlier, mercury emission rate is not reported in EIA923, so we need # to remove that column to avoid an error. if year <= 2015: @@ -734,8 +751,12 @@ def load_emissions_controls_eia923(year: int): names=emissions_controls_eia923_names, dtype=get_dtypes(), na_values=".", - parse_dates=["report_date", "particulate_test_date", "so2_test_date"], + parse_dates=datetime_columns, + date_format={"particulate_test_date": "%m-%Y", "so2_test_date": "%m-%Y"}, ) + emissions_controls_eia923["report_date"] = emissions_controls_eia923[ + "report_date" + ].astype("datetime64[s]") else: logger.warning( "Emissions control data prior to 2014 has not been integrated into the data pipeline." diff --git a/src/output_data.py b/src/output_data.py index 9d62f752..289bd341 100644 --- a/src/output_data.py +++ b/src/output_data.py @@ -141,7 +141,6 @@ def output_to_results( validation.test_for_missing_values(df, small) if not skip_outputs: - df.to_csv( results_folder(f"{path_prefix}{subfolder}us_units/{file_name}.csv"), index=False, @@ -477,7 +476,7 @@ def write_power_sector_results(ba_fuel_data, path_prefix, skip_outputs): # convert the datetime_utc column back to a datetime ba_table["datetime_utc"] = pd.to_datetime( ba_table["datetime_utc"], utc=True - ) + ).astype("datetime64[s]") # calculate a total for the BA # grouping by datetime_utc and report_date will create some duplicate datetime_utc From ecfa18284df3628ba6cd20cd84628ed801c7ae5f Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 7 Dec 2023 11:04:12 -0800 Subject: [PATCH 35/85] update docs --- docs/docs/Data Validation/Data Quality Metrics.md | 5 ++++- docs/docs/Methodology/Data Aggregation/Plant Primary Fuel.md | 2 +- docs/docs/Overview/Input Data Sources.md | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/docs/Data Validation/Data Quality Metrics.md b/docs/docs/Data Validation/Data Quality Metrics.md index 364730bd..f72c8364 100644 --- a/docs/docs/Data Validation/Data Quality Metrics.md +++ b/docs/docs/Data Validation/Data Quality Metrics.md @@ -25,4 +25,7 @@ These two tables indicate report the results of the cross-validation performed f Indicates for each subplant-month: - the input data source - the hourly profile method -- the gross-to-net generation method \ No newline at end of file +- the gross-to-net generation method + +### Data pipeline log +This text file is a log of all of the warnings and messages when running the data pipeline. This information flags when assumptions are being used, anomalies are detected, or known issues are identified. All warnings include the "[WARNING]" flag, which can be used to search them. \ No newline at end of file diff --git a/docs/docs/Methodology/Data Aggregation/Plant Primary Fuel.md b/docs/docs/Methodology/Data Aggregation/Plant Primary Fuel.md index 625e8047..1ece17e8 100644 --- a/docs/docs/Methodology/Data Aggregation/Plant Primary Fuel.md +++ b/docs/docs/Methodology/Data Aggregation/Plant Primary Fuel.md @@ -10,4 +10,4 @@ If no fuel consumption data is reported or if there are multiple fuels with the If multiple fuels are associated with the same amount of nameplate capacity at a plant, then the primary fuel is determined based on the energy source code that is associated with the highest annual volume of net generation. -In rare cases where all of the preceding methods of determining plant primary fuel fail, the plant primary fuel is determined based on the `energy_source_code_1` associated with the most number of generators at a plant. \ No newline at end of file +In rare cases where all of the preceding methods of determining plant primary fuel fail, the plant primary fuel is determined based on the primary fuel associated with the most number of generators at a plant. \ No newline at end of file diff --git a/docs/docs/Overview/Input Data Sources.md b/docs/docs/Overview/Input Data Sources.md index 16922b76..a9acc6b4 100644 --- a/docs/docs/Overview/Input Data Sources.md +++ b/docs/docs/Overview/Input Data Sources.md @@ -26,7 +26,7 @@ stoplight-id: input_data **Public Utility Data Liberation (PUDL) Project** * **What is it**: an open source data processing pipeline that makes U.S. energy data easier to access and use programmatically -* **How we use it**: To access pre-cleaned and standardized versions of CEMS, EIA-923, and EIA-860 data +* **How we use it**: To access pre-cleaned and standardized versions of CEMS, EIA-923, and EIA-860 data, as well as the EPA-EIA Power Sector Data Crosswalk. * **More information**: [https://catalystcoop-pudl.readthedocs.io/en/latest/](https://catalystcoop-pudl.readthedocs.io/en/latest/) **EPA-EIA Power Sector Data Crosswalk** From d547d191318fd919fdbc79d4408ae6bc6aef0823 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 7 Dec 2023 12:15:28 -0800 Subject: [PATCH 36/85] fix datetime dtype error --- src/impute_hourly_profiles.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/impute_hourly_profiles.py b/src/impute_hourly_profiles.py index 506222ce..abeefb67 100644 --- a/src/impute_hourly_profiles.py +++ b/src/impute_hourly_profiles.py @@ -664,8 +664,11 @@ def impute_missing_hourly_profiles( hourly_profiles = pd.concat([residual_profiles, hourly_profiles_to_add], axis=0) hourly_profiles["datetime_utc"] = pd.to_datetime( - hourly_profiles["datetime_utc"], utc=True + hourly_profiles["datetime_utc"] ).astype("datetime64[s]") + hourly_profiles["datetime_utc"] = hourly_profiles["datetime_utc"].dt.tz_localize( + "UTC" + ) validation.validate_unique_datetimes( hourly_profiles, "hourly_profiles", ["ba_code", "fuel_category"] ) @@ -770,7 +773,7 @@ def average_national_wind_solar_profiles(residual_profiles, ba, fuel, report_dat df_temporary["datetime_local"] = ( df_temporary["datetime_local"] .dt.tz_localize(local_tz, nonexistent="NaT", ambiguous="NaT") - .fillna(method="ffill") + .ffill() ) df_temporary["datetime_utc"] = df_temporary["datetime_local"].dt.tz_convert("UTC") From 06057516664ab87908783c37bb02cfd7532e37f5 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 7 Dec 2023 13:55:11 -0800 Subject: [PATCH 37/85] fix datetime error --- environment.yml | 2 +- src/impute_hourly_profiles.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/environment.yml b/environment.yml index 01dd6d3f..b44710b7 100644 --- a/environment.yml +++ b/environment.yml @@ -1,4 +1,4 @@ -name: open_grid_emissions_test +name: open_grid_emissions channels: - defaults - conda-forge diff --git a/src/impute_hourly_profiles.py b/src/impute_hourly_profiles.py index abeefb67..d796b013 100644 --- a/src/impute_hourly_profiles.py +++ b/src/impute_hourly_profiles.py @@ -663,11 +663,12 @@ def impute_missing_hourly_profiles( hourly_profiles = pd.concat([residual_profiles, hourly_profiles_to_add], axis=0) - hourly_profiles["datetime_utc"] = pd.to_datetime( - hourly_profiles["datetime_utc"] - ).astype("datetime64[s]") - hourly_profiles["datetime_utc"] = hourly_profiles["datetime_utc"].dt.tz_localize( - "UTC" + # convert to datetime64[s] format + hourly_profiles["datetime_utc"] = ( + pd.to_datetime(hourly_profiles["datetime_utc"]) + .dt.tz_localize(None) + .astype("datetime64[s]") + .dt.tz_localize("UTC") ) validation.validate_unique_datetimes( hourly_profiles, "hourly_profiles", ["ba_code", "fuel_category"] From 870815a4ab07fdcfeeb6b79d023f43201c760d96 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 7 Dec 2023 14:13:09 -0800 Subject: [PATCH 38/85] fix datetime error in outputs --- src/output_data.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/output_data.py b/src/output_data.py index 289bd341..f8137731 100644 --- a/src/output_data.py +++ b/src/output_data.py @@ -474,9 +474,12 @@ def write_power_sector_results(ba_fuel_data, path_prefix, skip_outputs): ) # convert the datetime_utc column back to a datetime - ba_table["datetime_utc"] = pd.to_datetime( - ba_table["datetime_utc"], utc=True - ).astype("datetime64[s]") + ba_table["datetime_utc"] = ( + pd.to_datetime(ba_table["datetime_utc"]) + .dt.tz_localize(None) + .astype("datetime64[s]") + .dt.tz_localize("UTC") + ) # calculate a total for the BA # grouping by datetime_utc and report_date will create some duplicate datetime_utc From e373b29de0150b2651ba1fc8bcef3123253171af Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 7 Dec 2023 16:48:22 -0800 Subject: [PATCH 39/85] update to pudl v2023.12.01 --- src/download_data.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/download_data.py b/src/download_data.py index 717bc1e2..60d1ad2b 100644 --- a/src/download_data.py +++ b/src/download_data.py @@ -103,10 +103,8 @@ def download_pudl_data(source: str = "aws"): if source == "aws": # define the urls - pudl_db_url = ( - "https://s3.us-west-2.amazonaws.com/pudl.catalyst.coop/dev/pudl.sqlite.gz" - ) - epacems_parquet_url = "https://s3.us-west-2.amazonaws.com/pudl.catalyst.coop/dev/hourly_emissions_epacems.parquet" + pudl_db_url = "https://s3.us-west-2.amazonaws.com/pudl.catalyst.coop/v2023.12.01/pudl.sqlite.gz" + epacems_parquet_url = "https://s3.us-west-2.amazonaws.com/pudl.catalyst.coop/v2023.12.01/hourly_emissions_epacems.parquet" # download the pudl sqlite database if not os.path.exists(downloads_folder("pudl/pudl.sqlite")): From 0f8d2fdb49672fff8263457f8bca56139219720a Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 8 Dec 2023 17:00:25 -0800 Subject: [PATCH 40/85] update references to 2021 --- data/manual/ba_reference.csv | 6 +++--- notebooks/manual_data/manually_update_ba_reference.ipynb | 4 +++- src/data_pipeline.py | 4 ++-- src/load_data.py | 3 +++ src/validation.py | 2 +- src/visualization.py | 2 +- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/data/manual/ba_reference.csv b/data/manual/ba_reference.csv index f175ebfb..4769237b 100644 --- a/data/manual/ba_reference.csv +++ b/data/manual/ba_reference.csv @@ -32,7 +32,7 @@ BUBA,"Constellation Energy Control and Dispatch - City of Benton, Arkansas",,,,Y CE,Commonwealth Edison,,,,Yes,1/1/2004,7/1/2006,,,,FERC,31 CEA,Chugash Electric Association,,US/Alaska,US/Alaska,Yes,,,,,,EIA,32 CEN,Centro Nacional de Control de Energia,,America/Mexico_City,America/Mexico_City,No,10/31/2017,,,1/1/2016,,EIA & FERC,33 -CFE,Comision Federal de Electricidad,,America/Mexico_City,America/Mexico_City,No,,,,,,EIA & FERC,34 +CFE,Comision Federal de Electricidad,,America/Mexico_City,America/Mexico_City,No,,7/1/2018,,,,EIA & FERC,34 CFEN,Comision Federal de Electricidad,,,,No,,4/1/2015,,,,FERC,35 CHPD,Public Utility District No. 1 of Chelan County,,US/Pacific,US/Pacific,Yes,1/1/2004,,,,,EIA & FERC,36 CILC,Central Illinois Light Co,,,,Yes,1/1/2004,10/1/2007,,,,FERC,37 @@ -82,7 +82,7 @@ FPC,"Duke Energy Florida, Inc.",,US/Eastern,US/Eastern,Yes,1/1/2004,,Florida Pow FPL,Florida Power & Light Co.,,US/Eastern,US/Eastern,Yes,1/1/2004,,,,,EIA & FERC,81 GA,GridAmerica,,,,Yes,1/1/2004,4/1/2015,,,,FERC,82 GCPD,"Public Utility District No. 2 of Grant County, Washington",,US/Pacific,US/Pacific,Yes,1/1/2004,,,,,EIA & FERC,83 -GLHB,GridLiance,generation_only,US/Central,US/Central,Yes,2/29/2020,,GridLiance Heartland (BA),1/1/2020,,EIA & FERC,84 +GLHB,GridLiance,generation_only,US/Central,US/Central,Yes,2/29/2020,9/1/2022,GridLiance Heartland (BA),1/1/2020,,EIA & FERC,84 GLHL,GridLiance Heartland,,,,Yes,1/1/2020,,,,,FERC,85 GRDA,Grand River Dam Authority,,,,Yes,1/1/2004,4/1/2015,,,,FERC,86 GRE,Great River Energy,,,,Yes,1/1/2004,,,,,FERC,87 @@ -90,7 +90,7 @@ GREC,Great River Energy,,,,Yes,1/1/2004,,,,,FERC,88 GREN,Great River Energy,,,,Yes,1/1/2004,,,,,FERC,89 GRES,Great River Energy,,,,Yes,1/1/2004,,,,,FERC,90 GRID,"Gridforce Energy Management, LLC",generation_only,US/Pacific,US/Pacific,Yes,4/1/2014,,Constellation Energy Control and Dispatch,,,EIA & FERC,91 -GRIF,"Griffith Energy, LLC",generation_only,US/Arizona,US/Arizona,Yes,10/1/2008,,Constellation Energy Control and Dispatch,,,EIA & FERC,92 +GRIF,"Griffith Energy, LLC",generation_only,US/Arizona,US/Arizona,Yes,10/1/2008,11/1/2023,Constellation Energy Control and Dispatch,,,EIA & FERC,92 GRIS,Gridforce South,,US/Central,US/Central,Yes,,,,,,EIA,93 GRMA,"Gila River Power, LLC",generation_only,US/Arizona,US/Arizona,Yes,1/1/2004,5/3/2018,Constellation Energy Control and Dispatch - Gila River,,,EIA & FERC,94 GSOC,Georgia System Operations Corporation,,,,Yes,1/1/2004,12/31/2009,,,,FERC,95 diff --git a/notebooks/manual_data/manually_update_ba_reference.ipynb b/notebooks/manual_data/manually_update_ba_reference.ipynb index b63ceb80..4c0df81a 100644 --- a/notebooks/manual_data/manually_update_ba_reference.ipynb +++ b/notebooks/manual_data/manually_update_ba_reference.ipynb @@ -10,7 +10,9 @@ "\n", "Check https://www.ferc.gov/power-sales-and-markets/electric-quarterly-reports-eqr and look for the \"Allowable Entries for Balancing Authorities and Hubs\"\n", "\n", - "The most recent file uploaded is https://www.ferc.gov/sites/default/files/2020-05/allowable-entries1_0.xls" + "The most recent file uploaded is https://www.ferc.gov/sites/default/files/2020-05/allowable-entries1_0.xls\n", + "\n", + "Also check the EIA-930 data reference tables and List of Balancing Authorities posted on https://www.eia.gov/electricity/gridmonitor/about" ] }, { diff --git a/src/data_pipeline.py b/src/data_pipeline.py index 890a4439..06bf4c89 100644 --- a/src/data_pipeline.py +++ b/src/data_pipeline.py @@ -3,7 +3,7 @@ Run from `src` as `python data_pipeline.py` after installing conda environment -Optional arguments are --year (default 2021), --shape_individual_plants (default True) +Optional arguments are --year (default 2022), --shape_individual_plants (default True) Optional arguments for development are --small, --flat, and --skip_outputs """ import argparse @@ -30,7 +30,7 @@ def get_args() -> argparse.Namespace: Returns dictionary of {arg_name: arg_value} """ parser = argparse.ArgumentParser() - parser.add_argument("--year", help="Year for analysis", default=2021, type=int) + parser.add_argument("--year", help="Year for analysis", default=2022, type=int) parser.add_argument( "--shape_individual_plants", help="Assign an hourly profile to each individual plant with EIA-only data, instead of aggregating to the fleet level before shaping.", diff --git a/src/load_data.py b/src/load_data.py index b1f9725e..dd286bda 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -742,6 +742,9 @@ def load_emissions_controls_eia923(year: int): 2021: downloads_folder( f"eia923/f923_{year}/EIA923_Schedule_8_Annual_Environmental_Information_{year}_Final_Revision.xlsx" ), + 2022: downloads_folder( + f"eia923/f923_{year}/EIA923_Schedule_8_Annual_Environmental_Information_{year}_Final.xlsx" + ), }[year] emissions_controls_eia923 = pd.read_excel( diff --git a/src/validation.py b/src/validation.py index 2302762c..c36efedb 100644 --- a/src/validation.py +++ b/src/validation.py @@ -19,7 +19,7 @@ def validate_year(year): """Returns a warning if the year specified is not known to work with the pipeline.""" earliest_validated_year = 2019 - latest_validated_year = 2021 + latest_validated_year = 2022 if year < earliest_validated_year: year_warning = f""" diff --git a/src/visualization.py b/src/visualization.py index 18c626bf..078fa4d1 100644 --- a/src/visualization.py +++ b/src/visualization.py @@ -11,7 +11,7 @@ """ -def day_hour_heatmap(timeseries: pd.Series, year: int = 2021): +def day_hour_heatmap(timeseries: pd.Series, year: int = 2022): timeseries = timeseries.rename("a") # needs to be named so we can merge # Make a new dataframe that has all full days in year in EST From 50365eab6067479dad1c5e42a53eb523a83e3ae6 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Wed, 29 Nov 2023 10:25:14 -0800 Subject: [PATCH 41/85] feat: write pyproject.toml enclosing default configuration for ruff --- pyproject.toml | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..dfe594eb --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,68 @@ +[project] +name = "open-grid-emissions" +requires-python = ">3.10" +readme = "README.md" + +[tool.ruff] +# Exclude a variety of commonly ignored directories. +exclude = [ + ".git", + ".github", + ".pytest_cache", + ".ruff_cache", + ".tox", + ".venv", + "__pypackages__", + "_build", + "build", + "venv", +] + +# All paths are relative to the project root, which is the directory containing the pyproject.toml. +src = ["src"] + +# Same as Black. +line-length = 88 +indent-width = 4 + +# Assume Python 3.8 +target-version = "py310" + +# Built-in for Jupyter +extend-include = ["*.ipynb"] + +[tool.ruff.lint] +# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. +# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or +# McCabe complexity (`C901`) by default. +select = ["E4", "E7", "E9", "F"] +ignore = [] + +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +# Exclude notebooks +exclude = ["*.ipynb"] + +[tool.ruff.lint.flake8-quotes] +docstring-quotes = "double" + +[tool.ruff.format] +# Like Black, use double quotes for strings. +quote-style = "double" + +# Like Black, indent with spaces, rather than tabs. +indent-style = "space" + +# Like Black, respect magic trailing commas. +skip-magic-trailing-comma = false + +# Like Black, automatically detect the appropriate line ending. +line-ending = "auto" + +[tool.ruff.lint.pydocstyle] +convention = "google" From 174132d3d34eadc129134e6ff75de4c046f4bd49 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Wed, 29 Nov 2023 10:26:31 -0800 Subject: [PATCH 42/85] chore: format notebook --- .../explore_data/compare_data_sources.ipynb | 68 +- .../explore_annually_reported_eia_data.ipynb | 92 +- .../explore_intermediate_outputs.ipynb | 64 +- notebooks/explore_data/gens_not_in_cems.ipynb | 73 +- ...import_uncontrolled_emission_factors.ipynb | 191 +- .../calculate_residual_net_generation.ipynb | 1670 +++++++++-------- .../national_wind_solar_correlations.ipynb | 17 +- .../default_fuel_sulfur_content.ipynb | 27 +- .../export_fuel_heat_content.ipynb | 7 +- .../identify_eia930_time_lags.ipynb | 495 +++-- .../manually_identify_crosswalk_updates.ipynb | 118 +- .../manually_update_OTH_fuel_code.ipynb | 19 +- .../manually_update_ba_reference.ipynb | 13 +- .../update_utility_name_ba_map.ipynb | 21 +- notebooks/manual_data/zip_data.ipynb | 11 +- notebooks/validation/data_validation.ipynb | 708 +++++-- .../validation/diff_output_versions.ipynb | 105 +- notebooks/validation/hourly_validation.ipynb | 647 +++++-- .../validation/validate_data_cleaning.ipynb | 89 +- .../validation/validate_hourly_profiles.ipynb | 129 +- .../validate_negative_profiles.ipynb | 150 +- notebooks/validation/validate_vs_egrid.ipynb | 83 +- .../visualization/map_visualization.ipynb | 1405 ++++++++------ .../visualization/plot_timeseries_data.ipynb | 19 +- .../work_in_progress/GH102_test_dask.ipynb | 55 +- .../GH153_fill_missing_nox_so2_cems.ipynb | 35 +- .../GH240_eia930_physics_reconciliation.ipynb | 44 +- .../clean_cems_outliers.ipynb | 161 +- .../work_in_progress/issue230_spikes.ipynb | 55 +- notebooks/work_in_progress/sandbox.ipynb | 4 +- .../uncertainty_analysis.ipynb | 307 ++- 31 files changed, 4346 insertions(+), 2536 deletions(-) diff --git a/notebooks/explore_data/compare_data_sources.ipynb b/notebooks/explore_data/compare_data_sources.ipynb index 886855af..41ee76c2 100644 --- a/notebooks/explore_data/compare_data_sources.ipynb +++ b/notebooks/explore_data/compare_data_sources.ipynb @@ -11,7 +11,7 @@ "# Depending on how your jupyter handles working directories, this may not be needed.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/\")\n" + "sys.path.append(\"../../../open-grid-emissions/\")" ] }, { @@ -57,7 +57,7 @@ "metadata": {}, "outputs": [], "source": [ - "year = 2019\n" + "year = 2019" ] }, { @@ -142,7 +142,7 @@ " col.replace(\"Net Generation (MW) from \", \"\") for col in eia_930.columns\n", "]\n", "\n", - "eia_930.head(3)\n" + "eia_930.head(3)" ] }, { @@ -171,7 +171,7 @@ " \"Natural Gas\",\n", " \"All Petroleum Products\",\n", " \"Other Fuel Sources\",\n", - "]\n" + "]" ] }, { @@ -185,7 +185,7 @@ "\n", "# replace negative values with NaN\n", "for col in emitting_gen_columns:\n", - " eia_930.loc[eia_930[col] < 0, col] = np.nan\n" + " eia_930.loc[eia_930[col] < 0, col] = np.nan" ] }, { @@ -201,7 +201,7 @@ "# Calculate hourly EIA-930 non-renewable generation\n", "eia_930[\"total_net_generation\"] = eia_930[net_gen_columns].sum(axis=1)\n", "\n", - "eia_930.head(3)\n" + "eia_930.head(3)" ] }, { @@ -215,7 +215,7 @@ " eia_930.groupby(\"Balancing Authority\").sum()[\"emitting_net_generation\"]\n", ")\n", "annual_930 = annual_930.rename(columns={\"emitting_net_generation\": \"EIA-930\"})\n", - "annual_930.head()\n" + "annual_930.head()" ] }, { @@ -247,7 +247,7 @@ " AND report_date <= '{year}-12-30'\",\n", " pudl_engine,\n", ")\n", - "gen_fuel_923.head()\n" + "gen_fuel_923.head()" ] }, { @@ -264,7 +264,7 @@ "fuel_code_dict_pudl = pd.Series(\n", " fuel_code_dict_pudl.fuel_type_code_pudl.values,\n", " index=fuel_code_dict_pudl.energy_source_code,\n", - ").to_dict()\n" + ").to_dict()" ] }, { @@ -336,7 +336,7 @@ "# Add ba code to generation_fuel_eia923\n", "gen_fuel_923 = gen_fuel_923.merge(plants_ba, how=\"left\", on=\"plant_id_eia\")\n", "\n", - "gen_fuel_923.head()\n" + "gen_fuel_923.head()" ] }, { @@ -350,7 +350,7 @@ " gen_fuel_923.groupby(\"balancing_authority_code_eia\").sum()[\"net_generation_mwh\"]\n", ")\n", "annual_923 = annual_923.rename(columns={\"net_generation_mwh\": \"EIA-923\"})\n", - "annual_923.head()\n" + "annual_923.head()" ] }, { @@ -362,7 +362,7 @@ "source": [ "compare_annual_923_930 = annual_923.merge(\n", " annual_930, how=\"outer\", left_index=True, right_index=True\n", - ")\n" + ")" ] }, { @@ -373,7 +373,7 @@ "outputs": [], "source": [ "# identify which BAs are missing from one or another dataset\n", - "compare_annual_923_930[compare_annual_923_930.isna().any(axis=1)]\n" + "compare_annual_923_930[compare_annual_923_930.isna().any(axis=1)]" ] }, { @@ -384,7 +384,7 @@ "outputs": [], "source": [ "# let's compare each BA\n", - "px.scatter(compare_annual_923_930)\n" + "px.scatter(compare_annual_923_930)" ] }, { @@ -404,7 +404,7 @@ " percent_diff_923_930,\n", " title=\"percent difference between emitting net generation in EIA-930 and EIA-923\",\n", " labels={\"value\": \"% change from EIA-923\"},\n", - ")\n" + ")" ] }, { @@ -430,7 +430,7 @@ "annual_923_by_fuel = annual_923_by_fuel.rename(\n", " columns={\"net_generation_mwh\": \"EIA-923\"}\n", ")\n", - "annual_923_by_fuel.head(3)\n" + "annual_923_by_fuel.head(3)" ] }, { @@ -457,7 +457,7 @@ "annual_930_by_fuel = annual_930_by_fuel.rename(\n", " columns={\"Balancing Authority\": \"balancing_authority_code_eia\"}\n", ")\n", - "annual_930_by_fuel\n" + "annual_930_by_fuel" ] }, { @@ -481,7 +481,7 @@ " facet_col_wrap=1,\n", " height=1000,\n", " title=\"comparison of net generation by fuel type for each BA\",\n", - ")\n" + ")" ] }, { @@ -498,7 +498,7 @@ "percent_error[\"percent_error\"] = (\n", " percent_error[\"EIA-930\"] - percent_error[\"EIA-923\"]\n", ") / percent_error[\"EIA-923\"]\n", - "percent_error\n" + "percent_error" ] }, { @@ -548,7 +548,7 @@ "hourly_net_emissions = pd.read_csv(\n", " \"../data/outputs/hourly_net_emission.csv\", index_col=0, parse_dates=True\n", ")\n", - "hourly_emission_rate.head()\n" + "hourly_emission_rate.head()" ] }, { @@ -558,7 +558,7 @@ "metadata": {}, "outputs": [], "source": [ - "eia_930.head()\n" + "eia_930.head()" ] }, { @@ -589,7 +589,7 @@ ")\n", "ax2.set_title(ba)\n", "ax2.legend()\n", - "ax2.set_xlim(parse_dt(\"2019-08-01\"), parse_dt(\"2019-08-10\"))\n" + "ax2.set_xlim(parse_dt(\"2019-08-01\"), parse_dt(\"2019-08-10\"))" ] }, { @@ -610,7 +610,7 @@ ")\n", "data_for_plot = data_for_plot.rename(columns={ba: \"CEMS\"})\n", "\n", - "px.line(data_for_plot, title=f\"Net generation in {ba} EIA-930 vs CEMS\")\n" + "px.line(data_for_plot, title=f\"Net generation in {ba} EIA-930 vs CEMS\")" ] }, { @@ -632,7 +632,7 @@ "source": [ "# For annual comparison graphs, see below with eGRID\n", "annual_eia_930 = eia_930.groupby(\"Balancing Authority\").sum()[\"emitting_net_generation\"]\n", - "annual_eia_930.head()\n" + "annual_eia_930.head()" ] }, { @@ -663,7 +663,7 @@ " AND report_date <= '{year}-12-30'\",\n", " pudl_engine,\n", ")\n", - "gen_923.head()\n" + "gen_923.head()" ] }, { @@ -682,7 +682,7 @@ "otherway = np.setdiff1d(\n", " gen_fuel_923[\"plant_id_eia\"].unique(), gen_923[\"plant_id_eia\"].unique()\n", ")\n", - "print(f\"{len(oneway)} plants in generation_fuel_eia923 are not in generation_eia923\")\n" + "print(f\"{len(oneway)} plants in generation_fuel_eia923 are not in generation_eia923\")" ] }, { @@ -731,7 +731,7 @@ " header=1,\n", " index_col=\"BACODE\",\n", ")\n", - "egrid.head()\n" + "egrid.head()" ] }, { @@ -753,7 +753,7 @@ " (egrid_data_code_to_name.loc[0, name], name)\n", " for name in egrid_data_code_to_name.columns\n", " ]\n", - ")\n" + ")" ] }, { @@ -767,7 +767,7 @@ "annual_generation = hourly_net_generation.sum(axis=0).rename(\"hourly\")\n", "annual_generation = egrid.merge(\n", " annual_generation, how=\"right\", left_index=True, right_index=True\n", - ").loc[:, [\"hourly\", \"BAGENACY\"]]\n" + ").loc[:, [\"hourly\", \"BAGENACY\"]]" ] }, { @@ -783,7 +783,7 @@ ")\n", "annual_generation = annual_generation.merge(\n", " annual_923, how=\"left\", left_index=True, right_index=True\n", - ")\n" + ")" ] }, { @@ -793,7 +793,7 @@ "metadata": {}, "outputs": [], "source": [ - "annual_generation.head()\n" + "annual_generation.head()" ] }, { @@ -860,7 +860,7 @@ "ax3.hlines([1.0], -0.5, len(annual_generation) - 0.5, color=\"r\")\n", "ax3.set_ylabel(\"Fraction of 930 generation captured by CEMS\")\n", "ax3.set_ylim(0, 2)\n", - "ax3.set_title(\"EIA-930 vs OGEI\")\n" + "ax3.set_title(\"EIA-930 vs OGEI\")" ] }, { @@ -872,7 +872,7 @@ "source": [ "# Many small BAs have terrible coverage of EIA-930 data, resulting in low annually aggregated 930 numbers.\n", "# The worst discrepencies between 930 and eGRID:\n", - "annual_generation.loc[[\"FPL\", \"IPCO\", \"NEVP\", \"SC\", \"TEC\", \"TVA\"], :]\n" + "annual_generation.loc[[\"FPL\", \"IPCO\", \"NEVP\", \"SC\", \"TEC\", \"TVA\"], :]" ] }, { @@ -900,7 +900,7 @@ "ax.set_xticklabels(labels=annual_generation.index, rotation=90)\n", "ax.hlines([1.0], -0.5, len(annual_generation) - 0.5, color=\"r\")\n", "ax.set_ylabel(\"Fraction of eGRID non-renewable generation captured by 923\")\n", - "ax.set_title(\"923 vs eGRID\")\n" + "ax.set_title(\"923 vs eGRID\")" ] }, { diff --git a/notebooks/explore_data/explore_annually_reported_eia_data.ipynb b/notebooks/explore_data/explore_annually_reported_eia_data.ipynb index af672e8c..b2b32a2c 100644 --- a/notebooks/explore_data/explore_annually_reported_eia_data.ipynb +++ b/notebooks/explore_data/explore_annually_reported_eia_data.ipynb @@ -14,7 +14,8 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "from column_checks import get_dtypes\n", "import load_data\n", @@ -39,11 +40,17 @@ "source": [ "pudl_out = load_data.initialize_pudl_out(year)\n", "\n", - "plant_frequency = pudl_out.plants_eia860()[[\"plant_id_eia\",\"respondent_frequency\"]]\n", + "plant_frequency = pudl_out.plants_eia860()[[\"plant_id_eia\", \"respondent_frequency\"]]\n", "\n", "# load the allocated EIA data\n", - "eia923_allocated = pd.read_csv(f'{outputs_folder()}{path_prefix}/eia923_allocated_{year}.csv', dtype=get_dtypes(), parse_dates=['report_date'])\n", - "eia923_allocated = eia923_allocated.merge(plant_frequency, how=\"left\", on=\"plant_id_eia\", validate=\"m:1\")" + "eia923_allocated = pd.read_csv(\n", + " f\"{outputs_folder()}{path_prefix}/eia923_allocated_{year}.csv\",\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"report_date\"],\n", + ")\n", + "eia923_allocated = eia923_allocated.merge(\n", + " plant_frequency, how=\"left\", on=\"plant_id_eia\", validate=\"m:1\"\n", + ")" ] }, { @@ -52,7 +59,15 @@ "metadata": {}, "outputs": [], "source": [ - "data_from_annual = eia923_allocated.groupby([\"respondent_frequency\"], dropna=False)[[\"fuel_consumed_mmbtu\", \"net_generation_mwh\",\"co2_mass_lb\"]].sum() / eia923_allocated[[\"fuel_consumed_mmbtu\", \"net_generation_mwh\",\"co2_mass_lb\"]].sum() * 100\n", + "data_from_annual = (\n", + " eia923_allocated.groupby([\"respondent_frequency\"], dropna=False)[\n", + " [\"fuel_consumed_mmbtu\", \"net_generation_mwh\", \"co2_mass_lb\"]\n", + " ].sum()\n", + " / eia923_allocated[\n", + " [\"fuel_consumed_mmbtu\", \"net_generation_mwh\", \"co2_mass_lb\"]\n", + " ].sum()\n", + " * 100\n", + ")\n", "data_from_annual.loc[\"Total Percent\"] = data_from_annual.sum()\n", "data_from_annual" ] @@ -63,7 +78,7 @@ "metadata": {}, "outputs": [], "source": [ - "data_from_annual.loc[\"A\",:].rename(\"% of EIA-923 input data from EIA annual reporters\")" + "data_from_annual.loc[\"A\", :].rename(\"% of EIA-923 input data from EIA annual reporters\")" ] }, { @@ -80,7 +95,17 @@ "metadata": {}, "outputs": [], "source": [ - "annual_eia_used = eia923_allocated[eia923_allocated[\"hourly_data_source\"] != \"cems\"].groupby([\"respondent_frequency\"], dropna=False)[[\"fuel_consumed_mmbtu\", \"net_generation_mwh\",\"co2_mass_lb\"]].sum() / eia923_allocated[[\"fuel_consumed_mmbtu\", \"net_generation_mwh\",\"co2_mass_lb\"]].sum() * 100\n", + "annual_eia_used = (\n", + " eia923_allocated[eia923_allocated[\"hourly_data_source\"] != \"cems\"]\n", + " .groupby([\"respondent_frequency\"], dropna=False)[\n", + " [\"fuel_consumed_mmbtu\", \"net_generation_mwh\", \"co2_mass_lb\"]\n", + " ]\n", + " .sum()\n", + " / eia923_allocated[\n", + " [\"fuel_consumed_mmbtu\", \"net_generation_mwh\", \"co2_mass_lb\"]\n", + " ].sum()\n", + " * 100\n", + ")\n", "annual_eia_used.loc[\"Total Percent\"] = annual_eia_used.sum()\n", "annual_eia_used" ] @@ -91,7 +116,7 @@ "metadata": {}, "outputs": [], "source": [ - "annual_eia_used.loc[\"A\",:].rename(\"% of output data from EIA annual reporters\")" + "annual_eia_used.loc[\"A\", :].rename(\"% of output data from EIA annual reporters\")" ] }, { @@ -108,15 +133,19 @@ "metadata": {}, "outputs": [], "source": [ - "multi_source_subplants = eia923_allocated[\n", - " [\"plant_id_eia\", \"subplant_id\", \"hourly_data_source\"]\n", - "].drop_duplicates().drop(columns=\"hourly_data_source\")\n", + "multi_source_subplants = (\n", + " eia923_allocated[[\"plant_id_eia\", \"subplant_id\", \"hourly_data_source\"]]\n", + " .drop_duplicates()\n", + " .drop(columns=\"hourly_data_source\")\n", + ")\n", "\n", "multi_source_subplants = multi_source_subplants[\n", - " multi_source_subplants.duplicated(\n", - " subset=[\"plant_id_eia\", \"subplant_id\"])]\n", + " multi_source_subplants.duplicated(subset=[\"plant_id_eia\", \"subplant_id\"])\n", + "]\n", "\n", - "multi_source_subplants = eia923_allocated.merge(multi_source_subplants, how=\"inner\", on=[\"plant_id_eia\", \"subplant_id\"])\n" + "multi_source_subplants = eia923_allocated.merge(\n", + " multi_source_subplants, how=\"inner\", on=[\"plant_id_eia\", \"subplant_id\"]\n", + ")" ] }, { @@ -126,7 +155,15 @@ "outputs": [], "source": [ "# what percent of the total EIA-923 data comes from subplants with annually-reported data and multiple sources?\n", - "multi_source_summary = (multi_source_subplants.groupby([\"respondent_frequency\"], dropna=False)[[\"fuel_consumed_mmbtu\", \"net_generation_mwh\",\"co2_mass_lb\"]].sum() / eia923_allocated[[\"fuel_consumed_mmbtu\", \"net_generation_mwh\",\"co2_mass_lb\"]].sum() * 100)\n", + "multi_source_summary = (\n", + " multi_source_subplants.groupby([\"respondent_frequency\"], dropna=False)[\n", + " [\"fuel_consumed_mmbtu\", \"net_generation_mwh\", \"co2_mass_lb\"]\n", + " ].sum()\n", + " / eia923_allocated[\n", + " [\"fuel_consumed_mmbtu\", \"net_generation_mwh\", \"co2_mass_lb\"]\n", + " ].sum()\n", + " * 100\n", + ")\n", "multi_source_summary.loc[\"Total Percent\"] = multi_source_summary.sum()\n", "multi_source_summary" ] @@ -137,7 +174,9 @@ "metadata": {}, "outputs": [], "source": [ - "multi_source_summary.loc[\"A\",:].rename(\"% of output data mixing CEMS and annually-reported EIA data\")" + "multi_source_summary.loc[\"A\", :].rename(\n", + " \"% of output data mixing CEMS and annually-reported EIA data\"\n", + ")" ] }, { @@ -146,7 +185,26 @@ "metadata": {}, "outputs": [], "source": [ - "pd.concat([pd.DataFrame(data_from_annual.loc[\"A\",:].rename(\"% of EIA-923 input data from EIA annual reporters\").round(2)).T, pd.DataFrame(annual_eia_used.loc[\"A\",:].rename(\"% of output data from EIA annual reporters\").round(2)).T, pd.DataFrame(multi_source_summary.loc[\"A\",:].rename(\"% of output data mixing CEMS and annually-reported EIA data\").round(2)).T], axis=0)" + "pd.concat(\n", + " [\n", + " pd.DataFrame(\n", + " data_from_annual.loc[\"A\", :]\n", + " .rename(\"% of EIA-923 input data from EIA annual reporters\")\n", + " .round(2)\n", + " ).T,\n", + " pd.DataFrame(\n", + " annual_eia_used.loc[\"A\", :]\n", + " .rename(\"% of output data from EIA annual reporters\")\n", + " .round(2)\n", + " ).T,\n", + " pd.DataFrame(\n", + " multi_source_summary.loc[\"A\", :]\n", + " .rename(\"% of output data mixing CEMS and annually-reported EIA data\")\n", + " .round(2)\n", + " ).T,\n", + " ],\n", + " axis=0,\n", + ")" ] } ], diff --git a/notebooks/explore_data/explore_intermediate_outputs.ipynb b/notebooks/explore_data/explore_intermediate_outputs.ipynb index e76796cd..ac41bb30 100644 --- a/notebooks/explore_data/explore_intermediate_outputs.ipynb +++ b/notebooks/explore_data/explore_intermediate_outputs.ipynb @@ -14,7 +14,8 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "from column_checks import get_dtypes\n", "from filepaths import *\n", @@ -40,11 +41,30 @@ "year = 2020\n", "path_prefix = f\"{year}/\"\n", "\n", - "cems = pd.read_csv(outputs_folder(f\"{path_prefix}/cems_subplant_{year}.csv\"), dtype=get_dtypes(), parse_dates=['datetime_utc', 'report_date'])\n", - "partial_cems_plant = pd.read_csv(outputs_folder(f\"{path_prefix}/partial_cems_plant_{year}.csv\"), dtype=get_dtypes(), parse_dates=['datetime_utc', 'report_date'])\n", - "partial_cems_subplant = pd.read_csv(outputs_folder(f\"{path_prefix}/partial_cems_subplant_{year}.csv\"), dtype=get_dtypes(), parse_dates=['datetime_utc', 'report_date'])\n", - "eia923_allocated = pd.read_csv(outputs_folder(f\"{path_prefix}/eia923_allocated_{year}.csv\"), dtype=get_dtypes(), parse_dates=['report_date'])\n", - "plant_attributes = pd.read_csv(outputs_folder(f\"{path_prefix}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes())" + "cems = pd.read_csv(\n", + " outputs_folder(f\"{path_prefix}/cems_subplant_{year}.csv\"),\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", + "partial_cems_plant = pd.read_csv(\n", + " outputs_folder(f\"{path_prefix}/partial_cems_plant_{year}.csv\"),\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", + "partial_cems_subplant = pd.read_csv(\n", + " outputs_folder(f\"{path_prefix}/partial_cems_subplant_{year}.csv\"),\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", + "eia923_allocated = pd.read_csv(\n", + " outputs_folder(f\"{path_prefix}/eia923_allocated_{year}.csv\"),\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"report_date\"],\n", + ")\n", + "plant_attributes = pd.read_csv(\n", + " outputs_folder(f\"{path_prefix}/plant_static_attributes_{year}.csv\"),\n", + " dtype=get_dtypes(),\n", + ")" ] }, { @@ -69,7 +89,7 @@ "source": [ "data = cems[cems[\"plant_id_eia\"] == 673]\n", "\n", - "data.groupby([\"plant_id_eia\",\"unitid\",\"report_date\"]).sum()" + "data.groupby([\"plant_id_eia\", \"unitid\", \"report_date\"]).sum()" ] }, { @@ -100,7 +120,9 @@ "\n", "all_data = []\n", "for ba in os.listdir(results_folder(f\"2021/power_sector_data/{resolution}/us_units\")):\n", - " df = pd.read_csv(results_folder(f\"2021/power_sector_data/{resolution}/us_units/{ba}\"))\n", + " df = pd.read_csv(\n", + " results_folder(f\"2021/power_sector_data/{resolution}/us_units/{ba}\")\n", + " )\n", " df[\"ba_code\"] = ba.split(\".\")[0]\n", " all_data.append(df)\n", "\n", @@ -120,10 +142,13 @@ "all_data[\"nox_mass_lb_for_electricity\"] / all_data[\"net_generation_mwh\"]\n", "all_data[\"so2_mass_lb_for_electricity\"] / all_data[\"net_generation_mwh\"]\n", "\n", - "for pol in [\"co2\",\"nox\",\"so2\"]:\n", - " for fuel in [\"biomass\", \"geothermal\",\"waste\", \"other\"]:\n", - " calc = all_data.loc[fuel,f\"{pol}_mass_lb_for_electricity\"] / all_data.loc[\"total\",f\"{pol}_mass_lb_for_electricity\"]\n", - " print(f\"{pol} {fuel}: {calc}\")\n" + "for pol in [\"co2\", \"nox\", \"so2\"]:\n", + " for fuel in [\"biomass\", \"geothermal\", \"waste\", \"other\"]:\n", + " calc = (\n", + " all_data.loc[fuel, f\"{pol}_mass_lb_for_electricity\"]\n", + " / all_data.loc[\"total\", f\"{pol}_mass_lb_for_electricity\"]\n", + " )\n", + " print(f\"{pol} {fuel}: {calc}\")" ] }, { @@ -139,10 +164,21 @@ "metadata": {}, "outputs": [], "source": [ - "all_data[\"pctdiff\"] = (all_data.generated_co2_rate_lb_per_mwh_for_electricity_adjusted - all_data.generated_co2_rate_lb_per_mwh_for_electricity) / all_data.generated_co2_rate_lb_per_mwh_for_electricity\n", + "all_data[\"pctdiff\"] = (\n", + " all_data.generated_co2_rate_lb_per_mwh_for_electricity_adjusted\n", + " - all_data.generated_co2_rate_lb_per_mwh_for_electricity\n", + ") / all_data.generated_co2_rate_lb_per_mwh_for_electricity\n", "\n", "\n", - "all_data.loc[all_data[\"fuel_category\"] == \"total\", [\"ba_code\",\"pctdiff\",\"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\",\"generated_co2_rate_lb_per_mwh_for_electricity\"]].sort_values(by=\"pctdiff\").head(25)" + "all_data.loc[\n", + " all_data[\"fuel_category\"] == \"total\",\n", + " [\n", + " \"ba_code\",\n", + " \"pctdiff\",\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\",\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity\",\n", + " ],\n", + "].sort_values(by=\"pctdiff\").head(25)" ] } ], diff --git a/notebooks/explore_data/gens_not_in_cems.ipynb b/notebooks/explore_data/gens_not_in_cems.ipynb index fbc76b6b..8b08bac8 100644 --- a/notebooks/explore_data/gens_not_in_cems.ipynb +++ b/notebooks/explore_data/gens_not_in_cems.ipynb @@ -17,7 +17,8 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "import download_data\n", "import load_data\n", @@ -42,13 +43,32 @@ "outputs": [], "source": [ "# load inputs to function\n", - "cems = pd.read_csv(outputs_folder(f\"{path_prefix}/cems_subplant_{year}.csv\"), dtype=get_dtypes(), parse_dates=['datetime_utc', 'report_date'])\n", - "partial_cems_plant = pd.read_csv(outputs_folder(f\"{path_prefix}/partial_cems_plant_{year}.csv\"), dtype=get_dtypes(), parse_dates=['datetime_utc', 'report_date'])\n", - "partial_cems_subplant = pd.read_csv(outputs_folder(f\"{path_prefix}/partial_cems_subplant_{year}.csv\"), dtype=get_dtypes(), parse_dates=['datetime_utc', 'report_date'])\n", - "eia923_allocated = pd.read_csv(outputs_folder(f\"{path_prefix}/eia923_allocated_{year}.csv\"), dtype=get_dtypes(), parse_dates=['report_date'])\n", - "plant_attributes = pd.read_csv(outputs_folder(f\"{path_prefix}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes())\n", + "cems = pd.read_csv(\n", + " outputs_folder(f\"{path_prefix}/cems_subplant_{year}.csv\"),\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", + "partial_cems_plant = pd.read_csv(\n", + " outputs_folder(f\"{path_prefix}/partial_cems_plant_{year}.csv\"),\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", + "partial_cems_subplant = pd.read_csv(\n", + " outputs_folder(f\"{path_prefix}/partial_cems_subplant_{year}.csv\"),\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", + "eia923_allocated = pd.read_csv(\n", + " outputs_folder(f\"{path_prefix}/eia923_allocated_{year}.csv\"),\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"report_date\"],\n", + ")\n", + "plant_attributes = pd.read_csv(\n", + " outputs_folder(f\"{path_prefix}/plant_static_attributes_{year}.csv\"),\n", + " dtype=get_dtypes(),\n", + ")\n", "\n", - "# select eia only data \n", + "# select eia only data\n", "eia_only_data = eia923_allocated[\n", " (eia923_allocated[\"hourly_data_source\"] == \"eia\")\n", " & ~(eia923_allocated[\"fuel_consumed_mmbtu\"].isna())\n", @@ -84,7 +104,7 @@ " how=\"left\",\n", " on=\"plant_id_eia\",\n", " validate=\"m:1\",\n", - ")\n" + ")" ] }, { @@ -121,7 +141,9 @@ "metadata": {}, "outputs": [], "source": [ - "eia_caiso[\"nox_rate\"] = eia_caiso[\"nox_mass_lb_for_electricity\"] / eia_caiso[\"net_generation_mwh\"]\n", + "eia_caiso[\"nox_rate\"] = (\n", + " eia_caiso[\"nox_mass_lb_for_electricity\"] / eia_caiso[\"net_generation_mwh\"]\n", + ")\n", "eia_caiso[\"nox_rate\"] = eia_caiso[\"nox_rate\"].replace(np.inf, np.nan)" ] }, @@ -131,7 +153,12 @@ "metadata": {}, "outputs": [], "source": [ - "eia_caiso.groupby([\"prime_mover_code\",\"energy_source_code\",])[\"nox_mass_lb_for_electricity\"].sum()" + "eia_caiso.groupby(\n", + " [\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + " ]\n", + ")[\"nox_mass_lb_for_electricity\"].sum()" ] }, { @@ -177,7 +204,7 @@ "subplant_nameplate = gross_to_net_generation.calculate_subplant_nameplate_capacity(year)\n", "\n", "pudl_out = load_data.initialize_pudl_out(year)\n", - "gen_cap = pudl_out.gens_eia860()[[\"plant_id_eia\",\"generator_id\",\"capacity_mw\"]]" + "gen_cap = pudl_out.gens_eia860()[[\"plant_id_eia\", \"generator_id\", \"capacity_mw\"]]" ] }, { @@ -186,8 +213,12 @@ "metadata": {}, "outputs": [], "source": [ - "eia_cf = eia_only_data.merge(gen_cap, how=\"left\", on=[\"plant_id_eia\",\"generator_id\"], validate=\"m:1\")\n", - "eia_cf[\"capfac\"] = eia_cf.net_generation_mwh / (eia_cf.report_date.dt.days_in_month * 24 * eia_cf.capacity_mw)\n", + "eia_cf = eia_only_data.merge(\n", + " gen_cap, how=\"left\", on=[\"plant_id_eia\", \"generator_id\"], validate=\"m:1\"\n", + ")\n", + "eia_cf[\"capfac\"] = eia_cf.net_generation_mwh / (\n", + " eia_cf.report_date.dt.days_in_month * 24 * eia_cf.capacity_mw\n", + ")\n", "eia_cf.loc[eia_cf[\"capfac\"] > 1.2, \"capfac\"] = np.NaN\n", "eia_cf.loc[eia_cf[\"capfac\"] < 0, \"capfac\"] = np.NaN\n", "eia_cf" @@ -199,7 +230,9 @@ "metadata": {}, "outputs": [], "source": [ - "px.histogram(eia_cf, x=\"capfac\", nbins=15, histnorm=\"percent\", width=500).update_xaxes(dtick=0.05)" + "px.histogram(eia_cf, x=\"capfac\", nbins=15, histnorm=\"percent\", width=500).update_xaxes(\n", + " dtick=0.05\n", + ")" ] }, { @@ -208,10 +241,12 @@ "metadata": {}, "outputs": [], "source": [ - "cems_cf = cems.merge(subplant_nameplate, how=\"left\", on=[\"plant_id_eia\",\"subplant_id\"])\n", - "cems_cf = cems_cf.groupby([\"plant_id_eia\",\"subplant_id\"])[[\"net_generation_mwh\",\"capacity_mw\"]].sum()\n", + "cems_cf = cems.merge(subplant_nameplate, how=\"left\", on=[\"plant_id_eia\", \"subplant_id\"])\n", + "cems_cf = cems_cf.groupby([\"plant_id_eia\", \"subplant_id\"])[\n", + " [\"net_generation_mwh\", \"capacity_mw\"]\n", + "].sum()\n", "cems_cf = cems_cf[cems_cf[\"capacity_mw\"] > 0]\n", - "cems_cf['capfac'] = cems_cf['net_generation_mwh'] / cems_cf['capacity_mw']\n", + "cems_cf[\"capfac\"] = cems_cf[\"net_generation_mwh\"] / cems_cf[\"capacity_mw\"]\n", "cems_cf.loc[cems_cf[\"capfac\"] > 1.2, \"capfac\"] = np.NaN\n", "cems_cf.loc[cems_cf[\"capfac\"] < 0, \"capfac\"] = np.NaN\n", "cems_cf" @@ -223,7 +258,9 @@ "metadata": {}, "outputs": [], "source": [ - "px.histogram(cems_cf, x=\"capfac\", nbins=15, histnorm=\"percent\", width=500).update_xaxes(dtick=0.05)" + "px.histogram(cems_cf, x=\"capfac\", nbins=15, histnorm=\"percent\", width=500).update_xaxes(\n", + " dtick=0.05\n", + ")" ] } ], diff --git a/notebooks/explore_data/manually_import_uncontrolled_emission_factors.ipynb b/notebooks/explore_data/manually_import_uncontrolled_emission_factors.ipynb index 89945fde..c288b336 100644 --- a/notebooks/explore_data/manually_import_uncontrolled_emission_factors.ipynb +++ b/notebooks/explore_data/manually_import_uncontrolled_emission_factors.ipynb @@ -40,31 +40,31 @@ " https://catalystcoop-pudl.readthedocs.io/en/latest/data_dictionaries/codes_and_labels.html\n", " \"\"\"\n", " column_names = [\n", - " 'readable_fuel_name',\n", - " 'eia_fuel_code',\n", - " 'source_and_tables',\n", - " 'emissions_units',\n", - " 'cyclone_firing_boiler',\n", - " 'fluidized_bed_firing_boiler',\n", - " 'stoker_boiler',\n", - " 'tangential_firing_boiler',\n", - " 'all_other_boiler_types',\n", - " 'combustion_turbine',\n", - " 'internal_combustion_engine'\n", + " \"readable_fuel_name\",\n", + " \"eia_fuel_code\",\n", + " \"source_and_tables\",\n", + " \"emissions_units\",\n", + " \"cyclone_firing_boiler\",\n", + " \"fluidized_bed_firing_boiler\",\n", + " \"stoker_boiler\",\n", + " \"tangential_firing_boiler\",\n", + " \"all_other_boiler_types\",\n", + " \"combustion_turbine\",\n", + " \"internal_combustion_engine\",\n", " ]\n", "\n", " column_dtypes = {\n", - " 'readable_fuel_name': 'str',\n", - " 'eia_fuel_code': 'str',\n", - " 'source_and_tables': 'str',\n", - " 'emissions_units': 'str',\n", + " \"readable_fuel_name\": \"str\",\n", + " \"eia_fuel_code\": \"str\",\n", + " \"source_and_tables\": \"str\",\n", + " \"emissions_units\": \"str\",\n", " }\n", - " \n", + "\n", " # Every other column is a float.\n", " for column_name in column_names:\n", " if column_name not in column_dtypes:\n", - " column_dtypes[column_name] = 'float64'\n", - " \n", + " column_dtypes[column_name] = \"float64\"\n", + "\n", " # NOTE(milo): Header starts on 2 for this one!\n", " df = pd.read_excel(\n", " io=path_to_xlsx,\n", @@ -89,35 +89,35 @@ "def load_nox_uncontrolled_efs(path_to_xlsx):\n", " \"\"\"\n", " https://catalystcoop-pudl.readthedocs.io/en/latest/data_dictionaries/codes_and_labels.html\n", - " \"\"\" \n", + " \"\"\"\n", " column_names = [\n", - " 'readable_fuel_name',\n", - " 'eia_fuel_code',\n", - " 'source_and_tables',\n", - " 'emissions_units',\n", - " 'cyclone_firing_boiler',\n", - " 'fluidized_bed_firing_boiler',\n", - " 'stoker_boiler',\n", - " 'tangential_firing_boiler_dry_bottom',\n", - " 'tangential_firing_boiler_wet_bottom',\n", - " 'all_other_boiler_types_dry_bottom',\n", - " 'all_other_boiler_types_wet_bottom',\n", - " 'combustion_turbine',\n", - " 'internal_combustion_engine'\n", + " \"readable_fuel_name\",\n", + " \"eia_fuel_code\",\n", + " \"source_and_tables\",\n", + " \"emissions_units\",\n", + " \"cyclone_firing_boiler\",\n", + " \"fluidized_bed_firing_boiler\",\n", + " \"stoker_boiler\",\n", + " \"tangential_firing_boiler_dry_bottom\",\n", + " \"tangential_firing_boiler_wet_bottom\",\n", + " \"all_other_boiler_types_dry_bottom\",\n", + " \"all_other_boiler_types_wet_bottom\",\n", + " \"combustion_turbine\",\n", + " \"internal_combustion_engine\",\n", " ]\n", - " \n", + "\n", " column_dtypes = {\n", - " 'readable_fuel_name': 'str',\n", - " 'eia_fuel_code': 'str',\n", - " 'source_and_tables': 'str',\n", - " 'emissions_units': 'str',\n", + " \"readable_fuel_name\": \"str\",\n", + " \"eia_fuel_code\": \"str\",\n", + " \"source_and_tables\": \"str\",\n", + " \"emissions_units\": \"str\",\n", " }\n", "\n", " # Every other column is a float.\n", " for column_name in column_names:\n", " if column_name not in column_dtypes:\n", - " column_dtypes[column_name] = 'float64'\n", - " \n", + " column_dtypes[column_name] = \"float64\"\n", + "\n", " # NOTE(milo): Header starts on 3 for this one!\n", " df = pd.read_excel(\n", " io=path_to_xlsx,\n", @@ -139,9 +139,13 @@ "metadata": {}, "outputs": [], "source": [ - "base_folder = filepaths.manual_folder('eia_electric_power_annual')\n", - "so2_uncontrolled_efs_path = os.path.join(base_folder, 'epa_a_01_so2_uncontrolled_efs.xlsx')\n", - "nox_uncontrolled_efs_path = os.path.join(base_folder, 'epa_a_02_nox_uncontrolled_efs.xlsx')" + "base_folder = filepaths.manual_folder(\"eia_electric_power_annual\")\n", + "so2_uncontrolled_efs_path = os.path.join(\n", + " base_folder, \"epa_a_01_so2_uncontrolled_efs.xlsx\"\n", + ")\n", + "nox_uncontrolled_efs_path = os.path.join(\n", + " base_folder, \"epa_a_02_nox_uncontrolled_efs.xlsx\"\n", + ")" ] }, { @@ -165,7 +169,7 @@ "def make_so2_emission_factor_rows(input_df):\n", " \"\"\"\n", " Convert the EIA emission factors excel format into the one we store in emission_factors_for_so2.csv.\n", - " \n", + "\n", " Columns:\n", " prime_mover_code,\n", " energy_source_code,\n", @@ -176,73 +180,72 @@ " multiply_by_sulfur_content\n", " \"\"\"\n", " min_column_idx = 4\n", - " \n", + "\n", " map_eia_units_to_ours = {\n", - " 'Lbs per MG': {\n", - " 'emission_factor_numerator': 'lb',\n", - " 'emission_factor_denominator': 'thousand gallons',\n", + " \"Lbs per MG\": {\n", + " \"emission_factor_numerator\": \"lb\",\n", + " \"emission_factor_denominator\": \"thousand gallons\",\n", + " },\n", + " \"Lbs per MMCF\": {\n", + " \"emission_factor_numerator\": \"lb\",\n", + " \"emission_factor_denominator\": \"Mcf\",\n", " },\n", - " 'Lbs per MMCF': {\n", - " 'emission_factor_numerator': 'lb',\n", - " 'emission_factor_denominator': 'Mcf',\n", + " \"Lbs per ton\": {\n", + " \"emission_factor_numerator\": \"lb\",\n", + " \"emission_factor_denominator\": \"short ton\",\n", " },\n", - " 'Lbs per ton': {\n", - " 'emission_factor_numerator': 'lb',\n", - " 'emission_factor_denominator': 'short ton',\n", - " }\n", " }\n", - " \n", + "\n", " map_eia_combustion_system_to_ours = {\n", - " 'cyclone_firing_boiler' : {\n", - " 'prime_mover_code': TODO\n", - " 'boiler_bottom_type': 'N/A',\n", - " 'boiler_firing_type': 'STOKER',\n", - " 'multiple_by_sulfur_content': 0,\n", + " \"cyclone_firing_boiler\": {\n", + " \"prime_mover_code\": \"TODO\",\n", + " \"boiler_bottom_type\": \"N/A\",\n", + " \"boiler_firing_type\": \"STOKER\",\n", + " \"multiple_by_sulfur_content\": 0,\n", " },\n", - " 'fluidized_bed_firing_boiler' : {\n", - " 'prime_mover_code': TODO\n", - " 'boiler_bottom_type': 'N/A',\n", - " 'boiler_firing_type': 'FLUIDIZED',\n", - " 'multiple_by_sulfur_content': 0,\n", + " \"fluidized_bed_firing_boiler\": {\n", + " \"prime_mover_code\": \"TODO\",\n", + " \"boiler_bottom_type\": \"N/A\",\n", + " \"boiler_firing_type\": \"FLUIDIZED\",\n", + " \"multiple_by_sulfur_content\": 0,\n", " },\n", - " 'stoker_boiler' : {\n", - " 'prime_mover_code': 'ST' # Steam\n", - " 'boiler_bottom_type': 'N/A',\n", - " 'boiler_firing_type': 'STOKER',\n", - " 'multiple_by_sulfur_content': 0,\n", + " \"stoker_boiler\": {\n", + " \"prime_mover_code\": \"ST\", # Steam\n", + " \"boiler_bottom_type\": \"N/A\",\n", + " \"boiler_firing_type\": \"STOKER\",\n", + " \"multiple_by_sulfur_content\": 0,\n", " },\n", - " 'tangential_firing_boiler' : {\n", - " 'prime_mover_code': 'ST' # Steam\n", - " 'boiler_bottom_type': 'N/A',\n", - " 'boiler_firing_type': 'TANGENTIAL',\n", - " 'multiple_by_sulfur_content': 0,\n", + " \"tangential_firing_boiler\": {\n", + " \"prime_mover_code\": \"ST\", # Steam\n", + " \"boiler_bottom_type\": \"N/A\",\n", + " \"boiler_firing_type\": \"TANGENTIAL\",\n", + " \"multiple_by_sulfur_content\": 0,\n", " },\n", - " 'all_other_boiler_types' : {\n", - " 'prime_mover_code': 'UNK',\n", - " 'boiler_firing_type': 'N/A',\n", - " 'multiply_by_sulfur_content': 0 \n", + " \"all_other_boiler_types\": {\n", + " \"prime_mover_code\": \"UNK\",\n", + " \"boiler_firing_type\": \"N/A\",\n", + " \"multiply_by_sulfur_content\": 0,\n", " },\n", - " 'combustion_turbine' : {\n", - " 'prime_mover_code': 'GT', # Gas combustion turbine.\n", - " 'boiler_firing_type': 'N/A',\n", - " 'multiply_by_sulfur_content': 0\n", + " \"combustion_turbine\": {\n", + " \"prime_mover_code\": \"GT\", # Gas combustion turbine.\n", + " \"boiler_firing_type\": \"N/A\",\n", + " \"multiply_by_sulfur_content\": 0,\n", + " },\n", + " \"internal_combustion_engine\": {\n", + " \"prime_mover_code\": \"IC\",\n", + " \"boiler_firing_type\": \"N/A\",\n", + " \"multiply_by_sulfur_content\": 0,\n", " },\n", - " 'internal_combustion_engine' : {\n", - " 'prime_mover_code': 'IC',\n", - " 'boiler_firing_type': 'N/A',\n", - " 'multiply_by_sulfur_content': 0\n", - " }\n", " }\n", - " \n", + "\n", " for i in range(len(input_df)):\n", " row = input_df.iloc[i]\n", - " units = row['emissions_units'].replace(' **', '') # Remove asterisks.\n", + " units = row[\"emissions_units\"].replace(\" **\", \"\") # Remove asterisks.\n", " print(units)\n", " mapped_units_dict = map_eia_units_to_ours[units]\n", " for colname in input_df.columns[min_column_idx:]:\n", " emission_factor = row[colname]\n", - " print(colname, ':', emission_factor)\n", - " " + " print(colname, \":\", emission_factor)" ] }, { @@ -266,7 +269,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.10.4 ('open_grid_emissions')", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -280,7 +283,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9 | packaged by conda-forge | (main, Jan 11 2023, 15:15:40) [MSC v.1916 64 bit (AMD64)]" + "version": "3.10.4" }, "vscode": { "interpreter": { diff --git a/notebooks/explore_methods/calculate_residual_net_generation.ipynb b/notebooks/explore_methods/calculate_residual_net_generation.ipynb index a7d3e415..f0373380 100644 --- a/notebooks/explore_methods/calculate_residual_net_generation.ipynb +++ b/notebooks/explore_methods/calculate_residual_net_generation.ipynb @@ -1,835 +1,841 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Cleaning of 930, analyze how cleaning affects residual profile" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# data source https://gridemissions.s3.us-east-2.amazonaws.com/EBA_elec.csv.gz\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "\n", - "import plotly.express as px\n", - "import plotly.graph_objects as go\n", - "\n", - "import datetime as dt\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%reload_ext autoreload\n", - "%autoreload 2\n", - "\n", - "# Tell python where to look for modules. \n", - "# Depending on how your jupyter handles working directories, this may not be needed.\n", - "import sys\n", - "sys.path.append('../../open-grid-emissions/')\n", - "\n", - "from src.visualization import day_hour_heatmap\n", - "from src.eia930 import fuel_code_map, reformat_chalendar, load_chalendar, load_chalendar_for_pipeline\n", - "from src.download_data import download_chalendar_files\n", - "from src.data_cleaning import distribute_monthly_eia_data_to_hourly\n", - "from src.impute_hourly_profiles import aggregate_for_residual, calculate_residual" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "year = 2020\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Download data if not exists\n", - "download_chalendar_files()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "original = load_chalendar_for_pipeline(\n", - " \"../data/eia930/chalendar/EBA_adjusted_rolling.csv\", year=year\n", - ")\n", - "original.head(5)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cleaned = load_chalendar_for_pipeline(\n", - " \"../data/eia930/chalendar/EBA_adjusted_elec.csv\", year=year\n", - ")\n", - "cleaned.head(5)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Name column same as CEMS. TODO: make eia930 output use this name\n", - "cleaned = cleaned.rename(columns={\"datetime_utc\": \"datetime_utc\"})\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# load hourly CEMS data outputted from main data pipeline\n", - "cems = pd.read_csv(\n", - " f\"../data/outputs/cems_{year}.csv\",\n", - " parse_dates=[\"datetime_utc\"],\n", - ")\n", - "cems.head(5)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Aggregate CEMS data and merge with EIA-930 data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# # combine original and cleaned EIA-930 data\n", - "# combined_data = cleaned.merge(\n", - "# original[[\"ba_code\", \"fuel_category\", \"datetime_utc\", \"net_generation_mwh_930\"]],\n", - "# how=\"left\",\n", - "# on=[\"ba_code\", \"fuel_category\", \"datetime_utc\"],\n", - "# suffixes=(\"_clean\", \"_orig\"),\n", - "# )\n", - "# combined_data\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Load plant attributes (including BA codes)\n", - "plant_attributes = pd.read_csv(\"../data/outputs/plant_static_attributes.csv\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plant_attributes.head()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cems = cems.merge(plant_attributes, how=\"left\", on=\"plant_id_eia\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "aggregate_for_residual(cems, \"datetime_utc\", \"ba_code_physical\", transmission=True)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# perform different groupby operations so that we can compare different ways of aggregating the cems data\n", - "\n", - "# aggregate all generation by commercial BA\n", - "cems_bac_all = (\n", - " cems.groupby([\"ba_code\", \"fuel_category_eia930\", \"datetime_utc\"])[\n", - " \"net_generation_mwh\"\n", - " ]\n", - " .sum()\n", - " .reset_index()\n", - " .rename(\n", - " columns={\n", - " \"fuel_category_eia930\": \"fuel_category\",\n", - " \"net_generation_mwh\": \"net_generation_mwh_bac_all\",\n", - " }\n", - " )\n", - ")\n", - "\n", - "# aggregate all generation by physical BA\n", - "cems_bap_all = (\n", - " cems.groupby([\"ba_code_physical\", \"fuel_category_eia930\", \"datetime_utc\"])[\n", - " \"net_generation_mwh\"\n", - " ]\n", - " .sum()\n", - " .reset_index()\n", - " .rename(\n", - " columns={\n", - " \"fuel_category_eia930\": \"fuel_category\",\n", - " \"ba_code_physical\": \"ba_code\",\n", - " \"net_generation_mwh\": \"net_generation_mwh_bap_all\",\n", - " }\n", - " )\n", - ")\n", - "\n", - "# Aggregate transmission-connected generation by commercial BA\n", - "cems_bac_trans = (\n", - " cems[cems[\"distribution_flag\"] is False]\n", - " .groupby([\"ba_code\", \"fuel_category_eia930\", \"datetime_utc\"])[\"net_generation_mwh\"]\n", - " .sum()\n", - " .reset_index()\n", - " .rename(\n", - " columns={\n", - " \"fuel_category_eia930\": \"fuel_category\",\n", - " \"net_generation_mwh\": \"net_generation_mwh_bac_trans\",\n", - " }\n", - " )\n", - ")\n", - "\n", - "# Aggregate transmission-connected generation by physical BA\n", - "cems_bap_trans = (\n", - " cems[cems[\"distribution_flag\"] == False]\n", - " .groupby([\"ba_code_physical\", \"fuel_category_eia930\", \"datetime_utc\"])[\n", - " \"net_generation_mwh\"\n", - " ]\n", - " .sum()\n", - " .reset_index()\n", - " .rename(\n", - " columns={\n", - " \"fuel_category_eia930\": \"fuel_category\",\n", - " \"ba_code_physical\": \"ba_code\",\n", - " \"net_generation_mwh\": \"net_generation_mwh_bap_trans\",\n", - " }\n", - " )\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# merge the aggregated data into the EIA data\n", - "combined_data = cleaned.merge(\n", - " cems_bac_all, how=\"left\", on=[\"ba_code\", \"fuel_category\", \"datetime_utc\"]\n", - ").fillna(0)\n", - "combined_data = combined_data.merge(\n", - " cems_bap_all, how=\"left\", on=[\"ba_code\", \"fuel_category\", \"datetime_utc\"]\n", - ").fillna(0)\n", - "combined_data = combined_data.merge(\n", - " cems_bac_trans, how=\"left\", on=[\"ba_code\", \"fuel_category\", \"datetime_utc\"]\n", - ").fillna(0)\n", - "combined_data = combined_data.merge(\n", - " cems_bap_trans, how=\"left\", on=[\"ba_code\", \"fuel_category\", \"datetime_utc\"]\n", - ").fillna(0)\n", - "combined_data\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cleaned\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# only keep rows where local datetime is in the current year\n", - "combined_data = combined_data[\n", - " combined_data[\"datetime_local\"].apply(lambda x: x.year) == year\n", - "]\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Evaluate BA mappings\n", - "\n", - "Mapping options: \n", - "Physical or commercial BA; include or exclude distribution-connected generation \n", - "\n", - "Metric: 923 data aggregated to BA should be close to 930 data aggregated to month. \n", - "For each BA, which aggregation metric minimizes difference? \n", - "How different are the aggreagtion metrics? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "eia923 = pd.read_csv(f\"../data/outputs/eia923_allocated_{year}.csv\")\n", - "eia923.report_date = pd.to_datetime(\n", - " eia923.report_date\n", - ") # TODO why is this not a date already?\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "eia923 = eia923.merge(plant_attributes, how=\"left\", on=\"plant_id_eia\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "eia930_agg = (\n", - " cleaned.groupby([\"ba_code\", \"fuel_category\", \"report_date\"]).sum().reset_index()\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "eia923.head()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "eia930_agg.head()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "eia923_agg = eia930_agg.copy()\n", - "# aggregate all generation by commercial BA\n", - "for ba_key in [\"ba_code\", \"ba_code_physical\"]:\n", - " for transmission_only in [\"transmission\", \"all\"]:\n", - " transmission_key = transmission_only == \"transmission\"\n", - " aggregated_gen = aggregate_for_residual(\n", - " eia923, time_key=\"report_date\", ba_key=ba_key, transmission=transmission_key\n", - " )\n", - " aggregated_gen.rename(\n", - " columns={\"net_generation_mwh\": f\"mwh_{ba_key}_{transmission_only}\"},\n", - " inplace=True,\n", - " )\n", - " aggregated_gen[f\"difference_{ba_key}_{transmission_only}\"] = (\n", - " eia923_agg[\"net_generation_mwh_930\"]\n", - " - aggregated_gen[f\"mwh_{ba_key}_{transmission_only}\"]\n", - " )\n", - " eia923_agg = eia923_agg.merge(\n", - " aggregated_gen, how=\"left\", on=[\"ba_code\", \"fuel_category\", \"report_date\"]\n", - " )\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "eia923_agg.head()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fig = px.histogram(\n", - " eia923_agg,\n", - " x=[\n", - " \"difference_ba_code_transmission\",\n", - " \"difference_ba_code_all\",\n", - " \"difference_ba_code_physical_transmission\",\n", - " \"difference_ba_code_physical_all\",\n", - " ],\n", - ")\n", - "\n", - "# Overlay both histograms\n", - "fig.update_layout(barmode=\"overlay\")\n", - "# Reduce opacity to see both histograms\n", - "fig.update_traces(opacity=0.25)\n", - "fig.show()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Visualize net generation data from each source in a single BA\n", - "Only visualize non-renewable data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ba = \"MISO\"\n", - "\n", - "data_to_visualize = combined_data[\n", - " (combined_data[\"ba_code\"] == ba)\n", - " & (~combined_data[\"fuel_category\"].isin([\"hydro\", \"solar\", \"wind\"]))\n", - "]\n", - "\n", - "px.line(\n", - " data_to_visualize,\n", - " x=\"datetime_local\",\n", - " y=[\n", - " \"net_generation_mwh_930_clean\",\n", - " \"net_generation_mwh_930_orig\",\n", - " \"net_generation_mwh_bac_all\",\n", - " \"net_generation_mwh_bap_all\",\n", - " \"net_generation_mwh_bac_trans\",\n", - " \"net_generation_mwh_bap_trans\",\n", - " ],\n", - " facet_col=\"fuel_category\",\n", - " height=1000,\n", - " facet_col_wrap=1,\n", - ").update_yaxes(matches=None)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Calculate the residual based on a single CEMS aggregation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# for now, let's pick a single cems aggregation to use to calculate a residual\n", - "cems_data_column = \"net_generation_mwh_bac_all\"\n", - "\n", - "combined_data[\"residual\"] = (\n", - " combined_data[\"net_generation_mwh_930_clean\"] - combined_data[cems_data_column]\n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Visualize residual for the BA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "data_to_visualize = combined_data[\n", - " (combined_data[\"ba_code\"] == ba)\n", - " & (~combined_data[\"fuel_category\"].isin([\"hydro\", \"solar\", \"wind\"]))\n", - "]\n", - "\n", - "px.line(\n", - " data_to_visualize,\n", - " x=\"datetime_local\",\n", - " y=[\"net_generation_mwh_930_clean\", cems_data_column, \"residual\"],\n", - " facet_col=\"fuel_category\",\n", - " height=1000,\n", - " facet_col_wrap=1,\n", - ").update_yaxes(matches=None)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Test Scaling Strategy\n", - "If the residual is ever negative, we want to scale the cems net generation data to always be less than or equal to the 930 net generation. \n", - "\n", - "To do this, we'll try scaling the data as a percentage:\n", - "1. For each hour, calculate the ratio between 930 NG and CEMS NG.\n", - "2. For each BA-fuel, find the minimum ratio. If the minimum ratio is >= 1, it means that 930 is always greater than CEMS and doesn't need to be scaled. For any BA-fuels where the ratio is < 1, we will use this as a scaling factor to scale the CEMS data such that the scaled data is always <= the 930 data\n", - "3. Multiply all hourly CEMS values by the scaling factor" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# only keep data where the cems data is greater than zero\n", - "scaling_factors = combined_data.copy()[combined_data[cems_data_column] != 0]\n", - "\n", - "# calculate the ratio of 930 net generation to cems net generation\n", - "# if correct, ratio should be >=1\n", - "scaling_factors[\"scaling_factor\"] = (\n", - " scaling_factors[\"net_generation_mwh_930_clean\"] / scaling_factors[cems_data_column]\n", - ")\n", - "\n", - "# find the minimum ratio for each ba-fuel\n", - "scaling_factors = (\n", - " scaling_factors.groupby([\"ba_code\", \"fuel_category\"])[\"scaling_factor\"]\n", - " .min()\n", - " .reset_index()\n", - ")\n", - "scaling_factors\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# merge the scaling factor into the combined data\n", - "# for any BA-fuels without a scaling factor, fill with 1 (scale to 100% of the origina data)\n", - "combined_data = combined_data.merge(\n", - " scaling_factors, how=\"left\", on=[\"ba_code\", \"fuel_category\"]\n", - ").fillna(1)\n", - "\n", - "# calculate the scaled cems data\n", - "combined_data[\"cems_scaled\"] = (\n", - " combined_data[cems_data_column] * combined_data[\"scaling_factor\"]\n", - ")\n", - "\n", - "# calculate a scaled residual\n", - "combined_data[\"residual_scaled\"] = (\n", - " combined_data[\"net_generation_mwh_930_clean\"] - combined_data[\"cems_scaled\"]\n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Plot scaled residuals" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ba = \"PJM\"\n", - "\n", - "data_to_visualize = combined_data[\n", - " (combined_data[\"ba_code\"] == ba)\n", - " & (~combined_data[\"fuel_category\"].isin([\"hydro\", \"solar\", \"wind\"]))\n", - "]\n", - "\n", - "px.line(\n", - " data_to_visualize,\n", - " x=\"datetime_local\",\n", - " y=[\n", - " \"net_generation_mwh_930_clean\",\n", - " cems_data_column,\n", - " \"cems_scaled\",\n", - " \"residual\",\n", - " \"residual_scaled\",\n", - " ],\n", - " facet_col=\"fuel_category\",\n", - " height=1000,\n", - " facet_col_wrap=1,\n", - ").update_yaxes(matches=None)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "combined_data = combined_data.reset_index()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# broken\n", - "\n", - "ba = \"MISO\"\n", - "fuel = \"natural_gas\"\n", - "\n", - "data_to_visualize = combined_data.copy()[\n", - " (combined_data[\"ba_code\"] == ba) & (combined_data[\"fuel_category\"] == fuel)\n", - "]\n", - "data_to_visualize[\"datetime_local\"] = pd.to_datetime(\n", - " data_to_visualize[\"datetime_local\"]\n", - ")\n", - "data_to_visualize[\"date\"] = data_to_visualize[\"datetime_local\"].dt.date\n", - "data_to_visualize[\"hour\"] = data_to_visualize[\"datetime_local\"].dt.hour\n", - "\n", - "# data_to_visualize = data_to_visualize.pivot(index='hour', columns='date', values='residual_scaled')\n", - "\n", - "# px.imshow(data_to_visualize, color_continuous_scale=\"RdBu\", width=1000, height=400, color_continuous_midpoint=0,)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Export the profile" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "data_to_export = combined_data[\n", - " [\n", - " \"ba_code\",\n", - " \"fuel_category\",\n", - " \"datetime_utc\",\n", - " \"datetime_local\",\n", - " \"report_date\",\n", - " \"residual_scaled\",\n", - " ]\n", - "]\n", - "data_to_export.to_csv(\"../data/output/residual_profiles.csv\", index=False)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Evaluate profile quality\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "with open(\"../data/outputs/residual_profiles.csv\") as f:\n", - " line = f.readline()\n", - " print(line.split(\",\"))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cems.head()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Produced by data_pipeline\n", - "eia = pd.read_csv(\"../data/output/eia923_for_residual.csv\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Produced by plant_class_differences\n", - "# TODO use output plant data to find smallest plants after cleaning -- some of these are in \"no cems\" data categories\n", - "validation_plants = pd.read_csv(\"../data/output/validation_plants.csv\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "to_distribute = eia[eia.plant_id_eia.isin(validation_plants.plant_id_eia)]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "to_distribute.head()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "distributed = distribute_monthly_eia_data_to_hourly(\n", - " to_distribute, combined_data, \"residual_scaled\"\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cleaned = load_chalendar_for_pipeline(\n", - " \"../data/eia930/chalendar/EBA_adjusted_elec.csv\", year=year\n", - ")\n", - "cems = pd.read_csv(\n", - " f\"../data/outputs/cems_{year}.csv\",\n", - " parse_dates=[\"datetime_utc\"],\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cleaned = cleaned.rename(columns={\"datetime_utc\": \"datetime_utc\"})\n", - "cems = cems.rename(columns={\"datetime_utc\": \"datetime_utc\"})\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plant_attributes = pd.read_csv(\"../data/outputs/plant_static_attributes.csv\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cleaned.head()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "calculate_residual(cems, cleaned, plant_attributes, 2020)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cems\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.10.5 ('hourly_egrid')", - "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.5" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "4103f3cd497821eca917ea303dbe10c590d787eb7d2dc3fd4e15dec0356e7931" - } - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Cleaning of 930, analyze how cleaning affects residual profile" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# data source https://gridemissions.s3.us-east-2.amazonaws.com/EBA_elec.csv.gz\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "import plotly.express as px\n", + "import plotly.graph_objects as go\n", + "\n", + "import datetime as dt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2\n", + "\n", + "# Tell python where to look for modules.\n", + "# Depending on how your jupyter handles working directories, this may not be needed.\n", + "import sys\n", + "\n", + "sys.path.append(\"../../open-grid-emissions/\")\n", + "\n", + "from src.visualization import day_hour_heatmap\n", + "from src.eia930 import (\n", + " fuel_code_map,\n", + " reformat_chalendar,\n", + " load_chalendar,\n", + " load_chalendar_for_pipeline,\n", + ")\n", + "from src.download_data import download_chalendar_files\n", + "from src.data_cleaning import distribute_monthly_eia_data_to_hourly\n", + "from src.impute_hourly_profiles import aggregate_for_residual, calculate_residual" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "year = 2020" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Download data if not exists\n", + "download_chalendar_files()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "original = load_chalendar_for_pipeline(\n", + " \"../data/eia930/chalendar/EBA_adjusted_rolling.csv\", year=year\n", + ")\n", + "original.head(5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cleaned = load_chalendar_for_pipeline(\n", + " \"../data/eia930/chalendar/EBA_adjusted_elec.csv\", year=year\n", + ")\n", + "cleaned.head(5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Name column same as CEMS. TODO: make eia930 output use this name\n", + "cleaned = cleaned.rename(columns={\"datetime_utc\": \"datetime_utc\"})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# load hourly CEMS data outputted from main data pipeline\n", + "cems = pd.read_csv(\n", + " f\"../data/outputs/cems_{year}.csv\",\n", + " parse_dates=[\"datetime_utc\"],\n", + ")\n", + "cems.head(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Aggregate CEMS data and merge with EIA-930 data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# # combine original and cleaned EIA-930 data\n", + "# combined_data = cleaned.merge(\n", + "# original[[\"ba_code\", \"fuel_category\", \"datetime_utc\", \"net_generation_mwh_930\"]],\n", + "# how=\"left\",\n", + "# on=[\"ba_code\", \"fuel_category\", \"datetime_utc\"],\n", + "# suffixes=(\"_clean\", \"_orig\"),\n", + "# )\n", + "# combined_data\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load plant attributes (including BA codes)\n", + "plant_attributes = pd.read_csv(\"../data/outputs/plant_static_attributes.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plant_attributes.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems = cems.merge(plant_attributes, how=\"left\", on=\"plant_id_eia\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "aggregate_for_residual(cems, \"datetime_utc\", \"ba_code_physical\", transmission=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# perform different groupby operations so that we can compare different ways of aggregating the cems data\n", + "\n", + "# aggregate all generation by commercial BA\n", + "cems_bac_all = (\n", + " cems.groupby([\"ba_code\", \"fuel_category_eia930\", \"datetime_utc\"])[\n", + " \"net_generation_mwh\"\n", + " ]\n", + " .sum()\n", + " .reset_index()\n", + " .rename(\n", + " columns={\n", + " \"fuel_category_eia930\": \"fuel_category\",\n", + " \"net_generation_mwh\": \"net_generation_mwh_bac_all\",\n", + " }\n", + " )\n", + ")\n", + "\n", + "# aggregate all generation by physical BA\n", + "cems_bap_all = (\n", + " cems.groupby([\"ba_code_physical\", \"fuel_category_eia930\", \"datetime_utc\"])[\n", + " \"net_generation_mwh\"\n", + " ]\n", + " .sum()\n", + " .reset_index()\n", + " .rename(\n", + " columns={\n", + " \"fuel_category_eia930\": \"fuel_category\",\n", + " \"ba_code_physical\": \"ba_code\",\n", + " \"net_generation_mwh\": \"net_generation_mwh_bap_all\",\n", + " }\n", + " )\n", + ")\n", + "\n", + "# Aggregate transmission-connected generation by commercial BA\n", + "cems_bac_trans = (\n", + " cems[cems[\"distribution_flag\"] is False]\n", + " .groupby([\"ba_code\", \"fuel_category_eia930\", \"datetime_utc\"])[\"net_generation_mwh\"]\n", + " .sum()\n", + " .reset_index()\n", + " .rename(\n", + " columns={\n", + " \"fuel_category_eia930\": \"fuel_category\",\n", + " \"net_generation_mwh\": \"net_generation_mwh_bac_trans\",\n", + " }\n", + " )\n", + ")\n", + "\n", + "# Aggregate transmission-connected generation by physical BA\n", + "cems_bap_trans = (\n", + " cems[cems[\"distribution_flag\"] == False]\n", + " .groupby([\"ba_code_physical\", \"fuel_category_eia930\", \"datetime_utc\"])[\n", + " \"net_generation_mwh\"\n", + " ]\n", + " .sum()\n", + " .reset_index()\n", + " .rename(\n", + " columns={\n", + " \"fuel_category_eia930\": \"fuel_category\",\n", + " \"ba_code_physical\": \"ba_code\",\n", + " \"net_generation_mwh\": \"net_generation_mwh_bap_trans\",\n", + " }\n", + " )\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# merge the aggregated data into the EIA data\n", + "combined_data = cleaned.merge(\n", + " cems_bac_all, how=\"left\", on=[\"ba_code\", \"fuel_category\", \"datetime_utc\"]\n", + ").fillna(0)\n", + "combined_data = combined_data.merge(\n", + " cems_bap_all, how=\"left\", on=[\"ba_code\", \"fuel_category\", \"datetime_utc\"]\n", + ").fillna(0)\n", + "combined_data = combined_data.merge(\n", + " cems_bac_trans, how=\"left\", on=[\"ba_code\", \"fuel_category\", \"datetime_utc\"]\n", + ").fillna(0)\n", + "combined_data = combined_data.merge(\n", + " cems_bap_trans, how=\"left\", on=[\"ba_code\", \"fuel_category\", \"datetime_utc\"]\n", + ").fillna(0)\n", + "combined_data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cleaned" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# only keep rows where local datetime is in the current year\n", + "combined_data = combined_data[\n", + " combined_data[\"datetime_local\"].apply(lambda x: x.year) == year\n", + "]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Evaluate BA mappings\n", + "\n", + "Mapping options: \n", + "Physical or commercial BA; include or exclude distribution-connected generation \n", + "\n", + "Metric: 923 data aggregated to BA should be close to 930 data aggregated to month. \n", + "For each BA, which aggregation metric minimizes difference? \n", + "How different are the aggreagtion metrics? " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "eia923 = pd.read_csv(f\"../data/outputs/eia923_allocated_{year}.csv\")\n", + "eia923.report_date = pd.to_datetime(\n", + " eia923.report_date\n", + ") # TODO why is this not a date already?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "eia923 = eia923.merge(plant_attributes, how=\"left\", on=\"plant_id_eia\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "eia930_agg = (\n", + " cleaned.groupby([\"ba_code\", \"fuel_category\", \"report_date\"]).sum().reset_index()\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "eia923.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "eia930_agg.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "eia923_agg = eia930_agg.copy()\n", + "# aggregate all generation by commercial BA\n", + "for ba_key in [\"ba_code\", \"ba_code_physical\"]:\n", + " for transmission_only in [\"transmission\", \"all\"]:\n", + " transmission_key = transmission_only == \"transmission\"\n", + " aggregated_gen = aggregate_for_residual(\n", + " eia923, time_key=\"report_date\", ba_key=ba_key, transmission=transmission_key\n", + " )\n", + " aggregated_gen.rename(\n", + " columns={\"net_generation_mwh\": f\"mwh_{ba_key}_{transmission_only}\"},\n", + " inplace=True,\n", + " )\n", + " aggregated_gen[f\"difference_{ba_key}_{transmission_only}\"] = (\n", + " eia923_agg[\"net_generation_mwh_930\"]\n", + " - aggregated_gen[f\"mwh_{ba_key}_{transmission_only}\"]\n", + " )\n", + " eia923_agg = eia923_agg.merge(\n", + " aggregated_gen, how=\"left\", on=[\"ba_code\", \"fuel_category\", \"report_date\"]\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "eia923_agg.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig = px.histogram(\n", + " eia923_agg,\n", + " x=[\n", + " \"difference_ba_code_transmission\",\n", + " \"difference_ba_code_all\",\n", + " \"difference_ba_code_physical_transmission\",\n", + " \"difference_ba_code_physical_all\",\n", + " ],\n", + ")\n", + "\n", + "# Overlay both histograms\n", + "fig.update_layout(barmode=\"overlay\")\n", + "# Reduce opacity to see both histograms\n", + "fig.update_traces(opacity=0.25)\n", + "fig.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Visualize net generation data from each source in a single BA\n", + "Only visualize non-renewable data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ba = \"MISO\"\n", + "\n", + "data_to_visualize = combined_data[\n", + " (combined_data[\"ba_code\"] == ba)\n", + " & (~combined_data[\"fuel_category\"].isin([\"hydro\", \"solar\", \"wind\"]))\n", + "]\n", + "\n", + "px.line(\n", + " data_to_visualize,\n", + " x=\"datetime_local\",\n", + " y=[\n", + " \"net_generation_mwh_930_clean\",\n", + " \"net_generation_mwh_930_orig\",\n", + " \"net_generation_mwh_bac_all\",\n", + " \"net_generation_mwh_bap_all\",\n", + " \"net_generation_mwh_bac_trans\",\n", + " \"net_generation_mwh_bap_trans\",\n", + " ],\n", + " facet_col=\"fuel_category\",\n", + " height=1000,\n", + " facet_col_wrap=1,\n", + ").update_yaxes(matches=None)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Calculate the residual based on a single CEMS aggregation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# for now, let's pick a single cems aggregation to use to calculate a residual\n", + "cems_data_column = \"net_generation_mwh_bac_all\"\n", + "\n", + "combined_data[\"residual\"] = (\n", + " combined_data[\"net_generation_mwh_930_clean\"] - combined_data[cems_data_column]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Visualize residual for the BA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data_to_visualize = combined_data[\n", + " (combined_data[\"ba_code\"] == ba)\n", + " & (~combined_data[\"fuel_category\"].isin([\"hydro\", \"solar\", \"wind\"]))\n", + "]\n", + "\n", + "px.line(\n", + " data_to_visualize,\n", + " x=\"datetime_local\",\n", + " y=[\"net_generation_mwh_930_clean\", cems_data_column, \"residual\"],\n", + " facet_col=\"fuel_category\",\n", + " height=1000,\n", + " facet_col_wrap=1,\n", + ").update_yaxes(matches=None)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test Scaling Strategy\n", + "If the residual is ever negative, we want to scale the cems net generation data to always be less than or equal to the 930 net generation. \n", + "\n", + "To do this, we'll try scaling the data as a percentage:\n", + "1. For each hour, calculate the ratio between 930 NG and CEMS NG.\n", + "2. For each BA-fuel, find the minimum ratio. If the minimum ratio is >= 1, it means that 930 is always greater than CEMS and doesn't need to be scaled. For any BA-fuels where the ratio is < 1, we will use this as a scaling factor to scale the CEMS data such that the scaled data is always <= the 930 data\n", + "3. Multiply all hourly CEMS values by the scaling factor" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# only keep data where the cems data is greater than zero\n", + "scaling_factors = combined_data.copy()[combined_data[cems_data_column] != 0]\n", + "\n", + "# calculate the ratio of 930 net generation to cems net generation\n", + "# if correct, ratio should be >=1\n", + "scaling_factors[\"scaling_factor\"] = (\n", + " scaling_factors[\"net_generation_mwh_930_clean\"] / scaling_factors[cems_data_column]\n", + ")\n", + "\n", + "# find the minimum ratio for each ba-fuel\n", + "scaling_factors = (\n", + " scaling_factors.groupby([\"ba_code\", \"fuel_category\"])[\"scaling_factor\"]\n", + " .min()\n", + " .reset_index()\n", + ")\n", + "scaling_factors" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# merge the scaling factor into the combined data\n", + "# for any BA-fuels without a scaling factor, fill with 1 (scale to 100% of the origina data)\n", + "combined_data = combined_data.merge(\n", + " scaling_factors, how=\"left\", on=[\"ba_code\", \"fuel_category\"]\n", + ").fillna(1)\n", + "\n", + "# calculate the scaled cems data\n", + "combined_data[\"cems_scaled\"] = (\n", + " combined_data[cems_data_column] * combined_data[\"scaling_factor\"]\n", + ")\n", + "\n", + "# calculate a scaled residual\n", + "combined_data[\"residual_scaled\"] = (\n", + " combined_data[\"net_generation_mwh_930_clean\"] - combined_data[\"cems_scaled\"]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot scaled residuals" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ba = \"PJM\"\n", + "\n", + "data_to_visualize = combined_data[\n", + " (combined_data[\"ba_code\"] == ba)\n", + " & (~combined_data[\"fuel_category\"].isin([\"hydro\", \"solar\", \"wind\"]))\n", + "]\n", + "\n", + "px.line(\n", + " data_to_visualize,\n", + " x=\"datetime_local\",\n", + " y=[\n", + " \"net_generation_mwh_930_clean\",\n", + " cems_data_column,\n", + " \"cems_scaled\",\n", + " \"residual\",\n", + " \"residual_scaled\",\n", + " ],\n", + " facet_col=\"fuel_category\",\n", + " height=1000,\n", + " facet_col_wrap=1,\n", + ").update_yaxes(matches=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "combined_data = combined_data.reset_index()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# broken\n", + "\n", + "ba = \"MISO\"\n", + "fuel = \"natural_gas\"\n", + "\n", + "data_to_visualize = combined_data.copy()[\n", + " (combined_data[\"ba_code\"] == ba) & (combined_data[\"fuel_category\"] == fuel)\n", + "]\n", + "data_to_visualize[\"datetime_local\"] = pd.to_datetime(\n", + " data_to_visualize[\"datetime_local\"]\n", + ")\n", + "data_to_visualize[\"date\"] = data_to_visualize[\"datetime_local\"].dt.date\n", + "data_to_visualize[\"hour\"] = data_to_visualize[\"datetime_local\"].dt.hour\n", + "\n", + "# data_to_visualize = data_to_visualize.pivot(index='hour', columns='date', values='residual_scaled')\n", + "\n", + "# px.imshow(data_to_visualize, color_continuous_scale=\"RdBu\", width=1000, height=400, color_continuous_midpoint=0,)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Export the profile" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data_to_export = combined_data[\n", + " [\n", + " \"ba_code\",\n", + " \"fuel_category\",\n", + " \"datetime_utc\",\n", + " \"datetime_local\",\n", + " \"report_date\",\n", + " \"residual_scaled\",\n", + " ]\n", + "]\n", + "data_to_export.to_csv(\"../data/output/residual_profiles.csv\", index=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Evaluate profile quality\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"../data/outputs/residual_profiles.csv\") as f:\n", + " line = f.readline()\n", + " print(line.split(\",\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Produced by data_pipeline\n", + "eia = pd.read_csv(\"../data/output/eia923_for_residual.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Produced by plant_class_differences\n", + "# TODO use output plant data to find smallest plants after cleaning -- some of these are in \"no cems\" data categories\n", + "validation_plants = pd.read_csv(\"../data/output/validation_plants.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "to_distribute = eia[eia.plant_id_eia.isin(validation_plants.plant_id_eia)]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "to_distribute.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "distributed = distribute_monthly_eia_data_to_hourly(\n", + " to_distribute, combined_data, \"residual_scaled\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cleaned = load_chalendar_for_pipeline(\n", + " \"../data/eia930/chalendar/EBA_adjusted_elec.csv\", year=year\n", + ")\n", + "cems = pd.read_csv(\n", + " f\"../data/outputs/cems_{year}.csv\",\n", + " parse_dates=[\"datetime_utc\"],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cleaned = cleaned.rename(columns={\"datetime_utc\": \"datetime_utc\"})\n", + "cems = cems.rename(columns={\"datetime_utc\": \"datetime_utc\"})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plant_attributes = pd.read_csv(\"../data/outputs/plant_static_attributes.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cleaned.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "calculate_residual(cems, cleaned, plant_attributes, 2020)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.10.5 ('hourly_egrid')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 }, - "nbformat": 4, - "nbformat_minor": 2 + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.5" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "4103f3cd497821eca917ea303dbe10c590d787eb7d2dc3fd4e15dec0356e7931" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/notebooks/explore_methods/national_wind_solar_correlations.ipynb b/notebooks/explore_methods/national_wind_solar_correlations.ipynb index 1b6a7669..99b4ff37 100644 --- a/notebooks/explore_methods/national_wind_solar_correlations.ipynb +++ b/notebooks/explore_methods/national_wind_solar_correlations.ipynb @@ -27,7 +27,8 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "\n", "import eia930\n", @@ -47,7 +48,7 @@ "# load eia930 data\n", "\n", "# If running small, we didn't clean the whole year, so need to use the Chalender file to build residual profiles.\n", - "clean_930_file = (f\"{outputs_folder()}{path_prefix}/eia930/eia930_elec.csv\")\n", + "clean_930_file = f\"{outputs_folder()}{path_prefix}/eia930/eia930_elec.csv\"\n", "eia930_data = eia930.load_chalendar_for_pipeline(clean_930_file, year=year)\n", "# until we can fix the physics reconciliation, we need to apply some post-processing steps\n", "eia930_data = eia930.remove_imputed_ones(eia930_data)\n", @@ -67,8 +68,8 @@ "metadata": {}, "outputs": [], "source": [ - "fuel=\"wind\"\n", - "report_date=\"2020-11-01\"\n", + "fuel = \"wind\"\n", + "report_date = \"2020-11-01\"\n", "\n", "df_temporary = eia930_data.copy()[\n", " (eia930_data[\"fuel_category_eia930\"] == fuel)\n", @@ -89,7 +90,9 @@ "outputs": [], "source": [ "# how well correlated are profiles across utc time\n", - "df_temporary.pivot(index=\"datetime_utc\", columns=\"ba_code\", values=\"net_generation_mwh_930\").corr().mean().mean()" + "df_temporary.pivot(\n", + " index=\"datetime_utc\", columns=\"ba_code\", values=\"net_generation_mwh_930\"\n", + ").corr().mean().mean()" ] }, { @@ -99,7 +102,9 @@ "outputs": [], "source": [ "# how well correlated are profiles across local time\n", - "df_temporary.pivot(index=\"datetime_local\", columns=\"ba_code\", values=\"net_generation_mwh_930\").corr().mean().mean()" + "df_temporary.pivot(\n", + " index=\"datetime_local\", columns=\"ba_code\", values=\"net_generation_mwh_930\"\n", + ").corr().mean().mean()" ] } ], diff --git a/notebooks/manual_data/default_fuel_sulfur_content.ipynb b/notebooks/manual_data/default_fuel_sulfur_content.ipynb index d70ac65d..48779e24 100644 --- a/notebooks/manual_data/default_fuel_sulfur_content.ipynb +++ b/notebooks/manual_data/default_fuel_sulfur_content.ipynb @@ -30,20 +30,25 @@ "metadata": {}, "outputs": [], "source": [ - "for year in [2015,2016,2017,2018,2019,2020]:\n", + "for year in [2015, 2016, 2017, 2018, 2019, 2020]:\n", + " pudl_out = load_data.initialize_pudl_out(year)\n", "\n", - " pudl_out = load_data.initialize_pudl_out(year)\n", + " (\n", + " plant_specific_fuel_sulfur_content,\n", + " national_avg_fuel_sulfur_content,\n", + " annual_avg_fuel_sulfur_content,\n", + " ) = emissions.return_monthly_plant_fuel_sulfur_content(pudl_out)\n", "\n", - " (plant_specific_fuel_sulfur_content,\n", - " national_avg_fuel_sulfur_content,\n", - " annual_avg_fuel_sulfur_content) = emissions.return_monthly_plant_fuel_sulfur_content(pudl_out)\n", + " annual_avg_fuel_sulfur_content = annual_avg_fuel_sulfur_content.rename(\n", + " columns={\"sulfur_content_pct\": f\"sulfur_content_pct_{year}\"}\n", + " )\n", "\n", - " annual_avg_fuel_sulfur_content = annual_avg_fuel_sulfur_content.rename(columns={\"sulfur_content_pct\":f\"sulfur_content_pct_{year}\"})\n", - "\n", - " if year == 2015:\n", - " result = annual_avg_fuel_sulfur_content.copy()\n", - " else:\n", - " result = result.merge(annual_avg_fuel_sulfur_content, how=\"outer\", on=\"energy_source_code\")\n", + " if year == 2015:\n", + " result = annual_avg_fuel_sulfur_content.copy()\n", + " else:\n", + " result = result.merge(\n", + " annual_avg_fuel_sulfur_content, how=\"outer\", on=\"energy_source_code\"\n", + " )\n", "\n", "result" ] diff --git a/notebooks/manual_data/export_fuel_heat_content.ipynb b/notebooks/manual_data/export_fuel_heat_content.ipynb index 62dee1bf..6a01315e 100644 --- a/notebooks/manual_data/export_fuel_heat_content.ipynb +++ b/notebooks/manual_data/export_fuel_heat_content.ipynb @@ -15,11 +15,12 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "import load_data\n", "from filepaths import *\n", - "import emissions\n" + "import emissions" ] }, { @@ -57,7 +58,7 @@ "\n", "fuel_heat_content.to_csv(\n", " outputs_folder(\"annual_average_fuel_heat_content.csv\"), index=False\n", - ")\n" + ")" ] } ], diff --git a/notebooks/manual_data/identify_eia930_time_lags.ipynb b/notebooks/manual_data/identify_eia930_time_lags.ipynb index 06cfd726..04d54e5b 100644 --- a/notebooks/manual_data/identify_eia930_time_lags.ipynb +++ b/notebooks/manual_data/identify_eia930_time_lags.ipynb @@ -57,7 +57,8 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "import download_data\n", "import load_data\n", @@ -78,8 +79,8 @@ "metadata": {}, "outputs": [], "source": [ - "# Data before and after shifts \n", - "# Note: this is very slow! (~30min) because it's pivoting large files. \n", + "# Data before and after shifts\n", + "# Note: this is very slow! (~30min) because it's pivoting large files.\n", "lraw = []\n", "lshift = []\n", "\n", @@ -92,16 +93,16 @@ " s = eia930.reformat_chalendar(s)\n", " r = eia930.reformat_chalendar(r)\n", "\n", - " s = s[s.fuel.isin([\"COL\",\"NG\",\"OIL\"])]\n", + " s = s[s.fuel.isin([\"COL\", \"NG\", \"OIL\"])]\n", " s = s.rename(columns={\"UTC Time at End of Hour\": \"datetime_utc\"})\n", - " s = s.groupby([\"datetime_utc\",\"BA\"]).sum()[\"generation\"].reset_index()\n", - " s = s[s.datetime_utc.dt.year == year] # filter for year\n", + " s = s.groupby([\"datetime_utc\", \"BA\"]).sum()[\"generation\"].reset_index()\n", + " s = s[s.datetime_utc.dt.year == year] # filter for year\n", "\n", " # Filter for fossil fuels, sum by BA\n", - " r = r[r.fuel.isin([\"COL\",\"NG\",\"OIL\"])]\n", + " r = r[r.fuel.isin([\"COL\", \"NG\", \"OIL\"])]\n", " r = r.rename(columns={\"UTC Time at End of Hour\": \"datetime_utc\"})\n", - " r = r.groupby([\"datetime_utc\",\"BA\"]).sum()[\"generation\"].reset_index()\n", - " r = r[r.datetime_utc.dt.year == year] # filter for year\n", + " r = r.groupby([\"datetime_utc\", \"BA\"]).sum()[\"generation\"].reset_index()\n", + " r = r[r.datetime_utc.dt.year == year] # filter for year\n", " lraw.append(r)\n", " lshift.append(s)" ] @@ -122,14 +123,18 @@ "metadata": {}, "outputs": [], "source": [ - "# Load data after shifting and rolling filter \n", + "# Load data after shifting and rolling filter\n", "\n", "all_rolled = []\n", "for y in [2019, 2020, 2021]:\n", - " rolled_930 = pd.read_csv(f\"../../data/outputs/{y}/eia930/eia930_rolling.csv\", index_col=0, parse_dates=True)\n", + " rolled_930 = pd.read_csv(\n", + " f\"../../data/outputs/{y}/eia930/eia930_rolling.csv\",\n", + " index_col=0,\n", + " parse_dates=True,\n", + " )\n", " rolled_930 = rolled_930[rolled_930.index.year == y]\n", " all_rolled.append(rolled_930)\n", - "rolled_930 = eia930.reformat_chalendar(pd.concat(all_rolled))\n" + "rolled_930 = eia930.reformat_chalendar(pd.concat(all_rolled))" ] }, { @@ -138,9 +143,14 @@ "metadata": {}, "outputs": [], "source": [ - "##### Remove renewables before summing 930 \n", + "##### Remove renewables before summing 930\n", "\n", - "rolled_930 = rolled_930[rolled_930.fuel.isin([\"COL\",\"NG\",\"OIL\"])].groupby([\"datetime_utc\",\"BA\"]).sum().reset_index()" + "rolled_930 = (\n", + " rolled_930[rolled_930.fuel.isin([\"COL\", \"NG\", \"OIL\"])]\n", + " .groupby([\"datetime_utc\", \"BA\"])\n", + " .sum()\n", + " .reset_index()\n", + ")" ] }, { @@ -152,19 +162,26 @@ "# Load files\n", "# Aggregate by BA during loading to cut down on space\n", "cems = pd.DataFrame()\n", - "for y in [2019, 2020, 2021]: \n", + "for y in [2019, 2020, 2021]:\n", " print(f\"loading {y}\")\n", " file = f\"{data_folder()}/outputs/{y}/cems_cleaned_{y}.csv\"\n", " plant_meta = pd.read_csv(f\"../../data/outputs/{y}/plant_static_attributes_{y}.csv\")\n", - " c = pd.read_csv(file, index_col=0, parse_dates=['datetime_utc'])\n", - " c = c.rename(columns={\"datetime_utc\":\"datetime_utc\"})\n", - " c = c.merge(plant_meta[['plant_id_eia', 'plant_primary_fuel', 'ba_code']], how='left', left_index=True, right_on='plant_id_eia')\n", + " c = pd.read_csv(file, index_col=0, parse_dates=[\"datetime_utc\"])\n", + " c = c.rename(columns={\"datetime_utc\": \"datetime_utc\"})\n", + " c = c.merge(\n", + " plant_meta[[\"plant_id_eia\", \"plant_primary_fuel\", \"ba_code\"]],\n", + " how=\"left\",\n", + " left_index=True,\n", + " right_on=\"plant_id_eia\",\n", + " )\n", " # exclude solar power for CEMS, since we're just going to look at COL + OIL + NG in the 930 data\n", " c = c[c[\"plant_primary_fuel\"] != \"SUN\"]\n", " print(\"Aggregating\")\n", - " if y == 2021: \n", - " c = c.rename(columns={\"gross_generation_mwh\":\"net_generation_mwh\"})\n", - " cems_aggregated = c.groupby([\"datetime_utc\",\"ba_code\"]).sum()[\"net_generation_mwh\"].reset_index()\n", + " if y == 2021:\n", + " c = c.rename(columns={\"gross_generation_mwh\": \"net_generation_mwh\"})\n", + " cems_aggregated = (\n", + " c.groupby([\"datetime_utc\", \"ba_code\"]).sum()[\"net_generation_mwh\"].reset_index()\n", + " )\n", " cems = pd.concat([cems, cems_aggregated])\n", "\n", "cems.head()" @@ -176,7 +193,9 @@ "metadata": {}, "outputs": [], "source": [ - "plant_attributes = pd.read_csv(outputs_folder(f\"{year}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes())" + "plant_attributes = pd.read_csv(\n", + " outputs_folder(f\"{year}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes()\n", + ")" ] }, { @@ -202,7 +221,9 @@ "metadata": {}, "outputs": [], "source": [ - "print(f\"shared BAs: {len(bas)} out of {len(raw.BA.unique())} 930 BAs and {len(cems.ba_code.unique())} CEMS BAs.\")\n", + "print(\n", + " f\"shared BAs: {len(bas)} out of {len(raw.BA.unique())} 930 BAs and {len(cems.ba_code.unique())} CEMS BAs.\"\n", + ")\n", "\n", "missing_cems = set(raw.BA.unique()).difference(set(cems.ba_code.unique()))\n", "missing_930 = set(cems.ba_code.unique()).difference(set(raw.BA.unique()))\n", @@ -217,26 +238,27 @@ "outputs": [], "source": [ "def find_best_cor(cems, df_eia930):\n", - " cems = cems.pivot(columns=\"ba_code\", index=\"datetime_utc\", values=\"net_generation_mwh\")\n", + " cems = cems.pivot(\n", + " columns=\"ba_code\", index=\"datetime_utc\", values=\"net_generation_mwh\"\n", + " )\n", " df_eia930 = df_eia930.pivot(columns=\"BA\", index=\"datetime_utc\", values=\"generation\")\n", "\n", " bas = set(cems.columns).intersection(set(df_eia930.columns))\n", "\n", - " correlations = pd.DataFrame(index=bas, columns=range(-12,12), dtype=float)\n", + " correlations = pd.DataFrame(index=bas, columns=range(-12, 12), dtype=float)\n", "\n", " for ba in correlations.index:\n", " for lag in correlations.columns:\n", - " # prepare 930: select BA \n", - " #eia = df_eia930[df_eia930.BA==ba][\"generation\"]\n", + " # prepare 930: select BA\n", + " # eia = df_eia930[df_eia930.BA==ba][\"generation\"]\n", " # prepare CEMS: select BA\n", - " #c = cems[cems.ba_code==ba][\"net_generation_mwh\"]\n", - " # calculate \n", - " correlations.loc[ba,lag] = cems[ba]\\\n", - " .corr(df_eia930[ba].shift(lag))\n", + " # c = cems[cems.ba_code==ba][\"net_generation_mwh\"]\n", + " # calculate\n", + " correlations.loc[ba, lag] = cems[ba].corr(df_eia930[ba].shift(lag))\n", "\n", " best = correlations.apply(lambda s: s.index[s.argmax()], axis=1).rename(\"best\")\n", "\n", - " correlations = pd.concat([best, correlations], axis='columns')\n", + " correlations = pd.concat([best, correlations], axis=\"columns\")\n", " return correlations" ] }, @@ -246,8 +268,8 @@ "metadata": {}, "outputs": [], "source": [ - "cems.drop_duplicates(subset=[\"datetime_utc\",\"ba_code\"], inplace=True)\n", - "#rolled_930.drop_duplicates(subset=[\"datetime_utc\",\"BA\"], inplace=True)" + "cems.drop_duplicates(subset=[\"datetime_utc\", \"ba_code\"], inplace=True)\n", + "# rolled_930.drop_duplicates(subset=[\"datetime_utc\",\"BA\"], inplace=True)" ] }, { @@ -258,18 +280,43 @@ "source": [ "# Calculate best correlations for shifted (no EBA cleaning) data\n", "\n", - "cems_930_cors = pd.concat([find_best_cor(cems, shifted).best.rename(\"all_years\"),\\\n", - " find_best_cor(cems[cems.datetime_utc.dt.year==2019],shifted[shifted.datetime_utc.dt.year==2019]).best.rename(\"2019\"),\n", - " find_best_cor(cems[cems.datetime_utc.dt.year==2020],shifted[shifted.datetime_utc.dt.year==2020]).best.rename(\"2020\"),\n", - " find_best_cor(cems[cems.datetime_utc.dt.year==2021],shifted[shifted.datetime_utc.dt.year==2021]).best.rename(\"2021\"),\n", - " find_best_cor(cems[(cems.datetime_utc.dt.month>=4)&(cems.datetime_utc.dt.month<=9)],\n", - " shifted[(shifted.datetime_utc.dt.month>=4)&(shifted.datetime_utc.dt.month<=9)]).best.rename(\"daylight time\"),\n", - " find_best_cor(cems[(cems.datetime_utc.dt.month>=11)|(cems.datetime_utc.dt.month<=2)],\n", - " shifted[(shifted.datetime_utc.dt.month>=11)|(shifted.datetime_utc.dt.month<=2)]).best.rename(\"standard time\")],\n", - " axis='columns')\n", + "cems_930_cors = pd.concat(\n", + " [\n", + " find_best_cor(cems, shifted).best.rename(\"all_years\"),\n", + " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2019],\n", + " shifted[shifted.datetime_utc.dt.year == 2019],\n", + " ).best.rename(\"2019\"),\n", + " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2020],\n", + " shifted[shifted.datetime_utc.dt.year == 2020],\n", + " ).best.rename(\"2020\"),\n", + " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2021],\n", + " shifted[shifted.datetime_utc.dt.year == 2021],\n", + " ).best.rename(\"2021\"),\n", + " find_best_cor(\n", + " cems[(cems.datetime_utc.dt.month >= 4) & (cems.datetime_utc.dt.month <= 9)],\n", + " shifted[\n", + " (shifted.datetime_utc.dt.month >= 4)\n", + " & (shifted.datetime_utc.dt.month <= 9)\n", + " ],\n", + " ).best.rename(\"daylight time\"),\n", + " find_best_cor(\n", + " cems[\n", + " (cems.datetime_utc.dt.month >= 11) | (cems.datetime_utc.dt.month <= 2)\n", + " ],\n", + " shifted[\n", + " (shifted.datetime_utc.dt.month >= 11)\n", + " | (shifted.datetime_utc.dt.month <= 2)\n", + " ],\n", + " ).best.rename(\"standard time\"),\n", + " ],\n", + " axis=\"columns\",\n", + ")\n", "\n", "cems_930_cors.to_csv(\"../../data/outputs/2021/cems_SHIFTEDeia930_cor_lags.csv\")\n", - "#cems_930_cors" + "# cems_930_cors" ] }, { @@ -280,15 +327,34 @@ "source": [ "# Calculate best correlations for raw data\n", "\n", - "cems_930_cors = pd.concat([find_best_cor(cems, raw).best.rename(\"all_years\"),\\\n", - " find_best_cor(cems[cems.datetime_utc.dt.year==2019],raw[raw.datetime_utc.dt.year==2019]).best.rename(\"2019\"),\n", - " find_best_cor(cems[cems.datetime_utc.dt.year==2020],raw[raw.datetime_utc.dt.year==2020]).best.rename(\"2020\"),\n", - " find_best_cor(cems[cems.datetime_utc.dt.year==2021],raw[raw.datetime_utc.dt.year==2021]).best.rename(\"2021\"),\n", - " find_best_cor(cems[(cems.datetime_utc.dt.month>=4)&(cems.datetime_utc.dt.month<=9)],\n", - " raw[(raw.datetime_utc.dt.month>=4)&(raw.datetime_utc.dt.month<=9)]).best.rename(\"daylight time\"),\n", - " find_best_cor(cems[(cems.datetime_utc.dt.month>=11)|(cems.datetime_utc.dt.month<=2)],\n", - " raw[(raw.datetime_utc.dt.month>=11)|(raw.datetime_utc.dt.month<=2)]).best.rename(\"standard time\")],\n", - " axis='columns')\n", + "cems_930_cors = pd.concat(\n", + " [\n", + " find_best_cor(cems, raw).best.rename(\"all_years\"),\n", + " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2019],\n", + " raw[raw.datetime_utc.dt.year == 2019],\n", + " ).best.rename(\"2019\"),\n", + " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2020],\n", + " raw[raw.datetime_utc.dt.year == 2020],\n", + " ).best.rename(\"2020\"),\n", + " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2021],\n", + " raw[raw.datetime_utc.dt.year == 2021],\n", + " ).best.rename(\"2021\"),\n", + " find_best_cor(\n", + " cems[(cems.datetime_utc.dt.month >= 4) & (cems.datetime_utc.dt.month <= 9)],\n", + " raw[(raw.datetime_utc.dt.month >= 4) & (raw.datetime_utc.dt.month <= 9)],\n", + " ).best.rename(\"daylight time\"),\n", + " find_best_cor(\n", + " cems[\n", + " (cems.datetime_utc.dt.month >= 11) | (cems.datetime_utc.dt.month <= 2)\n", + " ],\n", + " raw[(raw.datetime_utc.dt.month >= 11) | (raw.datetime_utc.dt.month <= 2)],\n", + " ).best.rename(\"standard time\"),\n", + " ],\n", + " axis=\"columns\",\n", + ")\n", "\n", "cems_930_cors.to_csv(\"../../data/outputs/2021/cems_RAWeia930_cor_lags.csv\")\n", "cems_930_cors" @@ -300,17 +366,42 @@ "metadata": {}, "outputs": [], "source": [ - "## Calculate correlations using different subsets of 930 data \n", - "\n", - "cems_930_cors = pd.concat([find_best_cor(cems, rolled_930).best.rename(\"all_years\"),\\\n", - " find_best_cor(cems[cems.datetime_utc.dt.year==2019],rolled_930[rolled_930.datetime_utc.dt.year==2019]).best.rename(\"2019\"),\n", - " find_best_cor(cems[cems.datetime_utc.dt.year==2020],rolled_930[rolled_930.datetime_utc.dt.year==2020]).best.rename(\"2020\"),\n", - " find_best_cor(cems[cems.datetime_utc.dt.year==2021],rolled_930[rolled_930.datetime_utc.dt.year==2021]).best.rename(\"2021\"),\n", - " find_best_cor(cems[(cems.datetime_utc.dt.month>=4)&(cems.datetime_utc.dt.month<=9)],\n", - " rolled_930[(rolled_930.datetime_utc.dt.month>=4)&(rolled_930.datetime_utc.dt.month<=9)]).best.rename(\"daylight time\"),\n", - " find_best_cor(cems[(cems.datetime_utc.dt.month>=11)|(cems.datetime_utc.dt.month<=2)],\n", - " rolled_930[(rolled_930.datetime_utc.dt.month>=11)|(rolled_930.datetime_utc.dt.month<=2)]).best.rename(\"standard time\")],\n", - " axis='columns')\n", + "## Calculate correlations using different subsets of 930 data\n", + "\n", + "cems_930_cors = pd.concat(\n", + " [\n", + " find_best_cor(cems, rolled_930).best.rename(\"all_years\"),\n", + " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2019],\n", + " rolled_930[rolled_930.datetime_utc.dt.year == 2019],\n", + " ).best.rename(\"2019\"),\n", + " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2020],\n", + " rolled_930[rolled_930.datetime_utc.dt.year == 2020],\n", + " ).best.rename(\"2020\"),\n", + " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2021],\n", + " rolled_930[rolled_930.datetime_utc.dt.year == 2021],\n", + " ).best.rename(\"2021\"),\n", + " find_best_cor(\n", + " cems[(cems.datetime_utc.dt.month >= 4) & (cems.datetime_utc.dt.month <= 9)],\n", + " rolled_930[\n", + " (rolled_930.datetime_utc.dt.month >= 4)\n", + " & (rolled_930.datetime_utc.dt.month <= 9)\n", + " ],\n", + " ).best.rename(\"daylight time\"),\n", + " find_best_cor(\n", + " cems[\n", + " (cems.datetime_utc.dt.month >= 11) | (cems.datetime_utc.dt.month <= 2)\n", + " ],\n", + " rolled_930[\n", + " (rolled_930.datetime_utc.dt.month >= 11)\n", + " | (rolled_930.datetime_utc.dt.month <= 2)\n", + " ],\n", + " ).best.rename(\"standard time\"),\n", + " ],\n", + " axis=\"columns\",\n", + ")\n", "\n", "cems_930_cors.to_csv(\"../../data/outputs/2021/cems_RAWeia930_cor_lags.csv\")\n", "cems_930_cors" @@ -326,19 +417,27 @@ "\n", "ba = \"SC\"\n", "\n", - "to_plot_930 = shifted[shifted.BA==ba].groupby(\"datetime_utc\").sum()\n", + "to_plot_930 = shifted[shifted.BA == ba].groupby(\"datetime_utc\").sum()\n", "\n", "print(f\"correlations for {ba}\")\n", "print(cems_930_cors.loc[ba])\n", "\n", "fig = go.Figure()\n", - "fig.add_trace(go.Scatter(x=cems[cems.ba_code==ba].datetime_utc, y=cems[cems.ba_code==ba].net_generation_mwh, name=\"CEMS\"))\n", - "fig.add_trace(go.Scatter(x=to_plot_930.index, y=to_plot_930.generation, name=\"EIA 930 (after adjustment and rolling cleaning)\"))\n", - "fig.update_layout(\n", - " title=ba,\n", - " xaxis_title=\"Date\",\n", - " yaxis_title=\"Generation\"\n", - ")" + "fig.add_trace(\n", + " go.Scatter(\n", + " x=cems[cems.ba_code == ba].datetime_utc,\n", + " y=cems[cems.ba_code == ba].net_generation_mwh,\n", + " name=\"CEMS\",\n", + " )\n", + ")\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=to_plot_930.index,\n", + " y=to_plot_930.generation,\n", + " name=\"EIA 930 (after adjustment and rolling cleaning)\",\n", + " )\n", + ")\n", + "fig.update_layout(title=ba, xaxis_title=\"Date\", yaxis_title=\"Generation\")" ] }, { @@ -354,11 +453,17 @@ "metadata": {}, "outputs": [], "source": [ - "#interchange = pd.read_csv(\"../data/eia930/chalendar/EBA_rolling.csv\",index_col=0, parse_dates=True)\n", + "# interchange = pd.read_csv(\"../data/eia930/chalendar/EBA_rolling.csv\",index_col=0, parse_dates=True)\n", "interchanges = []\n", - "for year in [2019, 2020, 2021]: \n", - " interchange = pd.read_csv(f\"../../data/outputs/{year}/eia930/eia930_raw.csv\",index_col=0, parse_dates=True)\n", - " interchange = interchange[interchange.index.year == year] # limit to after gen was reported by fuel type\n", + "for year in [2019, 2020, 2021]:\n", + " interchange = pd.read_csv(\n", + " f\"../../data/outputs/{year}/eia930/eia930_raw.csv\",\n", + " index_col=0,\n", + " parse_dates=True,\n", + " )\n", + " interchange = interchange[\n", + " interchange.index.year == year\n", + " ] # limit to after gen was reported by fuel type\n", " interchanges.append(interchange)" ] }, @@ -377,7 +482,7 @@ "metadata": {}, "outputs": [], "source": [ - "bas930 = {re.split(r\"[-.]\",c)[1] for c in interchange.columns}" + "bas930 = {re.split(r\"[-.]\", c)[1] for c in interchange.columns}" ] }, { @@ -388,47 +493,61 @@ "source": [ "# given a df where columns are interchange data, add best correlation between matching BAs to interchange_cors dict\n", "# optionally, write markdown to {file}.md and csvs at {file}_{ba}.csv\n", - "def interchange_cor(interchange, interchange_cors:dict={}, file=\"\", name:str=\"cors\"):\n", + "def interchange_cor(\n", + " interchange, interchange_cors: dict = {}, file=\"\", name: str = \"cors\"\n", + "):\n", " # Delete file\n", " if file != \"\":\n", - " hs = open(file+\".md\",\"w\")\n", + " hs = open(file + \".md\", \"w\")\n", " hs.write(\"\\n\\n\")\n", - " hs.close() \n", + " hs.close()\n", "\n", " for ba in bas930:\n", " print(ba, end=\"...\")\n", - " other_cols = [c for c in interchange.columns \\\n", - " if re.split(r\"[-.]\",c)[1]==ba \\\n", - " and re.split(r\"[-.]\",c)[2]!=\"ALL\"]\n", - " other_bas = [re.split(r\"[-.]\",c)[2] for c in other_cols]\n", - " #print(f\"{ba} connects to {other_bas}\")\n", - "\n", - " out = pd.DataFrame(index=other_bas, columns=range(-12,12), dtype=float)\n", + " other_cols = [\n", + " c\n", + " for c in interchange.columns\n", + " if re.split(r\"[-.]\", c)[1] == ba and re.split(r\"[-.]\", c)[2] != \"ALL\"\n", + " ]\n", + " other_bas = [re.split(r\"[-.]\", c)[2] for c in other_cols]\n", + " # print(f\"{ba} connects to {other_bas}\")\n", + "\n", + " out = pd.DataFrame(index=other_bas, columns=range(-12, 12), dtype=float)\n", " for o_ba in out.index:\n", " this_way = f\"EBA.{o_ba}-{ba}.ID.H\"\n", " other_way = f\"EBA.{ba}-{o_ba}.ID.H\"\n", - " if other_way not in interchange.columns or this_way not in interchange.columns: \n", + " if (\n", + " other_way not in interchange.columns\n", + " or this_way not in interchange.columns\n", + " ):\n", " continue\n", " for lag in out.columns:\n", - " out.loc[o_ba,lag] = abs(interchange[this_way]\\\n", - " .corr(-1*interchange[other_way].shift(lag)))\n", - " \n", + " out.loc[o_ba, lag] = abs(\n", + " interchange[this_way].corr(-1 * interchange[other_way].shift(lag))\n", + " )\n", + "\n", " # where is correlation the best?\n", - " out = pd.concat([out, out.apply(lambda s: s.index[s.argmax()], axis=1).rename(\"best\")], axis='columns')\n", + " out = pd.concat(\n", + " [out, out.apply(lambda s: s.index[s.argmax()], axis=1).rename(\"best\")],\n", + " axis=\"columns\",\n", + " )\n", "\n", " if file != \"\":\n", " # add new lines for proper markdown syntax\n", - " hs = open(file+\".md\",\"a\")\n", + " hs = open(file + \".md\", \"a\")\n", " hs.write(f\"\\n\\n# {ba}\\n\\n\")\n", - " hs.close() \n", + " hs.close()\n", "\n", - " out.to_markdown(file+\".md\",mode=\"a\")\n", + " out.to_markdown(file + \".md\", mode=\"a\")\n", "\n", - " out.to_csv(f\"{file}_{ba}\"+\".csv\")\n", + " out.to_csv(f\"{file}_{ba}\" + \".csv\")\n", "\n", - " interchange_cors[ba] = pd.concat([interchange_cors.get(ba, pd.DataFrame()), out.best.rename(name)], axis='columns')\n", + " interchange_cors[ba] = pd.concat(\n", + " [interchange_cors.get(ba, pd.DataFrame()), out.best.rename(name)],\n", + " axis=\"columns\",\n", + " )\n", "\n", - " return interchange_cors\n" + " return interchange_cors" ] }, { @@ -438,11 +557,25 @@ "outputs": [], "source": [ "int_cors = interchange_cor(interchange, interchange_cors={}, name=\"all_years\")\n", - "int_cors = interchange_cor(interchange[\"2019-01-01T00:00\":\"2019-12-30T00:00\"], int_cors, name=\"2019\")\n", - "int_cors = interchange_cor(interchange[\"2020-01-01T00:00\":\"2020-12-30T00:00\"], int_cors, name=\"2020\")\n", - "int_cors = interchange_cor(interchange[\"2021-01-01T00:00\":\"2021-12-30T00:00\"], int_cors, name=\"2021\")\n", - "int_cors = interchange_cor(interchange[(interchange.index.month >= 4)&(interchange.index.month <=9)], int_cors, name=\"daylight savings\")\n", - "int_cors = interchange_cor(interchange[(interchange.index.month >= 11)|(interchange.index.month <=2)], int_cors, name=\"standard time\")\n" + "int_cors = interchange_cor(\n", + " interchange[\"2019-01-01T00:00\":\"2019-12-30T00:00\"], int_cors, name=\"2019\"\n", + ")\n", + "int_cors = interchange_cor(\n", + " interchange[\"2020-01-01T00:00\":\"2020-12-30T00:00\"], int_cors, name=\"2020\"\n", + ")\n", + "int_cors = interchange_cor(\n", + " interchange[\"2021-01-01T00:00\":\"2021-12-30T00:00\"], int_cors, name=\"2021\"\n", + ")\n", + "int_cors = interchange_cor(\n", + " interchange[(interchange.index.month >= 4) & (interchange.index.month <= 9)],\n", + " int_cors,\n", + " name=\"daylight savings\",\n", + ")\n", + "int_cors = interchange_cor(\n", + " interchange[(interchange.index.month >= 11) | (interchange.index.month <= 2)],\n", + " int_cors,\n", + " name=\"standard time\",\n", + ")" ] }, { @@ -465,18 +598,17 @@ "# Output to md file because that's an easy way to manually scan through BAs and look for anomalies\n", "\n", "file = \"../../data/outputs/2021/interchange_corr_summary_adjusted.md\"\n", - "hs = open(file,\"w\")\n", + "hs = open(file, \"w\")\n", "hs.write(\"\\n\\n\")\n", - "hs.close() \n", - "\n", - "for (ba,out) in int_cors.items():\n", + "hs.close()\n", "\n", + "for ba, out in int_cors.items():\n", " # add new lines for proper markdown syntax\n", - " hs = open(file,\"a\")\n", - " hs.write(f\"\\n\\n# {ba}\\n\\n\")\n", - " hs.close() \n", + " hs = open(file, \"a\")\n", + " hs.write(f\"\\n\\n# {ba}\\n\\n\")\n", + " hs.close()\n", "\n", - " out.to_markdown(file,mode=\"a\")" + " out.to_markdown(file, mode=\"a\")" ] }, { @@ -496,7 +628,13 @@ "ba2 = \"MISO\"\n", "\n", "fig = px.line(interchange[f\"EBA.{ba1}-{ba2}.ID.H\"])\n", - "fig.add_trace(go.Scatter(x=interchange.index, y=interchange[f\"EBA.{ba2}-{ba1}.ID.H\"], name=f\"EBA.{ba2}-{ba1}.ID.H\"))" + "fig.add_trace(\n", + " go.Scatter(\n", + " x=interchange.index,\n", + " y=interchange[f\"EBA.{ba2}-{ba1}.ID.H\"],\n", + " name=f\"EBA.{ba2}-{ba1}.ID.H\",\n", + " )\n", + ")" ] }, { @@ -507,26 +645,28 @@ "source": [ "ba = \"PJM\"\n", "\n", - "# find cols of mappings in both directions \n", - "other_cols = [c for c in interchange.columns \\\n", - " if re.split(r\"[-.]\",c)[1]==ba \\\n", - " and re.split(r\"[-.]\",c)[2]!=\"ALL\"]\n", - "other_bas = [re.split(r\"[-.]\",c)[2] for c in other_cols]\n", + "# find cols of mappings in both directions\n", + "other_cols = [\n", + " c\n", + " for c in interchange.columns\n", + " if re.split(r\"[-.]\", c)[1] == ba and re.split(r\"[-.]\", c)[2] != \"ALL\"\n", + "]\n", + "other_bas = [re.split(r\"[-.]\", c)[2] for c in other_cols]\n", "\n", "these_cols = [f\"EBA.{o_ba}-{ba}.ID.H\" for o_ba in other_bas]\n", "\n", "# make long version with just cols of interest, adding BA column and to/from column\n", "toplot = pd.DataFrame()\n", - "for i in range(len(other_bas)): \n", + "for i in range(len(other_bas)):\n", " to_add = (interchange[other_cols[i]]).rename(\"interchange\").to_frame()\n", " to_add[\"source\"] = ba\n", " to_add[\"BA\"] = other_bas[i]\n", "\n", - " to_add_2 = (interchange[these_cols[i]]*(-1)).rename(\"interchange\").to_frame()\n", + " to_add_2 = (interchange[these_cols[i]] * (-1)).rename(\"interchange\").to_frame()\n", " to_add_2[\"source\"] = \"other BA\"\n", " to_add_2[\"BA\"] = other_bas[i]\n", "\n", - " toplot = pd.concat([toplot, to_add, to_add_2], axis='index')\n" + " toplot = pd.concat([toplot, to_add, to_add_2], axis=\"index\")" ] }, { @@ -535,14 +675,21 @@ "metadata": {}, "outputs": [], "source": [ - "fig = px.line(toplot, x=toplot.index, y=\"interchange\", facet_col=\"BA\", facet_col_wrap=2, color=\"source\")\n", + "fig = px.line(\n", + " toplot,\n", + " x=toplot.index,\n", + " y=\"interchange\",\n", + " facet_col=\"BA\",\n", + " facet_col_wrap=2,\n", + " color=\"source\",\n", + ")\n", "fig.update_layout(\n", " title=f\"Interchange from {ba}\",\n", " xaxis_title=\"Date\",\n", " yaxis_title=\"Interchange\",\n", - " legend_title=\"Source for
interchange data\"\n", + " legend_title=\"Source for
interchange data\",\n", ")\n", - "fig.for_each_annotation(lambda a: a.update(text=\"Other \"+a.text))" + "fig.for_each_annotation(lambda a: a.update(text=\"Other \" + a.text))" ] }, { @@ -551,16 +698,24 @@ "metadata": {}, "outputs": [], "source": [ - "first=\"PJM\"\n", - "second=\"MISO\"\n", - "\n", - "fig = px.line(interchange, x=interchange.index, y=[f\"EBA.{first}-{second}.ID.H\",f\"EBA.{second}-{first}.ID.H\", f\"EBA.{first}-ALL.TI.H\"])\n", + "first = \"PJM\"\n", + "second = \"MISO\"\n", + "\n", + "fig = px.line(\n", + " interchange,\n", + " x=interchange.index,\n", + " y=[\n", + " f\"EBA.{first}-{second}.ID.H\",\n", + " f\"EBA.{second}-{first}.ID.H\",\n", + " f\"EBA.{first}-ALL.TI.H\",\n", + " ],\n", + ")\n", "\n", "fig.update_layout(\n", " title=f\"{first}/{second} interchange\",\n", " xaxis_title=\"Date\",\n", " yaxis_title=\"Interchange\",\n", - " legend_title=\"Series\"\n", + " legend_title=\"Series\",\n", ")" ] }, @@ -573,14 +728,18 @@ "ba = \"CFE\"\n", "\n", "fig = go.Figure()\n", - "fig.add_trace(go.Scatter(x=interchange.index, \n", - " y=interchange[f\"EBA.{ba}-ALL.D.H\"]-interchange[f\"EBA.{ba}-ALL.NG.H\"]))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=interchange.index,\n", + " y=interchange[f\"EBA.{ba}-ALL.D.H\"] - interchange[f\"EBA.{ba}-ALL.NG.H\"],\n", + " )\n", + ")\n", "\n", "fig.update_layout(\n", " title=f\"{ba} demand - generation\",\n", " xaxis_title=\"Date\",\n", " yaxis_title=\"Demand - generation\",\n", - " legend_title=\"Series\"\n", + " legend_title=\"Series\",\n", ")" ] }, @@ -601,31 +760,36 @@ "source": [ "# given a df where columns are interchange data, add best correlation between matching BAs to interchange_cors dict\n", "# optionally, write markdown to {file}.md and csvs at {file}_{ba}.csv\n", - "def interchange_sign(interchange, i_sign:dict={}, file=\"\", name:str=\"cors\"):\n", + "def interchange_sign(interchange, i_sign: dict = {}, file=\"\", name: str = \"cors\"):\n", " for ba in bas930:\n", " print(ba, end=\"...\")\n", - " other_cols = [c for c in interchange.columns \\\n", - " if re.split(r\"[-.]\",c)[1]==ba \\\n", - " and re.split(r\"[-.]\",c)[2]!=\"ALL\"]\n", - " other_bas = [re.split(r\"[-.]\",c)[2] for c in other_cols]\n", - " #print(f\"{ba} connects to {other_bas}\")\n", - "\n", - " out = pd.DataFrame(index=other_bas, columns=range(-12,12), dtype=float)\n", + " other_cols = [\n", + " c\n", + " for c in interchange.columns\n", + " if re.split(r\"[-.]\", c)[1] == ba and re.split(r\"[-.]\", c)[2] != \"ALL\"\n", + " ]\n", + " other_bas = [re.split(r\"[-.]\", c)[2] for c in other_cols]\n", + " # print(f\"{ba} connects to {other_bas}\")\n", + "\n", + " out = pd.DataFrame(index=other_bas, columns=range(-12, 12), dtype=float)\n", " for o_ba in out.index:\n", " this_way = f\"EBA.{o_ba}-{ba}.ID.H\"\n", " other_way = f\"EBA.{ba}-{o_ba}.ID.H\"\n", - " if other_way not in interchange or this_way not in interchange: \n", - " continue \n", + " if other_way not in interchange or this_way not in interchange:\n", + " continue\n", " for lag in out.columns:\n", - " out.loc[o_ba,lag] = interchange[this_way]\\\n", - " .corr(-1*interchange[other_way].shift(lag))\n", - " \n", + " out.loc[o_ba, lag] = interchange[this_way].corr(\n", + " -1 * interchange[other_way].shift(lag)\n", + " )\n", + "\n", " # where is correlation the best?\n", " out = out.apply(lambda s: s.iloc[abs(s).argmax()], axis=1)\n", "\n", - " i_sign[ba] = pd.concat([i_sign.get(ba, pd.DataFrame()), out.rename(name)], axis='columns')\n", + " i_sign[ba] = pd.concat(\n", + " [i_sign.get(ba, pd.DataFrame()), out.rename(name)], axis=\"columns\"\n", + " )\n", "\n", - " return i_sign\n" + " return i_sign" ] }, { @@ -635,11 +799,25 @@ "outputs": [], "source": [ "int_sign = interchange_sign(interchange, {}, name=\"all_years\")\n", - "int_sign = interchange_sign(interchange[\"2019-01-01T00:00\":\"2019-12-30T00:00\"], int_sign, name=\"2019\")\n", - "int_sign = interchange_sign(interchange[\"2020-01-01T00:00\":\"2020-12-30T00:00\"], int_sign, name=\"2020\")\n", - "int_sign = interchange_sign(interchange[\"2020-01-01T00:00\":\"2020-12-30T00:00\"], int_sign, name=\"2021\")\n", - "int_sign = interchange_sign(interchange[(interchange.index.month >= 4)&(interchange.index.month <=9)], int_sign, name=\"daylight savings\")\n", - "int_sign = interchange_sign(interchange[(interchange.index.month >= 11)|(interchange.index.month <=2)], int_sign, name=\"standard time\")" + "int_sign = interchange_sign(\n", + " interchange[\"2019-01-01T00:00\":\"2019-12-30T00:00\"], int_sign, name=\"2019\"\n", + ")\n", + "int_sign = interchange_sign(\n", + " interchange[\"2020-01-01T00:00\":\"2020-12-30T00:00\"], int_sign, name=\"2020\"\n", + ")\n", + "int_sign = interchange_sign(\n", + " interchange[\"2020-01-01T00:00\":\"2020-12-30T00:00\"], int_sign, name=\"2021\"\n", + ")\n", + "int_sign = interchange_sign(\n", + " interchange[(interchange.index.month >= 4) & (interchange.index.month <= 9)],\n", + " int_sign,\n", + " name=\"daylight savings\",\n", + ")\n", + "int_sign = interchange_sign(\n", + " interchange[(interchange.index.month >= 11) | (interchange.index.month <= 2)],\n", + " int_sign,\n", + " name=\"standard time\",\n", + ")" ] }, { @@ -649,18 +827,17 @@ "outputs": [], "source": [ "file = f\"{outputs_folder('2021')}/interchange_cors_sign.md\"\n", - "hs = open(file,\"w\")\n", + "hs = open(file, \"w\")\n", "hs.write(\"\\n\\n\")\n", - "hs.close() \n", - "\n", - "for (ba,out) in int_sign.items():\n", + "hs.close()\n", "\n", + "for ba, out in int_sign.items():\n", " # add new lines for proper markdown syntax\n", - " hs = open(file,\"a\")\n", - " hs.write(f\"\\n\\n# {ba}\\n\\n\")\n", - " hs.close() \n", + " hs = open(file, \"a\")\n", + " hs.write(f\"\\n\\n# {ba}\\n\\n\")\n", + " hs.close()\n", "\n", - " out.to_markdown(file,mode=\"a\")" + " out.to_markdown(file, mode=\"a\")" ] } ], diff --git a/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb b/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb index 51bd809c..8e4de0c9 100644 --- a/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb +++ b/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb @@ -16,7 +16,7 @@ "outputs": [], "source": [ "import pandas as pd\n", - "import sqlalchemy as sa \n", + "import sqlalchemy as sa\n", "import pudl.output" ] }, @@ -26,7 +26,7 @@ "metadata": {}, "outputs": [], "source": [ - "year =2020" + "year = 2020" ] }, { @@ -38,11 +38,11 @@ "# load raw cems data\n", "cems_path = f\"../data/downloads/pudl/pudl_data/parquet/epacems/year={year}\"\n", "cems = pd.read_parquet(cems_path).rename(\n", - " columns={\n", - " \"plant_id_eia\": \"plant_id_epa\",\n", - " \"heat_content_mmbtu\": \"fuel_consumed_mmbtu\",\n", - " }\n", - " )\n", + " columns={\n", + " \"plant_id_eia\": \"plant_id_epa\",\n", + " \"heat_content_mmbtu\": \"fuel_consumed_mmbtu\",\n", + " }\n", + ")\n", "\n", "# load crosswalk data\n", "crosswalk = pudl.output.epacems.epa_crosswalk()\n", @@ -51,8 +51,8 @@ "pudl_db = \"sqlite:///../data/downloads/pudl/pudl_data/sqlite/pudl.sqlite\"\n", "pudl_engine = sa.create_engine(pudl_db)\n", "pudl_out = pudl.output.pudltabl.PudlTabl(\n", - " pudl_engine, freq=\"MS\", start_date=f\"{year}-01-01\", end_date=f\"{year}-12-31\"\n", - " )\n", + " pudl_engine, freq=\"MS\", start_date=f\"{year}-01-01\", end_date=f\"{year}-12-31\"\n", + ")\n", "gens_860 = pudl_out.gens_eia860()" ] }, @@ -83,7 +83,7 @@ " pd.read_csv(\n", " \"../data/manual/egrid_static_tables/table_4-2_plants_not_connected_to_grid.csv\"\n", " )[\"Plant ID\"]\n", - ")\n" + ")" ] }, { @@ -92,7 +92,7 @@ "metadata": {}, "outputs": [], "source": [ - "ids[ids['plant_id_epa'].isin(ngc_plants)].to_clipboard()" + "ids[ids[\"plant_id_epa\"].isin(ngc_plants)].to_clipboard()" ] }, { @@ -108,7 +108,9 @@ "metadata": {}, "outputs": [], "source": [ - "missing_eia = crosswalk[~crosswalk['CAMD_PLANT_ID'].isna() & crosswalk['EIA_PLANT_ID'].isna()]\n", + "missing_eia = crosswalk[\n", + " ~crosswalk[\"CAMD_PLANT_ID\"].isna() & crosswalk[\"EIA_PLANT_ID\"].isna()\n", + "]\n", "missing_eia" ] }, @@ -118,22 +120,47 @@ "metadata": {}, "outputs": [], "source": [ - "missing_ids = missing_eia[['CAMD_PLANT_ID','CAMD_UNIT_ID','CAMD_GENERATOR_ID']].drop_duplicates()\n", + "missing_ids = missing_eia[\n", + " [\"CAMD_PLANT_ID\", \"CAMD_UNIT_ID\", \"CAMD_GENERATOR_ID\"]\n", + "].drop_duplicates()\n", "\n", - "missing_ids = missing_ids.merge(gens_860[['plant_id_eia','generator_id']], how='left', left_on=['CAMD_PLANT_ID','CAMD_UNIT_ID'], right_on=['plant_id_eia','generator_id'])\n", - "missing_ids = missing_ids.merge(gens_860[['plant_id_eia','generator_id']], how='left', left_on=['CAMD_PLANT_ID','CAMD_GENERATOR_ID'], right_on=['plant_id_eia','generator_id'], suffixes=('_u','_g'))\n", + "missing_ids = missing_ids.merge(\n", + " gens_860[[\"plant_id_eia\", \"generator_id\"]],\n", + " how=\"left\",\n", + " left_on=[\"CAMD_PLANT_ID\", \"CAMD_UNIT_ID\"],\n", + " right_on=[\"plant_id_eia\", \"generator_id\"],\n", + ")\n", + "missing_ids = missing_ids.merge(\n", + " gens_860[[\"plant_id_eia\", \"generator_id\"]],\n", + " how=\"left\",\n", + " left_on=[\"CAMD_PLANT_ID\", \"CAMD_GENERATOR_ID\"],\n", + " right_on=[\"plant_id_eia\", \"generator_id\"],\n", + " suffixes=(\"_u\", \"_g\"),\n", + ")\n", "\n", "# identify the source of the data\n", - "missing_ids['source'] = ''\n", - "missing_ids.loc[~missing_ids['plant_id_eia_u'].isna(), 'source'] = \"CAMD_UNIT_ID matches EIA_GENERATOR_ID\"\n", - "missing_ids.loc[~missing_ids['plant_id_eia_g'].isna(), 'source'] = \"CAMD_GENERATOR_ID matches EIA_GENERATOR_ID\"\n", + "missing_ids[\"source\"] = \"\"\n", + "missing_ids.loc[\n", + " ~missing_ids[\"plant_id_eia_u\"].isna(), \"source\"\n", + "] = \"CAMD_UNIT_ID matches EIA_GENERATOR_ID\"\n", + "missing_ids.loc[\n", + " ~missing_ids[\"plant_id_eia_g\"].isna(), \"source\"\n", + "] = \"CAMD_GENERATOR_ID matches EIA_GENERATOR_ID\"\n", "\n", "# fill nas in each group so that we can identify where values match\n", - "missing_ids['generator_id_u'] = missing_ids['generator_id_u'].fillna(missing_ids['generator_id_g'])\n", - "missing_ids['generator_id_g'] = missing_ids['generator_id_g'].fillna(missing_ids['generator_id_u'])\n", + "missing_ids[\"generator_id_u\"] = missing_ids[\"generator_id_u\"].fillna(\n", + " missing_ids[\"generator_id_g\"]\n", + ")\n", + "missing_ids[\"generator_id_g\"] = missing_ids[\"generator_id_g\"].fillna(\n", + " missing_ids[\"generator_id_u\"]\n", + ")\n", "\n", - "missing_ids['plant_id_eia_u'] = missing_ids['plant_id_eia_u'].fillna(missing_ids['plant_id_eia_g'])\n", - "missing_ids['plant_id_eia_g'] = missing_ids['plant_id_eia_g'].fillna(missing_ids['plant_id_eia_u'])\n" + "missing_ids[\"plant_id_eia_u\"] = missing_ids[\"plant_id_eia_u\"].fillna(\n", + " missing_ids[\"plant_id_eia_g\"]\n", + ")\n", + "missing_ids[\"plant_id_eia_g\"] = missing_ids[\"plant_id_eia_g\"].fillna(\n", + " missing_ids[\"plant_id_eia_u\"]\n", + ")" ] }, { @@ -143,7 +170,13 @@ "outputs": [], "source": [ "# identify where we identified a consistent generator match\n", - "unit_manual_match = (missing_ids[missing_ids['generator_id_u'] == missing_ids['generator_id_g']]).drop(columns=['plant_id_eia_g','generator_id_g']).rename(columns={'plant_id_eia_u':'plant_id_eia','generator_id_u':'generator_id'})\n", + "unit_manual_match = (\n", + " (missing_ids[missing_ids[\"generator_id_u\"] == missing_ids[\"generator_id_g\"]])\n", + " .drop(columns=[\"plant_id_eia_g\", \"generator_id_g\"])\n", + " .rename(\n", + " columns={\"plant_id_eia_u\": \"plant_id_eia\", \"generator_id_u\": \"generator_id\"}\n", + " )\n", + ")\n", "unit_manual_match" ] }, @@ -153,7 +186,7 @@ "metadata": {}, "outputs": [], "source": [ - "unit_manual_match.to_csv('../data/outputs/crosswalk_unit_manual_matches.csv')" + "unit_manual_match.to_csv(\"../data/outputs/crosswalk_unit_manual_matches.csv\")" ] }, { @@ -163,7 +196,9 @@ "outputs": [], "source": [ "# identify where the two matching methods returned different generator matches\n", - "multi_match = missing_ids[missing_ids['generator_id_u'] != missing_ids['generator_id_g']]\n", + "multi_match = missing_ids[\n", + " missing_ids[\"generator_id_u\"] != missing_ids[\"generator_id_g\"]\n", + "]\n", "multi_match" ] }, @@ -173,7 +208,7 @@ "metadata": {}, "outputs": [], "source": [ - "multi_match.to_csv('../data/outputs/crosswalk_unit_manual_matches_multi.csv')" + "multi_match.to_csv(\"../data/outputs/crosswalk_unit_manual_matches_multi.csv\")" ] }, { @@ -182,7 +217,7 @@ "metadata": {}, "outputs": [], "source": [ - "gens_860[gens_860['plant_id_eia'] == 3443]" + "gens_860[gens_860[\"plant_id_eia\"] == 3443]" ] }, { @@ -198,8 +233,13 @@ "metadata": {}, "outputs": [], "source": [ - "missing_from_cw = ids.merge(crosswalk[['CAMD_PLANT_ID','CAMD_UNIT_ID']], how='left', left_on=['plant_id_epa','emissions_unit_id_epa'], right_on=['CAMD_PLANT_ID','CAMD_UNIT_ID'])\n", - "missing_from_cw = missing_from_cw[missing_from_cw['CAMD_UNIT_ID'].isna()]" + "missing_from_cw = ids.merge(\n", + " crosswalk[[\"CAMD_PLANT_ID\", \"CAMD_UNIT_ID\"]],\n", + " how=\"left\",\n", + " left_on=[\"plant_id_epa\", \"emissions_unit_id_epa\"],\n", + " right_on=[\"CAMD_PLANT_ID\", \"CAMD_UNIT_ID\"],\n", + ")\n", + "missing_from_cw = missing_from_cw[missing_from_cw[\"CAMD_UNIT_ID\"].isna()]" ] }, { @@ -208,10 +248,17 @@ "metadata": {}, "outputs": [], "source": [ - "missing_from_cw = missing_from_cw.merge(gens_860[['plant_id_eia','generator_id']], how='left', left_on=['plant_id_epa','emissions_unit_id_epa'], right_on=['plant_id_eia','generator_id'])\n", + "missing_from_cw = missing_from_cw.merge(\n", + " gens_860[[\"plant_id_eia\", \"generator_id\"]],\n", + " how=\"left\",\n", + " left_on=[\"plant_id_epa\", \"emissions_unit_id_epa\"],\n", + " right_on=[\"plant_id_eia\", \"generator_id\"],\n", + ")\n", "\n", - "missing_from_cw['source'] = ''\n", - "missing_from_cw.loc[~missing_from_cw['generator_id'].isna(), 'source'] = \"CAMD_UNIT_ID matches EIA_GENERATOR_ID\"\n", + "missing_from_cw[\"source\"] = \"\"\n", + "missing_from_cw.loc[\n", + " ~missing_from_cw[\"generator_id\"].isna(), \"source\"\n", + "] = \"CAMD_UNIT_ID matches EIA_GENERATOR_ID\"\n", "\n", "missing_from_cw" ] @@ -222,7 +269,7 @@ "metadata": {}, "outputs": [], "source": [ - "missing_from_cw.to_csv('../data/outputs/missing_from_crosswalk.csv', index=False)" + "missing_from_cw.to_csv(\"../data/outputs/missing_from_crosswalk.csv\", index=False)" ] }, { @@ -231,7 +278,10 @@ "metadata": {}, "outputs": [], "source": [ - "gens_860.loc[gens_860['plant_id_eia'] == 55641, ['plant_id_eia','generator_id','prime_mover_code']]" + "gens_860.loc[\n", + " gens_860[\"plant_id_eia\"] == 55641,\n", + " [\"plant_id_eia\", \"generator_id\", \"prime_mover_code\"],\n", + "]" ] } ], diff --git a/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb b/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb index 0472d9e2..af7ec875 100644 --- a/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb +++ b/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb @@ -15,7 +15,8 @@ "import plotly.express as px\n", "\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "import load_data\n", "import data_cleaning" @@ -28,7 +29,7 @@ "outputs": [], "source": [ "year = 2021\n", - "pudl_out = load_data.initialize_pudl_out(year=year)\n" + "pudl_out = load_data.initialize_pudl_out(year=year)" ] }, { @@ -49,8 +50,8 @@ " y=\"fuel_mmbtu_per_unit\",\n", " title=f\"Range of heat contents for each fuel reported in {year}\",\n", " width=1000,\n", - " height=600\n", - ")\n" + " height=600,\n", + ")" ] }, { @@ -59,7 +60,9 @@ "metadata": {}, "outputs": [], "source": [ - "plants_with_oth = fuel_heat_content[fuel_heat_content[\"energy_source_code\"] == \"OTH\"].copy()\n", + "plants_with_oth = fuel_heat_content[\n", + " fuel_heat_content[\"energy_source_code\"] == \"OTH\"\n", + "].copy()\n", "plants_with_oth = plants_with_oth.groupby(\"plant_id_eia\").mean()\n", "plants_with_oth" ] @@ -70,7 +73,7 @@ "metadata": {}, "outputs": [], "source": [ - "fuel_heat_content[fuel_heat_content[\"plant_id_eia\"] == 902]\n" + "fuel_heat_content[fuel_heat_content[\"plant_id_eia\"] == 902]" ] }, { @@ -81,7 +84,7 @@ "source": [ "# load EPA fuel type data\n", "epa_fuel_types = data_cleaning.get_epa_unit_fuel_types(year)\n", - "epa_fuel_types[epa_fuel_types[\"energy_source_code\"] == \"OTH\"]\n" + "epa_fuel_types[epa_fuel_types[\"energy_source_code\"] == \"OTH\"]" ] }, { @@ -92,7 +95,7 @@ "source": [ "# Load EIA-860 to examine whether a plant is retired\n", "gens_860 = pudl_out.gens_eia860()\n", - "gens_860[gens_860[\"plant_id_eia\"] == 60670]\n" + "gens_860[gens_860[\"plant_id_eia\"] == 60670]" ] } ], diff --git a/notebooks/manual_data/manually_update_ba_reference.ipynb b/notebooks/manual_data/manually_update_ba_reference.ipynb index b63ceb80..ab7f108f 100644 --- a/notebooks/manual_data/manually_update_ba_reference.ipynb +++ b/notebooks/manual_data/manually_update_ba_reference.ipynb @@ -22,7 +22,7 @@ "import os\n", "import requests\n", "import pandas as pd\n", - "import numpy as np\n" + "import numpy as np" ] }, { @@ -36,7 +36,12 @@ "\n", "# merge the ferc data into the manual table\n", "ba_reference_updated = ba_reference.merge(\n", - " ferc_bas, how=\"outer\", on=\"ba_code\", indicator=\"source\", suffixes=(None, \"_ferc\"), validate=\"1:1\"\n", + " ferc_bas,\n", + " how=\"outer\",\n", + " on=\"ba_code\",\n", + " indicator=\"source\",\n", + " suffixes=(None, \"_ferc\"),\n", + " validate=\"1:1\",\n", ")\n", "\n", "# fill any missing data in the manual table with the data from ferc\n", @@ -64,7 +69,7 @@ "ba_reference_updated = ba_reference_updated.drop(columns=[\"us_ba_ferc\"])\n", "\n", "\n", - "ba_reference_updated\n" + "ba_reference_updated" ] }, { @@ -73,7 +78,7 @@ "metadata": {}, "outputs": [], "source": [ - "ba_reference_updated.to_csv(\"../../data/manual/ba_reference_updated.csv\", index=False)\n" + "ba_reference_updated.to_csv(\"../../data/manual/ba_reference_updated.csv\", index=False)" ] } ], diff --git a/notebooks/manual_data/update_utility_name_ba_map.ipynb b/notebooks/manual_data/update_utility_name_ba_map.ipynb index ffddb998..ccc4a527 100644 --- a/notebooks/manual_data/update_utility_name_ba_map.ipynb +++ b/notebooks/manual_data/update_utility_name_ba_map.ipynb @@ -17,7 +17,8 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "import load_data\n", "from column_checks import get_dtypes\n", @@ -85,7 +86,11 @@ "outputs": [], "source": [ "# what are all the utility names not mapped to a BA?\n", - "list(plant_ba.loc[plant_ba[\"balancing_authority_code_eia\"].isna(), \"utility_name_eia\"].unique())" + "list(\n", + " plant_ba.loc[\n", + " plant_ba[\"balancing_authority_code_eia\"].isna(), \"utility_name_eia\"\n", + " ].unique()\n", + ")" ] }, { @@ -95,7 +100,12 @@ "outputs": [], "source": [ "# what are all the utility names not mapped to a BA?\n", - "list(plant_ba.loc[plant_ba[\"balancing_authority_code_eia\"].isna(), \"transmission_distribution_owner_name\"].unique())" + "list(\n", + " plant_ba.loc[\n", + " plant_ba[\"balancing_authority_code_eia\"].isna(),\n", + " \"transmission_distribution_owner_name\",\n", + " ].unique()\n", + ")" ] }, { @@ -104,7 +114,10 @@ "metadata": {}, "outputs": [], "source": [ - "plant_ba[plant_ba[\"balancing_authority_code_eia\"].isna() & (plant_ba[\"utility_name_eia\"] == \"Pacific Gas & Electric Co\")]" + "plant_ba[\n", + " plant_ba[\"balancing_authority_code_eia\"].isna()\n", + " & (plant_ba[\"utility_name_eia\"] == \"Pacific Gas & Electric Co\")\n", + "]" ] } ], diff --git a/notebooks/manual_data/zip_data.ipynb b/notebooks/manual_data/zip_data.ipynb index d67b546b..1660e436 100644 --- a/notebooks/manual_data/zip_data.ipynb +++ b/notebooks/manual_data/zip_data.ipynb @@ -18,9 +18,10 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", "\n", - "import output_data\n" + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "\n", + "import output_data" ] }, { @@ -29,7 +30,7 @@ "metadata": {}, "outputs": [], "source": [ - "years = [2019,2020,2021]\n", + "years = [2019, 2020, 2021]\n", "\n", "output_data.prepare_files_for_upload(years)" ] @@ -40,7 +41,7 @@ "metadata": {}, "outputs": [], "source": [ - "for year in [2019,2020,2021]:\n", + "for year in [2019, 2020, 2021]:\n", " output_data.zip_results_for_s3(year)" ] }, @@ -50,7 +51,7 @@ "metadata": {}, "outputs": [], "source": [ - "for year in [2019,2020,2021]:\n", + "for year in [2019, 2020, 2021]:\n", " output_data.zip_data_for_zenodo(year)" ] } diff --git a/notebooks/validation/data_validation.ipynb b/notebooks/validation/data_validation.ipynb index 557a1543..60cecf2e 100644 --- a/notebooks/validation/data_validation.ipynb +++ b/notebooks/validation/data_validation.ipynb @@ -22,9 +22,10 @@ "%reload_ext autoreload\n", "%autoreload 2\n", "\n", - "# Tell python where to look for modules. \n", + "# Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "# import local modules\n", "import load_data\n", @@ -49,8 +50,13 @@ "outputs": [], "source": [ "year = 2020\n", - "cems = pd.read_csv(f'../data/outputs/cems_subplant_{year}.csv', parse_dates=['datetime_utc','report_date'])\n", - "eia923_allocated = pd.read_csv(f'../data/outputs/eia923_allocated_{year}.csv', parse_dates=['report_date'])" + "cems = pd.read_csv(\n", + " f\"../data/outputs/cems_subplant_{year}.csv\",\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", + "eia923_allocated = pd.read_csv(\n", + " f\"../data/outputs/eia923_allocated_{year}.csv\", parse_dates=[\"report_date\"]\n", + ")" ] }, { @@ -61,7 +67,12 @@ "source": [ "# what percent of emissions is reported in CEMS vs EIA\n", "# NOTE: This does not include emissions only reported by CEMS, so the % may be higher\n", - "(eia923_allocated.groupby('hourly_data_source')['co2_mass_lb_adjusted'].sum() / eia923_allocated.groupby('hourly_data_source')['co2_mass_lb_adjusted'].sum().sum(axis=0)).round(3)" + "(\n", + " eia923_allocated.groupby(\"hourly_data_source\")[\"co2_mass_lb_adjusted\"].sum()\n", + " / eia923_allocated.groupby(\"hourly_data_source\")[\"co2_mass_lb_adjusted\"]\n", + " .sum()\n", + " .sum(axis=0)\n", + ").round(3)" ] }, { @@ -84,10 +95,21 @@ "source": [ "# perform checks on allocated data\n", "# fuel consumption and co2 emissions should be positive\n", - "negative_test = validation.test_for_negative_values(eia923_allocated, ['fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_for_electricity','co2_mass_lb_adjusted'])\n", + "negative_test = validation.test_for_negative_values(\n", + " eia923_allocated,\n", + " [\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_for_electricity\",\n", + " \"co2_mass_lb_adjusted\",\n", + " ],\n", + ")\n", "\n", "# if net generation is positive, fuel consumption should be non zero\n", - "missing_fuel_test = validation.test_for_missing_fuel(eia923_allocated, 'net_generation_mwh')\n", + "missing_fuel_test = validation.test_for_missing_fuel(\n", + " eia923_allocated, \"net_generation_mwh\"\n", + ")\n", "\n", "# fuel consumed for electricity should be less than fuel consumed\n", "chp_allocation_test = validation.test_chp_allocation(eia923_allocated)\n", @@ -96,16 +118,38 @@ "missing_co2_test = validation.test_for_missing_co2(eia923_allocated)\n", "\n", "# check for generators with no data\n", - "missing_data_test = validation.test_for_missing_data(eia923_allocated, ['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_for_electricity','co2_mass_lb_adjusted'])\n", + "missing_data_test = validation.test_for_missing_data(\n", + " eia923_allocated,\n", + " [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_for_electricity\",\n", + " \"co2_mass_lb_adjusted\",\n", + " ],\n", + ")\n", "\n", "# check for generators with all data = 0\n", - "zero_data_test = validation.test_for_zero_data(eia923_allocated, ['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_for_electricity','co2_mass_lb_adjusted'])\n", + "zero_data_test = validation.test_for_zero_data(\n", + " eia923_allocated,\n", + " [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_for_electricity\",\n", + " \"co2_mass_lb_adjusted\",\n", + " ],\n", + ")\n", "\n", "# check for missing energy source code\n", "missing_esc_test = validation.test_for_missing_energy_source_code(eia923_allocated)\n", "\n", "# check for missing and incorrect prime movers\n", - "incorrect_pm_test, missing_pm_test = validation.test_for_missing_incorrect_prime_movers(eia923_allocated, year)\n", + "incorrect_pm_test, missing_pm_test = validation.test_for_missing_incorrect_prime_movers(\n", + " eia923_allocated, year\n", + ")\n", "\n", "# check for missing subplant ids\n", "eia_missing_subplant_test = validation.test_for_missing_subplant_id(eia923_allocated)\n", @@ -120,7 +164,7 @@ "metadata": {}, "outputs": [], "source": [ - "heat_rate_test.sort_values(by='heat_rate')" + "heat_rate_test.sort_values(by=\"heat_rate\")" ] }, { @@ -137,10 +181,19 @@ "outputs": [], "source": [ "# fuel consumption and co2 emissions should be positive\n", - "cems_negative_test = validation.test_for_negative_values(cems, ['fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_adjusted', 'gross_generation_mwh'])\n", + "cems_negative_test = validation.test_for_negative_values(\n", + " cems,\n", + " [\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_adjusted\",\n", + " \"gross_generation_mwh\",\n", + " ],\n", + ")\n", "\n", "# if net generation is positive, fuel consumption should be non zero\n", - "cems_missing_fuel_test = validation.test_for_missing_fuel(cems,'gross_generation_mwh')\n", + "cems_missing_fuel_test = validation.test_for_missing_fuel(cems, \"gross_generation_mwh\")\n", "\n", "# fuel consumed for electricity should be less than fuel consumed\n", "cems_chp_allocation_test = validation.test_chp_allocation(cems)\n", @@ -155,7 +208,7 @@ "cems_missing_subplant_test = validation.test_for_missing_subplant_id(cems)\n", "\n", "# test to see if there are any net generation values greater than gross generation\n", - "gtn_test = validation.test_gtn_results(cems)\n" + "gtn_test = validation.test_gtn_results(cems)" ] }, { @@ -164,7 +217,7 @@ "metadata": {}, "outputs": [], "source": [ - "cems_missing_subplant_test[['plant_id_eia','emissions_unit_id_epa']].drop_duplicates()" + "cems_missing_subplant_test[[\"plant_id_eia\", \"emissions_unit_id_epa\"]].drop_duplicates()" ] }, { @@ -173,7 +226,7 @@ "metadata": {}, "outputs": [], "source": [ - "cems_missing_esc_test[['plant_id_eia','emissions_unit_id_epa']].drop_duplicates()" + "cems_missing_esc_test[[\"plant_id_eia\", \"emissions_unit_id_epa\"]].drop_duplicates()" ] }, { @@ -197,12 +250,20 @@ "outputs": [], "source": [ "year = 2020\n", - "cems = pd.read_csv(f'../data/outputs/{year}/cems_{year}.csv', dtype=get_dtypes())\n", - "partial_cems_scaled = pd.read_csv(f'../data/outputs/{year}/partial_cems_scaled_{year}.csv', dtype=get_dtypes())\n", - "eia923_allocated = pd.read_csv(f'../data/outputs/{year}/eia923_allocated_{year}.csv', dtype=get_dtypes())\n", + "cems = pd.read_csv(f\"../data/outputs/{year}/cems_{year}.csv\", dtype=get_dtypes())\n", + "partial_cems_scaled = pd.read_csv(\n", + " f\"../data/outputs/{year}/partial_cems_scaled_{year}.csv\", dtype=get_dtypes()\n", + ")\n", + "eia923_allocated = pd.read_csv(\n", + " f\"../data/outputs/{year}/eia923_allocated_{year}.csv\", dtype=get_dtypes()\n", + ")\n", "\n", - "plant_attributes = pd.read_csv(f\"../data/outputs/{year}/plant_static_attributes_{year}.csv\")\n", - "eia923_allocated = eia923_allocated.merge(plant_attributes, how=\"left\", on=\"plant_id_eia\")\n", + "plant_attributes = pd.read_csv(\n", + " f\"../data/outputs/{year}/plant_static_attributes_{year}.csv\"\n", + ")\n", + "eia923_allocated = eia923_allocated.merge(\n", + " plant_attributes, how=\"left\", on=\"plant_id_eia\"\n", + ")\n", "cems = cems.merge(plant_attributes, how=\"left\", on=\"plant_id_eia\")" ] }, @@ -212,7 +273,9 @@ "metadata": {}, "outputs": [], "source": [ - "partial_cems_scaled = partial_cems_scaled.merge(plant_attributes, how=\"left\", on=\"plant_id_eia\")" + "partial_cems_scaled = partial_cems_scaled.merge(\n", + " plant_attributes, how=\"left\", on=\"plant_id_eia\"\n", + ")" ] }, { @@ -223,9 +286,14 @@ "source": [ "ba = \"CISO\"\n", "fuel = \"natural_gas\"\n", - "test_eia = eia923_allocated[(eia923_allocated[\"ba_code\"] == ba) & (eia923_allocated[\"fuel_category\"] == fuel)]\n", + "test_eia = eia923_allocated[\n", + " (eia923_allocated[\"ba_code\"] == ba) & (eia923_allocated[\"fuel_category\"] == fuel)\n", + "]\n", "test_cems = cems[(cems[\"ba_code\"] == ba) & (cems[\"fuel_category\"] == fuel)]\n", - "test_pc = partial_cems_scaled[(partial_cems_scaled[\"ba_code\"] == ba) & (partial_cems_scaled[\"fuel_category\"] == fuel)]" + "test_pc = partial_cems_scaled[\n", + " (partial_cems_scaled[\"ba_code\"] == ba)\n", + " & (partial_cems_scaled[\"fuel_category\"] == fuel)\n", + "]" ] }, { @@ -234,7 +302,7 @@ "metadata": {}, "outputs": [], "source": [ - "test_eia.groupby('hourly_data_source').sum()['net_generation_mwh']" + "test_eia.groupby(\"hourly_data_source\").sum()[\"net_generation_mwh\"]" ] }, { @@ -243,7 +311,7 @@ "metadata": {}, "outputs": [], "source": [ - "test_cems[[\"gross_generation_mwh\",'net_generation_mwh']].sum()" + "test_cems[[\"gross_generation_mwh\", \"net_generation_mwh\"]].sum()" ] }, { @@ -252,7 +320,7 @@ "metadata": {}, "outputs": [], "source": [ - "test_pc[['net_generation_mwh']].sum()" + "test_pc[[\"net_generation_mwh\"]].sum()" ] }, { @@ -261,7 +329,7 @@ "metadata": {}, "outputs": [], "source": [ - "test_pc = test_pc.drop(columns='source')" + "test_pc = test_pc.drop(columns=\"source\")" ] }, { @@ -270,7 +338,7 @@ "metadata": {}, "outputs": [], "source": [ - "test_cems = test_cems.drop(columns='source')" + "test_cems = test_cems.drop(columns=\"source\")" ] }, { @@ -300,7 +368,7 @@ "metadata": {}, "outputs": [], "source": [ - "filtered_cems[[\"gross_generation_mwh\",'net_generation_mwh']].sum()" + "filtered_cems[[\"gross_generation_mwh\", \"net_generation_mwh\"]].sum()" ] }, { @@ -309,9 +377,16 @@ "metadata": {}, "outputs": [], "source": [ - "subplants_ided_as_cems = test_eia.loc[test_eia[\"hourly_data_source\"] == 'cems', [\"plant_id_eia\",\"subplant_id\"]].drop_duplicates()\n", - "subplants_in_cems = filtered_cems[[\"plant_id_eia\",\"subplant_id\"]].drop_duplicates()\n", - "cems_overlap = subplants_ided_as_cems.merge(subplants_in_cems, how=\"outer\", on=[\"plant_id_eia\",\"subplant_id\"], indicator=\"source\")\n", + "subplants_ided_as_cems = test_eia.loc[\n", + " test_eia[\"hourly_data_source\"] == \"cems\", [\"plant_id_eia\", \"subplant_id\"]\n", + "].drop_duplicates()\n", + "subplants_in_cems = filtered_cems[[\"plant_id_eia\", \"subplant_id\"]].drop_duplicates()\n", + "cems_overlap = subplants_ided_as_cems.merge(\n", + " subplants_in_cems,\n", + " how=\"outer\",\n", + " on=[\"plant_id_eia\", \"subplant_id\"],\n", + " indicator=\"source\",\n", + ")\n", "cems_overlap" ] }, @@ -321,9 +396,13 @@ "metadata": {}, "outputs": [], "source": [ - "subplants_ided_as_pc = test_eia.loc[test_eia[\"hourly_data_source\"] == 'partial_cems', [\"plant_id_eia\",\"subplant_id\"]].drop_duplicates()\n", - "subplants_in_pc = test_pc[[\"plant_id_eia\",\"subplant_id\"]].drop_duplicates()\n", - "pc_overlap = subplants_ided_as_pc.merge(subplants_in_pc, how=\"outer\", on=[\"plant_id_eia\",\"subplant_id\"], indicator=\"source\")\n", + "subplants_ided_as_pc = test_eia.loc[\n", + " test_eia[\"hourly_data_source\"] == \"partial_cems\", [\"plant_id_eia\", \"subplant_id\"]\n", + "].drop_duplicates()\n", + "subplants_in_pc = test_pc[[\"plant_id_eia\", \"subplant_id\"]].drop_duplicates()\n", + "pc_overlap = subplants_ided_as_pc.merge(\n", + " subplants_in_pc, how=\"outer\", on=[\"plant_id_eia\", \"subplant_id\"], indicator=\"source\"\n", + ")\n", "pc_overlap" ] }, @@ -333,7 +412,7 @@ "metadata": {}, "outputs": [], "source": [ - "test_cems.loc[test_cems['plant_id_eia'] == 55748, \"net_generation_mwh\"].sum()" + "test_cems.loc[test_cems[\"plant_id_eia\"] == 55748, \"net_generation_mwh\"].sum()" ] }, { @@ -350,15 +429,53 @@ "outputs": [], "source": [ "# for plants where there is data reported in cems, see how off it is from data reported in eia\n", - "cems_plant_monthly = cems.groupby(['plant_id_eia','subplant_id','report_date'], dropna=False).sum()[['gross_generation_mwh','net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_adjusted']].reset_index()\n", - "gf_plant_monthly = eia923_allocated.groupby(['plant_id_eia','subplant_id','report_date'], dropna=False).sum().reset_index()\n", - "compare_cems_eia = gf_plant_monthly.merge(cems_plant_monthly, how='inner', on=['plant_id_eia','subplant_id','report_date'], suffixes=(\"_eia\",'_cems'))\n", - "\n", + "cems_plant_monthly = (\n", + " cems.groupby([\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False)\n", + " .sum()[\n", + " [\n", + " \"gross_generation_mwh\",\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_adjusted\",\n", + " ]\n", + " ]\n", + " .reset_index()\n", + ")\n", + "gf_plant_monthly = (\n", + " eia923_allocated.groupby(\n", + " [\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False\n", + " )\n", + " .sum()\n", + " .reset_index()\n", + ")\n", + "compare_cems_eia = gf_plant_monthly.merge(\n", + " cems_plant_monthly,\n", + " how=\"inner\",\n", + " on=[\"plant_id_eia\", \"subplant_id\", \"report_date\"],\n", + " suffixes=(\"_eia\", \"_cems\"),\n", + ")\n", "\n", - "for column in ['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_adjusted']:\n", - " compare_cems_eia[f'{column}_pctdiff'] = ((compare_cems_eia[f'{column}_cems'].replace(0,0.1) - compare_cems_eia[f'{column}_eia'].replace(0,0.1)) / compare_cems_eia[f'{column}_eia'].replace(0,0.1)).round(3)\n", "\n", - "compare_cems_eia = compare_cems_eia.set_index(['plant_id_eia','subplant_id','report_date'])\n", + "for column in [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_adjusted\",\n", + "]:\n", + " compare_cems_eia[f\"{column}_pctdiff\"] = (\n", + " (\n", + " compare_cems_eia[f\"{column}_cems\"].replace(0, 0.1)\n", + " - compare_cems_eia[f\"{column}_eia\"].replace(0, 0.1)\n", + " )\n", + " / compare_cems_eia[f\"{column}_eia\"].replace(0, 0.1)\n", + " ).round(3)\n", + "\n", + "compare_cems_eia = compare_cems_eia.set_index(\n", + " [\"plant_id_eia\", \"subplant_id\", \"report_date\"]\n", + ")\n", "compare_cems_eia = compare_cems_eia.reindex(sorted(compare_cems_eia.columns), axis=1)" ] }, @@ -369,10 +486,10 @@ "outputs": [], "source": [ "# identify where there are differences between reported CEMS and EIA values for the same subplant-month\n", - "value = 'net_generation_mwh'\n", + "value = \"net_generation_mwh\"\n", "\n", - "comparison = compare_cems_eia[[f'{value}_cems', f'{value}_eia', f'{value}_pctdiff']]\n", - "comparison[(~comparison[f'{value}_pctdiff'].between(-0.05,0.05))]" + "comparison = compare_cems_eia[[f\"{value}_cems\", f\"{value}_eia\", f\"{value}_pctdiff\"]]\n", + "comparison[(~comparison[f\"{value}_pctdiff\"].between(-0.05, 0.05))]" ] }, { @@ -389,10 +506,15 @@ "outputs": [], "source": [ "# filter the data for which we only have EIA data\n", - "monthly_eia_data_to_distribute = eia923_allocated[(eia923_allocated['hourly_data_source'] == 'eia') & ~(eia923_allocated['fuel_consumed_mmbtu'].isna())]\n", + "monthly_eia_data_to_distribute = eia923_allocated[\n", + " (eia923_allocated[\"hourly_data_source\"] == \"eia\")\n", + " & ~(eia923_allocated[\"fuel_consumed_mmbtu\"].isna())\n", + "]\n", "\n", "# assign ba codes to the data\n", - "monthly_eia_data_to_distribute = assign_ba_code_to_plant(monthly_eia_data_to_distribute, year)\n", + "monthly_eia_data_to_distribute = assign_ba_code_to_plant(\n", + " monthly_eia_data_to_distribute, year\n", + ")\n", "cems = assign_ba_code_to_plant(cems, year)" ] }, @@ -406,14 +528,45 @@ "###################################\n", "\n", "# Aggregate cems and eia data by plant id, then combine\n", - "cems_plant_annual = cems.groupby(['ba_code','state','plant_id_eia'], dropna=False).sum()[['net_generation_mwh','fuel_consumed_mmbtu','co2_mass_lb','co2_mass_lb_adjusted']].reset_index()\n", - "eia_plant_annual = monthly_eia_data_to_distribute.groupby(['ba_code','state','plant_id_eia'], dropna=False).sum()[['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_adjusted']].reset_index()\n", - "plant_annual_total = pd.concat([cems_plant_annual,eia_plant_annual], axis=0)\n", + "cems_plant_annual = (\n", + " cems.groupby([\"ba_code\", \"state\", \"plant_id_eia\"], dropna=False)\n", + " .sum()[\n", + " [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_adjusted\",\n", + " ]\n", + " ]\n", + " .reset_index()\n", + ")\n", + "eia_plant_annual = (\n", + " monthly_eia_data_to_distribute.groupby(\n", + " [\"ba_code\", \"state\", \"plant_id_eia\"], dropna=False\n", + " )\n", + " .sum()[\n", + " [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_adjusted\",\n", + " ]\n", + " ]\n", + " .reset_index()\n", + ")\n", + "plant_annual_total = pd.concat([cems_plant_annual, eia_plant_annual], axis=0)\n", "# group any plants that have records from both datasets\n", - "plant_annual_total = plant_annual_total.groupby(['ba_code','state','plant_id_eia'], dropna=False).sum().reset_index()\n", + "plant_annual_total = (\n", + " plant_annual_total.groupby([\"ba_code\", \"state\", \"plant_id_eia\"], dropna=False)\n", + " .sum()\n", + " .reset_index()\n", + ")\n", "\n", "# add a egrid id\n", - "plant_annual_total = validation.add_egrid_plant_id(plant_annual_total, from_id='eia', to_id='egrid')\n", + "plant_annual_total = validation.add_egrid_plant_id(\n", + " plant_annual_total, from_id=\"eia\", to_id=\"egrid\"\n", + ")\n", "\n", "# Load the eGRID plant table\n", "egrid_plant = validation.load_egrid_plant_file(year)" @@ -435,14 +588,21 @@ "outputs": [], "source": [ "# identify any plants that are in egrid but not our totals, and any plants that are in our totals, but not egrid\n", - "plant_not_in_calc = list(set(egrid_plant['plant_id_eia'].unique()) - set(plant_annual_total['plant_id_eia'].unique()))\n", + "plant_not_in_calc = list(\n", + " set(egrid_plant[\"plant_id_eia\"].unique())\n", + " - set(plant_annual_total[\"plant_id_eia\"].unique())\n", + ")\n", "\n", "# Which plants are included in eGRID but are missing from our calculations?\n", - "missing_from_calc = egrid_plant[egrid_plant['plant_id_egrid'].isin(plant_not_in_calc)]\n", + "missing_from_calc = egrid_plant[egrid_plant[\"plant_id_egrid\"].isin(plant_not_in_calc)]\n", "\n", "# see if any of these plants are retired\n", - "generators_eia860 = load_data.load_pudl_table('generators_eia860', year=year)\n", - "missing_from_calc.merge(generators_eia860.groupby('plant_id_eia')['retirement_date'].unique().reset_index(), how='left', on='plant_id_eia')" + "generators_eia860 = load_data.load_pudl_table(\"generators_eia860\", year=year)\n", + "missing_from_calc.merge(\n", + " generators_eia860.groupby(\"plant_id_eia\")[\"retirement_date\"].unique().reset_index(),\n", + " how=\"left\",\n", + " on=\"plant_id_eia\",\n", + ")" ] }, { @@ -459,10 +619,17 @@ "outputs": [], "source": [ "# Which plants are in our calculations, but are missing from eGRID?\n", - "plants_not_in_egrid = list(set(plant_annual_total['plant_id_egrid'].unique()) - set(egrid_plant['plant_id_egrid'].unique()))\n", + "plants_not_in_egrid = list(\n", + " set(plant_annual_total[\"plant_id_egrid\"].unique())\n", + " - set(egrid_plant[\"plant_id_egrid\"].unique())\n", + ")\n", "\n", - "plant_names = load_data.load_pudl_table('plants_entity_eia')[['plant_id_eia','plant_name_eia','sector_name_eia']]\n", - "missing_from_egrid = plant_annual_total[plant_annual_total['plant_id_egrid'].isin(plants_not_in_egrid)].merge(plant_names, how='left', on='plant_id_eia')\n", + "plant_names = load_data.load_pudl_table(\"plants_entity_eia\")[\n", + " [\"plant_id_eia\", \"plant_name_eia\", \"sector_name_eia\"]\n", + "]\n", + "missing_from_egrid = plant_annual_total[\n", + " plant_annual_total[\"plant_id_egrid\"].isin(plants_not_in_egrid)\n", + "].merge(plant_names, how=\"left\", on=\"plant_id_eia\")\n", "\n", "missing_from_egrid" ] @@ -474,7 +641,7 @@ "outputs": [], "source": [ "# how many of the plants missing from egrid have non-zero data\n", - "missing_from_egrid[missing_from_egrid['fuel_consumed_mmbtu'] > 1].count()" + "missing_from_egrid[missing_from_egrid[\"fuel_consumed_mmbtu\"] > 1].count()" ] }, { @@ -491,11 +658,23 @@ "outputs": [], "source": [ "# identify where there is a single egrid plant id for multiple eia plant ids\n", - "double_ids = plant_annual_total[plant_annual_total['plant_id_egrid'].duplicated(keep=False)]\n", - "double_ids = double_ids.groupby('plant_id_egrid').sum()['net_generation_mwh'].reset_index() # focus on net generation for now\n", + "double_ids = plant_annual_total[\n", + " plant_annual_total[\"plant_id_egrid\"].duplicated(keep=False)\n", + "]\n", + "double_ids = (\n", + " double_ids.groupby(\"plant_id_egrid\").sum()[\"net_generation_mwh\"].reset_index()\n", + ") # focus on net generation for now\n", "# merge the egrid data\n", - "double_ids = double_ids.merge(egrid_plant[['plant_id_egrid','net_generation_mwh']], how='left', on='plant_id_egrid', suffixes=('_calc','_egrid'))\n", - "double_ids['percent_diff'] = ((double_ids['net_generation_mwh_calc'] - double_ids['net_generation_mwh_egrid']) / double_ids['net_generation_mwh_egrid']).round(3)\n", + "double_ids = double_ids.merge(\n", + " egrid_plant[[\"plant_id_egrid\", \"net_generation_mwh\"]],\n", + " how=\"left\",\n", + " on=\"plant_id_egrid\",\n", + " suffixes=(\"_calc\", \"_egrid\"),\n", + ")\n", + "double_ids[\"percent_diff\"] = (\n", + " (double_ids[\"net_generation_mwh_calc\"] - double_ids[\"net_generation_mwh_egrid\"])\n", + " / double_ids[\"net_generation_mwh_egrid\"]\n", + ").round(3)\n", "double_ids" ] }, @@ -512,10 +691,18 @@ "metadata": {}, "outputs": [], "source": [ - "ba_code_match = egrid_plant.set_index('plant_id_eia')[['plant_name','ba_code']].merge(plant_annual_total.set_index('plant_id_eia')[['ba_code']], how='inner', left_index=True, right_index=True, suffixes=(\"_egrid\",'_calc'))\n", + "ba_code_match = egrid_plant.set_index(\"plant_id_eia\")[[\"plant_name\", \"ba_code\"]].merge(\n", + " plant_annual_total.set_index(\"plant_id_eia\")[[\"ba_code\"]],\n", + " how=\"inner\",\n", + " left_index=True,\n", + " right_index=True,\n", + " suffixes=(\"_egrid\", \"_calc\"),\n", + ")\n", "\n", "# plants with missing ba code\n", - "ba_code_match[(ba_code_match['ba_code_calc'].isna()) & ~(ba_code_match['ba_code_egrid'].isna())]" + "ba_code_match[\n", + " (ba_code_match[\"ba_code_calc\"].isna()) & ~(ba_code_match[\"ba_code_egrid\"].isna())\n", + "]" ] }, { @@ -525,7 +712,10 @@ "outputs": [], "source": [ "# plants with incorrect ba code\n", - "ba_code_match[(ba_code_match['ba_code_calc'] != ba_code_match['ba_code_egrid']) & ~(ba_code_match['ba_code_calc'].isna())]" + "ba_code_match[\n", + " (ba_code_match[\"ba_code_calc\"] != ba_code_match[\"ba_code_egrid\"])\n", + " & ~(ba_code_match[\"ba_code_calc\"].isna())\n", + "]" ] }, { @@ -598,9 +788,7 @@ ") / egrid_eia_comparison[f\"{metric}_eia923\"]\n", "egrid_eia_comparison.loc[\n", " egrid_eia_comparison[\"difference\"] == 0, \"percent_difference\"\n", - "] = 0\n", - "\n", - "\n" + "] = 0" ] }, { @@ -610,13 +798,20 @@ "outputs": [], "source": [ "# add cems data\n", - "cems_total = cems.copy()[['plant_id_eia',metric]]\n", + "cems_total = cems.copy()[[\"plant_id_eia\", metric]]\n", "cems_total[\"plant_id_egrid\"] = cems_total[\"plant_id_eia\"]\n", "cems_total[\"plant_id_egrid\"].update(cems_total[\"plant_id_egrid\"].map(eia_to_egrid_id))\n", - "cems_total = cems_total.groupby('plant_id_egrid').sum()[metric].reset_index().rename(columns={metric:f\"{metric}_cems\"})\n", + "cems_total = (\n", + " cems_total.groupby(\"plant_id_egrid\")\n", + " .sum()[metric]\n", + " .reset_index()\n", + " .rename(columns={metric: f\"{metric}_cems\"})\n", + ")\n", "\n", - "# merge cems data into egrid \n", - "egrid_eia_comparison = egrid_eia_comparison.merge(cems_total, how='outer', on='plant_id_egrid')" + "# merge cems data into egrid\n", + "egrid_eia_comparison = egrid_eia_comparison.merge(\n", + " cems_total, how=\"outer\", on=\"plant_id_egrid\"\n", + ")" ] }, { @@ -641,7 +836,7 @@ "metadata": {}, "outputs": [], "source": [ - "egrid_eia_comparison[egrid_eia_comparison['source'] == 'left_only']" + "egrid_eia_comparison[egrid_eia_comparison[\"source\"] == \"left_only\"]" ] }, { @@ -651,7 +846,9 @@ "outputs": [], "source": [ "# egrid seems to be missing fuel consumption data for most nuclear power plants\n", - "missing_nuclear = egrid_eia_comparison[egrid_eia_comparison['energy_source_code'] == 'NUC']\n", + "missing_nuclear = egrid_eia_comparison[\n", + " egrid_eia_comparison[\"energy_source_code\"] == \"NUC\"\n", + "]\n", "missing_nuclear.sum()" ] }, @@ -661,7 +858,7 @@ "metadata": {}, "outputs": [], "source": [ - "egrid_eia_comparison[(egrid_eia_comparison['percent_difference'] < - 0.01)]" + "egrid_eia_comparison[(egrid_eia_comparison[\"percent_difference\"] < -0.01)]" ] }, { @@ -671,7 +868,10 @@ "outputs": [], "source": [ "# where is egrid missing data?\n", - "egrid_eia_comparison[(egrid_eia_comparison['percent_difference'] < -0.01) & (egrid_eia_comparison['energy_source_code'] != 'NUC')]#.sort_values(by='percent_difference').head(20)" + "egrid_eia_comparison[\n", + " (egrid_eia_comparison[\"percent_difference\"] < -0.01)\n", + " & (egrid_eia_comparison[\"energy_source_code\"] != \"NUC\")\n", + "] # .sort_values(by='percent_difference').head(20)" ] }, { @@ -682,12 +882,26 @@ "source": [ "# how much emissions does this account for?\n", "# group by fuel code\n", - "missing_emissions = egrid_eia_comparison[(egrid_eia_comparison['percent_difference'] < -0.01) & (egrid_eia_comparison['energy_source_code'] != 'NUC')].groupby('energy_source_code').sum().reset_index()\n", + "missing_emissions = (\n", + " egrid_eia_comparison[\n", + " (egrid_eia_comparison[\"percent_difference\"] < -0.01)\n", + " & (egrid_eia_comparison[\"energy_source_code\"] != \"NUC\")\n", + " ]\n", + " .groupby(\"energy_source_code\")\n", + " .sum()\n", + " .reset_index()\n", + ")\n", "\n", "# get emission factors\n", - "emission_factors = load_data.load_ghg_emission_factors()[['energy_source_code', 'co2_lb_per_mmbtu']]\n", - "missing_emissions = missing_emissions.merge(emission_factors, how='left', on='energy_source_code')\n", - "missing_emissions['co2_mass_lb'] = missing_emissions['difference'] * missing_emissions['co2_lb_per_mmbtu']\n", + "emission_factors = load_data.load_ghg_emission_factors()[\n", + " [\"energy_source_code\", \"co2_lb_per_mmbtu\"]\n", + "]\n", + "missing_emissions = missing_emissions.merge(\n", + " emission_factors, how=\"left\", on=\"energy_source_code\"\n", + ")\n", + "missing_emissions[\"co2_mass_lb\"] = (\n", + " missing_emissions[\"difference\"] * missing_emissions[\"co2_lb_per_mmbtu\"]\n", + ")\n", "missing_emissions.sum()" ] }, @@ -705,67 +919,196 @@ "outputs": [], "source": [ "# standardize column names and index so that the two dfs can be divided\n", - "calculated_to_compare = plant_annual_total.groupby('plant_id_egrid').sum().drop(columns=['plant_id_eia'])\n", + "calculated_to_compare = (\n", + " plant_annual_total.groupby(\"plant_id_egrid\").sum().drop(columns=[\"plant_id_eia\"])\n", + ")\n", "\n", "# drop the plants that have no data in eGRID\n", - "plants_with_no_data_in_egrid = list(egrid_plant[egrid_plant[['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_adjusted']].sum(axis=1) == 0]['plant_id_egrid'])\n", - "egrid_plant = egrid_plant[~egrid_plant['plant_id_eia'].isin(plants_with_no_data_in_egrid)]\n", + "plants_with_no_data_in_egrid = list(\n", + " egrid_plant[\n", + " egrid_plant[\n", + " [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_adjusted\",\n", + " ]\n", + " ].sum(axis=1)\n", + " == 0\n", + " ][\"plant_id_egrid\"]\n", + ")\n", + "egrid_plant = egrid_plant[\n", + " ~egrid_plant[\"plant_id_eia\"].isin(plants_with_no_data_in_egrid)\n", + "]\n", "\n", - "egrid_to_compare = egrid_plant.set_index(['plant_id_egrid']).drop(columns=['ba_code','state','plant_name','plant_id_eia'])\n", + "egrid_to_compare = egrid_plant.set_index([\"plant_id_egrid\"]).drop(\n", + " columns=[\"ba_code\", \"state\", \"plant_name\", \"plant_id_eia\"]\n", + ")\n", "\n", "# divide calculated value by egrid value\n", - "compared = calculated_to_compare.div(egrid_to_compare).merge(egrid_plant[['plant_id_egrid','plant_name','ba_code', 'state']], how='left', left_index=True, right_on='plant_id_egrid').set_index('plant_id_egrid')\n", - "compared['plant_name'] = compared['plant_name'].fillna('unknown')\n", + "compared = (\n", + " calculated_to_compare.div(egrid_to_compare)\n", + " .merge(\n", + " egrid_plant[[\"plant_id_egrid\", \"plant_name\", \"ba_code\", \"state\"]],\n", + " how=\"left\",\n", + " left_index=True,\n", + " right_on=\"plant_id_egrid\",\n", + " )\n", + " .set_index(\"plant_id_egrid\")\n", + ")\n", + "compared[\"plant_name\"] = compared[\"plant_name\"].fillna(\"unknown\")\n", "\n", "# create a dataframe that merges the two sources of data together\n", - "compared_merged = calculated_to_compare.merge(egrid_to_compare, how='outer', on='plant_id_egrid', suffixes=('_calc','_egrid'))\n", + "compared_merged = calculated_to_compare.merge(\n", + " egrid_to_compare, how=\"outer\", on=\"plant_id_egrid\", suffixes=(\"_calc\", \"_egrid\")\n", + ")\n", "\n", "# for each column, change missing values to zero if both values are zero (only nan b/c divide by zero)\n", - "for col in ['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb_adjusted','co2_mass_lb']:\n", + "for col in [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb_adjusted\",\n", + " \"co2_mass_lb\",\n", + "]:\n", " # identify plants with zero values for both\n", - " plant_ids = list(compared_merged[(compared_merged[f'{col}_calc'] == 0) & (compared_merged[f'{col}_egrid'] == 0)].index)\n", + " plant_ids = list(\n", + " compared_merged[\n", + " (compared_merged[f\"{col}_calc\"] == 0)\n", + " & (compared_merged[f\"{col}_egrid\"] == 0)\n", + " ].index\n", + " )\n", " compared.loc[compared.index.isin(plant_ids), col] = 1\n", "\n", "# for each column, categorize the data based on how far it is off from egrid\n", - "for col in ['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb_adjusted','co2_mass_lb']:\n", + "for col in [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb_adjusted\",\n", + " \"co2_mass_lb\",\n", + "]:\n", " # add a new column\n", - " compared[f'{col}_status'] = pd.cut(x=compared[col], \n", - " bins=[-999999999,0,0.5,0.9,0.99,0.9999,1,1.0001,1.01,1.1,1.5,999999999], \n", - " labels=['negative','<50%','+/-50%','+/-10%','+/-1%','!exact','!exact','+/-1%','+/-10%','+/-50%','>50%'], \n", - " ordered=False)\n", + " compared[f\"{col}_status\"] = pd.cut(\n", + " x=compared[col],\n", + " bins=[\n", + " -999999999,\n", + " 0,\n", + " 0.5,\n", + " 0.9,\n", + " 0.99,\n", + " 0.9999,\n", + " 1,\n", + " 1.0001,\n", + " 1.01,\n", + " 1.1,\n", + " 1.5,\n", + " 999999999,\n", + " ],\n", + " labels=[\n", + " \"negative\",\n", + " \"<50%\",\n", + " \"+/-50%\",\n", + " \"+/-10%\",\n", + " \"+/-1%\",\n", + " \"!exact\",\n", + " \"!exact\",\n", + " \"+/-1%\",\n", + " \"+/-10%\",\n", + " \"+/-50%\",\n", + " \">50%\",\n", + " ],\n", + " ordered=False,\n", + " )\n", " # replace any missing values with missing\n", - " compared[f'{col}_status'] = compared[f'{col}_status'].astype(str) \n", - " compared[f'{col}_status'] = compared[f'{col}_status'].fillna('missing')\n", - " compared[f'{col}_status'] = compared[f'{col}_status'].replace('nan','missing')\n", - " compared.loc[(compared.index.isin(plants_not_in_egrid)),f'{col}_status'] = 'not_in_egrid'\n", + " compared[f\"{col}_status\"] = compared[f\"{col}_status\"].astype(str)\n", + " compared[f\"{col}_status\"] = compared[f\"{col}_status\"].fillna(\"missing\")\n", + " compared[f\"{col}_status\"] = compared[f\"{col}_status\"].replace(\"nan\", \"missing\")\n", + " compared.loc[\n", + " (compared.index.isin(plants_not_in_egrid)), f\"{col}_status\"\n", + " ] = \"not_in_egrid\"\n", "\n", "# identify which plants are missing from egrid vs calculated values\n", - "for col in ['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb_adjusted','co2_mass_lb']:\n", + "for col in [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb_adjusted\",\n", + " \"co2_mass_lb\",\n", + "]:\n", " # identify plants that are missing in egrid\n", - " plants_missing_egrid = list(compared_merged[(compared_merged[f'{col}_calc'] > 0) & (compared_merged[f'{col}_egrid'].isna())].index)\n", - " compared.loc[compared.index.isin(plants_missing_egrid), f'{col}_status'] = 'missing_in_egrid'\n", + " plants_missing_egrid = list(\n", + " compared_merged[\n", + " (compared_merged[f\"{col}_calc\"] > 0)\n", + " & (compared_merged[f\"{col}_egrid\"].isna())\n", + " ].index\n", + " )\n", + " compared.loc[\n", + " compared.index.isin(plants_missing_egrid), f\"{col}_status\"\n", + " ] = \"missing_in_egrid\"\n", " # identify plants that are missing from our calculations\n", - " plants_missing_calc = list(compared_merged[(compared_merged[f'{col}_calc'].isna()) & (compared_merged[f'{col}_egrid'] > 0)].index)\n", - " compared.loc[compared.index.isin(plants_missing_calc), f'{col}_status'] = 'missing_in_calc'\n", + " plants_missing_calc = list(\n", + " compared_merged[\n", + " (compared_merged[f\"{col}_calc\"].isna())\n", + " & (compared_merged[f\"{col}_egrid\"] > 0)\n", + " ].index\n", + " )\n", + " compared.loc[\n", + " compared.index.isin(plants_missing_calc), f\"{col}_status\"\n", + " ] = \"missing_in_calc\"\n", " # identify where our calculations are missing a zero value\n", - " plants_missing_zero_calc = list(compared_merged[(compared_merged[f'{col}_calc'].isna()) & (compared_merged[f'{col}_egrid'] == 0)].index)\n", - " compared.loc[compared.index.isin(plants_missing_zero_calc), f'{col}_status'] = 'missing_zero_in_calc'\n", + " plants_missing_zero_calc = list(\n", + " compared_merged[\n", + " (compared_merged[f\"{col}_calc\"].isna())\n", + " & (compared_merged[f\"{col}_egrid\"] == 0)\n", + " ].index\n", + " )\n", + " compared.loc[\n", + " compared.index.isin(plants_missing_zero_calc), f\"{col}_status\"\n", + " ] = \"missing_zero_in_calc\"\n", " # identify where egrid has a missing value instead of a zero\n", - " plants_missing_zero_egrid = list(compared_merged[(compared_merged[f'{col}_calc'] == 0) & (compared_merged[f'{col}_egrid'].isna())].index)\n", - " compared.loc[compared.index.isin(plants_missing_zero_egrid), f'{col}_status'] = 'missing_zero_in_egrid'\n", + " plants_missing_zero_egrid = list(\n", + " compared_merged[\n", + " (compared_merged[f\"{col}_calc\"] == 0)\n", + " & (compared_merged[f\"{col}_egrid\"].isna())\n", + " ].index\n", + " )\n", + " compared.loc[\n", + " compared.index.isin(plants_missing_zero_egrid), f\"{col}_status\"\n", + " ] = \"missing_zero_in_egrid\"\n", " # identify where egrid has a zero value where we have a positive value\n", - " plants_incorrect_zero_egrid = list(compared_merged[(compared_merged[f'{col}_calc'] > 0) & (compared_merged[f'{col}_egrid'] == 0)].index)\n", - " compared.loc[compared.index.isin(plants_incorrect_zero_egrid), f'{col}_status'] = '>50%'\n", + " plants_incorrect_zero_egrid = list(\n", + " compared_merged[\n", + " (compared_merged[f\"{col}_calc\"] > 0)\n", + " & (compared_merged[f\"{col}_egrid\"] == 0)\n", + " ].index\n", + " )\n", + " compared.loc[\n", + " compared.index.isin(plants_incorrect_zero_egrid), f\"{col}_status\"\n", + " ] = \">50%\"\n", "\n", "# create a dataframe that counts how many plants are in each category\n", "comparison_count = []\n", - "for col in ['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb_adjusted','co2_mass_lb']:\n", - " count = compared.groupby(f'{col}_status', dropna=False).count()['plant_name'].rename(col)\n", - " count.index = count.index.rename('status')\n", + "for col in [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb_adjusted\",\n", + " \"co2_mass_lb\",\n", + "]:\n", + " count = (\n", + " compared.groupby(f\"{col}_status\", dropna=False)\n", + " .count()[\"plant_name\"]\n", + " .rename(col)\n", + " )\n", + " count.index = count.index.rename(\"status\")\n", " comparison_count.append(count)\n", "\n", "comparison_count = pd.concat(comparison_count, axis=1).fillna(0).astype(int)\n", - "comparison_count = pd.concat([comparison_count, pd.DataFrame(comparison_count.sum().rename('Total')).T], axis=0) \n", + "comparison_count = pd.concat(\n", + " [comparison_count, pd.DataFrame(comparison_count.sum().rename(\"Total\")).T], axis=0\n", + ")\n", "comparison_count" ] }, @@ -800,28 +1143,59 @@ " 'BANGENAN':'net_generation_mwh',\n", " 'BACO2AN':'co2_mass_lb'})\"\"\"\n", "\n", - "data_columns = ['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_adjusted']\n", + "data_columns = [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_adjusted\",\n", + "]\n", "\n", - "#aggregate the plant data up to the BA level\n", - "egrid_ba = egrid_plant.groupby(['ba_code']).sum()[data_columns].reset_index()\n", + "# aggregate the plant data up to the BA level\n", + "egrid_ba = egrid_plant.groupby([\"ba_code\"]).sum()[data_columns].reset_index()\n", "\n", "# divide our calculation by the BA totals from eGRID\n", "# if there are 0 values, replace with 0.1, so that div by zero doesn't return missing value\n", - "ba_metric = plant_annual_total.groupby('ba_code', dropna=False).sum().drop(columns='plant_id_eia').replace(0,0.1).div(egrid_ba.set_index('ba_code').replace(0,0.1)).sort_values(by='co2_mass_lb').round(3)\n", + "ba_metric = (\n", + " plant_annual_total.groupby(\"ba_code\", dropna=False)\n", + " .sum()\n", + " .drop(columns=\"plant_id_eia\")\n", + " .replace(0, 0.1)\n", + " .div(egrid_ba.set_index(\"ba_code\").replace(0, 0.1))\n", + " .sort_values(by=\"co2_mass_lb\")\n", + " .round(3)\n", + ")\n", "\n", - "total = pd.DataFrame(plant_annual_total[data_columns].sum().div(egrid_ba[data_columns].sum()).rename('Total')).T\n", + "total = pd.DataFrame(\n", + " plant_annual_total[data_columns]\n", + " .sum()\n", + " .div(egrid_ba[data_columns].sum())\n", + " .rename(\"Total\")\n", + ").T\n", "\n", "# calculate the difference in the number of plants in each region\n", - "plant_count = (plant_annual_total.groupby('ba_code', dropna=False).count()['plant_id_egrid'] - egrid_plant.groupby('ba_code', dropna=False).count()['plant_id_egrid']).rename('num_plants')\n", - "ba_metric = ba_metric.merge(plant_count, how='left', left_index=True, right_index=True).drop(columns=['plant_id_egrid']).sort_index()\n", + "plant_count = (\n", + " plant_annual_total.groupby(\"ba_code\", dropna=False).count()[\"plant_id_egrid\"]\n", + " - egrid_plant.groupby(\"ba_code\", dropna=False).count()[\"plant_id_egrid\"]\n", + ").rename(\"num_plants\")\n", + "ba_metric = (\n", + " ba_metric.merge(plant_count, how=\"left\", left_index=True, right_index=True)\n", + " .drop(columns=[\"plant_id_egrid\"])\n", + " .sort_index()\n", + ")\n", "\n", - "ba_metric = pd.concat([ba_metric, total], axis=0).round(2) \n", + "ba_metric = pd.concat([ba_metric, total], axis=0).round(2)\n", "\n", - "ba_metric = ba_metric[data_columns + ['num_plants']]\n", + "ba_metric = ba_metric[data_columns + [\"num_plants\"]]\n", "\n", - "columns_to_check = ['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb']\n", + "columns_to_check = [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + "]\n", "\n", - "with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n", + "with pd.option_context(\"display.max_rows\", None, \"display.max_columns\", None):\n", " display(ba_metric[~(ba_metric[columns_to_check] == 1).all(axis=1)])" ] }, @@ -832,10 +1206,17 @@ "outputs": [], "source": [ "# how much co2 comes from CEMS vs EIA\n", - "data_source_by_ba = pd.pivot_table(eia923_allocated, values='co2_mass_lb', index='ba_code', columns='data_source', dropna=False, aggfunc=np.sum).replace(0,0.001)\n", + "data_source_by_ba = pd.pivot_table(\n", + " eia923_allocated,\n", + " values=\"co2_mass_lb\",\n", + " index=\"ba_code\",\n", + " columns=\"data_source\",\n", + " dropna=False,\n", + " aggfunc=np.sum,\n", + ").replace(0, 0.001)\n", "data_source_by_ba = data_source_by_ba.div(data_source_by_ba.sum(axis=1), axis=0)\n", - "with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n", - " display(data_source_by_ba.round(3).fillna(0).sort_values(by='cems'))" + "with pd.option_context(\"display.max_rows\", None, \"display.max_columns\", None):\n", + " display(data_source_by_ba.round(3).fillna(0).sort_values(by=\"cems\"))" ] }, { @@ -889,12 +1270,12 @@ "outputs": [], "source": [ "# examine specific plants in a category\n", - "value = 'fuel_consumed_mmbtu'\n", - "status = '>50%'\n", + "value = \"fuel_consumed_mmbtu\"\n", + "status = \">50%\"\n", "\n", - "#compared_merged.loc[64877,:]\n", + "# compared_merged.loc[64877,:]\n", "\n", - "compared[compared[f'{value}_status'] == status].sort_values(by=value)" + "compared[compared[f\"{value}_status\"] == status].sort_values(by=value)" ] }, { @@ -903,7 +1284,7 @@ "metadata": {}, "outputs": [], "source": [ - "compared[compared[f'{value}_status'] == status].sort_values(by=value).sample(10)" + "compared[compared[f\"{value}_status\"] == status].sort_values(by=value).sample(10)" ] }, { @@ -921,7 +1302,7 @@ "metadata": {}, "outputs": [], "source": [ - "egrid_plant[egrid_plant['plant_id_eia'] == plant_to_explore]" + "egrid_plant[egrid_plant[\"plant_id_eia\"] == plant_to_explore]" ] }, { @@ -930,7 +1311,7 @@ "metadata": {}, "outputs": [], "source": [ - "plant_annual_total[plant_annual_total['plant_id_eia'] == plant_to_explore]" + "plant_annual_total[plant_annual_total[\"plant_id_eia\"] == plant_to_explore]" ] }, { @@ -939,7 +1320,7 @@ "metadata": {}, "outputs": [], "source": [ - "eia923_allocated[eia923_allocated['plant_id_eia'] == plant_to_explore].sum()" + "eia923_allocated[eia923_allocated[\"plant_id_eia\"] == plant_to_explore].sum()" ] }, { @@ -948,7 +1329,11 @@ "metadata": {}, "outputs": [], "source": [ - "cems_unit_monthly = cems.groupby(['plant_id_eia','emissions_unit_id_epa','report_date']).sum().reset_index()\n" + "cems_unit_monthly = (\n", + " cems.groupby([\"plant_id_eia\", \"emissions_unit_id_epa\", \"report_date\"])\n", + " .sum()\n", + " .reset_index()\n", + ")" ] }, { @@ -957,7 +1342,7 @@ "metadata": {}, "outputs": [], "source": [ - "cems_unit_monthly[cems_unit_monthly['plant_id_eia'] == plant_to_explore].sum()" + "cems_unit_monthly[cems_unit_monthly[\"plant_id_eia\"] == plant_to_explore].sum()" ] }, { @@ -966,7 +1351,7 @@ "metadata": {}, "outputs": [], "source": [ - "cems[(cems['plant_id_eia'] == plant_to_explore) & (cems['operating_time_hours'] > 0)]" + "cems[(cems[\"plant_id_eia\"] == plant_to_explore) & (cems[\"operating_time_hours\"] > 0)]" ] }, { @@ -975,7 +1360,7 @@ "metadata": {}, "outputs": [], "source": [ - "cems_plant_annual[cems_plant_annual['plant_id_eia'] == plant_to_explore]" + "cems_plant_annual[cems_plant_annual[\"plant_id_eia\"] == plant_to_explore]" ] }, { @@ -986,7 +1371,7 @@ "source": [ "# there are some plants that report heat input and co2 in CEMS, but are missing net generation data\n", "# TODO: we should maybe try and fill net generation data using EIA-923?\n", - "cems_plant_annual[cems_plant_annual['net_generation_mwh'] == 0]" + "cems_plant_annual[cems_plant_annual[\"net_generation_mwh\"] == 0]" ] }, { @@ -1004,8 +1389,16 @@ "metadata": {}, "outputs": [], "source": [ - "ba_plant_match = plant_annual_total[plant_annual_total['ba_code'].isna()].merge(egrid_plant[egrid_plant['ba_code'].isna()], how='left', on='plant_id_egrid', suffixes=(\"_calc\",'_egrid'))\n", - "ba_plant_match[ba_plant_match['net_generation_mwh_calc'].round(0) != ba_plant_match['net_generation_mwh_egrid'].round(0)]" + "ba_plant_match = plant_annual_total[plant_annual_total[\"ba_code\"].isna()].merge(\n", + " egrid_plant[egrid_plant[\"ba_code\"].isna()],\n", + " how=\"left\",\n", + " on=\"plant_id_egrid\",\n", + " suffixes=(\"_calc\", \"_egrid\"),\n", + ")\n", + "ba_plant_match[\n", + " ba_plant_match[\"net_generation_mwh_calc\"].round(0)\n", + " != ba_plant_match[\"net_generation_mwh_egrid\"].round(0)\n", + "]" ] }, { @@ -1014,7 +1407,7 @@ "metadata": {}, "outputs": [], "source": [ - "egrid_plant[egrid_plant['ba_code'] == 'CPLE']" + "egrid_plant[egrid_plant[\"ba_code\"] == \"CPLE\"]" ] }, { @@ -1023,7 +1416,9 @@ "metadata": {}, "outputs": [], "source": [ - "compare_plants_in_ba = egrid_plant.merge(plant_annual_total, how='outer', on='plant_id_egrid', suffixes=('_egrid','_calc'))" + "compare_plants_in_ba = egrid_plant.merge(\n", + " plant_annual_total, how=\"outer\", on=\"plant_id_egrid\", suffixes=(\"_egrid\", \"_calc\")\n", + ")" ] }, { @@ -1032,10 +1427,19 @@ "metadata": {}, "outputs": [], "source": [ - "ba = 'CPLE'\n", - "metric = 'fuel_consumed_mmbtu'\n", + "ba = \"CPLE\"\n", + "metric = \"fuel_consumed_mmbtu\"\n", "\n", - "compare_plants_in_ba[((compare_plants_in_ba['ba_code_egrid'] == ba) | (compare_plants_in_ba['ba_code_calc'] == ba)) & (compare_plants_in_ba[f'{metric}_egrid'].round(0) != compare_plants_in_ba[f'{metric}_calc'].round(0))]" + "compare_plants_in_ba[\n", + " (\n", + " (compare_plants_in_ba[\"ba_code_egrid\"] == ba)\n", + " | (compare_plants_in_ba[\"ba_code_calc\"] == ba)\n", + " )\n", + " & (\n", + " compare_plants_in_ba[f\"{metric}_egrid\"].round(0)\n", + " != compare_plants_in_ba[f\"{metric}_calc\"].round(0)\n", + " )\n", + "]" ] }, { @@ -1044,7 +1448,7 @@ "metadata": {}, "outputs": [], "source": [ - "plant_annual_total[plant_annual_total['ba_code'] == 'AMPL']" + "plant_annual_total[plant_annual_total[\"ba_code\"] == \"AMPL\"]" ] } ], diff --git a/notebooks/validation/diff_output_versions.ipynb b/notebooks/validation/diff_output_versions.ipynb index b6c8d200..7ba28be0 100644 --- a/notebooks/validation/diff_output_versions.ipynb +++ b/notebooks/validation/diff_output_versions.ipynb @@ -16,7 +16,8 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "import load_data\n", "from column_checks import get_dtypes\n", @@ -61,30 +62,62 @@ "# unzip archived data\n", "if not os.path.exists(data_folder(\"diff\")):\n", " os.mkdir(data_folder(\"diff\"))\n", - "with zipfile.ZipFile(data_folder(f\"s3_upload/{year}_{data_type}_{resolution}_us_units.zip\"), \"r\") as zip_to_unzip:\n", - " zip_to_unzip.extractall(data_folder(f\"diff/{year}_{data_type}_{resolution}_us_units\"))\n", + "with zipfile.ZipFile(\n", + " data_folder(f\"s3_upload/{year}_{data_type}_{resolution}_us_units.zip\"), \"r\"\n", + ") as zip_to_unzip:\n", + " zip_to_unzip.extractall(\n", + " data_folder(f\"diff/{year}_{data_type}_{resolution}_us_units\")\n", + " )\n", "\n", "# load archived data\n", - "prev_data = pd.read_csv(data_folder(f\"diff/{year}_{data_type}_{resolution}_us_units/plant_data.csv\"), dtype=get_dtypes()).round(0)\n", + "prev_data = pd.read_csv(\n", + " data_folder(f\"diff/{year}_{data_type}_{resolution}_us_units/plant_data.csv\"),\n", + " dtype=get_dtypes(),\n", + ").round(0)\n", "\n", "# load new data\n", - "new_data = pd.read_csv(results_folder(f\"{year}/{data_type}/{resolution}/us_units/plant_data.csv\"), dtype=get_dtypes()).round(0)\n", + "new_data = pd.read_csv(\n", + " results_folder(f\"{year}/{data_type}/{resolution}/us_units/plant_data.csv\"),\n", + " dtype=get_dtypes(),\n", + ").round(0)\n", "\n", "# load plant attributes\n", - "plant_attributes = pd.read_csv(outputs_folder(f\"{year}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes())\n", + "plant_attributes = pd.read_csv(\n", + " outputs_folder(f\"{year}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes()\n", + ")\n", "\n", - "prev_data = prev_data.merge(plant_attributes[[\"plant_id_eia\",\"ba_code\",\"fuel_category\"]], how=\"left\", on=\"plant_id_eia\")\n", - "new_data = new_data.merge(plant_attributes[[\"plant_id_eia\",\"ba_code\",\"fuel_category\"]], how=\"left\", on=\"plant_id_eia\")\n", + "prev_data = prev_data.merge(\n", + " plant_attributes[[\"plant_id_eia\", \"ba_code\", \"fuel_category\"]],\n", + " how=\"left\",\n", + " on=\"plant_id_eia\",\n", + ")\n", + "new_data = new_data.merge(\n", + " plant_attributes[[\"plant_id_eia\", \"ba_code\", \"fuel_category\"]],\n", + " how=\"left\",\n", + " on=\"plant_id_eia\",\n", + ")\n", "\n", - "key_cols = [\"plant_id_eia\",\"ba_code\",\"fuel_category\"]\n", - "comparison = prev_data.set_index(key_cols).compare(new_data.set_index(key_cols), result_names=(\"previous\",\"new\"))\n", + "key_cols = [\"plant_id_eia\", \"ba_code\", \"fuel_category\"]\n", + "comparison = prev_data.set_index(key_cols).compare(\n", + " new_data.set_index(key_cols), result_names=(\"previous\", \"new\")\n", + ")\n", "\n", "# get difference\n", - "diff = comparison.groupby(level=0, axis=1).diff().rename(columns={\"new\":\"pct_diff\"}).drop(columns=[\"previous\"], level=1)\n", - "comparison = pd.concat([comparison, diff], axis=1).sort_index(axis=1, level=0, ascending=True, sort_remaining=False)\n", - "comparison.iloc[:, comparison.columns.get_level_values(1)=='pct_diff'] = (comparison.iloc[:, comparison.columns.get_level_values(1)=='pct_diff'].values / comparison.iloc[:, comparison.columns.get_level_values(1)=='previous'].values).round(2)\n", + "diff = (\n", + " comparison.groupby(level=0, axis=1)\n", + " .diff()\n", + " .rename(columns={\"new\": \"pct_diff\"})\n", + " .drop(columns=[\"previous\"], level=1)\n", + ")\n", + "comparison = pd.concat([comparison, diff], axis=1).sort_index(\n", + " axis=1, level=0, ascending=True, sort_remaining=False\n", + ")\n", + "comparison.iloc[:, comparison.columns.get_level_values(1) == \"pct_diff\"] = (\n", + " comparison.iloc[:, comparison.columns.get_level_values(1) == \"pct_diff\"].values\n", + " / comparison.iloc[:, comparison.columns.get_level_values(1) == \"previous\"].values\n", + ").round(2)\n", "\n", - "comparison\n" + "comparison" ] }, { @@ -93,7 +126,9 @@ "metadata": {}, "outputs": [], "source": [ - "comparison[comparison.loc[:,(\"co2_mass_lb_for_electricity\",\"pct_diff\")] > 0.001]#.groupby(\"ba_code\").sum().sum()" + "comparison[\n", + " comparison.loc[:, (\"co2_mass_lb_for_electricity\", \"pct_diff\")] > 0.001\n", + "] # .groupby(\"ba_code\").sum().sum()" ] }, { @@ -117,13 +152,20 @@ "# unzip archived data\n", "if not os.path.exists(data_folder(\"diff\")):\n", " os.mkdir(data_folder(\"diff\"))\n", - "with zipfile.ZipFile(data_folder(f\"s3_upload/{year}_{data_type}_{resolution}_us_units.zip\"), \"r\") as zip_to_unzip:\n", - " zip_to_unzip.extractall(data_folder(f\"diff/{year}_{data_type}_{resolution}_us_units\"))\n", + "with zipfile.ZipFile(\n", + " data_folder(f\"s3_upload/{year}_{data_type}_{resolution}_us_units.zip\"), \"r\"\n", + ") as zip_to_unzip:\n", + " zip_to_unzip.extractall(\n", + " data_folder(f\"diff/{year}_{data_type}_{resolution}_us_units\")\n", + " )\n", "\n", "# load archived data\n", "prev_data = []\n", "for ba in os.listdir(data_folder(f\"diff/{year}_{data_type}_{resolution}_us_units\")):\n", - " df = pd.read_csv(data_folder(f\"diff/{year}_{data_type}_{resolution}_us_units/{ba}\"), dtype=get_dtypes())\n", + " df = pd.read_csv(\n", + " data_folder(f\"diff/{year}_{data_type}_{resolution}_us_units/{ba}\"),\n", + " dtype=get_dtypes(),\n", + " )\n", " df[\"ba_code\"] = ba.split(\".\")[0]\n", " prev_data.append(df)\n", "\n", @@ -132,15 +174,20 @@ "# load data\n", "new_data = []\n", "for ba in os.listdir(results_folder(f\"{year}/{data_type}/{resolution}/us_units\")):\n", - " df = pd.read_csv(results_folder(f\"{year}/{data_type}/{resolution}/us_units/{ba}\"), dtype=get_dtypes())\n", + " df = pd.read_csv(\n", + " results_folder(f\"{year}/{data_type}/{resolution}/us_units/{ba}\"),\n", + " dtype=get_dtypes(),\n", + " )\n", " df[\"ba_code\"] = ba.split(\".\")[0]\n", " new_data.append(df)\n", "\n", "new_data = pd.concat(new_data, axis=0).reset_index(drop=True)\n", "\n", "key_cols = [\"ba_code\", \"fuel_category\"]\n", - "comparison = prev_data.set_index(key_cols).compare(new_data.set_index(key_cols), result_names=(\"previous\",\"new\"))\n", - "comparison\n" + "comparison = prev_data.set_index(key_cols).compare(\n", + " new_data.set_index(key_cols), result_names=(\"previous\", \"new\")\n", + ")\n", + "comparison" ] }, { @@ -159,22 +206,28 @@ "source": [ "# load archived data\n", "file = \"cems_cleaned\"\n", - "key_cols = [\"plant_id_eia\",\"emissions_unit_id_epa\",\"datetime_utc\"]\n", + "key_cols = [\"plant_id_eia\", \"emissions_unit_id_epa\", \"datetime_utc\"]\n", "\n", "# unzip archived data\n", "if not os.path.exists(data_folder(f\"diff/outputs_{year}\")):\n", " os.mkdir(data_folder(f\"diff/outputs_{year}\"))\n", - " with zipfile.ZipFile(data_folder(f\"zenodo/outputs_{year}.zip\"), \"r\") as zip_to_unzip:\n", + " with zipfile.ZipFile(\n", + " data_folder(f\"zenodo/outputs_{year}.zip\"), \"r\"\n", + " ) as zip_to_unzip:\n", " zip_to_unzip.extractall(data_folder(f\"diff/outputs_{year}\"))\n", "\n", "# load archived data\n", - "prev_data = pd.read_csv(data_folder(f\"diff/outputs_{year}/{file}_{year}.csv\"), dtype=get_dtypes())\n", + "prev_data = pd.read_csv(\n", + " data_folder(f\"diff/outputs_{year}/{file}_{year}.csv\"), dtype=get_dtypes()\n", + ")\n", "\n", "# load new data\n", "new_data = pd.read_csv(outputs_folder(f\"{year}/{file}_{year}.csv\"), dtype=get_dtypes())\n", "\n", - "comparison = prev_data.set_index(key_cols).compare(new_data.set_index(key_cols), result_names=(\"previous\",\"new\"))\n", - "comparison\n" + "comparison = prev_data.set_index(key_cols).compare(\n", + " new_data.set_index(key_cols), result_names=(\"previous\", \"new\")\n", + ")\n", + "comparison" ] } ], diff --git a/notebooks/validation/hourly_validation.ipynb b/notebooks/validation/hourly_validation.ipynb index a52c7a73..c5c1d9d0 100644 --- a/notebooks/validation/hourly_validation.ipynb +++ b/notebooks/validation/hourly_validation.ipynb @@ -35,6 +35,7 @@ "outputs": [], "source": [ "import sys\n", + "\n", "sys.path.append(\"../../src\")\n", "\n", "import filepaths" @@ -56,7 +57,11 @@ "outputs": [], "source": [ "# EIA-930 data after timestamp adjustments but no cleaning\n", - "raw = pd.read_csv(f\"{filepaths.data_folder()}/outputs/2020/eia930/eia930_raw.csv\", index_col=0, parse_dates=True)" + "raw = pd.read_csv(\n", + " f\"{filepaths.data_folder()}/outputs/2020/eia930/eia930_raw.csv\",\n", + " index_col=0,\n", + " parse_dates=True,\n", + ")" ] }, { @@ -74,15 +79,15 @@ " ba = ba_f.replace(\".csv\", \"\")\n", " print(ba, end=\"...\")\n", " col_name = GEN_ID.format(ba)\n", - " if col_name not in raw.columns: \n", + " if col_name not in raw.columns:\n", " continue\n", " else:\n", - " dat = pd.read_csv(path+ba_f, parse_dates=[\"datetime_utc\"])\n", - " dat = dat[dat.fuel_category==\"total\"]\n", - " dat = dat.merge(raw[ col_name], left_on=\"datetime_utc\", right_index=True)\n", - " c = dat[[\"net_generation_mwh\", col_name]].corr().to_numpy()[0,1]\n", + " dat = pd.read_csv(path + ba_f, parse_dates=[\"datetime_utc\"])\n", + " dat = dat[dat.fuel_category == \"total\"]\n", + " dat = dat.merge(raw[col_name], left_on=\"datetime_utc\", right_index=True)\n", + " c = dat[[\"net_generation_mwh\", col_name]].corr().to_numpy()[0, 1]\n", " cors[ba] = c\n", - " difs = (dat[col_name]-dat[\"net_generation_mwh\"])/dat[\"net_generation_mwh\"]\n", + " difs = (dat[col_name] - dat[\"net_generation_mwh\"]) / dat[\"net_generation_mwh\"]\n", " difs = difs.replace(np.inf, np.nan)\n", " percent_difs[ba] = difs.median()\n", " annual_gen[ba] = dat[\"net_generation_mwh\"].sum()" @@ -94,11 +99,22 @@ "metadata": {}, "outputs": [], "source": [ - "os.makedirs(f\"{filepaths.data_folder()}/outputs/{year}/validation_metrics/us_units\", exist_ok=True)\n", + "os.makedirs(\n", + " f\"{filepaths.data_folder()}/outputs/{year}/validation_metrics/us_units\",\n", + " exist_ok=True,\n", + ")\n", "\n", - "out = pd.DataFrame(data={\"Difference as percent of hourly-egrid\":percent_difs, \"Correlation\":cors, \"Annual BA generation\":annual_gen})\n", + "out = pd.DataFrame(\n", + " data={\n", + " \"Difference as percent of hourly-egrid\": percent_difs,\n", + " \"Correlation\": cors,\n", + " \"Annual BA generation\": annual_gen,\n", + " }\n", + ")\n", "out = out.sort_values(\"Annual BA generation\", ascending=False)\n", - "out.to_csv(f\"{filepaths.data_folder()}/outputs/{year}/validation_metrics/us_units/compare_930_hourlyegrid.csv\")" + "out.to_csv(\n", + " f\"{filepaths.data_folder()}/outputs/{year}/validation_metrics/us_units/compare_930_hourlyegrid.csv\"\n", + ")" ] }, { @@ -116,9 +132,9 @@ "source": [ "ba = \"NYIS\"\n", "col_name = GEN_ID.format(ba)\n", - "dat = pd.read_csv(path+ba+\".csv\", parse_dates=[\"datetime_utc\"])\n", - "dat = dat[dat.fuel_category==\"total\"]\n", - "dat = dat.merge(raw[ col_name], left_on=\"datetime_utc\", right_index=True)\n", + "dat = pd.read_csv(path + ba + \".csv\", parse_dates=[\"datetime_utc\"])\n", + "dat = dat[dat.fuel_category == \"total\"]\n", + "dat = dat.merge(raw[col_name], left_on=\"datetime_utc\", right_index=True)\n", "\n", "px.line(dat, x=\"datetime_utc\", y=[\"net_generation_mwh\", col_name])" ] @@ -136,7 +152,11 @@ "metadata": {}, "outputs": [], "source": [ - "eia930 = pd.read_csv(f\"{filepaths.data_folder()}/outputs/{year}/eia930/eia930_rolling.csv\", parse_dates=True, index_col=0)" + "eia930 = pd.read_csv(\n", + " f\"{filepaths.data_folder()}/outputs/{year}/eia930/eia930_rolling.csv\",\n", + " parse_dates=True,\n", + " index_col=0,\n", + ")" ] }, { @@ -148,21 +168,21 @@ "## Load factors from Singularity API\n", "\n", "# Use last year's egrid because that's all we have in real time\n", - "# TODO: could expand to other pollutants if we use eGRID download \n", - "url = f\"https://api.singularity.energy/v1/emissions/\" \n", - "egrid_year = str(year-1) # use last year as eGRID year\n", + "# TODO: could expand to other pollutants if we use eGRID download\n", + "url = f\"https://api.singularity.energy/v1/emissions/\"\n", + "egrid_year = str(year - 1) # use last year as eGRID year\n", "\n", "headers = {\n", - " 'X-Api-Key': os.environ['SINGULARITY_API_KEY'],\n", + " \"X-Api-Key\": os.environ[\"SINGULARITY_API_KEY\"],\n", "}\n", "\n", "factors = {}\n", "\n", - "for adjustment in [\"adjusted\", \"unadjusted\"]: \n", + "for adjustment in [\"adjusted\", \"unadjusted\"]:\n", " adjusted = adjustment == \"adjusted\"\n", " key = f\"EGRID_{egrid_year}\" if adjusted else f\"EGRID_u{egrid_year}\"\n", - " response = requests.request(\"GET\", url+key, headers=headers)\n", - " factors[adjustment] = json.loads(response.content)[\"data\"]\n" + " response = requests.request(\"GET\", url + key, headers=headers)\n", + " factors[adjustment] = json.loads(response.content)[\"data\"]" ] }, { @@ -171,7 +191,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Default factors: coal factor is missing in FPC, PACW; so need national factor \n", + "# Default factors: coal factor is missing in FPC, PACW; so need national factor\n", "default_factors = {}\n", "default_factors[\"adjusted\"] = {}\n", "default_factors[\"unadjusted\"] = {}\n", @@ -195,13 +215,13 @@ "outputs": [], "source": [ "EIA_REGIONS = {\n", - " 'BPAT',\n", - " 'CISO',\n", - " 'ISNE',\n", - " 'MISO',\n", - " 'NYIS',\n", - " 'PJM',\n", - " 'SWPP',\n", + " \"BPAT\",\n", + " \"CISO\",\n", + " \"ISNE\",\n", + " \"MISO\",\n", + " \"NYIS\",\n", + " \"PJM\",\n", + " \"SWPP\",\n", "}" ] }, @@ -211,18 +231,23 @@ "metadata": {}, "outputs": [], "source": [ - "## For each BA, use singularity factors to calculate emission rate \n", - "bas_to_calc = [ba.replace(\".csv\", \"\") for ba in os.listdir(f\"{filepaths.results_folder()}/2020/power_sector_data/hourly/us_units/\")]\n", + "## For each BA, use singularity factors to calculate emission rate\n", + "bas_to_calc = [\n", + " ba.replace(\".csv\", \"\")\n", + " for ba in os.listdir(\n", + " f\"{filepaths.results_folder()}/2020/power_sector_data/hourly/us_units/\"\n", + " )\n", + "]\n", "\n", "fuel_categories = {\n", - " \"coal\":\"COL\",\n", - " \"natural_gas\":\"NG\",\n", - " \"other\":\"OTH\",\n", - " \"hydro\":\"WAT\",\n", - " \"wind\":\"WND\",\n", - " \"solar\":\"SUN\",\n", - " \"nuclear\":\"NUC\",\n", - " \"petroleum\":\"OIL\"\n", + " \"coal\": \"COL\",\n", + " \"natural_gas\": \"NG\",\n", + " \"other\": \"OTH\",\n", + " \"hydro\": \"WAT\",\n", + " \"wind\": \"WND\",\n", + " \"solar\": \"SUN\",\n", + " \"nuclear\": \"NUC\",\n", + " \"petroleum\": \"OIL\",\n", "}\n", "\n", "for ba in bas_to_calc:\n", @@ -231,24 +256,41 @@ " print(f\"missing ba {singularity_ba}\")\n", " continue\n", "\n", - " out = pd.DataFrame(index=eia930.index, columns=[\"adjusted_carbon\",\"unajusted_carbon\", \"adjusted_rate\", \"unadjusted_rate\"])\n", + " out = pd.DataFrame(\n", + " index=eia930.index,\n", + " columns=[\n", + " \"adjusted_carbon\",\n", + " \"unajusted_carbon\",\n", + " \"adjusted_rate\",\n", + " \"unadjusted_rate\",\n", + " ],\n", + " )\n", "\n", " for adjustment in [\"adjusted\", \"unadjusted\"]:\n", " s_fuels = list(factors[adjustment][singularity_ba].keys())\n", - " s_factors = [factors[adjustment][singularity_ba][f]['value'] for f in s_fuels]\n", - " # Add default factors for missing fuel types \n", + " s_factors = [factors[adjustment][singularity_ba][f][\"value\"] for f in s_fuels]\n", + " # Add default factors for missing fuel types\n", " for f in default_factors[adjustment].keys():\n", - " if f not in s_fuels: \n", + " if f not in s_fuels:\n", " s_fuels.append(f)\n", " s_factors.append(default_factors[adjustment][f])\n", " fuels = [fuel_categories[f] for f in s_fuels]\n", " generation_labels = [f\"EBA.{ba}-ALL.NG.{f}.H\" for f in fuels]\n", "\n", - " out.loc[:,f\"{adjustment}_carbon\"] = eia930[generation_labels].mul(s_factors, axis='columns').sum(axis='columns')\n", - " out.loc[:,f\"{adjustment}_rate\"] = out.loc[:,f\"{adjustment}_carbon\"] / eia930.loc[:,f\"EBA.{ba}-ALL.NG.H\"]\n", + " out.loc[:, f\"{adjustment}_carbon\"] = (\n", + " eia930[generation_labels].mul(s_factors, axis=\"columns\").sum(axis=\"columns\")\n", + " )\n", + " out.loc[:, f\"{adjustment}_rate\"] = (\n", + " out.loc[:, f\"{adjustment}_carbon\"] / eia930.loc[:, f\"EBA.{ba}-ALL.NG.H\"]\n", + " )\n", "\n", - " os.makedirs(f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/\", exist_ok=True)\n", - " out.to_csv(f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/{ba}.csv\")\n" + " os.makedirs(\n", + " f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/\",\n", + " exist_ok=True,\n", + " )\n", + " out.to_csv(\n", + " f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/{ba}.csv\"\n", + " )" ] }, { @@ -266,8 +308,12 @@ "metadata": {}, "outputs": [], "source": [ - "gen_path = f\"{filepaths.data_folder()}/results/{year}/power_sector_data/hourly/us_units/\"\n", - "consumed_path = f\"{filepaths.data_folder()}/results/{year}/carbon_accounting/hourly/us_units/\"" + "gen_path = (\n", + " f\"{filepaths.data_folder()}/results/{year}/power_sector_data/hourly/us_units/\"\n", + ")\n", + "consumed_path = (\n", + " f\"{filepaths.data_folder()}/results/{year}/carbon_accounting/hourly/us_units/\"\n", + ")" ] }, { @@ -290,39 +336,60 @@ "med_rate = {}\n", "cors = {}\n", "max_difs = {}\n", - "for ba in os.listdir(f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/\"):\n", - " if ba == \".DS_Store\": # just some os stuff\n", - " continue \n", + "for ba in os.listdir(\n", + " f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/\"\n", + "):\n", + " if ba == \".DS_Store\": # just some os stuff\n", + " continue\n", " ba = ba.replace(\".csv\", \"\")\n", - " singularity_dat = pd.read_csv(f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/{ba}.csv\", index_col=0, parse_dates=True)\n", + " singularity_dat = pd.read_csv(\n", + " f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/{ba}.csv\",\n", + " index_col=0,\n", + " parse_dates=True,\n", + " )\n", " # hourly_consumed = pd.read_csv(consumed_path+ba+\".csv\",\n", - " # usecols=[\"datetime_utc\", \"consumed_co2_rate_lb_per_mwh_for_electricity\", \"consumed_co2_rate_lb_per_mwh_adjusted\"], \n", + " # usecols=[\"datetime_utc\", \"consumed_co2_rate_lb_per_mwh_for_electricity\", \"consumed_co2_rate_lb_per_mwh_adjusted\"],\n", " # index_col=\"datetime_utc\", parse_dates=True)\n", - " hourly_generated = pd.read_csv(gen_path+ba+\".csv\", \n", - " usecols=[\"datetime_utc\", \"generated_co2_rate_lb_per_mwh_for_electricity\", \"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\", \"co2_mass_lb\", \"fuel_category\"], \n", - " index_col=\"datetime_utc\", parse_dates=True)\n", - " hourly_generated = hourly_generated.loc[hourly_generated.fuel_category==\"total\"]\n", + " hourly_generated = pd.read_csv(\n", + " gen_path + ba + \".csv\",\n", + " usecols=[\n", + " \"datetime_utc\",\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity\",\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\",\n", + " \"co2_mass_lb\",\n", + " \"fuel_category\",\n", + " ],\n", + " index_col=\"datetime_utc\",\n", + " parse_dates=True,\n", + " )\n", + " hourly_generated = hourly_generated.loc[hourly_generated.fuel_category == \"total\"]\n", " hourly_generated = hourly_generated.sort_index()\n", - " all_dat = pd.concat([singularity_dat, hourly_generated], axis='columns')\n", + " all_dat = pd.concat([singularity_dat, hourly_generated], axis=\"columns\")\n", "\n", " dat_key = \"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\"\n", "\n", " # Patch fix for PJM, see https://github.com/singularity-energy/open-grid-emissions/issues/230\n", - " if ba==\"PJM\":\n", + " if ba == \"PJM\":\n", " all_dat.loc[all_dat[dat_key] < 100, dat_key] = np.nan\n", " all_dat = all_dat[\"2020-02-01T00:00\":]\n", "\n", - " # Patch fix for FPL real-time issue not caught by rolling filter \n", - " if ba==\"FPL\":\n", + " # Patch fix for FPL real-time issue not caught by rolling filter\n", + " if ba == \"FPL\":\n", " all_dat.loc[all_dat[\"adjusted_rate\"] > 5000, \"adjusted_rate\"] = np.nan\n", "\n", - "\n", " all_dat = all_dat.sort_index()\n", - " cors[ba] = all_dat[[dat_key, \"adjusted_rate\"]].corr().to_numpy()[0,1]\n", - " percent_difs[ba] = ((all_dat[\"adjusted_rate\"] - all_dat[dat_key])/all_dat[dat_key]).median()\n", - " max_difs[ba] = ((all_dat[\"adjusted_rate\"] - all_dat[dat_key])/all_dat[dat_key]).abs().replace(1.0, np.nan).max()\n", - " abs_difs[ba] = ((all_dat[\"adjusted_rate\"] - all_dat[dat_key])).median()\n", - " med_rate[ba] = all_dat[\"adjusted_rate\"].median()\n" + " cors[ba] = all_dat[[dat_key, \"adjusted_rate\"]].corr().to_numpy()[0, 1]\n", + " percent_difs[ba] = (\n", + " (all_dat[\"adjusted_rate\"] - all_dat[dat_key]) / all_dat[dat_key]\n", + " ).median()\n", + " max_difs[ba] = (\n", + " ((all_dat[\"adjusted_rate\"] - all_dat[dat_key]) / all_dat[dat_key])\n", + " .abs()\n", + " .replace(1.0, np.nan)\n", + " .max()\n", + " )\n", + " abs_difs[ba] = (all_dat[\"adjusted_rate\"] - all_dat[dat_key]).median()\n", + " med_rate[ba] = all_dat[\"adjusted_rate\"].median()" ] }, { @@ -331,35 +398,48 @@ "metadata": {}, "outputs": [], "source": [ - "out = pd.DataFrame(data={\n", - " \"Median rate difference\":abs_difs,\n", - " \"Difference as percent of OGE\":percent_difs,\n", - " \"Correlation\":cors, \n", - " \"Annual BA generation\":annual_gen,\n", - " \"Median rate\":med_rate,\n", - " })\n", + "out = pd.DataFrame(\n", + " data={\n", + " \"Median rate difference\": abs_difs,\n", + " \"Difference as percent of OGE\": percent_difs,\n", + " \"Correlation\": cors,\n", + " \"Annual BA generation\": annual_gen,\n", + " \"Median rate\": med_rate,\n", + " }\n", + ")\n", "out = out.sort_values(\"Annual BA generation\", ascending=False)\n", "\n", - "# Exclude BAs for which we couldn't calculate a real-time rate \n", - "todrop = [b for b in out.index if (b not in factors[\"adjusted\"].keys()) and (\"EIA.\"+b not in factors[\"adjusted\"].keys())]\n", - "print(f\"dropping {todrop} because they aren't included in Singularity's emission rate API\")\n", + "# Exclude BAs for which we couldn't calculate a real-time rate\n", + "todrop = [\n", + " b\n", + " for b in out.index\n", + " if (b not in factors[\"adjusted\"].keys())\n", + " and (\"EIA.\" + b not in factors[\"adjusted\"].keys())\n", + "]\n", + "print(\n", + " f\"dropping {todrop} because they aren't included in Singularity's emission rate API\"\n", + ")\n", "out = out.drop(labels=todrop)\n", "# exclude BAs for which rate is always zero (Hydro-only BAs)\n", "zero_rates = []\n", - "for ba in out.index: \n", - " if (out.loc[ba, \"Median rate\"] == 0) and (out.loc[ba, \"Median rate difference\"] == 0):\n", + "for ba in out.index:\n", + " if (out.loc[ba, \"Median rate\"] == 0) and (\n", + " out.loc[ba, \"Median rate difference\"] == 0\n", + " ):\n", " zero_rates.append(ba)\n", "print(f\"Note {zero_rates} have zero rates in OGE data\")\n", - "#out = out.drop(labels=todrop)\n", + "# out = out.drop(labels=todrop)\n", "# exclude BAs with zero net gen according to our data\n", "zero_gen = []\n", - "for ba in out.index: \n", - " if (out.loc[ba, \"Annual BA generation\"] == 0):\n", + "for ba in out.index:\n", + " if out.loc[ba, \"Annual BA generation\"] == 0:\n", " zero_gen.append(ba)\n", "print(f\"Dropping {zero_gen} because they have zero generation in OGE data\")\n", "out = out.drop(labels=zero_gen)\n", "\n", - "out.to_csv(f\"{filepaths.data_folder()}/outputs/{year}/validation_metrics/us_units/compare_real_time_rates.csv\")" + "out.to_csv(\n", + " f\"{filepaths.data_folder()}/outputs/{year}/validation_metrics/us_units/compare_real_time_rates.csv\"\n", + ")" ] }, { @@ -377,11 +457,15 @@ "metadata": {}, "outputs": [], "source": [ - "out_tbl = out.copy()#.round(2)\n", - "out_tbl[\"Annual BA generation\"] = out_tbl[\"Annual BA generation\"]/1000000 # convert to millions\n", - "out_tbl[\"Difference as percent of OGE\"] = out_tbl[\"Difference as percent of OGE\"]*100 # convert to %\n", + "out_tbl = out.copy() # .round(2)\n", + "out_tbl[\"Annual BA generation\"] = (\n", + " out_tbl[\"Annual BA generation\"] / 1000000\n", + ") # convert to millions\n", + "out_tbl[\"Difference as percent of OGE\"] = (\n", + " out_tbl[\"Difference as percent of OGE\"] * 100\n", + ") # convert to %\n", "out_tbl = out_tbl.round(2)\n", - "for line in out_tbl.to_markdown().split(\"/n\"): \n", + "for line in out_tbl.to_markdown().split(\"/n\"):\n", " print(line)" ] }, @@ -411,47 +495,80 @@ "ba_of_interest = \"BPAT\"\n", "\n", "\n", - "\n", - "real_time = pd.read_csv(f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/{ba_of_interest}.csv\", index_col=0, parse_dates=True)\n", + "real_time = pd.read_csv(\n", + " f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/{ba_of_interest}.csv\",\n", + " index_col=0,\n", + " parse_dates=True,\n", + ")\n", "real_time = real_time[\"2020-01-01T00:00\":]\n", "if ba_of_interest == \"NYIS\":\n", - " # NYIS has a hole in the EIA data that's not there in ISO data: fill it \n", - " nyis_hole = pd.Series(data=[313, 287.79, 262.215], index=[\"2020-03-30T01:00+00\", \"2020-03-30T02:00+00\", \"2020-03-30T03:00+00\"])\n", + " # NYIS has a hole in the EIA data that's not there in ISO data: fill it\n", + " nyis_hole = pd.Series(\n", + " data=[313, 287.79, 262.215],\n", + " index=[\"2020-03-30T01:00+00\", \"2020-03-30T02:00+00\", \"2020-03-30T03:00+00\"],\n", + " )\n", " real_time.loc[nyis_hole.index, \"adjusted_rate\"] = nyis_hole\n", "\n", - "hourly_consumed = pd.read_csv(consumed_path+ba_of_interest+\".csv\",\n", - " usecols=[\"datetime_utc\", \"consumed_co2_rate_lb_per_mwh_for_electricity\", \"consumed_co2_rate_lb_per_mwh_for_electricity_adjusted\"], \n", - " index_col=\"datetime_utc\", parse_dates=True)\n", - "hourly_generated = pd.read_csv(gen_path+ba_of_interest+\".csv\", \n", - " usecols=[\"datetime_utc\", \"generated_co2_rate_lb_per_mwh_for_electricity\", \"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\", \"co2_mass_lb\", \"fuel_category\"], \n", - " index_col=\"datetime_utc\", parse_dates=True)\n", + "hourly_consumed = pd.read_csv(\n", + " consumed_path + ba_of_interest + \".csv\",\n", + " usecols=[\n", + " \"datetime_utc\",\n", + " \"consumed_co2_rate_lb_per_mwh_for_electricity\",\n", + " \"consumed_co2_rate_lb_per_mwh_for_electricity_adjusted\",\n", + " ],\n", + " index_col=\"datetime_utc\",\n", + " parse_dates=True,\n", + ")\n", + "hourly_generated = pd.read_csv(\n", + " gen_path + ba_of_interest + \".csv\",\n", + " usecols=[\n", + " \"datetime_utc\",\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity\",\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\",\n", + " \"co2_mass_lb\",\n", + " \"fuel_category\",\n", + " ],\n", + " index_col=\"datetime_utc\",\n", + " parse_dates=True,\n", + ")\n", "\n", - "all_dat = pd.concat([real_time, hourly_consumed, hourly_generated.loc[hourly_generated.fuel_category==\"total\"]], axis='columns')\n", + "all_dat = pd.concat(\n", + " [\n", + " real_time,\n", + " hourly_consumed,\n", + " hourly_generated.loc[hourly_generated.fuel_category == \"total\"],\n", + " ],\n", + " axis=\"columns\",\n", + ")\n", "all_dat = all_dat.sort_index()\n", "\n", - "all_dat[\"percent_difs\"] = (all_dat[\"adjusted_rate\"] - all_dat[\"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\"])/all_dat[\"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\"]\n", + "all_dat[\"percent_difs\"] = (\n", + " all_dat[\"adjusted_rate\"]\n", + " - all_dat[\"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\"]\n", + ") / all_dat[\"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\"]\n", "\n", - "#all_dat = all_dat.loc[parse_dt(\"2020-07-19T00:00+00\"):parse_dt(\"2020-08-06T00:00+00\")]\n", - "#all_dat = all_dat.loc[parse_dt(\"2020-02-10T00:00+00\"):parse_dt(\"2020-02-28T00:00+00\")]\n", + "# all_dat = all_dat.loc[parse_dt(\"2020-07-19T00:00+00\"):parse_dt(\"2020-08-06T00:00+00\")]\n", + "# all_dat = all_dat.loc[parse_dt(\"2020-02-10T00:00+00\"):parse_dt(\"2020-02-28T00:00+00\")]\n", "\n", - "fig = px.line(all_dat, x=all_dat.index, y=[\"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\", \"adjusted_rate\"], \n", + "fig = px.line(\n", + " all_dat,\n", + " x=all_dat.index,\n", + " y=[\"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\", \"adjusted_rate\"],\n", " title=f\"Real time accuracy in {ba_of_interest}\",\n", - " labels={\n", - " \"value\":\"CO2 emission rate (lb/mwh)\",\n", - " \"index\":\"Hour (UTC)\"\n", - " }, \n", - " template='plotly_white',\n", + " labels={\"value\": \"CO2 emission rate (lb/mwh)\", \"index\": \"Hour (UTC)\"},\n", + " template=\"plotly_white\",\n", ")\n", "\n", "newnames = {\n", - " 'generated_co2_rate_lb_per_mwh_for_electricity_adjusted': 'Historical benchmark',\n", - " 'adjusted_rate': 'Real-time data'}\n", - "fig.for_each_trace(lambda t: t.update(name = newnames[t.name]))\n", - "fig.update_layout(legend_title_text='')\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\": \"Historical benchmark\",\n", + " \"adjusted_rate\": \"Real-time data\",\n", + "}\n", + "fig.for_each_trace(lambda t: t.update(name=newnames[t.name]))\n", + "fig.update_layout(legend_title_text=\"\")\n", "fig.show()\n", "\n", "os.makedirs(f\"{filepaths.data_folder()}/outputs/viz/\", exist_ok=True)\n", - "#pio.write_image(fig, f\"{filepaths.data_folder()}/outputs/viz/{ba_of_interest}_aug_sm.jpg\", width=1000*(2/3), height=500*(2/3), scale=3)" + "# pio.write_image(fig, f\"{filepaths.data_folder()}/outputs/viz/{ba_of_interest}_aug_sm.jpg\", width=1000*(2/3), height=500*(2/3), scale=3)" ] }, { @@ -469,34 +586,60 @@ "metadata": {}, "outputs": [], "source": [ - "### Plot natural gas emission rate: does this explain larger gap in summer? \n", + "### Plot natural gas emission rate: does this explain larger gap in summer?\n", "\n", - "hourly_rate = pd.read_csv(gen_path+ba_of_interest+\".csv\", \n", - " usecols=[\"datetime_utc\", \"generated_co2_rate_lb_per_mwh_for_electricity\", \"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\", \"co2_mass_lb\", \"fuel_category\"], \n", - " index_col=\"datetime_utc\", parse_dates=True)\n", + "hourly_rate = pd.read_csv(\n", + " gen_path + ba_of_interest + \".csv\",\n", + " usecols=[\n", + " \"datetime_utc\",\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity\",\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\",\n", + " \"co2_mass_lb\",\n", + " \"fuel_category\",\n", + " ],\n", + " index_col=\"datetime_utc\",\n", + " parse_dates=True,\n", + ")\n", "hourly_rate = hourly_rate[hourly_rate.fuel_category == \"natural_gas\"]\n", "\n", "fig = go.Figure()\n", - "fig.add_trace(go.Scatter(x=hourly_rate.index, y=hourly_rate[\"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\"], name=\"Hourly emission rate\"))\n", - "fig.add_trace(go.Scatter(x=[parse_dt(\"2020-01-01T00:00\"), parse_dt(\"2021-01-01T00:00\")], \n", - " y=[factors[\"adjusted\"][\"EIA.\"+ba_of_interest][\"natural_gas\"][\"value\"], factors[\"adjusted\"][\"EIA.\"+ba_of_interest][\"natural_gas\"][\"value\"]], \n", - " name=\"eGRID annual emission rate\", mode=\"lines\"\n", - "))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=hourly_rate.index,\n", + " y=hourly_rate[\"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\"],\n", + " name=\"Hourly emission rate\",\n", + " )\n", + ")\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=[parse_dt(\"2020-01-01T00:00\"), parse_dt(\"2021-01-01T00:00\")],\n", + " y=[\n", + " factors[\"adjusted\"][\"EIA.\" + ba_of_interest][\"natural_gas\"][\"value\"],\n", + " factors[\"adjusted\"][\"EIA.\" + ba_of_interest][\"natural_gas\"][\"value\"],\n", + " ],\n", + " name=\"eGRID annual emission rate\",\n", + " mode=\"lines\",\n", + " )\n", + ")\n", "\n", "fig.update_xaxes(range=(parse_dt(\"2020-01-01T00:00\"), parse_dt(\"2021-01-01T00:00\")))\n", - "fig.update_layout(template=\"plotly_white\", title=f\"Natural gas emission rates in {ba_of_interest}O\",\n", - "legend=dict(\n", - " yanchor=\"top\",\n", - " y=0.99,\n", - " xanchor=\"left\",\n", - " x=0.01\n", - "))\n", + "fig.update_layout(\n", + " template=\"plotly_white\",\n", + " title=f\"Natural gas emission rates in {ba_of_interest}O\",\n", + " legend=dict(yanchor=\"top\", y=0.99, xanchor=\"left\", x=0.01),\n", + ")\n", "\n", - "fig.update_yaxes(title_text='Natural gas emission rate
(lb CO2/MWh)')\n", + "fig.update_yaxes(title_text=\"Natural gas emission rate
(lb CO2/MWh)\")\n", "\n", "fig.show()\n", "\n", - "pio.write_image(fig, f\"{filepaths.data_folder()}/outputs/viz/gas_rate_{ba_of_interest}.jpg\", width=1000*(4/5), height=500*(4/5), scale=3)" + "pio.write_image(\n", + " fig,\n", + " f\"{filepaths.data_folder()}/outputs/viz/gas_rate_{ba_of_interest}.jpg\",\n", + " width=1000 * (4 / 5),\n", + " height=500 * (4 / 5),\n", + " scale=3,\n", + ")" ] }, { @@ -505,21 +648,28 @@ "metadata": {}, "outputs": [], "source": [ - "oge_generation = pd.read_csv(gen_path+ba_of_interest+\".csv\", \n", - " usecols=[\"datetime_utc\", \"fuel_category\", \"net_generation_mwh\"], \n", - " index_col=\"datetime_utc\", parse_dates=True)\n", - "oge_generation = oge_generation.pivot(columns=\"fuel_category\", values=\"net_generation_mwh\")\n", + "oge_generation = pd.read_csv(\n", + " gen_path + ba_of_interest + \".csv\",\n", + " usecols=[\"datetime_utc\", \"fuel_category\", \"net_generation_mwh\"],\n", + " index_col=\"datetime_utc\",\n", + " parse_dates=True,\n", + ")\n", + "oge_generation = oge_generation.pivot(\n", + " columns=\"fuel_category\", values=\"net_generation_mwh\"\n", + ")\n", "\n", - "# plot real-time and OGE per-fuel generation in FPC to identify source of neg correlation \n", - "eiacols = [f'EBA.{ba_of_interest}-ALL.NG.COL.H',\n", - " f'EBA.{ba_of_interest}-ALL.NG.NG.H',\n", - " f'EBA.{ba_of_interest}-ALL.NG.NUC.H',\n", - " f'EBA.{ba_of_interest}-ALL.NG.OIL.H',\n", - " f'EBA.{ba_of_interest}-ALL.NG.OTH.H',\n", - " f'EBA.{ba_of_interest}-ALL.NG.SUN.H',\n", - " f'EBA.{ba_of_interest}-ALL.NG.UNK.H',\n", - " f'EBA.{ba_of_interest}-ALL.NG.WAT.H',\n", - " f'EBA.{ba_of_interest}-ALL.NG.WND.H']\n", + "# plot real-time and OGE per-fuel generation in FPC to identify source of neg correlation\n", + "eiacols = [\n", + " f\"EBA.{ba_of_interest}-ALL.NG.COL.H\",\n", + " f\"EBA.{ba_of_interest}-ALL.NG.NG.H\",\n", + " f\"EBA.{ba_of_interest}-ALL.NG.NUC.H\",\n", + " f\"EBA.{ba_of_interest}-ALL.NG.OIL.H\",\n", + " f\"EBA.{ba_of_interest}-ALL.NG.OTH.H\",\n", + " f\"EBA.{ba_of_interest}-ALL.NG.SUN.H\",\n", + " f\"EBA.{ba_of_interest}-ALL.NG.UNK.H\",\n", + " f\"EBA.{ba_of_interest}-ALL.NG.WAT.H\",\n", + " f\"EBA.{ba_of_interest}-ALL.NG.WND.H\",\n", + "]\n", "\n", "toplot = pd.concat([eia930[eiacols], oge_generation])" ] @@ -539,29 +689,29 @@ "metadata": {}, "outputs": [], "source": [ - "# plot real-time and OGE per-fuel generation in FPC to identify source of neg correlation \n", + "# plot real-time and OGE per-fuel generation in FPC to identify source of neg correlation\n", "plotcols = [\n", - " #f'EBA.{ba_of_interest}-ALL.NG.COL.H',\n", - " #f'EBA.{ba_of_interest}-ALL.NG.NG.H',\n", - " #f'EBA.{ba_of_interest}-ALL.NG.NUC.H',\n", - " #f'EBA.{ba_of_interest}-ALL.NG.OIL.H',\n", - " f'EBA.{ba_of_interest}-ALL.NG.OTH.H',\n", - " #f'EBA.{ba_of_interest}-ALL.NG.SUN.H',\n", - " f'EBA.{ba_of_interest}-ALL.NG.UNK.H',\n", - " f'EBA.{ba_of_interest}-ALL.NG.WAT.H',\n", - " #f'EBA.{ba_of_interest}-ALL.NG.WND.H',\n", - " #\"biomass\",\n", - " #\"natural_gas\",\n", - " #\"petroleum\",\n", - " #\"solar\",\n", - " #\"total\",\n", - " #\"waste\",\n", - " #\"geothermal\", \n", - " \"hydro\",\n", - " #\"wind\",\n", - " ]\n", + " # f'EBA.{ba_of_interest}-ALL.NG.COL.H',\n", + " # f'EBA.{ba_of_interest}-ALL.NG.NG.H',\n", + " # f'EBA.{ba_of_interest}-ALL.NG.NUC.H',\n", + " # f'EBA.{ba_of_interest}-ALL.NG.OIL.H',\n", + " f\"EBA.{ba_of_interest}-ALL.NG.OTH.H\",\n", + " # f'EBA.{ba_of_interest}-ALL.NG.SUN.H',\n", + " f\"EBA.{ba_of_interest}-ALL.NG.UNK.H\",\n", + " f\"EBA.{ba_of_interest}-ALL.NG.WAT.H\",\n", + " # f'EBA.{ba_of_interest}-ALL.NG.WND.H',\n", + " # \"biomass\",\n", + " # \"natural_gas\",\n", + " # \"petroleum\",\n", + " # \"solar\",\n", + " # \"total\",\n", + " # \"waste\",\n", + " # \"geothermal\",\n", + " \"hydro\",\n", + " # \"wind\",\n", + "]\n", "\n", - "px.line(toplot[plotcols])\n" + "px.line(toplot[plotcols])" ] }, { @@ -570,7 +720,7 @@ "metadata": {}, "outputs": [], "source": [ - "# What plants " + "# What plants" ] }, { @@ -579,7 +729,11 @@ "metadata": {}, "outputs": [], "source": [ - "px.histogram(all_dat, x=\"percent_difs\", title=\"NYIS hourly difference between benchmark and real-time
as percent of benchmark \")" + "px.histogram(\n", + " all_dat,\n", + " x=\"percent_difs\",\n", + " title=\"NYIS hourly difference between benchmark and real-time
as percent of benchmark \",\n", + ")" ] }, { @@ -605,7 +759,7 @@ "metadata": {}, "outputs": [], "source": [ - "(55539223793.10689 - 57691924000)/57691924000" + "(55539223793.10689 - 57691924000) / 57691924000" ] }, { @@ -633,7 +787,13 @@ "metadata": {}, "outputs": [], "source": [ - "px.scatter(out, x=\"Difference as percent of OGE\", y=\"Correlation\", size=\"Annual BA generation\", template=\"plotly_white\")#, text=out.index)" + "px.scatter(\n", + " out,\n", + " x=\"Difference as percent of OGE\",\n", + " y=\"Correlation\",\n", + " size=\"Annual BA generation\",\n", + " template=\"plotly_white\",\n", + ") # , text=out.index)" ] }, { @@ -642,17 +802,38 @@ "metadata": {}, "outputs": [], "source": [ - "#fig = px.scatter(out, x=\"Annual BA generation\", y=\"Correlation\", template=\"plotly_white\")#, text=out.index)\n", + "# fig = px.scatter(out, x=\"Annual BA generation\", y=\"Correlation\", template=\"plotly_white\")#, text=out.index)\n", "fig = go.Figure()\n", "\n", - "fig.add_trace(go.Scatter(y=[-3000000,805000000], x=[1,1], line={\"width\":2, \"color\":\"lightslategrey\"}, mode=\"lines\"))\n", - "fig.add_trace( go.Scatter(y=out[\"Annual BA generation\"], x=out[\"Correlation\"], text=out.index, mode=\"markers\", marker={\"color\":\"rgb(17, 119, 51)\"})) #, color=\"Median rate\")#, text=out.index)\n", - "fig.update_yaxes(range=(-3000000,805000000))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " y=[-3000000, 805000000],\n", + " x=[1, 1],\n", + " line={\"width\": 2, \"color\": \"lightslategrey\"},\n", + " mode=\"lines\",\n", + " )\n", + ")\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " y=out[\"Annual BA generation\"],\n", + " x=out[\"Correlation\"],\n", + " text=out.index,\n", + " mode=\"markers\",\n", + " marker={\"color\": \"rgb(17, 119, 51)\"},\n", + " )\n", + ") # , color=\"Median rate\")#, text=out.index)\n", + "fig.update_yaxes(range=(-3000000, 805000000))\n", "fig.update_layout(template=\"plotly_white\", showlegend=False)\n", "\n", - "fig.update_xaxes(dtick=.250)\n", + "fig.update_xaxes(dtick=0.250)\n", "fig.show()\n", - "pio.write_image(fig, f\"{filepaths.data_folder()}/outputs/viz/cor_ba_gen.jpg\", width=800*(1/2), height=900*(1/2), scale=4)" + "pio.write_image(\n", + " fig,\n", + " f\"{filepaths.data_folder()}/outputs/viz/cor_ba_gen.jpg\",\n", + " width=800 * (1 / 2),\n", + " height=900 * (1 / 2),\n", + " scale=4,\n", + ")" ] }, { @@ -661,7 +842,7 @@ "metadata": {}, "outputs": [], "source": [ - "#px.scatter(out, x=\"Annual BA generation\", y=\"Difference as percent of OGE\")#, text=out.index)" + "# px.scatter(out, x=\"Annual BA generation\", y=\"Difference as percent of OGE\")#, text=out.index)" ] }, { @@ -672,13 +853,34 @@ "source": [ "fig = go.Figure()\n", "\n", - "fig.add_trace(go.Scatter(y=[-3000000,805000000], x=[0,0], line={\"width\":2, \"color\":\"lightslategrey\"}, mode=\"lines\"))\n", - "fig.add_trace( go.Scatter(y=out[\"Annual BA generation\"], x=out[\"Median rate difference\"], text=out.index, mode=\"markers\", marker={\"color\":\"rgb(17, 119, 51)\"})) #, color=\"Median rate\")#, text=out.index)\n", - "fig.update_yaxes(range=(-3000000,805000000))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " y=[-3000000, 805000000],\n", + " x=[0, 0],\n", + " line={\"width\": 2, \"color\": \"lightslategrey\"},\n", + " mode=\"lines\",\n", + " )\n", + ")\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " y=out[\"Annual BA generation\"],\n", + " x=out[\"Median rate difference\"],\n", + " text=out.index,\n", + " mode=\"markers\",\n", + " marker={\"color\": \"rgb(17, 119, 51)\"},\n", + " )\n", + ") # , color=\"Median rate\")#, text=out.index)\n", + "fig.update_yaxes(range=(-3000000, 805000000))\n", "fig.update_layout(template=\"plotly_white\", showlegend=False)\n", "fig.update_xaxes(dtick=500)\n", "fig.show()\n", - "pio.write_image(fig, f\"{filepaths.data_folder()}/outputs/viz/dif_ba_gen.jpg\", width=800*(1/2), height=900*(1/2), scale=4)" + "pio.write_image(\n", + " fig,\n", + " f\"{filepaths.data_folder()}/outputs/viz/dif_ba_gen.jpg\",\n", + " width=800 * (1 / 2),\n", + " height=900 * (1 / 2),\n", + " scale=4,\n", + ")" ] }, { @@ -703,7 +905,7 @@ "metadata": {}, "outputs": [], "source": [ - "dat = " + "# dat =" ] }, { @@ -719,9 +921,9 @@ "metadata": {}, "outputs": [], "source": [ - "good = len(out[out[\"Difference as percent of OGE\"].abs() <= .1])\n", - "bad = len(out[out[\"Difference as percent of OGE\"].abs() > .1])\n", - "print(good/(bad+good))" + "good = len(out[out[\"Difference as percent of OGE\"].abs() <= 0.1])\n", + "bad = len(out[out[\"Difference as percent of OGE\"].abs() > 0.1])\n", + "print(good / (bad + good))" ] }, { @@ -730,9 +932,9 @@ "metadata": {}, "outputs": [], "source": [ - "for col in out.columns: \n", + "for col in out.columns:\n", " out = out.replace(np.inf, np.nan)\n", - " out = out.replace(-1*np.inf, np.nan)\n", + " out = out.replace(-1 * np.inf, np.nan)\n", " non_nan_out = out.dropna(subset=col)\n", " a = np.average(non_nan_out[col].abs(), weights=non_nan_out[\"Annual BA generation\"])\n", " print(f\"{col} = {a}\")" @@ -751,32 +953,64 @@ "metadata": {}, "outputs": [], "source": [ - "# Plot and save all BAs \n", - "for ba_of_interest in os.listdir(f\"{filepaths.data_folder()}/outputs/2020/validation/real_time_rate/\"):\n", + "# Plot and save all BAs\n", + "for ba_of_interest in os.listdir(\n", + " f\"{filepaths.data_folder()}/outputs/2020/validation/real_time_rate/\"\n", + "):\n", " ba_of_interest = ba_of_interest.replace(\".csv\", \"\")\n", " if \".DS_\" in ba_of_interest:\n", " continue\n", - " \n", - " real_time = pd.read_csv(f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/{ba_of_interest}.csv\", index_col=0, parse_dates=True)\n", + "\n", + " real_time = pd.read_csv(\n", + " f\"{filepaths.data_folder()}/outputs/{year}/validation/real_time_rate/{ba_of_interest}.csv\",\n", + " index_col=0,\n", + " parse_dates=True,\n", + " )\n", " real_time = real_time[\"2020-01-01T00:00\":]\n", "\n", - " hourly_generated = pd.read_csv(gen_path+ba_of_interest+\".csv\", \n", - " usecols=[\"datetime_utc\", \"generated_co2_rate_lb_per_mwh_for_electricity\", \"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\", \"co2_mass_lb\", \"fuel_category\"], \n", - " index_col=\"datetime_utc\", parse_dates=True)\n", + " hourly_generated = pd.read_csv(\n", + " gen_path + ba_of_interest + \".csv\",\n", + " usecols=[\n", + " \"datetime_utc\",\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity\",\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity_adjusted\",\n", + " \"co2_mass_lb\",\n", + " \"fuel_category\",\n", + " ],\n", + " index_col=\"datetime_utc\",\n", + " parse_dates=True,\n", + " )\n", "\n", - " all_dat = pd.concat([real_time, hourly_consumed, hourly_generated.loc[hourly_generated.fuel_category==\"total\"]], axis='columns')\n", + " all_dat = pd.concat(\n", + " [\n", + " real_time,\n", + " hourly_consumed,\n", + " hourly_generated.loc[hourly_generated.fuel_category == \"total\"],\n", + " ],\n", + " axis=\"columns\",\n", + " )\n", " all_dat = all_dat.sort_index()\n", "\n", - " fig = px.line(all_dat, x=all_dat.index, y=[\"generated_co2_rate_lb_per_mwh_for_electricity\", \"adjusted_rate\"], \n", + " fig = px.line(\n", + " all_dat,\n", + " x=all_dat.index,\n", + " y=[\"generated_co2_rate_lb_per_mwh_for_electricity\", \"adjusted_rate\"],\n", " title=f\"{ba_of_interest} rate comparison\",\n", - " labels={\n", - " \"value\":\"Adjsuted CO2 emission rate (lb/mwh)\",\n", - " \"index\":\"Hour\"\n", - " })\n", + " labels={\"value\": \"Adjsuted CO2 emission rate (lb/mwh)\", \"index\": \"Hour\"},\n", + " )\n", "\n", - " newnames = {'generated_co2_rate_lb_per_mwh_for_electricity': 'Our data', 'adjusted_rate': 'Real-time data'}\n", - " fig.for_each_trace(lambda t: t.update(name = newnames[t.name]))\n", - " pio.write_image(fig, f\"{filepaths.data_folder()}/outputs/viz/{ba_of_interest}.jpg\", width=1000, height=400, scale=3)" + " newnames = {\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity\": \"Our data\",\n", + " \"adjusted_rate\": \"Real-time data\",\n", + " }\n", + " fig.for_each_trace(lambda t: t.update(name=newnames[t.name]))\n", + " pio.write_image(\n", + " fig,\n", + " f\"{filepaths.data_folder()}/outputs/viz/{ba_of_interest}.jpg\",\n", + " width=1000,\n", + " height=400,\n", + " scale=3,\n", + " )" ] }, { @@ -789,7 +1023,7 @@ ], "metadata": { "kernelspec": { - "display_name": "oge_update", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -803,9 +1037,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8 | packaged by conda-forge | (main, Nov 24 2022, 14:07:00) [MSC v.1916 64 bit (AMD64)]" + "version": "3.10.4" }, - "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "a6b598b31fc646bdc0acd5c2004810e407b47ff3b1550e1d461e8498c70ba381" @@ -813,5 +1046,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/notebooks/validation/validate_data_cleaning.ipynb b/notebooks/validation/validate_data_cleaning.ipynb index 149f5f00..ebdd650e 100644 --- a/notebooks/validation/validate_data_cleaning.ipynb +++ b/notebooks/validation/validate_data_cleaning.ipynb @@ -12,9 +12,10 @@ "%reload_ext autoreload\n", "%autoreload 2\n", "\n", - "# Tell python where to look for modules. \n", + "# Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/\")\n", "\n", "# import local modules\n", "import src.validation as validation\n", @@ -22,7 +23,7 @@ "from src.column_checks import get_dtypes\n", "\n", "year = 2020\n", - "path_prefix = ''\n", + "path_prefix = \"\"\n", "path_prefix = f\"{path_prefix}{year}\"" ] }, @@ -44,7 +45,11 @@ "metadata": {}, "outputs": [], "source": [ - "eia923_allocated = pd.read_csv(f'../data/outputs/{path_prefix}/eia923_allocated_{year}.csv', dtype=get_dtypes(), parse_dates=['report_date'])" + "eia923_allocated = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}/eia923_allocated_{year}.csv\",\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"report_date\"],\n", + ")" ] }, { @@ -55,10 +60,21 @@ "source": [ "# perform checks on allocated data\n", "# fuel consumption and co2 emissions should be positive\n", - "negative_test = validation.test_for_negative_values(eia923_allocated, ['fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_for_electricity','co2_mass_lb_adjusted'])\n", + "negative_test = validation.test_for_negative_values(\n", + " eia923_allocated,\n", + " [\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_for_electricity\",\n", + " \"co2_mass_lb_adjusted\",\n", + " ],\n", + ")\n", "\n", "# if net generation is positive, fuel consumption should be non zero\n", - "missing_fuel_test = validation.test_for_missing_fuel(eia923_allocated, 'net_generation_mwh')\n", + "missing_fuel_test = validation.test_for_missing_fuel(\n", + " eia923_allocated, \"net_generation_mwh\"\n", + ")\n", "\n", "# fuel consumed for electricity should be less than fuel consumed\n", "chp_allocation_test = validation.test_chp_allocation(eia923_allocated)\n", @@ -67,16 +83,38 @@ "missing_co2_test = validation.test_for_missing_co2(eia923_allocated)\n", "\n", "# check for generators with no data\n", - "missing_data_test = validation.test_for_missing_data(eia923_allocated, ['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_for_electricity','co2_mass_lb_adjusted'])\n", + "missing_data_test = validation.test_for_missing_data(\n", + " eia923_allocated,\n", + " [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_for_electricity\",\n", + " \"co2_mass_lb_adjusted\",\n", + " ],\n", + ")\n", "\n", "# check for generators with all data = 0\n", - "zero_data_test = validation.test_for_zero_data(eia923_allocated, ['net_generation_mwh','fuel_consumed_mmbtu','fuel_consumed_for_electricity_mmbtu','co2_mass_lb','co2_mass_lb_for_electricity','co2_mass_lb_adjusted'])\n", + "zero_data_test = validation.test_for_zero_data(\n", + " eia923_allocated,\n", + " [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_for_electricity\",\n", + " \"co2_mass_lb_adjusted\",\n", + " ],\n", + ")\n", "\n", "# check for missing energy source code\n", "missing_esc_test = validation.test_for_missing_energy_source_code(eia923_allocated)\n", "\n", "# check for missing and incorrect prime movers\n", - "incorrect_pm_test, missing_pm_test = validation.test_for_missing_incorrect_prime_movers(eia923_allocated, year)\n", + "incorrect_pm_test, missing_pm_test = validation.test_for_missing_incorrect_prime_movers(\n", + " eia923_allocated, year\n", + ")\n", "\n", "# check for missing subplant ids\n", "eia_missing_subplant_test = validation.test_for_missing_subplant_id(eia923_allocated)" @@ -109,7 +147,26 @@ "source": [ "# what percent of emissions is reported in CEMS vs EIA\n", "# NOTE: This does not include emissions only reported by CEMS, so the % may be higher\n", - "(eia923_allocated.groupby('hourly_data_source')[[\"net_generation_mwh\",\"fuel_consumed_mmbtu\", 'co2_mass_lb',\"co2_mass_lb_for_electricity\"]].sum() / eia923_allocated.groupby('hourly_data_source')[[\"net_generation_mwh\",\"fuel_consumed_mmbtu\", 'co2_mass_lb',\"co2_mass_lb_for_electricity\"]].sum().sum(axis=0)).round(3)" + "(\n", + " eia923_allocated.groupby(\"hourly_data_source\")[\n", + " [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_for_electricity\",\n", + " ]\n", + " ].sum()\n", + " / eia923_allocated.groupby(\"hourly_data_source\")[\n", + " [\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"co2_mass_lb_for_electricity\",\n", + " ]\n", + " ]\n", + " .sum()\n", + " .sum(axis=0)\n", + ").round(3)" ] }, { @@ -125,7 +182,11 @@ "metadata": {}, "outputs": [], "source": [ - "cems = pd.read_csv(f'../data/outputs/{path_prefix}/cems_subplant_{year}.csv', dtype=get_dtypes(), parse_dates=['report_date'])" + "cems = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}/cems_subplant_{year}.csv\",\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"report_date\"],\n", + ")" ] }, { @@ -138,7 +199,7 @@ "cems_negative_test = validation.test_for_negative_values(cems)\n", "\n", "# if net generation is positive, fuel consumption should be non zero\n", - "cems_missing_fuel_test = validation.test_for_missing_fuel(cems,'gross_generation_mwh')\n", + "cems_missing_fuel_test = validation.test_for_missing_fuel(cems, \"gross_generation_mwh\")\n", "\n", "# fuel consumed for electricity should be less than fuel consumed\n", "cems_chp_allocation_test = validation.test_chp_allocation(cems)\n", @@ -147,13 +208,13 @@ "cems_missing_co2_test = validation.test_for_missing_co2(cems)\n", "\n", "# check for missing energy source code\n", - "#cems_missing_esc_test = validation.test_for_missing_energy_source_code(cems)\n", + "# cems_missing_esc_test = validation.test_for_missing_energy_source_code(cems)\n", "\n", "# test to make sure that there is a complete subplant mapping\n", "cems_missing_subplant_test = validation.test_for_missing_subplant_id(cems)\n", "\n", "# test to see if there are any net generation values greater than gross generation\n", - "gtn_test = validation.test_gtn_results(cems)\n" + "gtn_test = validation.test_gtn_results(cems)" ] }, { diff --git a/notebooks/validation/validate_hourly_profiles.ipynb b/notebooks/validation/validate_hourly_profiles.ipynb index 1564a00a..ec589bc7 100644 --- a/notebooks/validation/validate_hourly_profiles.ipynb +++ b/notebooks/validation/validate_hourly_profiles.ipynb @@ -10,7 +10,7 @@ "import sys\n", "import plotly.express as px\n", "\n", - "sys.path.append('../../../open-grid-emissions/')\n", + "sys.path.append(\"../../../open-grid-emissions/\")\n", "%reload_ext autoreload\n", "%autoreload 2\n", "from src.column_checks import get_dtypes, apply_dtypes\n", @@ -23,7 +23,7 @@ "\n", "# load data from csv\n", "year = 2020\n", - "path_prefix = ''\n", + "path_prefix = \"\"\n", "\n", "path_prefix = f\"{path_prefix}{year}\"" ] @@ -53,9 +53,27 @@ "metadata": {}, "outputs": [], "source": [ - "eia930_data_raw = eia930.load_chalendar_for_pipeline(f\"../data/outputs/{path_prefix}/eia930/eia930_raw.csv\", year=year).pipe(eia930.remove_imputed_ones).pipe(eia930.remove_months_with_zero_data)\n", - "eia930_data_roll = eia930.load_chalendar_for_pipeline(f\"../data/outputs/{path_prefix}/eia930/eia930_rolling.csv\", year=year).pipe(eia930.remove_imputed_ones).pipe(eia930.remove_months_with_zero_data)\n", - "eia930_data_cleaned = eia930.load_chalendar_for_pipeline(f\"../data/outputs/{path_prefix}/eia930/eia930_elec.csv\", year=year).pipe(eia930.remove_imputed_ones).pipe(eia930.remove_months_with_zero_data)" + "eia930_data_raw = (\n", + " eia930.load_chalendar_for_pipeline(\n", + " f\"../data/outputs/{path_prefix}/eia930/eia930_raw.csv\", year=year\n", + " )\n", + " .pipe(eia930.remove_imputed_ones)\n", + " .pipe(eia930.remove_months_with_zero_data)\n", + ")\n", + "eia930_data_roll = (\n", + " eia930.load_chalendar_for_pipeline(\n", + " f\"../data/outputs/{path_prefix}/eia930/eia930_rolling.csv\", year=year\n", + " )\n", + " .pipe(eia930.remove_imputed_ones)\n", + " .pipe(eia930.remove_months_with_zero_data)\n", + ")\n", + "eia930_data_cleaned = (\n", + " eia930.load_chalendar_for_pipeline(\n", + " f\"../data/outputs/{path_prefix}/eia930/eia930_elec.csv\", year=year\n", + " )\n", + " .pipe(eia930.remove_imputed_ones)\n", + " .pipe(eia930.remove_months_with_zero_data)\n", + ")" ] }, { @@ -64,11 +82,27 @@ "metadata": {}, "outputs": [], "source": [ - "cems = pd.read_csv(f'../data/outputs/{path_prefix}/cems_subplant_{year}.csv', dtype=get_dtypes(), parse_dates=['datetime_utc', 'report_date'])\n", - "partial_cems_scaled = pd.read_csv(f'../data/outputs/{path_prefix}/partial_cems_scaled_{year}.csv', dtype=get_dtypes(), parse_dates=['datetime_utc', 'report_date'])\n", - "eia923_allocated = pd.read_csv(f'../data/outputs/{path_prefix}/eia923_allocated_{year}.csv', dtype=get_dtypes(), parse_dates=['report_date'])\n", - "plant_attributes = pd.read_csv(f\"../data/outputs/{path_prefix}/plant_static_attributes_{year}.csv\")\n", - "primary_fuel_table = plant_attributes.drop_duplicates(subset=\"plant_id_eia\")[[\"plant_id_eia\", \"plant_primary_fuel\"]]\n", + "cems = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}/cems_subplant_{year}.csv\",\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", + "partial_cems_scaled = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}/partial_cems_scaled_{year}.csv\",\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", + "eia923_allocated = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}/eia923_allocated_{year}.csv\",\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"report_date\"],\n", + ")\n", + "plant_attributes = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}/plant_static_attributes_{year}.csv\"\n", + ")\n", + "primary_fuel_table = plant_attributes.drop_duplicates(subset=\"plant_id_eia\")[\n", + " [\"plant_id_eia\", \"plant_primary_fuel\"]\n", + "]\n", "\n", "# aggregate cems data to subplant level\n", "cems = data_cleaning.aggregate_cems_to_subplant(cems)\n", @@ -80,7 +114,7 @@ "monthly_eia_data_to_shape = eia923_allocated[\n", " (eia923_allocated[\"hourly_data_source\"] == \"eia\")\n", " & ~(eia923_allocated[\"fuel_consumed_mmbtu\"].isna())\n", - "]\n" + "]" ] }, { @@ -89,7 +123,10 @@ "metadata": {}, "outputs": [], "source": [ - "data_to_graph = eia930_data_roll[(eia930_data_roll[\"fuel_category_eia930\"] == \"solar\") & (eia930_data_roll[\"report_date\"] == \"2020-07-01\")]\n", + "data_to_graph = eia930_data_roll[\n", + " (eia930_data_roll[\"fuel_category_eia930\"] == \"solar\")\n", + " & (eia930_data_roll[\"report_date\"] == \"2020-07-01\")\n", + "]\n", "\n", "px.line(data_to_graph, x=\"datetime_local\", y=\"net_generation_mwh_930\", color=\"ba_code\")" ] @@ -144,7 +181,11 @@ "metadata": {}, "outputs": [], "source": [ - "hourly_profiles_raw[[\"ba_code\", \"fuel_category\", \"report_date\", \"profile_method\"]].drop_duplicates().drop(columns=[\"ba_code\"]).pivot_table(index=\"fuel_category\", columns=\"profile_method\", aggfunc=\"count\").fillna(0).astype(int)" + "hourly_profiles_raw[\n", + " [\"ba_code\", \"fuel_category\", \"report_date\", \"profile_method\"]\n", + "].drop_duplicates().drop(columns=[\"ba_code\"]).pivot_table(\n", + " index=\"fuel_category\", columns=\"profile_method\", aggfunc=\"count\"\n", + ").fillna(0).astype(int)" ] }, { @@ -163,7 +204,9 @@ "metadata": {}, "outputs": [], "source": [ - "national_validation = validation.validate_national_imputation_method(hourly_profiles_raw, year)\n", + "national_validation = validation.validate_national_imputation_method(\n", + " hourly_profiles_raw, year\n", + ")\n", "national_validation.groupby([\"fuel_category\"]).mean()[\"imputed_profile\"]" ] }, @@ -180,7 +223,11 @@ "metadata": {}, "outputs": [], "source": [ - "hourly_profiles_roll[[\"ba_code\", \"fuel_category\", \"report_date\", \"profile_method\"]].drop_duplicates().drop(columns=[\"ba_code\"]).pivot_table(index=\"fuel_category\", columns=\"profile_method\", aggfunc=\"count\").fillna(0).astype(int)" + "hourly_profiles_roll[\n", + " [\"ba_code\", \"fuel_category\", \"report_date\", \"profile_method\"]\n", + "].drop_duplicates().drop(columns=[\"ba_code\"]).pivot_table(\n", + " index=\"fuel_category\", columns=\"profile_method\", aggfunc=\"count\"\n", + ").fillna(0).astype(int)" ] }, { @@ -199,7 +246,9 @@ "metadata": {}, "outputs": [], "source": [ - "national_validation = validation.validate_national_imputation_method(hourly_profiles_roll, year)\n", + "national_validation = validation.validate_national_imputation_method(\n", + " hourly_profiles_roll, year\n", + ")\n", "national_validation.groupby([\"fuel_category\"]).mean()[\"imputed_profile\"]" ] }, @@ -216,7 +265,11 @@ "metadata": {}, "outputs": [], "source": [ - "hourly_profiles_cleaned[[\"ba_code\", \"fuel_category\", \"report_date\", \"profile_method\"]].drop_duplicates().drop(columns=[\"ba_code\"]).pivot_table(index=\"fuel_category\", columns=\"profile_method\", aggfunc=\"count\").fillna(0).astype(int)" + "hourly_profiles_cleaned[\n", + " [\"ba_code\", \"fuel_category\", \"report_date\", \"profile_method\"]\n", + "].drop_duplicates().drop(columns=[\"ba_code\"]).pivot_table(\n", + " index=\"fuel_category\", columns=\"profile_method\", aggfunc=\"count\"\n", + ").fillna(0).astype(int)" ] }, { @@ -225,7 +278,9 @@ "metadata": {}, "outputs": [], "source": [ - "diba_validation = validation.validate_diba_imputation_method(hourly_profiles_cleaned, year)\n", + "diba_validation = validation.validate_diba_imputation_method(\n", + " hourly_profiles_cleaned, year\n", + ")\n", "diba_validation.groupby([\"fuel_category\"]).mean()[\"imputed_profile\"]" ] }, @@ -235,7 +290,9 @@ "metadata": {}, "outputs": [], "source": [ - "national_validation = validation.validate_national_imputation_method(hourly_profiles_cleaned, year)\n", + "national_validation = validation.validate_national_imputation_method(\n", + " hourly_profiles_cleaned, year\n", + ")\n", "national_validation.groupby([\"fuel_category\"]).mean()[\"imputed_profile\"]" ] }, @@ -252,8 +309,12 @@ "metadata": {}, "outputs": [], "source": [ - "hourly_profiles = pd.read_csv(f\"../data/outputs/{path_prefix}/hourly_profiles_{year}.csv\")\n", - "shaped_eia923_data = pd.read_csv(f'../data/outputs/{path_prefix}/shaped_eia923_data_{year}.csv', dtype=get_dtypes())" + "hourly_profiles = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}/hourly_profiles_{year}.csv\"\n", + ")\n", + "shaped_eia923_data = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}/shaped_eia923_data_{year}.csv\", dtype=get_dtypes()\n", + ")" ] }, { @@ -271,9 +332,16 @@ "metadata": {}, "outputs": [], "source": [ - "data_to_graph = hourly_profiles[(hourly_profiles[\"fuel_category\"] == \"natural_gas\") & (hourly_profiles[\"ba_code\"] == \"ERCO\")]\n", + "data_to_graph = hourly_profiles[\n", + " (hourly_profiles[\"fuel_category\"] == \"natural_gas\")\n", + " & (hourly_profiles[\"ba_code\"] == \"ERCO\")\n", + "]\n", "\n", - "px.line(data_to_graph, x=\"datetime_local\", y=[\"eia930_profile\",\"cems_profile\",\"residual_profile\",\"scaled_residual_profile\"])" + "px.line(\n", + " data_to_graph,\n", + " x=\"datetime_local\",\n", + " y=[\"eia930_profile\", \"cems_profile\", \"residual_profile\", \"scaled_residual_profile\"],\n", + ")" ] }, { @@ -282,7 +350,10 @@ "metadata": {}, "outputs": [], "source": [ - "data_to_graph = shaped_eia923_data[(shaped_eia923_data[\"fuel_category\"] == \"natural_gas\") & (shaped_eia923_data[\"ba_code\"] == \"ERCO\")]\n", + "data_to_graph = shaped_eia923_data[\n", + " (shaped_eia923_data[\"fuel_category\"] == \"natural_gas\")\n", + " & (shaped_eia923_data[\"ba_code\"] == \"ERCO\")\n", + "]\n", "\n", "px.line(data_to_graph, x=\"datetime_utc\", y=[\"net_generation_mwh\"])" ] @@ -303,7 +374,9 @@ "metadata": {}, "outputs": [], "source": [ - "national_validation = validation.validate_national_imputation_method(hourly_profiles, year)\n", + "national_validation = validation.validate_national_imputation_method(\n", + " hourly_profiles, year\n", + ")\n", "national_validation.groupby([\"fuel_category\"]).mean()[\"imputed_profile\"]" ] }, @@ -318,11 +391,7 @@ " [\"ba_code\", \"fuel_category\", \"report_date\", \"profile_method\"]\n", "].drop_duplicates().drop(columns=[\"ba_code\"]).pivot_table(\n", " index=\"fuel_category\", columns=\"profile_method\", aggfunc=\"count\"\n", - ").fillna(\n", - " 0\n", - ").astype(\n", - " int\n", - ")" + ").fillna(0).astype(int)" ] } ], diff --git a/notebooks/validation/validate_negative_profiles.ipynb b/notebooks/validation/validate_negative_profiles.ipynb index 486b1322..27c44e04 100644 --- a/notebooks/validation/validate_negative_profiles.ipynb +++ b/notebooks/validation/validate_negative_profiles.ipynb @@ -17,7 +17,7 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append('../../../open-grid-emissions/')\n", + "sys.path.append(\"../../../open-grid-emissions/\")\n", "\n", "# import local modules\n", "import src.load_data as load_data\n", @@ -39,12 +39,26 @@ "source": [ "# load data from csv\n", "year = 2020\n", - "path_prefix = ''\n", + "path_prefix = \"\"\n", "\n", - "cems = pd.read_csv(f'../data/outputs/{path_prefix}{year}/cems_{year}.csv', dtype=get_dtypes(), parse_dates=['datetime_utc', 'report_date'])\n", - "partial_cems_scaled = pd.read_csv(f'../data/outputs/{path_prefix}{year}/partial_cems_scaled_{year}.csv', dtype=get_dtypes(), parse_dates=['datetime_utc', 'report_date'])\n", - "eia923_allocated = pd.read_csv(f'../data/outputs/{path_prefix}{year}/eia923_allocated_{year}.csv', dtype=get_dtypes(), parse_dates=['report_date'])\n", - "plant_attributes = pd.read_csv(f\"../data/outputs/{path_prefix}{year}/plant_static_attributes_{year}.csv\")" + "cems = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}{year}/cems_{year}.csv\",\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", + "partial_cems_scaled = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}{year}/partial_cems_scaled_{year}.csv\",\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", + "eia923_allocated = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}{year}/eia923_allocated_{year}.csv\",\n", + " dtype=get_dtypes(),\n", + " parse_dates=[\"report_date\"],\n", + ")\n", + "plant_attributes = pd.read_csv(\n", + " f\"../data/outputs/{path_prefix}{year}/plant_static_attributes_{year}.csv\"\n", + ")" ] }, { @@ -64,16 +78,41 @@ "# validate method\n", "\n", "# merge together monthly subplant totals from EIA and calculated from CEMS\n", - "eia_netgen = eia923_allocated.groupby(['plant_id_eia',\"subplant_id\",\"report_date\"], dropna=False).sum(min_count=1)['net_generation_mwh'].reset_index().dropna(subset=\"net_generation_mwh\")\n", - "calculated_netgen = cems.groupby(['plant_id_eia',\"subplant_id\",\"report_date\"], dropna=False).sum()['net_generation_mwh'].reset_index()\n", - "validated_ng = eia_netgen.merge(calculated_netgen, how=\"inner\", on=['plant_id_eia',\"subplant_id\",\"report_date\"], suffixes=(\"_eia\",\"_calc\"))\n", + "eia_netgen = (\n", + " eia923_allocated.groupby(\n", + " [\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False\n", + " )\n", + " .sum(min_count=1)[\"net_generation_mwh\"]\n", + " .reset_index()\n", + " .dropna(subset=\"net_generation_mwh\")\n", + ")\n", + "calculated_netgen = (\n", + " cems.groupby([\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False)\n", + " .sum()[\"net_generation_mwh\"]\n", + " .reset_index()\n", + ")\n", + "validated_ng = eia_netgen.merge(\n", + " calculated_netgen,\n", + " how=\"inner\",\n", + " on=[\"plant_id_eia\", \"subplant_id\", \"report_date\"],\n", + " suffixes=(\"_eia\", \"_calc\"),\n", + ")\n", "\n", - "validated_ng = validated_ng.groupby(\"plant_id_eia\").sum().reset_index().drop(columns=[\"subplant_id\"])\n", + "validated_ng = (\n", + " validated_ng.groupby(\"plant_id_eia\")\n", + " .sum()\n", + " .reset_index()\n", + " .drop(columns=[\"subplant_id\"])\n", + ")\n", "\n", "validated_ng = validated_ng.round(3)\n", - "validated_ng = validated_ng[validated_ng[[\"net_generation_mwh_eia\",\"net_generation_mwh_calc\"]].sum(axis=1) != 0]\n", + "validated_ng = validated_ng[\n", + " validated_ng[[\"net_generation_mwh_eia\", \"net_generation_mwh_calc\"]].sum(axis=1) != 0\n", + "]\n", "\n", - "validated_ng['pct_error'] = (validated_ng['net_generation_mwh_calc'] - validated_ng['net_generation_mwh_eia']) / validated_ng['net_generation_mwh_eia']\n", + "validated_ng[\"pct_error\"] = (\n", + " validated_ng[\"net_generation_mwh_calc\"] - validated_ng[\"net_generation_mwh_eia\"]\n", + ") / validated_ng[\"net_generation_mwh_eia\"]\n", "validated_ng.sort_values(by=\"pct_error\")" ] }, @@ -91,9 +130,13 @@ "outputs": [], "source": [ "# what is the most negative\n", - "negative_hourly = eia923_allocated.copy()[[\"plant_id_eia\",\"generator_id\",\"report_date\",\"net_generation_mwh\"]].dropna()\n", + "negative_hourly = eia923_allocated.copy()[\n", + " [\"plant_id_eia\", \"generator_id\", \"report_date\", \"net_generation_mwh\"]\n", + "].dropna()\n", "negative_hourly[\"hours\"] = negative_hourly.report_date.dt.daysinmonth * 24\n", - "negative_hourly[\"avg_generation_mw\"] = negative_hourly[\"net_generation_mwh\"] / negative_hourly[\"hours\"]\n", + "negative_hourly[\"avg_generation_mw\"] = (\n", + " negative_hourly[\"net_generation_mwh\"] / negative_hourly[\"hours\"]\n", + ")\n", "negative_hourly.sort_values(by=\"avg_generation_mw\")" ] }, @@ -127,24 +170,20 @@ " \"co2_mass_lb_adjusted\",\n", "]\n", "all_data = all_data.assign(\n", - " reported_eia923=lambda x: np.where(\n", - " x[columns_to_test].notnull().all(axis=1), 1, 0\n", - " )\n", + " reported_eia923=lambda x: np.where(x[columns_to_test].notnull().all(axis=1), 1, 0)\n", ")\n", "\n", "cems_monthly = (\n", - " cems_test.groupby(\n", - " [\"plant_id_eia\", \"subplant_id\",\"report_date\"], dropna=False\n", - " )\n", - " .count()[\"datetime_utc\"].reset_index())\n", + " cems_test.groupby([\"plant_id_eia\", \"subplant_id\", \"report_date\"], dropna=False)\n", + " .count()[\"datetime_utc\"]\n", + " .reset_index()\n", + ")\n", "\n", "cems_monthly[\"hourly_data_source\"] = \"cems\"\n", "\n", "# merge in the data source column from CEMS\n", "all_data = all_data.merge(\n", - " cems_monthly[\n", - " [\"plant_id_eia\", \"subplant_id\", \"report_date\", \"hourly_data_source\"]\n", - " ],\n", + " cems_monthly[[\"plant_id_eia\", \"subplant_id\", \"report_date\", \"hourly_data_source\"]],\n", " how=\"left\",\n", " on=[\"plant_id_eia\", \"subplant_id\", \"report_date\"],\n", " validate=\"m:1\",\n", @@ -153,7 +192,11 @@ "# for the remaining plants, identify the hourly data source as EIA\n", "all_data[\"hourly_data_source\"] = all_data[\"hourly_data_source\"].fillna(\"eia\")\n", "\n", - "all_data.loc[(all_data[\"hourly_data_source\"] == \"cems\") & (~all_data[\"net_generation_mwh\"].isna()), \"hourly_data_source\"] = \"both\"\n", + "all_data.loc[\n", + " (all_data[\"hourly_data_source\"] == \"cems\")\n", + " & (~all_data[\"net_generation_mwh\"].isna()),\n", + " \"hourly_data_source\",\n", + "] = \"both\"\n", "\n", "all_data" ] @@ -164,7 +207,9 @@ "metadata": {}, "outputs": [], "source": [ - "gtn_conversions = gross_to_net_generation.calculate_gross_to_net_conversion_factors(cems_test, eia_test, plant_attributes, year)\n", + "gtn_conversions = gross_to_net_generation.calculate_gross_to_net_conversion_factors(\n", + " cems_test, eia_test, plant_attributes, year\n", + ")\n", "\n", "factors_to_use = gross_to_net_generation.filter_gtn_conversion_factors(gtn_conversions)\n", "\n", @@ -211,17 +256,23 @@ " cems_test[\"gross_generation_mwh\"] + cems_test[\"annual_plant_shift_mw\"]\n", ")\n", "\n", - "cems_test.loc[cems_test[\"net_generation_mwh\"].isna(), \"gtn_method\"] = \"4_annual_plant_ratio\"\n", + "cems_test.loc[\n", + " cems_test[\"net_generation_mwh\"].isna(), \"gtn_method\"\n", + "] = \"4_annual_plant_ratio\"\n", "cems_test[\"net_generation_mwh\"] = cems_test[\"net_generation_mwh\"].fillna(\n", " cems_test[\"gross_generation_mwh\"] * cems_test[\"annual_plant_ratio\"]\n", ")\n", "\n", - "cems_test.loc[cems_test[\"net_generation_mwh\"].isna(), \"gtn_method\"] = \"5_annual_fuel_ratio\"\n", + "cems_test.loc[\n", + " cems_test[\"net_generation_mwh\"].isna(), \"gtn_method\"\n", + "] = \"5_annual_fuel_ratio\"\n", "cems_test[\"net_generation_mwh\"] = cems_test[\"net_generation_mwh\"].fillna(\n", " cems_test[\"gross_generation_mwh\"] * cems_test[\"annual_fuel_ratio\"]\n", ")\n", "\n", - "cems_test.loc[cems_test[\"net_generation_mwh\"].isna(), \"gtn_method\"] = \"6_gross_equals_net\"\n", + "cems_test.loc[\n", + " cems_test[\"net_generation_mwh\"].isna(), \"gtn_method\"\n", + "] = \"6_gross_equals_net\"\n", "cems_test[\"net_generation_mwh\"] = cems_test[\"net_generation_mwh\"].fillna(\n", " cems_test[\"gross_generation_mwh\"]\n", ")\n", @@ -229,7 +280,7 @@ "# drop intermediate columns\n", "cems_test = cems_test.drop(\n", " columns=[\n", - " #\"data_source\",\n", + " # \"data_source\",\n", " \"annual_subplant_shift_mw\",\n", " \"annual_plant_shift_mw\",\n", " \"annual_subplant_ratio\",\n", @@ -254,7 +305,9 @@ "metadata": {}, "outputs": [], "source": [ - "cems_test.groupby([\"data_source\",\"subplant_id\"], dropna=False).sum()[[\"gross_generation_mwh\",\"net_generation_mwh\"]].reset_index()" + "cems_test.groupby([\"data_source\", \"subplant_id\"], dropna=False).sum()[\n", + " [\"gross_generation_mwh\", \"net_generation_mwh\"]\n", + "].reset_index()" ] }, { @@ -263,7 +316,9 @@ "metadata": {}, "outputs": [], "source": [ - "eia_test.groupby([\"hourly_data_source\",\"subplant_id\"], dropna=False).sum()[\"net_generation_mwh\"].reset_index()" + "eia_test.groupby([\"hourly_data_source\", \"subplant_id\"], dropna=False).sum()[\n", + " \"net_generation_mwh\"\n", + "].reset_index()" ] }, { @@ -272,7 +327,9 @@ "metadata": {}, "outputs": [], "source": [ - "factors_to_use.groupby([\"data_source\",\"subplant_id\"], dropna=False).sum()[\"net_generation_mwh\"].reset_index()" + "factors_to_use.groupby([\"data_source\", \"subplant_id\"], dropna=False).sum()[\n", + " \"net_generation_mwh\"\n", + "].reset_index()" ] }, { @@ -297,9 +354,24 @@ "metadata": {}, "outputs": [], "source": [ - "data_to_graph = hourly_profiles[(hourly_profiles[\"fuel_category\"] == \"coal\") & (hourly_profiles[\"ba_code\"] == \"MISO\")]\n", + "data_to_graph = hourly_profiles[\n", + " (hourly_profiles[\"fuel_category\"] == \"coal\")\n", + " & (hourly_profiles[\"ba_code\"] == \"MISO\")\n", + "]\n", "\n", - "px.line(data_to_graph, x=\"datetime_utc\", y=[\"eia930_profile\",\"cems_profile\",\"residual_profile\",\"scaled_residual_profile\",\"shifted_residual_profile\",\"imputed_profile\",\"profile\"])" + "px.line(\n", + " data_to_graph,\n", + " x=\"datetime_utc\",\n", + " y=[\n", + " \"eia930_profile\",\n", + " \"cems_profile\",\n", + " \"residual_profile\",\n", + " \"scaled_residual_profile\",\n", + " \"shifted_residual_profile\",\n", + " \"imputed_profile\",\n", + " \"profile\",\n", + " ],\n", + ")" ] }, { @@ -311,9 +383,13 @@ "plant_to_test = 3399\n", "subplant = 1\n", "\n", - "cems_to_graph = cems[(cems[\"plant_id_eia\"] == plant_to_test) & (cems[\"subplant_id\"] == subplant)]\n", + "cems_to_graph = cems[\n", + " (cems[\"plant_id_eia\"] == plant_to_test) & (cems[\"subplant_id\"] == subplant)\n", + "]\n", "\n", - "px.line(cems_to_graph, x=\"datetime_utc\", y=[\"gross_generation_mwh\",\"net_generation_mwh\"])" + "px.line(\n", + " cems_to_graph, x=\"datetime_utc\", y=[\"gross_generation_mwh\", \"net_generation_mwh\"]\n", + ")" ] } ], diff --git a/notebooks/validation/validate_vs_egrid.ipynb b/notebooks/validation/validate_vs_egrid.ipynb index 70ec8518..8e9bb8da 100644 --- a/notebooks/validation/validate_vs_egrid.ipynb +++ b/notebooks/validation/validate_vs_egrid.ipynb @@ -16,9 +16,10 @@ "%reload_ext autoreload\n", "%autoreload 2\n", "\n", - "# Tell python where to look for modules. \n", + "# Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "# import local modules\n", "import load_data\n", @@ -75,7 +76,7 @@ ")\n", "\n", "# Load the eGRID plant table\n", - "egrid_plant = validation.load_egrid_plant_file(year)\n" + "egrid_plant = validation.load_egrid_plant_file(year)" ] }, { @@ -97,7 +98,7 @@ ") = validation.identify_plants_missing_from_our_calculations(\n", " egrid_plant, annual_plant_results, year\n", ")\n", - "missing_from_calc\n" + "missing_from_calc" ] }, { @@ -129,7 +130,7 @@ " \"fuel_consumed_for_electricity_mmbtu\",\n", " \"fuel_consumed_mmbtu\",\n", " ],\n", - "]\n" + "]" ] }, { @@ -163,7 +164,7 @@ " (double_ids[\"net_generation_mwh_calc\"] - double_ids[\"net_generation_mwh_egrid\"])\n", " / double_ids[\"net_generation_mwh_egrid\"]\n", ").round(3)\n", - "double_ids\n" + "double_ids" ] }, { @@ -175,7 +176,7 @@ "# compare egrid vs eia plant ids\n", "annual_plant_results[\n", " annual_plant_results[\"plant_id_egrid\"].duplicated(keep=False)\n", - "].groupby([\"plant_id_egrid\", \"plant_id_eia\"]).sum()\n" + "].groupby([\"plant_id_egrid\", \"plant_id_eia\"]).sum()" ] }, { @@ -191,7 +192,9 @@ "metadata": {}, "outputs": [], "source": [ - "ba_code_match = egrid_plant.set_index(\"plant_id_eia\")[[\"plant_name_eia\", \"ba_code\"]].merge(\n", + "ba_code_match = egrid_plant.set_index(\"plant_id_eia\")[\n", + " [\"plant_name_eia\", \"ba_code\"]\n", + "].merge(\n", " annual_plant_results.set_index(\"plant_id_eia\")[[\"ba_code\"]],\n", " how=\"inner\",\n", " left_index=True,\n", @@ -201,7 +204,7 @@ "\n", "# plants with missing ba code\n", "# ba_code_match[(ba_code_match['ba_code_calc'].isna()) & ~(ba_code_match['ba_code_egrid'].isna())]\n", - "ba_code_match[ba_code_match[\"ba_code_calc\"] != ba_code_match[\"ba_code_egrid\"]]\n" + "ba_code_match[ba_code_match[\"ba_code_calc\"] != ba_code_match[\"ba_code_egrid\"]]" ] }, { @@ -214,7 +217,7 @@ "ba_code_match[\n", " (ba_code_match[\"ba_code_calc\"] != ba_code_match[\"ba_code_egrid\"])\n", " & ~(ba_code_match[\"ba_code_egrid\"].isna())\n", - "]\n" + "]" ] }, { @@ -242,7 +245,7 @@ "\n", "fuel_match[\n", " fuel_match[\"plant_primary_fuel_egrid\"] != fuel_match[\"plant_primary_fuel_calc\"]\n", - "]\n" + "]" ] }, { @@ -314,7 +317,7 @@ " eia923_allocated,\n", " pudl_out,\n", " PLANTS_MISSING_FROM_EGRID,\n", - ")\n" + ")" ] }, { @@ -350,7 +353,7 @@ "comparison_count, compared = validation.compare_plant_level_results_to_egrid(\n", " segment_to_compare, egrid_plant, PLANTS_MISSING_FROM_EGRID\n", ")\n", - "comparison_count\n" + "comparison_count" ] }, { @@ -359,7 +362,7 @@ "metadata": {}, "outputs": [], "source": [ - "validation.compare_egrid_fuel_total(segment_to_compare, egrid_plant).sum()\n" + "validation.compare_egrid_fuel_total(segment_to_compare, egrid_plant).sum()" ] }, { @@ -379,7 +382,7 @@ "comparison_count, compared = validation.compare_plant_level_results_to_egrid(\n", " segment_to_compare, egrid_plant, PLANTS_MISSING_FROM_EGRID\n", ")\n", - "comparison_count\n" + "comparison_count" ] }, { @@ -413,12 +416,32 @@ "metric = \"so2_mass_lb\"\n", "status = \"<50%\"\n", "\n", - "comparison_df = comparison_df.merge(egrid_plant.set_index(\"plant_id_egrid\")[[metric]], how=\"left\", left_index=True, right_index=True, suffixes=(None,\"_egrid\"))\n", - "comparison_df = comparison_df.merge(annual_plant_results.set_index(\"plant_id_egrid\")[[metric]], how=\"left\", left_index=True, right_index=True, suffixes=(None,\"_calc\"))\n", + "comparison_df = comparison_df.merge(\n", + " egrid_plant.set_index(\"plant_id_egrid\")[[metric]],\n", + " how=\"left\",\n", + " left_index=True,\n", + " right_index=True,\n", + " suffixes=(None, \"_egrid\"),\n", + ")\n", + "comparison_df = comparison_df.merge(\n", + " annual_plant_results.set_index(\"plant_id_egrid\")[[metric]],\n", + " how=\"left\",\n", + " left_index=True,\n", + " right_index=True,\n", + " suffixes=(None, \"_calc\"),\n", + ")\n", "\n", "# show the data\n", - "columns_to_show = [\"plant_name_eia\", \"ba_code\", \"state\", metric, f\"{metric}_status\", f\"{metric}_egrid\", f\"{metric}_calc\"]\n", - "comparison_df.loc[(comparison_df[f\"{metric}_status\"] == status), columns_to_show]\n" + "columns_to_show = [\n", + " \"plant_name_eia\",\n", + " \"ba_code\",\n", + " \"state\",\n", + " metric,\n", + " f\"{metric}_status\",\n", + " f\"{metric}_egrid\",\n", + " f\"{metric}_calc\",\n", + "]\n", + "comparison_df.loc[(comparison_df[f\"{metric}_status\"] == status), columns_to_show]" ] }, { @@ -459,7 +482,9 @@ "# aggregate the plant data up to the BA level\n", "egrid_plant_ba_agg = egrid_plant.groupby([\"ba_code\"]).sum()[DATA_COLUMNS].reset_index()\n", "\n", - "egrid_plant_ba_agg[\"generated_co2_rate_lb_per_mwh\"] = egrid_plant_ba_agg[\"co2_mass_lb\"] / egrid_plant_ba_agg[\"net_generation_mwh\"]" + "egrid_plant_ba_agg[\"generated_co2_rate_lb_per_mwh\"] = (\n", + " egrid_plant_ba_agg[\"co2_mass_lb\"] / egrid_plant_ba_agg[\"net_generation_mwh\"]\n", + ")" ] }, { @@ -488,7 +513,9 @@ "\n", "calculated_ba = pd.concat(calculated_ba, axis=0)\n", "\n", - "calculated_ba[\"generated_co2_rate_lb_per_mwh\"] = calculated_ba[\"co2_mass_lb\"] / calculated_ba[\"net_generation_mwh\"]\n" + "calculated_ba[\"generated_co2_rate_lb_per_mwh\"] = (\n", + " calculated_ba[\"co2_mass_lb\"] / calculated_ba[\"net_generation_mwh\"]\n", + ")" ] }, { @@ -503,7 +530,7 @@ " - egrid_plant_ba_agg.set_index(\"ba_code\").replace(0, 0.1)\n", " )\n", " / egrid_plant_ba_agg.set_index(\"ba_code\").replace(0, 0.1)\n", - ").round(2)\n" + ").round(2)" ] }, { @@ -583,7 +610,7 @@ "]\n", "\n", "with pd.option_context(\"display.max_rows\", None, \"display.max_columns\", None):\n", - " display(ba_metric[~(ba_metric[columns_to_check] == 0).all(axis=1)])\n" + " display(ba_metric[~(ba_metric[columns_to_check] == 0).all(axis=1)])" ] }, { @@ -600,7 +627,7 @@ "metadata": {}, "outputs": [], "source": [ - "plant_to_explore = 58223\n" + "plant_to_explore = 58223" ] }, { @@ -609,7 +636,7 @@ "metadata": {}, "outputs": [], "source": [ - "egrid_plant[egrid_plant[\"plant_id_eia\"] == plant_to_explore]\n" + "egrid_plant[egrid_plant[\"plant_id_eia\"] == plant_to_explore]" ] }, { @@ -618,7 +645,7 @@ "metadata": {}, "outputs": [], "source": [ - "annual_plant_results[annual_plant_results[\"plant_id_eia\"] == plant_to_explore]\n" + "annual_plant_results[annual_plant_results[\"plant_id_eia\"] == plant_to_explore]" ] }, { @@ -627,7 +654,7 @@ "metadata": {}, "outputs": [], "source": [ - "eia923_allocated[eia923_allocated[\"plant_id_eia\"] == plant_to_explore]\n" + "eia923_allocated[eia923_allocated[\"plant_id_eia\"] == plant_to_explore]" ] }, { @@ -639,7 +666,7 @@ "eia923_allocated.loc[\n", " eia923_allocated[\"plant_id_eia\"] == plant_to_explore,\n", " [\"generator_id\", \"subplant_id\"],\n", - "].drop_duplicates()\n" + "].drop_duplicates()" ] } ], diff --git a/notebooks/visualization/map_visualization.ipynb b/notebooks/visualization/map_visualization.ipynb index 73284fbf..0f5c85e1 100644 --- a/notebooks/visualization/map_visualization.ipynb +++ b/notebooks/visualization/map_visualization.ipynb @@ -1,623 +1,788 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Maps for announcement blog post\n", - "\n", - "Visualization 2: The carbon intensity of consumed electricity differs from generated electricity\n", - "* Show a static carbon flow map focused on a single BA plus all directly-interconnected BAs\n", - "* Pick an hour when there is some particularly dirty electricity getting imported\n", - "* Each BA would be represented by a bubble, where the color changes based on carbon intensity, and carbon flows would be represented by colored arrows between the bubbles. \n", - "* To illustrate the difference between produced and consumed, we might want to have a pair of bubbles for each BA - one that shows the produced CI and one that shows the consumed CI. If we do this, we probably don’t want to vary the size of each bubble based on total generation. Or maybe we could do a split bubble - the top half shows produced CI and the bottom shows consumed CI.\n", - "\n", - "\n", - "Visualization 3: Animating hourly and consumed emissions for the whole county\n", - "* This animation should put the previous two concepts together and show how carbon flows and how CI changes across the entire country for a single day (or a week?)\n", - "* We could also potentially have two maps side by side: one that shows annual averages in bubbles (with no carbon flow), and one that shows the animated hourly flow (to really draw the distinction between annual and hourly datasets)\n", - "\n", - "\n", - "### Ref for making gif: \n", - "`https://stackoverflow.com/questions/753190/programmatically-generate-video-or-animated-gif-in-python`" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import plotly.express as px\n", - "import plotly.graph_objects as go\n", - "from plotly.colors import * \n", - "import plotly.io as pio\n", - "import os\n", - "import pandas as pd\n", - "import numpy as np\n", - "from PIL import Image\n", - "import imageio" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%reload_ext autoreload\n", - "%autoreload 2\n", - "\n", - "# # Tell python where to look for modules.\n", - "import sys\n", - "\n", - "sys.path.append(\"../../src/\")\n", - "\n", - "import output_data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ba_coords = pd.read_csv(\"resources/ba_coords.csv\", index_col=0, dtype={\"cx\":np.float64, \"cy\":np.float64})\n", - "ba_meta = pd.read_csv(\"../../data/manual/ba_reference.csv\", index_col=0)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Note: 150+ BAs are not in ba_coords\n", - "ba_list = ba_meta[(ba_meta.ba_category != \"misellaneous\") & (ba_meta.us_ba) & (ba_meta.index.isin(ba_coords.index))].index\n", - "ba_list = [ba for ba in ba_list if (f\"{ba}.csv\" in os.listdir(\"../../data/results/2020/power_sector_data/hourly/us_units/\"))]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cleaned_io = pd.read_csv(\"../../data/outputs/2020/eia930/eia930_elec.csv\", index_col=0, parse_dates=True)\n", - "cleaned_io = cleaned_io[[c for c in cleaned_io.columns if \".ID.\" in c]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "all = []\n", - "for ba in ba_list:\n", - " produced = pd.read_csv(f\"../../data/results/2020/power_sector_data/hourly/us_units/{ba}.csv\", index_col=\"datetime_utc\", parse_dates=True, usecols=[\"datetime_utc\",\"fuel_category\", \"net_generation_mwh\", \"generated_co2_rate_lb_per_mwh_for_electricity\"])\n", - " produced = produced[produced.fuel_category == \"total\"]\n", - " produced = produced.drop(columns=[\"fuel_category\"])\n", - " \n", - " if ba_meta.loc[ba,\"ba_category\"] == \"generation_only\":\n", - " consumed = pd.DataFrame(index=produced.index, columns=[[\"consumed_co2_rate_lb_per_mwh_for_electricity\"]], dtype=np.float64)\n", - " else:\n", - " consumed = pd.read_csv(f\"../../data/results/2020/carbon_accounting/hourly/us_units/{ba}.csv\", index_col=\"datetime_utc\", parse_dates=True, usecols=[\"datetime_utc\", \"consumed_co2_rate_lb_per_mwh_for_electricity\"])\n", - " consumed.columns = consumed.columns.get_level_values(0)\n", - "\n", - " both = pd.concat([produced, consumed], axis='columns')\n", - " #both = both.loc[range_start:range_end]\n", - " both = both.reset_index()\n", - " both[\"BA\"] = ba\n", - " all.append(both)\n", - "\n", - "all = pd.concat(all)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Add coordinates\n", - "all = all.merge(ba_coords, how='left', validate='many_to_one', left_on=\"BA\", right_index=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# src: https://community.plotly.com/t/how-to-include-a-colorscale-for-color-of-line-graphs/38002/3 \n", - "from ast import literal_eval\n", - "def get_color_for_val(val, vmin, vmax, pl_colors):\n", - " if pl_colors[0][:3] != 'rgb':\n", - " raise ValueError('This function works only with Plotly rgb-colorscales')\n", - " if vmin >= vmax:\n", - " raise ValueError('vmin should be < vmax')\n", - "\n", - " scale = [round(k / (len(pl_colors)), 3) for k in range(len(pl_colors) + 1)]\n", - "\n", - " colors_01 = np.array([literal_eval(color[3:]) for color in pl_colors]) / 255 # color codes in [0,1]\n", - "\n", - " v = (val - vmin) / (vmax - vmin) # val is mapped to v in [0,1]\n", - " # find two consecutive values in plotly_scale such that v is in the corresponding interval\n", - " idx = 0\n", - "\n", - " while idx < (len(scale)-2) and (v > scale[idx + 1]):\n", - " idx += 1\n", - "\n", - " vv = (v - scale[idx]) / (scale[idx + 1] - scale[idx])\n", - "\n", - " # get [0,1]-valued color code representing the rgb color corresponding to val\n", - " if idx == len(pl_colors)-1: # Make this work when some values exceed range\n", - " val_color01 = colors_01[idx] # color by last color \n", - " else: \n", - " val_color01 = colors_01[idx] + vv * (colors_01[idx + 1] - colors_01[idx])\n", - "\n", - " val_color_0255 = (255 * val_color01 + 0.5).astype(int)\n", - " return f'rgb{str(tuple(val_color_0255))}'" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "range_start = \"2020-08-01T04:00+00\"\n", - "range_end = \"2020-08-3T04:00+00\"\n", - "\n", - "#range_start = \"2020-07-21T12:00+00\"\n", - "#range_end = \"2020-07-23T12:00+00\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dir_name = \"maps\"\n", - "\n", - "c_max = 2200 #np.floor(all.generated_co2_rate_lb_per_mwh_for_electricity.max() + 100)\n", - "\n", - "hours = all.datetime_utc[(all.datetime_utc < pd.to_datetime(range_end)) & (all.datetime_utc > pd.to_datetime(range_start)) & (all.BA == \"CISO\")]\n", - "for hour in hours:\n", - " print(hour, end=\"...\")\n", - " io_toplot = cleaned_io.loc[hour]\n", - " toplot = all[all.datetime_utc == hour]\n", - " fig = go.Figure()\n", - "\n", - " toplot.loc[toplot.net_generation_mwh < 1, \"net_generation_mwh\"] = 1\n", - " sizes = np.log(toplot.net_generation_mwh)/np.log(1.5)\n", - " offset = sizes/2.5\n", - "\n", - " colorscale = diverging.RdYlGn_r\n", - " #colorscale = cmocean.solar_r\n", - "\n", - " ### From when \n", - " # max_width = io_toplot.max()\n", - " # width_factor = 8/max_width\n", - " #width_factor = 1/200\n", - " for name, val in io_toplot.iteritems():\n", - " if val <= 0: \n", - " continue \n", - " bas = name.split(\".\")[1].split(\"-\")\n", - " (ba1, ba2) = bas\n", - "\n", - " next = False\n", - " for ba in bas: \n", - " if ba not in ba_coords.index:\n", - " next=True\n", - " if ba not in toplot.BA.unique():\n", - " next=True\n", - " if next:\n", - " continue\n", - "\n", - " color = toplot.loc[toplot.BA == ba1, \"generated_co2_rate_lb_per_mwh_for_electricity\"].to_numpy()[0]\n", - "\n", - " fig.add_trace(\n", - " go.Scatter(x = ba_coords.loc[bas,\"cx\"], y = ba_coords.loc[bas,\"cy\"], opacity=1.0,\n", - " mode=\"lines\", line = dict(color=get_color_for_val(color, 0, c_max, colorscale), width=2), showlegend=False\n", - " )\n", - " )\n", - "\n", - " ################################# Plot BAs \n", - " toplot.loc[toplot.net_generation_mwh < 1, \"net_generation_mwh\"] = 1\n", - " sizes = np.log(toplot.net_generation_mwh)/np.log(1.5)\n", - " offset = sizes/1.6\n", - "\n", - " # Zero-generation BAs: plot under BAs with non-zero gen \n", - " zero_gen_bas = (toplot.net_generation_mwh == 1) # (we set to 1 above to make log work)\n", - " fig.add_trace(\n", - " go.Scatter(x=toplot.loc[zero_gen_bas,\"cx\"], y=toplot.loc[zero_gen_bas,\"cy\"]+(2/2.5), mode=\"markers\", \n", - " hoverinfo=\"text\", text=toplot.loc[zero_gen_bas,\"BA\"], \n", - " marker_symbol=\"triangle-up\",\n", - " marker=dict(color='lightgrey', \n", - " line=dict(width=1, color='DarkSlateGrey'),\n", - " size=7, opacity=1.0,\n", - " sizemode='diameter'),\n", - " showlegend=False \n", - " )\n", - " )\n", - "\n", - " fig.add_trace(\n", - " go.Scatter(x=toplot.cx, y=toplot.cy, mode=\"markers\", hoverinfo=\"text\", text=toplot.BA, \n", - " marker_symbol=\"triangle-up\", \n", - " opacity=1.0,\n", - " marker=dict(color=toplot.generated_co2_rate_lb_per_mwh_for_electricity, size=sizes,\n", - " sizemode='diameter', cmin=0, cmax=c_max, opacity=1.0,\n", - " line=dict(width=1, color='DarkSlateGrey'),\n", - " colorscale=\"rdylgn_r\"),\n", - " name=\"Generated\", \n", - " showlegend=False\n", - " )\n", - " )\n", - " consumed_toplot = ~toplot.consumed_co2_rate_lb_per_mwh_for_electricity.isna()\n", - " fig.add_trace(\n", - " go.Scatter(x=toplot.loc[consumed_toplot,\"cx\"], y=toplot.loc[consumed_toplot,\"cy\"]+offset[consumed_toplot], mode=\"markers\", \n", - " hoverinfo=\"text\", text=toplot.loc[consumed_toplot,\"BA\"], \n", - " marker_symbol=\"triangle-down\",\n", - " marker=dict(color=toplot.loc[consumed_toplot,\"consumed_co2_rate_lb_per_mwh_for_electricity\"], \n", - " size=sizes[consumed_toplot], opacity=1.0,\n", - " line=dict(width=1, color='DarkSlateGrey'),\n", - " sizemode='diameter', cmin=0, cmax=c_max, \n", - " colorbar=dict(\n", - " title=\"Emission rate
(lbs/MWh)\", orientation='v', len=.8, \n", - " thickness=20, yanchor='bottom', y=0, xpad=20\n", - " ),\n", - " colorscale=\"rdylgn_r\"\n", - " ),\n", - " name=\"Consumed\", \n", - " showlegend=False \n", - " )\n", - " )\n", - "\n", - " # Legends: don't want colored markers\n", - " fig.add_trace(\n", - " go.Scatter(x=[-10], y=[-10], mode=\"markers\", \n", - " marker_symbol=\"triangle-up\",\n", - " marker=dict(color='white', line=dict(width=2, color='DarkSlateGrey'), size=10),\n", - " name=\"Generated\", \n", - " )\n", - " )\n", - " fig.add_trace(\n", - " go.Scatter(x=[-10], y=[-10], mode=\"markers\", \n", - " marker_symbol=\"triangle-down\",\n", - " marker=dict(color='white', line=dict(width=2, color='DarkSlateGrey'), size=10),\n", - " name=\"Consumed\", \n", - " )\n", - " )\n", - " fig.update_yaxes(range=(550,0)) # autorange=\"reversed\")\n", - " fig.update_xaxes(range=(0,800))\n", - "\n", - " # Add images\n", - " fig.add_layout_image(\n", - " dict(\n", - " source=Image.open(\"resources/usa.png\"),\n", - " xref=\"x\",\n", - " yref=\"y\",\n", - " x=10,\n", - " y=0,\n", - " sizex=790,\n", - " sizey=550,\n", - " sizing=\"stretch\",\n", - " opacity=0.5,\n", - " layer=\"below\")\n", - " )\n", - "\n", - " # Add images\n", - " fig.add_layout_image(\n", - " dict(\n", - " source=Image.open(\"resources/legend_bottom_smaller.png\"),\n", - " xref=\"x\",\n", - " yref=\"y\",\n", - " x=-20,\n", - " y=400,\n", - " sizex=260,\n", - " sizey=200,\n", - " sizing=\"contain\",\n", - " opacity=1.0,\n", - " layer=\"below\")\n", - " )\n", - "\n", - " # Set templates\n", - " fig.update_layout(template=\"plotly_white\", width=800, height=600, \n", - " yaxis_visible=False, xaxis_visible=False,\n", - " title=hour.tz_convert(\"US/Eastern\").strftime(\"%B %-d, %Y - %-I:00 %p ET\"))\n", - " #fig.show()\n", - " os.makedirs(f\"outputs/{dir_name}/\", exist_ok=True)\n", - " fig.write_image(f\"outputs/{dir_name}/{hour}.png\", scale=2)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Make gif \n", - "images = []\n", - "files = [f for f in os.listdir(f\"outputs/{dir_name}/\") if \".png\" in f]\n", - "files.sort()\n", - "for f in files:\n", - " images.append(imageio.imread(f\"outputs/{dir_name}/\"+f))\n", - "imageio.mimsave(f\"outputs/movie_{dir_name}.gif\", images)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Now just CISO and neighbors. \n", - "\n", - "# Get list of CISO neighbors \n", - "ciso_interchanges = [c for c in cleaned_io.columns if \"CISO\" in c]\n", - "ciso_bas = []\n", - "for ci in ciso_interchanges: \n", - " ba1, ba2 = ci.split(\".\")[1].split(\"-\")\n", - " if ba1 not in ciso_bas: \n", - " ciso_bas.append(ba1)\n", - " if ba2 not in ciso_bas:\n", - " ciso_bas.append(ba2)\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Identify day with max rate difference in CISO \n", - "tester = (all[all.BA==\"CISO\"]).copy()\n", - "tester[\"difference\"] = tester.consumed_co2_rate_lb_per_mwh_for_electricity - tester.generated_co2_rate_lb_per_mwh_for_electricity\n", - "tester.difference.abs().max()\n", - "tester[tester.difference == tester.difference.abs().max()]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Hour with max CISO difference generated / consumed \n", - "hour = '2020-09-25 12:00:00+00:00'\n", - "\n", - "io_toplot = cleaned_io.loc[hour, ciso_interchanges]\n", - "toplot = all[all.datetime_utc == hour]\n", - "toplot = toplot[toplot.BA.isin(ciso_bas)]\n", - "fig = go.Figure()\n", - "\n", - "colorscale = diverging.RdYlGn_r\n", - "#colorscale = cmocean.solar_r\n", - "\n", - "c_max = np.floor(toplot.generated_co2_rate_lb_per_mwh_for_electricity.max() + 100)\n", - "\n", - "### From when \n", - "# max_width = io_toplot.max()\n", - "# width_factor = 8/max_width\n", - "#width_factor = 1/200\n", - "for name, val in io_toplot.iteritems():\n", - " if val <= 0: \n", - " continue \n", - " bas = name.split(\".\")[1].split(\"-\")\n", - " (ba1, ba2) = bas\n", - "\n", - " next = False\n", - " for ba in bas: \n", - " if ba not in ba_coords.index:\n", - " next=True\n", - " if ba not in toplot.BA.unique():\n", - " next=True\n", - " if next:\n", - " continue\n", - "\n", - " color = toplot.loc[toplot.BA == ba1, \"generated_co2_rate_lb_per_mwh_for_electricity\"].to_numpy()[0]\n", - " print(color)\n", - "\n", - " fig.add_trace(\n", - " go.Scatter(x = ba_coords.loc[bas,\"cx\"], y = ba_coords.loc[bas,\"cy\"], opacity=1.0,\n", - " mode=\"lines\", line = dict(color=get_color_for_val(color, 0, c_max, colorscale), width=2), showlegend=False\n", - " )\n", - " )\n", - "\n", - "################################# Plot BAs \n", - "toplot.loc[toplot.net_generation_mwh < 1, \"net_generation_mwh\"] = 1\n", - "sizes = np.log(toplot.net_generation_mwh)/np.log(1.5)\n", - "offset = sizes/1.6\n", - "fig.add_trace(\n", - " go.Scatter(x=toplot.cx, y=toplot.cy-offset, mode=\"markers\", hoverinfo=\"text\", text=toplot.BA, \n", - " marker_symbol=\"triangle-up\", \n", - " opacity=1.0,\n", - " marker=dict(line=dict(width=1, color='DarkSlateGrey'),\n", - " color=toplot.generated_co2_rate_lb_per_mwh_for_electricity, size=sizes,\n", - " sizemode='diameter', cmin=0, cmax=c_max, opacity=1.0,\n", - " colorscale=\"rdylgn_r\"),\n", - " name=\"Generated\", \n", - " showlegend=False\n", - " )\n", - ")\n", - "fig.add_trace(\n", - " go.Scatter(x=toplot.cx, y=toplot.cy, mode=\"markers\", hoverinfo=\"text\", text=toplot.BA, \n", - " marker_symbol=\"triangle-down\",\n", - " marker=dict(color=toplot.consumed_co2_rate_lb_per_mwh_for_electricity, size=sizes, opacity=1.0,\n", - " line=dict(width=1, color='DarkSlateGrey'),\n", - " sizemode='diameter', cmin=0, cmax=c_max, colorbar=dict(\n", - " title=\"Emission rate
(lbs/MWh)\", orientation='v', len=.8, thickness=20, yanchor='bottom', y=0, xpad=20\n", - " ),\n", - " colorscale=\"rdylgn_r\"),\n", - " name=\"Consumed\", \n", - " showlegend=False \n", - " )\n", - ")\n", - "\n", - "\n", - "# Legends: don't want colored markers\n", - "# Legends: don't want colored markers\n", - "fig.add_trace(\n", - " go.Scatter(x=[-10], y=[-10], mode=\"markers\", \n", - " marker_symbol=\"triangle-up\",\n", - " marker=dict(color='white', line=dict(width=2, color='DarkSlateGrey'), size=10),\n", - " name=\"Generated\", \n", - " )\n", - ")\n", - "fig.add_trace(\n", - " go.Scatter(x=[-10], y=[-10], mode=\"markers\", \n", - " marker_symbol=\"triangle-down\",\n", - " marker=dict(color='white', line=dict(width=2, color='DarkSlateGrey'), size=10),\n", - " name=\"Consumed\", \n", - " )\n", - ")\n", - "fig.update_yaxes(range=(500,0)) # autorange=\"reversed\")\n", - "fig.update_xaxes(range=(0,200))\n", - "\n", - "## loop through the labels and add them as annotations\n", - "for x in zip(toplot.BA, toplot.cx, toplot.cy):\n", - " left_bas = [\"BANC\",\"TIDC\",\"CISO\",\"LDWP\",\"IID\"]\n", - " delta = (-12 if x[0] in left_bas else 12)\n", - " fig.add_annotation(\n", - " x=x[1] + delta,\n", - " y=x[2],\n", - " text=x[0],\n", - " showarrow=False,\n", - " xanchor=('right' if x[0] in left_bas else 'left')\n", - " )\n", - "\n", - "# Add images\n", - "fig.add_layout_image(\n", - " dict(\n", - " source=Image.open(\"resources/usa.png\"),\n", - " xref=\"x\",\n", - " yref=\"y\",\n", - " x=10,\n", - " y=0,\n", - " sizex=790,\n", - " sizey=550,\n", - " sizing=\"stretch\",\n", - " opacity=0.5,\n", - " layer=\"below\")\n", - ")\n", - "\n", - "# Add images\n", - "fig.add_layout_image(\n", - " dict(\n", - " source=Image.open(\"resources/legend_bottom_smaller.png\"),\n", - " xref=\"x\",\n", - " yref=\"y\",\n", - " x=-20,\n", - " y=360,\n", - " sizex=220,\n", - " sizey=144,\n", - " sizing=\"contain\",\n", - " opacity=1.0,\n", - " layer=\"below\")\n", - ")\n", - "\n", - "# Set templates\n", - "fig.update_layout(template=\"plotly_white\", width=400, height=550,\n", - " yaxis_visible=False, xaxis_visible=False,\n", - " title=pd.to_datetime(hour).tz_convert(\"US/Pacific\").strftime(\"%B %-d, %Y - %-I:00 %p PT\")\n", - ")\n", - "fig.show()\n", - "fig.write_image(f\"outputs/viz2_legend.png\", scale=3) " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "toplot[\"difference\"] = (toplot.generated_co2_rate_lb_per_mwh_for_electricity - toplot.consumed_co2_rate_lb_per_mwh_for_electricity)/toplot.generated_co2_rate_lb_per_mwh_for_electricity\n", - "toplot" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "all[\"difference\"] = ((all.generated_co2_rate_lb_per_mwh_for_electricity - all.consumed_co2_rate_lb_per_mwh_for_electricity).abs())* all.net_generation_mwh\n", - "px.line(all.groupby(\"datetime_utc\").mean()[\"difference\"])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "all[all.datetime_utc==\"12-01-2020 T05:00+00:00\"].to_csv(\"outputs/problem_date.csv\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "### Old code for arrows\n", - " # # Arrows have to be added separately\n", - " # line_size = val*width_factor\n", - " # fig.add_annotation(\n", - " # x=ba_coords.loc[ba2,\"cx\"], # arrows' head\n", - " # y=ba_coords.loc[ba2,\"cy\"], # arrows' head\n", - " # ax=ba_coords.loc[ba1,\"cx\"], # arrows' tail\n", - " # ay=ba_coords.loc[ba1,\"cy\"], # arrows' tail\n", - " # xref='x',\n", - " # yref='y',\n", - " # axref='x',\n", - " # ayref='y',\n", - " # text='', # if you want only the arrow\n", - " # showarrow=True,\n", - " # arrowhead=1,\n", - " # arrowsize=1, #max(.3, line_size),\n", - " # arrowwidth=1,\n", - " # arrowcolor='royalblue'\n", - " # )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.10.5 ('hourly_egrid')", - "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.5" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "65c02dfd2dc2ef471c0b5088763a28c1faaa7cad28937ca42fadf51e669fd8e8" - } - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Maps for announcement blog post\n", + "\n", + "Visualization 2: The carbon intensity of consumed electricity differs from generated electricity\n", + "* Show a static carbon flow map focused on a single BA plus all directly-interconnected BAs\n", + "* Pick an hour when there is some particularly dirty electricity getting imported\n", + "* Each BA would be represented by a bubble, where the color changes based on carbon intensity, and carbon flows would be represented by colored arrows between the bubbles. \n", + "* To illustrate the difference between produced and consumed, we might want to have a pair of bubbles for each BA - one that shows the produced CI and one that shows the consumed CI. If we do this, we probably don’t want to vary the size of each bubble based on total generation. Or maybe we could do a split bubble - the top half shows produced CI and the bottom shows consumed CI.\n", + "\n", + "\n", + "Visualization 3: Animating hourly and consumed emissions for the whole county\n", + "* This animation should put the previous two concepts together and show how carbon flows and how CI changes across the entire country for a single day (or a week?)\n", + "* We could also potentially have two maps side by side: one that shows annual averages in bubbles (with no carbon flow), and one that shows the animated hourly flow (to really draw the distinction between annual and hourly datasets)\n", + "\n", + "\n", + "### Ref for making gif: \n", + "`https://stackoverflow.com/questions/753190/programmatically-generate-video-or-animated-gif-in-python`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import plotly.express as px\n", + "import plotly.graph_objects as go\n", + "from plotly.colors import *\n", + "import plotly.io as pio\n", + "import os\n", + "import pandas as pd\n", + "import numpy as np\n", + "from PIL import Image\n", + "import imageio" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2\n", + "\n", + "# # Tell python where to look for modules.\n", + "import sys\n", + "\n", + "sys.path.append(\"../../src/\")\n", + "\n", + "import output_data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ba_coords = pd.read_csv(\n", + " \"resources/ba_coords.csv\", index_col=0, dtype={\"cx\": np.float64, \"cy\": np.float64}\n", + ")\n", + "ba_meta = pd.read_csv(\"../../data/manual/ba_reference.csv\", index_col=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Note: 150+ BAs are not in ba_coords\n", + "ba_list = ba_meta[\n", + " (ba_meta.ba_category != \"misellaneous\")\n", + " & (ba_meta.us_ba)\n", + " & (ba_meta.index.isin(ba_coords.index))\n", + "].index\n", + "ba_list = [\n", + " ba\n", + " for ba in ba_list\n", + " if (\n", + " f\"{ba}.csv\"\n", + " in os.listdir(\"../../data/results/2020/power_sector_data/hourly/us_units/\")\n", + " )\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cleaned_io = pd.read_csv(\n", + " \"../../data/outputs/2020/eia930/eia930_elec.csv\", index_col=0, parse_dates=True\n", + ")\n", + "cleaned_io = cleaned_io[[c for c in cleaned_io.columns if \".ID.\" in c]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "all = []\n", + "for ba in ba_list:\n", + " produced = pd.read_csv(\n", + " f\"../../data/results/2020/power_sector_data/hourly/us_units/{ba}.csv\",\n", + " index_col=\"datetime_utc\",\n", + " parse_dates=True,\n", + " usecols=[\n", + " \"datetime_utc\",\n", + " \"fuel_category\",\n", + " \"net_generation_mwh\",\n", + " \"generated_co2_rate_lb_per_mwh_for_electricity\",\n", + " ],\n", + " )\n", + " produced = produced[produced.fuel_category == \"total\"]\n", + " produced = produced.drop(columns=[\"fuel_category\"])\n", + "\n", + " if ba_meta.loc[ba, \"ba_category\"] == \"generation_only\":\n", + " consumed = pd.DataFrame(\n", + " index=produced.index,\n", + " columns=[[\"consumed_co2_rate_lb_per_mwh_for_electricity\"]],\n", + " dtype=np.float64,\n", + " )\n", + " else:\n", + " consumed = pd.read_csv(\n", + " f\"../../data/results/2020/carbon_accounting/hourly/us_units/{ba}.csv\",\n", + " index_col=\"datetime_utc\",\n", + " parse_dates=True,\n", + " usecols=[\"datetime_utc\", \"consumed_co2_rate_lb_per_mwh_for_electricity\"],\n", + " )\n", + " consumed.columns = consumed.columns.get_level_values(0)\n", + "\n", + " both = pd.concat([produced, consumed], axis=\"columns\")\n", + " # both = both.loc[range_start:range_end]\n", + " both = both.reset_index()\n", + " both[\"BA\"] = ba\n", + " all.append(both)\n", + "\n", + "all = pd.concat(all)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Add coordinates\n", + "all = all.merge(\n", + " ba_coords, how=\"left\", validate=\"many_to_one\", left_on=\"BA\", right_index=True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# src: https://community.plotly.com/t/how-to-include-a-colorscale-for-color-of-line-graphs/38002/3\n", + "from ast import literal_eval\n", + "\n", + "\n", + "def get_color_for_val(val, vmin, vmax, pl_colors):\n", + " if pl_colors[0][:3] != \"rgb\":\n", + " raise ValueError(\"This function works only with Plotly rgb-colorscales\")\n", + " if vmin >= vmax:\n", + " raise ValueError(\"vmin should be < vmax\")\n", + "\n", + " scale = [round(k / (len(pl_colors)), 3) for k in range(len(pl_colors) + 1)]\n", + "\n", + " colors_01 = (\n", + " np.array([literal_eval(color[3:]) for color in pl_colors]) / 255\n", + " ) # color codes in [0,1]\n", + "\n", + " v = (val - vmin) / (vmax - vmin) # val is mapped to v in [0,1]\n", + " # find two consecutive values in plotly_scale such that v is in the corresponding interval\n", + " idx = 0\n", + "\n", + " while idx < (len(scale) - 2) and (v > scale[idx + 1]):\n", + " idx += 1\n", + "\n", + " vv = (v - scale[idx]) / (scale[idx + 1] - scale[idx])\n", + "\n", + " # get [0,1]-valued color code representing the rgb color corresponding to val\n", + " if idx == len(pl_colors) - 1: # Make this work when some values exceed range\n", + " val_color01 = colors_01[idx] # color by last color\n", + " else:\n", + " val_color01 = colors_01[idx] + vv * (colors_01[idx + 1] - colors_01[idx])\n", + "\n", + " val_color_0255 = (255 * val_color01 + 0.5).astype(int)\n", + " return f\"rgb{str(tuple(val_color_0255))}\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "range_start = \"2020-08-01T04:00+00\"\n", + "range_end = \"2020-08-3T04:00+00\"\n", + "\n", + "# range_start = \"2020-07-21T12:00+00\"\n", + "# range_end = \"2020-07-23T12:00+00\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dir_name = \"maps\"\n", + "\n", + "c_max = 2200 # np.floor(all.generated_co2_rate_lb_per_mwh_for_electricity.max() + 100)\n", + "\n", + "hours = all.datetime_utc[\n", + " (all.datetime_utc < pd.to_datetime(range_end))\n", + " & (all.datetime_utc > pd.to_datetime(range_start))\n", + " & (all.BA == \"CISO\")\n", + "]\n", + "for hour in hours:\n", + " print(hour, end=\"...\")\n", + " io_toplot = cleaned_io.loc[hour]\n", + " toplot = all[all.datetime_utc == hour]\n", + " fig = go.Figure()\n", + "\n", + " toplot.loc[toplot.net_generation_mwh < 1, \"net_generation_mwh\"] = 1\n", + " sizes = np.log(toplot.net_generation_mwh) / np.log(1.5)\n", + " offset = sizes / 2.5\n", + "\n", + " colorscale = diverging.RdYlGn_r\n", + " # colorscale = cmocean.solar_r\n", + "\n", + " ### From when\n", + " # max_width = io_toplot.max()\n", + " # width_factor = 8/max_width\n", + " # width_factor = 1/200\n", + " for name, val in io_toplot.iteritems():\n", + " if val <= 0:\n", + " continue\n", + " bas = name.split(\".\")[1].split(\"-\")\n", + " (ba1, ba2) = bas\n", + "\n", + " next = False\n", + " for ba in bas:\n", + " if ba not in ba_coords.index:\n", + " next = True\n", + " if ba not in toplot.BA.unique():\n", + " next = True\n", + " if next:\n", + " continue\n", + "\n", + " color = toplot.loc[\n", + " toplot.BA == ba1, \"generated_co2_rate_lb_per_mwh_for_electricity\"\n", + " ].to_numpy()[0]\n", + "\n", + " fig.add_trace(\n", + " go.Scatter(\n", + " x=ba_coords.loc[bas, \"cx\"],\n", + " y=ba_coords.loc[bas, \"cy\"],\n", + " opacity=1.0,\n", + " mode=\"lines\",\n", + " line=dict(\n", + " color=get_color_for_val(color, 0, c_max, colorscale), width=2\n", + " ),\n", + " showlegend=False,\n", + " )\n", + " )\n", + "\n", + " ################################# Plot BAs\n", + " toplot.loc[toplot.net_generation_mwh < 1, \"net_generation_mwh\"] = 1\n", + " sizes = np.log(toplot.net_generation_mwh) / np.log(1.5)\n", + " offset = sizes / 1.6\n", + "\n", + " # Zero-generation BAs: plot under BAs with non-zero gen\n", + " zero_gen_bas = (\n", + " toplot.net_generation_mwh == 1\n", + " ) # (we set to 1 above to make log work)\n", + " fig.add_trace(\n", + " go.Scatter(\n", + " x=toplot.loc[zero_gen_bas, \"cx\"],\n", + " y=toplot.loc[zero_gen_bas, \"cy\"] + (2 / 2.5),\n", + " mode=\"markers\",\n", + " hoverinfo=\"text\",\n", + " text=toplot.loc[zero_gen_bas, \"BA\"],\n", + " marker_symbol=\"triangle-up\",\n", + " marker=dict(\n", + " color=\"lightgrey\",\n", + " line=dict(width=1, color=\"DarkSlateGrey\"),\n", + " size=7,\n", + " opacity=1.0,\n", + " sizemode=\"diameter\",\n", + " ),\n", + " showlegend=False,\n", + " )\n", + " )\n", + "\n", + " fig.add_trace(\n", + " go.Scatter(\n", + " x=toplot.cx,\n", + " y=toplot.cy,\n", + " mode=\"markers\",\n", + " hoverinfo=\"text\",\n", + " text=toplot.BA,\n", + " marker_symbol=\"triangle-up\",\n", + " opacity=1.0,\n", + " marker=dict(\n", + " color=toplot.generated_co2_rate_lb_per_mwh_for_electricity,\n", + " size=sizes,\n", + " sizemode=\"diameter\",\n", + " cmin=0,\n", + " cmax=c_max,\n", + " opacity=1.0,\n", + " line=dict(width=1, color=\"DarkSlateGrey\"),\n", + " colorscale=\"rdylgn_r\",\n", + " ),\n", + " name=\"Generated\",\n", + " showlegend=False,\n", + " )\n", + " )\n", + " consumed_toplot = ~toplot.consumed_co2_rate_lb_per_mwh_for_electricity.isna()\n", + " fig.add_trace(\n", + " go.Scatter(\n", + " x=toplot.loc[consumed_toplot, \"cx\"],\n", + " y=toplot.loc[consumed_toplot, \"cy\"] + offset[consumed_toplot],\n", + " mode=\"markers\",\n", + " hoverinfo=\"text\",\n", + " text=toplot.loc[consumed_toplot, \"BA\"],\n", + " marker_symbol=\"triangle-down\",\n", + " marker=dict(\n", + " color=toplot.loc[\n", + " consumed_toplot, \"consumed_co2_rate_lb_per_mwh_for_electricity\"\n", + " ],\n", + " size=sizes[consumed_toplot],\n", + " opacity=1.0,\n", + " line=dict(width=1, color=\"DarkSlateGrey\"),\n", + " sizemode=\"diameter\",\n", + " cmin=0,\n", + " cmax=c_max,\n", + " colorbar=dict(\n", + " title=\"Emission rate
(lbs/MWh)\",\n", + " orientation=\"v\",\n", + " len=0.8,\n", + " thickness=20,\n", + " yanchor=\"bottom\",\n", + " y=0,\n", + " xpad=20,\n", + " ),\n", + " colorscale=\"rdylgn_r\",\n", + " ),\n", + " name=\"Consumed\",\n", + " showlegend=False,\n", + " )\n", + " )\n", + "\n", + " # Legends: don't want colored markers\n", + " fig.add_trace(\n", + " go.Scatter(\n", + " x=[-10],\n", + " y=[-10],\n", + " mode=\"markers\",\n", + " marker_symbol=\"triangle-up\",\n", + " marker=dict(\n", + " color=\"white\", line=dict(width=2, color=\"DarkSlateGrey\"), size=10\n", + " ),\n", + " name=\"Generated\",\n", + " )\n", + " )\n", + " fig.add_trace(\n", + " go.Scatter(\n", + " x=[-10],\n", + " y=[-10],\n", + " mode=\"markers\",\n", + " marker_symbol=\"triangle-down\",\n", + " marker=dict(\n", + " color=\"white\", line=dict(width=2, color=\"DarkSlateGrey\"), size=10\n", + " ),\n", + " name=\"Consumed\",\n", + " )\n", + " )\n", + " fig.update_yaxes(range=(550, 0)) # autorange=\"reversed\")\n", + " fig.update_xaxes(range=(0, 800))\n", + "\n", + " # Add images\n", + " fig.add_layout_image(\n", + " dict(\n", + " source=Image.open(\"resources/usa.png\"),\n", + " xref=\"x\",\n", + " yref=\"y\",\n", + " x=10,\n", + " y=0,\n", + " sizex=790,\n", + " sizey=550,\n", + " sizing=\"stretch\",\n", + " opacity=0.5,\n", + " layer=\"below\",\n", + " )\n", + " )\n", + "\n", + " # Add images\n", + " fig.add_layout_image(\n", + " dict(\n", + " source=Image.open(\"resources/legend_bottom_smaller.png\"),\n", + " xref=\"x\",\n", + " yref=\"y\",\n", + " x=-20,\n", + " y=400,\n", + " sizex=260,\n", + " sizey=200,\n", + " sizing=\"contain\",\n", + " opacity=1.0,\n", + " layer=\"below\",\n", + " )\n", + " )\n", + "\n", + " # Set templates\n", + " fig.update_layout(\n", + " template=\"plotly_white\",\n", + " width=800,\n", + " height=600,\n", + " yaxis_visible=False,\n", + " xaxis_visible=False,\n", + " title=hour.tz_convert(\"US/Eastern\").strftime(\"%B %-d, %Y - %-I:00 %p ET\"),\n", + " )\n", + " # fig.show()\n", + " os.makedirs(f\"outputs/{dir_name}/\", exist_ok=True)\n", + " fig.write_image(f\"outputs/{dir_name}/{hour}.png\", scale=2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## Make gif\n", + "images = []\n", + "files = [f for f in os.listdir(f\"outputs/{dir_name}/\") if \".png\" in f]\n", + "files.sort()\n", + "for f in files:\n", + " images.append(imageio.imread(f\"outputs/{dir_name}/\" + f))\n", + "imageio.mimsave(f\"outputs/movie_{dir_name}.gif\", images)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Now just CISO and neighbors.\n", + "\n", + "# Get list of CISO neighbors\n", + "ciso_interchanges = [c for c in cleaned_io.columns if \"CISO\" in c]\n", + "ciso_bas = []\n", + "for ci in ciso_interchanges:\n", + " ba1, ba2 = ci.split(\".\")[1].split(\"-\")\n", + " if ba1 not in ciso_bas:\n", + " ciso_bas.append(ba1)\n", + " if ba2 not in ciso_bas:\n", + " ciso_bas.append(ba2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Identify day with max rate difference in CISO\n", + "tester = (all[all.BA == \"CISO\"]).copy()\n", + "tester[\"difference\"] = (\n", + " tester.consumed_co2_rate_lb_per_mwh_for_electricity\n", + " - tester.generated_co2_rate_lb_per_mwh_for_electricity\n", + ")\n", + "tester.difference.abs().max()\n", + "tester[tester.difference == tester.difference.abs().max()]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Hour with max CISO difference generated / consumed\n", + "hour = \"2020-09-25 12:00:00+00:00\"\n", + "\n", + "io_toplot = cleaned_io.loc[hour, ciso_interchanges]\n", + "toplot = all[all.datetime_utc == hour]\n", + "toplot = toplot[toplot.BA.isin(ciso_bas)]\n", + "fig = go.Figure()\n", + "\n", + "colorscale = diverging.RdYlGn_r\n", + "# colorscale = cmocean.solar_r\n", + "\n", + "c_max = np.floor(toplot.generated_co2_rate_lb_per_mwh_for_electricity.max() + 100)\n", + "\n", + "### From when\n", + "# max_width = io_toplot.max()\n", + "# width_factor = 8/max_width\n", + "# width_factor = 1/200\n", + "for name, val in io_toplot.iteritems():\n", + " if val <= 0:\n", + " continue\n", + " bas = name.split(\".\")[1].split(\"-\")\n", + " (ba1, ba2) = bas\n", + "\n", + " next = False\n", + " for ba in bas:\n", + " if ba not in ba_coords.index:\n", + " next = True\n", + " if ba not in toplot.BA.unique():\n", + " next = True\n", + " if next:\n", + " continue\n", + "\n", + " color = toplot.loc[\n", + " toplot.BA == ba1, \"generated_co2_rate_lb_per_mwh_for_electricity\"\n", + " ].to_numpy()[0]\n", + " print(color)\n", + "\n", + " fig.add_trace(\n", + " go.Scatter(\n", + " x=ba_coords.loc[bas, \"cx\"],\n", + " y=ba_coords.loc[bas, \"cy\"],\n", + " opacity=1.0,\n", + " mode=\"lines\",\n", + " line=dict(color=get_color_for_val(color, 0, c_max, colorscale), width=2),\n", + " showlegend=False,\n", + " )\n", + " )\n", + "\n", + "################################# Plot BAs\n", + "toplot.loc[toplot.net_generation_mwh < 1, \"net_generation_mwh\"] = 1\n", + "sizes = np.log(toplot.net_generation_mwh) / np.log(1.5)\n", + "offset = sizes / 1.6\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=toplot.cx,\n", + " y=toplot.cy - offset,\n", + " mode=\"markers\",\n", + " hoverinfo=\"text\",\n", + " text=toplot.BA,\n", + " marker_symbol=\"triangle-up\",\n", + " opacity=1.0,\n", + " marker=dict(\n", + " line=dict(width=1, color=\"DarkSlateGrey\"),\n", + " color=toplot.generated_co2_rate_lb_per_mwh_for_electricity,\n", + " size=sizes,\n", + " sizemode=\"diameter\",\n", + " cmin=0,\n", + " cmax=c_max,\n", + " opacity=1.0,\n", + " colorscale=\"rdylgn_r\",\n", + " ),\n", + " name=\"Generated\",\n", + " showlegend=False,\n", + " )\n", + ")\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=toplot.cx,\n", + " y=toplot.cy,\n", + " mode=\"markers\",\n", + " hoverinfo=\"text\",\n", + " text=toplot.BA,\n", + " marker_symbol=\"triangle-down\",\n", + " marker=dict(\n", + " color=toplot.consumed_co2_rate_lb_per_mwh_for_electricity,\n", + " size=sizes,\n", + " opacity=1.0,\n", + " line=dict(width=1, color=\"DarkSlateGrey\"),\n", + " sizemode=\"diameter\",\n", + " cmin=0,\n", + " cmax=c_max,\n", + " colorbar=dict(\n", + " title=\"Emission rate
(lbs/MWh)\",\n", + " orientation=\"v\",\n", + " len=0.8,\n", + " thickness=20,\n", + " yanchor=\"bottom\",\n", + " y=0,\n", + " xpad=20,\n", + " ),\n", + " colorscale=\"rdylgn_r\",\n", + " ),\n", + " name=\"Consumed\",\n", + " showlegend=False,\n", + " )\n", + ")\n", + "\n", + "\n", + "# Legends: don't want colored markers\n", + "# Legends: don't want colored markers\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=[-10],\n", + " y=[-10],\n", + " mode=\"markers\",\n", + " marker_symbol=\"triangle-up\",\n", + " marker=dict(color=\"white\", line=dict(width=2, color=\"DarkSlateGrey\"), size=10),\n", + " name=\"Generated\",\n", + " )\n", + ")\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=[-10],\n", + " y=[-10],\n", + " mode=\"markers\",\n", + " marker_symbol=\"triangle-down\",\n", + " marker=dict(color=\"white\", line=dict(width=2, color=\"DarkSlateGrey\"), size=10),\n", + " name=\"Consumed\",\n", + " )\n", + ")\n", + "fig.update_yaxes(range=(500, 0)) # autorange=\"reversed\")\n", + "fig.update_xaxes(range=(0, 200))\n", + "\n", + "## loop through the labels and add them as annotations\n", + "for x in zip(toplot.BA, toplot.cx, toplot.cy):\n", + " left_bas = [\"BANC\", \"TIDC\", \"CISO\", \"LDWP\", \"IID\"]\n", + " delta = -12 if x[0] in left_bas else 12\n", + " fig.add_annotation(\n", + " x=x[1] + delta,\n", + " y=x[2],\n", + " text=x[0],\n", + " showarrow=False,\n", + " xanchor=(\"right\" if x[0] in left_bas else \"left\"),\n", + " )\n", + "\n", + "# Add images\n", + "fig.add_layout_image(\n", + " dict(\n", + " source=Image.open(\"resources/usa.png\"),\n", + " xref=\"x\",\n", + " yref=\"y\",\n", + " x=10,\n", + " y=0,\n", + " sizex=790,\n", + " sizey=550,\n", + " sizing=\"stretch\",\n", + " opacity=0.5,\n", + " layer=\"below\",\n", + " )\n", + ")\n", + "\n", + "# Add images\n", + "fig.add_layout_image(\n", + " dict(\n", + " source=Image.open(\"resources/legend_bottom_smaller.png\"),\n", + " xref=\"x\",\n", + " yref=\"y\",\n", + " x=-20,\n", + " y=360,\n", + " sizex=220,\n", + " sizey=144,\n", + " sizing=\"contain\",\n", + " opacity=1.0,\n", + " layer=\"below\",\n", + " )\n", + ")\n", + "\n", + "# Set templates\n", + "fig.update_layout(\n", + " template=\"plotly_white\",\n", + " width=400,\n", + " height=550,\n", + " yaxis_visible=False,\n", + " xaxis_visible=False,\n", + " title=pd.to_datetime(hour)\n", + " .tz_convert(\"US/Pacific\")\n", + " .strftime(\"%B %-d, %Y - %-I:00 %p PT\"),\n", + ")\n", + "fig.show()\n", + "fig.write_image(f\"outputs/viz2_legend.png\", scale=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "toplot[\"difference\"] = (\n", + " toplot.generated_co2_rate_lb_per_mwh_for_electricity\n", + " - toplot.consumed_co2_rate_lb_per_mwh_for_electricity\n", + ") / toplot.generated_co2_rate_lb_per_mwh_for_electricity\n", + "toplot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "all[\"difference\"] = (\n", + " (\n", + " all.generated_co2_rate_lb_per_mwh_for_electricity\n", + " - all.consumed_co2_rate_lb_per_mwh_for_electricity\n", + " ).abs()\n", + ") * all.net_generation_mwh\n", + "px.line(all.groupby(\"datetime_utc\").mean()[\"difference\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "all[all.datetime_utc == \"12-01-2020 T05:00+00:00\"].to_csv(\"outputs/problem_date.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "### Old code for arrows\n", + "# # Arrows have to be added separately\n", + "# line_size = val*width_factor\n", + "# fig.add_annotation(\n", + "# x=ba_coords.loc[ba2,\"cx\"], # arrows' head\n", + "# y=ba_coords.loc[ba2,\"cy\"], # arrows' head\n", + "# ax=ba_coords.loc[ba1,\"cx\"], # arrows' tail\n", + "# ay=ba_coords.loc[ba1,\"cy\"], # arrows' tail\n", + "# xref='x',\n", + "# yref='y',\n", + "# axref='x',\n", + "# ayref='y',\n", + "# text='', # if you want only the arrow\n", + "# showarrow=True,\n", + "# arrowhead=1,\n", + "# arrowsize=1, #max(.3, line_size),\n", + "# arrowwidth=1,\n", + "# arrowcolor='royalblue'\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.10.5 ('hourly_egrid')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 }, - "nbformat": 4, - "nbformat_minor": 2 + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.5" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "65c02dfd2dc2ef471c0b5088763a28c1faaa7cad28937ca42fadf51e669fd8e8" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/notebooks/visualization/plot_timeseries_data.ipynb b/notebooks/visualization/plot_timeseries_data.ipynb index baf8e715..0228b61d 100644 --- a/notebooks/visualization/plot_timeseries_data.ipynb +++ b/notebooks/visualization/plot_timeseries_data.ipynb @@ -15,7 +15,8 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "from filepaths import *\n", "import validation\n", @@ -41,7 +42,9 @@ "pollutant = \"co2\"\n", "rate_type = \"for_electricity\"\n", "\n", - "data_to_graph = visualization.load_ba_ef_data_to_graph(ba, year, pollutant, rate_type, show_egrid)\n", + "data_to_graph = visualization.load_ba_ef_data_to_graph(\n", + " ba, year, pollutant, rate_type, show_egrid\n", + ")\n", "data_to_graph" ] }, @@ -77,7 +80,7 @@ " labels={\"value\": \"lbCO2e/MWh\"},\n", " template=\"plotly_white\",\n", " title=ba,\n", - ")\n" + ")" ] }, { @@ -117,7 +120,7 @@ ")\n", "\n", "\n", - "fig.show()\n" + "fig.show()" ] }, { @@ -145,7 +148,9 @@ "ba = \"CISO\"\n", "year = 2020\n", "\n", - "power_sector_data = pd.read_csv(results_folder(f\"{year}/power_sector_data/hourly/us_units/{ba}.csv\"))" + "power_sector_data = pd.read_csv(\n", + " results_folder(f\"{year}/power_sector_data/hourly/us_units/{ba}.csv\")\n", + ")" ] }, { @@ -160,7 +165,7 @@ " column_name=\"net_generation_mwh\",\n", " fuel_category_name=\"fuel_category\",\n", " plot_type=\"area\",\n", - ")\n" + ")" ] }, { @@ -175,7 +180,7 @@ " column_name=\"co2_mass_lb\",\n", " fuel_category_name=\"fuel_category\",\n", " plot_type=\"area\",\n", - ")\n" + ")" ] } ], diff --git a/notebooks/work_in_progress/GH102_test_dask.ipynb b/notebooks/work_in_progress/GH102_test_dask.ipynb index db4d08ad..5d0553aa 100644 --- a/notebooks/work_in_progress/GH102_test_dask.ipynb +++ b/notebooks/work_in_progress/GH102_test_dask.ipynb @@ -28,8 +28,11 @@ "outputs": [], "source": [ "# Start client so can see worker mem use\n", - "from dask.distributed import Client \n", - "client = Client(n_workers=2, threads_per_worker=2, memory_limit='1GB') # limit worker size to create issues even on --small dataset\n", + "from dask.distributed import Client\n", + "\n", + "client = Client(\n", + " n_workers=2, threads_per_worker=2, memory_limit=\"1GB\"\n", + ") # limit worker size to create issues even on --small dataset\n", "client" ] }, @@ -45,7 +48,7 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append('../../open-grid-emissions/')\n", + "sys.path.append(\"../../open-grid-emissions/\")\n", "\n", "# import local modules\n", "import src.data_cleaning as data_cleaning" @@ -57,12 +60,21 @@ "metadata": {}, "outputs": [], "source": [ - "o_shaped_eia_data = pd.read_csv(PATH_TO_LOCAL_REPO + 'data/outputs/small/shaped_eia923_data_2020.csv', parse_dates=['datetime_utc'])\n", - "o_partial_cems_scaled = pd.read_csv(PATH_TO_LOCAL_REPO + 'data/outputs/small/partial_cems_scaled_2020.csv', parse_dates=['datetime_utc']) #NOT FINAL VERSION \n", - "o_cems = pd.read_csv(PATH_TO_LOCAL_REPO + 'data/outputs/small/cems_2020.csv', parse_dates=['datetime_utc']) # NOT FINAL VERSION\n", + "o_shaped_eia_data = pd.read_csv(\n", + " PATH_TO_LOCAL_REPO + \"data/outputs/small/shaped_eia923_data_2020.csv\",\n", + " parse_dates=[\"datetime_utc\"],\n", + ")\n", + "o_partial_cems_scaled = pd.read_csv(\n", + " PATH_TO_LOCAL_REPO + \"data/outputs/small/partial_cems_scaled_2020.csv\",\n", + " parse_dates=[\"datetime_utc\"],\n", + ") # NOT FINAL VERSION\n", + "o_cems = pd.read_csv(\n", + " PATH_TO_LOCAL_REPO + \"data/outputs/small/cems_2020.csv\",\n", + " parse_dates=[\"datetime_utc\"],\n", + ") # NOT FINAL VERSION\n", "\n", "# shaped_eia_data = pd.read_csv(PATH_TO_LOCAL_REPO + 'data/outputs/shaped_eia923_data_2020.csv')\n", - "# partial_cems_scaled = pd.read_csv(PATH_TO_LOCAL_REPO + 'data/outputs/partial_cems_scaled_2020.csv') #NOT FINAL VERSION \n", + "# partial_cems_scaled = pd.read_csv(PATH_TO_LOCAL_REPO + 'data/outputs/partial_cems_scaled_2020.csv') #NOT FINAL VERSION\n", "# cems = pd.read_csv(PATH_TO_LOCAL_REPO + 'data/outputs/cems_2020.csv') # NOT FINAL VERSION" ] }, @@ -72,10 +84,12 @@ "metadata": {}, "outputs": [], "source": [ - "# most of the stuff done to partial_cems_scaled and cems in data_pipeline is in plant_static_attributes: \n", - "#plant_static_attributes = pd.read_csv(PATH_TO_LOCAL_REPO + 'data/results/plant_data/plant_static_attributes.csv')\n", + "# most of the stuff done to partial_cems_scaled and cems in data_pipeline is in plant_static_attributes:\n", + "# plant_static_attributes = pd.read_csv(PATH_TO_LOCAL_REPO + 'data/results/plant_data/plant_static_attributes.csv')\n", "\n", - "plant_static_attributes = pd.read_csv(PATH_TO_LOCAL_REPO + 'data/results/small/plant_data/plant_static_attributes.csv')" + "plant_static_attributes = pd.read_csv(\n", + " PATH_TO_LOCAL_REPO + \"data/results/small/plant_data/plant_static_attributes.csv\"\n", + ")" ] }, { @@ -84,8 +98,10 @@ "metadata": {}, "outputs": [], "source": [ - "o_partial_cems_scaled = o_partial_cems_scaled.merge(plant_static_attributes, how='left', on='plant_id_eia')\n", - "o_cems = o_cems.merge(plant_static_attributes, how='left', on='plant_id_eia')" + "o_partial_cems_scaled = o_partial_cems_scaled.merge(\n", + " plant_static_attributes, how=\"left\", on=\"plant_id_eia\"\n", + ")\n", + "o_cems = o_cems.merge(plant_static_attributes, how=\"left\", on=\"plant_id_eia\")" ] }, { @@ -98,7 +114,7 @@ "# On full dataset, these break with worker size 16GB (ie Gailin's laptop)\n", "\n", "combined_plant_data = data_cleaning.combine_subplant_data(\n", - " o_cems, o_partial_cems_scaled, o_shaped_eia_data\n", + " o_cems, o_partial_cems_scaled, o_shaped_eia_data\n", ")\n", "\n", "# 12. Aggregate CEMS data to BA-fuel and write power sector results\n", @@ -113,8 +129,7 @@ "metadata": {}, "outputs": [], "source": [ - "\n", - "#plants = combined_plant_data.groupby('plant_id_eia').sum().compute()" + "# plants = combined_plant_data.groupby('plant_id_eia').sum().compute()" ] }, { @@ -139,7 +154,7 @@ "metadata": {}, "outputs": [], "source": [ - "#dt_shaped['datetime_utc'] = dt_shaped.datetime_utc.dt.to_datetime64()\n" + "# dt_shaped['datetime_utc'] = dt_shaped.datetime_utc.dt.to_datetime64()\n" ] }, { @@ -148,7 +163,7 @@ "metadata": {}, "outputs": [], "source": [ - "dt_shaped = o_shaped_eia_data.set_index('datetime_utc')\n", + "dt_shaped = o_shaped_eia_data.set_index(\"datetime_utc\")\n", "shaped_eia_dask = dd.from_pandas(dt_shaped, npartitions=50)" ] }, @@ -167,7 +182,7 @@ "metadata": {}, "outputs": [], "source": [ - "smol = shaped_eia_dask[['net_generation_mwh','fuel_consumed_mmbtu']]" + "smol = shaped_eia_dask[[\"net_generation_mwh\", \"fuel_consumed_mmbtu\"]]" ] }, { @@ -176,8 +191,8 @@ "metadata": {}, "outputs": [], "source": [ - "# even this breaks. If can get this to work, maybe that solution works for rest? \n", - "smol.groupby('datetime_utc').sum().compute()" + "# even this breaks. If can get this to work, maybe that solution works for rest?\n", + "smol.groupby(\"datetime_utc\").sum().compute()" ] }, { diff --git a/notebooks/work_in_progress/GH153_fill_missing_nox_so2_cems.ipynb b/notebooks/work_in_progress/GH153_fill_missing_nox_so2_cems.ipynb index d9c1c94b..1196e6a6 100644 --- a/notebooks/work_in_progress/GH153_fill_missing_nox_so2_cems.ipynb +++ b/notebooks/work_in_progress/GH153_fill_missing_nox_so2_cems.ipynb @@ -122,7 +122,9 @@ "outputs": [], "source": [ "epa_eia_crosswalk = load_data.load_epa_eia_crosswalk(year)\n", - "boiler_to_unit_crosswalk = epa_eia_crosswalk[[\"plant_id_eia\",\"emissions_unit_id_epa\",\"boiler_id\"]].drop_duplicates()\n", + "boiler_to_unit_crosswalk = epa_eia_crosswalk[\n", + " [\"plant_id_eia\", \"emissions_unit_id_epa\", \"boiler_id\"]\n", + "].drop_duplicates()\n", "boiler_to_unit_crosswalk" ] }, @@ -175,8 +177,7 @@ " \"boiler_bottom_type\",\n", " \"boiler_firing_type\",\n", " ]\n", - ")\n", - "\n" + ")" ] }, { @@ -201,7 +202,9 @@ "outputs": [], "source": [ "epa_eia_crosswalk = load_data.load_epa_eia_crosswalk(year)\n", - "boiler_to_unit_crosswalk = epa_eia_crosswalk[[\"plant_id_eia\",\"emissions_unit_id_epa\",\"boiler_id\"]].drop_duplicates()" + "boiler_to_unit_crosswalk = epa_eia_crosswalk[\n", + " [\"plant_id_eia\", \"emissions_unit_id_epa\", \"boiler_id\"]\n", + "].drop_duplicates()" ] }, { @@ -211,13 +214,31 @@ "outputs": [], "source": [ "# merge in all possible fuel-specific emission factors for the pm boiler design parameters\n", - "boiler_factors = boiler_firing_type.merge(nox_emission_factors, how=\"left\", on=[\"prime_mover_code\",\"boiler_bottom_type\",\"boiler_firing_type\"])\n", + "boiler_factors = boiler_firing_type.merge(\n", + " nox_emission_factors,\n", + " how=\"left\",\n", + " on=[\"prime_mover_code\", \"boiler_bottom_type\", \"boiler_firing_type\"],\n", + ")\n", "\n", "# associate a unit\n", - "boiler_factors = boiler_factors.merge(boiler_to_unit_crosswalk, how=\"left\", on=[\"plant_id_eia\",\"boiler_id\"])\n", + "boiler_factors = boiler_factors.merge(\n", + " boiler_to_unit_crosswalk, how=\"left\", on=[\"plant_id_eia\", \"boiler_id\"]\n", + ")\n", "\n", "# aggregate by unit fuel\n", - "boiler_factors = boiler_factors.groupby([\"plant_id_eia\",\"emissions_unit_id_epa\",\"energy_source_code\",\"emission_factor_denominator\"], dropna=False)[\"emission_factor\"].mean().reset_index()\n", + "boiler_factors = (\n", + " boiler_factors.groupby(\n", + " [\n", + " \"plant_id_eia\",\n", + " \"emissions_unit_id_epa\",\n", + " \"energy_source_code\",\n", + " \"emission_factor_denominator\",\n", + " ],\n", + " dropna=False,\n", + " )[\"emission_factor\"]\n", + " .mean()\n", + " .reset_index()\n", + ")\n", "\n", "boiler_factors" ] diff --git a/notebooks/work_in_progress/GH240_eia930_physics_reconciliation.ipynb b/notebooks/work_in_progress/GH240_eia930_physics_reconciliation.ipynb index b67df60b..92cc342c 100644 --- a/notebooks/work_in_progress/GH240_eia930_physics_reconciliation.ipynb +++ b/notebooks/work_in_progress/GH240_eia930_physics_reconciliation.ipynb @@ -33,7 +33,8 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "import download_data\n", "import load_data\n", @@ -64,7 +65,18 @@ "eia930_raw = eia930.load_chalendar_for_pipeline(raw_930_file, year=year)\n", "eia930_data = eia930.load_chalendar_for_pipeline(clean_930_file, year=year)\n", "\n", - "eia930_merged = eia930_raw.merge(eia930_data, how=\"left\", on=[\"ba_code\",\"fuel_category_eia930\",\"datetime_utc\",\"datetime_local\",\"report_date\"], suffixes=(\"_raw\",\"_cleaned\"))" + "eia930_merged = eia930_raw.merge(\n", + " eia930_data,\n", + " how=\"left\",\n", + " on=[\n", + " \"ba_code\",\n", + " \"fuel_category_eia930\",\n", + " \"datetime_utc\",\n", + " \"datetime_local\",\n", + " \"report_date\",\n", + " ],\n", + " suffixes=(\"_raw\", \"_cleaned\"),\n", + ")" ] }, { @@ -74,10 +86,18 @@ "outputs": [], "source": [ "# calculate how well correlated the raw and cleaned data is\n", - "correlations = eia930_merged.groupby([\"ba_code\",\"fuel_category_eia930\",\"report_date\"], dropna=False)[[\"net_generation_mwh_930_raw\",\"net_generation_mwh_930_cleaned\"]].corr().reset_index()\n", + "correlations = (\n", + " eia930_merged.groupby(\n", + " [\"ba_code\", \"fuel_category_eia930\", \"report_date\"], dropna=False\n", + " )[[\"net_generation_mwh_930_raw\", \"net_generation_mwh_930_cleaned\"]]\n", + " .corr()\n", + " .reset_index()\n", + ")\n", "correlations = correlations[correlations[\"level_3\"] == \"net_generation_mwh_930_raw\"]\n", - "correlations = correlations.drop(columns=[\"level_3\",\"net_generation_mwh_930_raw\"])\n", - "correlations = correlations.rename(columns={\"net_generation_mwh_930_cleaned\":\"correlation_with_raw\"})\n", + "correlations = correlations.drop(columns=[\"level_3\", \"net_generation_mwh_930_raw\"])\n", + "correlations = correlations.rename(\n", + " columns={\"net_generation_mwh_930_cleaned\": \"correlation_with_raw\"}\n", + ")\n", "correlations = correlations[correlations[\"report_date\"].dt.year == 2020]\n", "correlations" ] @@ -91,7 +111,9 @@ "ba = \"PJM\"\n", "fuel = \"coal\"\n", "\n", - "correlations[(correlations[\"ba_code\"] == ba) & (correlations[\"fuel_category_eia930\"] == fuel)]" + "correlations[\n", + " (correlations[\"ba_code\"] == ba) & (correlations[\"fuel_category_eia930\"] == fuel)\n", + "]" ] }, { @@ -112,9 +134,15 @@ "ba = \"BPAT\"\n", "fuel = \"nuclear\"\n", "\n", - "data_to_plot = eia930_merged[(eia930_merged[\"ba_code\"] == ba) & (eia930_merged[\"fuel_category_eia930\"] == fuel)]\n", + "data_to_plot = eia930_merged[\n", + " (eia930_merged[\"ba_code\"] == ba) & (eia930_merged[\"fuel_category_eia930\"] == fuel)\n", + "]\n", "\n", - "px.line(data_to_plot, x=\"datetime_local\", y=[\"net_generation_mwh_930_raw\",\"net_generation_mwh_930_cleaned\"])" + "px.line(\n", + " data_to_plot,\n", + " x=\"datetime_local\",\n", + " y=[\"net_generation_mwh_930_raw\", \"net_generation_mwh_930_cleaned\"],\n", + ")" ] } ], diff --git a/notebooks/work_in_progress/clean_cems_outliers.ipynb b/notebooks/work_in_progress/clean_cems_outliers.ipynb index 9df519cf..5c4a565d 100644 --- a/notebooks/work_in_progress/clean_cems_outliers.ipynb +++ b/notebooks/work_in_progress/clean_cems_outliers.ipynb @@ -59,7 +59,9 @@ "metadata": {}, "outputs": [], "source": [ - "cems = pd.read_csv(f\"{outputs_folder()}/{year}/cems_cleaned_{year}.csv\", dtype=get_dtypes())" + "cems = pd.read_csv(\n", + " f\"{outputs_folder()}/{year}/cems_cleaned_{year}.csv\", dtype=get_dtypes()\n", + ")" ] }, { @@ -68,8 +70,13 @@ "metadata": {}, "outputs": [], "source": [ - "# example CEMS data \n", - "px.line(cems[cems.plant_id_eia==3], x=\"datetime_utc\", y=\"net_generation_mwh\", color=\"subplant_id\")" + "# example CEMS data\n", + "px.line(\n", + " cems[cems.plant_id_eia == 3],\n", + " x=\"datetime_utc\",\n", + " y=\"net_generation_mwh\",\n", + " color=\"subplant_id\",\n", + ")" ] }, { @@ -108,12 +115,12 @@ "metadata": {}, "outputs": [], "source": [ - "# Table is unique by plant ID, generator ID. \n", + "# Table is unique by plant ID, generator ID.\n", "# For each plant and generator, find the maximum of the three capacity values (summer, winter, nameplate)\n", "gens = gens_pudl.copy(deep=True)\n", "gens[\"net_capacity_mw\"] = gens.winter_capacity_mw.combine(gens.summer_capacity_mw, max)\n", "gens[\"net_capacity_mw\"] = gens.net_capacity_mw.combine(gens.capacity_mw, max)\n", - "gens = gens.loc[:,[\"plant_id_eia\",\"generator_id\",\"net_capacity_mw\"]]" + "gens = gens.loc[:, [\"plant_id_eia\", \"generator_id\", \"net_capacity_mw\"]]" ] }, { @@ -132,7 +139,9 @@ "metadata": {}, "outputs": [], "source": [ - "gens_unit = gens.merge(subplant_crosswalk, how='left', on=['plant_id_eia','generator_id'])\n", + "gens_unit = gens.merge(\n", + " subplant_crosswalk, how=\"left\", on=[\"plant_id_eia\", \"generator_id\"]\n", + ")\n", "print(f\"Setting {sum(gens_unit.subplant_id.isna())} NaN subplants to 1 in 860 data\")\n", "gens_unit.loc[gens_unit.subplant_id.isna()] = 1" ] @@ -143,7 +152,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Group gens by subplant \n", + "# Group gens by subplant\n", "gens_per_sub = gens_unit.groupby([\"plant_id_eia\", \"subplant_id\"]).sum().reset_index()" ] }, @@ -172,8 +181,8 @@ "metadata": {}, "outputs": [], "source": [ - "# Now that nans are gone, we can switch from the weird pandas int dtype to numpy dtype, which is required for merge \n", - "cems = cems.astype(dtype={\"subplant_id\":np.int32})" + "# Now that nans are gone, we can switch from the weird pandas int dtype to numpy dtype, which is required for merge\n", + "cems = cems.astype(dtype={\"subplant_id\": np.int32})" ] }, { @@ -182,7 +191,11 @@ "metadata": {}, "outputs": [], "source": [ - "cems_cap = cems.merge(gens_per_sub[[\"plant_id_eia\", \"subplant_id\", \"net_capacity_mw\"]], how='left', on=[\"plant_id_eia\", \"subplant_id\"])" + "cems_cap = cems.merge(\n", + " gens_per_sub[[\"plant_id_eia\", \"subplant_id\", \"net_capacity_mw\"]],\n", + " how=\"left\",\n", + " on=[\"plant_id_eia\", \"subplant_id\"],\n", + ")" ] }, { @@ -191,10 +204,37 @@ "metadata": {}, "outputs": [], "source": [ - "# TODO: here we're assuming that all columns are bad if net gen is bad, and that all bad rows have bad net gen. \n", - "dat_cols = ['gross_generation_mwh', 'steam_load_1000_lb', 'fuel_consumed_mmbtu', 'co2_mass_lb', 'nox_mass_lb', 'so2_mass_lb', 'plant_id_epa', 'co2_mass_measurement_code', 'nox_mass_measurement_code', 'so2_mass_measurement_code', 'report_date', 'energy_source_code', 'ch4_mass_lb', 'n2o_mass_lb', 'fuel_consumed_for_electricity_mmbtu', 'co2_mass_lb_for_electricity', 'ch4_mass_lb_for_electricity', 'n2o_mass_lb_for_electricity', 'nox_mass_lb_for_electricity', 'so2_mass_lb_for_electricity', 'co2_mass_lb_adjusted', 'ch4_mass_lb_adjusted', 'n2o_mass_lb_adjusted', 'nox_mass_lb_adjusted', 'so2_mass_lb_adjusted','net_generation_mwh']\n", + "# TODO: here we're assuming that all columns are bad if net gen is bad, and that all bad rows have bad net gen.\n", + "dat_cols = [\n", + " \"gross_generation_mwh\",\n", + " \"steam_load_1000_lb\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"nox_mass_lb\",\n", + " \"so2_mass_lb\",\n", + " \"plant_id_epa\",\n", + " \"co2_mass_measurement_code\",\n", + " \"nox_mass_measurement_code\",\n", + " \"so2_mass_measurement_code\",\n", + " \"report_date\",\n", + " \"energy_source_code\",\n", + " \"ch4_mass_lb\",\n", + " \"n2o_mass_lb\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb_for_electricity\",\n", + " \"ch4_mass_lb_for_electricity\",\n", + " \"n2o_mass_lb_for_electricity\",\n", + " \"nox_mass_lb_for_electricity\",\n", + " \"so2_mass_lb_for_electricity\",\n", + " \"co2_mass_lb_adjusted\",\n", + " \"ch4_mass_lb_adjusted\",\n", + " \"n2o_mass_lb_adjusted\",\n", + " \"nox_mass_lb_adjusted\",\n", + " \"so2_mass_lb_adjusted\",\n", + " \"net_generation_mwh\",\n", + "]\n", "bad = cems_cap.net_generation_mwh > cems_cap.net_capacity_mw\n", - "cems_cap.loc[bad,dat_cols] = np.nan" + "cems_cap.loc[bad, dat_cols] = np.nan" ] }, { @@ -212,8 +252,8 @@ "metadata": {}, "outputs": [], "source": [ - "## What proportion of CEMS data was ID'ed as bad using capacity filter? \n", - "sum(bad)/len(cems)" + "## What proportion of CEMS data was ID'ed as bad using capacity filter?\n", + "sum(bad) / len(cems)" ] }, { @@ -224,9 +264,19 @@ "source": [ "plant = 2410\n", "\n", - "print(gens_unit.loc[gens_unit.plant_id_eia==plant,[\"plant_id_eia\", \"subplant_id\", \"generator_id\",\"net_capacity_mw\"]])\n", + "print(\n", + " gens_unit.loc[\n", + " gens_unit.plant_id_eia == plant,\n", + " [\"plant_id_eia\", \"subplant_id\", \"generator_id\", \"net_capacity_mw\"],\n", + " ]\n", + ")\n", "\n", - "px.line(cems_cap[cems_cap.plant_id_eia==plant], x=\"datetime_utc\", y=\"net_generation_mwh\", color=\"subplant_id\")" + "px.line(\n", + " cems_cap[cems_cap.plant_id_eia == plant],\n", + " x=\"datetime_utc\",\n", + " y=\"net_generation_mwh\",\n", + " color=\"subplant_id\",\n", + ")" ] }, { @@ -235,9 +285,20 @@ "metadata": {}, "outputs": [], "source": [ - "print(gens_unit.loc[gens_unit.plant_id_eia==plant,[\"plant_id_eia\", \"subplant_id\", \"generator_id\",\"net_capacity_mw\"]])\n", + "print(\n", + " gens_unit.loc[\n", + " gens_unit.plant_id_eia == plant,\n", + " [\"plant_id_eia\", \"subplant_id\", \"generator_id\", \"net_capacity_mw\"],\n", + " ]\n", + ")\n", "\n", - "px.line(cems[cems.plant_id_eia==plant], x=\"datetime_utc\", y=\"net_generation_mwh\", color=\"subplant_id\", title=f\"plant id = {plant}\")" + "px.line(\n", + " cems[cems.plant_id_eia == plant],\n", + " x=\"datetime_utc\",\n", + " y=\"net_generation_mwh\",\n", + " color=\"subplant_id\",\n", + " title=f\"plant id = {plant}\",\n", + ")" ] }, { @@ -256,9 +317,41 @@ "metadata": {}, "outputs": [], "source": [ - "# Get per-plant, per-variable median and IQR \n", - "numeric_cols = ['gross_generation_mwh', 'steam_load_1000_lb', 'fuel_consumed_mmbtu', 'co2_mass_lb', 'ch4_mass_lb', 'n2o_mass_lb', 'nox_mass_lb', 'so2_mass_lb', 'co2_mass_lb_adjusted', 'ch4_mass_lb_adjusted', 'n2o_mass_lb_adjusted', 'nox_mass_lb_adjusted', 'so2_mass_lb_adjusted', 'net_generation_mwh', 'fuel_consumed_for_electricity_mmbtu', 'co2_mass_lb_for_electricity', 'co2_mass_lb_for_electricity_adjusted', 'ch4_mass_lb_for_electricity', 'ch4_mass_lb_for_electricity_adjusted', 'n2o_mass_lb_for_electricity', 'n2o_mass_lb_for_electricity_adjusted', 'nox_mass_lb_for_electricity', 'nox_mass_lb_for_electricity_adjusted', 'so2_mass_lb_for_electricity', 'so2_mass_lb_for_electricity_adjusted', 'co2e_mass_lb', 'co2e_mass_lb_adjusted', 'co2e_mass_lb_for_electricity', 'co2e_mass_lb_for_electricity_adjusted']\n", - "iqr = cems.groupby([\"plant_id_eia\", \"subplant_id\"])[numeric_cols].quantile(.75) - cems.groupby([\"plant_id_eia\",\"subplant_id\"])[numeric_cols].quantile(.25)" + "# Get per-plant, per-variable median and IQR\n", + "numeric_cols = [\n", + " \"gross_generation_mwh\",\n", + " \"steam_load_1000_lb\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"co2_mass_lb\",\n", + " \"ch4_mass_lb\",\n", + " \"n2o_mass_lb\",\n", + " \"nox_mass_lb\",\n", + " \"so2_mass_lb\",\n", + " \"co2_mass_lb_adjusted\",\n", + " \"ch4_mass_lb_adjusted\",\n", + " \"n2o_mass_lb_adjusted\",\n", + " \"nox_mass_lb_adjusted\",\n", + " \"so2_mass_lb_adjusted\",\n", + " \"net_generation_mwh\",\n", + " \"fuel_consumed_for_electricity_mmbtu\",\n", + " \"co2_mass_lb_for_electricity\",\n", + " \"co2_mass_lb_for_electricity_adjusted\",\n", + " \"ch4_mass_lb_for_electricity\",\n", + " \"ch4_mass_lb_for_electricity_adjusted\",\n", + " \"n2o_mass_lb_for_electricity\",\n", + " \"n2o_mass_lb_for_electricity_adjusted\",\n", + " \"nox_mass_lb_for_electricity\",\n", + " \"nox_mass_lb_for_electricity_adjusted\",\n", + " \"so2_mass_lb_for_electricity\",\n", + " \"so2_mass_lb_for_electricity_adjusted\",\n", + " \"co2e_mass_lb\",\n", + " \"co2e_mass_lb_adjusted\",\n", + " \"co2e_mass_lb_for_electricity\",\n", + " \"co2e_mass_lb_for_electricity_adjusted\",\n", + "]\n", + "iqr = cems.groupby([\"plant_id_eia\", \"subplant_id\"])[numeric_cols].quantile(\n", + " 0.75\n", + ") - cems.groupby([\"plant_id_eia\", \"subplant_id\"])[numeric_cols].quantile(0.25)" ] }, { @@ -267,7 +360,7 @@ "metadata": {}, "outputs": [], "source": [ - "median = cems.groupby([\"plant_id_eia\",\"subplant_id\"]).median()" + "median = cems.groupby([\"plant_id_eia\", \"subplant_id\"]).median()" ] }, { @@ -287,8 +380,7 @@ "outputs": [], "source": [ "cems_filtered = cems.copy()\n", - "#for plant in cems_filtered.plant_id_eia.unique():\n", - " " + "# for plant in cems_filtered.plant_id_eia.unique():" ] }, { @@ -297,7 +389,7 @@ "metadata": {}, "outputs": [], "source": [ - "cems_filtered = cems_filtered.set_index([\"plant_id_eia\",\"subplant_id\"])" + "cems_filtered = cems_filtered.set_index([\"plant_id_eia\", \"subplant_id\"])" ] }, { @@ -306,7 +398,7 @@ "metadata": {}, "outputs": [], "source": [ - "cems_filtered.loc[(3,1)]" + "cems_filtered.loc[(3, 1)]" ] }, { @@ -315,7 +407,9 @@ "metadata": {}, "outputs": [], "source": [ - "checked = (cems_filtered.loc[(3,1), lower_bound.columns] < lower_bound.loc[(3,1)]) | (cems_filtered.loc[(3,1), lower_bound.columns] > upper_bound.loc[(3, 1)])" + "checked = (cems_filtered.loc[(3, 1), lower_bound.columns] < lower_bound.loc[(3, 1)]) | (\n", + " cems_filtered.loc[(3, 1), lower_bound.columns] > upper_bound.loc[(3, 1)]\n", + ")" ] }, { @@ -333,8 +427,13 @@ "metadata": {}, "outputs": [], "source": [ - "toplot = cems_filtered.loc[(3,1)]\n", - "px.scatter(toplot, x=\"datetime_utc\", y=\"fuel_consumed_mmbtu\", color=checked[\"fuel_consumed_mmbtu\"])" + "toplot = cems_filtered.loc[(3, 1)]\n", + "px.scatter(\n", + " toplot,\n", + " x=\"datetime_utc\",\n", + " y=\"fuel_consumed_mmbtu\",\n", + " color=checked[\"fuel_consumed_mmbtu\"],\n", + ")" ] }, { @@ -343,7 +442,7 @@ "metadata": {}, "outputs": [], "source": [ - "median.loc[(3,1)]" + "median.loc[(3, 1)]" ] } ], diff --git a/notebooks/work_in_progress/issue230_spikes.ipynb b/notebooks/work_in_progress/issue230_spikes.ipynb index 5a3468ed..7a98e8e2 100644 --- a/notebooks/work_in_progress/issue230_spikes.ipynb +++ b/notebooks/work_in_progress/issue230_spikes.ipynb @@ -24,7 +24,7 @@ "metadata": {}, "outputs": [], "source": [ - "import pandas as pd \n", + "import pandas as pd\n", "import plotly.express as px" ] }, @@ -39,11 +39,12 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../src/')\n", + "\n", + "sys.path.append(\"../../src/\")\n", "\n", "import impute_hourly_profiles\n", "from filepaths import outputs_folder, results_folder\n", - "from column_checks import get_dtypes\n" + "from column_checks import get_dtypes" ] }, { @@ -52,7 +53,9 @@ "metadata": {}, "outputs": [], "source": [ - "problem_profiles = pd.read_csv(f\"{outputs_folder()}/2020/hourly_profiles_2020.csv\", dtype=get_dtypes())" + "problem_profiles = pd.read_csv(\n", + " f\"{outputs_folder()}/2020/hourly_profiles_2020.csv\", dtype=get_dtypes()\n", + ")" ] }, { @@ -61,7 +64,9 @@ "metadata": {}, "outputs": [], "source": [ - "problem_profiles = problem_profiles[(problem_profiles.ba_code==\"PJM\") & (problem_profiles.fuel_category==\"nuclear\")]" + "problem_profiles = problem_profiles[\n", + " (problem_profiles.ba_code == \"PJM\") & (problem_profiles.fuel_category == \"nuclear\")\n", + "]" ] }, { @@ -72,7 +77,16 @@ "source": [ "problem_profiles.head()\n", "\n", - "px.line(problem_profiles, x=\"datetime_utc\", y=[\"residual_profile\",\"scaled_residual_profile\",\"shifted_residual_profile\",\"profile\"])" + "px.line(\n", + " problem_profiles,\n", + " x=\"datetime_utc\",\n", + " y=[\n", + " \"residual_profile\",\n", + " \"scaled_residual_profile\",\n", + " \"shifted_residual_profile\",\n", + " \"profile\",\n", + " ],\n", + ")" ] }, { @@ -81,7 +95,7 @@ "metadata": {}, "outputs": [], "source": [ - "problem_profiles.profile_method.unique()\n" + "problem_profiles.profile_method.unique()" ] }, { @@ -90,7 +104,10 @@ "metadata": {}, "outputs": [], "source": [ - "problem_profiles[(problem_profiles.datetime_utc > \"2020-04-15\") & (problem_profiles.datetime_utc < \"2020-04-16\")]" + "problem_profiles[\n", + " (problem_profiles.datetime_utc > \"2020-04-15\")\n", + " & (problem_profiles.datetime_utc < \"2020-04-16\")\n", + "]" ] }, { @@ -99,8 +116,10 @@ "metadata": {}, "outputs": [], "source": [ - "### Look for the issue in the next output \n", - "shaped = pd.read_csv(f\"{outputs_folder()}/2020/shaped_eia923_data_2020.csv\", dtype=get_dtypes())" + "### Look for the issue in the next output\n", + "shaped = pd.read_csv(\n", + " f\"{outputs_folder()}/2020/shaped_eia923_data_2020.csv\", dtype=get_dtypes()\n", + ")" ] }, { @@ -109,7 +128,7 @@ "metadata": {}, "outputs": [], "source": [ - "shaped = shaped[(shaped.ba_code==\"PJM\")]" + "shaped = shaped[(shaped.ba_code == \"PJM\")]" ] }, { @@ -118,7 +137,13 @@ "metadata": {}, "outputs": [], "source": [ - "px.line(shaped, x=\"datetime_utc\", y=\"net_generation_mwh\", line_group=\"fuel_category\", color=\"fuel_category\")" + "px.line(\n", + " shaped,\n", + " x=\"datetime_utc\",\n", + " y=\"net_generation_mwh\",\n", + " line_group=\"fuel_category\",\n", + " color=\"fuel_category\",\n", + ")" ] }, { @@ -127,8 +152,10 @@ "metadata": {}, "outputs": [], "source": [ - "#### Ok, issue is not in 923 shaped data, so it must just be in CEMS data \n", - "plant_level = pd.read_csv(f\"{results_folder()}/2020/plant_data/hourly/us_units/individual_plant_data.csv\")" + "#### Ok, issue is not in 923 shaped data, so it must just be in CEMS data\n", + "plant_level = pd.read_csv(\n", + " f\"{results_folder()}/2020/plant_data/hourly/us_units/individual_plant_data.csv\"\n", + ")" ] }, { diff --git a/notebooks/work_in_progress/sandbox.ipynb b/notebooks/work_in_progress/sandbox.ipynb index b69f7db2..37714709 100644 --- a/notebooks/work_in_progress/sandbox.ipynb +++ b/notebooks/work_in_progress/sandbox.ipynb @@ -17,7 +17,8 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", - "sys.path.append('../../../open-grid-emissions/src/')\n", + "\n", + "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", "import download_data\n", "import load_data\n", @@ -31,6 +32,7 @@ "import gross_to_net_generation\n", "import eia930\n", "from logging_util import get_logger, configure_root_logger\n", + "\n", "configure_root_logger()\n", "logger = get_logger(\"test\")\n", "\n", diff --git a/notebooks/work_in_progress/uncertainty_analysis.ipynb b/notebooks/work_in_progress/uncertainty_analysis.ipynb index e327b28a..79f519d4 100644 --- a/notebooks/work_in_progress/uncertainty_analysis.ipynb +++ b/notebooks/work_in_progress/uncertainty_analysis.ipynb @@ -18,7 +18,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Calculate min and max possible at each hour \n", + "# Calculate min and max possible at each hour\n", "import pandas as pd\n", "import plotly.express as px\n", "import plotly.graph_objects as go\n", @@ -34,10 +34,11 @@ "%reload_ext autoreload\n", "%autoreload 2\n", "\n", - "# Tell python where to look for modules. \n", + "# Tell python where to look for modules.\n", "# Depending on how your jupyter handles working directories, this may not be needed.\n", "import sys\n", - "sys.path.append('../../hourly-egrid/')\n", + "\n", + "sys.path.append(\"../../hourly-egrid/\")\n", "\n", "import src.load_data as load_data\n", "import src.column_checks as column_checks" @@ -49,7 +50,7 @@ "metadata": {}, "outputs": [], "source": [ - "year = 2020 " + "year = 2020" ] }, { @@ -74,8 +75,14 @@ "metadata": {}, "outputs": [], "source": [ - "flat = pd.read_csv(f\"../data/results/flat/{year}/power_sector_data/hourly/us_units/{ba}.csv\", parse_dates=[\"datetime_utc\"])\n", - "base = pd.read_csv(f\"../data/results/{year}/power_sector_data/hourly/us_units/{ba}.csv\", parse_dates=[\"datetime_utc\"])\n" + "flat = pd.read_csv(\n", + " f\"../data/results/flat/{year}/power_sector_data/hourly/us_units/{ba}.csv\",\n", + " parse_dates=[\"datetime_utc\"],\n", + ")\n", + "base = pd.read_csv(\n", + " f\"../data/results/{year}/power_sector_data/hourly/us_units/{ba}.csv\",\n", + " parse_dates=[\"datetime_utc\"],\n", + ")" ] }, { @@ -84,8 +91,8 @@ "metadata": {}, "outputs": [], "source": [ - "flat = flat[flat.fuel_category==\"total\"]\n", - "base = base[base.fuel_category==\"total\"]" + "flat = flat[flat.fuel_category == \"total\"]\n", + "base = base[base.fuel_category == \"total\"]" ] }, { @@ -94,7 +101,7 @@ "metadata": {}, "outputs": [], "source": [ - "both = flat.merge(base, how='left', on='datetime_utc', suffixes=(\"_flat\", \"_base\"))" + "both = flat.merge(base, how=\"left\", on=\"datetime_utc\", suffixes=(\"_flat\", \"_base\"))" ] }, { @@ -112,10 +119,18 @@ "metadata": {}, "outputs": [], "source": [ - "fig = px.line(both, x=\"datetime_utc\", y=['generated_co2e_rate_lb_per_mwh_for_electricity_adjusted_flat','generated_co2e_rate_lb_per_mwh_for_electricity_adjusted_base'], title=f\"{ba}, carbon intensity using flat vs. base generation\")\n", + "fig = px.line(\n", + " both,\n", + " x=\"datetime_utc\",\n", + " y=[\n", + " \"generated_co2e_rate_lb_per_mwh_for_electricity_adjusted_flat\",\n", + " \"generated_co2e_rate_lb_per_mwh_for_electricity_adjusted_base\",\n", + " ],\n", + " title=f\"{ba}, carbon intensity using flat vs. base generation\",\n", + ")\n", "fig.show()\n", - "#newnames = {'generated_co2_rate_lb_per_mwh_adjusted': 'Our data', 'generated_co2_rate_lb_per_mwh_for_electricity_adjusted': 'Real-time data'}\n", - "#fig.for_each_trace(lambda t: t.update(name = newnames[t.name]))" + "# newnames = {'generated_co2_rate_lb_per_mwh_adjusted': 'Our data', 'generated_co2_rate_lb_per_mwh_for_electricity_adjusted': 'Real-time data'}\n", + "# fig.for_each_trace(lambda t: t.update(name = newnames[t.name]))" ] }, { @@ -131,7 +146,10 @@ "metadata": {}, "outputs": [], "source": [ - "cems = pd.read_csv(\"../data/results/2020/plant_data/hourly/us_units/individual_plant_data.csv\", parse_dates=[\"datetime_utc\", \"report_date\"])\n", + "cems = pd.read_csv(\n", + " \"../data/results/2020/plant_data/hourly/us_units/individual_plant_data.csv\",\n", + " parse_dates=[\"datetime_utc\", \"report_date\"],\n", + ")\n", "plant_meta = pd.read_csv(\"../data/results/2020/plant_data/plant_static_attributes.csv\")" ] }, @@ -141,7 +159,7 @@ "metadata": {}, "outputs": [], "source": [ - "cems = cems.merge(plant_meta, how='left', on='plant_id_eia')" + "cems = cems.merge(plant_meta, how=\"left\", on=\"plant_id_eia\")" ] }, { @@ -178,8 +196,12 @@ "metadata": {}, "outputs": [], "source": [ - "caps = pudl_reader.gens_eia860()[[\"plant_id_eia\", \"capacity_mw\", \"summer_capacity_mw\", \"winter_capacity_mw\"]].copy()\n", - "caps[\"max_capacity\"] = caps[[\"capacity_mw\", \"summer_capacity_mw\", \"winter_capacity_mw\"]].max(axis=1)\n", + "caps = pudl_reader.gens_eia860()[\n", + " [\"plant_id_eia\", \"capacity_mw\", \"summer_capacity_mw\", \"winter_capacity_mw\"]\n", + "].copy()\n", + "caps[\"max_capacity\"] = caps[\n", + " [\"capacity_mw\", \"summer_capacity_mw\", \"winter_capacity_mw\"]\n", + "].max(axis=1)\n", "caps = caps.groupby(\"plant_id_eia\").sum()[\"max_capacity\"]" ] }, @@ -189,7 +211,10 @@ "metadata": {}, "outputs": [], "source": [ - "monthly_rates = pd.read_csv(\"../data/results/2020/plant_data/monthly/us_units/plant_data.csv\", parse_dates=[\"report_date\"])" + "monthly_rates = pd.read_csv(\n", + " \"../data/results/2020/plant_data/monthly/us_units/plant_data.csv\",\n", + " parse_dates=[\"report_date\"],\n", + ")" ] }, { @@ -198,8 +223,10 @@ "metadata": {}, "outputs": [], "source": [ - "monthly_rates = monthly_rates.merge(caps, how='left', left_on='plant_id_eia', right_index=True)\n", - "monthly_rates = monthly_rates.merge(plant_meta, how='left', on='plant_id_eia')" + "monthly_rates = monthly_rates.merge(\n", + " caps, how=\"left\", left_on=\"plant_id_eia\", right_index=True\n", + ")\n", + "monthly_rates = monthly_rates.merge(plant_meta, how=\"left\", on=\"plant_id_eia\")" ] }, { @@ -208,12 +235,15 @@ "metadata": {}, "outputs": [], "source": [ - "# Calculate per-plant, per-month maximum net generation and emissions: \n", + "# Calculate per-plant, per-month maximum net generation and emissions:\n", "# max net gen = capacity\n", "# max emissions = capacity * monthly rate\n", "pols = [\"co2\", \"ch4\", \"n2o\", \"co2e\", \"nox\", \"so2\"]\n", "for pol in pols:\n", - " monthly_rates[f\"max_hourly_{pol}\"] = monthly_rates[\"max_capacity\"] * (monthly_rates[f\"{pol}_mass_lb_for_electricity_adjusted\"]/monthly_rates[\"net_generation_mwh\"])" + " monthly_rates[f\"max_hourly_{pol}\"] = monthly_rates[\"max_capacity\"] * (\n", + " monthly_rates[f\"{pol}_mass_lb_for_electricity_adjusted\"]\n", + " / monthly_rates[\"net_generation_mwh\"]\n", + " )" ] }, { @@ -224,10 +254,17 @@ "source": [ "# Filter for non-CEMS plants\n", "# Filter for plants with non-zero generation in this month: we know that hourly generation shouldn't include the capacity of these plants\n", - "# Group by BA and month to get monthly max hourly emissions \n", + "# Group by BA and month to get monthly max hourly emissions\n", "pol_cols = [f\"max_hourly_{p}\" for p in pols] + [\"max_capacity\"]\n", - "filtered_monthly_rates = monthly_rates[(monthly_rates.data_availability == \"eia_only\") & (monthly_rates.net_generation_mwh > 0)]\n", - "non_cems_maxes = filtered_monthly_rates.groupby([\"report_date\", \"ba_code\"])[pol_cols].sum().reset_index()" + "filtered_monthly_rates = monthly_rates[\n", + " (monthly_rates.data_availability == \"eia_only\")\n", + " & (monthly_rates.net_generation_mwh > 0)\n", + "]\n", + "non_cems_maxes = (\n", + " filtered_monthly_rates.groupby([\"report_date\", \"ba_code\"])[pol_cols]\n", + " .sum()\n", + " .reset_index()\n", + ")" ] }, { @@ -236,13 +273,16 @@ "metadata": {}, "outputs": [], "source": [ - "# Identify plants with negative net generation. \n", + "# Identify plants with negative net generation.\n", "# These will be included in net generation minimum, emissions maximum\n", - "negative_monthly = monthly_rates[(monthly_rates.data_availability == \"eia_only\") & (monthly_rates.net_generation_mwh < 0)]\n", + "negative_monthly = monthly_rates[\n", + " (monthly_rates.data_availability == \"eia_only\")\n", + " & (monthly_rates.net_generation_mwh < 0)\n", + "]\n", "assert len(negative_monthly) == 0\n", "\n", "\n", - "# ########### FAKE NEGATIVE PLANT FOR TESTING \n", + "# ########### FAKE NEGATIVE PLANT FOR TESTING\n", "# negative_monthly = monthly_rates[(monthly_rates.plant_id_eia == 3)].copy()\n", "# negative_monthly.loc[:,\"net_generation_mwh\"] = -300" ] @@ -264,8 +304,12 @@ "outputs": [], "source": [ "# Add report date back in (dropped during groupby)\n", - "report_dates = cems.groupby([\"datetime_utc\",\"ba_code\"])[\"report_date\"].first().reset_index()\n", - "minimum_bound = minimum_bound.merge(report_dates, how='left', on=[\"datetime_utc\",\"ba_code\"])" + "report_dates = (\n", + " cems.groupby([\"datetime_utc\", \"ba_code\"])[\"report_date\"].first().reset_index()\n", + ")\n", + "minimum_bound = minimum_bound.merge(\n", + " report_dates, how=\"left\", on=[\"datetime_utc\", \"ba_code\"]\n", + ")" ] }, { @@ -274,8 +318,10 @@ "metadata": {}, "outputs": [], "source": [ - "# Calculate maximum by merging hourly max emissions and generation into minimum, then adding \n", - "maximum_bound = minimum_bound.merge(non_cems_maxes, how='left', on=[\"report_date\", \"ba_code\"])" + "# Calculate maximum by merging hourly max emissions and generation into minimum, then adding\n", + "maximum_bound = minimum_bound.merge(\n", + " non_cems_maxes, how=\"left\", on=[\"report_date\", \"ba_code\"]\n", + ")" ] }, { @@ -285,8 +331,13 @@ "outputs": [], "source": [ "for pol in pols:\n", - " maximum_bound[f\"{pol}_mass_lb_for_electricity_adjusted\"] = maximum_bound[f\"{pol}_mass_lb_for_electricity_adjusted\"] + maximum_bound[f\"max_hourly_{pol}\"]\n", - "maximum_bound[\"net_generation_mwh\"] = maximum_bound[\"net_generation_mwh\"] + maximum_bound[\"max_capacity\"]\n", + " maximum_bound[f\"{pol}_mass_lb_for_electricity_adjusted\"] = (\n", + " maximum_bound[f\"{pol}_mass_lb_for_electricity_adjusted\"]\n", + " + maximum_bound[f\"max_hourly_{pol}\"]\n", + " )\n", + "maximum_bound[\"net_generation_mwh\"] = (\n", + " maximum_bound[\"net_generation_mwh\"] + maximum_bound[\"max_capacity\"]\n", + ")\n", "maximum_bound = maximum_bound[cols + [\"datetime_utc\", \"ba_code\"]]" ] }, @@ -312,8 +363,14 @@ "metadata": {}, "outputs": [], "source": [ - "flat = pd.read_csv(f\"../data/results/flat/2020/power_sector_data/hourly/us_units/{ba}.csv\", parse_dates=[\"datetime_utc\"])\n", - "base = pd.read_csv(f\"../data/results/2020/power_sector_data/hourly/us_units/{ba}.csv\", parse_dates=[\"datetime_utc\"])" + "flat = pd.read_csv(\n", + " f\"../data/results/flat/2020/power_sector_data/hourly/us_units/{ba}.csv\",\n", + " parse_dates=[\"datetime_utc\"],\n", + ")\n", + "base = pd.read_csv(\n", + " f\"../data/results/2020/power_sector_data/hourly/us_units/{ba}.csv\",\n", + " parse_dates=[\"datetime_utc\"],\n", + ")" ] }, { @@ -322,7 +379,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Only take totals \n", + "# Only take totals\n", "flat = flat[flat.fuel_category == \"total\"]\n", "base = base[base.fuel_category == \"total\"]" ] @@ -333,30 +390,50 @@ "metadata": {}, "outputs": [], "source": [ - "this_max = maximum_bound[maximum_bound.ba_code==ba]\n", - "this_min = minimum_bound[minimum_bound.ba_code==ba]\n", + "this_max = maximum_bound[maximum_bound.ba_code == ba]\n", + "this_min = minimum_bound[minimum_bound.ba_code == ba]\n", "\n", "fig = go.Figure()\n", - "fig.add_trace(go.Scatter(x=this_min.datetime_utc, y=this_min.net_generation_mwh,\n", - " fill=None,\n", - " mode='lines',\n", - " line_color='indigo', showlegend=False\n", - " ))\n", - "fig.add_trace(go.Scatter(\n", - " x=this_max.datetime_utc,\n", - " y=this_max.net_generation_mwh,\n", - " fill='tonexty', # fill area between trace0 and trace1\n", - " mode='lines', line_color='indigo', name=\"Min/max possible\"))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=this_min.datetime_utc,\n", + " y=this_min.net_generation_mwh,\n", + " fill=None,\n", + " mode=\"lines\",\n", + " line_color=\"indigo\",\n", + " showlegend=False,\n", + " )\n", + ")\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=this_max.datetime_utc,\n", + " y=this_max.net_generation_mwh,\n", + " fill=\"tonexty\", # fill area between trace0 and trace1\n", + " mode=\"lines\",\n", + " line_color=\"indigo\",\n", + " name=\"Min/max possible\",\n", + " )\n", + ")\n", "\n", - "fig.add_trace(go.Scatter(\n", - " x=flat.datetime_utc,\n", - " y=flat.net_generation_mwh,\n", - " mode='lines', line_color='brown', name=\"Flat\"))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=flat.datetime_utc,\n", + " y=flat.net_generation_mwh,\n", + " mode=\"lines\",\n", + " line_color=\"brown\",\n", + " name=\"Flat\",\n", + " )\n", + ")\n", "\n", - "fig.add_trace(go.Scatter(\n", - " x=base.datetime_utc,\n", - " y=base.net_generation_mwh,\n", - " mode='lines', line_color='blue', name=\"Best guess\"))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=base.datetime_utc,\n", + " y=base.net_generation_mwh,\n", + " mode=\"lines\",\n", + " line_color=\"blue\",\n", + " name=\"Best guess\",\n", + " )\n", + ")\n", "\n", "fig.update_layout(\n", " title=f\"{ba} total net generation estimates\",\n", @@ -365,7 +442,7 @@ " legend_title=\"Estimate type\",\n", ")\n", "\n", - "fig.show()\n" + "fig.show()" ] }, { @@ -374,30 +451,50 @@ "metadata": {}, "outputs": [], "source": [ - "this_max = maximum_bound[maximum_bound.ba_code==ba]\n", - "this_min = minimum_bound[minimum_bound.ba_code==ba]\n", + "this_max = maximum_bound[maximum_bound.ba_code == ba]\n", + "this_min = minimum_bound[minimum_bound.ba_code == ba]\n", "\n", "fig = go.Figure()\n", - "fig.add_trace(go.Scatter(x=this_min.datetime_utc, y=this_min.co2_mass_lb_for_electricity_adjusted,\n", - " fill=None,\n", - " mode='lines',\n", - " line_color='indigo', showlegend=False\n", - " ))\n", - "fig.add_trace(go.Scatter(\n", - " x=this_max.datetime_utc,\n", - " y=this_max.co2_mass_lb_for_electricity_adjusted,\n", - " fill='tonexty', # fill area between trace0 and trace1\n", - " mode='lines', line_color='indigo', name=\"Min/max possible\"))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=this_min.datetime_utc,\n", + " y=this_min.co2_mass_lb_for_electricity_adjusted,\n", + " fill=None,\n", + " mode=\"lines\",\n", + " line_color=\"indigo\",\n", + " showlegend=False,\n", + " )\n", + ")\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=this_max.datetime_utc,\n", + " y=this_max.co2_mass_lb_for_electricity_adjusted,\n", + " fill=\"tonexty\", # fill area between trace0 and trace1\n", + " mode=\"lines\",\n", + " line_color=\"indigo\",\n", + " name=\"Min/max possible\",\n", + " )\n", + ")\n", "\n", - "fig.add_trace(go.Scatter(\n", - " x=flat.datetime_utc,\n", - " y=flat.co2_mass_lb_for_electricity_adjusted,\n", - " mode='lines', line_color='brown', name=\"Flat\"))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=flat.datetime_utc,\n", + " y=flat.co2_mass_lb_for_electricity_adjusted,\n", + " mode=\"lines\",\n", + " line_color=\"brown\",\n", + " name=\"Flat\",\n", + " )\n", + ")\n", "\n", - "fig.add_trace(go.Scatter(\n", - " x=base.datetime_utc,\n", - " y=base.co2_mass_lb_for_electricity_adjusted,\n", - " mode='lines', line_color='blue', name=\"Best guess\"))\n", + "fig.add_trace(\n", + " go.Scatter(\n", + " x=base.datetime_utc,\n", + " y=base.co2_mass_lb_for_electricity_adjusted,\n", + " mode=\"lines\",\n", + " line_color=\"blue\",\n", + " name=\"Best guess\",\n", + " )\n", + ")\n", "\n", "fig.update_layout(\n", " title=f\"{ba} total carbon emissions\",\n", @@ -406,7 +503,7 @@ " legend_title=\"Estimate type\",\n", ")\n", "\n", - "fig.show()\n" + "fig.show()" ] }, { @@ -427,23 +524,51 @@ "\n", "issues = []\n", "for ba in os.listdir(\"../data/results/2020/power_sector_data/hourly/us_units/\"):\n", - " if \".DS_Store\" in ba: \n", + " if \".DS_Store\" in ba:\n", " continue\n", - " our_guess = pd.read_csv(f\"../data/results/2020/power_sector_data/hourly/us_units/{ba}\", parse_dates=[\"datetime_utc\"])\n", + " our_guess = pd.read_csv(\n", + " f\"../data/results/2020/power_sector_data/hourly/us_units/{ba}\",\n", + " parse_dates=[\"datetime_utc\"],\n", + " )\n", " our_guess = our_guess[our_guess.fuel_category == \"total\"]\n", " ba = ba.replace(\".csv\", \"\")\n", - " to_compare = our_guess[[\"datetime_utc\", \"co2_mass_lb_for_electricity_adjusted\", \"net_generation_mwh\"]].merge(minimum_bound.loc[minimum_bound.ba_code==ba,[\"datetime_utc\", \"co2_mass_lb_for_electricity_adjusted\", \"net_generation_mwh\"]],\n", - " how='left',\n", - " on='datetime_utc',\n", - " suffixes=(\"\",\"_min\")\n", + " to_compare = our_guess[\n", + " [\"datetime_utc\", \"co2_mass_lb_for_electricity_adjusted\", \"net_generation_mwh\"]\n", + " ].merge(\n", + " minimum_bound.loc[\n", + " minimum_bound.ba_code == ba,\n", + " [\n", + " \"datetime_utc\",\n", + " \"co2_mass_lb_for_electricity_adjusted\",\n", + " \"net_generation_mwh\",\n", + " ],\n", + " ],\n", + " how=\"left\",\n", + " on=\"datetime_utc\",\n", + " suffixes=(\"\", \"_min\"),\n", " )\n", - " to_compare = to_compare.merge(maximum_bound.loc[maximum_bound.ba_code==ba,[\"datetime_utc\", \"co2_mass_lb_for_electricity_adjusted\", \"net_generation_mwh\"]],\n", - " how='left',\n", - " on='datetime_utc',\n", - " suffixes=(\"_best\",\"_max\")\n", + " to_compare = to_compare.merge(\n", + " maximum_bound.loc[\n", + " maximum_bound.ba_code == ba,\n", + " [\n", + " \"datetime_utc\",\n", + " \"co2_mass_lb_for_electricity_adjusted\",\n", + " \"net_generation_mwh\",\n", + " ],\n", + " ],\n", + " how=\"left\",\n", + " on=\"datetime_utc\",\n", + " suffixes=(\"_best\", \"_max\"),\n", " )\n", - " to_compare[\"ok\"] = (to_compare[f\"{col_to_check}_min\"] > to_compare[f\"{col_to_check}_best\"]) | (to_compare[f\"{col_to_check}_best\"] > to_compare[f\"{col_to_check}_max\"])\n", - " issues.append(to_compare[[\"datetime_utc\", \"ok\"]].set_index(\"datetime_utc\").squeeze().rename(ba))\n" + " to_compare[\"ok\"] = (\n", + " to_compare[f\"{col_to_check}_min\"] > to_compare[f\"{col_to_check}_best\"]\n", + " ) | (to_compare[f\"{col_to_check}_best\"] > to_compare[f\"{col_to_check}_max\"])\n", + " issues.append(\n", + " to_compare[[\"datetime_utc\", \"ok\"]]\n", + " .set_index(\"datetime_utc\")\n", + " .squeeze()\n", + " .rename(ba)\n", + " )" ] }, { @@ -470,7 +595,7 @@ "metadata": {}, "outputs": [], "source": [ - "monthly_rates[monthly_rates.ba_code==\"DEAA\"]" + "monthly_rates[monthly_rates.ba_code == \"DEAA\"]" ] }, { From f1a8e3acdf24afd97bea4ff2d0edddf882a7e95c Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Wed, 29 Nov 2023 10:27:27 -0800 Subject: [PATCH 43/85] chore: format __init__ files --- src/__init__.py | 1 + test/__init__.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/__init__.py b/src/__init__.py index efd6d259..ef0055b3 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -2,4 +2,5 @@ import logging from .logging_util import configure_root_logger from .filepaths import outputs_folder + configure_root_logger(outputs_folder("logfile.txt"), logging.INFO) diff --git a/test/__init__.py b/test/__init__.py index 3ccc99fe..af248428 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1,3 +1,4 @@ # Tell path where our code is import sys -sys.path.append('../src') + +sys.path.append("../src") From cb1c4090362a778c7a8b65d03ce91f1aa997f0d1 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Mon, 11 Dec 2023 13:16:17 -0800 Subject: [PATCH 44/85] chore: format modules --- src/consumed.py | 10 +++++----- src/data_cleaning.py | 12 +++--------- src/eia930.py | 4 +--- src/impute_hourly_profiles.py | 4 +--- src/validation.py | 22 ++++++---------------- 5 files changed, 16 insertions(+), 36 deletions(-) diff --git a/src/consumed.py b/src/consumed.py index 5ff7cce8..ba75b609 100644 --- a/src/consumed.py +++ b/src/consumed.py @@ -439,12 +439,12 @@ def _load_rates(self): ) # Cut off emissions at 9 hours after UTC year - emissions = emissions[:f"{self.year+1}-01-01 09:00:00+00:00"] - rates[((adj, pol))] = emissions + emissions = emissions[: f"{self.year+1}-01-01 09:00:00+00:00"] + rates[(adj, pol)] = emissions # Make generation data frame generation = pd.DataFrame(data=gens) - generation = generation[:f"{self.year+1}-01-01 09:00:00+00:00"] + generation = generation[: f"{self.year+1}-01-01 09:00:00+00:00"] return rates, generation @@ -462,7 +462,7 @@ def build_matrices(self, pol: str, adj: str, date): # Build generation array, using 930 for import-only regions G = np.zeros(len(self.regions)) - for (i, r) in enumerate(self.regions): + for i, r in enumerate(self.regions): if r in self.import_regions: G[i] = self.eia930.df.loc[date, KEYS["E"]["NG"] % r] else: @@ -513,7 +513,7 @@ def run(self): consumed_emissions = np.full(len(self.regions), np.nan) # Export - for (i, r) in enumerate(self.regions): + for i, r in enumerate(self.regions): self.results[r].loc[date, col] = consumed_emissions[i] if total_failed > 0: logger.warning( diff --git a/src/data_cleaning.py b/src/data_cleaning.py index e5c70a14..1589f019 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -88,9 +88,7 @@ def generate_subplant_ids(start_year, end_year, cems_ids): filtered_crosswalk = epacamd_eia.filter_crosswalk(crosswalk, cems_ids) # use graph analysis to identify subplants - crosswalk_with_subplant_ids = make_subplant_ids( - filtered_crosswalk - ) + crosswalk_with_subplant_ids = make_subplant_ids(filtered_crosswalk) # change the eia plant id to int crosswalk_with_subplant_ids["plant_id_eia"] = crosswalk_with_subplant_ids[ @@ -462,9 +460,7 @@ def clean_eia923( "fuel_consumed_mmbtu", "fuel_consumed_for_electricity_mmbtu", ], - ].round( - 1 - ) + ].round(1) validation.test_for_missing_energy_source_code(gen_fuel_allocated) validation.test_for_negative_values(gen_fuel_allocated) @@ -637,9 +633,7 @@ def create_primary_fuel_table(gen_fuel_allocated, add_subplant_id, year): ascending=True, ).drop_duplicates( subset=["plant_id_eia", "subplant_id", "generator_id"], keep="last" - )[ - ["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"] - ] + )[["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"]] if not add_subplant_id: gen_primary_fuel = gen_primary_fuel.drop(columns=["subplant_id"]) diff --git a/src/eia930.py b/src/eia930.py index a4892f64..88da923d 100644 --- a/src/eia930.py +++ b/src/eia930.py @@ -459,9 +459,7 @@ def manual_930_adjust(raw: pd.DataFrame): & (raw.index < "2022-06-16 07:00:00+00") ), cols, - ].shift( - 1, freq="H" - ) + ].shift(1, freq="H") raw = raw.drop(columns=cols) raw = pd.concat([raw, new], axis="columns") diff --git a/src/impute_hourly_profiles.py b/src/impute_hourly_profiles.py index d796b013..102192cd 100644 --- a/src/impute_hourly_profiles.py +++ b/src/impute_hourly_profiles.py @@ -425,9 +425,7 @@ def calculate_residual( ~combined_data["eia930_profile"].isna(), "cems_profile" ] = combined_data.loc[ ~combined_data["eia930_profile"].isna(), "cems_profile" - ].fillna( - 0 - ) + ].fillna(0) combined_data = calculate_scaled_residual(combined_data) combined_data = calculate_shifted_residual(combined_data) diff --git a/src/validation.py b/src/validation.py index 2302762c..beb91e2e 100644 --- a/src/validation.py +++ b/src/validation.py @@ -340,7 +340,7 @@ def check_missing_or_zero_generation_matches(combined_gen_data): # identify when there is zero or NA gross generation associated with positive net generation missing_gross_gen = combined_gen_data[ (combined_gen_data["net_generation_mwh"] > 0) - & ((combined_gen_data["gross_generation_mwh"] == 0)) + & (combined_gen_data["gross_generation_mwh"] == 0) ] # identify when there is zero or NA net generation associated with nonzero gross generation @@ -620,9 +620,7 @@ def ensure_non_overlapping_data_from_all_sources( ["in_eia", "in_cems", "in_partial_cems_subplant", "in_partial_cems_plant"] ] = data_overlap[ ["in_eia", "in_cems", "in_partial_cems_subplant", "in_partial_cems_plant"] - ].fillna( - 0 - ) + ].fillna(0) data_overlap["number_of_locations"] = ( data_overlap["in_eia"] + data_overlap["in_cems"] @@ -1257,9 +1255,7 @@ def summarize_cems_measurement_quality(cems): "so2_mass_measurement_code", "nox_mass_measurement_code", ] - ].astype( - str - ) + ].astype(str) # replace the CEMS mass measurement codes with two categories measurement_code_map = { "Measured": "Measured", @@ -1282,9 +1278,7 @@ def summarize_cems_measurement_quality(cems): "so2_mass_measurement_code", "nox_mass_measurement_code", ] - ].replace( - measurement_code_map - ) + ].replace(measurement_code_map) cems_quality_summary = [] # calculate the percent of mass for each pollutant that is measured or imputed @@ -1797,16 +1791,12 @@ def load_egrid_plant_file(year): ] = egrid_plant.loc[ egrid_plant["plant_primary_fuel"].isin(CLEAN_FUELS), "co2_mass_lb_for_electricity_adjusted", - ].fillna( - 0 - ) + ].fillna(0) egrid_plant.loc[ egrid_plant["plant_primary_fuel"].isin(CLEAN_FUELS), "co2_mass_lb" ] = egrid_plant.loc[ egrid_plant["plant_primary_fuel"].isin(CLEAN_FUELS), "co2_mass_lb" - ].fillna( - 0 - ) + ].fillna(0) # reorder the columns egrid_plant = egrid_plant[ From 8fa55c0751f50840f01addf40d95204d93c89647 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Mon, 11 Dec 2023 13:24:44 -0800 Subject: [PATCH 45/85] chore: lint modules --- src/data_cleaning.py | 4 +--- src/eia930.py | 2 +- src/gross_to_net_generation.py | 3 +-- src/load_data.py | 1 - src/output_data.py | 2 +- src/validation.py | 2 +- 6 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/data_cleaning.py b/src/data_cleaning.py index 1589f019..c2bf1d24 100644 --- a/src/data_cleaning.py +++ b/src/data_cleaning.py @@ -1,7 +1,5 @@ import pandas as pd import numpy as np -import os -import sqlalchemy as sa import pudl.analysis.allocate_gen_fuel as allocate_gen_fuel import pudl.analysis.epacamd_eia as epacamd_eia @@ -12,7 +10,7 @@ import emissions from emissions import CLEAN_FUELS from column_checks import get_dtypes, apply_dtypes -from filepaths import manual_folder, outputs_folder, downloads_folder +from filepaths import manual_folder, outputs_folder from logging_util import get_logger logger = get_logger(__name__) diff --git a/src/eia930.py b/src/eia930.py index 88da923d..2e49a15a 100644 --- a/src/eia930.py +++ b/src/eia930.py @@ -12,7 +12,7 @@ # Tell gridemissions where to find config before we load gridemissions os.environ["GRIDEMISSIONS_CONFIG_FILE_PATH"] = top_folder("config/gridemissions.json") -from gridemissions.workflows import make_dataset +from gridemissions.workflows import make_dataset # noqa E402 logger = get_logger(__name__) diff --git a/src/gross_to_net_generation.py b/src/gross_to_net_generation.py index ad5aae58..f1cd861e 100644 --- a/src/gross_to_net_generation.py +++ b/src/gross_to_net_generation.py @@ -2,7 +2,6 @@ import os import pandas as pd import statsmodels.formula.api as smf -import sqlalchemy as sa import warnings # import pudl packages @@ -13,7 +12,7 @@ import data_cleaning import validation from column_checks import get_dtypes -from filepaths import outputs_folder, downloads_folder +from filepaths import outputs_folder from logging_util import get_logger logger = get_logger(__name__) diff --git a/src/load_data.py b/src/load_data.py index b1f9725e..43f6ab63 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -1,6 +1,5 @@ import pandas as pd import numpy as np -import os import sqlalchemy as sa import warnings from pathlib import Path diff --git a/src/output_data.py b/src/output_data.py index f8137731..4591e8bb 100644 --- a/src/output_data.py +++ b/src/output_data.py @@ -462,7 +462,7 @@ def write_power_sector_results(ba_fuel_data, path_prefix, skip_outputs): if not skip_outputs: for ba in list(ba_fuel_data.ba_code.unique()): - if type(ba) is not str: + if not isinstance(ba, str): logger.warning( f"not aggregating {sum(ba_fuel_data.ba_code.isna())} plants with numeric BA {ba}" ) diff --git a/src/validation.py b/src/validation.py index beb91e2e..7c9f9016 100644 --- a/src/validation.py +++ b/src/validation.py @@ -220,7 +220,7 @@ def check_for_orphaned_cc_part_in_subplant(subplant_crosswalk): "prime_mover_code" ].agg(["unique"]) cc_subplants["unique_cc_pms"] = [ - ",".join(map(str, l)) for l in cc_subplants["unique"] + ",".join(map(str, L)) for L in cc_subplants["unique"] ] cc_subplants = cc_subplants.drop(columns="unique") # identify where there are subplants that only contain a single CC part From f1675fafeb73474df2599b435ba57a52688c334d Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Mon, 11 Dec 2023 13:35:29 -0800 Subject: [PATCH 46/85] chore: format test modules --- test/test_eia.py | 1 + test/test_logging.py | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/test/test_eia.py b/test/test_eia.py index 21642077..0203722a 100644 --- a/test/test_eia.py +++ b/test/test_eia.py @@ -7,6 +7,7 @@ from src.eia import EIA + # File open mocking modeled on https://stackoverflow.com/questions/1289894/how-do-i-mock-an-open-used-in-a-with-statement-using-the-mock-framework-in-pyth @pytest.fixture @patch( diff --git a/test/test_logging.py b/test/test_logging.py index f905175f..5758cca5 100644 --- a/test/test_logging.py +++ b/test/test_logging.py @@ -3,8 +3,8 @@ import pandas as pd -sys.path.append('../src') -sys.path.append('..') +sys.path.append("../src") +sys.path.append("..") import src.eia930 as eia930 from src.filepaths import top_folder @@ -13,21 +13,21 @@ pudl_logger = logging.getLogger(name="catalystcoop.pudl") -configure_root_logger(logfile=top_folder('test/test_logfile.txt'), level=logging.INFO) +configure_root_logger(logfile=top_folder("test/test_logfile.txt"), level=logging.INFO) # If you call this again, nothing bad should happen. Logging statements should # still only show up once. -configure_root_logger(logfile=top_folder('test/test_logfile.txt'), level=logging.INFO) -logger = get_logger('test') +configure_root_logger(logfile=top_folder("test/test_logfile.txt"), level=logging.INFO) +logger = get_logger("test") def main(): - """These statements should each be printed once in a nice format.""" - logger.info('This is the OGE logger') - pudl_logger.info('This is the PUDL logger') + """These statements should each be printed once in a nice format.""" + logger.info("This is the OGE logger") + pudl_logger.info("This is the PUDL logger") - df = pd.DataFrame({"a": [1,2,3], "b": [4,5,6]}) - logger.info("\n" + df.to_string()) + df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}) + logger.info("\n" + df.to_string()) -if __name__ == '__main__': - main() +if __name__ == "__main__": + main() From 6a9e473d75a6d6d04bf261b9a64001c774b6bd47 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Mon, 11 Dec 2023 13:38:34 -0800 Subject: [PATCH 47/85] chore: lint test modules --- test/test_logging.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/test_logging.py b/test/test_logging.py index 5758cca5..c97b82d1 100644 --- a/test/test_logging.py +++ b/test/test_logging.py @@ -6,10 +6,9 @@ sys.path.append("../src") sys.path.append("..") -import src.eia930 as eia930 -from src.filepaths import top_folder +from src.filepaths import top_folder # noqa E402 -from src.logging_util import get_logger, configure_root_logger +from src.logging_util import get_logger, configure_root_logger # noqa E402 pudl_logger = logging.getLogger(name="catalystcoop.pudl") From 7580cc77dc3896a90c25054277f0264aa87da214 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Wed, 29 Nov 2023 10:49:40 -0800 Subject: [PATCH 48/85] chore: add lint github workflow --- .github/workflows/lint.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..5c7c50a6 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,19 @@ +name: Lint + +on: + push: + pull_request: + branches: + - development + - main + +jobs: + formatting: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + - run: python -m pip install --upgrade ruff + - run: ruff check . --diff + - run: ruff format . --diff From f796aa586dea884b8a960422e4c16247628e511d Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Mon, 11 Dec 2023 15:05:48 -0800 Subject: [PATCH 49/85] chore: update pyproject.toml file for packaging with Hatch --- pyproject.toml | 64 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index dfe594eb..127d44d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,67 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + + [project] -name = "open-grid-emissions" -requires-python = ">3.10" +name = "oge" +version = "0.2.2" +requires-python = ">3.11" readme = "README.md" +authors = [ + { name="Greg Miller", email="greg.miller@singularity.energy" }, +] +description = "Open-source grid emissions data processing tools" +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", +] + +dependencies = [ + "cvxopt", + "cvxpy", + "osqp", + "numpy", + "openpyxl", + "pandas", + "pyarrow", + "qdldl", + "requests", + "seaborn", + "sqlalchemy", + "statsmodels", + "coloredlogs", + "catalystcoop-pudl@git+https://github.com/singularity-energy/pudl.git", + "gridemissions@git+https://github.com/gailin-p/gridemissions.git", +] + +[project.optional-dependencies] +dev = [ + "pytest", + "ruff", +] +notebook = [ + "ipykernel", + "notebook", + "plotly", +] + +[project.urls] +Homepage = "https://github.com/singularity-energy/open-grid-emissions" +Issues = "https://github.com/singularity-energy/open-grid-emissions/issues" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.wheel] +only-include = ["config", "data/manual", "src/oge"] + +[tool.hatch.build.targets.wheel.sources] +"src" = "" +"data" = "data" +"config" = "config" + [tool.ruff] # Exclude a variety of commonly ignored directories. From af6467877d543e6c1501252771d7e431498073b2 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Mon, 11 Dec 2023 15:08:16 -0800 Subject: [PATCH 50/85] chore: move modules into a new oge directory --- src/{ => oge}/__init__.py | 0 src/{ => oge}/column_checks.py | 0 src/{ => oge}/consumed.py | 0 src/{ => oge}/data_cleaning.py | 0 src/{ => oge}/data_pipeline.py | 0 src/{ => oge}/download_data.py | 0 src/{ => oge}/eia930.py | 0 src/{ => oge}/emissions.py | 0 src/{ => oge}/filepaths.py | 0 src/{ => oge}/gross_to_net_generation.py | 0 src/{ => oge}/impute_hourly_profiles.py | 0 src/{ => oge}/load_data.py | 0 src/{ => oge}/logging_util.py | 0 src/{ => oge}/output_data.py | 0 src/{ => oge}/validation.py | 0 src/{ => oge}/visualization.py | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename src/{ => oge}/__init__.py (100%) rename src/{ => oge}/column_checks.py (100%) rename src/{ => oge}/consumed.py (100%) rename src/{ => oge}/data_cleaning.py (100%) rename src/{ => oge}/data_pipeline.py (100%) rename src/{ => oge}/download_data.py (100%) rename src/{ => oge}/eia930.py (100%) rename src/{ => oge}/emissions.py (100%) rename src/{ => oge}/filepaths.py (100%) rename src/{ => oge}/gross_to_net_generation.py (100%) rename src/{ => oge}/impute_hourly_profiles.py (100%) rename src/{ => oge}/load_data.py (100%) rename src/{ => oge}/logging_util.py (100%) rename src/{ => oge}/output_data.py (100%) rename src/{ => oge}/validation.py (100%) rename src/{ => oge}/visualization.py (100%) diff --git a/src/__init__.py b/src/oge/__init__.py similarity index 100% rename from src/__init__.py rename to src/oge/__init__.py diff --git a/src/column_checks.py b/src/oge/column_checks.py similarity index 100% rename from src/column_checks.py rename to src/oge/column_checks.py diff --git a/src/consumed.py b/src/oge/consumed.py similarity index 100% rename from src/consumed.py rename to src/oge/consumed.py diff --git a/src/data_cleaning.py b/src/oge/data_cleaning.py similarity index 100% rename from src/data_cleaning.py rename to src/oge/data_cleaning.py diff --git a/src/data_pipeline.py b/src/oge/data_pipeline.py similarity index 100% rename from src/data_pipeline.py rename to src/oge/data_pipeline.py diff --git a/src/download_data.py b/src/oge/download_data.py similarity index 100% rename from src/download_data.py rename to src/oge/download_data.py diff --git a/src/eia930.py b/src/oge/eia930.py similarity index 100% rename from src/eia930.py rename to src/oge/eia930.py diff --git a/src/emissions.py b/src/oge/emissions.py similarity index 100% rename from src/emissions.py rename to src/oge/emissions.py diff --git a/src/filepaths.py b/src/oge/filepaths.py similarity index 100% rename from src/filepaths.py rename to src/oge/filepaths.py diff --git a/src/gross_to_net_generation.py b/src/oge/gross_to_net_generation.py similarity index 100% rename from src/gross_to_net_generation.py rename to src/oge/gross_to_net_generation.py diff --git a/src/impute_hourly_profiles.py b/src/oge/impute_hourly_profiles.py similarity index 100% rename from src/impute_hourly_profiles.py rename to src/oge/impute_hourly_profiles.py diff --git a/src/load_data.py b/src/oge/load_data.py similarity index 100% rename from src/load_data.py rename to src/oge/load_data.py diff --git a/src/logging_util.py b/src/oge/logging_util.py similarity index 100% rename from src/logging_util.py rename to src/oge/logging_util.py diff --git a/src/output_data.py b/src/oge/output_data.py similarity index 100% rename from src/output_data.py rename to src/oge/output_data.py diff --git a/src/validation.py b/src/oge/validation.py similarity index 100% rename from src/validation.py rename to src/oge/validation.py diff --git a/src/visualization.py b/src/oge/visualization.py similarity index 100% rename from src/visualization.py rename to src/oge/visualization.py From 5beb23a95086f0eb12058731f570f88df903709b Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Mon, 11 Dec 2023 15:09:17 -0800 Subject: [PATCH 51/85] chore: update .gitignore file --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 093d108f..239ee4a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +src/oge/__pycache__ + +dist/* + data/* !data/manual/ From 451bb1186a778ccb836f3eb8b99722d7f6976385 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Mon, 11 Dec 2023 18:48:05 -0800 Subject: [PATCH 52/85] chore: update import statements in modules --- src/oge/__init__.py | 4 ++-- src/oge/column_checks.py | 2 +- src/oge/consumed.py | 6 +++--- src/oge/data_cleaning.py | 14 +++++++------- src/oge/data_pipeline.py | 28 +++++++++++++++------------- src/oge/download_data.py | 4 ++-- src/oge/eia930.py | 8 ++++---- src/oge/emissions.py | 10 +++++----- src/oge/gross_to_net_generation.py | 12 ++++++------ src/oge/impute_hourly_profiles.py | 12 ++++++------ src/oge/load_data.py | 8 ++++---- src/oge/logging_util.py | 2 +- src/oge/output_data.py | 11 ++++++----- src/oge/validation.py | 12 ++++++------ src/oge/visualization.py | 2 +- 15 files changed, 69 insertions(+), 66 deletions(-) diff --git a/src/oge/__init__.py b/src/oge/__init__.py index ef0055b3..e100a715 100644 --- a/src/oge/__init__.py +++ b/src/oge/__init__.py @@ -1,6 +1,6 @@ # Set up the OGE logging configuration once. import logging -from .logging_util import configure_root_logger -from .filepaths import outputs_folder +from oge.logging_util import configure_root_logger +from oge.filepaths import outputs_folder configure_root_logger(outputs_folder("logfile.txt"), logging.INFO) diff --git a/src/oge/column_checks.py b/src/oge/column_checks.py index c2ae36ff..fc948bcb 100644 --- a/src/oge/column_checks.py +++ b/src/oge/column_checks.py @@ -17,7 +17,7 @@ After any change, re-run data_pipeline to regenerate all files and re-run these checks. """ -from logging_util import get_logger +from oge.logging_util import get_logger logger = get_logger(__name__) diff --git a/src/oge/consumed.py b/src/oge/consumed.py index ba75b609..f63879e2 100644 --- a/src/oge/consumed.py +++ b/src/oge/consumed.py @@ -5,10 +5,10 @@ from gridemissions.load import BaData from gridemissions.eia_api import KEYS, SRC -from filepaths import outputs_folder, manual_folder, results_folder -from logging_util import get_logger +from oge.filepaths import outputs_folder, manual_folder, results_folder +from oge.logging_util import get_logger -from output_data import ( +from oge.output_data import ( GENERATED_EMISSION_RATE_COLS, CONSUMED_EMISSION_RATE_COLS, output_to_results, diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index c2bf1d24..e12724ab 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -5,13 +5,13 @@ import pudl.analysis.epacamd_eia as epacamd_eia from pudl.etl.glue_assets import make_subplant_ids -import load_data -import validation -import emissions -from emissions import CLEAN_FUELS -from column_checks import get_dtypes, apply_dtypes -from filepaths import manual_folder, outputs_folder -from logging_util import get_logger +import oge.load_data as load_data +import oge.validation as validation +import oge.emissions as emissions +from oge.emissions import CLEAN_FUELS +from oge.column_checks import get_dtypes, apply_dtypes +from oge.filepaths import manual_folder, outputs_folder +from oge.logging_util import get_logger logger = get_logger(__name__) diff --git a/src/oge/data_pipeline.py b/src/oge/data_pipeline.py index 890a4439..d28820ca 100644 --- a/src/oge/data_pipeline.py +++ b/src/oge/data_pipeline.py @@ -11,17 +11,17 @@ import shutil # import local modules -import download_data -import data_cleaning -import emissions -import gross_to_net_generation -import impute_hourly_profiles -import eia930 -import validation -import output_data -import consumed -from filepaths import downloads_folder, outputs_folder, results_folder -from logging_util import get_logger, configure_root_logger +import oge.download_data as download_data +import oge.data_cleaning as data_cleaning +import oge.emissions as emissions +import oge.gross_to_net_generation as gross_to_net_generation +import oge.impute_hourly_profiles as impute_hourly_profiles +import oge.eia930 as eia930 +import oge.validation as validation +import oge.output_data as output_data +import oge.consumed as consumed +from oge.filepaths import downloads_folder, outputs_folder, results_folder +from oge.logging_util import get_logger, configure_root_logger def get_args() -> argparse.Namespace: @@ -67,7 +67,7 @@ def print_args(args: argparse.Namespace, logger): logger.info(f"\n\nRunning with the following options:\n{argstring}\n") -def main(): +def main(args): """Runs the OGE data pipeline.""" args = get_args() year = args.year @@ -616,4 +616,6 @@ def main(): if __name__ == "__main__": - main() + import sys + + main(sys.argv[1:]) diff --git a/src/oge/download_data.py b/src/oge/download_data.py index 60d1ad2b..4d7fac1f 100644 --- a/src/oge/download_data.py +++ b/src/oge/download_data.py @@ -7,8 +7,8 @@ import tarfile import zipfile -from filepaths import downloads_folder, data_folder -from logging_util import get_logger +from oge.filepaths import downloads_folder, data_folder +from oge.logging_util import get_logger logger = get_logger(__name__) diff --git a/src/oge/eia930.py b/src/oge/eia930.py index 2e49a15a..db5fbbe1 100644 --- a/src/oge/eia930.py +++ b/src/oge/eia930.py @@ -4,10 +4,10 @@ import os from os.path import join -import load_data -from column_checks import get_dtypes -from filepaths import top_folder, downloads_folder, outputs_folder, manual_folder -from logging_util import get_logger +import oge.load_data as load_data +from oge.column_checks import get_dtypes +from oge.filepaths import top_folder, downloads_folder, outputs_folder, manual_folder +from oge.logging_util import get_logger # Tell gridemissions where to find config before we load gridemissions os.environ["GRIDEMISSIONS_CONFIG_FILE_PATH"] = top_folder("config/gridemissions.json") diff --git a/src/oge/emissions.py b/src/oge/emissions.py index da8aca7f..b3e5e3f4 100644 --- a/src/oge/emissions.py +++ b/src/oge/emissions.py @@ -1,11 +1,11 @@ import pandas as pd import numpy as np -import load_data -import validation -from column_checks import get_dtypes -from filepaths import manual_folder -from logging_util import get_logger +import oge.load_data as load_data +import oge.validation as validation +from oge.column_checks import get_dtypes +from oge.filepaths import manual_folder +from oge.logging_util import get_logger from pudl.analysis.allocate_gen_fuel import ( distribute_annually_reported_data_to_months_if_annual, diff --git a/src/oge/gross_to_net_generation.py b/src/oge/gross_to_net_generation.py index f1cd861e..f835c586 100644 --- a/src/oge/gross_to_net_generation.py +++ b/src/oge/gross_to_net_generation.py @@ -8,12 +8,12 @@ import pudl.analysis.allocate_gen_fuel as allocate_gen_fuel # import other modules -import load_data -import data_cleaning -import validation -from column_checks import get_dtypes -from filepaths import outputs_folder -from logging_util import get_logger +import oge.load_data as load_data +import oge.data_cleaning as data_cleaning +import oge.validation as validation +from oge.column_checks import get_dtypes +from oge.filepaths import outputs_folder +from oge.logging_util import get_logger logger = get_logger(__name__) diff --git a/src/oge/impute_hourly_profiles.py b/src/oge/impute_hourly_profiles.py index 102192cd..13869136 100644 --- a/src/oge/impute_hourly_profiles.py +++ b/src/oge/impute_hourly_profiles.py @@ -2,12 +2,12 @@ import numpy as np # import open-grid-emissions modules -from column_checks import apply_dtypes -import load_data -from filepaths import manual_folder -import validation -import output_data -from logging_util import get_logger +from oge.column_checks import apply_dtypes +import oge.load_data as load_data +from oge.filepaths import manual_folder +import oge.validation as validation +import oge.output_data as output_data +from oge.logging_util import get_logger logger = get_logger(__name__) diff --git a/src/oge/load_data.py b/src/oge/load_data.py index 43f6ab63..9d9f9846 100644 --- a/src/oge/load_data.py +++ b/src/oge/load_data.py @@ -4,10 +4,10 @@ import warnings from pathlib import Path -from column_checks import get_dtypes -from filepaths import downloads_folder, manual_folder, outputs_folder -from validation import validate_unique_datetimes -from logging_util import get_logger +from oge.column_checks import get_dtypes +from oge.filepaths import downloads_folder, manual_folder, outputs_folder +from oge.validation import validate_unique_datetimes +from oge.logging_util import get_logger from pudl.metadata.fields import apply_pudl_dtypes diff --git a/src/oge/logging_util.py b/src/oge/logging_util.py index 3ad47428..f719278d 100644 --- a/src/oge/logging_util.py +++ b/src/oge/logging_util.py @@ -2,7 +2,7 @@ import logging import coloredlogs -from filepaths import make_containing_folder +from oge.filepaths import make_containing_folder def get_logger(name: str) -> logging.Logger: diff --git a/src/oge/output_data.py b/src/oge/output_data.py index 4591e8bb..2a966495 100644 --- a/src/oge/output_data.py +++ b/src/oge/output_data.py @@ -3,11 +3,12 @@ import numpy as np import shutil import os -import load_data -import column_checks -import validation -from filepaths import outputs_folder, results_folder, data_folder -from logging_util import get_logger + +import oge.load_data as load_data +import oge.column_checks as column_checks +import oge.validation as validation +from oge.filepaths import outputs_folder, results_folder, data_folder +from oge.logging_util import get_logger logger = get_logger(__name__) diff --git a/src/oge/validation.py b/src/oge/validation.py index 7c9f9016..fbd46aea 100644 --- a/src/oge/validation.py +++ b/src/oge/validation.py @@ -1,12 +1,12 @@ import pandas as pd import numpy as np -import load_data -import impute_hourly_profiles -from emissions import CLEAN_FUELS -from column_checks import get_dtypes -from filepaths import downloads_folder, manual_folder -from logging_util import get_logger +import oge.load_data as load_data +import oge.impute_hourly_profiles as impute_hourly_profiles +from oge.emissions import CLEAN_FUELS +from oge.column_checks import get_dtypes +from oge.filepaths import downloads_folder, manual_folder +from oge.logging_util import get_logger logger = get_logger(__name__) diff --git a/src/oge/visualization.py b/src/oge/visualization.py index 18c626bf..1ae25fee 100644 --- a/src/oge/visualization.py +++ b/src/oge/visualization.py @@ -2,7 +2,7 @@ import pandas as pd import plotly.express as px -from filepaths import downloads_folder, results_folder +from oge.filepaths import downloads_folder, results_folder """ From a timeseries, make a day-hour array with hours in EST. Also return day labels for plotting. From 65cb5b388d0e61b3b25a50eb0589dce2cf94d777 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Wed, 13 Dec 2023 16:55:23 -0800 Subject: [PATCH 53/85] chore: regenerate pipenv lockfile --- Pipfile.lock | 508 +++++++++++++++++++++------------------------------ 1 file changed, 206 insertions(+), 302 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 99d8df37..79b4829f 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -169,13 +169,21 @@ ], "version": "==1.4.4" }, + "appnope": { + "hashes": [ + "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24", + "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e" + ], + "markers": "platform_system == 'Darwin'", + "version": "==0.1.3" + }, "arelle-release": { "hashes": [ - "sha256:359b403a9b621668af21c3c249651580a44052a7b669075d512adb5fa18ef590", - "sha256:8b9db9108de1c714e794a0d5f827609ef524a6b2dd1204a298d7ced0ba220079" + "sha256:1a585cc9a9a222ebb6a351c28ae942ea750bf194c9c3081edbe2685be80addc1", + "sha256:fd2145bed91043a584dca79f04c06c604ac912a97e3ea5e8c289b2576a71a7b1" ], "markers": "python_version >= '3.8'", - "version": "==2.18.0" + "version": "==2.19.0" }, "argon2-cffi": { "hashes": [ @@ -237,11 +245,11 @@ }, "astroid": { "hashes": [ - "sha256:7d5895c9825e18079c5aeac0572bc2e4c83205c95d416e0b4fee8bc361d2d9ca", - "sha256:86b0bb7d7da0be1a7c4aedb7974e391b32d4ed89e33de6ed6902b4b15c97577e" + "sha256:4a61cf0a59097c7bb52689b0fd63717cd2a8a14dc9f1eee97b82d814881c8c91", + "sha256:d6e62862355f60e716164082d6b4b041d38e2a8cf1c7cd953ded5108bac8ff5c" ], "markers": "python_version < '3.12'", - "version": "==3.0.1" + "version": "==3.0.2" }, "asttokens": { "hashes": [ @@ -268,11 +276,11 @@ }, "babel": { "hashes": [ - "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900", - "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed" + "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363", + "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287" ], "markers": "python_version >= '3.7'", - "version": "==2.13.1" + "version": "==2.14.0" }, "beautifulsoup4": { "hashes": [ @@ -292,19 +300,19 @@ }, "boto3": { "hashes": [ - "sha256:9486f66f9a89f66d64d25cb4baa55aad323a1734ef9815b7a2c4c0787a3fc1fb", - "sha256:baa6ea61527bcc82365a4ef365aa8f34126483ff8533d01274f3cdb340c22d73" + "sha256:8b3c4d4e720c0ad706590c284b8f30c76de3472c1ce1bac610425f99bf6ab53b", + "sha256:c9b400529932ed4652304756528ab235c6730aa5d00cb4d9e4848ce460c82c16" ], - "markers": "python_version >= '3.7'", - "version": "==1.33.9" + "markers": "python_version >= '3.8'", + "version": "==1.34.0" }, "botocore": { "hashes": [ - "sha256:07ff4eea62f546da540310887000c81fca802c788eb374fef06eda28009dcafd", - "sha256:1b90be11dd9a9a25290c995a6b713e76b9e2bf7bf86ba9036e0d28f2ceb2edfc" + "sha256:6ec19f6c9f61c3df22fb3e083940ac7946a3d96128db1f370f10aea702bb157f", + "sha256:711b406de910585395466ca649bceeea87a04300ddf74d9a2e20727c7f27f2f1" ], - "markers": "python_version >= '3.7'", - "version": "==1.33.9" + "markers": "python_version >= '3.8'", + "version": "==1.34.0" }, "bottleneck": { "hashes": [ @@ -880,24 +888,24 @@ }, "dagster": { "hashes": [ - "sha256:6fb1a26bc4b345c3b71aea7f629656f9f37b578bce11293b554fbaa9d655c6b9", - "sha256:80f7f90e54893573b3939562f7282cb6ddfa3ad033a5c09c286819f9d7f95907" + "sha256:1de2373bea87603873de12a8d08862d5c29d53fb145a7ff3fd97ad5874c21972", + "sha256:ea0937f08421c07aa0400b532c35ea25cae39e111aff412f49382692d574749c" ], - "version": "==1.5.10" + "version": "==1.5.12" }, "dagster-pipes": { "hashes": [ - "sha256:5c34c7788b29414d1d855125a122a6c3e2d5af7af17f542bd9e53bd1b46aef2e", - "sha256:c305e09de6b467394c9c2d5977fa66ded2cf3d7d41a297fd316db3bcb8200c37" + "sha256:66fcd15a0fd68d7a3be1dc0a384163b6d43cc83adcf868de98b0134315b87c41", + "sha256:aa488ee92ce7b89df2eada9282e6da39f967ee241ff12ab468ebbf2332f090e8" ], - "version": "==1.5.10" + "version": "==1.5.12" }, "dagster-postgres": { "hashes": [ - "sha256:1ee17fe04db39f726c4cee219144cfe777a948c29e0949188230e9615ee54fe7", - "sha256:8bd21d904baffd8373912c9ea1f60f087d43c81bcb563679889fca6d48a7815f" + "sha256:566b33e3a5e05809eec4501ab4915beced9e1ba125d9e41d988632ffc330562f", + "sha256:e2cadae93f099938d460be7290ef3c330d8b2bcfe666b4ce8593d0f91fb3aca5" ], - "version": "==0.21.10" + "version": "==0.21.12" }, "dask": { "hashes": [ @@ -964,10 +972,10 @@ }, "distlib": { "hashes": [ - "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057", - "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8" + "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784", + "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64" ], - "version": "==0.3.7" + "version": "==0.3.8" }, "dnspython": { "hashes": [ @@ -1237,11 +1245,11 @@ }, "fsspec": { "hashes": [ - "sha256:6271f1d3075a378bfe432f6f42bf7e1d2a6ba74f78dd9b512385474c579146a0", - "sha256:c4da01a35ac65c853f833e43f67802c25213f560820d54ddf248f92eddd5e990" + "sha256:8548d39e8810b59c38014934f6b31e57f40c1b20f911f4cc2b85389c7e9bf0cb", + "sha256:d800d87f72189a745fa3d6b033b9dc4a34ad069f60ca60b943a63599f5501960" ], "markers": "python_version >= '3.8'", - "version": "==2023.12.1" + "version": "==2023.12.2" }, "furo": { "hashes": [ @@ -1253,11 +1261,11 @@ }, "gcsfs": { "hashes": [ - "sha256:c1ccfa9f84dca019cd334aaf7eb03cc1dc13c296717346927a9fd40255348f9c", - "sha256:e86cc583fdf879e5ea2f87bab61738d26ec7e8972762a1e6c6ab758b1e1af99c" + "sha256:4123cee2c44118d4c0c0f7405abe7610dd2d87087857520c6a7769765ec51d43", + "sha256:e38b7e59580a1e490d62d55a47cba33b49a941b01917c3d6f6cfd2563371ab7b" ], "markers": "python_version >= '3.8'", - "version": "==2023.12.1" + "version": "==2023.12.2.post1" }, "geopandas": { "hashes": [ @@ -1285,43 +1293,43 @@ }, "google-api-core": { "hashes": [ - "sha256:5368a4502b793d9bbf812a5912e13e4e69f9bd87f6efb508460c43f5bbd1ce41", - "sha256:de2fb50ed34d47ddbb2bd2dcf680ee8fead46279f4ed6b16de362aca23a18952" + "sha256:2aa56d2be495551e66bbff7f729b790546f87d5c90e74781aa77233bcb395a8a", + "sha256:abc978a72658f14a2df1e5e12532effe40f94f868f6e23d95133bd6abcca35ca" ], "markers": "python_version >= '3.7'", - "version": "==2.14.0" + "version": "==2.15.0" }, "google-auth": { "hashes": [ - "sha256:d5d66b8f4f6e3273740d7bb73ddefa6c2d1ff691704bd407d51c6b5800e7c97b", - "sha256:dfd7b44935d498e106c08883b2dac0ad36d8aa10402a6412e9a1c9d74b4773f1" + "sha256:42f707937feb4f5e5a39e6c4f343a17300a459aaf03141457ba505812841cc40", + "sha256:473a8dfd0135f75bb79d878436e568f2695dce456764bf3a02b6f8c540b1d256" ], "markers": "python_version >= '3.7'", - "version": "==2.25.1" + "version": "==2.25.2" }, "google-auth-oauthlib": { "hashes": [ - "sha256:089c6e587d36f4803ac7e0720c045c6a8b1fd1790088b8424975b90d0ee61c12", - "sha256:83ea8c3b0881e453790baff4448e8a6112ac8778d1de9da0b68010b843937afb" + "sha256:292d2d3783349f2b0734a0a0207b1e1e322ac193c2c09d8f7c613fb7cc501ea8", + "sha256:297c1ce4cb13a99b5834c74a1fe03252e1e499716718b190f56bcb9c4abc4faf" ], "markers": "python_version >= '3.6'", - "version": "==1.1.0" + "version": "==1.2.0" }, "google-cloud-core": { "hashes": [ - "sha256:37b80273c8d7eee1ae816b3a20ae43585ea50506cb0e60f3cf5be5f87f1373cb", - "sha256:fbd11cad3e98a7e5b0343dc07cb1039a5ffd7a5bb96e1f1e27cee4bda4a90863" + "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073", + "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61" ], "markers": "python_version >= '3.7'", - "version": "==2.3.3" + "version": "==2.4.1" }, "google-cloud-storage": { "hashes": [ - "sha256:ab0bf2e1780a1b74cf17fccb13788070b729f50c252f0c94ada2aae0ca95437d", - "sha256:f62dc4c7b6cd4360d072e3deb28035fbdad491ac3d9b0b1815a12daea10f37c7" + "sha256:2d23fcf59b55e7b45336729c148bb1c464468c69d5efbaee30f7201dd90eb97e", + "sha256:8641243bbf2a2042c16a6399551fbb13f062cbc9a2de38d6c0bb5426962e9dbd" ], "markers": "python_version >= '3.7'", - "version": "==2.13.0" + "version": "==2.14.0" }, "google-crc32c": { "hashes": [ @@ -1399,82 +1407,19 @@ }, "google-resumable-media": { "hashes": [ - "sha256:972852f6c65f933e15a4a210c2b96930763b47197cdf4aa5f5bea435efb626e7", - "sha256:fc03d344381970f79eebb632a3c18bb1828593a2dc5572b5f90115ef7d11e81b" + "sha256:5f18f5fa9836f4b083162064a1c2c98c17239bfda9ca50ad970ccf905f3e625b", + "sha256:79543cfe433b63fd81c0844b7803aba1bb8950b47bedf7d980c38fa123937e08" ], "markers": "python_version >= '3.7'", - "version": "==2.6.0" + "version": "==2.7.0" }, "googleapis-common-protos": { "hashes": [ - "sha256:22f1915393bb3245343f6efe87f6fe868532efc12aa26b391b15132e1279f1c0", - "sha256:8a64866a97f6304a7179873a465d6eee97b7a24ec6cfd78e0f575e96b821240b" + "sha256:4750113612205514f9f6aa4cb00d523a94f3e8c06c5ad2fee466387dc4875f07", + "sha256:83f0ece9f94e5672cced82f592d2a5edf527a96ed1794f0bab36d5735c996277" ], "markers": "python_version >= '3.7'", - "version": "==1.61.0" - }, - "greenlet": { - "hashes": [ - "sha256:0a02d259510b3630f330c86557331a3b0e0c79dac3d166e449a39363beaae174", - "sha256:0b6f9f8ca7093fd4433472fd99b5650f8a26dcd8ba410e14094c1e44cd3ceddd", - "sha256:100f78a29707ca1525ea47388cec8a049405147719f47ebf3895e7509c6446aa", - "sha256:1757936efea16e3f03db20efd0cd50a1c86b06734f9f7338a90c4ba85ec2ad5a", - "sha256:19075157a10055759066854a973b3d1325d964d498a805bb68a1f9af4aaef8ec", - "sha256:19bbdf1cce0346ef7341705d71e2ecf6f41a35c311137f29b8a2dc2341374565", - "sha256:20107edf7c2c3644c67c12205dc60b1bb11d26b2610b276f97d666110d1b511d", - "sha256:22f79120a24aeeae2b4471c711dcf4f8c736a2bb2fabad2a67ac9a55ea72523c", - "sha256:2847e5d7beedb8d614186962c3d774d40d3374d580d2cbdab7f184580a39d234", - "sha256:28e89e232c7593d33cac35425b58950789962011cc274aa43ef8865f2e11f46d", - "sha256:329c5a2e5a0ee942f2992c5e3ff40be03e75f745f48847f118a3cfece7a28546", - "sha256:337322096d92808f76ad26061a8f5fccb22b0809bea39212cd6c406f6a7060d2", - "sha256:3fcc780ae8edbb1d050d920ab44790201f027d59fdbd21362340a85c79066a74", - "sha256:41bdeeb552d814bcd7fb52172b304898a35818107cc8778b5101423c9017b3de", - "sha256:4eddd98afc726f8aee1948858aed9e6feeb1758889dfd869072d4465973f6bfd", - "sha256:52e93b28db27ae7d208748f45d2db8a7b6a380e0d703f099c949d0f0d80b70e9", - "sha256:55d62807f1c5a1682075c62436702aaba941daa316e9161e4b6ccebbbf38bda3", - "sha256:5805e71e5b570d490938d55552f5a9e10f477c19400c38bf1d5190d760691846", - "sha256:599daf06ea59bfedbec564b1692b0166a0045f32b6f0933b0dd4df59a854caf2", - "sha256:60d5772e8195f4e9ebf74046a9121bbb90090f6550f81d8956a05387ba139353", - "sha256:696d8e7d82398e810f2b3622b24e87906763b6ebfd90e361e88eb85b0e554dc8", - "sha256:6e6061bf1e9565c29002e3c601cf68569c450be7fc3f7336671af7ddb4657166", - "sha256:80ac992f25d10aaebe1ee15df45ca0d7571d0f70b645c08ec68733fb7a020206", - "sha256:816bd9488a94cba78d93e1abb58000e8266fa9cc2aa9ccdd6eb0696acb24005b", - "sha256:85d2b77e7c9382f004b41d9c72c85537fac834fb141b0296942d52bf03fe4a3d", - "sha256:87c8ceb0cf8a5a51b8008b643844b7f4a8264a2c13fcbcd8a8316161725383fe", - "sha256:89ee2e967bd7ff85d84a2de09df10e021c9b38c7d91dead95b406ed6350c6997", - "sha256:8bef097455dea90ffe855286926ae02d8faa335ed8e4067326257cb571fc1445", - "sha256:8d11ebbd679e927593978aa44c10fc2092bc454b7d13fdc958d3e9d508aba7d0", - "sha256:91e6c7db42638dc45cf2e13c73be16bf83179f7859b07cfc139518941320be96", - "sha256:97e7ac860d64e2dcba5c5944cfc8fa9ea185cd84061c623536154d5a89237884", - "sha256:990066bff27c4fcf3b69382b86f4c99b3652bab2a7e685d968cd4d0cfc6f67c6", - "sha256:9fbc5b8f3dfe24784cee8ce0be3da2d8a79e46a276593db6868382d9c50d97b1", - "sha256:ac4a39d1abae48184d420aa8e5e63efd1b75c8444dd95daa3e03f6c6310e9619", - "sha256:b2c02d2ad98116e914d4f3155ffc905fd0c025d901ead3f6ed07385e19122c94", - "sha256:b2d3337dcfaa99698aa2377c81c9ca72fcd89c07e7eb62ece3f23a3fe89b2ce4", - "sha256:b489c36d1327868d207002391f662a1d163bdc8daf10ab2e5f6e41b9b96de3b1", - "sha256:b641161c302efbb860ae6b081f406839a8b7d5573f20a455539823802c655f63", - "sha256:b8ba29306c5de7717b5761b9ea74f9c72b9e2b834e24aa984da99cbfc70157fd", - "sha256:b9934adbd0f6e476f0ecff3c94626529f344f57b38c9a541f87098710b18af0a", - "sha256:ce85c43ae54845272f6f9cd8320d034d7a946e9773c693b27d620edec825e376", - "sha256:cf868e08690cb89360eebc73ba4be7fb461cfbc6168dd88e2fbbe6f31812cd57", - "sha256:d2905ce1df400360463c772b55d8e2518d0e488a87cdea13dd2c71dcb2a1fa16", - "sha256:d57e20ba591727da0c230ab2c3f200ac9d6d333860d85348816e1dca4cc4792e", - "sha256:d6a8c9d4f8692917a3dc7eb25a6fb337bff86909febe2f793ec1928cd97bedfc", - "sha256:d923ff276f1c1f9680d32832f8d6c040fe9306cbfb5d161b0911e9634be9ef0a", - "sha256:daa7197b43c707462f06d2c693ffdbb5991cbb8b80b5b984007de431493a319c", - "sha256:dbd4c177afb8a8d9ba348d925b0b67246147af806f0b104af4d24f144d461cd5", - "sha256:dc4d815b794fd8868c4d67602692c21bf5293a75e4b607bb92a11e821e2b859a", - "sha256:e9d21aaa84557d64209af04ff48e0ad5e28c5cca67ce43444e939579d085da72", - "sha256:ea6b8aa9e08eea388c5f7a276fabb1d4b6b9d6e4ceb12cc477c3d352001768a9", - "sha256:eabe7090db68c981fca689299c2d116400b553f4b713266b130cfc9e2aa9c5a9", - "sha256:f2f6d303f3dee132b322a14cd8765287b8f86cdc10d2cb6a6fae234ea488888e", - "sha256:f33f3258aae89da191c6ebaa3bc517c6c4cbc9b9f689e5d8452f7aedbb913fa8", - "sha256:f7bfb769f7efa0eefcd039dd19d843a4fbfbac52f1878b1da2ed5793ec9b1a65", - "sha256:f89e21afe925fcfa655965ca8ea10f24773a1791400989ff32f467badfe4a064", - "sha256:fa24255ae3c0ab67e613556375a4341af04a084bd58764731972bcbc8baeba36" - ], - "markers": "platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))", - "version": "==3.0.1" + "version": "==1.62.0" }, "gridemissions": { "git": "git+https://github.com/gailin-p/gridemissions", @@ -1649,19 +1594,19 @@ }, "hypothesis": { "hashes": [ - "sha256:316e06d6f7d5f8ab87bcc7417fca750a2b082ed3ce902b979816b413276680b3", - "sha256:a9f61a2bcfc342febcc1d04b80a99e789c57b700f91cbd43bbdb5d651af385cd" + "sha256:65b72c7dc7da3e16144db54fe093c6b74a33631b933a8063eb754c5a61361ae6", + "sha256:d4577f99b912acc725bea684899b7cb62591a0412e2446c618be0b4855995276" ], "markers": "python_version >= '3.8'", - "version": "==6.91.0" + "version": "==6.92.0" }, "identify": { "hashes": [ - "sha256:0b7656ef6cba81664b783352c73f8c24b39cf82f926f78f4550eda928e5e0545", - "sha256:5d9979348ec1a21c768ae07e0a652924538e8bce67313a73cb0f681cf08ba407" + "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d", + "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34" ], "markers": "python_version >= '3.8'", - "version": "==2.5.32" + "version": "==2.5.33" }, "idna": { "hashes": [ @@ -2055,11 +2000,11 @@ }, "jupyter-server-terminals": { "hashes": [ - "sha256:57ab779797c25a7ba68e97bcfb5d7740f2b5e8a83b5e8102b10438041a7eac5d", - "sha256:75779164661cec02a8758a5311e18bb8eb70c4e86c6b699403100f1585a12a36" + "sha256:2fc0692c883bfd891f4fba0c4b4a684a37234b0ba472f2e97ed0a3888f46e1e4", + "sha256:ebcd68c9afbf98a480a533e6f3266354336e645536953b7abcc7bdeebc0154a3" ], "markers": "python_version >= '3.8'", - "version": "==0.4.4" + "version": "==0.5.0" }, "jupyterlab": { "hashes": [ @@ -2777,38 +2722,38 @@ }, "numexpr": { "hashes": [ - "sha256:0983052f308ea75dd232eb7f4729eed839db8fe8d82289940342b32cc55b15d0", - "sha256:11121b14ee3179bade92e823f25f1b94e18716d33845db5081973331188c3338", - "sha256:32934d51b5bc8a6636436326da79ed380e2f151989968789cf65b1210572cb46", - "sha256:3a84284e0a407ca52980fd20962e89aff671c84cd6e73458f2e29ea2aa206356", - "sha256:47a249cecd1382d482a5bf1fac0d11392fb2ed0f7d415ebc4cd901959deb1ec9", - "sha256:4ecaa5be24cf8fa0f00108e9dfa1021b7510e9dd9d159b8d8bc7c7ddbb995b31", - "sha256:5340d2c86d83f52e1a3e7fd97c37d358ae99af9de316bdeeab2565b9b1e622ca", - "sha256:5496fc9e3ae214637cbca1ab556b0e602bd3afe9ff4c943a29c482430972cda8", - "sha256:56ec95f8d1db0819e64987dcf1789acd500fa4ea396eeabe4af6efdcb8902d07", - "sha256:596eeb3bbfebc912f4b6eaaf842b61ba722cebdb8bc42dfefa657d3a74953849", - "sha256:81451962d4145a46dba189df65df101d4d1caddb6efe6ebfe05982cd9f62b2cf", - "sha256:8bf005acd7f1985c71b1b247aaac8950d6ea05a0fe0bbbbf3f96cd398b136daa", - "sha256:a371cfc1670a18eea2d5c70abaa95a0e8824b70d28da884bad11931266e3a0ca", - "sha256:a4546416004ff2e7eb9cf52c2d7ab82732b1b505593193ee9f93fa770edc5230", - "sha256:b8a5b2c21c26b62875bf819d375d798b96a32644e3c28bd4ce7789ed1fb489da", - "sha256:c7bf60fc1a9c90a9cb21c4c235723e579bff70c8d5362228cb2cf34426104ba2", - "sha256:cb2f473fdfd09d17db3038e34818d05b6bc561a36785aa927d6c0e06bccc9911", - "sha256:cf5f112bce5c5966c47cc33700bc14ce745c8351d437ed57a9574fff581f341a", - "sha256:d43f1f0253a6f2db2f76214e6f7ae9611b422cba3f7d4c86415d7a78bbbd606f", - "sha256:d46c47e361fa60966a3339cb4f463ae6151ce7d78ed38075f06e8585d2c8929f", - "sha256:d88531ffea3ea9287e8a1665c6a2d0206d3f4660d5244423e2a134a7f0ce5fba", - "sha256:da55ba845b847cc33c4bf81cee4b1bddfb0831118cabff8db62888ab8697ec34", - "sha256:db1065ba663a854115cf1f493afd7206e2efcef6643129e8061e97a51ad66ebb", - "sha256:dccf572763517db6562fb7b17db46aacbbf62a9ca0a66672872f4f71aee7b186", - "sha256:e838289e3b7bbe100b99e35496e6cc4cc0541c2207078941ee5a1d46e6b925ae", - "sha256:f021ac93cb3dd5d8ba2882627b615b1f58cb089dcc85764c6fbe7a549ed21b0c", - "sha256:f29f4d08d9b0ed6fa5d32082971294b2f9131b8577c2b7c36432ed670924313f", - "sha256:f3bdf8cbc00c77a46230c765d242f92d35905c239b20c256c48dbac91e49f253", - "sha256:fd93b88d5332069916fa00829ea1b972b7e73abcb1081eee5c905a514b8b59e3" + "sha256:0d7bfc8b77d8a7b04cd64ae42b62b3bf824a8c751ca235692bfd5231c6e90127", + "sha256:12146521b1730073859a20454e75004e38cd0cb61333e763c58ef5171e101eb2", + "sha256:121b049b6909787111daf92919c052c4fd87b5691172e8f19f702b96f20aaafa", + "sha256:17104051f0bd83fd350212e268d8b48017d5eff522b09b573fdbcc560c5e7ab3", + "sha256:22ccd67c0fbeae091f2c577f5b9c8046de6631d46b1cbe22aad46a08d2b42c2d", + "sha256:290f91c7ba7772abaf7107f3cc0601d93d6a3f21c13ee3da93f1b8a9ca3e8d39", + "sha256:296dc1f79d386166dec3bdb45f51caba29ffd8dc91db15447108c04d3001d921", + "sha256:2ae264c35fa67cd510191ab8144f131fddd0f1d13413af710913ea6fc0c6aa61", + "sha256:307b49fd15ef2ca292f381e67759e5b477410341f2f499a377234f1b42f529a6", + "sha256:399cb914b41c4027ba88a18f6b8ccfc3af5c32bc3b1758403a7c44c72530618a", + "sha256:3f168b4b42d4cb120fe1993676dcf74b77a3e8e45b58855566da037cfd938ca3", + "sha256:47c05007cd1c553515492c1a78b5477eaaba9cadc5d7b795d49f7aae53ccdf68", + "sha256:4d83a542d9deefb050e389aacaddea0f09d68ec617dd37e45b9a7cfbcba6d729", + "sha256:4f01d71db6fdb97a68def5407e2dbd748eaea9d98929db08816de40aa4ae3084", + "sha256:5a92f230dd9d6c42803f855970e93677b44290b6dad15cb6796fd85edee171ce", + "sha256:6459dc6ed6abcdeab3cd3667c79f29e4a0f0a02c29ad71ee5cff065e880ee9ef", + "sha256:76f0f010f9c6318bae213b21c5c0e381c2fc9c9ecb8b35f99f5030e7ac96c9ce", + "sha256:7badc50efbb2f1c8b78cd68089031e0fd29cbafa6a9e6d730533f22d88168406", + "sha256:85c9f79e346c26aa0d425ecfc9e5de7184567d5e48d0bdb02d468bb927e92525", + "sha256:925927cd1f610593e7783d8f2e12e3d800d5928601e077e4910e2b50bde624b6", + "sha256:a82d710145b0fbaec919dde9c90ed9df1e6785625cc36d1c71f3a53112b66fc5", + "sha256:aab17d65751c039d13ed9d49c9a7517b130ef488c1885c4666af9b5c6ad59520", + "sha256:b4649c1dcf9b0c2ae0a7b767dbbbde4e05ee68480c1ba7f06fc7963f1f73acf4", + "sha256:bf8c517bbbb82c07c23c17f9d52b4c9f86601f57d48e87c0cbda24af5907f4dd", + "sha256:ccef9b09432d59229c2a737882e55de7906006452003323e107576f264cec373", + "sha256:cd07793b074cc38e478637cbe738dff7d8eb92b5cf8ffaacff0c4f0bca5270a0", + "sha256:dbac846f713b4c82333e6af0814ebea0b4e74dfb2649e76c58953fd4862322dd", + "sha256:e76ce4d25372f46170cf7eb1ff14ed5d9c69a0b162a405063cbe481bafe3af34", + "sha256:f031ac4e70f9ad867543bfbde8452e9d1a14f0525346b4b8bd4e5c0f1380a11c" ], "markers": "python_version >= '3.9'", - "version": "==2.8.7" + "version": "==2.8.8" }, "numpy": { "hashes": [ @@ -2919,43 +2864,43 @@ }, "pandas": { "hashes": [ - "sha256:0296a66200dee556850d99b24c54c7dfa53a3264b1ca6f440e42bad424caea03", - "sha256:04d4c58e1f112a74689da707be31cf689db086949c71828ef5da86727cfe3f82", - "sha256:08637041279b8981a062899da0ef47828df52a1838204d2b3761fbd3e9fcb549", - "sha256:11a771450f36cebf2a4c9dbd3a19dfa8c46c4b905a3ea09dc8e556626060fe71", - "sha256:1329dbe93a880a3d7893149979caa82d6ba64a25e471682637f846d9dbc10dd2", - "sha256:1f539e113739a3e0cc15176bf1231a553db0239bfa47a2c870283fd93ba4f683", - "sha256:22929f84bca106921917eb73c1521317ddd0a4c71b395bcf767a106e3494209f", - "sha256:321ecdb117bf0f16c339cc6d5c9a06063854f12d4d9bc422a84bb2ed3207380a", - "sha256:35172bff95f598cc5866c047f43c7f4df2c893acd8e10e6653a4b792ed7f19bb", - "sha256:3cc4469ff0cf9aa3a005870cb49ab8969942b7156e0a46cc3f5abd6b11051dfb", - "sha256:4441ac94a2a2613e3982e502ccec3bdedefe871e8cea54b8775992485c5660ef", - "sha256:465571472267a2d6e00657900afadbe6097c8e1dc43746917db4dfc862e8863e", - "sha256:59dfe0e65a2f3988e940224e2a70932edc964df79f3356e5f2997c7d63e758b4", - "sha256:72c84ec1b1d8e5efcbff5312abe92bfb9d5b558f11e0cf077f5496c4f4a3c99e", - "sha256:7cf4cf26042476e39394f1f86868d25b265ff787c9b2f0d367280f11afbdee6d", - "sha256:7fa2ad4ff196768ae63a33f8062e6838efed3a319cf938fdf8b95e956c813042", - "sha256:a5d53c725832e5f1645e7674989f4c106e4b7249c1d57549023ed5462d73b140", - "sha256:acf08a73b5022b479c1be155d4988b72f3020f308f7a87c527702c5f8966d34f", - "sha256:b99c4e51ef2ed98f69099c72c75ec904dd610eb41a32847c4fcbc1a975f2d2b8", - "sha256:d5ded6ff28abbf0ea7689f251754d3789e1edb0c4d0d91028f0b980598418a58", - "sha256:de21e12bf1511190fc1e9ebc067f14ca09fccfb189a813b38d63211d54832f5f", - "sha256:f7ea8ae8004de0381a2376662c0505bb0a4f679f4c61fbfd122aa3d1b0e5f09d", - "sha256:fc77309da3b55732059e484a1efc0897f6149183c522390772d3561f9bf96c00", - "sha256:fca5680368a5139d4920ae3dc993eb5106d49f814ff24018b64d8850a52c6ed2", - "sha256:fcd76d67ca2d48f56e2db45833cf9d58f548f97f61eecd3fdc74268417632b8a" + "sha256:00028e6737c594feac3c2df15636d73ace46b8314d236100b57ed7e4b9ebe8d9", + "sha256:0aa6e92e639da0d6e2017d9ccff563222f4eb31e4b2c3cf32a2a392fc3103c0d", + "sha256:1ebfd771110b50055712b3b711b51bee5d50135429364d0498e1213a7adc2be8", + "sha256:294d96cfaf28d688f30c918a765ea2ae2e0e71d3536754f4b6de0ea4a496d034", + "sha256:3f06bda01a143020bad20f7a85dd5f4a1600112145f126bc9e3e42077c24ef34", + "sha256:426dc0f1b187523c4db06f96fb5c8d1a845e259c99bda74f7de97bd8a3bb3139", + "sha256:45d63d2a9b1b37fa6c84a68ba2422dc9ed018bdaa668c7f47566a01188ceeec1", + "sha256:482d5076e1791777e1571f2e2d789e940dedd927325cc3cb6d0800c6304082f6", + "sha256:6b728fb8deba8905b319f96447a27033969f3ea1fea09d07d296c9030ab2ed1d", + "sha256:8a706cfe7955c4ca59af8c7a0517370eafbd98593155b48f10f9811da440248b", + "sha256:8ea107e0be2aba1da619cc6ba3f999b2bfc9669a83554b1904ce3dd9507f0860", + "sha256:ab5796839eb1fd62a39eec2916d3e979ec3130509930fea17fe6f81e18108f6a", + "sha256:b0513a132a15977b4a5b89aabd304647919bc2169eac4c8536afb29c07c23540", + "sha256:b7d852d16c270e4331f6f59b3e9aa23f935f5c4b0ed2d0bc77637a8890a5d092", + "sha256:bd7d5f2f54f78164b3d7a40f33bf79a74cdee72c31affec86bfcabe7e0789821", + "sha256:bdec823dc6ec53f7a6339a0e34c68b144a7a1fd28d80c260534c39c62c5bf8c9", + "sha256:d2d3e7b00f703aea3945995ee63375c61b2e6aa5aa7871c5d622870e5e137623", + "sha256:d65148b14788b3758daf57bf42725caa536575da2b64df9964c563b015230984", + "sha256:d797591b6846b9db79e65dc2d0d48e61f7db8d10b2a9480b4e3faaddc421a171", + "sha256:dc9bf7ade01143cddc0074aa6995edd05323974e6e40d9dbde081021ded8510e", + "sha256:e9f17f2b6fc076b2a0078862547595d66244db0f41bf79fc5f64a5c4d635bead", + "sha256:edbaf9e8d3a63a9276d707b4d25930a262341bca9874fcb22eff5e3da5394732", + "sha256:f237e6ca6421265643608813ce9793610ad09b40154a3344a088159590469e46", + "sha256:f69b0c9bb174a2342818d3e2778584e18c740d56857fc5cdb944ec8bbe4082cf", + "sha256:fcb68203c833cc735321512e13861358079a96c174a61f5116a1de89c58c0ef7" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==2.1.3" + "version": "==2.1.4" }, "pandera": { "hashes": [ - "sha256:67515984f855ba14d12443f893b5ff90ae6796f613d5f3df43abad406a48c373", - "sha256:8e4e7b279c62f6d4b5109801544bf8d46e1c9fdf7ceceb8fedd5f3dad0c1bea1" + "sha256:97ab33d884362c0bb99668a12be2855d15c1a71f4934c588a999947b47764bc1", + "sha256:fe2da835a16df5a7e49fbfb828f1eeaea9d6f4534f124630957e64fef53e7e73" ], "markers": "python_version >= '3.7'", - "version": "==0.17.2" + "version": "==0.18.0" }, "pandocfilters": { "hashes": [ @@ -3038,6 +2983,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.7.14" }, + "pexpect": { + "hashes": [ + "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", + "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f" + ], + "markers": "sys_platform != 'win32'", + "version": "==4.9.0" + }, "pillow": { "hashes": [ "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d", @@ -3100,11 +3053,11 @@ }, "pint": { "hashes": [ - "sha256:2d139f6abbcf3016cad7d3cec05707fe908ac4f99cf59aedfd6ee667b7a64433", - "sha256:6e2b3c5c2b4d9b516608bc860a417a39d66eb99c958f36540cf931d2c2e9f80f" + "sha256:df79b6b5f1beb7ed0cd55d91a0766fc55f972f757a9364e844958c05e8eb66f9", + "sha256:e1509b91606dbc52527c600a4ef74ffac12fff70688aff20e9072409346ec9b4" ], "markers": "python_version >= '3.9'", - "version": "==0.22" + "version": "==0.23" }, "pip": { "hashes": [ @@ -3149,11 +3102,11 @@ }, "pre-commit": { "hashes": [ - "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32", - "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660" + "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376", + "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d" ], - "markers": "python_version >= '3.8'", - "version": "==3.5.0" + "markers": "python_version >= '3.9'", + "version": "==3.6.0" }, "prometheus-client": { "hashes": [ @@ -3165,11 +3118,11 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0", - "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2" + "sha256:3527b7af26106cbc65a040bcc84839a3566ec1b051bb0bfe953631e704b0ff7d", + "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6" ], "markers": "python_full_version >= '3.7.0'", - "version": "==3.0.41" + "version": "==3.0.43" }, "protobuf": { "hashes": [ @@ -3288,6 +3241,13 @@ "markers": "python_version >= '3.7'", "version": "==2.9.9" }, + "ptyprocess": { + "hashes": [ + "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", + "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" + ], + "version": "==0.7.0" + }, "pure-eval": { "hashes": [ "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", @@ -3579,14 +3539,6 @@ "markers": "python_version >= '3.7'", "version": "==1.0.0" }, - "pyreadline3": { - "hashes": [ - "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae", - "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb" - ], - "markers": "python_version >= '3.8' and sys_platform == 'win32'", - "version": "==3.4.1" - }, "pytest": { "hashes": [ "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac", @@ -3682,46 +3634,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2020.1" }, - "pywin32": { - "hashes": [ - "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d", - "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65", - "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e", - "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b", - "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4", - "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040", - "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a", - "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36", - "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8", - "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e", - "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802", - "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a", - "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407", - "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0" - ], - "markers": "platform_system == 'Windows'", - "version": "==306" - }, - "pywin32-ctypes": { - "hashes": [ - "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60", - "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7" - ], - "markers": "sys_platform == 'win32'", - "version": "==0.2.2" - }, - "pywinpty": { - "hashes": [ - "sha256:1617b729999eb6713590e17665052b1a6ae0ad76ee31e60b444147c5b6a35dca", - "sha256:189380469ca143d06e19e19ff3fba0fcefe8b4a8cc942140a6b863aed7eebb2d", - "sha256:21319cd1d7c8844fb2c970fb3a55a3db5543f112ff9cfcd623746b9c47501575", - "sha256:7520575b6546db23e693cbd865db2764097bd6d4ef5dc18c92555904cd62c3d4", - "sha256:8197de460ae8ebb7f5d1701dfa1b5df45b157bb832e92acba316305e18ca00dd", - "sha256:853985a8f48f4731a716653170cd735da36ffbdc79dcb4c7b7140bce11d8c722" - ], - "markers": "os_name == 'nt'", - "version": "==2.0.12" - }, "pyxlsb": { "hashes": [ "sha256:8062d1ea8626d3f1980e8b1cfe91a4483747449242ecb61013bc2df85435f685", @@ -3927,10 +3839,10 @@ }, "readthedocs-sphinx-ext": { "hashes": [ - "sha256:6583c26791a5853ee9e57ce9db864e2fb06808ba470f805d74d53fc50811e012", - "sha256:e9d911792789b88ae12e2be94d88c619f89a4fa1fe9e42c1505c9930a07163d8" + "sha256:77b5b12e9fa6bb7ab623e7be5bfbd7523c83a2ea72c48f6f6f4d5e3df87ac896", + "sha256:e99ed77d7618b2990d12953ba03722d1f354f7dd0f4097702383d40d2288ce3c" ], - "version": "==2.2.3" + "version": "==2.2.4" }, "recordlinkage": { "hashes": [ @@ -3942,11 +3854,11 @@ }, "referencing": { "hashes": [ - "sha256:81a1471c68c9d5e3831c30ad1dd9815c45b558e596653db751a2bfdd17b3b9ec", - "sha256:c19c4d006f1757e3dd75c4f784d38f8698d87b649c54f9ace14e5e8c9667c01d" + "sha256:689e64fe121843dcfd57b71933318ef1f91188ffb45367332700a86ac8fd6161", + "sha256:bdcd3efb936f82ff86f993093f6da7435c7de69a3b3a5a06678a6050184bee99" ], "markers": "python_version >= '3.8'", - "version": "==0.31.1" + "version": "==0.32.0" }, "regex": { "hashes": [ @@ -4283,34 +4195,34 @@ }, "ruff": { "hashes": [ - "sha256:0683b7bfbb95e6df3c7c04fe9d78f631f8e8ba4868dfc932d43d690698057e2e", - "sha256:1ea109bdb23c2a4413f397ebd8ac32cb498bee234d4191ae1a310af760e5d287", - "sha256:276a89bcb149b3d8c1b11d91aa81898fe698900ed553a08129b38d9d6570e717", - "sha256:290ecab680dce94affebefe0bbca2322a6277e83d4f29234627e0f8f6b4fa9ce", - "sha256:416dfd0bd45d1a2baa3b1b07b1b9758e7d993c256d3e51dc6e03a5e7901c7d80", - "sha256:45b38c3f8788a65e6a2cab02e0f7adfa88872696839d9882c13b7e2f35d64c5f", - "sha256:4af95fd1d3b001fc41325064336db36e3d27d2004cdb6d21fd617d45a172dd96", - "sha256:69a4bed13bc1d5dabf3902522b5a2aadfebe28226c6269694283c3b0cecb45fd", - "sha256:6b05e3b123f93bb4146a761b7a7d57af8cb7384ccb2502d29d736eaade0db519", - "sha256:6c64cb67b2025b1ac6d58e5ffca8f7b3f7fd921f35e78198411237e4f0db8e73", - "sha256:7f80496854fdc65b6659c271d2c26e90d4d401e6a4a31908e7e334fab4645aac", - "sha256:8b0c2de9dd9daf5e07624c24add25c3a490dbf74b0e9bca4145c632457b3b42a", - "sha256:90c958fe950735041f1c80d21b42184f1072cc3975d05e736e8d66fc377119ea", - "sha256:9dcc6bb2f4df59cb5b4b40ff14be7d57012179d69c6565c1da0d1f013d29951b", - "sha256:de02ca331f2143195a712983a57137c5ec0f10acc4aa81f7c1f86519e52b92a1", - "sha256:df2bb4bb6bbe921f6b4f5b6fdd8d8468c940731cb9406f274ae8c5ed7a78c478", - "sha256:dffd699d07abf54833e5f6cc50b85a6ff043715da8788c4a79bcd4ab4734d306" + "sha256:05ffe9dbd278965271252704eddb97b4384bf58b971054d517decfbf8c523f05", + "sha256:5daaeaf00ae3c1efec9742ff294b06c3a2a9db8d3db51ee4851c12ad385cda30", + "sha256:7d076717c67b34c162da7c1a5bda16ffc205e0e0072c03745275e7eab888719f", + "sha256:7de792582f6e490ae6aef36a58d85df9f7a0cfd1b0d4fe6b4fb51803a3ac96fa", + "sha256:a05b0ddd7ea25495e4115a43125e8a7ebed0aa043c3d432de7e7d6e8e8cd6448", + "sha256:aa8ee4f8440023b0a6c3707f76cadce8657553655dcbb5fc9b2f9bb9bee389f6", + "sha256:b6a21ab023124eafb7cef6d038f835cb1155cd5ea798edd8d9eb2f8b84be07d9", + "sha256:bd8ee69b02e7bdefe1e5da2d5b6eaaddcf4f90859f00281b2333c0e3a0cc9cd6", + "sha256:c8e3255afd186c142eef4ec400d7826134f028a85da2146102a1172ecc7c3696", + "sha256:ce697c463458555027dfb194cb96d26608abab920fa85213deb5edf26e026664", + "sha256:db6cedd9ffed55548ab313ad718bc34582d394e27a7875b4b952c2d29c001b26", + "sha256:e49fbdfe257fa41e5c9e13c79b9e79a23a79bd0e40b9314bc53840f520c2c0b3", + "sha256:e6f08ca730f4dc1b76b473bdf30b1b37d42da379202a059eae54ec7fc1fbcfed", + "sha256:f35960b02df6b827c1b903091bb14f4b003f6cf102705efc4ce78132a0aa5af3", + "sha256:f41f692f1691ad87f51708b823af4bb2c5c87c9248ddd3191c8f088e66ce590a", + "sha256:f7ee467677467526cfe135eab86a40a0e8db43117936ac4f9b469ce9cdb3fb62", + "sha256:ff78a7583020da124dd0deb835ece1d87bb91762d40c514ee9b67a087940528b" ], "markers": "python_version >= '3.7'", - "version": "==0.1.7" + "version": "==0.1.8" }, "s3transfer": { "hashes": [ - "sha256:368ac6876a9e9ed91f6bc86581e319be08188dc60d50e0d56308ed5765446283", - "sha256:c9e56cbe88b28d8e197cf841f1f0c130f246595e77ae5b5a05b69fe7cb83de76" + "sha256:01d4d2c35a016db8cb14f9a4d5e84c1f8c96e7ffc211422555eed45c11fa7eb1", + "sha256:9e1b186ec8bb5907a1e82b51237091889a9973a2bb799a924bcd9f301ff79d3d" ], - "markers": "python_version >= '3.7'", - "version": "==0.8.2" + "markers": "python_version >= '3.8'", + "version": "==0.9.0" }, "scikit-learn": { "hashes": [ @@ -4903,11 +4815,11 @@ }, "typing-extensions": { "hashes": [ - "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0", - "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef" + "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783", + "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" ], "markers": "python_version >= '3.8'", - "version": "==4.8.0" + "version": "==4.9.0" }, "typing-inspect": { "hashes": [ @@ -5245,14 +5157,6 @@ } }, "develop": { - "colorama": { - "hashes": [ - "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", - "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" - ], - "markers": "os_name == 'nt'", - "version": "==0.4.6" - }, "iniconfig": { "hashes": [ "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", @@ -5287,26 +5191,26 @@ }, "ruff": { "hashes": [ - "sha256:0683b7bfbb95e6df3c7c04fe9d78f631f8e8ba4868dfc932d43d690698057e2e", - "sha256:1ea109bdb23c2a4413f397ebd8ac32cb498bee234d4191ae1a310af760e5d287", - "sha256:276a89bcb149b3d8c1b11d91aa81898fe698900ed553a08129b38d9d6570e717", - "sha256:290ecab680dce94affebefe0bbca2322a6277e83d4f29234627e0f8f6b4fa9ce", - "sha256:416dfd0bd45d1a2baa3b1b07b1b9758e7d993c256d3e51dc6e03a5e7901c7d80", - "sha256:45b38c3f8788a65e6a2cab02e0f7adfa88872696839d9882c13b7e2f35d64c5f", - "sha256:4af95fd1d3b001fc41325064336db36e3d27d2004cdb6d21fd617d45a172dd96", - "sha256:69a4bed13bc1d5dabf3902522b5a2aadfebe28226c6269694283c3b0cecb45fd", - "sha256:6b05e3b123f93bb4146a761b7a7d57af8cb7384ccb2502d29d736eaade0db519", - "sha256:6c64cb67b2025b1ac6d58e5ffca8f7b3f7fd921f35e78198411237e4f0db8e73", - "sha256:7f80496854fdc65b6659c271d2c26e90d4d401e6a4a31908e7e334fab4645aac", - "sha256:8b0c2de9dd9daf5e07624c24add25c3a490dbf74b0e9bca4145c632457b3b42a", - "sha256:90c958fe950735041f1c80d21b42184f1072cc3975d05e736e8d66fc377119ea", - "sha256:9dcc6bb2f4df59cb5b4b40ff14be7d57012179d69c6565c1da0d1f013d29951b", - "sha256:de02ca331f2143195a712983a57137c5ec0f10acc4aa81f7c1f86519e52b92a1", - "sha256:df2bb4bb6bbe921f6b4f5b6fdd8d8468c940731cb9406f274ae8c5ed7a78c478", - "sha256:dffd699d07abf54833e5f6cc50b85a6ff043715da8788c4a79bcd4ab4734d306" + "sha256:05ffe9dbd278965271252704eddb97b4384bf58b971054d517decfbf8c523f05", + "sha256:5daaeaf00ae3c1efec9742ff294b06c3a2a9db8d3db51ee4851c12ad385cda30", + "sha256:7d076717c67b34c162da7c1a5bda16ffc205e0e0072c03745275e7eab888719f", + "sha256:7de792582f6e490ae6aef36a58d85df9f7a0cfd1b0d4fe6b4fb51803a3ac96fa", + "sha256:a05b0ddd7ea25495e4115a43125e8a7ebed0aa043c3d432de7e7d6e8e8cd6448", + "sha256:aa8ee4f8440023b0a6c3707f76cadce8657553655dcbb5fc9b2f9bb9bee389f6", + "sha256:b6a21ab023124eafb7cef6d038f835cb1155cd5ea798edd8d9eb2f8b84be07d9", + "sha256:bd8ee69b02e7bdefe1e5da2d5b6eaaddcf4f90859f00281b2333c0e3a0cc9cd6", + "sha256:c8e3255afd186c142eef4ec400d7826134f028a85da2146102a1172ecc7c3696", + "sha256:ce697c463458555027dfb194cb96d26608abab920fa85213deb5edf26e026664", + "sha256:db6cedd9ffed55548ab313ad718bc34582d394e27a7875b4b952c2d29c001b26", + "sha256:e49fbdfe257fa41e5c9e13c79b9e79a23a79bd0e40b9314bc53840f520c2c0b3", + "sha256:e6f08ca730f4dc1b76b473bdf30b1b37d42da379202a059eae54ec7fc1fbcfed", + "sha256:f35960b02df6b827c1b903091bb14f4b003f6cf102705efc4ce78132a0aa5af3", + "sha256:f41f692f1691ad87f51708b823af4bb2c5c87c9248ddd3191c8f088e66ce590a", + "sha256:f7ee467677467526cfe135eab86a40a0e8db43117936ac4f9b469ce9cdb3fb62", + "sha256:ff78a7583020da124dd0deb835ece1d87bb91762d40c514ee9b67a087940528b" ], "markers": "python_version >= '3.7'", - "version": "==0.1.7" + "version": "==0.1.8" } } } From 991e8e648d60e55b0ea18f7d2ec994b5a9083b10 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Wed, 13 Dec 2023 23:45:14 -0800 Subject: [PATCH 54/85] chore: avoid circular import --- src/oge/load_data.py | 6 ++++-- src/oge/validation.py | 26 +++++++++++++++++--------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/oge/load_data.py b/src/oge/load_data.py index 9d9f9846..eb9cffc1 100644 --- a/src/oge/load_data.py +++ b/src/oge/load_data.py @@ -6,7 +6,7 @@ from oge.column_checks import get_dtypes from oge.filepaths import downloads_folder, manual_folder, outputs_folder -from oge.validation import validate_unique_datetimes +import oge.validation as validation from oge.logging_util import get_logger from pudl.metadata.fields import apply_pudl_dtypes @@ -105,7 +105,9 @@ def load_cems_data(year): } ) - validate_unique_datetimes(cems, "cems", ["plant_id_eia", "emissions_unit_id_epa"]) + validation.validate_unique_datetimes( + cems, "cems", ["plant_id_eia", "emissions_unit_id_epa"] + ) return cems diff --git a/src/oge/validation.py b/src/oge/validation.py index fbd46aea..3ea79c84 100644 --- a/src/oge/validation.py +++ b/src/oge/validation.py @@ -3,7 +3,7 @@ import oge.load_data as load_data import oge.impute_hourly_profiles as impute_hourly_profiles -from oge.emissions import CLEAN_FUELS +import oge.emissions as emissions from oge.column_checks import get_dtypes from oge.filepaths import downloads_folder, manual_folder from oge.logging_util import get_logger @@ -975,22 +975,30 @@ def identify_percent_of_data_by_input_source( # use the generator-specific energy source code for the eia data, otherwise use the pliant primary fuel eia_only_data = eia_only_data.assign( emitting_net_generation_mwh=lambda x: np.where( - ~x.energy_source_code.isin(CLEAN_FUELS + ["GEO"]), x.net_generation_mwh, 0 + ~x.energy_source_code.isin(emissions.CLEAN_FUELS + ["GEO"]), + x.net_generation_mwh, + 0, ) ) cems = cems.assign( emitting_net_generation_mwh=lambda x: np.where( - ~x.plant_primary_fuel.isin(CLEAN_FUELS + ["GEO"]), x.net_generation_mwh, 0 + ~x.plant_primary_fuel.isin(emissions.CLEAN_FUELS + ["GEO"]), + x.net_generation_mwh, + 0, ) ) partial_cems_subplant = partial_cems_subplant.assign( emitting_net_generation_mwh=lambda x: np.where( - ~x.plant_primary_fuel.isin(CLEAN_FUELS + ["GEO"]), x.net_generation_mwh, 0 + ~x.plant_primary_fuel.isin(emissions.CLEAN_FUELS + ["GEO"]), + x.net_generation_mwh, + 0, ) ) partial_cems_plant = partial_cems_plant.assign( emitting_net_generation_mwh=lambda x: np.where( - ~x.plant_primary_fuel.isin(CLEAN_FUELS + ["GEO"]), x.net_generation_mwh, 0 + ~x.plant_primary_fuel.isin(emissions.CLEAN_FUELS + ["GEO"]), + x.net_generation_mwh, + 0, ) ) @@ -1786,16 +1794,16 @@ def load_egrid_plant_file(year): # if egrid has a missing value for co2 for a clean plant, replace with zero egrid_plant.loc[ - egrid_plant["plant_primary_fuel"].isin(CLEAN_FUELS), + egrid_plant["plant_primary_fuel"].isin(emissions.CLEAN_FUELS), "co2_mass_lb_for_electricity_adjusted", ] = egrid_plant.loc[ - egrid_plant["plant_primary_fuel"].isin(CLEAN_FUELS), + egrid_plant["plant_primary_fuel"].isin(emissions.CLEAN_FUELS), "co2_mass_lb_for_electricity_adjusted", ].fillna(0) egrid_plant.loc[ - egrid_plant["plant_primary_fuel"].isin(CLEAN_FUELS), "co2_mass_lb" + egrid_plant["plant_primary_fuel"].isin(emissions.CLEAN_FUELS), "co2_mass_lb" ] = egrid_plant.loc[ - egrid_plant["plant_primary_fuel"].isin(CLEAN_FUELS), "co2_mass_lb" + egrid_plant["plant_primary_fuel"].isin(emissions.CLEAN_FUELS), "co2_mass_lb" ].fillna(0) # reorder the columns From 86a01ac2bd4badcbf657d370a247e25cad4ce8c5 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Wed, 13 Dec 2023 23:45:48 -0800 Subject: [PATCH 55/85] chore: update import statements in notebooks --- .../explore_data/compare_data_sources.ipynb | 8 ++-- .../explore_annually_reported_eia_data.ipynb | 12 +++--- .../explore_intermediate_outputs.ipynb | 12 +++--- notebooks/explore_data/gens_not_in_cems.ipynb | 22 +++++------ ...import_uncontrolled_emission_factors.ipynb | 12 +++--- .../calculate_residual_net_generation.ipynb | 15 ++++---- .../national_wind_solar_correlations.ipynb | 10 ++--- .../default_fuel_sulfur_content.ipynb | 9 +++-- .../export_fuel_heat_content.ipynb | 10 ++--- .../identify_eia930_time_lags.ipynb | 30 +++++++-------- .../manually_update_OTH_fuel_code.ipynb | 10 ++--- .../update_utility_name_ba_map.ipynb | 12 +++--- notebooks/manual_data/zip_data.ipynb | 8 ++-- notebooks/validation/data_validation.ipynb | 14 +++---- .../validation/diff_output_versions.ipynb | 12 +++--- notebooks/validation/hourly_validation.ipynb | 6 +-- .../validation/validate_data_cleaning.ipynb | 10 ++--- .../validation/validate_hourly_profiles.ipynb | 22 ++++++----- .../validate_negative_profiles.ipynb | 16 ++++---- notebooks/validation/validate_vs_egrid.ipynb | 14 +++---- .../visualization/map_visualization.ipynb | 8 ++-- .../visualization/plot_timeseries_data.ipynb | 12 +++--- .../work_in_progress/GH102_test_dask.ipynb | 24 +++++++----- .../GH153_fill_missing_nox_so2_cems.ipynb | 18 +++++---- .../GH240_eia930_physics_reconciliation.ipynb | 28 +++++++------- .../clean_cems_outliers.ipynb | 12 +++--- .../work_in_progress/issue230_spikes.ipynb | 10 ++--- notebooks/work_in_progress/sandbox.ipynb | 37 +++++++++++-------- .../uncertainty_analysis.ipynb | 12 +++--- 29 files changed, 221 insertions(+), 204 deletions(-) diff --git a/notebooks/explore_data/compare_data_sources.ipynb b/notebooks/explore_data/compare_data_sources.ipynb index 41ee76c2..dd2c4cc9 100644 --- a/notebooks/explore_data/compare_data_sources.ipynb +++ b/notebooks/explore_data/compare_data_sources.ipynb @@ -11,7 +11,7 @@ "# Depending on how your jupyter handles working directories, this may not be needed.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/\")" + "sys.path.append(\"../../src\")" ] }, { @@ -47,7 +47,7 @@ "%reload_ext autoreload\n", "%autoreload 2\n", "\n", - "import src.data_cleaning as data_cleaning" + "import oge.data_cleaning as data_cleaning" ] }, { @@ -914,7 +914,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.10.5 ('hourly_egrid')", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -928,7 +928,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" }, "vscode": { "interpreter": { diff --git a/notebooks/explore_data/explore_annually_reported_eia_data.ipynb b/notebooks/explore_data/explore_annually_reported_eia_data.ipynb index b2b32a2c..9655b664 100644 --- a/notebooks/explore_data/explore_annually_reported_eia_data.ipynb +++ b/notebooks/explore_data/explore_annually_reported_eia_data.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -15,11 +15,11 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", - "from column_checks import get_dtypes\n", - "import load_data\n", - "from filepaths import *\n", + "from oge.column_checks import get_dtypes\n", + "import oge.load_data as load_data\n", + "from oge.filepaths import *\n", "\n", "year = 2020\n", "path_prefix = f\"{year}/\"" @@ -224,7 +224,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/explore_data/explore_intermediate_outputs.ipynb b/notebooks/explore_data/explore_intermediate_outputs.ipynb index ac41bb30..e5960b46 100644 --- a/notebooks/explore_data/explore_intermediate_outputs.ipynb +++ b/notebooks/explore_data/explore_intermediate_outputs.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -15,11 +15,11 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", - "from column_checks import get_dtypes\n", - "from filepaths import *\n", - "import data_cleaning\n", + "from oge.column_checks import get_dtypes\n", + "from oge.filepaths import *\n", + "import oge.data_cleaning as data_cleaning\n", "\n", "year = 2020" ] @@ -198,7 +198,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/explore_data/gens_not_in_cems.ipynb b/notebooks/explore_data/gens_not_in_cems.ipynb index 8b08bac8..578abb11 100644 --- a/notebooks/explore_data/gens_not_in_cems.ipynb +++ b/notebooks/explore_data/gens_not_in_cems.ipynb @@ -20,17 +20,17 @@ "\n", "sys.path.append(\"../../../open-grid-emissions/src/\")\n", "\n", - "import download_data\n", - "import load_data\n", - "from column_checks import get_dtypes\n", - "from filepaths import *\n", - "import impute_hourly_profiles\n", - "import data_cleaning\n", - "import output_data\n", - "import emissions\n", - "import validation\n", - "import gross_to_net_generation\n", - "import eia930\n", + "import oge.download_data as download_data\n", + "import oge.load_data as load_data\n", + "from oge.column_checks import get_dtypes\n", + "from oge.filepaths import *\n", + "import oge.impute_hourly_profiles as impute_hourly_profiles\n", + "import oge.data_cleaning as data_cleaning\n", + "import oge.output_data as output_data\n", + "import oge.emissions as emissions\n", + "import oge.validation as validation\n", + "import oge.gross_to_net_generation as gross_to_net_generation\n", + "import oge.eia930 as eia930\n", "\n", "year = 2020\n", "path_prefix = f\"{year}/\"" diff --git a/notebooks/explore_data/manually_import_uncontrolled_emission_factors.ipynb b/notebooks/explore_data/manually_import_uncontrolled_emission_factors.ipynb index c288b336..f7a4229e 100644 --- a/notebooks/explore_data/manually_import_uncontrolled_emission_factors.ipynb +++ b/notebooks/explore_data/manually_import_uncontrolled_emission_factors.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "b0de1a57", "metadata": {}, "outputs": [], @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "fcd771a8", "metadata": {}, "outputs": [], @@ -23,9 +23,9 @@ "# NOTE(milo): Need to add 'src' to the path to fix import errors.\n", "sys.path.append(\"../../src\")\n", "\n", - "import src.data_cleaning as data_cleaning\n", - "import src.load_data as load_data\n", - "import src.filepaths as filepaths" + "import oge.data_cleaning as data_cleaning\n", + "import oge.load_data as load_data\n", + "import oge.filepaths as filepaths" ] }, { @@ -283,7 +283,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.4" + "version": "3.11.2" }, "vscode": { "interpreter": { diff --git a/notebooks/explore_methods/calculate_residual_net_generation.ipynb b/notebooks/explore_methods/calculate_residual_net_generation.ipynb index f0373380..cbc202d9 100644 --- a/notebooks/explore_methods/calculate_residual_net_generation.ipynb +++ b/notebooks/explore_methods/calculate_residual_net_generation.ipynb @@ -44,18 +44,17 @@ "# Depending on how your jupyter handles working directories, this may not be needed.\n", "import sys\n", "\n", - "sys.path.append(\"../../open-grid-emissions/\")\n", + "sys.path.append(\"../../src\")\n", "\n", - "from src.visualization import day_hour_heatmap\n", - "from src.eia930 import (\n", - " fuel_code_map,\n", + "from oge.visualization import day_hour_heatmap\n", + "from oge.eia930 import (\n", " reformat_chalendar,\n", " load_chalendar,\n", " load_chalendar_for_pipeline,\n", ")\n", - "from src.download_data import download_chalendar_files\n", - "from src.data_cleaning import distribute_monthly_eia_data_to_hourly\n", - "from src.impute_hourly_profiles import aggregate_for_residual, calculate_residual" + "from oge.download_data import download_chalendar_files\n", + "from oge.data_cleaning import distribute_monthly_eia_data_to_hourly\n", + "from oge.impute_hourly_profiles import aggregate_for_residual, calculate_residual" ] }, { @@ -827,7 +826,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/explore_methods/national_wind_solar_correlations.ipynb b/notebooks/explore_methods/national_wind_solar_correlations.ipynb index 99b4ff37..0c61c8eb 100644 --- a/notebooks/explore_methods/national_wind_solar_correlations.ipynb +++ b/notebooks/explore_methods/national_wind_solar_correlations.ipynb @@ -15,7 +15,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -28,12 +28,12 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", "\n", - "import eia930\n", + "import oge.eia930 as eia930\n", "\n", - "from filepaths import *\n", + "from oge.filepaths import *\n", "\n", "year = 2020\n", "path_prefix = f\"{year}/\"" @@ -124,7 +124,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/manual_data/default_fuel_sulfur_content.ipynb b/notebooks/manual_data/default_fuel_sulfur_content.ipynb index 48779e24..f7b40abe 100644 --- a/notebooks/manual_data/default_fuel_sulfur_content.ipynb +++ b/notebooks/manual_data/default_fuel_sulfur_content.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -20,8 +20,9 @@ "import plotly.express as px\n", "\n", "sys.path.append(\"../../src\")\n", - "import emissions\n", - "import load_data" + "\n", + "import oge.emissions as emissions\n", + "import oge.load_data as load_data" ] }, { @@ -70,7 +71,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/manual_data/export_fuel_heat_content.ipynb b/notebooks/manual_data/export_fuel_heat_content.ipynb index 6a01315e..c7c2a8d0 100644 --- a/notebooks/manual_data/export_fuel_heat_content.ipynb +++ b/notebooks/manual_data/export_fuel_heat_content.ipynb @@ -16,11 +16,11 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", - "import load_data\n", - "from filepaths import *\n", - "import emissions" + "import oge.load_data as load_data\n", + "from oge.filepaths import *\n", + "import oge.emissions as emissions" ] }, { @@ -78,7 +78,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/manual_data/identify_eia930_time_lags.ipynb b/notebooks/manual_data/identify_eia930_time_lags.ipynb index 04d54e5b..37c43fdd 100644 --- a/notebooks/manual_data/identify_eia930_time_lags.ipynb +++ b/notebooks/manual_data/identify_eia930_time_lags.ipynb @@ -33,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -58,19 +58,19 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", - "import download_data\n", - "import load_data\n", - "from column_checks import get_dtypes\n", - "from filepaths import *\n", - "import impute_hourly_profiles\n", - "import data_cleaning\n", - "import output_data\n", - "import emissions\n", - "import validation\n", - "import gross_to_net_generation\n", - "import eia930" + "import oge.download_data as download_data\n", + "import oge.load_data as load_data\n", + "from oge.column_checks import get_dtypes\n", + "from oge.filepaths import *\n", + "import oge.impute_hourly_profiles as impute_hourly_profiles\n", + "import oge.data_cleaning as data_cleaning\n", + "import oge.output_data as output_data\n", + "import oge.emissions as emissions\n", + "import oge.validation as validation\n", + "import oge.gross_to_net_generation as gross_to_net_generation\n", + "import oge.eia930 as eia930" ] }, { @@ -857,7 +857,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb b/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb index af7ec875..4d3e62c0 100644 --- a/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb +++ b/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -16,10 +16,10 @@ "\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", - "import load_data\n", - "import data_cleaning" + "import oge.load_data as load_data\n", + "import oge.data_cleaning as data_cleaning" ] }, { @@ -115,7 +115,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8 | packaged by conda-forge | (main, Nov 24 2022, 14:07:00) [MSC v.1916 64 bit (AMD64)]" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/manual_data/update_utility_name_ba_map.ipynb b/notebooks/manual_data/update_utility_name_ba_map.ipynb index ccc4a527..736e07ac 100644 --- a/notebooks/manual_data/update_utility_name_ba_map.ipynb +++ b/notebooks/manual_data/update_utility_name_ba_map.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -18,11 +18,11 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", - "import load_data\n", - "from column_checks import get_dtypes\n", - "from filepaths import *\n", + "import oge.load_data as load_data\n", + "from oge.column_checks import get_dtypes\n", + "from oge.filepaths import *\n", "\n", "\n", "year = 2021\n", @@ -137,7 +137,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/manual_data/zip_data.ipynb b/notebooks/manual_data/zip_data.ipynb index 1660e436..8e7413c9 100644 --- a/notebooks/manual_data/zip_data.ipynb +++ b/notebooks/manual_data/zip_data.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -19,9 +19,9 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", - "import output_data" + "import oge.output_data as output_data" ] }, { @@ -72,7 +72,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/validation/data_validation.ipynb b/notebooks/validation/data_validation.ipynb index 60cecf2e..03520d14 100644 --- a/notebooks/validation/data_validation.ipynb +++ b/notebooks/validation/data_validation.ipynb @@ -15,7 +15,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -25,14 +25,14 @@ "# Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", "# import local modules\n", - "import load_data\n", - "from data_cleaning import assign_ba_code_to_plant\n", - "import validation\n", + "import oge.load_data as load_data\n", + "from oge.data_cleaning import assign_ba_code_to_plant\n", + "import oge.validation as validation\n", "\n", - "from column_checks import get_dtypes, apply_dtypes" + "from oge.column_checks import get_dtypes, apply_dtypes" ] }, { @@ -1471,7 +1471,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" } }, "nbformat": 4, diff --git a/notebooks/validation/diff_output_versions.ipynb b/notebooks/validation/diff_output_versions.ipynb index 7ba28be0..1fb0d1d3 100644 --- a/notebooks/validation/diff_output_versions.ipynb +++ b/notebooks/validation/diff_output_versions.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -17,11 +17,11 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", - "import load_data\n", - "from column_checks import get_dtypes\n", - "from filepaths import *\n", + "import oge.load_data as load_data\n", + "from oge.column_checks import get_dtypes\n", + "from oge.filepaths import *\n", "\n", "\n", "year = 2021\n", @@ -247,7 +247,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/validation/hourly_validation.ipynb b/notebooks/validation/hourly_validation.ipynb index c5c1d9d0..908cd6f7 100644 --- a/notebooks/validation/hourly_validation.ipynb +++ b/notebooks/validation/hourly_validation.ipynb @@ -30,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -38,7 +38,7 @@ "\n", "sys.path.append(\"../../src\")\n", "\n", - "import filepaths" + "import oge.filepaths as filepaths" ] }, { @@ -1037,7 +1037,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.4" + "version": "3.11.2" }, "vscode": { "interpreter": { diff --git a/notebooks/validation/validate_data_cleaning.ipynb b/notebooks/validation/validate_data_cleaning.ipynb index ebdd650e..f0431861 100644 --- a/notebooks/validation/validate_data_cleaning.ipynb +++ b/notebooks/validation/validate_data_cleaning.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -15,12 +15,12 @@ "# Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/\")\n", + "sys.path.append(\"../../src\")\n", "\n", "# import local modules\n", - "import src.validation as validation\n", + "import oge.validation as validation\n", "\n", - "from src.column_checks import get_dtypes\n", + "from oge.column_checks import get_dtypes\n", "\n", "year = 2020\n", "path_prefix = \"\"\n", @@ -244,7 +244,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" } }, "nbformat": 4, diff --git a/notebooks/validation/validate_hourly_profiles.ipynb b/notebooks/validation/validate_hourly_profiles.ipynb index ec589bc7..320cf75b 100644 --- a/notebooks/validation/validate_hourly_profiles.ipynb +++ b/notebooks/validation/validate_hourly_profiles.ipynb @@ -2,24 +2,26 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ + "import numpy as np\n", "import pandas as pd\n", "import sys\n", "import plotly.express as px\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/\")\n", + "sys.path.append(\"../../src\")\n", + "\n", "%reload_ext autoreload\n", "%autoreload 2\n", - "from src.column_checks import get_dtypes, apply_dtypes\n", - "import src.impute_hourly_profiles as impute_hourly_profiles\n", - "import src.data_cleaning as data_cleaning\n", - "import src.load_data as load_data\n", - "import src.validation as validation\n", - "import src.eia930 as eia930\n", - "import numpy as np\n", + "\n", + "from oge.column_checks import get_dtypes, apply_dtypes\n", + "import oge.impute_hourly_profiles as impute_hourly_profiles\n", + "import oge.data_cleaning as data_cleaning\n", + "import oge.load_data as load_data\n", + "import oge.validation as validation\n", + "import oge.eia930 as eia930\n", "\n", "# load data from csv\n", "year = 2020\n", @@ -411,7 +413,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/validation/validate_negative_profiles.ipynb b/notebooks/validation/validate_negative_profiles.ipynb index 27c44e04..68706544 100644 --- a/notebooks/validation/validate_negative_profiles.ipynb +++ b/notebooks/validation/validate_negative_profiles.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -17,16 +17,16 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/\")\n", + "sys.path.append(\"../../src\")\n", "\n", "# import local modules\n", - "import src.load_data as load_data\n", - "import src.data_cleaning as data_cleaning\n", - "import src.gross_to_net_generation as gross_to_net_generation\n", - "import src.impute_hourly_profiles as impute_hourly_profiles\n", + "import oge.load_data as load_data\n", + "import oge.data_cleaning as data_cleaning\n", + "import oge.gross_to_net_generation as gross_to_net_generation\n", + "import oge.impute_hourly_profiles as impute_hourly_profiles\n", "\n", "\n", - "from src.column_checks import get_dtypes, apply_dtypes\n", + "from oge.column_checks import get_dtypes, apply_dtypes\n", "\n", "year = 2020" ] @@ -409,7 +409,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8 | packaged by conda-forge | (main, Nov 24 2022, 14:07:00) [MSC v.1916 64 bit (AMD64)]" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/validation/validate_vs_egrid.ipynb b/notebooks/validation/validate_vs_egrid.ipynb index 8e9bb8da..eba6eba2 100644 --- a/notebooks/validation/validate_vs_egrid.ipynb +++ b/notebooks/validation/validate_vs_egrid.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -19,14 +19,14 @@ "# Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", "# import local modules\n", - "import load_data\n", - "import validation\n", - "from filepaths import *\n", + "import oge.load_data as load_data\n", + "import oge.validation as validation\n", + "from oge.filepaths import *\n", "\n", - "from column_checks import get_dtypes" + "from oge.column_checks import get_dtypes" ] }, { @@ -686,7 +686,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.11.2" }, "vscode": { "interpreter": { diff --git a/notebooks/visualization/map_visualization.ipynb b/notebooks/visualization/map_visualization.ipynb index 0f5c85e1..043d39ee 100644 --- a/notebooks/visualization/map_visualization.ipynb +++ b/notebooks/visualization/map_visualization.ipynb @@ -41,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -51,9 +51,9 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", - "import output_data" + "import oge.output_data as output_data" ] }, { @@ -774,7 +774,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/visualization/plot_timeseries_data.ipynb b/notebooks/visualization/plot_timeseries_data.ipynb index 0228b61d..857d7c63 100644 --- a/notebooks/visualization/plot_timeseries_data.ipynb +++ b/notebooks/visualization/plot_timeseries_data.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -16,11 +16,11 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src\")\n", "\n", - "from filepaths import *\n", - "import validation\n", - "import visualization" + "from oge.filepaths import *\n", + "import oge.validation as validation\n", + "import oge.visualization as visualization" ] }, { @@ -200,7 +200,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.4" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/work_in_progress/GH102_test_dask.ipynb b/notebooks/work_in_progress/GH102_test_dask.ipynb index 5d0553aa..72becb7c 100644 --- a/notebooks/work_in_progress/GH102_test_dask.ipynb +++ b/notebooks/work_in_progress/GH102_test_dask.ipynb @@ -11,14 +11,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ + "import os\n", "import pandas as pd\n", "import numpy as np\n", "import dask.dataframe as dd\n", - "from src.load_data import PATH_TO_LOCAL_REPO" + "\n", + "# Tell python where to look for modules.\n", + "import sys\n", + "\n", + "sys.path.append(\"../../src/\")\n", + "\n", + "from oge.filepaths import top_folder\n", + "\n", + "PATH_TO_LOCAL_REPO = top_folder()" ] }, { @@ -38,20 +47,15 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "%reload_ext autoreload\n", "%autoreload 2\n", "\n", - "# # Tell python where to look for modules.\n", - "import sys\n", - "\n", - "sys.path.append(\"../../open-grid-emissions/\")\n", - "\n", "# import local modules\n", - "import src.data_cleaning as data_cleaning" + "import oge.data_cleaning as data_cleaning" ] }, { @@ -226,7 +230,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/work_in_progress/GH153_fill_missing_nox_so2_cems.ipynb b/notebooks/work_in_progress/GH153_fill_missing_nox_so2_cems.ipynb index 1196e6a6..cbdc80c2 100644 --- a/notebooks/work_in_progress/GH153_fill_missing_nox_so2_cems.ipynb +++ b/notebooks/work_in_progress/GH153_fill_missing_nox_so2_cems.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -12,16 +12,18 @@ "%reload_ext autoreload\n", "%autoreload 2\n", "\n", - "# # Tell python where to look for modules.\n", + "# Tell python where to look for modules.\n", "import sys\n", "\n", "sys.path.append(\"../../src\")\n", - "from column_checks import get_dtypes\n", - "import load_data\n", - "from data_cleaning import *\n", - "from emissions import *\n", + "from oge.column_checks import get_dtypes\n", + "import oge.load_data as load_data\n", + "from oge.data_cleaning import *\n", + "from oge.emissions import *\n", "\n", - "from pudl.analysis.allocate_net_gen import distribute_annually_reported_data_to_months" + "from pudl.analysis.allocate_gen_fuel import (\n", + " distribute_annually_reported_data_to_months_if_annual,\n", + ")" ] }, { @@ -260,7 +262,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/work_in_progress/GH240_eia930_physics_reconciliation.ipynb b/notebooks/work_in_progress/GH240_eia930_physics_reconciliation.ipynb index 92cc342c..b0613917 100644 --- a/notebooks/work_in_progress/GH240_eia930_physics_reconciliation.ipynb +++ b/notebooks/work_in_progress/GH240_eia930_physics_reconciliation.ipynb @@ -19,7 +19,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -34,19 +34,19 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src/\")\n", "\n", - "import download_data\n", - "import load_data\n", - "from column_checks import get_dtypes\n", - "from filepaths import *\n", - "import impute_hourly_profiles\n", - "import data_cleaning\n", - "import output_data\n", - "import emissions\n", - "import validation\n", - "import gross_to_net_generation\n", - "import eia930\n", + "import oge.download_data as download_data\n", + "import oge.load_data as load_data\n", + "from oge.column_checks import get_dtypes\n", + "from oge.filepaths import *\n", + "import oge.impute_hourly_profiles as impute_hourly_profiles\n", + "import oge.data_cleaning as data_cleaning\n", + "import oge.output_data as output_data\n", + "import oge.emissions as emissions\n", + "import oge.validation as validation\n", + "import oge.gross_to_net_generation as gross_to_net_generation\n", + "import oge.eia930 as eia930\n", "\n", "year = 2020\n", "path_prefix = f\"{year}/\"" @@ -162,7 +162,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.4" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/work_in_progress/clean_cems_outliers.ipynb b/notebooks/work_in_progress/clean_cems_outliers.ipynb index 5c4a565d..6d0dc2d5 100644 --- a/notebooks/work_in_progress/clean_cems_outliers.ipynb +++ b/notebooks/work_in_progress/clean_cems_outliers.ipynb @@ -26,22 +26,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%reload_ext autoreload\n", "%autoreload 2\n", "\n", - "# # Tell python where to look for modules.\n", + "# Tell python where to look for modules.\n", "import sys\n", "\n", "sys.path.append(\"../../src/\")\n", "\n", "# import local modules\n", - "import src.load_data as load_data\n", - "from src.filepaths import outputs_folder\n", - "from src.column_checks import get_dtypes" + "import oge.load_data as load_data\n", + "from oge.filepaths import outputs_folder\n", + "from oge.column_checks import get_dtypes" ] }, { @@ -462,7 +462,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8 | packaged by conda-forge | (main, Nov 24 2022, 14:07:00) [MSC v.1916 64 bit (AMD64)]" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/work_in_progress/issue230_spikes.ipynb b/notebooks/work_in_progress/issue230_spikes.ipynb index 7a98e8e2..7d8f8684 100644 --- a/notebooks/work_in_progress/issue230_spikes.ipynb +++ b/notebooks/work_in_progress/issue230_spikes.ipynb @@ -30,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -42,9 +42,9 @@ "\n", "sys.path.append(\"../../src/\")\n", "\n", - "import impute_hourly_profiles\n", - "from filepaths import outputs_folder, results_folder\n", - "from column_checks import get_dtypes" + "import oge.impute_hourly_profiles as impute_hourly_profiles\n", + "from oge.filepaths import outputs_folder, results_folder\n", + "from oge.column_checks import get_dtypes" ] }, { @@ -200,7 +200,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/work_in_progress/sandbox.ipynb b/notebooks/work_in_progress/sandbox.ipynb index 37714709..952f563e 100644 --- a/notebooks/work_in_progress/sandbox.ipynb +++ b/notebooks/work_in_progress/sandbox.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -18,20 +18,20 @@ "# # Tell python where to look for modules.\n", "import sys\n", "\n", - "sys.path.append(\"../../../open-grid-emissions/src/\")\n", + "sys.path.append(\"../../src/\")\n", "\n", - "import download_data\n", - "import load_data\n", - "from column_checks import get_dtypes\n", - "from filepaths import *\n", - "import impute_hourly_profiles\n", - "import data_cleaning\n", - "import output_data\n", - "import emissions\n", - "import validation\n", - "import gross_to_net_generation\n", - "import eia930\n", - "from logging_util import get_logger, configure_root_logger\n", + "import oge.download_data as download_data\n", + "import oge.load_data as load_data\n", + "from oge.column_checks import get_dtypes\n", + "from oge.filepaths import *\n", + "import oge.impute_hourly_profiles as impute_hourly_profiles\n", + "import oge.data_cleaning as data_cleaning\n", + "import oge.output_data as output_data\n", + "import oge.emissions as emissions\n", + "import oge.validation as validation\n", + "import oge.gross_to_net_generation as gross_to_net_generation\n", + "import oge.eia930 as eia930\n", + "from oge.logging_util import get_logger, configure_root_logger\n", "\n", "configure_root_logger()\n", "logger = get_logger(\"test\")\n", @@ -40,6 +40,13 @@ "year = 2020\n", "path_prefix = f\"{year}/\"" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -58,7 +65,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.11" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/work_in_progress/uncertainty_analysis.ipynb b/notebooks/work_in_progress/uncertainty_analysis.ipynb index 79f519d4..af6acabd 100644 --- a/notebooks/work_in_progress/uncertainty_analysis.ipynb +++ b/notebooks/work_in_progress/uncertainty_analysis.ipynb @@ -14,7 +14,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -27,7 +27,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -39,9 +39,11 @@ "import sys\n", "\n", "sys.path.append(\"../../hourly-egrid/\")\n", + "sys.path.append(\"../../src\")\n", + "\n", "\n", - "import src.load_data as load_data\n", - "import src.column_checks as column_checks" + "import oge.load_data as load_data\n", + "import oge.column_checks as column_checks" ] }, { @@ -622,7 +624,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.4" + "version": "3.11.2" }, "orig_nbformat": 4, "vscode": { From b5d6a13305fedbccf0848b54f6530e89812c2a32 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 14 Dec 2023 17:19:05 -0800 Subject: [PATCH 56/85] move data --- pyproject.toml | 4 +--- {config => src/oge/config}/gridemissions.json | 0 src/oge/consumed.py | 4 ++-- src/oge/data_cleaning.py | 16 +++++++-------- src/oge/eia930.py | 4 ++-- src/oge/emissions.py | 4 ++-- src/oge/filepaths.py | 16 +++++++-------- src/oge/impute_hourly_profiles.py | 4 ++-- src/oge/load_data.py | 20 +++++++++---------- .../oge/reference_tables}/ba_reference.csv | 0 .../default_gross_to_net_ratios.csv | 0 ...GRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv | 0 .../emission_factors_for_co2_ch4_n2o.csv | 0 .../emission_factors_for_nox.csv | 0 .../emission_factors_for_so2.csv | 0 .../energy_source_groups.csv | 0 .../epa_eia_crosswalk_manual.csv | 0 .../geothermal_emission_factors.csv | 0 .../oge/reference_tables}/ipcc_gwp.csv | 0 .../oge/reference_tables}/physical_ba.csv | 0 .../plants_not_connected_to_grid.csv | 0 .../steam_units_to_remove.csv | 0 .../updated_oth_energy_source_codes.csv | 0 .../utility_name_ba_code_map.csv | 0 src/oge/validation.py | 8 ++++---- 25 files changed, 39 insertions(+), 41 deletions(-) rename {config => src/oge/config}/gridemissions.json (100%) rename {data/manual => src/oge/reference_tables}/ba_reference.csv (100%) rename {data/manual => src/oge/reference_tables}/default_gross_to_net_ratios.csv (100%) rename {data/manual => src/oge/reference_tables}/eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv (100%) rename {data/manual => src/oge/reference_tables}/emission_factors_for_co2_ch4_n2o.csv (100%) rename {data/manual => src/oge/reference_tables}/emission_factors_for_nox.csv (100%) rename {data/manual => src/oge/reference_tables}/emission_factors_for_so2.csv (100%) rename {data/manual => src/oge/reference_tables}/energy_source_groups.csv (100%) rename {data/manual => src/oge/reference_tables}/epa_eia_crosswalk_manual.csv (100%) rename {data/manual => src/oge/reference_tables}/geothermal_emission_factors.csv (100%) rename {data/manual => src/oge/reference_tables}/ipcc_gwp.csv (100%) rename {data/manual => src/oge/reference_tables}/physical_ba.csv (100%) rename {data/manual => src/oge/reference_tables}/plants_not_connected_to_grid.csv (100%) rename {data/manual => src/oge/reference_tables}/steam_units_to_remove.csv (100%) rename {data/manual => src/oge/reference_tables}/updated_oth_energy_source_codes.csv (100%) rename {data/manual => src/oge/reference_tables}/utility_name_ba_code_map.csv (100%) diff --git a/pyproject.toml b/pyproject.toml index 127d44d9..56e5ab1c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,12 +55,10 @@ Issues = "https://github.com/singularity-energy/open-grid-emissions/issues" allow-direct-references = true [tool.hatch.build.targets.wheel] -only-include = ["config", "data/manual", "src/oge"] +only-include = ["src/oge"] [tool.hatch.build.targets.wheel.sources] "src" = "" -"data" = "data" -"config" = "config" [tool.ruff] diff --git a/config/gridemissions.json b/src/oge/config/gridemissions.json similarity index 100% rename from config/gridemissions.json rename to src/oge/config/gridemissions.json diff --git a/src/oge/consumed.py b/src/oge/consumed.py index f63879e2..cdf7bdb3 100644 --- a/src/oge/consumed.py +++ b/src/oge/consumed.py @@ -5,7 +5,7 @@ from gridemissions.load import BaData from gridemissions.eia_api import KEYS, SRC -from oge.filepaths import outputs_folder, manual_folder, results_folder +from oge.filepaths import outputs_folder, reference_table_folder, results_folder from oge.logging_util import get_logger from oge.output_data import ( @@ -246,7 +246,7 @@ def _get_special_regions(self): We won't export files for these """ self.ba_ref = pd.read_csv( - manual_folder("ba_reference.csv"), index_col="ba_code" + reference_table_folder("ba_reference.csv"), index_col="ba_code" ) generation_only = list( self.ba_ref[self.ba_ref.ba_category == "generation_only"].index diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index e12724ab..a4652359 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -10,7 +10,7 @@ import oge.emissions as emissions from oge.emissions import CLEAN_FUELS from oge.column_checks import get_dtypes, apply_dtypes -from oge.filepaths import manual_folder, outputs_folder +from oge.filepaths import reference_table_folder, outputs_folder from oge.logging_util import get_logger logger = get_logger(__name__) @@ -565,7 +565,7 @@ def update_energy_source_codes(df): Manually update fuel source codes """ # load the table of updated fuel types - updated_esc = pd.read_csv(manual_folder("updated_oth_energy_source_codes.csv")) + updated_esc = pd.read_csv(reference_table_folder("updated_oth_energy_source_codes.csv")) for index, row in updated_esc.iterrows(): plant_id = row["plant_id_eia"] @@ -957,7 +957,7 @@ def remove_non_grid_connected_plants(df): # get the list of plant_id_eia from the static table ngc_plants = list( pd.read_csv( - manual_folder("plants_not_connected_to_grid.csv"), + reference_table_folder("plants_not_connected_to_grid.csv"), dtype=get_dtypes(), )["Plant ID"] ) @@ -1080,7 +1080,7 @@ def manually_remove_steam_units(df): # get the list of plant_id_eia from the static table units_to_remove = pd.read_csv( - manual_folder("steam_units_to_remove.csv"), + reference_table_folder("steam_units_to_remove.csv"), dtype=get_dtypes(), )[["plant_id_eia", "emissions_unit_id_epa"]] @@ -2082,7 +2082,7 @@ def create_plant_ba_table(year): ].fillna(value=np.NaN) # load the ba name reference - ba_name_to_ba_code = pd.read_csv(manual_folder("ba_reference.csv")) + ba_name_to_ba_code = pd.read_csv(reference_table_folder("ba_reference.csv")) ba_name_to_ba_code = dict( zip( ba_name_to_ba_code["ba_name"], @@ -2091,7 +2091,7 @@ def create_plant_ba_table(year): ) # specify a ba code for certain utilities - utility_as_ba_code = pd.read_csv(manual_folder("utility_name_ba_code_map.csv")) + utility_as_ba_code = pd.read_csv(reference_table_folder("utility_name_ba_code_map.csv")) utility_as_ba_code = dict( zip( utility_as_ba_code["name"], @@ -2138,7 +2138,7 @@ def create_plant_ba_table(year): ) # update based on mapping table when ambiguous - physical_ba = pd.read_csv(manual_folder("physical_ba.csv"), dtype=get_dtypes()) + physical_ba = pd.read_csv(reference_table_folder("physical_ba.csv"), dtype=get_dtypes()) plant_ba = plant_ba.merge( physical_ba, how="left", @@ -2200,7 +2200,7 @@ def assign_fuel_category_to_ESC( """ # load the fuel category table energy_source_groups = pd.read_csv( - manual_folder("energy_source_groups.csv"), dtype=get_dtypes() + reference_table_folder("energy_source_groups.csv"), dtype=get_dtypes() )[["energy_source_code"] + fuel_category_names].rename( columns={"energy_source_code": esc_column} ) diff --git a/src/oge/eia930.py b/src/oge/eia930.py index db5fbbe1..ec4759d3 100644 --- a/src/oge/eia930.py +++ b/src/oge/eia930.py @@ -6,7 +6,7 @@ import oge.load_data as load_data from oge.column_checks import get_dtypes -from oge.filepaths import top_folder, downloads_folder, outputs_folder, manual_folder +from oge.filepaths import top_folder, downloads_folder, outputs_folder, reference_table_folder from oge.logging_util import get_logger # Tell gridemissions where to find config before we load gridemissions @@ -236,7 +236,7 @@ def load_chalendar_for_pipeline(cleaned_data_filepath, year): )[[1, 4]] # drop BAs not located in the United States - ba_ref = pd.read_csv(manual_folder("ba_reference.csv")) + ba_ref = pd.read_csv(reference_table_folder("ba_reference.csv")) foreign_bas = list(ba_ref.loc[ba_ref["us_ba"] == "No", "ba_code"]) data = data[~data["ba_code"].isin(foreign_bas)] diff --git a/src/oge/emissions.py b/src/oge/emissions.py index b3e5e3f4..4f802df7 100644 --- a/src/oge/emissions.py +++ b/src/oge/emissions.py @@ -4,7 +4,7 @@ import oge.load_data as load_data import oge.validation as validation from oge.column_checks import get_dtypes -from oge.filepaths import manual_folder +from oge.filepaths import reference_table_folder from oge.logging_util import get_logger from pudl.analysis.allocate_gen_fuel import ( @@ -128,7 +128,7 @@ def calculate_geothermal_emission_factors(year): """ # load geothermal efs geothermal_efs = pd.read_csv( - manual_folder("geothermal_emission_factors.csv"), + reference_table_folder("geothermal_emission_factors.csv"), dtype=get_dtypes(), ).loc[ :, ["geotype_code", "co2_lb_per_mmbtu", "nox_lb_per_mmbtu", "so2_lb_per_mmbtu"] diff --git a/src/oge/filepaths.py b/src/oge/filepaths.py index bc8d9c60..2aa5a80b 100644 --- a/src/oge/filepaths.py +++ b/src/oge/filepaths.py @@ -9,31 +9,31 @@ def top_folder(rel=""): This will work regardless of where the function is imported or called from. """ return os.path.join( - os.path.abspath(os.path.join(os.path.realpath(__file__), "../../")), rel + os.path.abspath(os.path.join(os.path.realpath(__file__), "../")), rel ) +def reference_table_folder(rel=""): + return os.path.join(top_folder("reference_tables"), rel) + + def data_folder(rel=""): """Returns a path relative to the `data` folder.""" - return os.path.join(top_folder("data"), rel) + return os.path.join(os.path.join(os.path.expanduser("~"), "open_grid_emissions_data"), rel) def downloads_folder(rel=""): return os.path.join(data_folder("downloads"), rel) -def manual_folder(rel=""): - return os.path.join(data_folder("manual"), rel) +def outputs_folder(rel=""): + return os.path.join(data_folder("outputs"), rel) def results_folder(rel=""): return os.path.join(data_folder("results"), rel) -def outputs_folder(rel=""): - return os.path.join(data_folder("outputs"), rel) - - def containing_folder(filepath: str) -> str: """Returns the folder containing `filepath`.""" return os.path.dirname(os.path.realpath(filepath)) diff --git a/src/oge/impute_hourly_profiles.py b/src/oge/impute_hourly_profiles.py index 13869136..bf705085 100644 --- a/src/oge/impute_hourly_profiles.py +++ b/src/oge/impute_hourly_profiles.py @@ -4,7 +4,7 @@ # import open-grid-emissions modules from oge.column_checks import apply_dtypes import oge.load_data as load_data -from oge.filepaths import manual_folder +from oge.filepaths import reference_table_folder import oge.validation as validation import oge.output_data as output_data from oge.logging_util import get_logger @@ -1106,7 +1106,7 @@ def get_shaped_plant_id_from_ba_fuel(df): """ # load the ba reference table with all of the ba number ids - ba_numbers = pd.read_csv(manual_folder("ba_reference.csv"))[ + ba_numbers = pd.read_csv(reference_table_folder("ba_reference.csv"))[ ["ba_code", "ba_number"] ] # reformat the number with leading zeros diff --git a/src/oge/load_data.py b/src/oge/load_data.py index eb9cffc1..a70ab6b5 100644 --- a/src/oge/load_data.py +++ b/src/oge/load_data.py @@ -5,7 +5,7 @@ from pathlib import Path from oge.column_checks import get_dtypes -from oge.filepaths import downloads_folder, manual_folder, outputs_folder +from oge.filepaths import downloads_folder, reference_table_folder, outputs_folder import oge.validation as validation from oge.logging_util import get_logger @@ -243,7 +243,7 @@ def load_ghg_emission_factors(): """ efs = pd.read_csv( - manual_folder("emission_factors_for_co2_ch4_n2o.csv"), + reference_table_folder("emission_factors_for_co2_ch4_n2o.csv"), dtype=get_dtypes(), ) @@ -259,7 +259,7 @@ def load_ghg_emission_factors(): def load_nox_emission_factors(): """Read in the NOx emission factors from eGRID Table C2.""" emission_factors = pd.read_csv( - manual_folder("emission_factors_for_nox.csv"), + reference_table_folder("emission_factors_for_nox.csv"), dtype=get_dtypes(), ) @@ -279,7 +279,7 @@ def load_so2_emission_factors(): reported in Table C3 as a formula like `123*S`. """ df = pd.read_csv( - manual_folder("emission_factors_for_so2.csv"), + reference_table_folder("emission_factors_for_so2.csv"), dtype=get_dtypes(), ) @@ -420,7 +420,7 @@ def load_epa_eia_crosswalk_from_raw(year): # load manually inputted data crosswalk_manual = pd.read_csv( - manual_folder("epa_eia_crosswalk_manual.csv"), + reference_table_folder("epa_eia_crosswalk_manual.csv"), dtype=get_dtypes(), ).drop(columns=["notes"]) @@ -469,7 +469,7 @@ def load_epa_eia_crosswalk(year): # load manually inputted data crosswalk_manual = pd.read_csv( - manual_folder("epa_eia_crosswalk_manual.csv"), + reference_table_folder("epa_eia_crosswalk_manual.csv"), dtype=get_dtypes(), ).drop(columns=["notes"]) @@ -568,7 +568,7 @@ def load_gross_to_net_data( def load_ipcc_gwp(): """Load a table containing global warming potential (GWP) values for CO2, CH4, and N2O.""" - return pd.read_csv(manual_folder("ipcc_gwp.csv"), dtype=get_dtypes()) + return pd.read_csv(reference_table_folder("ipcc_gwp.csv"), dtype=get_dtypes()) def load_raw_eia930_data(year, description): @@ -609,7 +609,7 @@ def load_raw_eia930_data(year, description): def load_ba_reference(): return pd.read_csv( - manual_folder("ba_reference.csv"), + reference_table_folder("ba_reference.csv"), dtype=get_dtypes(), parse_dates=["activation_date", "retirement_date"], ) @@ -659,7 +659,7 @@ def ba_timezone(ba, type): """ tz = pd.read_csv( - manual_folder("ba_reference.csv"), + reference_table_folder("ba_reference.csv"), usecols=["ba_code", f"timezone_{type}"], ) tz = tz.loc[tz["ba_code"] == ba, f"timezone_{type}"] @@ -792,7 +792,7 @@ def load_unit_to_boiler_associations(year): def load_default_gtn_ratios(): """Read in the default gross to net generation ratios.""" default_gtn = pd.read_csv( - manual_folder("default_gross_to_net_ratios.csv"), + reference_table_folder("default_gross_to_net_ratios.csv"), dtype=get_dtypes(), )[["prime_mover_code", "default_gtn_ratio"]] diff --git a/data/manual/ba_reference.csv b/src/oge/reference_tables/ba_reference.csv similarity index 100% rename from data/manual/ba_reference.csv rename to src/oge/reference_tables/ba_reference.csv diff --git a/data/manual/default_gross_to_net_ratios.csv b/src/oge/reference_tables/default_gross_to_net_ratios.csv similarity index 100% rename from data/manual/default_gross_to_net_ratios.csv rename to src/oge/reference_tables/default_gross_to_net_ratios.csv diff --git a/data/manual/eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv b/src/oge/reference_tables/eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv similarity index 100% rename from data/manual/eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv rename to src/oge/reference_tables/eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv diff --git a/data/manual/emission_factors_for_co2_ch4_n2o.csv b/src/oge/reference_tables/emission_factors_for_co2_ch4_n2o.csv similarity index 100% rename from data/manual/emission_factors_for_co2_ch4_n2o.csv rename to src/oge/reference_tables/emission_factors_for_co2_ch4_n2o.csv diff --git a/data/manual/emission_factors_for_nox.csv b/src/oge/reference_tables/emission_factors_for_nox.csv similarity index 100% rename from data/manual/emission_factors_for_nox.csv rename to src/oge/reference_tables/emission_factors_for_nox.csv diff --git a/data/manual/emission_factors_for_so2.csv b/src/oge/reference_tables/emission_factors_for_so2.csv similarity index 100% rename from data/manual/emission_factors_for_so2.csv rename to src/oge/reference_tables/emission_factors_for_so2.csv diff --git a/data/manual/energy_source_groups.csv b/src/oge/reference_tables/energy_source_groups.csv similarity index 100% rename from data/manual/energy_source_groups.csv rename to src/oge/reference_tables/energy_source_groups.csv diff --git a/data/manual/epa_eia_crosswalk_manual.csv b/src/oge/reference_tables/epa_eia_crosswalk_manual.csv similarity index 100% rename from data/manual/epa_eia_crosswalk_manual.csv rename to src/oge/reference_tables/epa_eia_crosswalk_manual.csv diff --git a/data/manual/geothermal_emission_factors.csv b/src/oge/reference_tables/geothermal_emission_factors.csv similarity index 100% rename from data/manual/geothermal_emission_factors.csv rename to src/oge/reference_tables/geothermal_emission_factors.csv diff --git a/data/manual/ipcc_gwp.csv b/src/oge/reference_tables/ipcc_gwp.csv similarity index 100% rename from data/manual/ipcc_gwp.csv rename to src/oge/reference_tables/ipcc_gwp.csv diff --git a/data/manual/physical_ba.csv b/src/oge/reference_tables/physical_ba.csv similarity index 100% rename from data/manual/physical_ba.csv rename to src/oge/reference_tables/physical_ba.csv diff --git a/data/manual/plants_not_connected_to_grid.csv b/src/oge/reference_tables/plants_not_connected_to_grid.csv similarity index 100% rename from data/manual/plants_not_connected_to_grid.csv rename to src/oge/reference_tables/plants_not_connected_to_grid.csv diff --git a/data/manual/steam_units_to_remove.csv b/src/oge/reference_tables/steam_units_to_remove.csv similarity index 100% rename from data/manual/steam_units_to_remove.csv rename to src/oge/reference_tables/steam_units_to_remove.csv diff --git a/data/manual/updated_oth_energy_source_codes.csv b/src/oge/reference_tables/updated_oth_energy_source_codes.csv similarity index 100% rename from data/manual/updated_oth_energy_source_codes.csv rename to src/oge/reference_tables/updated_oth_energy_source_codes.csv diff --git a/data/manual/utility_name_ba_code_map.csv b/src/oge/reference_tables/utility_name_ba_code_map.csv similarity index 100% rename from data/manual/utility_name_ba_code_map.csv rename to src/oge/reference_tables/utility_name_ba_code_map.csv diff --git a/src/oge/validation.py b/src/oge/validation.py index 3ea79c84..4807a315 100644 --- a/src/oge/validation.py +++ b/src/oge/validation.py @@ -5,7 +5,7 @@ import oge.impute_hourly_profiles as impute_hourly_profiles import oge.emissions as emissions from oge.column_checks import get_dtypes -from oge.filepaths import downloads_folder, manual_folder +from oge.filepaths import downloads_folder, reference_table_folder from oge.logging_util import get_logger logger = get_logger(__name__) @@ -112,7 +112,7 @@ def flag_possible_primary_fuel_mismatches(plant_primary_fuel): for esc_column in ["plant_primary_fuel_from_capacity_mw", "plant_primary_fuel"]: # load the fuel category table energy_source_groups = pd.read_csv( - manual_folder("energy_source_groups.csv"), dtype=get_dtypes() + reference_table_folder("energy_source_groups.csv"), dtype=get_dtypes() )[["energy_source_code", "fuel_category_eia930"]].rename( columns={ "energy_source_code": esc_column, @@ -1866,7 +1866,7 @@ def add_egrid_plant_id(df, from_id, to_id): # however, there are sometime 2 EIA IDs for a single eGRID ID, so we need to group the data in the EIA table by the egrid id # We need to update all of the egrid plant IDs to the EIA plant IDs egrid_crosswalk = pd.read_csv( - manual_folder("eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv"), + reference_table_folder("eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv"), dtype=get_dtypes(), ) id_map = dict( @@ -2392,7 +2392,7 @@ def identify_potential_missing_fuel_in_egrid(year, egrid_plant, cems): # add egrid plant ids egrid_crosswalk = pd.read_csv( - manual_folder("eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv") + reference_table_folder("eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv") ) eia_to_egrid_id = dict( zip( From 67ca8c0af45767099460619b799bdf124f0f3383 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 14 Dec 2023 17:28:22 -0800 Subject: [PATCH 57/85] update gitignore --- .gitignore | 2 -- README.md | 10 ++++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 239ee4a8..76d79525 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,6 @@ src/oge/__pycache__ dist/* -data/* -!data/manual/ example/.ipynb_checkpoints/ test/__pycache__/ diff --git a/README.md b/README.md index 2106af2e..ed1f4069 100644 --- a/README.md +++ b/README.md @@ -84,10 +84,12 @@ Notebooks are organized into five directories based on their purpose - `work_in_progress`: temporary notebooks being used for development purposes on specific branches ### Data Structure -- `data/downloads` contains all files that are downloaded by functions in `load_data` -- `data/manual` contains all manually-created files, including the egrid static tables -- `data/outputs` contains intermediate outputs from the data pipeline... any files created by our code that are not final results -- `data/results` contains all final output files that will be published +All manual reference tables are stored in `src/oge/reference_tables`. + +All files downloaded/created as part of the pipeline are stored in your HOME directory (e.g. users/user.name/): +- `HOME/open_grid_emissions_data/downloads` contains all files that are downloaded by functions in `load_data` +- `HOME/open_grid_emissions_data/outputs` contains intermediate outputs from the data pipeline... any files created by our code that are not final results +- `HOME/open_grid_emissions_data/results` contains all final output files that will be published ## Development Setup If you would like to run the code on your own computer and/or contribute updates to the code, the following steps can help get you started. From c43cca198e9613e37bea9deb2c8abb5c4ee550db Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 14 Dec 2023 17:31:26 -0800 Subject: [PATCH 58/85] update formatting --- src/oge/eia930.py | 11 +++++++++-- src/oge/filepaths.py | 4 +++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/oge/eia930.py b/src/oge/eia930.py index ec4759d3..bb07c6e6 100644 --- a/src/oge/eia930.py +++ b/src/oge/eia930.py @@ -6,7 +6,12 @@ import oge.load_data as load_data from oge.column_checks import get_dtypes -from oge.filepaths import top_folder, downloads_folder, outputs_folder, reference_table_folder +from oge.filepaths import ( + top_folder, + downloads_folder, + outputs_folder, + reference_table_folder, +) from oge.logging_util import get_logger # Tell gridemissions where to find config before we load gridemissions @@ -459,7 +464,9 @@ def manual_930_adjust(raw: pd.DataFrame): & (raw.index < "2022-06-16 07:00:00+00") ), cols, - ].shift(1, freq="H") + ].shift( + 1, freq="H" + ) raw = raw.drop(columns=cols) raw = pd.concat([raw, new], axis="columns") diff --git a/src/oge/filepaths.py b/src/oge/filepaths.py index 2aa5a80b..49f976fd 100644 --- a/src/oge/filepaths.py +++ b/src/oge/filepaths.py @@ -19,7 +19,9 @@ def reference_table_folder(rel=""): def data_folder(rel=""): """Returns a path relative to the `data` folder.""" - return os.path.join(os.path.join(os.path.expanduser("~"), "open_grid_emissions_data"), rel) + return os.path.join( + os.path.join(os.path.expanduser("~"), "open_grid_emissions_data"), rel + ) def downloads_folder(rel=""): From fbb32380e313201f0a093051b8fd3505a0f4aa33 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 14 Dec 2023 17:59:11 -0800 Subject: [PATCH 59/85] update formatting --- src/oge/data_cleaning.py | 20 +++++++++++++++----- src/oge/eia930.py | 4 +--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index a4652359..203834a7 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -458,7 +458,9 @@ def clean_eia923( "fuel_consumed_mmbtu", "fuel_consumed_for_electricity_mmbtu", ], - ].round(1) + ].round( + 1 + ) validation.test_for_missing_energy_source_code(gen_fuel_allocated) validation.test_for_negative_values(gen_fuel_allocated) @@ -565,7 +567,9 @@ def update_energy_source_codes(df): Manually update fuel source codes """ # load the table of updated fuel types - updated_esc = pd.read_csv(reference_table_folder("updated_oth_energy_source_codes.csv")) + updated_esc = pd.read_csv( + reference_table_folder("updated_oth_energy_source_codes.csv") + ) for index, row in updated_esc.iterrows(): plant_id = row["plant_id_eia"] @@ -631,7 +635,9 @@ def create_primary_fuel_table(gen_fuel_allocated, add_subplant_id, year): ascending=True, ).drop_duplicates( subset=["plant_id_eia", "subplant_id", "generator_id"], keep="last" - )[["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"]] + )[ + ["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"] + ] if not add_subplant_id: gen_primary_fuel = gen_primary_fuel.drop(columns=["subplant_id"]) @@ -2091,7 +2097,9 @@ def create_plant_ba_table(year): ) # specify a ba code for certain utilities - utility_as_ba_code = pd.read_csv(reference_table_folder("utility_name_ba_code_map.csv")) + utility_as_ba_code = pd.read_csv( + reference_table_folder("utility_name_ba_code_map.csv") + ) utility_as_ba_code = dict( zip( utility_as_ba_code["name"], @@ -2138,7 +2146,9 @@ def create_plant_ba_table(year): ) # update based on mapping table when ambiguous - physical_ba = pd.read_csv(reference_table_folder("physical_ba.csv"), dtype=get_dtypes()) + physical_ba = pd.read_csv( + reference_table_folder("physical_ba.csv"), dtype=get_dtypes() + ) plant_ba = plant_ba.merge( physical_ba, how="left", diff --git a/src/oge/eia930.py b/src/oge/eia930.py index bb07c6e6..f3f778d7 100644 --- a/src/oge/eia930.py +++ b/src/oge/eia930.py @@ -464,9 +464,7 @@ def manual_930_adjust(raw: pd.DataFrame): & (raw.index < "2022-06-16 07:00:00+00") ), cols, - ].shift( - 1, freq="H" - ) + ].shift(1, freq="H") raw = raw.drop(columns=cols) raw = pd.concat([raw, new], axis="columns") From 41094832887bc5c1f8b4084dccfd8a6692e8df04 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 15 Dec 2023 11:13:14 -0800 Subject: [PATCH 60/85] ruff formatting --- src/oge/data_cleaning.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index 203834a7..524437ac 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -458,9 +458,7 @@ def clean_eia923( "fuel_consumed_mmbtu", "fuel_consumed_for_electricity_mmbtu", ], - ].round( - 1 - ) + ].round(1) validation.test_for_missing_energy_source_code(gen_fuel_allocated) validation.test_for_negative_values(gen_fuel_allocated) @@ -635,9 +633,7 @@ def create_primary_fuel_table(gen_fuel_allocated, add_subplant_id, year): ascending=True, ).drop_duplicates( subset=["plant_id_eia", "subplant_id", "generator_id"], keep="last" - )[ - ["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"] - ] + )[["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"]] if not add_subplant_id: gen_primary_fuel = gen_primary_fuel.drop(columns=["subplant_id"]) From 69976b7946f48617db6eaa5f406e72ec5b82017e Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 15 Dec 2023 15:52:36 -0800 Subject: [PATCH 61/85] update egrid2020 url --- src/oge/data_pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oge/data_pipeline.py b/src/oge/data_pipeline.py index cc2ce018..d0f1ddb2 100644 --- a/src/oge/data_pipeline.py +++ b/src/oge/data_pipeline.py @@ -122,7 +122,7 @@ def main(args): egrid_files_to_download = [ "https://www.epa.gov/sites/default/files/2020-03/egrid2018_data_v2.xlsx", "https://www.epa.gov/sites/default/files/2021-02/egrid2019_data.xlsx", - "https://www.epa.gov/system/files/documents/2022-01/egrid2020_data.xlsx", + "https://www.epa.gov/system/files/documents/2022-09/eGRID2020_Data_v2.xlsx", "https://www.epa.gov/system/files/documents/2023-01/eGRID2021_data.xlsx", ] download_data.download_egrid_files(egrid_files_to_download) From 0d9aeca3fa6981b9929123ef3b02a94b60be2787 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 15 Dec 2023 17:41:45 -0800 Subject: [PATCH 62/85] update 930 cleaning for TEPC --- src/oge/eia930.py | 7 ++- src/oge/gross_to_net_generation.py | 2 +- src/oge/load_data.py | 2 +- src/oge/validation.py | 86 ++++++++++++++++++++++++++---- 4 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/oge/eia930.py b/src/oge/eia930.py index f3f778d7..99509bf5 100644 --- a/src/oge/eia930.py +++ b/src/oge/eia930.py @@ -437,10 +437,13 @@ def manual_930_adjust(raw: pd.DataFrame): # TEPC data reports start of hour instead of end of hour # This issue may have been fixed but will be addressed in a future PR # we need to shift all data by +1 hour + # This issue was corrected in the raw data on 2021-11-01 ba = "TEPC" cols = get_columns(ba, raw.columns) - cols = get_columns(ba, raw.columns) - new = raw[cols].shift(1, freq="H") + new = raw[cols].copy() + new.loc[raw.index < "2021-11-01 00:00:00+00", cols] = new.loc[ + raw.index < "2021-11-01 00:00:00+00", cols + ].shift(1, freq="H") raw = raw.drop(columns=cols) raw = pd.concat([raw, new], axis="columns") diff --git a/src/oge/gross_to_net_generation.py b/src/oge/gross_to_net_generation.py index f835c586..2e1f0274 100644 --- a/src/oge/gross_to_net_generation.py +++ b/src/oge/gross_to_net_generation.py @@ -514,7 +514,7 @@ def filter_gtn_conversion_factors(gtn_conversions): for method in method_hierarchy: # get a count of the number of non-na factor values and non-na net generation values for each plant incomplete_factors = ( - factors_to_use.groupby(["plant_id_eia", "data_source"], dropna=False) + factors_to_use.groupby(["plant_id_eia", "data_source"], dropna=False, observed=False) .count()[[method, "net_generation_mwh"]] .reset_index() ) diff --git a/src/oge/load_data.py b/src/oge/load_data.py index 24b855ad..6e8d8178 100644 --- a/src/oge/load_data.py +++ b/src/oge/load_data.py @@ -215,7 +215,7 @@ def add_report_date(df): # convert UTC to the local timezone for tz in timezones: - tz_mask = df["timezone"] == tz # find all rows where the tz matches + tz_mask = (df["timezone"] == tz) # find all rows where the tz matches with warnings.catch_warnings(): warnings.filterwarnings( "ignore", diff --git a/src/oge/validation.py b/src/oge/validation.py index 19929534..3ded8cca 100644 --- a/src/oge/validation.py +++ b/src/oge/validation.py @@ -160,6 +160,23 @@ def test_for_negative_values(df, small: bool = False): logger.warning( f"There are {len(negative_test)} records where {column} is negative." ) + logger.warning( + negative_test[ + [ + col + for col in df.columns + if col + in [ + "report_date", + "plant_id_eia", + "generator_id", + "energy_source_code", + "prime_mover_code", + column, + ] + ] + ] + ) negative_warnings += 1 else: pass @@ -524,7 +541,7 @@ def test_emissions_adjustments(df): pollutants = ["co2", "ch4", "n2o", "co2e", "nox", "so2"] - bad_adjustments = 0 + bad_adjustment_count = 0 for pollutant in pollutants: # test that mass_lb >= mass_lb_for_electricity @@ -535,7 +552,20 @@ def test_emissions_adjustments(df): logger.warning( f"There are {len(bad_adjustment)} records where {pollutant}_mass_lb_for_electricity > {pollutant}_mass_lb" ) - bad_adjustment += 1 + logger.warning( + bad_adjustment[ + [ + "report_date", + "plant_id_eia", + "generator_id", + "prime_mover_code", + "energy_source_code", + f"{pollutant}_mass_lb", + f"{pollutant}_mass_lb_for_electricity", + ] + ] + ) + bad_adjustment_count += 1 # test that mass_lb >= mass_lb_adjusted bad_adjustment = df[ @@ -545,7 +575,20 @@ def test_emissions_adjustments(df): logger.warning( f"There are {len(bad_adjustment)} records where {pollutant}_mass_lb_adjusted > {pollutant}_mass_lb" ) - bad_adjustment += 1 + logger.warning( + bad_adjustment[ + [ + "report_date", + "plant_id_eia", + "generator_id", + "prime_mover_code", + "energy_source_code", + f"{pollutant}_mass_lb", + f"{pollutant}_mass_lb_adjusted", + ] + ] + ) + bad_adjustment_count += 1 # test that mass_lb_for_electricity >= mass_lb_for_electricity_adjusted bad_adjustment = df[ @@ -558,10 +601,23 @@ def test_emissions_adjustments(df): logger.warning( f"There are {len(bad_adjustment)} records where {pollutant}_mass_lb_for_electricity_adjusted > {pollutant}_mass_lb_for_electricity" ) - bad_adjustment += 1 + logger.warning( + bad_adjustment[ + [ + "report_date", + "plant_id_eia", + "generator_id", + "prime_mover_code", + "energy_source_code", + f"{pollutant}_mass_lb_for_electricity", + f"{pollutant}_mass_lb_for_electricity_adjusted", + ] + ] + ) + bad_adjustment_count += 1 # if there were any bad adjustments, raise a userwarning. - if bad_adjustments > 0: + if bad_adjustment_count > 0: raise UserWarning("The above issues with emissions adjustments must be fixed.") else: logger.info("OK") @@ -620,7 +676,9 @@ def ensure_non_overlapping_data_from_all_sources( ["in_eia", "in_cems", "in_partial_cems_subplant", "in_partial_cems_plant"] ] = data_overlap[ ["in_eia", "in_cems", "in_partial_cems_subplant", "in_partial_cems_plant"] - ].fillna(0) + ].fillna( + 0 + ) data_overlap["number_of_locations"] = ( data_overlap["in_eia"] + data_overlap["in_cems"] @@ -1263,7 +1321,9 @@ def summarize_cems_measurement_quality(cems): "so2_mass_measurement_code", "nox_mass_measurement_code", ] - ].astype(str) + ].astype( + str + ) # replace the CEMS mass measurement codes with two categories measurement_code_map = { "Measured": "Measured", @@ -1286,7 +1346,9 @@ def summarize_cems_measurement_quality(cems): "so2_mass_measurement_code", "nox_mass_measurement_code", ] - ].replace(measurement_code_map) + ].replace( + measurement_code_map + ) cems_quality_summary = [] # calculate the percent of mass for each pollutant that is measured or imputed @@ -1799,12 +1861,16 @@ def load_egrid_plant_file(year): ] = egrid_plant.loc[ egrid_plant["plant_primary_fuel"].isin(emissions.CLEAN_FUELS), "co2_mass_lb_for_electricity_adjusted", - ].fillna(0) + ].fillna( + 0 + ) egrid_plant.loc[ egrid_plant["plant_primary_fuel"].isin(emissions.CLEAN_FUELS), "co2_mass_lb" ] = egrid_plant.loc[ egrid_plant["plant_primary_fuel"].isin(emissions.CLEAN_FUELS), "co2_mass_lb" - ].fillna(0) + ].fillna( + 0 + ) # reorder the columns egrid_plant = egrid_plant[ From b4cc46cf8596db2e3ccbafe79e841dc158eb7918 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 16 Dec 2023 11:25:32 -0800 Subject: [PATCH 63/85] update manual tables --- .../default_fuel_sulfur_content.ipynb | 2 +- .../manually_identify_crosswalk_updates.ipynb | 4 +- .../manually_update_OTH_fuel_code.ipynb | 81 +- .../update_steam_units_to_remove.ipynb | 840 ++++++++++++++++++ .../update_utility_name_ba_map.ipynb | 98 +- src/oge/data_cleaning.py | 3 +- src/oge/load_data.py | 29 +- ...> eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv} | 1 + .../utility_name_ba_code_map.csv | 17 +- src/oge/validation.py | 4 +- 10 files changed, 980 insertions(+), 99 deletions(-) create mode 100644 notebooks/manual_data/update_steam_units_to_remove.ipynb rename src/oge/reference_tables/{eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv => eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv} (97%) diff --git a/notebooks/manual_data/default_fuel_sulfur_content.ipynb b/notebooks/manual_data/default_fuel_sulfur_content.ipynb index f7b40abe..75412882 100644 --- a/notebooks/manual_data/default_fuel_sulfur_content.ipynb +++ b/notebooks/manual_data/default_fuel_sulfur_content.ipynb @@ -71,7 +71,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.11.4" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb b/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb index 8e4de0c9..5e5c32c4 100644 --- a/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb +++ b/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb @@ -15,9 +15,7 @@ "metadata": {}, "outputs": [], "source": [ - "import pandas as pd\n", - "import sqlalchemy as sa\n", - "import pudl.output" + "import pandas as pd\n" ] }, { diff --git a/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb b/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb index 4d3e62c0..959e31d4 100644 --- a/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb +++ b/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -19,17 +19,8 @@ "sys.path.append(\"../../src\")\n", "\n", "import oge.load_data as load_data\n", - "import oge.data_cleaning as data_cleaning" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "year = 2021\n", - "pudl_out = load_data.initialize_pudl_out(year=year)" + "import oge.data_cleaning as data_cleaning\n", + "import oge.filepaths as filepaths" ] }, { @@ -38,20 +29,23 @@ "metadata": {}, "outputs": [], "source": [ - "# load the fuel content data and visualize the distribution by fuel\n", - "fuel_heat_content = pudl_out.gf_eia923()[\n", - " [\"plant_id_eia\", \"report_date\", \"energy_source_code\", \"fuel_mmbtu_per_unit\"]\n", - "]\n", + "year = 2022\n", + "\n", + "# load the fuel content data\n", + "fuel_heat_content = load_data.load_pudl_table(\n", + " \"generation_fuel_eia923\",\n", + " year,\n", + " columns=[\n", + " \"plant_id_eia\",\n", + " \"report_date\",\n", + " \"energy_source_code\",\n", + " \"fuel_mmbtu_per_unit\",\n", + " \"fuel_consumed_mmbtu\"\n", + " ],\n", + ")\n", "fuel_heat_content = fuel_heat_content.replace([np.inf, -np.inf], np.nan)\n", "fuel_heat_content = fuel_heat_content.dropna()\n", - "px.box(\n", - " fuel_heat_content.sort_values(by=\"fuel_mmbtu_per_unit\"),\n", - " x=\"energy_source_code\",\n", - " y=\"fuel_mmbtu_per_unit\",\n", - " title=f\"Range of heat contents for each fuel reported in {year}\",\n", - " width=1000,\n", - " height=600,\n", - ")" + "fuel_heat_content" ] }, { @@ -60,10 +54,14 @@ "metadata": {}, "outputs": [], "source": [ + "# identify which plants have an \"OTH\" fuel type with non-zero fuel consumption\n", "plants_with_oth = fuel_heat_content[\n", " fuel_heat_content[\"energy_source_code\"] == \"OTH\"\n", "].copy()\n", - "plants_with_oth = plants_with_oth.groupby(\"plant_id_eia\").mean()\n", + "plants_with_oth = plants_with_oth.groupby(\"plant_id_eia\")[\n", + " [\"fuel_mmbtu_per_unit\", \"fuel_consumed_mmbtu\"]\n", + "].mean().reset_index()\n", + "plants_with_oth = plants_with_oth[plants_with_oth[\"fuel_consumed_mmbtu\"] != 0]\n", "plants_with_oth" ] }, @@ -73,18 +71,11 @@ "metadata": {}, "outputs": [], "source": [ - "fuel_heat_content[fuel_heat_content[\"plant_id_eia\"] == 902]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# load EPA fuel type data\n", - "epa_fuel_types = data_cleaning.get_epa_unit_fuel_types(year)\n", - "epa_fuel_types[epa_fuel_types[\"energy_source_code\"] == \"OTH\"]" + "# load the existing manual fuel map table and check which plants already have been manually matched\n", + "# any plants with a missing `updated_energy_source_code` column need to be manually matched\n", + "manual_table = pd.read_csv(filepaths.reference_table_folder(\"updated_oth_energy_source_codes.csv\"))\n", + "plants_with_oth = plants_with_oth.merge(manual_table, how=\"left\", on=\"plant_id_eia\", validate=\"1:1\")\n", + "plants_with_oth" ] }, { @@ -93,9 +84,17 @@ "metadata": {}, "outputs": [], "source": [ - "# Load EIA-860 to examine whether a plant is retired\n", - "gens_860 = pudl_out.gens_eia860()\n", - "gens_860[gens_860[\"plant_id_eia\"] == 60670]" + "# visualize heat content by fuel\n", + "# to manually match a fuel type, examine the average `fuel_mmbtu_per_unit` from \n", + "# `plants_with_oth` and identify which heat content matches best\n", + "px.box(\n", + " fuel_heat_content.sort_values(by=\"fuel_mmbtu_per_unit\"),\n", + " x=\"energy_source_code\",\n", + " y=\"fuel_mmbtu_per_unit\",\n", + " title=f\"Range of heat contents for each fuel reported in {year}\",\n", + " width=1000,\n", + " height=600,\n", + ")" ] } ], @@ -115,7 +114,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.11.4" }, "orig_nbformat": 4, "vscode": { diff --git a/notebooks/manual_data/update_steam_units_to_remove.ipynb b/notebooks/manual_data/update_steam_units_to_remove.ipynb new file mode 100644 index 00000000..32ff6154 --- /dev/null +++ b/notebooks/manual_data/update_steam_units_to_remove.ipynb @@ -0,0 +1,840 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "# import packages\n", + "import pandas as pd\n", + "import numpy as np\n", + "import os\n", + "\n", + "%reload_ext autoreload\n", + "%autoreload 2\n", + "\n", + "# # Tell python where to look for modules.\n", + "import sys\n", + "sys.path.append(\"../../src/\")\n", + "\n", + "\n", + "import oge.load_data as load_data\n", + "from oge.filepaths import *\n", + "\n", + "year = 2022" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# About\n", + "The purpose of this notebook is to update the `reference_tables/steam_units_to_remove.csv` table.\n", + "This table identifies units in CEMS that do not exist in the EIA data, and which only report steam data." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
plant_id_eiaemissions_unit_id_epadatetime_utcoperating_time_hoursgross_generation_mwhsteam_load_1000_lbfuel_consumed_mmbtuco2_mass_lbnox_mass_lbso2_mass_lbplant_id_epaco2_mass_measurement_codenox_mass_measurement_codeso2_mass_measurement_code
0628822022-01-01 09:00:00+00:001.052.00.0NaNNaNNaNNaN6288<NA><NA><NA>
1628822022-01-01 10:00:00+00:001.052.00.0NaNNaNNaNNaN6288<NA><NA><NA>
2628822022-01-01 11:00:00+00:001.052.00.0NaNNaNNaNNaN6288<NA><NA><NA>
3628822022-01-01 12:00:00+00:001.052.00.0NaNNaNNaNNaN6288<NA><NA><NA>
4628822022-01-01 13:00:00+00:001.052.00.0NaNNaNNaNNaN6288<NA><NA><NA>
.............................................
3514266757703CT032023-01-01 02:00:00+00:000.0NaN0.0NaNNaNNaNNaN57703<NA><NA><NA>
3514266857703CT032023-01-01 03:00:00+00:000.0NaN0.0NaNNaNNaNNaN57703<NA><NA><NA>
3514266957703CT032023-01-01 04:00:00+00:000.0NaN0.0NaNNaNNaNNaN57703<NA><NA><NA>
3514267057703CT032023-01-01 05:00:00+00:000.0NaN0.0NaNNaNNaNNaN57703<NA><NA><NA>
3514267157703CT032023-01-01 06:00:00+00:000.0NaN0.0NaNNaNNaNNaN57703<NA><NA><NA>
\n", + "

35142672 rows × 14 columns

\n", + "
" + ], + "text/plain": [ + " plant_id_eia emissions_unit_id_epa datetime_utc operating_time_hours gross_generation_mwh steam_load_1000_lb fuel_consumed_mmbtu co2_mass_lb nox_mass_lb so2_mass_lb plant_id_epa co2_mass_measurement_code nox_mass_measurement_code so2_mass_measurement_code\n", + "0 6288 2 2022-01-01 09:00:00+00:00 1.0 52.0 0.0 NaN NaN NaN NaN 6288 \n", + "1 6288 2 2022-01-01 10:00:00+00:00 1.0 52.0 0.0 NaN NaN NaN NaN 6288 \n", + "2 6288 2 2022-01-01 11:00:00+00:00 1.0 52.0 0.0 NaN NaN NaN NaN 6288 \n", + "3 6288 2 2022-01-01 12:00:00+00:00 1.0 52.0 0.0 NaN NaN NaN NaN 6288 \n", + "4 6288 2 2022-01-01 13:00:00+00:00 1.0 52.0 0.0 NaN NaN NaN NaN 6288 \n", + "... ... ... ... ... ... ... ... ... ... ... ... ... ... ...\n", + "35142667 57703 CT03 2023-01-01 02:00:00+00:00 0.0 NaN 0.0 NaN NaN NaN NaN 57703 \n", + "35142668 57703 CT03 2023-01-01 03:00:00+00:00 0.0 NaN 0.0 NaN NaN NaN NaN 57703 \n", + "35142669 57703 CT03 2023-01-01 04:00:00+00:00 0.0 NaN 0.0 NaN NaN NaN NaN 57703 \n", + "35142670 57703 CT03 2023-01-01 05:00:00+00:00 0.0 NaN 0.0 NaN NaN NaN NaN 57703 \n", + "35142671 57703 CT03 2023-01-01 06:00:00+00:00 0.0 NaN 0.0 NaN NaN NaN NaN 57703 \n", + "\n", + "[35142672 rows x 14 columns]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cems = load_data.load_cems_data(2022)\n", + "cems" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "cems_units = cems.groupby([\"plant_id_epa\", \"plant_id_eia\", \"emissions_unit_id_epa\"])[\n", + " [\"gross_generation_mwh\", \"steam_load_1000_lb\",\"co2_mass_lb\"]\n", + "].sum().reset_index()\n", + "cems_units = cems_units.merge(generator_unit_map, how=\"left\", on=[\"plant_id_eia\",\"emissions_unit_id_epa\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
plant_id_epaplant_id_eiaemissions_unit_id_epagross_generation_mwhsteam_load_1000_lbco2_mass_lbgenerator_id
367155212552121866882.00.01.131372e+09U1
367255212552122915101.00.01.174157e+09U2
\n", + "
" + ], + "text/plain": [ + " plant_id_epa plant_id_eia emissions_unit_id_epa gross_generation_mwh steam_load_1000_lb co2_mass_lb generator_id\n", + "3671 55212 55212 1 866882.0 0.0 1.131372e+09 U1\n", + "3672 55212 55212 2 915101.0 0.0 1.174157e+09 U2" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cems_units[cems_units[\"plant_id_eia\"] == 55212]" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
plant_id_epaplant_id_eiaemissions_unit_id_epagross_generation_mwhsteam_load_1000_lbco2_mass_lbgenerator_id
72115941594110.0111048.00.000000e+00NaN
72215941594120.0125561.00.000000e+00NaN
75217021702A0.019443.02.688114e+06NaN
75317021702B0.044874.05.821982e+06NaN
109025032503BLR1140.0980786.00.000000e+00NaN
........................
5404880109880109B0010.00.00.000000e+00NaN
540588011088011010.063168.00.000000e+00NaN
540688011088011020.072578.00.000000e+00NaN
540788011088011030.098377.00.000000e+00NaN
540888011088011040.088601.00.000000e+00NaN
\n", + "

150 rows × 7 columns

\n", + "
" + ], + "text/plain": [ + " plant_id_epa plant_id_eia emissions_unit_id_epa gross_generation_mwh steam_load_1000_lb co2_mass_lb generator_id\n", + "721 1594 1594 11 0.0 111048.0 0.000000e+00 NaN\n", + "722 1594 1594 12 0.0 125561.0 0.000000e+00 NaN\n", + "752 1702 1702 A 0.0 19443.0 2.688114e+06 NaN\n", + "753 1702 1702 B 0.0 44874.0 5.821982e+06 NaN\n", + "1090 2503 2503 BLR114 0.0 980786.0 0.000000e+00 NaN\n", + "... ... ... ... ... ... ... ...\n", + "5404 880109 880109 B001 0.0 0.0 0.000000e+00 NaN\n", + "5405 880110 880110 1 0.0 63168.0 0.000000e+00 NaN\n", + "5406 880110 880110 2 0.0 72578.0 0.000000e+00 NaN\n", + "5407 880110 880110 3 0.0 98377.0 0.000000e+00 NaN\n", + "5408 880110 880110 4 0.0 88601.0 0.000000e+00 NaN\n", + "\n", + "[150 rows x 7 columns]" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cems_units[cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] == 0)]" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "crosswalk = load_data.load_pudl_table(\"epacamd_eia\")" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
report_yearplant_id_epaemissions_unit_id_epagenerator_id_epaplant_id_eiaboiler_idgenerator_id
48512018552121U155212U1U1
48522018552122U255212U2U2
111882021552121U155212U1U1
111892021552122U255212U2U2
\n", + "
" + ], + "text/plain": [ + " report_year plant_id_epa emissions_unit_id_epa generator_id_epa plant_id_eia boiler_id generator_id\n", + "4851 2018 55212 1 U1 55212 U1 U1\n", + "4852 2018 55212 2 U2 55212 U2 U2\n", + "11188 2021 55212 1 U1 55212 U1 U1\n", + "11189 2021 55212 2 U2 55212 U2 U2" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "crosswalk[crosswalk[\"plant_id_eia\"] == 55212]" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "generator_unit_map = pd.read_csv(\n", + " outputs_folder(f\"{year}/subplant_crosswalk_{year}.csv\"),\n", + " )[[\"plant_id_eia\", \"generator_id\", \"emissions_unit_id_epa\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
plant_id_eiagenerator_idemissions_unit_id_epa
015.1NaN
113NaN
211NaN
312NaN
415NaN
............
33627880109NaNB001
33628880110NaN1
33629880110NaN2
33630880110NaN3
33631880110NaN4
\n", + "

33632 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " plant_id_eia generator_id emissions_unit_id_epa\n", + "0 1 5.1 NaN\n", + "1 1 3 NaN\n", + "2 1 1 NaN\n", + "3 1 2 NaN\n", + "4 1 5 NaN\n", + "... ... ... ...\n", + "33627 880109 NaN B001\n", + "33628 880110 NaN 1\n", + "33629 880110 NaN 2\n", + "33630 880110 NaN 3\n", + "33631 880110 NaN 4\n", + "\n", + "[33632 rows x 3 columns]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "generator_unit_map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "eia_" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "open-grid-emissions-QkuIZ37I", + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/manual_data/update_utility_name_ba_map.ipynb b/notebooks/manual_data/update_utility_name_ba_map.ipynb index 736e07ac..b6f96f22 100644 --- a/notebooks/manual_data/update_utility_name_ba_map.ipynb +++ b/notebooks/manual_data/update_utility_name_ba_map.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -10,7 +10,7 @@ "import pandas as pd\n", "import numpy as np\n", "import os\n", - "import plotly.express as px\n", + "#import plotly.express as px\n", "\n", "%reload_ext autoreload\n", "%autoreload 2\n", @@ -35,19 +35,31 @@ "metadata": {}, "outputs": [], "source": [ - "pudl_out = load_data.initialize_pudl_out(year=year)\n", - "\n", - "plant_ba = pudl_out.plants_eia860().loc[\n", - " :,\n", - " [\n", + "plant_ba = load_data.load_pudl_table(\n", + " \"plants_eia860\",\n", + " year,\n", + " columns=[\n", " \"plant_id_eia\",\n", " \"balancing_authority_code_eia\",\n", " \"balancing_authority_name_eia\",\n", - " \"utility_name_eia\",\n", + " \"utility_id_eia\",\n", " \"transmission_distribution_owner_name\",\n", - " \"state\",\n", " ],\n", - "]\n", + ")\n", + "# merge utility name\n", + "utilities_eia = load_data.load_pudl_table(\n", + " \"utilities_eia\", columns=[\"utility_id_eia\", \"utility_name_eia\"]\n", + ")\n", + "plant_ba = plant_ba.merge(\n", + " utilities_eia, how=\"left\", on=\"utility_id_eia\", validate=\"m:1\"\n", + ")\n", + "# merge plant state\n", + "plant_states = load_data.load_pudl_table(\n", + " \"plants_entity_eia\", columns=[\"plant_id_eia\", \"state\"]\n", + ")\n", + "plant_ba = plant_ba.merge(\n", + " plant_states, how=\"left\", on=\"plant_id_eia\", validate=\"m:1\"\n", + ")\n", "\n", "# convert the dtype of the balancing authority code column from string to object\n", "# this will allow for missing values to be filled\n", @@ -58,8 +70,19 @@ " \"balancing_authority_code_eia\"\n", "].fillna(value=np.NaN)\n", "\n", + "# load the ba name reference\n", + "ba_name_to_ba_code = pd.read_csv(reference_table_folder(\"ba_reference.csv\"))\n", + "ba_name_to_ba_code = dict(\n", + " zip(\n", + " ba_name_to_ba_code[\"ba_name\"],\n", + " ba_name_to_ba_code[\"ba_code\"],\n", + " )\n", + ")\n", + "\n", "# specify a ba code for certain utilities\n", - "utility_as_ba_code = pd.read_csv(manual_folder(\"utility_name_ba_code_map.csv\"))\n", + "utility_as_ba_code = pd.read_csv(\n", + " reference_table_folder(\"utility_name_ba_code_map.csv\")\n", + ")\n", "utility_as_ba_code = dict(\n", " zip(\n", " utility_as_ba_code[\"name\"],\n", @@ -70,6 +93,9 @@ "# fill missing BA codes first based on the BA name, then utility name, then on the transmisison owner name\n", "plant_ba[\"balancing_authority_code_eia\"] = plant_ba[\n", " \"balancing_authority_code_eia\"\n", + "].fillna(plant_ba[\"balancing_authority_name_eia\"].map(ba_name_to_ba_code))\n", + "plant_ba[\"balancing_authority_code_eia\"] = plant_ba[\n", + " \"balancing_authority_code_eia\"\n", "].fillna(plant_ba[\"balancing_authority_name_eia\"].map(utility_as_ba_code))\n", "plant_ba[\"balancing_authority_code_eia\"] = plant_ba[\n", " \"balancing_authority_code_eia\"\n", @@ -85,40 +111,24 @@ "metadata": {}, "outputs": [], "source": [ - "# what are all the utility names not mapped to a BA?\n", - "list(\n", - " plant_ba.loc[\n", - " plant_ba[\"balancing_authority_code_eia\"].isna(), \"utility_name_eia\"\n", - " ].unique()\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# what are all the utility names not mapped to a BA?\n", - "list(\n", - " plant_ba.loc[\n", - " plant_ba[\"balancing_authority_code_eia\"].isna(),\n", - " \"transmission_distribution_owner_name\",\n", - " ].unique()\n", + "# what are all the utility names and td owner names not mapped to a BA?\n", + "# look through the list and make sure none overlap with balancing authority names\n", + "sorted(\n", + " list(\n", + " pd.concat(\n", + " [\n", + " plant_ba.loc[\n", + " plant_ba[\"balancing_authority_code_eia\"].isna(),\n", + " \"transmission_distribution_owner_name\",\n", + " ].dropna(),\n", + " plant_ba.loc[\n", + " plant_ba[\"balancing_authority_code_eia\"].isna(), \"utility_name_eia\"\n", + " ].dropna(),\n", + " ]\n", + " ).unique()\n", + " )\n", ")" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plant_ba[\n", - " plant_ba[\"balancing_authority_code_eia\"].isna()\n", - " & (plant_ba[\"utility_name_eia\"] == \"Pacific Gas & Electric Co\")\n", - "]" - ] } ], "metadata": { @@ -137,7 +147,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.11.4" }, "orig_nbformat": 4, "vscode": { diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index 524437ac..559a0235 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -1002,7 +1002,8 @@ def clean_cems(year: int, small: bool, primary_fuel_table, subplant_emission_fac ) # manually remove steam-only units - cems = manually_remove_steam_units(cems) + #NOTE(greg): disabling this for the 2022 data release + #cems = manually_remove_steam_units(cems) # add a report date cems = load_data.add_report_date(cems) diff --git a/src/oge/load_data.py b/src/oge/load_data.py index 6e8d8178..3e646372 100644 --- a/src/oge/load_data.py +++ b/src/oge/load_data.py @@ -215,7 +215,7 @@ def add_report_date(df): # convert UTC to the local timezone for tz in timezones: - tz_mask = (df["timezone"] == tz) # find all rows where the tz matches + tz_mask = df["timezone"] == tz # find all rows where the tz matches with warnings.catch_warnings(): warnings.filterwarnings( "ignore", @@ -479,6 +479,33 @@ def load_epa_eia_crosswalk(year): axis=0, ) + # load eGRID plant mapping + egrid_plant_map = pd.read_csv( + reference_table_folder("eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv"), + dtype=get_dtypes(), + ).drop(columns=["plant_id_egrid"]) + + # concat this data with the main table + crosswalk = pd.concat( + [crosswalk, egrid_plant_map], + axis=0, + ) + + # drop duplicate crosswalks + # pudl now includes crosswalks related to multiple report years + # keep the newest mapping + crosswalk = crosswalk.drop_duplicates( + subset=[ + "plant_id_epa", + "emissions_unit_id_epa", + "generator_id_epa", + "plant_id_eia", + "boiler_id", + "generator_id", + ], + keep="last", + ) + # load EIA-860 data gen_ids = load_pudl_table( "generators_eia860", year, columns=["plant_id_eia", "generator_id"] diff --git a/src/oge/reference_tables/eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv b/src/oge/reference_tables/eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv similarity index 97% rename from src/oge/reference_tables/eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv rename to src/oge/reference_tables/eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv index 888a66e6..fd5f95ec 100644 --- a/src/oge/reference_tables/eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv +++ b/src/oge/reference_tables/eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv @@ -9,6 +9,7 @@ 58697,2713,2713 7512,3612,3612 7799,4076,4076 +2518,7146,7146 7294,7254,7254 7268,7258,7258 55545,7762,7762 diff --git a/src/oge/reference_tables/utility_name_ba_code_map.csv b/src/oge/reference_tables/utility_name_ba_code_map.csv index b186f205..21e97193 100644 --- a/src/oge/reference_tables/utility_name_ba_code_map.csv +++ b/src/oge/reference_tables/utility_name_ba_code_map.csv @@ -2,29 +2,34 @@ name,ba_code Anchorage Municipal Light and Power,AMPL Arizona Public Service Co,AZPS "Associated Electric Coop, Inc",AECI -Avista Corp,AVA Avangrid Renewables Inc,AVRN -Bonneville Power Administration,BPAT +Avista Corp,AVA Bonneville Power Admin,BPAT +Bonneville Power Administration,BPAT Chugach Electric Assn Inc,CEA +City of Homestead - (FL),HST "Duke Energy Carolinas, LLC",DUK "Duke Energy Florida, Inc",FPC "Duke Energy Florida, LLC",FPC +"Duke Energy Indiana, LLC",MISO Duke Energy Progress - (NC),CPLE El Paso Electric Co,EPE Florida Power & Light Co,FPL Florida Power & Light Co,FPL Gainesville Regional Utilities,GVL -Hawaiian Electric Co Inc,HECO +Georgia Power Co,SOCO Hawaii Electric Light Co Inc,HECO -City of Homestead - (FL),HST +Hawaiian Electric Co Inc,HECO Imperial Irrigation District,IID JEA,JEA Kentucky Utilities Co,LGEE Los Angeles Department of Water & Power,LDWP Louisville Gas & Electric Co,LGEE +Mississippi Power Co,SOCO Nevada Power Co,NEVP New Smyrna Beach City of,NSB +Northern States Power Co,MISO +Northern States Power Co - Minnesota,MISO NorthWestern Corporation,NWMT NorthWestern Energy,NWMT NorthWestern Energy - (SD),NWMT @@ -43,12 +48,12 @@ Puget Sound Energy Inc,PSEI Sacramento Municipal Util Dist,BANC Salt River Project,SRP Seminole Electric Cooperative Inc,SEC -South Carolina Electric&Gas Company,SCEG South Carolina Electric & Gas Co,SCEG South Carolina Electric & Gas Co,SCEG South Carolina Electric&Gas Company,SCEG -South Carolina Public Service Authority,SC +South Carolina Electric&Gas Company,SCEG South Carolina Public Service Auth,SC +South Carolina Public Service Authority,SC Southwestern Power Administration,SPA Tacoma City of,TPWR Tampa Electric Co,TEC diff --git a/src/oge/validation.py b/src/oge/validation.py index 3ded8cca..f1c12c2f 100644 --- a/src/oge/validation.py +++ b/src/oge/validation.py @@ -1932,7 +1932,7 @@ def add_egrid_plant_id(df, from_id, to_id): # however, there are sometime 2 EIA IDs for a single eGRID ID, so we need to group the data in the EIA table by the egrid id # We need to update all of the egrid plant IDs to the EIA plant IDs egrid_crosswalk = pd.read_csv( - reference_table_folder("eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv"), + reference_table_folder("eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv"), dtype=get_dtypes(), ) id_map = dict( @@ -2458,7 +2458,7 @@ def identify_potential_missing_fuel_in_egrid(year, egrid_plant, cems): # add egrid plant ids egrid_crosswalk = pd.read_csv( - reference_table_folder("eGRID2020_crosswalk_of_EIA_ID_to_EPA_ID.csv") + reference_table_folder("eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv") ) eia_to_egrid_id = dict( zip( From be1aecefcc2fdb21f9c71fcd95b85be63e5046b7 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 16 Dec 2023 14:30:21 -0800 Subject: [PATCH 64/85] manual epa eia mapping --- .../manually_identify_crosswalk_updates.ipynb | 265 ++---- .../update_steam_units_to_remove.ipynb | 838 +++++++++++++----- src/oge/data_cleaning.py | 41 +- src/oge/load_data.py | 49 +- .../eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv | 1 - .../epa_eia_crosswalk_manual.csv | 48 + 6 files changed, 817 insertions(+), 425 deletions(-) diff --git a/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb b/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb index 5e5c32c4..bdcd09b7 100644 --- a/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb +++ b/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb @@ -15,16 +15,31 @@ "metadata": {}, "outputs": [], "source": [ - "import pandas as pd\n" + "# import packages\n", + "import pandas as pd\n", + "import numpy as np\n", + "import os\n", + "\n", + "%reload_ext autoreload\n", + "%autoreload 2\n", + "\n", + "# # Tell python where to look for modules.\n", + "import sys\n", + "sys.path.append(\"../../src/\")\n", + "\n", + "\n", + "import oge.load_data as load_data\n", + "from oge.filepaths import *\n", + "import oge.data_cleaning as data_cleaning\n", + "\n", + "year = 2022" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "year = 2020" + "### Identify CEMS Units that are not mapped to EIA" ] }, { @@ -33,41 +48,39 @@ "metadata": {}, "outputs": [], "source": [ - "# load raw cems data\n", - "cems_path = f\"../data/downloads/pudl/pudl_data/parquet/epacems/year={year}\"\n", - "cems = pd.read_parquet(cems_path).rename(\n", - " columns={\n", - " \"plant_id_eia\": \"plant_id_epa\",\n", - " \"heat_content_mmbtu\": \"fuel_consumed_mmbtu\",\n", - " }\n", + "# load cems data\n", + "cems = load_data.load_cems_data(year)\n", + "# remove non-grid connected plants\n", + "cems = data_cleaning.remove_plants(\n", + " cems,\n", + " non_grid_connected=True,\n", + " remove_states=[\"PR\"],\n", + " steam_only_plants=False,\n", + " distribution_connected_plants=False,\n", ")\n", "\n", - "# load crosswalk data\n", - "crosswalk = pudl.output.epacems.epa_crosswalk()\n", + "# load the unit to generator mapping from the subplant crosswalk\n", + "# NOTE: you will need to run this in the pipeline first\n", + "generator_unit_map = pd.read_csv(\n", + " outputs_folder(f\"{year}/subplant_crosswalk_{year}.csv\"),\n", + ")[[\"plant_id_epa\", \"generator_id\", \"emissions_unit_id_epa\"]]\n", "\n", - "# load eia-860 data\n", - "pudl_db = \"sqlite:///../data/downloads/pudl/pudl_data/sqlite/pudl.sqlite\"\n", - "pudl_engine = sa.create_engine(pudl_db)\n", - "pudl_out = pudl.output.pudltabl.PudlTabl(\n", - " pudl_engine, freq=\"MS\", start_date=f\"{year}-01-01\", end_date=f\"{year}-12-31\"\n", + "# sum operational data by unit and merge the generator map\n", + "cems_units = (\n", + " cems.groupby([\"plant_id_epa\", \"plant_id_eia\", \"emissions_unit_id_epa\"])[\n", + " [\n", + " \"gross_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"steam_load_1000_lb\",\n", + " \"co2_mass_lb\",\n", + " ]\n", + " ]\n", + " .sum()\n", + " .reset_index()\n", ")\n", - "gens_860 = pudl_out.gens_eia860()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ids = cems[[\"plant_id_epa\", \"emissions_unit_id_epa\"]].drop_duplicates()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Complete list of non grid connected plants" + "cems_units = cems_units.merge(\n", + " generator_unit_map, how=\"left\", on=[\"plant_id_epa\", \"emissions_unit_id_epa\"]\n", + ")" ] }, { @@ -76,12 +89,8 @@ "metadata": {}, "outputs": [], "source": [ - "# get the list of plant_id_eia from the static table\n", - "ngc_plants = list(\n", - " pd.read_csv(\n", - " \"../data/manual/egrid_static_tables/table_4-2_plants_not_connected_to_grid.csv\"\n", - " )[\"Plant ID\"]\n", - ")" + "# identify units that are not mapped to a generator and have non-zero generation\n", + "cems_units[cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] > 0)]" ] }, { @@ -90,26 +99,15 @@ "metadata": {}, "outputs": [], "source": [ - "ids[ids[\"plant_id_epa\"].isin(ngc_plants)].to_clipboard()" + "# identify units that are not mapped to a generator and have non-zero generation\n", + "cems_units[cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] == 0)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "# Identify where there is no EIA plant that matches the EPA plant" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "missing_eia = crosswalk[\n", - " ~crosswalk[\"CAMD_PLANT_ID\"].isna() & crosswalk[\"EIA_PLANT_ID\"].isna()\n", - "]\n", - "missing_eia" + "### Investigate matches for a specific plant" ] }, { @@ -118,95 +116,36 @@ "metadata": {}, "outputs": [], "source": [ - "missing_ids = missing_eia[\n", - " [\"CAMD_PLANT_ID\", \"CAMD_UNIT_ID\", \"CAMD_GENERATOR_ID\"]\n", - "].drop_duplicates()\n", - "\n", - "missing_ids = missing_ids.merge(\n", - " gens_860[[\"plant_id_eia\", \"generator_id\"]],\n", - " how=\"left\",\n", - " left_on=[\"CAMD_PLANT_ID\", \"CAMD_UNIT_ID\"],\n", - " right_on=[\"plant_id_eia\", \"generator_id\"],\n", - ")\n", - "missing_ids = missing_ids.merge(\n", - " gens_860[[\"plant_id_eia\", \"generator_id\"]],\n", - " how=\"left\",\n", - " left_on=[\"CAMD_PLANT_ID\", \"CAMD_GENERATOR_ID\"],\n", - " right_on=[\"plant_id_eia\", \"generator_id\"],\n", - " suffixes=(\"_u\", \"_g\"),\n", - ")\n", - "\n", - "# identify the source of the data\n", - "missing_ids[\"source\"] = \"\"\n", - "missing_ids.loc[\n", - " ~missing_ids[\"plant_id_eia_u\"].isna(), \"source\"\n", - "] = \"CAMD_UNIT_ID matches EIA_GENERATOR_ID\"\n", - "missing_ids.loc[\n", - " ~missing_ids[\"plant_id_eia_g\"].isna(), \"source\"\n", - "] = \"CAMD_GENERATOR_ID matches EIA_GENERATOR_ID\"\n", - "\n", - "# fill nas in each group so that we can identify where values match\n", - "missing_ids[\"generator_id_u\"] = missing_ids[\"generator_id_u\"].fillna(\n", - " missing_ids[\"generator_id_g\"]\n", + "# load data that will help with exploration\n", + "gens860 = load_data.load_pudl_table(\n", + " \"generators_eia860\",\n", + " year,\n", + " columns=[\n", + " \"plant_id_eia\",\n", + " \"generator_id\",\n", + " \"operational_status\",\n", + " \"current_planned_generator_operating_date\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code_1\",\n", + " \"energy_source_code_2\",\n", + " ],\n", ")\n", - "missing_ids[\"generator_id_g\"] = missing_ids[\"generator_id_g\"].fillna(\n", - " missing_ids[\"generator_id_u\"]\n", + "plants_entity_eia = load_data.load_pudl_table(\n", + " \"plants_entity_eia\",\n", + " columns=[\"plant_id_eia\", \"plant_name_eia\", \"street_address\", \"city\", \"county\", \"state\"],\n", ")\n", + "gens860 = gens860.merge(plants_entity_eia, how=\"left\", on=\"plant_id_eia\")\n", "\n", - "missing_ids[\"plant_id_eia_u\"] = missing_ids[\"plant_id_eia_u\"].fillna(\n", - " missing_ids[\"plant_id_eia_g\"]\n", - ")\n", - "missing_ids[\"plant_id_eia_g\"] = missing_ids[\"plant_id_eia_g\"].fillna(\n", - " missing_ids[\"plant_id_eia_u\"]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# identify where we identified a consistent generator match\n", - "unit_manual_match = (\n", - " (missing_ids[missing_ids[\"generator_id_u\"] == missing_ids[\"generator_id_g\"]])\n", - " .drop(columns=[\"plant_id_eia_g\", \"generator_id_g\"])\n", - " .rename(\n", - " columns={\"plant_id_eia_u\": \"plant_id_eia\", \"generator_id_u\": \"generator_id\"}\n", + "gen_fuel_allocated = (\n", + " load_data.load_pudl_table(\n", + " \"generation_fuel_by_generator_energy_source_monthly_eia923\", year\n", " )\n", - ")\n", - "unit_manual_match" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "unit_manual_match.to_csv(\"../data/outputs/crosswalk_unit_manual_matches.csv\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# identify where the two matching methods returned different generator matches\n", - "multi_match = missing_ids[\n", - " missing_ids[\"generator_id_u\"] != missing_ids[\"generator_id_g\"]\n", - "]\n", - "multi_match" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "multi_match.to_csv(\"../data/outputs/crosswalk_unit_manual_matches_multi.csv\")" + " .groupby(\n", + " [\"plant_id_eia\", \"generator_id\", \"prime_mover_code\", \"energy_source_code\"]\n", + " )[[\"net_generation_mwh\", \"fuel_consumed_mmbtu\"]]\n", + " .sum()\n", + " .reset_index()\n", + ")" ] }, { @@ -215,14 +154,9 @@ "metadata": {}, "outputs": [], "source": [ - "gens_860[gens_860[\"plant_id_eia\"] == 3443]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Identify units missing from crosswalk" + "plant_id = 2503\n", + "\n", + "cems_units[cems_units[\"plant_id_eia\"] == plant_id]" ] }, { @@ -231,13 +165,7 @@ "metadata": {}, "outputs": [], "source": [ - "missing_from_cw = ids.merge(\n", - " crosswalk[[\"CAMD_PLANT_ID\", \"CAMD_UNIT_ID\"]],\n", - " how=\"left\",\n", - " left_on=[\"plant_id_epa\", \"emissions_unit_id_epa\"],\n", - " right_on=[\"CAMD_PLANT_ID\", \"CAMD_UNIT_ID\"],\n", - ")\n", - "missing_from_cw = missing_from_cw[missing_from_cw[\"CAMD_UNIT_ID\"].isna()]" + "gens860[gens860[\"plant_id_eia\"] == plant_id]" ] }, { @@ -246,19 +174,9 @@ "metadata": {}, "outputs": [], "source": [ - "missing_from_cw = missing_from_cw.merge(\n", - " gens_860[[\"plant_id_eia\", \"generator_id\"]],\n", - " how=\"left\",\n", - " left_on=[\"plant_id_epa\", \"emissions_unit_id_epa\"],\n", - " right_on=[\"plant_id_eia\", \"generator_id\"],\n", - ")\n", - "\n", - "missing_from_cw[\"source\"] = \"\"\n", - "missing_from_cw.loc[\n", - " ~missing_from_cw[\"generator_id\"].isna(), \"source\"\n", - "] = \"CAMD_UNIT_ID matches EIA_GENERATOR_ID\"\n", - "\n", - "missing_from_cw" + "# look and see if there are plants with similar names in the same county\n", + "# sometimes plants split off\n", + "gens860[(gens860[\"county\"] == \"Queens\") & gens860[\"plant_name_eia\"].str.contains(\"Bayswater\")]" ] }, { @@ -267,7 +185,7 @@ "metadata": {}, "outputs": [], "source": [ - "missing_from_cw.to_csv(\"../data/outputs/missing_from_crosswalk.csv\", index=False)" + "gens860[(gens860[\"city\"] == \"New York\")]" ] }, { @@ -276,10 +194,7 @@ "metadata": {}, "outputs": [], "source": [ - "gens_860.loc[\n", - " gens_860[\"plant_id_eia\"] == 55641,\n", - " [\"plant_id_eia\", \"generator_id\", \"prime_mover_code\"],\n", - "]" + "gen_fuel_allocated[gen_fuel_allocated[\"plant_id_eia\"] == plant_id]" ] } ], @@ -302,7 +217,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.4" }, "orig_nbformat": 4 }, diff --git a/notebooks/manual_data/update_steam_units_to_remove.ipynb b/notebooks/manual_data/update_steam_units_to_remove.ipynb index 32ff6154..ca565d54 100644 --- a/notebooks/manual_data/update_steam_units_to_remove.ipynb +++ b/notebooks/manual_data/update_steam_units_to_remove.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 8, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -298,7 +298,18 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "generator_unit_map = pd.read_csv(\n", + " outputs_folder(f\"{year}/subplant_crosswalk_{year}.csv\"),\n", + " )[[\"plant_id_eia\", \"generator_id\", \"emissions_unit_id_epa\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -310,7 +321,115 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
plant_id_epaplant_id_eiaemissions_unit_id_epagross_generation_mwhsteam_load_1000_lbco2_mass_lbgenerator_id
1133153153283821.00.04.000174e+083
1143153154275972.00.04.260050e+084
1153153155110825.00.01.561026e+085
116315315CT11763448.00.01.415544e+09NaN
117315315CT21833818.00.01.473966e+09NaN
\n", + "
" + ], + "text/plain": [ + " plant_id_epa plant_id_eia emissions_unit_id_epa gross_generation_mwh steam_load_1000_lb co2_mass_lb generator_id\n", + "113 315 315 3 283821.0 0.0 4.000174e+08 3\n", + "114 315 315 4 275972.0 0.0 4.260050e+08 4\n", + "115 315 315 5 110825.0 0.0 1.561026e+08 5\n", + "116 315 315 CT1 1763448.0 0.0 1.415544e+09 NaN\n", + "117 315 315 CT2 1833818.0 0.0 1.473966e+09 NaN" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cems_units[cems_units[\"plant_id_eia\"] == 315]" + ] + }, + { + "cell_type": "code", + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -345,24 +464,434 @@ " \n", " \n", " \n", - " 3671\n", - " 55212\n", - " 55212\n", + " 81\n", + " 141\n", + " 141\n", + " 7\n", + " 3048.0\n", + " 0.0\n", + " 2.999672e+06\n", + " NaN\n", + " \n", + " \n", + " 82\n", + " 141\n", + " 141\n", + " 8\n", + " 2649.0\n", + " 0.0\n", + " 2.587676e+06\n", + " NaN\n", + " \n", + " \n", + " 116\n", + " 315\n", + " 315\n", + " CT1\n", + " 1763448.0\n", + " 0.0\n", + " 1.415544e+09\n", + " NaN\n", + " \n", + " \n", + " 117\n", + " 315\n", + " 315\n", + " CT2\n", + " 1833818.0\n", + " 0.0\n", + " 1.473966e+09\n", + " NaN\n", + " \n", + " \n", + " 123\n", + " 335\n", + " 335\n", + " CT1\n", + " 2059491.0\n", + " 0.0\n", + " 1.641396e+09\n", + " NaN\n", + " \n", + " \n", + " 124\n", + " 335\n", + " 335\n", + " CT2\n", + " 2007010.0\n", + " 0.0\n", + " 1.596175e+09\n", + " NaN\n", + " \n", + " \n", + " 302\n", + " 613\n", + " 613\n", + " PFL7A\n", + " 1189258.0\n", + " 0.0\n", + " 1.345747e+09\n", + " NaN\n", + " \n", + " \n", + " 303\n", + " 613\n", + " 613\n", + " PFL7B\n", + " 1357601.0\n", + " 0.0\n", + " 1.530212e+09\n", + " NaN\n", + " \n", + " \n", + " 1793\n", + " 6061\n", + " 6061\n", + " 3\n", + " 106269.0\n", + " 0.0\n", + " 8.501555e+07\n", + " NaN\n", + " \n", + " \n", + " 2680\n", + " 10350\n", + " 10350\n", + " CTGA\n", + " 2229.0\n", + " 0.0\n", + " 2.561142e+06\n", + " NaN\n", + " \n", + " \n", + " 2681\n", + " 10350\n", + " 10350\n", + " CTGB\n", + " 1998.0\n", + " 0.0\n", + " 5.298030e+06\n", + " NaN\n", + " \n", + " \n", + " 2800\n", + " 10776\n", + " 10776\n", + " GTG\n", + " 2722.0\n", + " 0.0\n", + " 4.383388e+06\n", + " NaN\n", + " \n", + " \n", + " 3409\n", + " 55098\n", + " 55098\n", " 1\n", - " 866882.0\n", + " 1734798.0\n", " 0.0\n", - " 1.131372e+09\n", - " U1\n", + " 1.399941e+09\n", + " NaN\n", + " \n", + " \n", + " 3410\n", + " 55098\n", + " 55098\n", + " 2\n", + " 1750618.0\n", + " 0.0\n", + " 1.413555e+09\n", + " NaN\n", + " \n", + " \n", + " 3482\n", + " 55129\n", + " 55129\n", + " DBG4\n", + " 3790.0\n", + " 0.0\n", + " 3.611402e+06\n", + " NaN\n", + " \n", + " \n", + " 3483\n", + " 55129\n", + " 55129\n", + " DBG5\n", + " 4231.0\n", + " 0.0\n", + " 4.175970e+06\n", + " NaN\n", " \n", " \n", - " 3672\n", - " 55212\n", - " 55212\n", + " 4324\n", + " 55460\n", + " 55460\n", + " EUCT1\n", + " 1693386.0\n", + " 0.0\n", + " 1.269812e+09\n", + " NaN\n", + " \n", + " \n", + " 4325\n", + " 55460\n", + " 55460\n", + " EUCT2\n", + " 1676139.0\n", + " 0.0\n", + " 1.260775e+09\n", + " NaN\n", + " \n", + " \n", + " 4569\n", + " 55699\n", + " 55699\n", " 2\n", - " 915101.0\n", + " 72429.0\n", " 0.0\n", - " 1.174157e+09\n", - " U2\n", + " 8.422479e+07\n", + " NaN\n", + " \n", + " \n", + " 4835\n", + " 56298\n", + " 56298\n", + " CT005\n", + " 417.0\n", + " 0.0\n", + " 4.861280e+05\n", + " NaN\n", + " \n", + " \n", + " 4836\n", + " 56298\n", + " 56298\n", + " CT006\n", + " 492.0\n", + " 0.0\n", + " 5.746020e+05\n", + " NaN\n", + " \n", + " \n", + " 4853\n", + " 56350\n", + " 56350\n", + " CT-4A\n", + " 2.0\n", + " 0.0\n", + " 1.229100e+05\n", + " NaN\n", + " \n", + " \n", + " 5289\n", + " 61966\n", + " 61966\n", + " CT1\n", + " 46180.0\n", + " 0.0\n", + " 4.926615e+07\n", + " NaN\n", + " \n", + " \n", + " 5290\n", + " 61966\n", + " 61966\n", + " CT2\n", + " 69861.0\n", + " 0.0\n", + " 7.244601e+07\n", + " NaN\n", + " \n", + " \n", + " 5291\n", + " 62192\n", + " 62192\n", + " 11\n", + " 2395576.0\n", + " 0.0\n", + " 1.832203e+09\n", + " NaN\n", + " \n", + " \n", + " 5292\n", + " 62192\n", + " 62192\n", + " 12\n", + " 2461687.0\n", + " 0.0\n", + " 1.877159e+09\n", + " NaN\n", + " \n", + " \n", + " 5293\n", + " 62548\n", + " 62548\n", + " CT1\n", + " 12003.0\n", + " 0.0\n", + " 1.200281e+07\n", + " NaN\n", + " \n", + " \n", + " 5294\n", + " 62548\n", + " 62548\n", + " CT2\n", + " 10688.0\n", + " 0.0\n", + " 1.063082e+07\n", + " NaN\n", + " \n", + " \n", + " 5296\n", + " 62926\n", + " 62926\n", + " CTG-01\n", + " 2726883.0\n", + " 0.0\n", + " 2.117006e+09\n", + " NaN\n", + " \n", + " \n", + " 5297\n", + " 62926\n", + " 62926\n", + " CTG-02\n", + " 2637462.0\n", + " 0.0\n", + " 2.041643e+09\n", + " NaN\n", + " \n", + " \n", + " 5323\n", + " 64383\n", + " 64383\n", + " CT-1\n", + " 7370.0\n", + " 0.0\n", + " 7.530906e+06\n", + " NaN\n", + " \n", + " \n", + " 5324\n", + " 64383\n", + " 64383\n", + " CT-2\n", + " 25871.0\n", + " 0.0\n", + " 2.794315e+07\n", + " NaN\n", + " \n", + " \n", + " 5325\n", + " 64383\n", + " 64383\n", + " CT-3\n", + " 44498.0\n", + " 0.0\n", + " 5.131757e+07\n", + " NaN\n", + " \n", + " \n", + " 5326\n", + " 64383\n", + " 64383\n", + " CT-4\n", + " 47154.0\n", + " 0.0\n", + " 5.363030e+07\n", + " NaN\n", + " \n", + " \n", + " 5327\n", + " 64383\n", + " 64383\n", + " CT-5\n", + " 47083.0\n", + " 0.0\n", + " 5.422807e+07\n", + " NaN\n", + " \n", + " \n", + " 5328\n", + " 64383\n", + " 64383\n", + " CT-6\n", + " 31170.0\n", + " 0.0\n", + " 3.566296e+07\n", + " NaN\n", + " \n", + " \n", + " 5329\n", + " 64383\n", + " 64383\n", + " CT-7\n", + " 32983.0\n", + " 0.0\n", + " 3.784613e+07\n", + " NaN\n", + " \n", + " \n", + " 5330\n", + " 64383\n", + " 64383\n", + " CT-8\n", + " 32519.0\n", + " 0.0\n", + " 3.769657e+07\n", + " NaN\n", + " \n", + " \n", + " 5333\n", + " 65372\n", + " 65372\n", + " CT-1\n", + " 2671.0\n", + " 0.0\n", + " 2.826774e+06\n", + " NaN\n", + " \n", + " \n", + " 5334\n", + " 65372\n", + " 65372\n", + " CT-2\n", + " 1854.0\n", + " 0.0\n", + " 1.795638e+06\n", + " NaN\n", + " \n", + " \n", + " 5335\n", + " 65372\n", + " 65372\n", + " CT-3\n", + " 2902.0\n", + " 0.0\n", + " 2.957624e+06\n", + " NaN\n", + " \n", + " \n", + " 5384\n", + " 880079\n", + " 880079\n", + " 37\n", + " 208417.0\n", + " 0.0\n", + " 0.000000e+00\n", + " NaN\n", + " \n", + " \n", + " 5385\n", + " 880079\n", + " 880079\n", + " 38\n", + " 176358.0\n", + " 0.0\n", + " 0.000000e+00\n", + " NaN\n", " \n", " \n", "\n", @@ -370,22 +899,63 @@ ], "text/plain": [ " plant_id_epa plant_id_eia emissions_unit_id_epa gross_generation_mwh steam_load_1000_lb co2_mass_lb generator_id\n", - "3671 55212 55212 1 866882.0 0.0 1.131372e+09 U1\n", - "3672 55212 55212 2 915101.0 0.0 1.174157e+09 U2" + "81 141 141 7 3048.0 0.0 2.999672e+06 NaN\n", + "82 141 141 8 2649.0 0.0 2.587676e+06 NaN\n", + "116 315 315 CT1 1763448.0 0.0 1.415544e+09 NaN\n", + "117 315 315 CT2 1833818.0 0.0 1.473966e+09 NaN\n", + "123 335 335 CT1 2059491.0 0.0 1.641396e+09 NaN\n", + "124 335 335 CT2 2007010.0 0.0 1.596175e+09 NaN\n", + "302 613 613 PFL7A 1189258.0 0.0 1.345747e+09 NaN\n", + "303 613 613 PFL7B 1357601.0 0.0 1.530212e+09 NaN\n", + "1793 6061 6061 3 106269.0 0.0 8.501555e+07 NaN\n", + "2680 10350 10350 CTGA 2229.0 0.0 2.561142e+06 NaN\n", + "2681 10350 10350 CTGB 1998.0 0.0 5.298030e+06 NaN\n", + "2800 10776 10776 GTG 2722.0 0.0 4.383388e+06 NaN\n", + "3409 55098 55098 1 1734798.0 0.0 1.399941e+09 NaN\n", + "3410 55098 55098 2 1750618.0 0.0 1.413555e+09 NaN\n", + "3482 55129 55129 DBG4 3790.0 0.0 3.611402e+06 NaN\n", + "3483 55129 55129 DBG5 4231.0 0.0 4.175970e+06 NaN\n", + "4324 55460 55460 EUCT1 1693386.0 0.0 1.269812e+09 NaN\n", + "4325 55460 55460 EUCT2 1676139.0 0.0 1.260775e+09 NaN\n", + "4569 55699 55699 2 72429.0 0.0 8.422479e+07 NaN\n", + "4835 56298 56298 CT005 417.0 0.0 4.861280e+05 NaN\n", + "4836 56298 56298 CT006 492.0 0.0 5.746020e+05 NaN\n", + "4853 56350 56350 CT-4A 2.0 0.0 1.229100e+05 NaN\n", + "5289 61966 61966 CT1 46180.0 0.0 4.926615e+07 NaN\n", + "5290 61966 61966 CT2 69861.0 0.0 7.244601e+07 NaN\n", + "5291 62192 62192 11 2395576.0 0.0 1.832203e+09 NaN\n", + "5292 62192 62192 12 2461687.0 0.0 1.877159e+09 NaN\n", + "5293 62548 62548 CT1 12003.0 0.0 1.200281e+07 NaN\n", + "5294 62548 62548 CT2 10688.0 0.0 1.063082e+07 NaN\n", + "5296 62926 62926 CTG-01 2726883.0 0.0 2.117006e+09 NaN\n", + "5297 62926 62926 CTG-02 2637462.0 0.0 2.041643e+09 NaN\n", + "5323 64383 64383 CT-1 7370.0 0.0 7.530906e+06 NaN\n", + "5324 64383 64383 CT-2 25871.0 0.0 2.794315e+07 NaN\n", + "5325 64383 64383 CT-3 44498.0 0.0 5.131757e+07 NaN\n", + "5326 64383 64383 CT-4 47154.0 0.0 5.363030e+07 NaN\n", + "5327 64383 64383 CT-5 47083.0 0.0 5.422807e+07 NaN\n", + "5328 64383 64383 CT-6 31170.0 0.0 3.566296e+07 NaN\n", + "5329 64383 64383 CT-7 32983.0 0.0 3.784613e+07 NaN\n", + "5330 64383 64383 CT-8 32519.0 0.0 3.769657e+07 NaN\n", + "5333 65372 65372 CT-1 2671.0 0.0 2.826774e+06 NaN\n", + "5334 65372 65372 CT-2 1854.0 0.0 1.795638e+06 NaN\n", + "5335 65372 65372 CT-3 2902.0 0.0 2.957624e+06 NaN\n", + "5384 880079 880079 37 208417.0 0.0 0.000000e+00 NaN\n", + "5385 880079 880079 38 176358.0 0.0 0.000000e+00 NaN" ] }, - "execution_count": 29, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "cems_units[cems_units[\"plant_id_eia\"] == 55212]" + "cems_units[cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] > 0)]" ] }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -551,7 +1121,7 @@ "[150 rows x 7 columns]" ] }, - "execution_count": 26, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -562,7 +1132,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -571,237 +1141,25 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
report_yearplant_id_epaemissions_unit_id_epagenerator_id_epaplant_id_eiaboiler_idgenerator_id
48512018552121U155212U1U1
48522018552122U255212U2U2
111882021552121U155212U1U1
111892021552122U255212U2U2
\n", - "
" - ], - "text/plain": [ - " report_year plant_id_epa emissions_unit_id_epa generator_id_epa plant_id_eia boiler_id generator_id\n", - "4851 2018 55212 1 U1 55212 U1 U1\n", - "4852 2018 55212 2 U2 55212 U2 U2\n", - "11188 2021 55212 1 U1 55212 U1 U1\n", - "11189 2021 55212 2 U2 55212 U2 U2" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "crosswalk[crosswalk[\"plant_id_eia\"] == 55212]" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "generator_unit_map = pd.read_csv(\n", - " outputs_folder(f\"{year}/subplant_crosswalk_{year}.csv\"),\n", - " )[[\"plant_id_eia\", \"generator_id\", \"emissions_unit_id_epa\"]]" - ] + "source": [] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
plant_id_eiagenerator_idemissions_unit_id_epa
015.1NaN
113NaN
211NaN
312NaN
415NaN
............
33627880109NaNB001
33628880110NaN1
33629880110NaN2
33630880110NaN3
33631880110NaN4
\n", - "

33632 rows × 3 columns

\n", - "
" - ], - "text/plain": [ - " plant_id_eia generator_id emissions_unit_id_epa\n", - "0 1 5.1 NaN\n", - "1 1 3 NaN\n", - "2 1 1 NaN\n", - "3 1 2 NaN\n", - "4 1 5 NaN\n", - "... ... ... ...\n", - "33627 880109 NaN B001\n", - "33628 880110 NaN 1\n", - "33629 880110 NaN 2\n", - "33630 880110 NaN 3\n", - "33631 880110 NaN 4\n", - "\n", - "[33632 rows x 3 columns]" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "generator_unit_map" ] diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index 559a0235..391f7212 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -411,9 +411,7 @@ def clean_eia923( """ This is the coordinating function for cleaning and allocating generation and fuel data in EIA-923. """ - # Distribute net generation and heat input data reported by the three different EIA-923 tables - - # allocate net generation and heat input to each generator-fuel grouping + # Load the EIA-923 data that is already allocated to each generator-pm-fuel gen_fuel_allocated = load_data.load_pudl_table( "generation_fuel_by_generator_energy_source_monthly_eia923", year ) @@ -437,6 +435,31 @@ def clean_eia923( ) ] + # drop bad data where there is negative fuel consumption + # NOTE(greg) this is in response to a specific issue with the input data for + # plant 10613 in May 2022, where the data is reported incorrectly in the source + # data from EIA. EIA has been notified to fix this as of 12/15/2023 + for column in ["fuel_consumed_mmbtu","fuel_consumed_for_electricity_mmbtu"]: + bad_fuel_data = gen_fuel_allocated[gen_fuel_allocated[column] < 0] + if len(bad_fuel_data) > 0: + logger.warning("Bad input fuel data detected for the following generators:") + logger.warning( + bad_fuel_data[ + [ + "report_date", + "plant_id_eia", + "generator_id", + "energy_source_code", + "prime_mover_code", + column, + ] + ] + ) + logger.warning("These values will be treated as missing values") + gen_fuel_allocated.loc[ + gen_fuel_allocated[column] < 0, column + ] = np.NaN + # test to make sure allocated totals match input totals validation.check_allocated_gf_matches_input_gf(year, gen_fuel_allocated) @@ -458,7 +481,9 @@ def clean_eia923( "fuel_consumed_mmbtu", "fuel_consumed_for_electricity_mmbtu", ], - ].round(1) + ].round( + 1 + ) validation.test_for_missing_energy_source_code(gen_fuel_allocated) validation.test_for_negative_values(gen_fuel_allocated) @@ -633,7 +658,9 @@ def create_primary_fuel_table(gen_fuel_allocated, add_subplant_id, year): ascending=True, ).drop_duplicates( subset=["plant_id_eia", "subplant_id", "generator_id"], keep="last" - )[["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"]] + )[ + ["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"] + ] if not add_subplant_id: gen_primary_fuel = gen_primary_fuel.drop(columns=["subplant_id"]) @@ -1002,8 +1029,8 @@ def clean_cems(year: int, small: bool, primary_fuel_table, subplant_emission_fac ) # manually remove steam-only units - #NOTE(greg): disabling this for the 2022 data release - #cems = manually_remove_steam_units(cems) + # NOTE(greg): disabling this for the 2022 data release + # cems = manually_remove_steam_units(cems) # add a report date cems = load_data.add_report_date(cems) diff --git a/src/oge/load_data.py b/src/oge/load_data.py index 3e646372..82ec1115 100644 --- a/src/oge/load_data.py +++ b/src/oge/load_data.py @@ -57,6 +57,9 @@ def load_cems_data(year): "UTC" ) + # update the plant_id_eia column using manual matches + cems = update_epa_to_eia_map(cems) + cems = cems.rename( columns={ "operating_datetime_utc": "datetime_utc", @@ -119,11 +122,14 @@ def load_cems_ids(start_year, end_year): cems = pd.read_parquet( downloads_folder("pudl/hourly_emissions_epacems.parquet"), filters=[["year", ">=", start_year], ["year", "<=", end_year]], - columns=["plant_id_eia", "emissions_unit_id_epa"], + columns=["plant_id_epa", "plant_id_eia", "emissions_unit_id_epa"], ).drop_duplicates() cems = apply_pudl_dtypes(cems) - return cems + # update the plant_id_eia column using manual matches + cems = update_epa_to_eia_map(cems) + + return cems[["plant_id_eia", "emissions_unit_id_epa"]] def load_cems_gross_generation(start_year, end_year): @@ -131,6 +137,7 @@ def load_cems_gross_generation(start_year, end_year): # specify the columns to use from the CEMS database cems_columns = [ + "plant_id_epa", "plant_id_eia", "emissions_unit_id_epa", "operating_datetime_utc", @@ -151,6 +158,9 @@ def load_cems_gross_generation(start_year, end_year): "UTC" ) + # update the plant_id_eia column using manual matches + cems = update_epa_to_eia_map(cems) + # only keep values when the plant was operating # this will help speed up calculations and allow us to add this data back later cems = cems[(cems["gross_load_mw"] > 0) | (cems["operating_time_hours"] > 0)] @@ -183,6 +193,41 @@ def load_cems_gross_generation(start_year, end_year): return cems +def update_epa_to_eia_map(cems_df: pd.DataFrame): + """ + Updates the `plant_id_eia` column in cems data loaded from pudl based on the + manual epa_eia_crosswalk_manual table + """ + # load the manual table + manual_plant_map = pd.read_csv( + reference_table_folder("epa_eia_crosswalk_manual.csv"), + dtype=get_dtypes(), + ).drop(columns=["notes"]) + + # only keep rows where the epa and eia plant ids don't match + manual_plant_map = manual_plant_map.loc[ + manual_plant_map["plant_id_epa"] != manual_plant_map["plant_id_eia"], + ["plant_id_epa", "emissions_unit_id_epa", "plant_id_eia"], + ].drop_duplicates() + + # merge into the cems data + cems_df = cems_df.merge( + manual_plant_map, + how="left", + on=["plant_id_epa", "emissions_unit_id_epa"], + suffixes=(None, "_manual"), + validate="m:1", + ) + + # update the eia plant ids + cems_df["plant_id_eia"].update(cems_df["plant_id_eia_manual"]) + + # drop the intermediate column + cems_df = cems_df.drop(columns=["plant_id_eia_manual"]) + + return cems_df + + def add_report_date(df): """ Add a report date column to the cems data based on the plant's local timezone diff --git a/src/oge/reference_tables/eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv b/src/oge/reference_tables/eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv index fd5f95ec..888a66e6 100644 --- a/src/oge/reference_tables/eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv +++ b/src/oge/reference_tables/eGRID_crosswalk_of_EIA_ID_to_EPA_ID.csv @@ -9,7 +9,6 @@ 58697,2713,2713 7512,3612,3612 7799,4076,4076 -2518,7146,7146 7294,7254,7254 7268,7258,7258 55545,7762,7762 diff --git a/src/oge/reference_tables/epa_eia_crosswalk_manual.csv b/src/oge/reference_tables/epa_eia_crosswalk_manual.csv index 6b778f06..0cbac199 100644 --- a/src/oge/reference_tables/epa_eia_crosswalk_manual.csv +++ b/src/oge/reference_tables/epa_eia_crosswalk_manual.csv @@ -95,3 +95,51 @@ plant_id_epa,emissions_unit_id_epa,plant_id_eia,generator_id,notes 63259,DEPS1,63259,DEPS1,Matched based on generator ID 63259,DEPC2,63259,DEPC2,Matched based on generator ID 63259,DEPC3,63259,DEPC3,Matched based on generator ID +315,CT1,62115,1A,"Matched based on plant name, prime mover, and generation. Plant 315 is ""AES Alamitos LLC"" while plant 62115 is ""AES Alamitos Energy Center""" +315,CT1,62115,1S,"Matched based on plant name, prime mover, and generation. Plant 315 is ""AES Alamitos LLC"" while plant 62115 is ""AES Alamitos Energy Center""" +315,CT2,62115,1B,"Matched based on plant name, prime mover, and generation. Plant 315 is ""AES Alamitos LLC"" while plant 62115 is ""AES Alamitos Energy Center""" +315,CT2,62115,1S,"Matched based on plant name, prime mover, and generation. Plant 315 is ""AES Alamitos LLC"" while plant 62115 is ""AES Alamitos Energy Center""" +141,7,141,AF7,Matched based on generator ID +141,8,141,AF8,Matched based on generator ID +335,CT1,62116,1A,"Matched based on plant name, prime mover, and generation. Plant 335 is ""Huntington Beach"" while plant 62115 is ""AES Huntington Beach Energy Project""" +335,CT1,62116,1S,"Matched based on plant name, prime mover, and generation. Plant 335 is ""Huntington Beach"" while plant 62115 is ""AES Huntington Beach Energy Project""" +335,CT2,62116,1B,"Matched based on plant name, prime mover, and generation. Plant 335 is ""Huntington Beach"" while plant 62115 is ""AES Huntington Beach Energy Project""" +335,CT2,62116,1S,"Matched based on plant name, prime mover, and generation. Plant 335 is ""Huntington Beach"" while plant 62115 is ""AES Huntington Beach Energy Project""" +613,PFL7A,65978,7GT1,"Matched based on plant address, generator id, and generation" +613,PFL7A,65978,ST7,"Matched based on plant address, generator id, and generation" +613,PFL7B,65978,7GT2,"Matched based on plant address, generator id, and generation" +613,PFL7B,65978,ST7,"Matched based on plant address, generator id, and generation" +6061,3,6061,MOR1,"Matched based on operational date, and fuel emission factor. New unit at repowered plant" +6061,3,6061,MOR2,"Matched based on operational date, and fuel emission factor. New unit at repowered plant" +10350,CTGA,10350,CTGA,Matched based on generator ID +10350,CTGB,10350,CTGB,Matched based on generator ID +10776,GTG,10776,GTG,Matched based on generator ID +55129,DBG4,55129,CTG4,Matched based on generator ID +55129,DBG5,55129,CTG5,Matched based on generator ID +55460,EUCT1,55460,CT1,Matched based on generator ID and generation +55460,EUCT1,55460,ST1,Matched based on generator ID and generation +55460,EUCT2,55460,CT2,Matched based on generator ID and generation +55460,EUCT2,55460,ST1,Matched based on generator ID and generation +55699,2,56141,2,"Matched based on plant address, generator id, and generation" +56298,CT005,56298,4,"Matched based on generator ID, fuel consumption" +56298,CT006,56298,5,"Matched based on generator ID, fuel consumption" +56350,CT-4A,56350,CT4A,Matched based on generator ID +61966,CT1,61966,VP2-1,"Matched based on generator ID, fuel consumption" +61966,CT2,61966,VP2-2,"Matched based on generator ID, fuel consumption" +62192,11,62192,11,Matched based on generator ID +62192,12,62192,12,Matched based on generator ID +62548,CT1,62548,SJ-1,Matched based on generator ID +62548,CT2,62548,SJ-2,Matched based on generator ID +62926,CTG-01,62926,1,"Matched based on generator ID, fuel consumption" +62926,CTG-02,62926,2,"Matched based on generator ID, fuel consumption" +64383,CT-1,64383,CTG-1,Matched based on generator ID +64383,CT-2,64383,CTG-2,Matched based on generator ID +64383,CT-3,64383,CTG-3,Matched based on generator ID +64383,CT-4,64383,CTG-4,Matched based on generator ID +64383,CT-5,64383,CTG-5,Matched based on generator ID +64383,CT-6,64383,CTG-6,Matched based on generator ID +64383,CT-7,64383,CTG-7,Matched based on generator ID +64383,CT-8,64383,CTG-8,Matched based on generator ID +65372,CT-1,65372,CTG-1,Matched based on generator ID +65372,CT-2,65372,CTG-2,Matched based on generator ID +65372,CT-3,65372,CTG-3,Matched based on generator ID From fcaa139f356de165874677c67ff5aa6f7fcd1b05 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 16 Dec 2023 15:32:31 -0800 Subject: [PATCH 65/85] fix missing nox factors for JF --- .../manually_identify_crosswalk_updates.ipynb | 19 +++- .../manually_update_OTH_fuel_code.ipynb | 22 +++-- .../update_steam_units_to_remove.ipynb | 23 +++-- .../update_utility_name_ba_map.ipynb | 10 +- notebooks/work_in_progress/sandbox.ipynb | 11 +-- src/oge/data_cleaning.py | 14 +-- src/oge/emissions.py | 96 +++++++++++++------ src/oge/gross_to_net_generation.py | 4 +- .../emission_factors_for_nox.csv | 24 +++-- .../emission_factors_for_so2.csv | 1 + src/oge/validation.py | 20 +--- 11 files changed, 149 insertions(+), 95 deletions(-) diff --git a/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb b/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb index bdcd09b7..2e8f0cd1 100644 --- a/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb +++ b/notebooks/manual_data/manually_identify_crosswalk_updates.ipynb @@ -25,6 +25,7 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", + "\n", "sys.path.append(\"../../src/\")\n", "\n", "\n", @@ -100,7 +101,9 @@ "outputs": [], "source": [ "# identify units that are not mapped to a generator and have non-zero generation\n", - "cems_units[cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] == 0)]" + "cems_units[\n", + " cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] == 0)\n", + "]" ] }, { @@ -132,7 +135,14 @@ ")\n", "plants_entity_eia = load_data.load_pudl_table(\n", " \"plants_entity_eia\",\n", - " columns=[\"plant_id_eia\", \"plant_name_eia\", \"street_address\", \"city\", \"county\", \"state\"],\n", + " columns=[\n", + " \"plant_id_eia\",\n", + " \"plant_name_eia\",\n", + " \"street_address\",\n", + " \"city\",\n", + " \"county\",\n", + " \"state\",\n", + " ],\n", ")\n", "gens860 = gens860.merge(plants_entity_eia, how=\"left\", on=\"plant_id_eia\")\n", "\n", @@ -176,7 +186,10 @@ "source": [ "# look and see if there are plants with similar names in the same county\n", "# sometimes plants split off\n", - "gens860[(gens860[\"county\"] == \"Queens\") & gens860[\"plant_name_eia\"].str.contains(\"Bayswater\")]" + "gens860[\n", + " (gens860[\"county\"] == \"Queens\")\n", + " & gens860[\"plant_name_eia\"].str.contains(\"Bayswater\")\n", + "]" ] }, { diff --git a/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb b/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb index 959e31d4..7591100e 100644 --- a/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb +++ b/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb @@ -40,7 +40,7 @@ " \"report_date\",\n", " \"energy_source_code\",\n", " \"fuel_mmbtu_per_unit\",\n", - " \"fuel_consumed_mmbtu\"\n", + " \"fuel_consumed_mmbtu\",\n", " ],\n", ")\n", "fuel_heat_content = fuel_heat_content.replace([np.inf, -np.inf], np.nan)\n", @@ -58,9 +58,13 @@ "plants_with_oth = fuel_heat_content[\n", " fuel_heat_content[\"energy_source_code\"] == \"OTH\"\n", "].copy()\n", - "plants_with_oth = plants_with_oth.groupby(\"plant_id_eia\")[\n", - " [\"fuel_mmbtu_per_unit\", \"fuel_consumed_mmbtu\"]\n", - "].mean().reset_index()\n", + "plants_with_oth = (\n", + " plants_with_oth.groupby(\"plant_id_eia\")[\n", + " [\"fuel_mmbtu_per_unit\", \"fuel_consumed_mmbtu\"]\n", + " ]\n", + " .mean()\n", + " .reset_index()\n", + ")\n", "plants_with_oth = plants_with_oth[plants_with_oth[\"fuel_consumed_mmbtu\"] != 0]\n", "plants_with_oth" ] @@ -73,8 +77,12 @@ "source": [ "# load the existing manual fuel map table and check which plants already have been manually matched\n", "# any plants with a missing `updated_energy_source_code` column need to be manually matched\n", - "manual_table = pd.read_csv(filepaths.reference_table_folder(\"updated_oth_energy_source_codes.csv\"))\n", - "plants_with_oth = plants_with_oth.merge(manual_table, how=\"left\", on=\"plant_id_eia\", validate=\"1:1\")\n", + "manual_table = pd.read_csv(\n", + " filepaths.reference_table_folder(\"updated_oth_energy_source_codes.csv\")\n", + ")\n", + "plants_with_oth = plants_with_oth.merge(\n", + " manual_table, how=\"left\", on=\"plant_id_eia\", validate=\"1:1\"\n", + ")\n", "plants_with_oth" ] }, @@ -85,7 +93,7 @@ "outputs": [], "source": [ "# visualize heat content by fuel\n", - "# to manually match a fuel type, examine the average `fuel_mmbtu_per_unit` from \n", + "# to manually match a fuel type, examine the average `fuel_mmbtu_per_unit` from\n", "# `plants_with_oth` and identify which heat content matches best\n", "px.box(\n", " fuel_heat_content.sort_values(by=\"fuel_mmbtu_per_unit\"),\n", diff --git a/notebooks/manual_data/update_steam_units_to_remove.ipynb b/notebooks/manual_data/update_steam_units_to_remove.ipynb index ca565d54..2f38e999 100644 --- a/notebooks/manual_data/update_steam_units_to_remove.ipynb +++ b/notebooks/manual_data/update_steam_units_to_remove.ipynb @@ -16,6 +16,7 @@ "\n", "# # Tell python where to look for modules.\n", "import sys\n", + "\n", "sys.path.append(\"../../src/\")\n", "\n", "\n", @@ -303,8 +304,8 @@ "outputs": [], "source": [ "generator_unit_map = pd.read_csv(\n", - " outputs_folder(f\"{year}/subplant_crosswalk_{year}.csv\"),\n", - " )[[\"plant_id_eia\", \"generator_id\", \"emissions_unit_id_epa\"]]" + " outputs_folder(f\"{year}/subplant_crosswalk_{year}.csv\"),\n", + ")[[\"plant_id_eia\", \"generator_id\", \"emissions_unit_id_epa\"]]" ] }, { @@ -313,10 +314,16 @@ "metadata": {}, "outputs": [], "source": [ - "cems_units = cems.groupby([\"plant_id_epa\", \"plant_id_eia\", \"emissions_unit_id_epa\"])[\n", - " [\"gross_generation_mwh\", \"steam_load_1000_lb\",\"co2_mass_lb\"]\n", - "].sum().reset_index()\n", - "cems_units = cems_units.merge(generator_unit_map, how=\"left\", on=[\"plant_id_eia\",\"emissions_unit_id_epa\"])" + "cems_units = (\n", + " cems.groupby([\"plant_id_epa\", \"plant_id_eia\", \"emissions_unit_id_epa\"])[\n", + " [\"gross_generation_mwh\", \"steam_load_1000_lb\", \"co2_mass_lb\"]\n", + " ]\n", + " .sum()\n", + " .reset_index()\n", + ")\n", + "cems_units = cems_units.merge(\n", + " generator_unit_map, how=\"left\", on=[\"plant_id_eia\", \"emissions_unit_id_epa\"]\n", + ")" ] }, { @@ -1127,7 +1134,9 @@ } ], "source": [ - "cems_units[cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] == 0)]" + "cems_units[\n", + " cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] == 0)\n", + "]" ] }, { diff --git a/notebooks/manual_data/update_utility_name_ba_map.ipynb b/notebooks/manual_data/update_utility_name_ba_map.ipynb index b6f96f22..3339e900 100644 --- a/notebooks/manual_data/update_utility_name_ba_map.ipynb +++ b/notebooks/manual_data/update_utility_name_ba_map.ipynb @@ -10,7 +10,7 @@ "import pandas as pd\n", "import numpy as np\n", "import os\n", - "#import plotly.express as px\n", + "# import plotly.express as px\n", "\n", "%reload_ext autoreload\n", "%autoreload 2\n", @@ -57,9 +57,7 @@ "plant_states = load_data.load_pudl_table(\n", " \"plants_entity_eia\", columns=[\"plant_id_eia\", \"state\"]\n", ")\n", - "plant_ba = plant_ba.merge(\n", - " plant_states, how=\"left\", on=\"plant_id_eia\", validate=\"m:1\"\n", - ")\n", + "plant_ba = plant_ba.merge(plant_states, how=\"left\", on=\"plant_id_eia\", validate=\"m:1\")\n", "\n", "# convert the dtype of the balancing authority code column from string to object\n", "# this will allow for missing values to be filled\n", @@ -80,9 +78,7 @@ ")\n", "\n", "# specify a ba code for certain utilities\n", - "utility_as_ba_code = pd.read_csv(\n", - " reference_table_folder(\"utility_name_ba_code_map.csv\")\n", - ")\n", + "utility_as_ba_code = pd.read_csv(reference_table_folder(\"utility_name_ba_code_map.csv\"))\n", "utility_as_ba_code = dict(\n", " zip(\n", " utility_as_ba_code[\"name\"],\n", diff --git a/notebooks/work_in_progress/sandbox.ipynb b/notebooks/work_in_progress/sandbox.ipynb index fd2510d2..ba56f332 100644 --- a/notebooks/work_in_progress/sandbox.ipynb +++ b/notebooks/work_in_progress/sandbox.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 24, "metadata": {}, "outputs": [], "source": [ @@ -37,16 +37,9 @@ "logger = get_logger(\"test\")\n", "\n", "\n", - "year = 2020\n", + "year = 2022\n", "path_prefix = f\"{year}/\"" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index 391f7212..8ad5615d 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -439,7 +439,7 @@ def clean_eia923( # NOTE(greg) this is in response to a specific issue with the input data for # plant 10613 in May 2022, where the data is reported incorrectly in the source # data from EIA. EIA has been notified to fix this as of 12/15/2023 - for column in ["fuel_consumed_mmbtu","fuel_consumed_for_electricity_mmbtu"]: + for column in ["fuel_consumed_mmbtu", "fuel_consumed_for_electricity_mmbtu"]: bad_fuel_data = gen_fuel_allocated[gen_fuel_allocated[column] < 0] if len(bad_fuel_data) > 0: logger.warning("Bad input fuel data detected for the following generators:") @@ -456,9 +456,7 @@ def clean_eia923( ] ) logger.warning("These values will be treated as missing values") - gen_fuel_allocated.loc[ - gen_fuel_allocated[column] < 0, column - ] = np.NaN + gen_fuel_allocated.loc[gen_fuel_allocated[column] < 0, column] = np.NaN # test to make sure allocated totals match input totals validation.check_allocated_gf_matches_input_gf(year, gen_fuel_allocated) @@ -481,9 +479,7 @@ def clean_eia923( "fuel_consumed_mmbtu", "fuel_consumed_for_electricity_mmbtu", ], - ].round( - 1 - ) + ].round(1) validation.test_for_missing_energy_source_code(gen_fuel_allocated) validation.test_for_negative_values(gen_fuel_allocated) @@ -658,9 +654,7 @@ def create_primary_fuel_table(gen_fuel_allocated, add_subplant_id, year): ascending=True, ).drop_duplicates( subset=["plant_id_eia", "subplant_id", "generator_id"], keep="last" - )[ - ["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"] - ] + )[["plant_id_eia", "subplant_id", "generator_id", "energy_source_code"]] if not add_subplant_id: gen_primary_fuel = gen_primary_fuel.drop(columns=["subplant_id"]) diff --git a/src/oge/emissions.py b/src/oge/emissions.py index 4f802df7..2b9fe6ab 100644 --- a/src/oge/emissions.py +++ b/src/oge/emissions.py @@ -1462,6 +1462,70 @@ def return_monthly_plant_fuel_sulfur_content(year): Sulfur content values are on a 0-100 scale (e.g. 5.2% = 5.2) """ + plant_specific_fuel_sulfur_content = load_plant_specific_fuel_sulfur_content(year) + + # calculate the average monthly heat content for a fuel + national_avg_fuel_sulfur_content = ( + plant_specific_fuel_sulfur_content.drop(columns=["plant_id_eia"]) + .groupby(["energy_source_code", "report_date"], dropna=False) + .mean(numeric_only=True) + .reset_index() + ) + + annual_avg_fuel_sulfur_content = ( + national_avg_fuel_sulfur_content.groupby(["energy_source_code"], dropna=False) + .mean(numeric_only=True) + .reset_index() + ) + + # if there are any missing annual average values, attempt to fill using data from + # previous years + if annual_avg_fuel_sulfur_content["sulfur_content_pct"].isna().any(): + previous_year_values = load_plant_specific_fuel_sulfur_content((year - 1)) + previous_year_values = ( + previous_year_values.groupby(["energy_source_code"], dropna=False)[ + ["sulfur_content_pct"] + ] + .mean(numeric_only=True) + .reset_index() + ) + annual_avg_fuel_sulfur_content = annual_avg_fuel_sulfur_content.merge( + previous_year_values, + how="left", + on="energy_source_code", + validate="1:1", + suffixes=(None, "_fill"), + ) + annual_avg_fuel_sulfur_content[ + "sulfur_content_pct" + ] = annual_avg_fuel_sulfur_content["sulfur_content_pct"].fillna( + annual_avg_fuel_sulfur_content["sulfur_content_pct_fill"] + ) + annual_avg_fuel_sulfur_content = annual_avg_fuel_sulfur_content.drop( + columns=["sulfur_content_pct_fill"] + ) + + # change the report date columns back to datetimes + plant_specific_fuel_sulfur_content["report_date"] = pd.to_datetime( + plant_specific_fuel_sulfur_content["report_date"] + ).astype("datetime64[s]") + national_avg_fuel_sulfur_content["report_date"] = pd.to_datetime( + national_avg_fuel_sulfur_content["report_date"] + ).astype("datetime64[s]") + + plant_specific_fuel_sulfur_content + + return ( + plant_specific_fuel_sulfur_content, + national_avg_fuel_sulfur_content, + annual_avg_fuel_sulfur_content, + ) + + +def load_plant_specific_fuel_sulfur_content(year: int) -> pd.DataFrame: + """ + Calculates the weighted average sulfur content of each fuel by the fuel consumption + """ plant_specific_fuel_sulfur_content = load_data.load_pudl_table( "boiler_fuel_eia923", year, @@ -1495,35 +1559,7 @@ def return_monthly_plant_fuel_sulfur_content(year): weight_col="fuel_consumed_units", ) - # calculate the average monthly heat content for a fuel - national_avg_fuel_sulfur_content = ( - plant_specific_fuel_sulfur_content.drop(columns=["plant_id_eia"]) - .groupby(["energy_source_code", "report_date"], dropna=False) - .mean(numeric_only=True) - .reset_index() - ) - - annual_avg_fuel_sulfur_content = ( - national_avg_fuel_sulfur_content.groupby(["energy_source_code"], dropna=False) - .mean(numeric_only=True) - .reset_index() - ) - - # change the report date columns back to datetimes - plant_specific_fuel_sulfur_content["report_date"] = pd.to_datetime( - plant_specific_fuel_sulfur_content["report_date"] - ).astype("datetime64[s]") - national_avg_fuel_sulfur_content["report_date"] = pd.to_datetime( - national_avg_fuel_sulfur_content["report_date"] - ).astype("datetime64[s]") - - plant_specific_fuel_sulfur_content - - return ( - plant_specific_fuel_sulfur_content, - national_avg_fuel_sulfur_content, - annual_avg_fuel_sulfur_content, - ) + return plant_specific_fuel_sulfur_content def adjust_so2_efs_for_fuel_sulfur_content(uncontrolled_so2_factors, year): @@ -1575,7 +1611,7 @@ def adjust_so2_efs_for_fuel_sulfur_content(uncontrolled_so2_factors, year): & (uncontrolled_so2_factors["multiply_by_sulfur_content"] == 1) ] if len(missing_sulfur_content) > 0: - logger.warning("Sulfur content data is missing in EIA-923 for the above units.") + logger.warning("Sulfur content data is missing in EIA-923 for the below units.") logger.warning( "\n" + missing_sulfur_content[ diff --git a/src/oge/gross_to_net_generation.py b/src/oge/gross_to_net_generation.py index 2e1f0274..12cddf94 100644 --- a/src/oge/gross_to_net_generation.py +++ b/src/oge/gross_to_net_generation.py @@ -514,7 +514,9 @@ def filter_gtn_conversion_factors(gtn_conversions): for method in method_hierarchy: # get a count of the number of non-na factor values and non-na net generation values for each plant incomplete_factors = ( - factors_to_use.groupby(["plant_id_eia", "data_source"], dropna=False, observed=False) + factors_to_use.groupby( + ["plant_id_eia", "data_source"], dropna=False, observed=False + ) .count()[[method, "net_generation_mwh"]] .reset_index() ) diff --git a/src/oge/reference_tables/emission_factors_for_nox.csv b/src/oge/reference_tables/emission_factors_for_nox.csv index 9417b07d..bb2dc925 100644 --- a/src/oge/reference_tables/emission_factors_for_nox.csv +++ b/src/oge/reference_tables/emission_factors_for_nox.csv @@ -3,14 +3,20 @@ ST,AB,wet,cyclone_firing,1.2,lb,ton ST,AB,none,none,1.2,lb,ton ST,AB,dry,stoker,1.2,lb,ton ST,AB,none,stoker,1.2,lb,ton +OT,AB,dry,none,1.2,lb,ton +OT,AB,wet,none,1.2,lb,ton +OT,AB,none,none,1.2,lb,ton OT,BFG,none,none,0.0154,lb,mcf ST,BFG,none,none,0.0154,lb,mcf +ST,BFG,wet,tangential_firing,0.0154,lb,mcf +ST,BFG,dry,tangential_firing,0.0154,lb,mcf ST,BFG,none,tangential_firing,0.0154,lb,mcf ST,BFG,dry,wall_fired,0.0154,lb,mcf ST,BFG,none,wall_fired,0.0154,lb,mcf CA,BIT,dry,duct_burner,12,lb,ton CA,BIT,none,duct_burner,12,lb,ton CA,BIT,wet,duct_burner,31,lb,ton +CA,BIT,none,none,12,lb,ton ST,BIT,dry,cell_burner,12,lb,ton ST,BIT,dry,cyclone_firing,33,lb,ton ST,BIT,none,cyclone_firing,33,lb,ton @@ -18,7 +24,7 @@ ST,BIT,wet,cyclone_firing,33,lb,ton ST,BIT,dry,fluidized_bed_firing,5,lb,ton ST,BIT,none,fluidized_bed_firing,5,lb,ton ST,BIT,wet,fluidized_bed_firing,5,lb,ton -ST,BIT,none,none,31,lb,ton +ST,BIT,none,none,12,lb,ton ST,BIT,dry,none,12,lb,ton ST,BIT,wet,none,31,lb,ton ST,BIT,dry,other,12,lb,ton @@ -94,6 +100,7 @@ ST,DFO,wet,none,1.008,lb,barrels ST,DFO,dry,other,1.008,lb,barrels ST,DFO,none,other,1.008,lb,barrels ST,DFO,dry,stoker,1.008,lb,barrels +ST,DFO,wet,stoker,1.008,lb,barrels ST,DFO,dry,tangential_firing,1.008,lb,barrels ST,DFO,none,tangential_firing,1.008,lb,barrels ST,DFO,wet,tangential_firing,1.008,lb,barrels @@ -147,6 +154,7 @@ CA,NG,none,duct_burner,0.328,lb,mcf CA,NG,wet,duct_burner,0.328,lb,mcf CA,NG,none,none,0.32,lb,MMBtu CA,NG,dry,other,0.328,lb,mcf +CA,NG,wet,other,0.328,lb,mcf CA,NG,none,other,0.328,lb,mcf CA,NG,none,tangential_firing,0.328,lb,mcf CA,NG,dry,wall_fired,0.328,lb,mcf @@ -165,6 +173,7 @@ CT,NG,none,duct_burner,0.328,lb,mcf CT,NG,wet,duct_burner,0.328,lb,mcf CT,NG,none,none,0.328,lb,mcf CT,NG,dry,other,0.328,lb,mcf +CT,NG,wet,other,0.328,lb,mcf CT,NG,none,other,0.328,lb,mcf CT,NG,none,tangential_firing,0.328,lb,mcf CT,NG,dry,wall_fired,0.328,lb,mcf @@ -295,6 +304,7 @@ ST,PC,dry,wall_fired,21,lb,ton ST,PC,wet,wall_fired,21,lb,ton ST,PC,wet,cyclone_firing,21,lb,ton ST,PC,wet,other,21,lb,ton +ST,PC,dry,stoker,21,lb,ton ST,PC,wet,tangential_firing,21,lb,ton ST,PC,none,wall_fired,21,lb,ton CS,PG,none,none,0.80336,lb,mcf @@ -346,14 +356,16 @@ ST,RFO,dry,vertical_firing,1.974,lb,barrels ST,RFO,dry,wall_fired,1.974,lb,barrels ST,RFO,none,wall_fired,1.974,lb,barrels ST,RFO,wet,wall_fired,1.974,lb,barrels -CA,SGC,none,duct_burner,0.28,lb,mcf -CA,SGC,none,other,0.28,lb,mcf +CA,SGC,none,duct_burner,0.328,lb,mcf +CA,SGC,none,other,0.328,lb,mcf +CA,SGC,none,none,0.328,lb,mcf CT,SGC,none,duct_burner,0.328,lb,mcf CT,SGC,none,other,0.328,lb,mcf +CT,SGC,none,none,0.328,lb,mcf ST,SGC,none,none,0.28,lb,mcf -CA,SGP,none,none,0.28,lb,mcf -CS,SGP,none,none,0.28,lb,mcf -CT,SGP,none,none,0.28,lb,mcf +CA,SGP,none,none,0.328,lb,mcf +CS,SGP,none,none,0.328,lb,mcf +CT,SGP,none,none,0.328,lb,mcf ST,SLW,dry,fluidized_bed_firing,5,lb,ton ST,SLW,wet,fluidized_bed_firing,5,lb,ton ST,SLW,none,none,5,lb,ton diff --git a/src/oge/reference_tables/emission_factors_for_so2.csv b/src/oge/reference_tables/emission_factors_for_so2.csv index d34ee2bd..f61cab06 100644 --- a/src/oge/reference_tables/emission_factors_for_so2.csv +++ b/src/oge/reference_tables/emission_factors_for_so2.csv @@ -90,6 +90,7 @@ ST,BFG,tangential_firing,0.0006,lb,Mcf,0 ST,BFG,vertical_firing,0.0006,lb,Mcf,0 ST,BFG,wall_fired,0.0006,lb,Mcf,0 CA,BIT,duct_burner,38*S,lb,short ton,1 +CA,BIT,none,38*S,lb,short ton,1 OT,BIT,cell_burner,38*S,lb,short ton,1 OT,BIT,cyclone_firing,38*S,lb,short ton,1 OT,BIT,duct_burner,38*S,lb,short ton,1 diff --git a/src/oge/validation.py b/src/oge/validation.py index f1c12c2f..588c54cd 100644 --- a/src/oge/validation.py +++ b/src/oge/validation.py @@ -676,9 +676,7 @@ def ensure_non_overlapping_data_from_all_sources( ["in_eia", "in_cems", "in_partial_cems_subplant", "in_partial_cems_plant"] ] = data_overlap[ ["in_eia", "in_cems", "in_partial_cems_subplant", "in_partial_cems_plant"] - ].fillna( - 0 - ) + ].fillna(0) data_overlap["number_of_locations"] = ( data_overlap["in_eia"] + data_overlap["in_cems"] @@ -1321,9 +1319,7 @@ def summarize_cems_measurement_quality(cems): "so2_mass_measurement_code", "nox_mass_measurement_code", ] - ].astype( - str - ) + ].astype(str) # replace the CEMS mass measurement codes with two categories measurement_code_map = { "Measured": "Measured", @@ -1346,9 +1342,7 @@ def summarize_cems_measurement_quality(cems): "so2_mass_measurement_code", "nox_mass_measurement_code", ] - ].replace( - measurement_code_map - ) + ].replace(measurement_code_map) cems_quality_summary = [] # calculate the percent of mass for each pollutant that is measured or imputed @@ -1861,16 +1855,12 @@ def load_egrid_plant_file(year): ] = egrid_plant.loc[ egrid_plant["plant_primary_fuel"].isin(emissions.CLEAN_FUELS), "co2_mass_lb_for_electricity_adjusted", - ].fillna( - 0 - ) + ].fillna(0) egrid_plant.loc[ egrid_plant["plant_primary_fuel"].isin(emissions.CLEAN_FUELS), "co2_mass_lb" ] = egrid_plant.loc[ egrid_plant["plant_primary_fuel"].isin(emissions.CLEAN_FUELS), "co2_mass_lb" - ].fillna( - 0 - ) + ].fillna(0) # reorder the columns egrid_plant = egrid_plant[ From c58f42fa0a1168caf85501396153d307a2f1d2c6 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 16 Dec 2023 16:12:34 -0800 Subject: [PATCH 66/85] fix futurewarning --- .../update_steam_units_to_remove.ipynb | 1139 +---------------- src/oge/load_data.py | 2 +- 2 files changed, 44 insertions(+), 1097 deletions(-) diff --git a/notebooks/manual_data/update_steam_units_to_remove.ipynb b/notebooks/manual_data/update_steam_units_to_remove.ipynb index 2f38e999..1e893046 100644 --- a/notebooks/manual_data/update_steam_units_to_remove.ipynb +++ b/notebooks/manual_data/update_steam_units_to_remove.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -21,6 +21,7 @@ "\n", "\n", "import oge.load_data as load_data\n", + "import oge.data_cleaning as data_cleaning\n", "from oge.filepaths import *\n", "\n", "year = 2022" @@ -37,1115 +38,58 @@ }, { "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
plant_id_eiaemissions_unit_id_epadatetime_utcoperating_time_hoursgross_generation_mwhsteam_load_1000_lbfuel_consumed_mmbtuco2_mass_lbnox_mass_lbso2_mass_lbplant_id_epaco2_mass_measurement_codenox_mass_measurement_codeso2_mass_measurement_code
0628822022-01-01 09:00:00+00:001.052.00.0NaNNaNNaNNaN6288<NA><NA><NA>
1628822022-01-01 10:00:00+00:001.052.00.0NaNNaNNaNNaN6288<NA><NA><NA>
2628822022-01-01 11:00:00+00:001.052.00.0NaNNaNNaNNaN6288<NA><NA><NA>
3628822022-01-01 12:00:00+00:001.052.00.0NaNNaNNaNNaN6288<NA><NA><NA>
4628822022-01-01 13:00:00+00:001.052.00.0NaNNaNNaNNaN6288<NA><NA><NA>
.............................................
3514266757703CT032023-01-01 02:00:00+00:000.0NaN0.0NaNNaNNaNNaN57703<NA><NA><NA>
3514266857703CT032023-01-01 03:00:00+00:000.0NaN0.0NaNNaNNaNNaN57703<NA><NA><NA>
3514266957703CT032023-01-01 04:00:00+00:000.0NaN0.0NaNNaNNaNNaN57703<NA><NA><NA>
3514267057703CT032023-01-01 05:00:00+00:000.0NaN0.0NaNNaNNaNNaN57703<NA><NA><NA>
3514267157703CT032023-01-01 06:00:00+00:000.0NaN0.0NaNNaNNaNNaN57703<NA><NA><NA>
\n", - "

35142672 rows × 14 columns

\n", - "
" - ], - "text/plain": [ - " plant_id_eia emissions_unit_id_epa datetime_utc operating_time_hours gross_generation_mwh steam_load_1000_lb fuel_consumed_mmbtu co2_mass_lb nox_mass_lb so2_mass_lb plant_id_epa co2_mass_measurement_code nox_mass_measurement_code so2_mass_measurement_code\n", - "0 6288 2 2022-01-01 09:00:00+00:00 1.0 52.0 0.0 NaN NaN NaN NaN 6288 \n", - "1 6288 2 2022-01-01 10:00:00+00:00 1.0 52.0 0.0 NaN NaN NaN NaN 6288 \n", - "2 6288 2 2022-01-01 11:00:00+00:00 1.0 52.0 0.0 NaN NaN NaN NaN 6288 \n", - "3 6288 2 2022-01-01 12:00:00+00:00 1.0 52.0 0.0 NaN NaN NaN NaN 6288 \n", - "4 6288 2 2022-01-01 13:00:00+00:00 1.0 52.0 0.0 NaN NaN NaN NaN 6288 \n", - "... ... ... ... ... ... ... ... ... ... ... ... ... ... ...\n", - "35142667 57703 CT03 2023-01-01 02:00:00+00:00 0.0 NaN 0.0 NaN NaN NaN NaN 57703 \n", - "35142668 57703 CT03 2023-01-01 03:00:00+00:00 0.0 NaN 0.0 NaN NaN NaN NaN 57703 \n", - "35142669 57703 CT03 2023-01-01 04:00:00+00:00 0.0 NaN 0.0 NaN NaN NaN NaN 57703 \n", - "35142670 57703 CT03 2023-01-01 05:00:00+00:00 0.0 NaN 0.0 NaN NaN NaN NaN 57703 \n", - "35142671 57703 CT03 2023-01-01 06:00:00+00:00 0.0 NaN 0.0 NaN NaN NaN NaN 57703 \n", - "\n", - "[35142672 rows x 14 columns]" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cems = load_data.load_cems_data(2022)\n", - "cems" - ] - }, - { - "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "generator_unit_map = pd.read_csv(\n", - " outputs_folder(f\"{year}/subplant_crosswalk_{year}.csv\"),\n", - ")[[\"plant_id_eia\", \"generator_id\", \"emissions_unit_id_epa\"]]" + "# load cems data\n", + "cems = load_data.load_cems_data(year)\n", + "# remove non-grid connected plants\n", + "cems = data_cleaning.remove_plants(\n", + " cems,\n", + " non_grid_connected=True,\n", + " remove_states=[\"PR\"],\n", + " steam_only_plants=False,\n", + " distribution_connected_plants=False,\n", + ")" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ + "# sum operational data by unit and merge the generator map\n", "cems_units = (\n", " cems.groupby([\"plant_id_epa\", \"plant_id_eia\", \"emissions_unit_id_epa\"])[\n", - " [\"gross_generation_mwh\", \"steam_load_1000_lb\", \"co2_mass_lb\"]\n", + " [\n", + " \"gross_generation_mwh\",\n", + " \"fuel_consumed_mmbtu\",\n", + " \"steam_load_1000_lb\",\n", + " \"co2_mass_lb\",\n", + " ]\n", " ]\n", " .sum()\n", " .reset_index()\n", - ")\n", - "cems_units = cems_units.merge(\n", - " generator_unit_map, how=\"left\", on=[\"plant_id_eia\", \"emissions_unit_id_epa\"]\n", ")" ] }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
plant_id_epaplant_id_eiaemissions_unit_id_epagross_generation_mwhsteam_load_1000_lbco2_mass_lbgenerator_id
1133153153283821.00.04.000174e+083
1143153154275972.00.04.260050e+084
1153153155110825.00.01.561026e+085
116315315CT11763448.00.01.415544e+09NaN
117315315CT21833818.00.01.473966e+09NaN
\n", - "
" - ], - "text/plain": [ - " plant_id_epa plant_id_eia emissions_unit_id_epa gross_generation_mwh steam_load_1000_lb co2_mass_lb generator_id\n", - "113 315 315 3 283821.0 0.0 4.000174e+08 3\n", - "114 315 315 4 275972.0 0.0 4.260050e+08 4\n", - "115 315 315 5 110825.0 0.0 1.561026e+08 5\n", - "116 315 315 CT1 1763448.0 0.0 1.415544e+09 NaN\n", - "117 315 315 CT2 1833818.0 0.0 1.473966e+09 NaN" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cems_units[cems_units[\"plant_id_eia\"] == 315]" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
plant_id_epaplant_id_eiaemissions_unit_id_epagross_generation_mwhsteam_load_1000_lbco2_mass_lbgenerator_id
8114114173048.00.02.999672e+06NaN
8214114182649.00.02.587676e+06NaN
116315315CT11763448.00.01.415544e+09NaN
117315315CT21833818.00.01.473966e+09NaN
123335335CT12059491.00.01.641396e+09NaN
124335335CT22007010.00.01.596175e+09NaN
302613613PFL7A1189258.00.01.345747e+09NaN
303613613PFL7B1357601.00.01.530212e+09NaN
1793606160613106269.00.08.501555e+07NaN
26801035010350CTGA2229.00.02.561142e+06NaN
26811035010350CTGB1998.00.05.298030e+06NaN
28001077610776GTG2722.00.04.383388e+06NaN
3409550985509811734798.00.01.399941e+09NaN
3410550985509821750618.00.01.413555e+09NaN
34825512955129DBG43790.00.03.611402e+06NaN
34835512955129DBG54231.00.04.175970e+06NaN
43245546055460EUCT11693386.00.01.269812e+09NaN
43255546055460EUCT21676139.00.01.260775e+09NaN
45695569955699272429.00.08.422479e+07NaN
48355629856298CT005417.00.04.861280e+05NaN
48365629856298CT006492.00.05.746020e+05NaN
48535635056350CT-4A2.00.01.229100e+05NaN
52896196661966CT146180.00.04.926615e+07NaN
52906196661966CT269861.00.07.244601e+07NaN
52916219262192112395576.00.01.832203e+09NaN
52926219262192122461687.00.01.877159e+09NaN
52936254862548CT112003.00.01.200281e+07NaN
52946254862548CT210688.00.01.063082e+07NaN
52966292662926CTG-012726883.00.02.117006e+09NaN
52976292662926CTG-022637462.00.02.041643e+09NaN
53236438364383CT-17370.00.07.530906e+06NaN
53246438364383CT-225871.00.02.794315e+07NaN
53256438364383CT-344498.00.05.131757e+07NaN
53266438364383CT-447154.00.05.363030e+07NaN
53276438364383CT-547083.00.05.422807e+07NaN
53286438364383CT-631170.00.03.566296e+07NaN
53296438364383CT-732983.00.03.784613e+07NaN
53306438364383CT-832519.00.03.769657e+07NaN
53336537265372CT-12671.00.02.826774e+06NaN
53346537265372CT-21854.00.01.795638e+06NaN
53356537265372CT-32902.00.02.957624e+06NaN
538488007988007937208417.00.00.000000e+00NaN
538588007988007938176358.00.00.000000e+00NaN
\n", - "
" - ], - "text/plain": [ - " plant_id_epa plant_id_eia emissions_unit_id_epa gross_generation_mwh steam_load_1000_lb co2_mass_lb generator_id\n", - "81 141 141 7 3048.0 0.0 2.999672e+06 NaN\n", - "82 141 141 8 2649.0 0.0 2.587676e+06 NaN\n", - "116 315 315 CT1 1763448.0 0.0 1.415544e+09 NaN\n", - "117 315 315 CT2 1833818.0 0.0 1.473966e+09 NaN\n", - "123 335 335 CT1 2059491.0 0.0 1.641396e+09 NaN\n", - "124 335 335 CT2 2007010.0 0.0 1.596175e+09 NaN\n", - "302 613 613 PFL7A 1189258.0 0.0 1.345747e+09 NaN\n", - "303 613 613 PFL7B 1357601.0 0.0 1.530212e+09 NaN\n", - "1793 6061 6061 3 106269.0 0.0 8.501555e+07 NaN\n", - "2680 10350 10350 CTGA 2229.0 0.0 2.561142e+06 NaN\n", - "2681 10350 10350 CTGB 1998.0 0.0 5.298030e+06 NaN\n", - "2800 10776 10776 GTG 2722.0 0.0 4.383388e+06 NaN\n", - "3409 55098 55098 1 1734798.0 0.0 1.399941e+09 NaN\n", - "3410 55098 55098 2 1750618.0 0.0 1.413555e+09 NaN\n", - "3482 55129 55129 DBG4 3790.0 0.0 3.611402e+06 NaN\n", - "3483 55129 55129 DBG5 4231.0 0.0 4.175970e+06 NaN\n", - "4324 55460 55460 EUCT1 1693386.0 0.0 1.269812e+09 NaN\n", - "4325 55460 55460 EUCT2 1676139.0 0.0 1.260775e+09 NaN\n", - "4569 55699 55699 2 72429.0 0.0 8.422479e+07 NaN\n", - "4835 56298 56298 CT005 417.0 0.0 4.861280e+05 NaN\n", - "4836 56298 56298 CT006 492.0 0.0 5.746020e+05 NaN\n", - "4853 56350 56350 CT-4A 2.0 0.0 1.229100e+05 NaN\n", - "5289 61966 61966 CT1 46180.0 0.0 4.926615e+07 NaN\n", - "5290 61966 61966 CT2 69861.0 0.0 7.244601e+07 NaN\n", - "5291 62192 62192 11 2395576.0 0.0 1.832203e+09 NaN\n", - "5292 62192 62192 12 2461687.0 0.0 1.877159e+09 NaN\n", - "5293 62548 62548 CT1 12003.0 0.0 1.200281e+07 NaN\n", - "5294 62548 62548 CT2 10688.0 0.0 1.063082e+07 NaN\n", - "5296 62926 62926 CTG-01 2726883.0 0.0 2.117006e+09 NaN\n", - "5297 62926 62926 CTG-02 2637462.0 0.0 2.041643e+09 NaN\n", - "5323 64383 64383 CT-1 7370.0 0.0 7.530906e+06 NaN\n", - "5324 64383 64383 CT-2 25871.0 0.0 2.794315e+07 NaN\n", - "5325 64383 64383 CT-3 44498.0 0.0 5.131757e+07 NaN\n", - "5326 64383 64383 CT-4 47154.0 0.0 5.363030e+07 NaN\n", - "5327 64383 64383 CT-5 47083.0 0.0 5.422807e+07 NaN\n", - "5328 64383 64383 CT-6 31170.0 0.0 3.566296e+07 NaN\n", - "5329 64383 64383 CT-7 32983.0 0.0 3.784613e+07 NaN\n", - "5330 64383 64383 CT-8 32519.0 0.0 3.769657e+07 NaN\n", - "5333 65372 65372 CT-1 2671.0 0.0 2.826774e+06 NaN\n", - "5334 65372 65372 CT-2 1854.0 0.0 1.795638e+06 NaN\n", - "5335 65372 65372 CT-3 2902.0 0.0 2.957624e+06 NaN\n", - "5384 880079 880079 37 208417.0 0.0 0.000000e+00 NaN\n", - "5385 880079 880079 38 176358.0 0.0 0.000000e+00 NaN" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cems_units[cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] > 0)]" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
plant_id_epaplant_id_eiaemissions_unit_id_epagross_generation_mwhsteam_load_1000_lbco2_mass_lbgenerator_id
72115941594110.0111048.00.000000e+00NaN
72215941594120.0125561.00.000000e+00NaN
75217021702A0.019443.02.688114e+06NaN
75317021702B0.044874.05.821982e+06NaN
109025032503BLR1140.0980786.00.000000e+00NaN
........................
5404880109880109B0010.00.00.000000e+00NaN
540588011088011010.063168.00.000000e+00NaN
540688011088011020.072578.00.000000e+00NaN
540788011088011030.098377.00.000000e+00NaN
540888011088011040.088601.00.000000e+00NaN
\n", - "

150 rows × 7 columns

\n", - "
" - ], - "text/plain": [ - " plant_id_epa plant_id_eia emissions_unit_id_epa gross_generation_mwh steam_load_1000_lb co2_mass_lb generator_id\n", - "721 1594 1594 11 0.0 111048.0 0.000000e+00 NaN\n", - "722 1594 1594 12 0.0 125561.0 0.000000e+00 NaN\n", - "752 1702 1702 A 0.0 19443.0 2.688114e+06 NaN\n", - "753 1702 1702 B 0.0 44874.0 5.821982e+06 NaN\n", - "1090 2503 2503 BLR114 0.0 980786.0 0.000000e+00 NaN\n", - "... ... ... ... ... ... ... ...\n", - "5404 880109 880109 B001 0.0 0.0 0.000000e+00 NaN\n", - "5405 880110 880110 1 0.0 63168.0 0.000000e+00 NaN\n", - "5406 880110 880110 2 0.0 72578.0 0.000000e+00 NaN\n", - "5407 880110 880110 3 0.0 98377.0 0.000000e+00 NaN\n", - "5408 880110 880110 4 0.0 88601.0 0.000000e+00 NaN\n", - "\n", - "[150 rows x 7 columns]" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cems_units[\n", - " cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] == 0)\n", - "]" - ] - }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "crosswalk = load_data.load_pudl_table(\"epacamd_eia\")" + "# load the unit to generator mapping from the subplant crosswalk\n", + "# NOTE: you will need to run this in the pipeline first\n", + "generator_unit_map = pd.read_csv(\n", + " outputs_folder(f\"{year}/subplant_crosswalk_{year}.csv\"),\n", + ")[[\"plant_id_epa\", \"generator_id\", \"emissions_unit_id_epa\"]]\n", + "\n", + "cems_units = cems_units.merge(\n", + " generator_unit_map, how=\"left\", on=[\"plant_id_epa\", \"emissions_unit_id_epa\"]\n", + ")" ] }, { @@ -1154,23 +98,21 @@ "metadata": {}, "outputs": [], "source": [ - "crosswalk[crosswalk[\"plant_id_eia\"] == 55212]" + "# identify units that are not mapped to a generator and have non-zero generation\n", + "cems_units[\n", + " cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] == 0)\n", + "]" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "generator_unit_map" + "cems_units[\n", + " (~cems_units[\"generator_id\"].isna()) & (cems_units[\"gross_generation_mwh\"] == 0)\n", + "]" ] }, { @@ -1179,7 +121,12 @@ "metadata": {}, "outputs": [], "source": [ - "eia_" + "cems_units.loc[\n", + " cems_units[\"generator_id\"].isna() & (cems_units[\"gross_generation_mwh\"] == 0),\n", + " [\"plant_id_eia\", \"emissions_unit_id_epa\"],\n", + "].drop_duplicates().to_csv(\n", + " reference_table_folder(\"steam_units_to_remove.csv\", index=False)\n", + ")" ] } ], diff --git a/src/oge/load_data.py b/src/oge/load_data.py index 82ec1115..4a83cf0f 100644 --- a/src/oge/load_data.py +++ b/src/oge/load_data.py @@ -253,7 +253,7 @@ def add_report_date(df): datetime_utc = pd.DatetimeIndex(df["datetime_utc"]) # create blank column to hold local datetimes - df["report_date"] = np.NaN + df["report_date"] = pd.to_datetime(np.NaN) # get list of unique timezones timezones = list(df["timezone"].unique()) From 2eaa0238581d257ddc2123a7103a84818542db96 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Wed, 20 Dec 2023 09:46:19 -0800 Subject: [PATCH 67/85] update consumed calcs for 2022 --- src/oge/consumed.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/oge/consumed.py b/src/oge/consumed.py index cdf7bdb3..07ae1727 100644 --- a/src/oge/consumed.py +++ b/src/oge/consumed.py @@ -25,10 +25,13 @@ which results in unreasonable profiles with many negative hours. """ # Identify the BAs for which we need to use demand data for the consumed calculation +# To identify these, run the pipeline, and if the validation checks raise any negative +# consumed emissions rates for a region, add those to this list. BA_930_INCONSISTENCY = { 2019: ["CPLW", "EEI"], 2020: ["CPLW", "EEI"], 2021: ["CPLW", "GCPD"], + 2022: ["CPLW", "GCPD", "HST"], } # Defined in output_data, written to each BA file @@ -438,13 +441,13 @@ def _load_rates(self): axis=1, ) - # Cut off emissions at 9 hours after UTC year - emissions = emissions[: f"{self.year+1}-01-01 09:00:00+00:00"] + # Cut off emissions at 8 hours after UTC year + emissions = emissions[: f"{self.year+1}-01-01 08:00:00+00:00"] rates[(adj, pol)] = emissions # Make generation data frame generation = pd.DataFrame(data=gens) - generation = generation[: f"{self.year+1}-01-01 09:00:00+00:00"] + generation = generation[: f"{self.year+1}-01-01 08:00:00+00:00"] return rates, generation From fb49d6a810fee5138e9c69ee24133b02f7e5bcfe Mon Sep 17 00:00:00 2001 From: grgmiller Date: Wed, 20 Dec 2023 15:02:14 -0800 Subject: [PATCH 68/85] fix allocate_gen_fuel warning --- .../test_allocate_gen_fuel.ipynb | 379 ++++++++++++++++++ .../manually_update_OTH_fuel_code.ipynb | 2 +- src/oge/data_cleaning.py | 2 +- src/oge/emissions.py | 2 +- src/oge/validation.py | 4 +- 5 files changed, 384 insertions(+), 5 deletions(-) create mode 100644 notebooks/explore_methods/test_allocate_gen_fuel.ipynb diff --git a/notebooks/explore_methods/test_allocate_gen_fuel.ipynb b/notebooks/explore_methods/test_allocate_gen_fuel.ipynb new file mode 100644 index 00000000..61b79077 --- /dev/null +++ b/notebooks/explore_methods/test_allocate_gen_fuel.ipynb @@ -0,0 +1,379 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### About\n", + "This notebook can be used to explore the processing steps in `pudl.analysis.allocate_gen_fuel`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "import oge.load_data as load_data\n", + "\n", + "from pudl.analysis import allocate_gen_fuel\n", + "\n", + "year = 2022" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# pick a plant to investigate\n", + "plant_to_investigate = 621" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf = load_data.load_pudl_table(\"denorm_generation_fuel_combined_eia923\", year)\n", + "bf = load_data.load_pudl_table(\"denorm_boiler_fuel_eia923\", year)\n", + "gen = load_data.load_pudl_table(\"denorm_generation_eia923\", year)\n", + "gens = load_data.load_pudl_table(\"denorm_generators_eia\", year)\n", + "bga = load_data.load_pudl_table(\"boiler_generator_assn_eia860\", year)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf, bf, gen, bga, gens = allocate_gen_fuel.select_input_data(\n", + " gf=gf, bf=bf, gen=gen, bga=bga, gens=gens\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bf[bf[\"plant_id_eia\"] == plant_to_investigate]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gen[gen[\"plant_id_eia\"] == plant_to_investigate]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf[gf[\"plant_id_eia\"] == plant_to_investigate][[\"fuel_consumed_mmbtu\"]].sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf[gf[\"plant_id_eia\"] == plant_to_investigate]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "freq = \"MS\"\n", + "bf, gens_at_freq, gen = allocate_gen_fuel.standardize_input_frequency(bf, gens, gen, freq)\n", + "# Add any startup energy source codes to the list of energy source codes\n", + "gens_at_freq = allocate_gen_fuel.adjust_msw_energy_source_codes(gens_at_freq, gf, bf)\n", + "gens_at_freq = allocate_gen_fuel.add_missing_energy_source_codes_to_gens(gens_at_freq, gf, bf)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gens_at_freq[gens_at_freq[\"plant_id_eia\"] == plant_to_investigate]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gen_assoc = allocate_gen_fuel.associate_generator_tables(\n", + " gens=gens_at_freq, gf=gf, gen=gen, bf=bf, bga=bga\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gen_assoc[gen_assoc[\"plant_id_eia\"] == plant_to_investigate]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Generate a fraction to use to allocate net generation and fuel consumption by.\n", + "# These two methods create a column called `frac`, which will be a fraction\n", + "# to allocate net generation from the gf table for each `IDX_PM_ESC` group\n", + "gen_pm_fuel = allocate_gen_fuel.prep_alloction_fraction(gen_assoc)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gen_pm_fuel[gen_pm_fuel[\"plant_id_eia\"] == plant_to_investigate]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Net gen allocation\n", + "net_gen_alloc = allocate_gen_fuel.allocate_gen_fuel_by_gen_esc(gen_pm_fuel).pipe(\n", + " allocate_gen_fuel._test_gen_pm_fuel_output, gf=gf, gen=gen\n", + ")\n", + "allocate_gen_fuel.test_gen_fuel_allocation(gen, net_gen_alloc)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "net_gen_alloc[net_gen_alloc[\"plant_id_eia\"] == plant_to_investigate][[\"net_generation_mwh\"]].sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf[gf[\"plant_id_eia\"] == plant_to_investigate][[\"net_generation_mwh\"]].sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf_923 = load_data.load_pudl_table(\"generation_fuel_eia923\", year)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf_923" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf_923[gf_923[\"plant_id_eia\"] == plant_to_investigate]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "net_gen_alloc[net_gen_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + "])[\"net_generation_mwh\"].sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(net_gen_alloc[net_gen_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + "])[\"net_generation_mwh\"].sum() - gf[gf[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + "])[\"net_generation_mwh\"].sum()).head(50)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# fuel allocation\n", + "fuel_alloc = allocate_gen_fuel.allocate_fuel_by_gen_esc(gen_pm_fuel)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate][[\"fuel_consumed_mmbtu\"]].sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate].head(20)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + "])[\"frac\"].sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + "])[\"fuel_consumed_mmbtu\"].sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf[gf[\"plant_id_eia\"] == plant_to_investigate][[\"fuel_consumed_mmbtu\"]].sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf[gf[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + "])[\"fuel_consumed_mmbtu\"].sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + "])[\"fuel_consumed_mmbtu\"].sum() - gf[gf[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + "])[\"fuel_consumed_mmbtu\"].sum()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "open-grid-emissions-QkuIZ37I", + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb b/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb index 7591100e..b2b05deb 100644 --- a/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb +++ b/notebooks/manual_data/manually_update_OTH_fuel_code.ipynb @@ -33,7 +33,7 @@ "\n", "# load the fuel content data\n", "fuel_heat_content = load_data.load_pudl_table(\n", - " \"generation_fuel_eia923\",\n", + " \"denorm_generation_fuel_combined_eia923\",\n", " year,\n", " columns=[\n", " \"plant_id_eia\",\n", diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index 8ad5615d..4e5b151a 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -1289,7 +1289,7 @@ def fill_missing_fuel_for_single_fuel_plant_months(df, year): # identify plant-months for which there is a single fossil fuel type reported gf = load_data.load_pudl_table( - "generation_fuel_eia923", + "denorm_generation_fuel_combined_eia923", year, columns=[ "plant_id_eia", diff --git a/src/oge/emissions.py b/src/oge/emissions.py index 2b9fe6ab..56b53dfb 100644 --- a/src/oge/emissions.py +++ b/src/oge/emissions.py @@ -900,7 +900,7 @@ def convert_ef_to_lb_per_mmbtu(gen_emission_factors, year, pollutant): def return_monthly_plant_fuel_heat_content(year): # load information about the monthly heat input of fuels plant_specific_fuel_heat_content = load_data.load_pudl_table( - "generation_fuel_eia923", + "denorm_generation_fuel_combined_eia923", year, columns=[ "plant_id_eia", diff --git a/src/oge/validation.py b/src/oge/validation.py index 588c54cd..8161919b 100644 --- a/src/oge/validation.py +++ b/src/oge/validation.py @@ -50,7 +50,7 @@ def check_allocated_gf_matches_input_gf(year, gen_fuel_allocated): We use np.isclose() to identify any values that are off by more than 1e-9% different from the total input generation or fuel. """ - gf = load_data.load_pudl_table("generation_fuel_eia923", year) + gf = load_data.load_pudl_table("denorm_generation_fuel_combined_eia923", year) plant_total_gf = gf.groupby("plant_id_eia")[ [ "net_generation_mwh", @@ -2436,7 +2436,7 @@ def identify_potential_missing_fuel_in_egrid(year, egrid_plant, cems): "prime_mover_code", ] gf = load_data.load_pudl_table( - "generation_fuel_eia923", + "denorm_generation_fuel_combined_eia923", year, columns=IDX_PM_ESC + [ From b1d93276ad250a3f9ea0ba2d1f35608af1daa66f Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 21 Dec 2023 17:36:29 -0800 Subject: [PATCH 69/85] add check for monthly data --- .../test_allocate_gen_fuel.ipynb | 187 ++++++++---------- src/oge/data_cleaning.py | 39 ++-- src/oge/data_pipeline.py | 13 +- src/oge/emissions.py | 8 +- src/oge/output_data.py | 4 +- src/oge/validation.py | 31 ++- 6 files changed, 141 insertions(+), 141 deletions(-) diff --git a/notebooks/explore_methods/test_allocate_gen_fuel.ipynb b/notebooks/explore_methods/test_allocate_gen_fuel.ipynb index 61b79077..ba3f7724 100644 --- a/notebooks/explore_methods/test_allocate_gen_fuel.ipynb +++ b/notebooks/explore_methods/test_allocate_gen_fuel.ipynb @@ -30,7 +30,7 @@ "outputs": [], "source": [ "# pick a plant to investigate\n", - "plant_to_investigate = 621" + "plant_to_investigate = 47" ] }, { @@ -43,15 +43,8 @@ "bf = load_data.load_pudl_table(\"denorm_boiler_fuel_eia923\", year)\n", "gen = load_data.load_pudl_table(\"denorm_generation_eia923\", year)\n", "gens = load_data.load_pudl_table(\"denorm_generators_eia\", year)\n", - "bga = load_data.load_pudl_table(\"boiler_generator_assn_eia860\", year)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ + "bga = load_data.load_pudl_table(\"boiler_generator_assn_eia860\", year)\n", + "\n", "gf, bf, gen, bga, gens = allocate_gen_fuel.select_input_data(\n", " gf=gf, bf=bf, gen=gen, bga=bga, gens=gens\n", ")" @@ -100,10 +93,14 @@ "outputs": [], "source": [ "freq = \"MS\"\n", - "bf, gens_at_freq, gen = allocate_gen_fuel.standardize_input_frequency(bf, gens, gen, freq)\n", + "bf, gens_at_freq, gen = allocate_gen_fuel.standardize_input_frequency(\n", + " bf, gens, gen, freq\n", + ")\n", "# Add any startup energy source codes to the list of energy source codes\n", "gens_at_freq = allocate_gen_fuel.adjust_msw_energy_source_codes(gens_at_freq, gf, bf)\n", - "gens_at_freq = allocate_gen_fuel.add_missing_energy_source_codes_to_gens(gens_at_freq, gf, bf)" + "gens_at_freq = allocate_gen_fuel.add_missing_energy_source_codes_to_gens(\n", + " gens_at_freq, gf, bf\n", + ")" ] }, { @@ -122,8 +119,8 @@ "outputs": [], "source": [ "gen_assoc = allocate_gen_fuel.associate_generator_tables(\n", - " gens=gens_at_freq, gf=gf, gen=gen, bf=bf, bga=bga\n", - " )" + " gens=gens_at_freq, gf=gf, gen=gen, bf=bf, bga=bga\n", + ")" ] }, { @@ -175,7 +172,9 @@ "metadata": {}, "outputs": [], "source": [ - "net_gen_alloc[net_gen_alloc[\"plant_id_eia\"] == plant_to_investigate][[\"net_generation_mwh\"]].sum()" + "net_gen_alloc[net_gen_alloc[\"plant_id_eia\"] == plant_to_investigate][\n", + " [\"net_generation_mwh\"]\n", + "].sum()" ] }, { @@ -196,24 +195,6 @@ "gf_923 = load_data.load_pudl_table(\"generation_fuel_eia923\", year)" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gf" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gf_923" - ] - }, { "cell_type": "code", "execution_count": null, @@ -229,12 +210,14 @@ "metadata": {}, "outputs": [], "source": [ - "net_gen_alloc[net_gen_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", - " \"report_date\",\n", - " \"plant_id_eia\",\n", - " \"prime_mover_code\",\n", - " \"energy_source_code\",\n", - "])[\"net_generation_mwh\"].sum()" + "net_gen_alloc[net_gen_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby(\n", + " [\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + " ]\n", + ")[\"net_generation_mwh\"].sum()" ] }, { @@ -243,17 +226,28 @@ "metadata": {}, "outputs": [], "source": [ - "(net_gen_alloc[net_gen_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", - " \"report_date\",\n", - " \"plant_id_eia\",\n", - " \"prime_mover_code\",\n", - " \"energy_source_code\",\n", - "])[\"net_generation_mwh\"].sum() - gf[gf[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", - " \"report_date\",\n", - " \"plant_id_eia\",\n", - " \"prime_mover_code\",\n", - " \"energy_source_code\",\n", - "])[\"net_generation_mwh\"].sum()).head(50)" + "(\n", + " net_gen_alloc[net_gen_alloc[\"plant_id_eia\"] == plant_to_investigate]\n", + " .groupby(\n", + " [\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + " ]\n", + " )[\"net_generation_mwh\"]\n", + " .sum()\n", + " - gf[gf[\"plant_id_eia\"] == plant_to_investigate]\n", + " .groupby(\n", + " [\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + " ]\n", + " )[\"net_generation_mwh\"]\n", + " .sum()\n", + ").head(50)" ] }, { @@ -272,16 +266,10 @@ "metadata": {}, "outputs": [], "source": [ - "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate][[\"fuel_consumed_mmbtu\"]].sum()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate].head(20)" + "# check total fuel after allocation\n", + "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate][\n", + " [\"fuel_consumed_mmbtu\"]\n", + "].sum()" ] }, { @@ -290,12 +278,7 @@ "metadata": {}, "outputs": [], "source": [ - "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", - " \"report_date\",\n", - " \"plant_id_eia\",\n", - " \"prime_mover_code\",\n", - " \"energy_source_code\",\n", - "])[\"frac\"].sum()" + "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate]" ] }, { @@ -304,12 +287,15 @@ "metadata": {}, "outputs": [], "source": [ - "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", - " \"report_date\",\n", - " \"plant_id_eia\",\n", - " \"prime_mover_code\",\n", - " \"energy_source_code\",\n", - "])[\"fuel_consumed_mmbtu\"].sum()" + "# check that allocation fractions sum to 1\n", + "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby(\n", + " [\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + " ]\n", + ")[\"frac\"].sum()" ] }, { @@ -318,40 +304,29 @@ "metadata": {}, "outputs": [], "source": [ - "gf[gf[\"plant_id_eia\"] == plant_to_investigate][[\"fuel_consumed_mmbtu\"]].sum()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gf[gf[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", - " \"report_date\",\n", - " \"plant_id_eia\",\n", - " \"prime_mover_code\",\n", - " \"energy_source_code\",\n", - "])[\"fuel_consumed_mmbtu\"].sum()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", - " \"report_date\",\n", - " \"plant_id_eia\",\n", - " \"prime_mover_code\",\n", - " \"energy_source_code\",\n", - "])[\"fuel_consumed_mmbtu\"].sum() - gf[gf[\"plant_id_eia\"] == plant_to_investigate].groupby([\n", - " \"report_date\",\n", - " \"plant_id_eia\",\n", - " \"prime_mover_code\",\n", - " \"energy_source_code\",\n", - "])[\"fuel_consumed_mmbtu\"].sum()" + "# see where tehre is a difference between inputs and outputs\n", + "(\n", + " fuel_alloc[fuel_alloc[\"plant_id_eia\"] == plant_to_investigate]\n", + " .groupby(\n", + " [\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + " ]\n", + " )[\"fuel_consumed_mmbtu\"]\n", + " .sum()\n", + " - gf[gf[\"plant_id_eia\"] == plant_to_investigate]\n", + " .groupby(\n", + " [\n", + " \"report_date\",\n", + " \"plant_id_eia\",\n", + " \"prime_mover_code\",\n", + " \"energy_source_code\",\n", + " ]\n", + " )[\"fuel_consumed_mmbtu\"]\n", + " .sum()\n", + ")" ] } ], diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index 4e5b151a..0bbadfcf 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -411,29 +411,24 @@ def clean_eia923( """ This is the coordinating function for cleaning and allocating generation and fuel data in EIA-923. """ - # Load the EIA-923 data that is already allocated to each generator-pm-fuel - gen_fuel_allocated = load_data.load_pudl_table( - "generation_fuel_by_generator_energy_source_monthly_eia923", year - ) + # Allocate fuel and generation across each generator-pm-energy source + gf = load_data.load_pudl_table("denorm_generation_fuel_combined_eia923", year) + bf = load_data.load_pudl_table("denorm_boiler_fuel_eia923", year) + gen = load_data.load_pudl_table("denorm_generation_eia923", year) + gens = load_data.load_pudl_table("denorm_generators_eia", year) + bga = load_data.load_pudl_table("boiler_generator_assn_eia860", year) - # drop rows where all allocated data is missing - gen_fuel_allocated = gen_fuel_allocated.dropna( - subset=[ - "net_generation_mwh", - "fuel_consumed_mmbtu", - "fuel_consumed_for_electricity_mmbtu", - ], - how="all", + gf, bf, gen, bga, gens = allocate_gen_fuel.select_input_data( + gf=gf, bf=bf, gen=gen, bga=bga, gens=gens + ) + gen_fuel_allocated = allocate_gen_fuel.allocate_gen_fuel_by_generator_energy_source( + gf, + bf, + gen, + bga, + gens, + freq="MS", ) - - # drop rows where all allocated data is zero - gen_fuel_allocated = gen_fuel_allocated[ - ~( - (gen_fuel_allocated["net_generation_mwh"] == 0) - & (gen_fuel_allocated["fuel_consumed_mmbtu"] == 0) - & (gen_fuel_allocated["fuel_consumed_for_electricity_mmbtu"] == 0) - ) - ] # drop bad data where there is negative fuel consumption # NOTE(greg) this is in response to a specific issue with the input data for @@ -1739,7 +1734,7 @@ def identify_partial_cems_plants(all_data): (all_data["hourly_data_source"] == "eia") & (all_data["partial_plant"] == "both") & ( - ~all_data["energy_source_code"].isin(non_cems_fuels) + ~all_data["plant_primary_fuel"].isin(non_cems_fuels) ), # CEMS data should only be used to shape if plant is primarilly fossil "hourly_data_source", ] = "partial_cems_plant" diff --git a/src/oge/data_pipeline.py b/src/oge/data_pipeline.py index d0f1ddb2..cb76af36 100644 --- a/src/oge/data_pipeline.py +++ b/src/oge/data_pipeline.py @@ -271,7 +271,7 @@ def main(args): df_name="partial_cems_plant", keys=["plant_id_eia", "subplant_id"], ) - validation.check_for_complete_timeseries( + validation.check_for_complete_hourly_timeseries( df=partial_cems_plant, df_name="partial_cems_plant", keys=["plant_id_eia", "subplant_id"], @@ -295,7 +295,7 @@ def main(args): df_name="partial_cems_subplant", keys=["plant_id_eia", "subplant_id"], ) - validation.check_for_complete_timeseries( + validation.check_for_complete_hourly_timeseries( df=partial_cems_subplant, df_name="partial_cems_subplant", keys=["plant_id_eia", "subplant_id"], @@ -344,7 +344,7 @@ def main(args): df_name="cems_subplant", keys=["plant_id_eia", "subplant_id"], ) - validation.check_for_complete_timeseries( + validation.check_for_complete_hourly_timeseries( df=cems, df_name="cems_subplant", keys=["plant_id_eia", "subplant_id"], @@ -383,6 +383,9 @@ def main(args): monthly_eia_data_to_shape, "monthly", ) + validation.check_for_complete_monthly_timeseries( + monthly_plant_data, "monthly_plant_data", ["plant_id_eia"] + ) output_data.output_plant_data( monthly_plant_data, path_prefix, "monthly", args.skip_outputs, plant_attributes ) @@ -507,7 +510,7 @@ def main(args): df_name="shaped_eia_data", keys=["plant_id_eia"], ) - validation.check_for_complete_timeseries( + validation.check_for_complete_hourly_timeseries( df=shaped_eia_data, df_name="shaped_eia_data", keys=["plant_id_eia"], @@ -572,7 +575,7 @@ def main(args): df_name="combined_plant_data", keys=["plant_id_eia"], ) - validation.check_for_complete_timeseries( + validation.check_for_complete_hourly_timeseries( df=combined_plant_data, df_name="combined_plant_data", keys=["plant_id_eia"], diff --git a/src/oge/emissions.py b/src/oge/emissions.py index 56b53dfb..567e5bbb 100644 --- a/src/oge/emissions.py +++ b/src/oge/emissions.py @@ -493,7 +493,7 @@ def calculate_nox_from_fuel_consumption( # raise a warning if we are missing emission factors for any non-zero fuel consumption from non-clean fuels missing_ef = gen_fuel_allocated[ gen_fuel_allocated["nox_ef_lb_per_mmbtu"].isna() - & ~gen_fuel_allocated["fuel_consumed_mmbtu"].isna() + & (gen_fuel_allocated["fuel_consumed_mmbtu"] > 0) & ~gen_fuel_allocated["energy_source_code"].isin(CLEAN_FUELS) ] if len(missing_ef) > 0: @@ -570,7 +570,7 @@ def calculate_generator_nox_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea # get a dataframe with all unique generator-pm-esc combinations for emitting energy source types with data reported gen_keys_for_nox = gen_fuel_allocated.copy()[ - ~gen_fuel_allocated["fuel_consumed_mmbtu"].isna() + (gen_fuel_allocated["fuel_consumed_mmbtu"] > 0) ] gen_keys_for_nox = gen_keys_for_nox[ [ @@ -1238,7 +1238,7 @@ def calculate_so2_from_fuel_consumption(gen_fuel_allocated, year): # raise a warning if we are missing emission factors for any non-zero fuel consumption from non-clean fuels missing_ef = gen_fuel_allocated[ gen_fuel_allocated["so2_ef_lb_per_mmbtu"].isna() - & ~gen_fuel_allocated["fuel_consumed_mmbtu"].isna() + & (gen_fuel_allocated["fuel_consumed_mmbtu"] > 0) & ~gen_fuel_allocated["energy_source_code"].isin(CLEAN_FUELS) ] if len(missing_ef) > 0: @@ -1306,7 +1306,7 @@ def calculate_generator_so2_ef_per_unit_from_boiler_type(gen_fuel_allocated, yea # get a dataframe with all unique generator-pm-esc combinations for emitting energy source types with data reported gen_keys_for_so2 = gen_fuel_allocated.copy()[ - ~gen_fuel_allocated["fuel_consumed_mmbtu"].isna() + (gen_fuel_allocated["fuel_consumed_mmbtu"] > 0) ] gen_keys_for_so2 = gen_keys_for_so2[ [ diff --git a/src/oge/output_data.py b/src/oge/output_data.py index 2a966495..c052bcb3 100644 --- a/src/oge/output_data.py +++ b/src/oge/output_data.py @@ -181,7 +181,7 @@ def output_plant_data(df, path_prefix, resolution, skip_outputs, plant_attribute validation.validate_unique_datetimes( df, "individual_plant_data", ["plant_id_eia"] ) - validation.check_for_complete_timeseries( + validation.check_for_complete_hourly_timeseries( df, "individual_plant_data", ["plant_id_eia"], "year" ) # Separately save real and aggregate plants @@ -557,7 +557,7 @@ def add_generated_emission_rate_columns(df): df_name="power sector hourly ba table", keys=["fuel_category"], ) - validation.check_for_complete_timeseries( + validation.check_for_complete_hourly_timeseries( ba_table_hourly, "power sector hourly ba table", ["fuel_category"], diff --git a/src/oge/validation.py b/src/oge/validation.py index 8161919b..e786e8c8 100644 --- a/src/oge/validation.py +++ b/src/oge/validation.py @@ -795,7 +795,9 @@ def validate_unique_datetimes(df, df_name, keys): ) -def check_for_complete_timeseries(df, df_name, keys, period): +def check_for_complete_hourly_timeseries( + df: pd.DataFrame, df_name: str, keys: list[str], period: str +): """Validates that a timeseries contains complete hourly data. If the `period` is a 'year', checks that the length of the timeseries is 8760 (for a @@ -849,8 +851,33 @@ def check_for_complete_timeseries(df, df_name, keys, period): logger.warning("\n" + test.to_string()) else: raise UserWarning( - f"{period} is not a valid value for the `period` argument in `check_for_complete_timeseries`. Value must be 'year' or 'month'" + f"{period} is not a valid value for the `period` argument in `check_for_complete_hourly_timeseries`. Value must be 'year' or 'month'" + ) + + +def check_for_complete_monthly_timeseries( + df: pd.DataFrame, df_name: str, keys: list[str] +): + """Validates that a dataset contains complete monthly data for all months. + + Checks that there are 12 observations for each group of keys + + Args: + df: dataframe containing datetime columns + df_name: a descriptive name for the dataframe + keys: list of column names that contain the groups within which datetimes should be unique + """ + + # count the number of report_dates in each group + test = df.groupby(keys)[["report_date"]].count() + test["expected_num_months"] = 12 + # identify any rows where there are less than 12 months of data + test = test[test["report_date"] != test["expected_num_months"]] + if len(test) > 0: + logger.warning( + f"There is incomplete monthly data for the following {keys} groups in {df_name}" ) + logger.warning("\n" + test.to_string()) # DATA QUALITY METRIC FUNCTIONS From c43bb1b7f230a0fa8428ca661cee1175d969a966 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 22 Dec 2023 11:28:50 -0800 Subject: [PATCH 70/85] fix issue with incorrect plant metadata --- src/oge/column_checks.py | 1 - src/oge/data_cleaning.py | 4 - src/oge/data_pipeline.py | 11 ++ src/oge/impute_hourly_profiles.py | 26 +++-- src/oge/output_data.py | 179 ++++++++++++++++-------------- 5 files changed, 121 insertions(+), 100 deletions(-) diff --git a/src/oge/column_checks.py b/src/oge/column_checks.py index fc948bcb..1ba5a576 100644 --- a/src/oge/column_checks.py +++ b/src/oge/column_checks.py @@ -202,7 +202,6 @@ "data_source", "hourly_profile_source", "net_generation_method", - "shaped_plant_id", }, "hourly_profiles": { "ba_code", diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index 0bbadfcf..141284cb 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -1017,10 +1017,6 @@ def clean_cems(year: int, small: bool, primary_fuel_table, subplant_emission_fac distribution_connected_plants=False, ) - # manually remove steam-only units - # NOTE(greg): disabling this for the 2022 data release - # cems = manually_remove_steam_units(cems) - # add a report date cems = load_data.add_report_date(cems) diff --git a/src/oge/data_pipeline.py b/src/oge/data_pipeline.py index cb76af36..13551505 100644 --- a/src/oge/data_pipeline.py +++ b/src/oge/data_pipeline.py @@ -453,6 +453,17 @@ def main(args): # 14. Export hourly plant-level data #################################################################################### + # The data pipeline offers two options for exporting plant-level data. The first + # option, executed here in step 14 is to shape hourly data for each individual plant + # This option provides a complete hourly timeseries for each plant, but is more + # memory-intensive and results in larger output files. + # This data is immediately exported and not held in memory for the rest of the pipe- + # line. Instead, this data is re-combined again using the aggregated shaped plants + # in step 16. + # The other option happens in step 16 if step 14 is not run: instead of shaping each + # plant, only an aggregate fleet-level synthetic plant is exported, which represents + # the characteristics of all plants that do not report hourly data elsewhere in each + # month. logger.info("14. Exporting Hourly Plant-level data for each BA") if args.shape_individual_plants and not args.small: impute_hourly_profiles.combine_and_export_hourly_plant_data( diff --git a/src/oge/impute_hourly_profiles.py b/src/oge/impute_hourly_profiles.py index bf705085..52b4bce0 100644 --- a/src/oge/impute_hourly_profiles.py +++ b/src/oge/impute_hourly_profiles.py @@ -896,15 +896,15 @@ def convert_profile_to_percent(hourly_profiles, group_keys, columns_to_convert): def combine_and_export_hourly_plant_data( - cems, - partial_cems_subplant, - partial_cems_plant, - monthly_eia_data_to_shape, - plant_attributes, - hourly_profiles, - path_prefix, - skip_outputs, - region_to_group, + cems: pd.DataFrame, + partial_cems_subplant: pd.DataFrame, + partial_cems_plant: pd.DataFrame, + monthly_eia_data_to_shape: pd.DataFrame, + plant_attributes: pd.DataFrame, + hourly_profiles: pd.DataFrame, + path_prefix: str, + skip_outputs: bool, + region_to_group: str = "ba_code", ): """ Exports files with hourly data for each individual plant, split up by region. @@ -1085,6 +1085,14 @@ def combine_and_export_hourly_plant_data( # re-order columns combined_plant_data = combined_plant_data[all_columns] + # validate that there are complete timeseries + validation.check_for_complete_hourly_timeseries( + df=combined_plant_data, + df_name=f"plant_data/hourly/{region}", + keys=["plant_id_eia"], + period="year", + ) + # write data output_data.output_to_results( combined_plant_data, diff --git a/src/oge/output_data.py b/src/oge/output_data.py index c052bcb3..2b598c8e 100644 --- a/src/oge/output_data.py +++ b/src/oge/output_data.py @@ -292,20 +292,20 @@ def write_generated_averages(ba_fuel_data, year, path_prefix, skip_outputs): def write_plant_metadata( - plant_static_attributes, - eia923_allocated, - cems, - partial_cems_subplant, - partial_cems_plant, - shaped_eia_data, - path_prefix, - skip_outputs, + plant_static_attributes: pd.DataFrame, + eia923_allocated: pd.DataFrame, + cems: pd.DataFrame, + partial_cems_subplant: pd.DataFrame, + partial_cems_plant: pd.DataFrame, + shaped_eia_data: pd.DataFrame, + path_prefix: str, + skip_outputs: bool, ): """ Outputs metadata for each subplant-month. - Include rows for subplants aggregated to a synthetic plant, - so users can see when a plant's subplants are split across plant-level and synthetic hourly data files + Include rows for subplants aggregated to a synthetic plant, so users can see when a + plant's subplants are split across plant-level and synthetic hourly data files """ KEY_COLUMNS = [ @@ -314,91 +314,98 @@ def write_plant_metadata( "report_date", ] - METADATA_COLUMNS = [ - "data_source", - "hourly_profile_source", - "net_generation_method", - ] - - if not skip_outputs: - # From monthly EIA data, we want only the EIA-only subplants -- these are the ones that got shaped - eia_only_subplants = eia923_allocated[ + # create CEMS metadata + # only keep one metadata row per plant/subplant-month + cems_meta = cems.copy()[KEY_COLUMNS + ["gtn_method"]].drop_duplicates( + subset=KEY_COLUMNS + ) + cems_meta["data_source"] = "CEMS" + cems_meta = cems_meta.rename(columns={"gtn_method": "net_generation_method"}) + cems_meta["hourly_profile_source"] = "CEMS" + + # create partial cems subplant metadata + partial_cems_subplant_meta = partial_cems_subplant.copy()[ + KEY_COLUMNS + ].drop_duplicates(subset=KEY_COLUMNS) + partial_cems_subplant_meta["data_source"] = "EIA" + partial_cems_subplant_meta["net_generation_method"] = "scaled_partial_cems_subplant" + partial_cems_subplant_meta["hourly_profile_source"] = "partial CEMS subplant" + + # create partial cems plant metadata + partial_cems_plant_meta = partial_cems_plant.copy()[KEY_COLUMNS].drop_duplicates( + subset=KEY_COLUMNS + ) + partial_cems_plant_meta["data_source"] = "EIA" + partial_cems_plant_meta["net_generation_method"] = "shaped_from_partial_cems_plant" + partial_cems_plant_meta["hourly_profile_source"] = "partial CEMS plant" + + # create EIA-only metadata + # From monthly EIA data, we want only the EIA-only subplants + # these are the ones that got shaped + monthly_eia_meta = ( + eia923_allocated.copy() + .loc[ (eia923_allocated["hourly_data_source"] == "eia") - & ~(eia923_allocated["fuel_consumed_mmbtu"].isna()) - ].copy() - - # identify the source - cems["data_source"] = "CEMS" - partial_cems_subplant["data_source"] = "EIA" - partial_cems_plant["data_source"] = "EIA" - shaped_eia_data["data_source"] = "EIA" - eia_only_subplants["data_source"] = "EIA" - - # identify net generation method - cems = cems.rename(columns={"gtn_method": "net_generation_method"}) - shaped_eia_data["net_generation_method"] = shaped_eia_data["profile_method"] - eia_only_subplants["net_generation_method"] = "" - partial_cems_subplant["net_generation_method"] = "scaled_partial_cems_subplant" - partial_cems_plant["net_generation_method"] = "shaped_from_partial_cems_plant" - - # identify hourly profile method - cems["hourly_profile_source"] = "CEMS" - partial_cems_subplant["hourly_profile_source"] = "partial CEMS subplant" - partial_cems_plant["hourly_profile_source"] = "partial CEMS plant" - shaped_eia_data = shaped_eia_data.rename( - columns={"profile_method": "hourly_profile_source"} - ) - eia_only_subplants["hourly_profile_source"] = "" + & ~(eia923_allocated["fuel_consumed_mmbtu"].isna()), + ["plant_id_eia", "subplant_id", "report_date"], + ] + .drop_duplicates(subset=["plant_id_eia", "subplant_id", "report_date"]) + ) - # only keep one metadata row per plant/subplant-month - cems_meta = cems.copy()[KEY_COLUMNS + METADATA_COLUMNS].drop_duplicates( - subset=KEY_COLUMNS - ) - partial_cems_subplant_meta = partial_cems_subplant.copy()[ - KEY_COLUMNS + METADATA_COLUMNS - ].drop_duplicates(subset=KEY_COLUMNS) - partial_cems_plant_meta = partial_cems_plant.copy()[ - KEY_COLUMNS + METADATA_COLUMNS - ].drop_duplicates(subset=KEY_COLUMNS) - shaped_eia_data_meta = shaped_eia_data.copy()[ - ["plant_id_eia", "report_date"] + METADATA_COLUMNS - ].drop_duplicates(subset=["plant_id_eia", "report_date"]) - monthly_eia_meta = eia_only_subplants.copy()[ - ["plant_id_eia", "report_date"] + METADATA_COLUMNS - ].drop_duplicates(subset=["plant_id_eia", "report_date"]) - - # For monthly only: specify which synthetic plant we were aggregated to - monthly_eia_meta = monthly_eia_meta.merge( - plant_static_attributes[["plant_id_eia", "shaped_plant_id"]], - how="left", - on="plant_id_eia", - validate="m:1", # There can be multiple subplants in monthly EIA for each plant in static attributes - ) + # For monthly only: specify which synthetic plant we were aggregated to + monthly_eia_meta = monthly_eia_meta.merge( + plant_static_attributes[["plant_id_eia", "shaped_plant_id"]], + how="left", + on="plant_id_eia", + validate="m:1", # There can be multiple subplants for each plant + ) - # concat the metadata into a one file and export - metadata = pd.concat( - [ - cems_meta, - partial_cems_subplant_meta, - partial_cems_plant_meta, - shaped_eia_data_meta, - monthly_eia_meta, - ], - axis=0, - ) + monthly_eia_meta["data_source"] = "EIA" + + # merge in the net generation method and hourly profile from the shaped metadata + shaped_eia_data_meta = shaped_eia_data.copy()[ + ["plant_id_eia", "report_date", "profile_method"] + ].drop_duplicates(subset=["plant_id_eia", "report_date"]) + shaped_eia_data_meta = shaped_eia_data_meta.rename( + columns={"plant_id_eia": "shaped_plant_id"} + ) + shaped_eia_data_meta["net_generation_method"] = shaped_eia_data_meta[ + "profile_method" + ] + shaped_eia_data_meta = shaped_eia_data_meta.rename( + columns={"profile_method": "hourly_profile_source"} + ) + monthly_eia_meta = monthly_eia_meta.merge( + shaped_eia_data_meta, + how="left", + on=["shaped_plant_id", "report_date"], + validate="m:1", # There can be multiple subplants for each plant + ) + + monthly_eia_meta = monthly_eia_meta.drop(columns=["shaped_plant_id"]) + + # concat the metadata into a one file and export + metadata = pd.concat( + [ + cems_meta, + partial_cems_subplant_meta, + partial_cems_plant_meta, + monthly_eia_meta, + ], + axis=0, + ).sort_values(by=["plant_id_eia", "subplant_id", "report_date"], ascending=True) + + validation.check_for_complete_monthly_timeseries( + metadata, "plant_metadata", ["plant_id_eia", "subplant_id"] + ) - column_checks.check_columns(metadata, "plant_metadata") + column_checks.check_columns(metadata, "plant_metadata") + if not skip_outputs: metadata.to_csv( results_folder(f"{path_prefix}plant_data/plant_metadata.csv"), index=False ) - # drop the metadata columns from each dataframe - cems = cems.drop(columns=METADATA_COLUMNS) - partial_cems_subplant = partial_cems_subplant.drop(columns=METADATA_COLUMNS) - partial_cems_plant = partial_cems_plant.drop(columns=METADATA_COLUMNS) - shaped_eia_data = shaped_eia_data.drop(columns=METADATA_COLUMNS) - def round_table(table): """ From b37dc7ed478297f7af7a1f025037514faf5ba3a0 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 22 Dec 2023 16:49:27 -0800 Subject: [PATCH 71/85] stop dropping missing data --- src/oge/data_cleaning.py | 169 ++++++++++++++++++++++++++++++++++----- src/oge/data_pipeline.py | 9 ++- src/oge/output_data.py | 7 +- src/oge/validation.py | 67 +++++++++++++--- 4 files changed, 221 insertions(+), 31 deletions(-) diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index 141284cb..bffe1a01 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -1,5 +1,6 @@ import pandas as pd import numpy as np +from itertools import product import pudl.analysis.allocate_gen_fuel as allocate_gen_fuel import pudl.analysis.epacamd_eia as epacamd_eia @@ -1024,6 +1025,9 @@ def clean_cems(year: int, small: bool, primary_fuel_table, subplant_emission_fac # this is generally when there is a single observation reported for an entire month cems = remove_incomplete_unit_months(cems) + # create an inventory of which plant-months have input data from any source + inventory_input_data_sources(cems, year) + # TODO: identify and remove any hourly values that appear to be outliers # See: https://github.com/singularity-energy/open-grid-emissions/issues/50 @@ -1059,9 +1063,14 @@ def clean_cems(year: int, small: bool, primary_fuel_table, subplant_emission_fac df=cems, year=year, include_co2=False, include_ch4=True, include_n2o=True ) - # remove any observations from cems where zero operation is reported for an entire month - # although this data could be considered to be accurately reported, let's remove it so that we can double check against the eia data - cems = remove_cems_with_zero_monthly_data(cems) + # remove any observations from cems where zero operation is reported for an entire + # month. Although this data could be considered to be accurately reported, let's + # remove it so that we can double check against the eia data + # NOTE(12/22/23): We will treat reported zeros as actual data and not attempt to + # fill reported zeros with EIA-923 data due to the issues that exist with the method + # EIA uses to allocate annual data to months. In the future, we could use monthly- + # reported EIA data since this is directly reported by the generator. + # cems = remove_cems_with_zero_monthly_data(cems) validation.test_for_negative_values(cems) validation.validate_unique_datetimes( @@ -1124,10 +1133,10 @@ def remove_incomplete_unit_months(cems): .reset_index() ) - # identify months where there is not complete data + # identify months where there is less than a single day of data # The fewest number of hours in a month is 28*24 = 672 unit_months_to_remove = unit_hours_in_month[ - unit_hours_in_month["datetime_utc"] < 600 + unit_hours_in_month["datetime_utc"] < 24 ].drop(columns="datetime_utc") logger.info( @@ -1247,6 +1256,136 @@ def assign_fuel_type_to_cems(cems, year, primary_fuel_table): return cems +def inventory_input_data_sources(cems: pd.DataFrame, year: int): + """ + Exports a csv that identifies for each plant-month whether input data exists from + CEMS or EIA-923. This will be used when checking for missing timestamps in the + output data. + + This function expects CEMS data after it has been loaded, non-grid connected plants + removed, report date added, and incomplete unit-months removed. + """ + + # load EIA-923 generation and fuel data + gf = load_data.load_pudl_table("denorm_generation_fuel_combined_eia923", year) + + # sum generation and fuel by plant-month + plant_months_in_eia = ( + gf.groupby(["plant_id_eia", "report_date"], dropna=False)[ + ["net_generation_mwh", "fuel_consumed_mmbtu"] + ] + .sum(min_count=1) + .reset_index() + ) + # add a flag if the data exists + plant_months_in_eia["data_in_eia"] = 1 + # add a flag if the data is nonzero + plant_months_in_eia["nonzero_data_in_eia"] = 0 + plant_months_in_eia.loc[ + plant_months_in_eia[["net_generation_mwh", "fuel_consumed_mmbtu"]].sum(axis=1) + > 0, + "nonzero_data_in_eia", + ] = 1 + + plant_months_in_eia = plant_months_in_eia[ + ["plant_id_eia", "report_date", "data_in_eia", "nonzero_data_in_eia"] + ].sort_values(by=["plant_id_eia", "report_date"]) + + # sum the generation and fuel data for each plant-month, + # if there is at least one non-na value + plant_months_in_cems = ( + cems.groupby(["plant_id_eia", "report_date"], dropna=False)[ + ["gross_generation_mwh", "fuel_consumed_mmbtu"] + ] + .sum(min_count=1) + .reset_index() + ) + # add an indicator column if any data exists + plant_months_in_cems["data_in_cems"] = 0 + plant_months_in_cems.loc[ + ( + ~plant_months_in_cems[["gross_generation_mwh", "fuel_consumed_mmbtu"]] + .isna() + .all(axis=1) + ), + "data_in_cems", + ] = 1 + + # add a flag if the data is zero + plant_months_in_cems["nonzero_data_in_cems"] = 0 + plant_months_in_cems.loc[ + plant_months_in_cems[["gross_generation_mwh", "fuel_consumed_mmbtu"]].sum( + axis=1 + ) + > 0, + "nonzero_data_in_cems", + ] = 1 + + plant_months_in_cems = plant_months_in_cems[ + ["plant_id_eia", "report_date", "data_in_cems", "nonzero_data_in_cems"] + ].sort_values(by=["plant_id_eia", "report_date"]) + + # outer merge cems and eia inventories together + input_data_exists = plant_months_in_eia.merge( + plant_months_in_cems, + how="outer", + on=["plant_id_eia", "report_date"], + validate="1:1", + ).sort_values(by=["plant_id_eia", "report_date"]) + + # create a dataframe with a complete set of plant-months in case some months + # are missing from the inventory + complete_plant_months = pd.DataFrame( + list( + product( + list(input_data_exists.plant_id_eia.unique()), + list(input_data_exists.report_date.unique()), + ) + ), + columns=["plant_id_eia", "report_date"], + ) + # make sure the datetime dtypes match before merging + complete_plant_months["report_date"] = complete_plant_months.report_date.astype( + input_data_exists.report_date.dtype + ) + # complete the report dates + input_data_exists = input_data_exists.merge( + complete_plant_months, + how="outer", + on=["plant_id_eia", "report_date"], + validate="1:1", + ).sort_values(by=["plant_id_eia", "report_date"]) + + # fill missing values with zeros + input_data_exists["data_in_eia"] = input_data_exists["data_in_eia"].fillna(0) + input_data_exists["data_in_cems"] = input_data_exists["data_in_cems"].fillna(0) + input_data_exists["nonzero_data_in_eia"] = input_data_exists[ + "nonzero_data_in_eia" + ].fillna(0) + input_data_exists["nonzero_data_in_cems"] = input_data_exists[ + "nonzero_data_in_cems" + ].fillna(0) + + # create a column to indicate if data exists from any source + input_data_exists["input_data_exists"] = 0 + input_data_exists.loc[ + input_data_exists[["data_in_eia", "data_in_cems"]].sum(axis=1) > 0, + "input_data_exists", + ] = 1 + # create a column to indicate if nonzero data exists from any source + input_data_exists["nonzero_input_data_exists"] = 0 + input_data_exists.loc[ + input_data_exists[["nonzero_data_in_eia", "nonzero_data_in_cems"]].sum(axis=1) + > 0, + "nonzero_input_data_exists", + ] = 1 + + # export to csv + input_data_exists.to_csv( + outputs_folder(f"{year}/input_data_inventory_{year}.csv"), index=False + ) + + def fillna_with_missing_strings(df, column_to_fill, filler_column): """ Fills missing values in string columns using another string column with missing values. @@ -1523,15 +1662,6 @@ def identify_hourly_data_source(eia923_allocated, cems, year): # for the remaining plants, identify the hourly data source as EIA all_data["hourly_data_source"] = all_data["hourly_data_source"].fillna("eia") - - # remove any generator-months for which there is no data reported in either data source - all_data = all_data[ - ~( - (all_data["reported_eia923"] == 0) - & (all_data["hourly_data_source"] == "eia") - ) - ] - all_data = all_data.drop(columns=["reported_eia923"]) # identify the partial cems plants @@ -1593,14 +1723,16 @@ def identify_partial_cems_subplants(year, cems, eia923_allocated): ) # identify which subplant-months have complete or partial cems data - # we identify this as subplant months where the number of CEMS reported units is less - # than the total number of units in that subplant, AND the total fuel reported in CEMS - # is less than 95% of the fuel reported in EIA + # we identify this as subplant months where the number of CEMS reported units is + # less than the total number of units in that subplant, AND the total, non-zero fuel + # reported in CEMS is less than 95% of the non-zero fuel reported in EIA cems_status = cems_units_reported.assign( hourly_data_source=lambda x: np.where( ( (x.reported_units_in_subplant < x.units_in_subplant) & (x.fuel_consumed_mmbtu_cems < (x.fuel_consumed_mmbtu_eia * 0.95)) + & (x.fuel_consumed_mmbtu_cems > 0) + & (x.fuel_consumed_mmbtu_eia > 0) ), "partial_cems_subplant", "cems", @@ -1757,6 +1889,7 @@ def identify_partial_cems_plants(all_data): # Check for subplants with mixed hourly data sources, # likely resulting from mixed fuel types. # If subplant_id assignment is working, there shouldn't be any + print(mixed_method_subplants) raise Exception( f"ERROR: {len(mixed_method_subplants)} subplant-months have multiple hourly methods assigned." ) @@ -1939,7 +2072,7 @@ def combine_plant_data( def create_plant_attributes_table(cems, eia923_allocated, year, primary_fuel_table): # create a table with the unique plantids from both dataframes - eia_plants = eia923_allocated[ + eia_plants = eia923_allocated.copy()[ ["plant_id_eia", "plant_primary_fuel"] ].drop_duplicates() cems_plants = cems[["plant_id_eia"]].drop_duplicates() diff --git a/src/oge/data_pipeline.py b/src/oge/data_pipeline.py index 13551505..6c18e4c3 100644 --- a/src/oge/data_pipeline.py +++ b/src/oge/data_pipeline.py @@ -360,7 +360,7 @@ def main(args): # create a separate dataframe containing only the EIA data that is missing from cems monthly_eia_data_to_shape = eia923_allocated[ (eia923_allocated["hourly_data_source"] == "eia") - & ~(eia923_allocated["fuel_consumed_mmbtu"].isna()) + #& ~(eia923_allocated["fuel_consumed_mmbtu"].isna()) ] output_data.output_data_quality_metrics( validation.identify_percent_of_data_by_input_source( @@ -384,7 +384,11 @@ def main(args): "monthly", ) validation.check_for_complete_monthly_timeseries( - monthly_plant_data, "monthly_plant_data", ["plant_id_eia"] + df=monthly_plant_data, + df_name="monthly_plant_data", + keys=["plant_id_eia"], + columns_to_check=["net_generation_mwh", "fuel_consumed_for_electricity_mmbtu"], + year=year, ) output_data.output_plant_data( monthly_plant_data, path_prefix, "monthly", args.skip_outputs, plant_attributes @@ -562,6 +566,7 @@ def main(args): shaped_eia_data, path_prefix, args.skip_outputs, + year, ) # set validate parameter to False since validating non-overlapping data requires subplant-level data # since the shaped eia data is at the fleet level, this check will not work. diff --git a/src/oge/output_data.py b/src/oge/output_data.py index 2b598c8e..5747b31a 100644 --- a/src/oge/output_data.py +++ b/src/oge/output_data.py @@ -300,6 +300,7 @@ def write_plant_metadata( shaped_eia_data: pd.DataFrame, path_prefix: str, skip_outputs: bool, + year: int, ): """ Outputs metadata for each subplant-month. @@ -396,7 +397,11 @@ def write_plant_metadata( ).sort_values(by=["plant_id_eia", "subplant_id", "report_date"], ascending=True) validation.check_for_complete_monthly_timeseries( - metadata, "plant_metadata", ["plant_id_eia", "subplant_id"] + df=metadata, + df_name="plant_metadata", + keys=["plant_id_eia", "subplant_id"], + columns_to_check=["hourly_profile_source"], + year=year, ) column_checks.check_columns(metadata, "plant_metadata") diff --git a/src/oge/validation.py b/src/oge/validation.py index e786e8c8..96fff6df 100644 --- a/src/oge/validation.py +++ b/src/oge/validation.py @@ -5,7 +5,7 @@ import oge.impute_hourly_profiles as impute_hourly_profiles import oge.emissions as emissions from oge.column_checks import get_dtypes -from oge.filepaths import downloads_folder, reference_table_folder +from oge.filepaths import downloads_folder, reference_table_folder, outputs_folder from oge.logging_util import get_logger logger = get_logger(__name__) @@ -856,11 +856,19 @@ def check_for_complete_hourly_timeseries( def check_for_complete_monthly_timeseries( - df: pd.DataFrame, df_name: str, keys: list[str] + df: pd.DataFrame, + df_name: str, + keys: list[str], + columns_to_check: list[str], + year: int, ): - """Validates that a dataset contains complete monthly data for all months. + """ + Validates that a dataset contains complete monthly data for all months. - Checks that there are 12 observations for each group of keys + There are two separate checks that are completed: + 1. Ensure that there is a complete set of 12 report_date's for each group + 2. Ensure that missing data within a month is expected based on the availability + of input data Args: df: dataframe containing datetime columns @@ -868,16 +876,55 @@ def check_for_complete_monthly_timeseries( keys: list of column names that contain the groups within which datetimes should be unique """ - # count the number of report_dates in each group - test = df.groupby(keys)[["report_date"]].count() - test["expected_num_months"] = 12 + input_data_inventory = pd.read_csv( + outputs_folder(f"{year}/input_data_inventory_{year}.csv") + ) + + # count the number of report_dates and non-missing data in each group + test = df.groupby(keys)[["report_date"] + columns_to_check].count().reset_index() + # identify the expected number of months of data + expected_months = ( + input_data_inventory.groupby("plant_id_eia")[ + ["input_data_exists", "nonzero_input_data_exists"] + ] + .sum() + .reset_index() + ) + + test = test.merge( + expected_months, + how="outer", + on="plant_id_eia", + ) + test[["report_date"] + columns_to_check] = test[ + ["report_date"] + columns_to_check + ].fillna(0) + + # 1. Check that all 12 months exist for each group # identify any rows where there are less than 12 months of data - test = test[test["report_date"] != test["expected_num_months"]] + missing_rd_test = test.loc[ + (test["report_date"] < 12) & (test["nonzero_input_data_exists"] > 0), + (keys + ["report_date", "input_data_exists", "nonzero_input_data_exists"]), + ] + if len(missing_rd_test) > 0: + logger.warning( + f"There is less than 12 months of data for the following {keys} groups in {df_name}" + ) + logger.warning("\n" + missing_rd_test.to_string()) + + # 2. identify any rows where there is data that is missing + missing_data_test = test[ + ( + test[columns_to_check].min(axis=1) + < test[["input_data_exists", "nonzero_input_data_exists"]].max(axis=1) + ) + & (test["nonzero_input_data_exists"] > 0) + ] if len(test) > 0: logger.warning( - f"There is incomplete monthly data for the following {keys} groups in {df_name}" + f"There appears to be missing data for the following {keys} groups in {df_name}" ) - logger.warning("\n" + test.to_string()) + logger.warning("\n" + missing_data_test.to_string()) # DATA QUALITY METRIC FUNCTIONS From c33ea9b6009532c205c6c86f2db59b50a0209379 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 22 Dec 2023 17:07:43 -0800 Subject: [PATCH 72/85] fix bug with to_string --- src/oge/data_cleaning.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index bffe1a01..679dc62b 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -2180,7 +2180,7 @@ def assign_ba_code_to_plant(df, year): if len(df[df["ba_code"].isna()]) > 0: logger.warning("the following plants are missing ba_code:") - logger.warning("\n" + df[df["ba_code"].isna()].tostring()) + logger.warning("\n" + df[df["ba_code"].isna()].to_string()) # replace missing ba codes with NA df["ba_code"] = df["ba_code"].fillna("NA") From ea9ee2ac41ca5a2a5dc63323000860ee962ec73e Mon Sep 17 00:00:00 2001 From: grgmiller Date: Sat, 23 Dec 2023 11:06:30 -0800 Subject: [PATCH 73/85] fix eia-923 validation --- .../test_allocate_gen_fuel.ipynb | 152 ++++++++++++++++-- src/oge/data_cleaning.py | 16 +- src/oge/data_pipeline.py | 1 - src/oge/validation.py | 7 +- 4 files changed, 159 insertions(+), 17 deletions(-) diff --git a/notebooks/explore_methods/test_allocate_gen_fuel.ipynb b/notebooks/explore_methods/test_allocate_gen_fuel.ipynb index ba3f7724..f522dc04 100644 --- a/notebooks/explore_methods/test_allocate_gen_fuel.ipynb +++ b/notebooks/explore_methods/test_allocate_gen_fuel.ipynb @@ -30,7 +30,7 @@ "outputs": [], "source": [ "# pick a plant to investigate\n", - "plant_to_investigate = 47" + "plant_to_investigate = 50937" ] }, { @@ -68,15 +68,6 @@ "gen[gen[\"plant_id_eia\"] == plant_to_investigate]" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gf[gf[\"plant_id_eia\"] == plant_to_investigate][[\"fuel_consumed_mmbtu\"]].sum()" - ] - }, { "cell_type": "code", "execution_count": null, @@ -103,6 +94,15 @@ ")" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gens_at_freq" + ] + }, { "cell_type": "code", "execution_count": null, @@ -132,6 +132,138 @@ "gen_assoc[gen_assoc[\"plant_id_eia\"] == plant_to_investigate]" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gf[gf[\"plant_id_eia\"] == plant_to_investigate]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "### associate generator tables step by step\n", + "\n", + "\n", + "stack_gens = allocate_gen_fuel.stack_generators(\n", + " gens_at_freq, cat_col=\"energy_source_code_num\", stacked_col=\"energy_source_code\"\n", + ").pipe(allocate_gen_fuel.apply_pudl_dtypes, group=\"eia\")\n", + "# allocate the boiler fuel data to generators\n", + "bf_by_gens = (\n", + " allocate_gen_fuel.allocate_bf_data_to_gens(bf, gens, bga)\n", + " .set_index(allocate_gen_fuel.IDX_GENS_PM_ESC)\n", + " .add_suffix(\"_bf_tbl\")\n", + " .reset_index()\n", + " .pipe(allocate_gen_fuel.apply_pudl_dtypes, group=\"eia\")\n", + ")\n", + "gf = (\n", + " gf.set_index(allocate_gen_fuel.IDX_PM_ESC)[allocate_gen_fuel.DATA_COLUMNS]\n", + " .add_suffix(\"_gf_tbl\")\n", + " .reset_index()\n", + " .pipe(allocate_gen_fuel.apply_pudl_dtypes, group=\"eia\")\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gen_assoc = pd.merge(\n", + " stack_gens,\n", + " gen.rename(columns={\"net_generation_mwh\": \"net_generation_mwh_g_tbl\"}),\n", + " on=allocate_gen_fuel.IDX_GENS,\n", + " how=\"outer\",\n", + ").merge(\n", + " gf, on=allocate_gen_fuel.IDX_PM_ESC, how=\"outer\", validate=\"m:1\", indicator=True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# identify the complete set of generator ids that match this criteria\n", + "retiring_generator_identities = gen_assoc.loc[\n", + " (gen_assoc.operational_status == \"retired\")\n", + " & (\n", + " (gen_assoc.report_date <= gen_assoc.generator_retirement_date)\n", + " | (gen_assoc.net_generation_mwh_g_tbl.notnull())\n", + " ),\n", + " [\"plant_id_eia\", \"generator_id\"],\n", + "].drop_duplicates()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# merge these ids into gen_assoc and keep all months of data for these gens\n", + "retiring_generators = gen_assoc.copy().merge(\n", + " retiring_generator_identities,\n", + " how=\"outer\",\n", + " on=[\"plant_id_eia\", \"generator_id\"],\n", + " indicator=\"_retiring_gens\",\n", + ")\n", + "\n", + "retiring_generators = retiring_generators[\n", + " retiring_generators[\"_retiring_gens\"] == \"both\"\n", + "].drop(columns=\"_retiring_gens\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "retiring_generators[retiring_generators[\"plant_id_eia\"] == plant_to_investigate]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gen_assoc = gen_assoc.pipe(allocate_gen_fuel.remove_inactive_generators)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gen_assoc[gen_assoc[\"plant_id_eia\"] == plant_to_investigate]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "unassociated_plants[unassociated_plants[\"plant_id_eia\"] == plant_to_investigate]" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/src/oge/data_cleaning.py b/src/oge/data_cleaning.py index 679dc62b..059313ee 100644 --- a/src/oge/data_cleaning.py +++ b/src/oge/data_cleaning.py @@ -745,7 +745,7 @@ def calculate_aggregated_primary_fuel( # identify the fuel type with the maximum value for each plant primary_fuel_calc = primary_fuel_calc[ - primary_fuel_calc.groupby(agg_keys, dropna=False)[source].transform(max) + primary_fuel_calc.groupby(agg_keys, dropna=False)[source].transform("max") == primary_fuel_calc[source] ][agg_keys + ["energy_source_code"]] @@ -852,7 +852,7 @@ def calculate_capacity_based_primary_fuel(agg_level, agg_keys, year): # find the fuel with the greatest capacity gen_capacity = gen_capacity[ - gen_capacity.groupby(agg_keys, dropna=False)["capacity_mw"].transform(max) + gen_capacity.groupby(agg_keys, dropna=False)["capacity_mw"].transform("max") == gen_capacity["capacity_mw"] ][agg_keys + ["energy_source_code_1"]].rename( columns={"energy_source_code_1": f"{agg_level}_primary_fuel_from_capacity_mw"} @@ -2196,15 +2196,25 @@ def create_plant_ba_table(year): plant_ba = load_data.load_pudl_table( "plants_eia860", - year, columns=[ "plant_id_eia", + "report_date", "balancing_authority_code_eia", "balancing_authority_name_eia", "utility_id_eia", "transmission_distribution_owner_name", ], ) + + # remove report dates newer than the current year + plant_ba = plant_ba[plant_ba["report_date"].dt.year <= year] + + # sort the data from newest to oldest + plant_ba = plant_ba.sort_values(by=["plant_id_eia", "report_date"], ascending=False) + + # only keep the most recent row of data + plant_ba = plant_ba.drop_duplicates(subset=["plant_id_eia"], keep="first") + # merge utility name utilities_eia = load_data.load_pudl_table( "utilities_eia", columns=["utility_id_eia", "utility_name_eia"] diff --git a/src/oge/data_pipeline.py b/src/oge/data_pipeline.py index 6c18e4c3..918499ff 100644 --- a/src/oge/data_pipeline.py +++ b/src/oge/data_pipeline.py @@ -360,7 +360,6 @@ def main(args): # create a separate dataframe containing only the EIA data that is missing from cems monthly_eia_data_to_shape = eia923_allocated[ (eia923_allocated["hourly_data_source"] == "eia") - #& ~(eia923_allocated["fuel_consumed_mmbtu"].isna()) ] output_data.output_data_quality_metrics( validation.identify_percent_of_data_by_input_source( diff --git a/src/oge/validation.py b/src/oge/validation.py index 96fff6df..d68dbf3e 100644 --- a/src/oge/validation.py +++ b/src/oge/validation.py @@ -66,9 +66,10 @@ def check_allocated_gf_matches_input_gf(year, gen_fuel_allocated): ] ].sum() # calculate the percentage difference between the values - plant_total_diff = ((plant_total_alloc - plant_total_gf) / plant_total_gf).dropna( - how="any", axis=0 - ) + # replace 0s with small sentinel value to prevent missing values from divide by zero + plant_total_diff = ( + (plant_total_alloc - plant_total_gf) / plant_total_gf.replace(0, 0.00001) + ).dropna(how="all", axis=0) # flag rows where the absolute percentage difference is greater than our threshold mismatched_allocation = plant_total_diff[ (~np.isclose(plant_total_diff["fuel_consumed_mmbtu"], 0)) From de10b0a016cce8caae6eb113170017d8880825b3 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Wed, 27 Dec 2023 14:48:50 -0800 Subject: [PATCH 74/85] update documentation --- README.md | 2 +- .../Data Validation/Comparing Data to eGRID.md | 2 +- .../Shaping Using Fleet-Specific Profiles.md | 2 +- .../Summary.md | 2 +- docs/docs/Methodology/Data Cleaning/CEMS Data.md | 14 ++++++-------- .../docs/Methodology/Data Cleaning/EIA-923 Data.md | 4 ++-- .../Adjusting Emissions for Biomass.md | 2 +- .../Emissions Calculations/GHG Emissions.md | 4 ++-- .../Emissions Calculations/NOx Emissions.md | 2 +- .../Methodology/Emissions Calculations/Overview.md | 2 +- .../Emissions Calculations/SO2 Emissions.md | 2 +- docs/docs/Methodology/Method_overview.md | 5 ++--- .../Contributing to the Code Repository.md | 2 +- docs/docs/Overview/Using the Data.md | 6 ++---- src/oge/load_data.py | 1 - 15 files changed, 23 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index ed1f4069..c914d224 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ A more detailed walkthrough of these steps can be found below in the "Developmen ## Data Availability and Release Schedule The latest release includes data for year 2019-2021 covering the contiguous United States, Alaska, and Hawaii. In future releases, we plan to expand the geographic coverage to additional U.S. territories (dependent on data availability), and to expand the historical coverage of the data. -Parts of the input data used for the Open Grid Emissions dataset is released by the U.S. Energy Information Administration in the Autumn following the end of each year (2022 data should be available Autumn 2023). Each release will include the most recent year of available data as well as updates of all previous available years based on any updates to the OGEI methodology. All previous versions of the data will be archived on Zenodo. +Parts of the input data used for the Open Grid Emissions dataset is released by the U.S. Energy Information Administration in the Autumn following the end of each year (2022 data was published in September 2023). Each release will include the most recent year of available data as well as updates of all previous available years based on any updates to the OGE methodology. All previous versions of the data will be archived on Zenodo. Updated datasets will also be published whenever a new version of the open-grid-emissions repository is released. diff --git a/docs/docs/Data Validation/Comparing Data to eGRID.md b/docs/docs/Data Validation/Comparing Data to eGRID.md index 1680d928..7ee7b165 100644 --- a/docs/docs/Data Validation/Comparing Data to eGRID.md +++ b/docs/docs/Data Validation/Comparing Data to eGRID.md @@ -1,7 +1,7 @@ --- stoplight-id: egrid_comparison --- -Although the OGEI methodology is based on the EPA's eGRID methodology, there are some important differences. Thus, if comparing OGEI data to eGRID data, it is important to keep the following differences in mind: +Although the OGE methodology is based on the EPA's eGRID methodology, there are some important differences. Thus, if comparing OGEI data to eGRID data, it is important to keep the following differences in mind: diff --git a/docs/docs/Methodology/Assigning Hourly Profiles to Monthly Data/Shaping Using Fleet-Specific Profiles.md b/docs/docs/Methodology/Assigning Hourly Profiles to Monthly Data/Shaping Using Fleet-Specific Profiles.md index 177103a2..abdf2061 100644 --- a/docs/docs/Methodology/Assigning Hourly Profiles to Monthly Data/Shaping Using Fleet-Specific Profiles.md +++ b/docs/docs/Methodology/Assigning Hourly Profiles to Monthly Data/Shaping Using Fleet-Specific Profiles.md @@ -63,7 +63,7 @@ Our understanding is that the BA reported in EIA-860 represents the plant’s co **Fuel code assignment** -The primary fuel codes assigned to each plant in the OGEI pipeline may not match the generator primary fuel code used by the balancing authority. Thus, it is possible that the set of plants classified as “natural gas”, for example, in EIA-930 may be different from the set of plants that we classify as natural gas. +The primary fuel codes assigned to each plant in the OGE pipeline may not match the generator primary fuel code used by the balancing authority. Thus, it is possible that the set of plants classified as “natural gas”, for example, in EIA-930 may be different from the set of plants that we classify as natural gas. **Inclusion of distribution-connected plants** diff --git a/docs/docs/Methodology/Assigning Hourly Profiles to Monthly Data/Summary.md b/docs/docs/Methodology/Assigning Hourly Profiles to Monthly Data/Summary.md index ebda5350..627f0a38 100644 --- a/docs/docs/Methodology/Assigning Hourly Profiles to Monthly Data/Summary.md +++ b/docs/docs/Methodology/Assigning Hourly Profiles to Monthly Data/Summary.md @@ -9,7 +9,7 @@ One of the novel contributions of the Open Grid Emissions Initiative is a method ### Summary of approaches -The hourly data provided by the OGEI is a combination of measured hourly data reported in CEMS and monthly data reported in EIA-923 which is assigned an imputed hourly profile. +The hourly data provided by the OGE is a combination of measured hourly data reported in CEMS and monthly data reported in EIA-923 which is assigned an imputed hourly profile. The first step in ensuring complete data coverage is identifying the subplant-months for which complete data is available from either source. If complete CEMS data is available for all hours in a month and for all units in a subplant, the reported CEMS data is used for that subplant month. If the CEMS data for a subplant-month is incomplete or not available, the reported EIA-923 is used, and an hourly profile must be assigned to it. diff --git a/docs/docs/Methodology/Data Cleaning/CEMS Data.md b/docs/docs/Methodology/Data Cleaning/CEMS Data.md index 15c32709..baf7ed71 100644 --- a/docs/docs/Methodology/Data Cleaning/CEMS Data.md +++ b/docs/docs/Methodology/Data Cleaning/CEMS Data.md @@ -3,26 +3,24 @@ stoplight-id: cleaning_cems --- ## Loading data from PUDL -All of the CEMS data used by the OGEI is loaded from pre-cleaned versions of these files created by the PUDL project. The PUDL transformation process cleans the input data so that it is adjusted for uniformity, corrected for errors, and ready for bulk programmatic use. +All of the CEMS data used by OGE is loaded from pre-cleaned versions of these files created by the PUDL project. The PUDL transformation process cleans the input data so that it is adjusted for uniformity, corrected for errors, and ready for bulk programmatic use. A comprehensive list of transformations made by by pudl can be found [here](https://catalystcoop-pudl.readthedocs.io/en/latest/data_sources/epacems.html#pudl-data-transformations) , but the most notable data cleaning that pudl performs is: - converts all datetimes to UTC - - Corrects anomalous `gross_load_mw` values (if a gross load value is greater than 2,000 MW, they assume that they have accidentally reported kWh, so the gross load value is divided by 1,000). - - fills missing `gross_load_mw` and `heat_content_mmbtu` values with zero (NOTE: This step causes issues with later data cleaning steps by making it difficult to differentiate between missing values and measured zeros. We are working with the Catalyst team to fix this. Track progress [here](https://github.com/catalyst-cooperative/pudl/issues/604)) + - Corrects anomalous `gross_load_mw` values (if a gross load value is greater than 2,000 MW, they assume that they have accidentally reported kWh, so the gross load value is divided by 1,000). This may cause errors if a single unit greater than 2GW of nameplate capacity is ever built. + - Harmonizes plant ID codes between the EPA version and the EIA version (For some plants, the EPA uses different plant codes from the ones used by the EI.), based on the EPA-EIA power sector data crosswalk (Note: The PSDC does not contain the most up to date plant ID crosswalk. We supplement this matching using the `epa_eia_crosswalk_manual.csv` reference table in OGE) After loading the transformed cems data into the pipeline, we perform several other data cleaning steps: - Convert `co2_mass_tons` to `co2_mass_lb` so that all emissions mass units are standardized. -- Convert the `plant_id_epa` to `plant_id_eia`. For some plants, the EPA uses different plant codes from the ones used by the EIA. In order to accurately match plant data between CEMS and the EIA datasets, we use the EPA's [Power Sector Data Crosswalk](https://www.epa.gov/airmarkets/power-sector-data-crosswalk) to convert these IDs. -- Remove leading zeros from the `unitid` column to enable matching with other tables. +- Add a "report date" to each data point to enable crosswalking with monthly EIA-923 data. This report date reflects the month of the local prevailing time for each plant's reported hourly data. ## Data removed from the CEMS data Certain data reported to CEMS are removed, including: - Data for plants that are not connected to the electrical grid (These include all plants with a `plant_id_eia` of `88xxxx` and the plants in [this table](https://github.com/singularity-energy/open-grid-emissions/blob/main/data/manual/plants_not_connected_to_grid.csv)) - Data for plants in Puerto Rico (These data will be added in a future release. Track progress [here](https://github.com/singularity-energy/open-grid-emissions/issues/79)) -- Certain units report only steam production (and no electricity generation) and also do not report any data to the EIA. A list of these units can be found [here](https://github.com/singularity-energy/open-grid-emissions/blob/main/data/manual/steam_units_to_remove.csv) -- Data for any unit-months where there is incomplete hourly data for the entire month are dropped. -- Data for any unit-months where zero generation, fuel consumption, and emissions reported are removed, so that we can check if non-zero data was reported for this unit in EIA-923. This step is partially necessary because we cannot currently tell the difference between missing data and measured zeros (see above section). +- Data for any unit-months where there is less than one day of non-missing data are dropped. This is generally months that have a single hour of data reported. + ## Imputing missing emissions data Although CEMS reports measured hourly CO2, NOx, and SO2 emissions, in some cases these data are missing. In addition, there is no data reported for CH4 and N2O. diff --git a/docs/docs/Methodology/Data Cleaning/EIA-923 Data.md b/docs/docs/Methodology/Data Cleaning/EIA-923 Data.md index 07e5480a..470a0c0c 100644 --- a/docs/docs/Methodology/Data Cleaning/EIA-923 Data.md +++ b/docs/docs/Methodology/Data Cleaning/EIA-923 Data.md @@ -4,9 +4,9 @@ stoplight-id: cleaning_eia923 ## Loading data from PUDL -All of the generation and fuel consumption data that the OGEI uses from EIA-923 comes from pre-cleaned tables from the PUDL project, rather than from raw EIA-923 webfiles. The PUDL transformation process cleans the input data so that it is adjusted for uniformity, corrected for errors, and ready for bulk programmatic use. More information about the transformations that PUDL applies to the raw data can be found [here](https://catalystcoop-pudl.readthedocs.io/en/latest/data_sources/eia923.html#pudl-data-transformations). +All of the generation and fuel consumption data that OGE uses from EIA-923 comes from pre-cleaned tables from the PUDL project, rather than from raw EIA-923 webfiles. The PUDL transformation process cleans the input data so that it is adjusted for uniformity, corrected for errors, and ready for bulk programmatic use. More information about the transformations that PUDL applies to the raw data can be found [here](https://catalystcoop-pudl.readthedocs.io/en/latest/data_sources/eia923.html#pudl-data-transformations). -Because annual environmental information from EIA-923 has not yet been integrated into PUDL, these tables are loaded from the raw files, and column names are changed so that they are consistent with the column names used in PUDL. +Because annual emissions control data from EIA-923 (Schedule 8) has not yet been integrated into PUDL, these tables are loaded from the raw files, and column names are changed so that they are consistent with the column names used in PUDL. ## Allocating Generation and Fuel Data diff --git a/docs/docs/Methodology/Emissions Calculations/Adjusting Emissions for Biomass.md b/docs/docs/Methodology/Emissions Calculations/Adjusting Emissions for Biomass.md index 942a55f4..364633d8 100644 --- a/docs/docs/Methodology/Emissions Calculations/Adjusting Emissions for Biomass.md +++ b/docs/docs/Methodology/Emissions Calculations/Adjusting Emissions for Biomass.md @@ -10,7 +10,7 @@ However, this approach of assuming zero emissions from biomass combustion is pro 1. There is much debate in the academic literature about the assumption of zero net emissions from biomass. This is far from a comprehensive literature review on the topic, but for example see: [Johnson 2009](https://www.sciencedirect.com/science/article/pii/S0195925508001637), [Cherubini et al 2011](https://onlinelibrary.wiley.com/doi/abs/10.1111/j.1757-1707.2011.01102.x), [Haberl et al 2012](https://www.sciencedirect.com/science/article/pii/S0301421512001681), [Downie et al 2014](https://www.sciencedirect.com/science/article/pii/S0961953413004820) 2. This approach selectively applies a partial life-cycle accounting approach to biomass fuels (as it consideres the upstream emissions impacts of the fuel), which is inconsistent with the treatment of other fuels in this dataset -Based on our current understanding of this topic, it may not be appropriate to use biomass-adjusted emissions data for carbon accounting or other general uses, unless they are being used in a specific policy or regulatory context that treats biomass emissions as carbon neutral. Thus, biomass-adjusted emissions are only included in the OGEI dataset for consistency with eGRID and for use in these niche cases. All emissions data that has been adjusted for biomass emissions will include `_adjusted` in the name of the column. +Based on our current understanding of this topic, it may not be appropriate to use biomass-adjusted emissions data for carbon accounting or other general uses, unless they are being used in a specific policy or regulatory context that treats biomass emissions as carbon neutral. Thus, biomass-adjusted emissions are only included in the OGE dataset for consistency with eGRID and for use in these niche cases. All emissions data that has been adjusted for biomass emissions will include `_adjusted` in the name of the column. ## Calculating biomass-adjusted emissions Adjusted CO2 emissions are set to zero for all biomass fuel consumption, including agricultural byproducts (AB), black liquor (BLQ), landfill gas (LFG), biogenic municipal solid waste (MSB), other biomass gas (OBG), other biomass liquids (OBL), other biomass solids (OBS), sludge waste (SLW), wood and wood waste solids (WDS), and wood waste liquids (WDL). diff --git a/docs/docs/Methodology/Emissions Calculations/GHG Emissions.md b/docs/docs/Methodology/Emissions Calculations/GHG Emissions.md index a9c37941..e3c5d6fc 100644 --- a/docs/docs/Methodology/Emissions Calculations/GHG Emissions.md +++ b/docs/docs/Methodology/Emissions Calculations/GHG Emissions.md @@ -25,9 +25,9 @@ MassCO2e = (Massco2 * GWPco2) + (Massch4 Date: Wed, 27 Dec 2023 15:21:05 -0800 Subject: [PATCH 75/85] update version --- CITATION.cff | 4 ++-- LICENSE.md | 2 +- Pipfile | 4 ++-- README.md | 4 ++-- pyproject.toml | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index c09f942e..8ea2eda0 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -22,6 +22,6 @@ authors: identifiers: - type: doi value: 'https://doi.org/10.5281/zenodo.7692997' -version: 0.2.2 +version: 0.3.0 license: MIT -date-released: '2023-03-02' +date-released: '2023-12-29' diff --git a/LICENSE.md b/LICENSE.md index 5928dcf1..d890bb7d 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Singularity Energy +Copyright (c) 2023 Singularity Energy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Pipfile b/Pipfile index 0bb3992e..3ee8e796 100644 --- a/Pipfile +++ b/Pipfile @@ -20,8 +20,8 @@ seaborn = "*" sqlalchemy = "*" statsmodels = "*" coloredlogs = "*" -"catalystcoop.pudl" = {git = "git+https://github.com/singularity-energy/pudl.git"} -gridemissions = {git = "git+https://github.com/gailin-p/gridemissions"} +"catalystcoop.pudl" = {git = "git+https://github.com/singularity-energy/pudl.git@oge_dev"} +gridemissions = {git = "git+https://github.com/singularity-energy/gridemissions"} [dev-packages] ruff = "*" diff --git a/README.md b/README.md index c914d224..2df74465 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ The Open Grid Emissions Initiative seeks to fill a critical need for high-quality, publicly-accessible, hourly grid emissions data that can be used for GHG accounting, policymaking, academic research, and energy attribute certificate markets. The initiative includes this repository of open-source grid emissions data processing tools that use peer-reviewed, well-documented, and validated methodologies to create the accompanying public dataset of hourly, monthly, and annual U.S. electric grid generation, GHG, and air pollution data. -Please check out [our documentation](https://docs.singularity.energy/docs/open-grid-emissions-docs) for more details about the Open Grid Emissions methodology. +Please check out [our documentation](https://docs.singularity.energy/docs/open-grid-emissions) for more details about the Open Grid Emissions methodology. The Open Grid Emissions Dataset can be [downloaded here](https://singularity.energy/open-grid-emissions). An archive of previous versions of the dataset and intermediate data outputs (for research and validation purposes) can be found on [Zenodo](https://zenodo.org/communities/singularity-energy?page=1&size=20). @@ -35,7 +35,7 @@ pipenv shell The pipeline can be run as follows: ```bash cd src -python data_pipeline.py --year 2021 +python data_pipeline.py --year 2022 ``` independently of the installation method you chose. diff --git a/pyproject.toml b/pyproject.toml index 56e5ab1c..aaa51169 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "hatchling.build" [project] name = "oge" -version = "0.2.2" +version = "0.3.0" requires-python = ">3.11" readme = "README.md" authors = [ @@ -32,8 +32,8 @@ dependencies = [ "sqlalchemy", "statsmodels", "coloredlogs", - "catalystcoop-pudl@git+https://github.com/singularity-energy/pudl.git", - "gridemissions@git+https://github.com/gailin-p/gridemissions.git", + "catalystcoop-pudl@git+https://github.com/singularity-energy/pudl.git@oge_dev", + "gridemissions@git+https://github.com/singularity-energy/gridemissions.git", ] [project.optional-dependencies] From b3681e062c4b7131e8e5445c790aa9376ba73c4a Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 28 Dec 2023 15:22:34 -0800 Subject: [PATCH 76/85] add known issues to docs --- CITATION.cff | 6 +- docs/docs/Data Validation/Known Issues.md | 171 +++++++ ...26_investigate_incomplete_timeseries.ipynb | 464 ++++++++++++++++++ .../emission_factors_for_nox.csv | 4 + toc.json | 5 + 5 files changed, 647 insertions(+), 3 deletions(-) create mode 100644 docs/docs/Data Validation/Known Issues.md create mode 100644 notebooks/work_in_progress/GH326_investigate_incomplete_timeseries.ipynb diff --git a/CITATION.cff b/CITATION.cff index 8ea2eda0..cfcfdf3d 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -12,12 +12,12 @@ authors: family-names: Pease orcid: 'https://orcid.org/0000-0003-3528-6048' affiliation: "Singularity Energy" - - given-names: Milo - family-names: Knowles - orcid: 'https://orcid.org/0000-0003-4052-5517' + - given-names: Benjamin + family-names: Rouille d'Orfeuil affiliation: "Singularity Energy" - given-names: Wenbo family-names: Shi + orcid: 'https://orcid.org/0000-0003-4889-0834' affiliation: "Singularity Energy" identifiers: - type: doi diff --git a/docs/docs/Data Validation/Known Issues.md b/docs/docs/Data Validation/Known Issues.md new file mode 100644 index 00000000..5b476577 --- /dev/null +++ b/docs/docs/Data Validation/Known Issues.md @@ -0,0 +1,171 @@ +--- +stoplight-id: known_issues +--- +## Known Issues +While to our knowledge, the published OGE data represents the highest-quality data of its kind that is publicly available, there are nevertheless a number of known data quality issues with the published OGE data. + +We maintain a [list of these known issues on GitHub](https://github.com/singularity-energy/open-grid-emissions/issues), and seek to prioritize and fix these issues over time. + +When running the OGE data pipeline, we run a growing number of [validation checks](https://github.com/singularity-energy/open-grid-emissions/blob/main/src/validation.py) on the data at all stages of the pipeline to ensure that no unexpected transformations are occuring and the data is as complete and accurate as possible. The full results of these validation checks can be viewed in the `data_pipeline.txt` file included with the `data_quality_metrics` results, but we have also summarized warnings raised by these validation checks for the 2022 data below. + +### Some subplants only contain a single component of a combined-cycle generator +When identifying subplants that include a combined cycle generator, the subplant should include both parts (i.e. the steam turbine with prime mover CA and the combustion turbine with prime mover CT). In 2022, we identified 259 subplants (out of over 33,000) that only include a single combined cycle part. This could affect the accuracy of our data crosswalks between EIA data and CEMS data. + +``` + unique_cc_pms +plant_id_eia subplant_id +3 7.0 CT + 8.0 CA +56 3.0 CT + 4.0 CA +96 6.0 CA +341 4.0 CT + 5.0 CT + 6.0 CT + 7.0 CA + 8.0 CA +[...] +``` + +### Some generation and fuel data from EIA-923 is being erroneously allocated +For 8 plants, the total generation or fuel allocated to individual generators does not match the total generation or fuel associated with the plant in the raw input data. Possible causes include inconsistent reporting of prime movers or fuel types between EIA-923 tables, mid-year plant retirements, anomalous fuel totals being reported, or other unknown issues. + +``` +2023-12-23 11:27:47,744 [WARNING] oge.oge.validation:79 Allocated EIA-923 doesn't match input data for plants: +2023-12-23 11:27:47,744 [WARNING] oge.oge.validation:80 Percentage Difference: +2023-12-23 11:27:47,744 [WARNING] oge.oge.validation:81 + net_generation_mwh fuel_consumed_mmbtu fuel_consumed_for_electricity_mmbtu +plant_id_eia +1316 0.071287 0.000000 0.000000 +10613 0.000000 0.005637 0.033157 +50937 0.000000 -0.121487 -0.121487 +54724 -1.000000 -1.000000 -1.000000 +54809 0.000000 -0.302998 -0.797823 +58256 0.142367 0.000000 0.000000 +59817 -0.054505 -0.054741 -0.054741 +59825 -1.000000 -1.000000 -1.000000 +65498 -1.000000 -1.000000 -1.000000 +2023-12-23 11:27:47,744 [WARNING] oge.oge.validation:82 EIA-923 Input Totals: +2023-12-23 11:27:47,744 [WARNING] oge.oge.validation:83 + net_generation_mwh fuel_consumed_mmbtu fuel_consumed_for_electricity_mmbtu +plant_id_eia +1316 505.00 17176.0 17176.0 +10613 373515.00 9084933.0 1544644.0 +50937 0.00 1103.0 1103.0 +54724 98804.00 337120.0 337120.0 +54809 9033.11 1493143.0 567067.0 +58256 583.00 2274.0 2274.0 +59817 1798.00 6138.0 6138.0 +59825 9972.00 34024.0 34024.0 +65498 1158.00 3950.0 3950.0 +2023-12-23 11:27:47,744 [WARNING] oge.oge.validation:86 Allocated Totals: +2023-12-23 11:27:47,744 [WARNING] oge.oge.validation:87 + net_generation_mwh fuel_consumed_mmbtu fuel_consumed_for_electricity_mmbtu +plant_id_eia +1316 541.00 17176.0 17176.0 +10613 373515.00 9136149.0 1595860.0 +50937 0.00 969.0 969.0 +54724 0.00 0.0 0.0 +54809 9033.11 1040724.0 114648.0 +58256 666.00 2274.0 2274.0 +59817 1700.00 5802.0 5802.0 +59825 0.00 0.0 0.0 +65498 0.00 0.0 0.0 +``` + +### Primary fuel assignment is inconsistent with capacity-based assignment +In OGE, we assign a primary fuel to a plant based on the fuel that was consumed in the highest volume (by mmBTU) in a year, rather than based on the greatest nameplate capacity associated with a fuel (which is used in other contexts). Our validation check flagged 173 plants where our primary fuel assignment is inconsistent with a capacity-based assignment. + +``` +023-12-23 11:27:50,249 [WARNING] oge.oge.validation:141 There are 173 plants where the assigned primary fuel doesn't match the capacity-based primary fuel. +It is possible that these plants will categorized as a different fuel in EIA-930 +2023-12-23 11:27:50,249 [WARNING] oge.oge.validation:144 + plant_id_eia plant_primary_fuel_from_capacity_mw plant_primary_fuel plant_primary_fuel_from_capacity_mw_category plant_primary_fuel_category +23 47 BIT NG coal natural_gas +33 63 DFO WAT petroleum hydro +49 91 DFO WAT petroleum hydro +81 160 NG SUB natural_gas coal +278 460 NG DFO natural_gas petroleum +288 477 BIT NG coal natural_gas +305 508 SUB WND coal wind +333 552 DFO WAT petroleum hydro +336 557 JF WAT petroleum hydro +[...] +``` + +### Missing NOx and SO2 emission factors for Fuel Cells +Our validation check identifies that there are missing NOx and SO2 emission factors for plants with fuel cell prime movers. This is a known and expected issue - to our knowledge emission factors for fuel cells have not yet been published. + +### Certain subplants have inconsistent gross and net generation values +In general, a subplant's net generation should be some smaller percentage of the total gross generation. + +However, there are a number of plants that have positive net generation but zero gross generation. +``` +2023-12-23 11:40:28,584 [WARNING] oge.oge.validation:375 There are 949 subplants at 405 plants for which there is zero gross generation associated with positive net generation. +2023-12-23 11:40:28,599 [WARNING] oge.oge.validation:378 + plant_id_eia subplant_id report_date gross_generation_mwh net_generation_mwh data_source +82 7 0 2022-11-01 0.0 1180.0 both +144 10 3 2022-01-01 0.0 8.1 both +146 10 3 2022-03-01 0.0 3.8 both +151 10 3 2022-08-01 0.0 1431.3 both +[...] +``` + +There are also a number of plants that have zero net generation associated with positive gross generation +``` +2023-12-23 11:40:28,599 [WARNING] oge.oge.validation:412 There are 76 subplants at 62 plants for which there is zero net generation associated with positive gross generation. +2023-12-23 11:40:28,599 [WARNING] oge.oge.validation:415 + plant_id_eia subplant_id report_date gross_generation_mwh net_generation_mwh data_source +843 141 2 2022-04-01 6733.0 0.0 both +844 141 2 2022-05-01 4482.0 0.0 both +845 141 2 2022-06-01 11353.0 0.0 both +846 141 2 2022-07-01 16718.0 0.0 both +``` +There are also a number of plants where the total annual net generation is substantially higher than the reported gross generation: +``` +2023-12-23 11:40:28,646 [WARNING] oge.oge.validation:451 The following plants have annual net generation that is >125% of annual gross generation: +2023-12-23 11:40:28,646 [WARNING] oge.oge.validation:454 + plant_id_eia gross_generation_mwh net_generation_mwh annual_plant_ratio +772 54096 18039.0 162310.0 8.997727 +693 10567 17734.0 134118.2 7.562772 +293 2831 1913.0 7158.4 3.741976 +1017 55470 1200399.0 3786786.0 3.154606 +``` +These warnings could be the result of incorrect crosswalking between subplants, inconsistent or inaccurate reporting of generation data by the plant, or an incorrect monthly allocation of annually-reported EIA-923 data by the EIA. + +### Several plants are missing default gross-to-net conversion factors +``` +2023-12-23 11:41:07,486 [WARNING] oge.oge.gross_to_net_generation:93 The following subplants are missing default GTN ratios. Using a default value of 0.97 +2023-12-23 11:41:07,486 [WARNING] oge.oge.gross_to_net_generation:96 + plant_id_eia subplant_id +17264257 50733 2 +17338728 50900 4 +23352705 55641 1 +``` + +### Our calculated net generation does not match reported net generation for several plants +Currently, we trust CEMS gross generation data more than EIA-923 net generation data, so in certain instances where these are inconsistent with each other, we use default gross-to-net conversion factors to calculate net generation from the CEMS data, which means that the net generation data will not match what is reported in EIA-923. + +``` +2023-12-23 11:41:12,857 [WARNING] oge.oge.validation:528 There are 6 plants where calculated annual net generation does not match EIA annual net generation. +2023-12-23 11:41:12,872 [WARNING] oge.oge.validation:531 + net_generation_mwh_eia net_generation_mwh_calc pct_error gtn_method +plant_id_eia +3406 845833.6 1228806.261 0.452775 [5_annual_fuel_ratio, 6_default_eia_ratio, 4_annual_plant_shift_factor] +8906 828822.0 1736788.787 1.095491 [5_annual_fuel_ratio, 6_default_eia_ratio] +50625 3444415.8 6045743.480 0.755230 [6_default_eia_ratio] +55075 1276484.0 1817106.918 0.423525 [5_annual_fuel_ratio] +57865 41887.8 753792.480 16.995514 [5_annual_fuel_ratio, 6_default_eia_ratio] +62192 3019018.0 4452630.770 0.474861 [6_default_eia_ratio] +``` + +### Some data outputs are missing complete monthly or hourly values +Currently, there are a number of plants for which there may not be 12 reported monthly values or 8760 reported hourly values in the OGE outputs. These likely represent missing input data, but we are working to fill these missing timestamps and ensure that no data is being mistakenly dropped from the data pipeline. + +In some of the regional data, the validation checks flagged certain fuel types for which there are more than 8760 reported values in a year. This appears to result when a BA spans multiple time zones. We are investigating this in more detail to correct this issue. + +### Some plants have extreme emission factors +There are approximately 30 plants that have extremely high or low calculated emission rates. The extreme low values appear to mostly occur when a clean plant (eg nuclear) has a fossil-based backup generator that ocassionally runs, resulting in a small amount of emissions relative to the total generation. The extreme high values appear to mostly occur at natural gas and petroleum plants with a small amount of net generation. These may represent peaker plants or spinning reserves, which consume a large amount of fuel throughout the year, but generate only a small amount of net electricity. + +### Negative consumed emission rates in HST +For the small balancing area of HST (City of Homestead, FL), there are 62 hours when the calculated consumed emission rate is negative. We are currently investigating this issue, but did not correct this prior to the data release given that it affected only a small number of hours in a small balancing area. \ No newline at end of file diff --git a/notebooks/work_in_progress/GH326_investigate_incomplete_timeseries.ipynb b/notebooks/work_in_progress/GH326_investigate_incomplete_timeseries.ipynb new file mode 100644 index 00000000..9ed3494a --- /dev/null +++ b/notebooks/work_in_progress/GH326_investigate_incomplete_timeseries.ipynb @@ -0,0 +1,464 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# import packages\n", + "import pandas as pd\n", + "import numpy as np\n", + "import os\n", + "import plotly.express as px\n", + "\n", + "%reload_ext autoreload\n", + "%autoreload 2\n", + "\n", + "# # Tell python where to look for modules.\n", + "import sys\n", + "\n", + "sys.path.append(\"../../src/\")\n", + "\n", + "import oge.download_data as download_data\n", + "import oge.load_data as load_data\n", + "from oge.column_checks import get_dtypes\n", + "from oge.filepaths import *\n", + "import oge.impute_hourly_profiles as impute_hourly_profiles\n", + "import oge.data_cleaning as data_cleaning\n", + "import oge.output_data as output_data\n", + "import oge.emissions as emissions\n", + "import oge.validation as validation\n", + "import oge.gross_to_net_generation as gross_to_net_generation\n", + "import oge.eia930 as eia930\n", + "from oge.logging_util import get_logger, configure_root_logger\n", + "\n", + "configure_root_logger()\n", + "logger = get_logger(\"test\")\n", + "\n", + "\n", + "year = 2022\n", + "path_prefix = f\"{year}/\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Evaluate plants with 8761 data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data = pd.read_csv(results_folder(f\"{year}/plant_data/hourly/us_units/MISO.csv\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test = data.pivot(index=\"datetime_utc\",columns=\"plant_id_eia\", values=\"plant_id_eia\")\n", + "test" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test.loc[\"2023-01-01 06:00:00+00:00\",:].dropna()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test[50240]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# plant 50240 is located in ET, where MISO spans from MT to CT to ET. 50240 has data \n", + "# starting 5am UTC (expected for EST), but ending at 5am UTC (it should end 4am.)\n", + "# It looks like this plant has data for December from both CEMS and EIA\n", + "# it is possible that we are using CT to shape the EIA data since this is in MISO - \n", + "# we need to make sure that we are using plant-specific time zones" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems_cleaned = pd.read_csv(outputs_folder(\"2022/cems_subplant_2022.csv\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems_cleaned[cems_cleaned[\"plant_id_eia\"] == 50240]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# It looks like the CEMS data is correct - goes until 4am on 2023-01-01" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "profiles = pd.read_csv(outputs_folder(\"2022/hourly_profiles_2022.csv\"), parse_dates=[\"datetime_utc\",\"datetime_local\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "profiles[\n", + " (profiles[\"ba_code\"] == \"MISO\")\n", + " & (profiles[\"fuel_category\"] == \"natural_gas\")\n", + "]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Evaluate 8759 plants" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data = pd.read_csv(results_folder(f\"{year}/plant_data/hourly/us_units/ISNE.csv\"))\n", + "test = data.pivot(index=\"datetime_utc\",columns=\"plant_id_eia\", values=\"plant_id_eia\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test[test[542].isna()]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# it appears that multiple plants are missing data at this 4/1 4am timestamp\n", + "# they all appear to be petroluem - this is likely an issue with the hourly eia-930 profile being used.\n", + "# let's look at those" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "profiles = pd.read_csv(outputs_folder(\"2022/hourly_profiles_2022.csv\"), parse_dates=[\"datetime_utc\",\"datetime_local\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "profiles[\n", + " (profiles[\"ba_code\"] == \"ISNE\")\n", + " & (profiles[\"fuel_category\"] == \"petroleum\")\n", + " & (profiles[\"datetime_utc\"] >= \"2022-04-01\")\n", + " & (profiles[\"datetime_utc\"] < \"2022-04-02\")\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# it looks like this profile is non-missing for that entire day, which means it's not an issue with the profile itself\n", + "# looking at the plant metadata, we switch from using the 930 profile in march to the CEMS profile in April\n", + "# is the CEMS profile missing some data here? Is there an incorrect transition between DST where we are missing an hour?\n", + "# did this hour exist in the original CEMS data but we dropped it when removing standalone plant hours?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# let's look at our cleaned cems data first" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems_cleaned = pd.read_csv(outputs_folder(\"2022/cems_subplant_2022.csv\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems_cleaned[cems_cleaned[\"plant_id_eia\"] == 540]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# the earliest datetime in our cleaned CEMS data is 2022-04-01 05:00:00+00:00\n", + "# at this point in the year, we are in EDT, which is UTC -4, so midnight local time on 4/1 should be 4am UTC time.\n", + "# it looks like we are missing the first hour of this month" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# next, let's look at the \"raw\" CEMS data from PUDL\n", + "# it looks like on the CEMS website, there is no data available prior to 2022-04-01 at hour 0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# specify the columns to use from the CEMS database\n", + "cems_columns = [\n", + " \"plant_id_epa\", # try to load this column to make sure it has been converted to plant_id_eia\n", + " \"plant_id_eia\",\n", + " \"emissions_unit_id_epa\",\n", + " \"operating_datetime_utc\",\n", + " \"operating_time_hours\",\n", + " \"gross_load_mw\",\n", + " \"steam_load_1000_lbs\",\n", + " \"co2_mass_tons\",\n", + " \"co2_mass_measurement_code\",\n", + " \"nox_mass_lbs\",\n", + " \"nox_mass_measurement_code\",\n", + " \"so2_mass_lbs\",\n", + " \"so2_mass_measurement_code\",\n", + " \"heat_content_mmbtu\",\n", + "]\n", + "\n", + "# load the CEMS data\n", + "cems = pd.read_parquet(\n", + " downloads_folder(\"pudl/hourly_emissions_epacems.parquet\"),\n", + " filters=[[\"year\", \"==\", year]],\n", + " columns=cems_columns,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems[cems[\"plant_id_eia\"] == 540]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# this data is also available at 5am UTC at the earliest" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems_540 = cems_cleaned[cems_cleaned[\"plant_id_eia\"] == 540].copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems_540.report_date = pd.to_datetime(cems_540.report_date)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cems_540.report_date.dt.days_in_month" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test = (\n", + " cems_540.groupby([\"plant_id_eia\", \"subplant_id\"] + [\"report_date\"])[[\"datetime_utc\"]]\n", + " .agg([\"count\", \"min\", \"max\"])\n", + " .droplevel(level=0, axis=1)\n", + " ).reset_index()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# get complete number of hours in month\n", + "test[\"hours_in_month\"] = test[\"report_date\"].dt.days_in_month * 24\n", + "# adjust March and November for DST" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# we want to ensure a complete hourly timeseries for all plants in CEMS\n", + "# we want to test and make sure this works for both hourly and monthly data\n", + "\n", + "# import necessary modules\n", + "from itertools import product\n", + "\n", + "# define what will be function inputs\n", + "df = cems_cleaned[cems_cleaned[\"plant_id_eia\"].isin([3,540])]\n", + "key_columns = [\"plant_id_eia\", \"subplant_id\"]\n", + "timeseries_column = [\"datetime_utc\"]\n", + "year = 2022\n", + "\n", + "# add timezones to each CEMS plant\n", + "\n", + "# for each timezone, create a complete hourly timeseries\n", + "# we want to do this for each timezone so that we are not adding more than 8760 values for any plant\n", + "\n", + "# for each group of plants in each timezone, create a complete index, concating all together\n", + "\n", + "col_list = key_columns + timeseries_column\n", + "\n", + "# get a list of lists of unique values in each column\n", + "unique_column_values = []\n", + "for col in col_list: unique_column_values.append(list(df[col].unique()))\n", + "\n", + "# get the cartesian product of all possible combinations\n", + "unique_combinations = []\n", + "for element in product(*unique_column_values):\n", + " unique_combinations.append(element)\n", + "\n", + "# create a complete timeseries based on this\n", + "complete_timeseries_df = pd.DataFrame(\n", + " unique_combinations,\n", + " columns=[\"plant_id_eia\", \"subplant_id\", \"datetime_utc\"],\n", + ")\n", + "\n", + "\n", + "\n", + "# make sure the datetime dtypes match before merging\n", + "complete_timeseries_df[timeseries_column] = complete_timeseries_df[timeseries_column].astype(\n", + " df[timeseries_column].dtype\n", + ")\n", + "# complete the report dates\n", + "df = df.merge(\n", + " complete_timeseries_df,\n", + " how=\"outer\",\n", + " on=col_list,\n", + " validate=\"1:1\",\n", + ").sort_values(by=col_list)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "open_grid_emissions", + "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.4" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "b893a8d8fbb165be288531947168b3b06bdb1508177327a21c265e0400df3100" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/src/oge/reference_tables/emission_factors_for_nox.csv b/src/oge/reference_tables/emission_factors_for_nox.csv index bb2dc925..1240c849 100644 --- a/src/oge/reference_tables/emission_factors_for_nox.csv +++ b/src/oge/reference_tables/emission_factors_for_nox.csv @@ -8,6 +8,7 @@ OT,AB,wet,none,1.2,lb,ton OT,AB,none,none,1.2,lb,ton OT,BFG,none,none,0.0154,lb,mcf ST,BFG,none,none,0.0154,lb,mcf +ST,BFG,dry,none,0.0154,lb,mcf ST,BFG,wet,tangential_firing,0.0154,lb,mcf ST,BFG,dry,tangential_firing,0.0154,lb,mcf ST,BFG,none,tangential_firing,0.0154,lb,mcf @@ -83,6 +84,7 @@ CT,DFO,dry,other,5.124,lb,barrels CT,DFO,none,other,5.124,lb,barrels CT,DFO,none,tangential_firing,5.124,lb,barrels CT,DFO,none,wall_fired,5.124,lb,barrels +CT,DFO,dry,wall_fired,5.124,lb,barrels GT,DFO,none,CT,5.124,lb,barrels GT,DFO,none,none,5.124,lb,barrels IC,DFO,none,none,18.6396,lb,barrels @@ -182,6 +184,7 @@ FC,NG,none,none,,lb,mcf GT,NG,none,CT,0.328,lb,mcf GT,NG,none,none,0.32,lb,MMBtu GT,NG,none,tangential_firing,0.328,lb,mcf +GT,NG,none,wall_fired,0.328,lb,mcf IC,NG,none,none,2.768,lb,mcf OT,NG,none,none,0.28,lb,mcf ST,NG,dry,cell_burner,0.28,lb,mcf @@ -305,6 +308,7 @@ ST,PC,wet,wall_fired,21,lb,ton ST,PC,wet,cyclone_firing,21,lb,ton ST,PC,wet,other,21,lb,ton ST,PC,dry,stoker,21,lb,ton +ST,PC,none,stoker,21,lb,ton ST,PC,wet,tangential_firing,21,lb,ton ST,PC,none,wall_fired,21,lb,ton CS,PG,none,none,0.80336,lb,mcf diff --git a/toc.json b/toc.json index 14add9e3..b69c6756 100644 --- a/toc.json +++ b/toc.json @@ -167,6 +167,11 @@ "title": "Data Quality Metrics", "uri": "/docs/docs/Data Validation/Data Quality Metrics.md" }, + { + "type": "item", + "title": "Known Issues", + "uri": "/docs/docs/Data Validation/Known Issues.md" + }, { "type": "item", "title": "Comparing Data to eGRID", From 193b2b25a9afe69e67d3296b3ce016f19ed434f5 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 28 Dec 2023 15:28:38 -0800 Subject: [PATCH 77/85] format notebook --- ...26_investigate_incomplete_timeseries.ipynb | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/notebooks/work_in_progress/GH326_investigate_incomplete_timeseries.ipynb b/notebooks/work_in_progress/GH326_investigate_incomplete_timeseries.ipynb index 9ed3494a..012d07aa 100644 --- a/notebooks/work_in_progress/GH326_investigate_incomplete_timeseries.ipynb +++ b/notebooks/work_in_progress/GH326_investigate_incomplete_timeseries.ipynb @@ -63,7 +63,7 @@ "metadata": {}, "outputs": [], "source": [ - "test = data.pivot(index=\"datetime_utc\",columns=\"plant_id_eia\", values=\"plant_id_eia\")\n", + "test = data.pivot(index=\"datetime_utc\", columns=\"plant_id_eia\", values=\"plant_id_eia\")\n", "test" ] }, @@ -73,7 +73,7 @@ "metadata": {}, "outputs": [], "source": [ - "test.loc[\"2023-01-01 06:00:00+00:00\",:].dropna()" + "test.loc[\"2023-01-01 06:00:00+00:00\", :].dropna()" ] }, { @@ -91,10 +91,10 @@ "metadata": {}, "outputs": [], "source": [ - "# plant 50240 is located in ET, where MISO spans from MT to CT to ET. 50240 has data \n", + "# plant 50240 is located in ET, where MISO spans from MT to CT to ET. 50240 has data\n", "# starting 5am UTC (expected for EST), but ending at 5am UTC (it should end 4am.)\n", "# It looks like this plant has data for December from both CEMS and EIA\n", - "# it is possible that we are using CT to shape the EIA data since this is in MISO - \n", + "# it is possible that we are using CT to shape the EIA data since this is in MISO -\n", "# we need to make sure that we are using plant-specific time zones" ] }, @@ -131,7 +131,10 @@ "metadata": {}, "outputs": [], "source": [ - "profiles = pd.read_csv(outputs_folder(\"2022/hourly_profiles_2022.csv\"), parse_dates=[\"datetime_utc\",\"datetime_local\"])" + "profiles = pd.read_csv(\n", + " outputs_folder(\"2022/hourly_profiles_2022.csv\"),\n", + " parse_dates=[\"datetime_utc\", \"datetime_local\"],\n", + ")" ] }, { @@ -140,10 +143,7 @@ "metadata": {}, "outputs": [], "source": [ - "profiles[\n", - " (profiles[\"ba_code\"] == \"MISO\")\n", - " & (profiles[\"fuel_category\"] == \"natural_gas\")\n", - "]" + "profiles[(profiles[\"ba_code\"] == \"MISO\") & (profiles[\"fuel_category\"] == \"natural_gas\")]" ] }, { @@ -160,7 +160,7 @@ "outputs": [], "source": [ "data = pd.read_csv(results_folder(f\"{year}/plant_data/hourly/us_units/ISNE.csv\"))\n", - "test = data.pivot(index=\"datetime_utc\",columns=\"plant_id_eia\", values=\"plant_id_eia\")" + "test = data.pivot(index=\"datetime_utc\", columns=\"plant_id_eia\", values=\"plant_id_eia\")" ] }, { @@ -189,7 +189,10 @@ "metadata": {}, "outputs": [], "source": [ - "profiles = pd.read_csv(outputs_folder(\"2022/hourly_profiles_2022.csv\"), parse_dates=[\"datetime_utc\",\"datetime_local\"])" + "profiles = pd.read_csv(\n", + " outputs_folder(\"2022/hourly_profiles_2022.csv\"),\n", + " parse_dates=[\"datetime_utc\", \"datetime_local\"],\n", + ")" ] }, { @@ -350,10 +353,12 @@ "outputs": [], "source": [ "test = (\n", - " cems_540.groupby([\"plant_id_eia\", \"subplant_id\"] + [\"report_date\"])[[\"datetime_utc\"]]\n", - " .agg([\"count\", \"min\", \"max\"])\n", - " .droplevel(level=0, axis=1)\n", - " ).reset_index()" + " cems_540.groupby([\"plant_id_eia\", \"subplant_id\"] + [\"report_date\"])[\n", + " [\"datetime_utc\"]\n", + " ]\n", + " .agg([\"count\", \"min\", \"max\"])\n", + " .droplevel(level=0, axis=1)\n", + ").reset_index()" ] }, { @@ -389,7 +394,7 @@ "from itertools import product\n", "\n", "# define what will be function inputs\n", - "df = cems_cleaned[cems_cleaned[\"plant_id_eia\"].isin([3,540])]\n", + "df = cems_cleaned[cems_cleaned[\"plant_id_eia\"].isin([3, 540])]\n", "key_columns = [\"plant_id_eia\", \"subplant_id\"]\n", "timeseries_column = [\"datetime_utc\"]\n", "year = 2022\n", @@ -405,7 +410,8 @@ "\n", "# get a list of lists of unique values in each column\n", "unique_column_values = []\n", - "for col in col_list: unique_column_values.append(list(df[col].unique()))\n", + "for col in col_list:\n", + " unique_column_values.append(list(df[col].unique()))\n", "\n", "# get the cartesian product of all possible combinations\n", "unique_combinations = []\n", @@ -419,11 +425,10 @@ ")\n", "\n", "\n", - "\n", "# make sure the datetime dtypes match before merging\n", - "complete_timeseries_df[timeseries_column] = complete_timeseries_df[timeseries_column].astype(\n", - " df[timeseries_column].dtype\n", - ")\n", + "complete_timeseries_df[timeseries_column] = complete_timeseries_df[\n", + " timeseries_column\n", + "].astype(df[timeseries_column].dtype)\n", "# complete the report dates\n", "df = df.merge(\n", " complete_timeseries_df,\n", From 0d2601332799299f7db357aede6b305e74ffeffb Mon Sep 17 00:00:00 2001 From: grgmiller Date: Thu, 28 Dec 2023 16:04:34 -0800 Subject: [PATCH 78/85] update pipfile --- Pipfile.lock | 1773 +++++++++++++++++++++++++++----------------------- 1 file changed, 948 insertions(+), 825 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 79b4829f..762f0b8f 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "7249563398d2518deb9e27b91ad7cfea052a50a07efcb91354fd7b3f5691dade" + "sha256": "c51d83577cc5f3d322b45f7c1eba3f6b0cd67c5ce0f197a1dd2ffd4ed0ea3842" }, "pipfile-spec": 6, "requires": { @@ -132,11 +132,11 @@ }, "alembic": { "hashes": [ - "sha256:a23974ea301c3ee52705db809c7413cecd165290c6679b9998dd6c74342ca23a", - "sha256:ab4b3b94d2e1e5f81e34be8a9b7b7575fc9dd5398fccb0bef351ec9b14872623" + "sha256:2edcc97bed0bd3272611ce3a98d98279e9c209e7186e43e75bbb1b2bdfdbcc43", + "sha256:4932c8558bf68f2ee92b9bbcb8218671c627064d5b08939437af6d77dc05e595" ], "markers": "python_version >= '3.8'", - "version": "==1.13.0" + "version": "==1.13.1" }, "annotated-types": { "hashes": [ @@ -156,11 +156,11 @@ }, "anyio": { "hashes": [ - "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f", - "sha256:5a0bec7085176715be77df87fc66d6c9d70626bd752fcc85f57cdbee5b3760da" + "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee", + "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f" ], "markers": "python_version >= '3.8'", - "version": "==4.1.0" + "version": "==4.2.0" }, "appdirs": { "hashes": [ @@ -169,21 +169,13 @@ ], "version": "==1.4.4" }, - "appnope": { - "hashes": [ - "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24", - "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e" - ], - "markers": "platform_system == 'Darwin'", - "version": "==0.1.3" - }, "arelle-release": { "hashes": [ - "sha256:1a585cc9a9a222ebb6a351c28ae942ea750bf194c9c3081edbe2685be80addc1", - "sha256:fd2145bed91043a584dca79f04c06c604ac912a97e3ea5e8c289b2576a71a7b1" + "sha256:812589ea232d93e6f938112b56ef3eb5c7db5235811bb2f70cc803f869b59174", + "sha256:c15b59f53e36c4373b9f817666b7a59136971c2c65b13e3b4077f60efe2d119d" ], "markers": "python_version >= '3.8'", - "version": "==2.19.0" + "version": "==2.20.3" }, "argon2-cffi": { "hashes": [ @@ -300,19 +292,19 @@ }, "boto3": { "hashes": [ - "sha256:8b3c4d4e720c0ad706590c284b8f30c76de3472c1ce1bac610425f99bf6ab53b", - "sha256:c9b400529932ed4652304756528ab235c6730aa5d00cb4d9e4848ce460c82c16" + "sha256:8d3d3cc8bffc3fd6c64c55f69327d4e375b6796054dcf09f43ec8b0a9f864a74", + "sha256:ea14bc081d9cb40291133f89b3ad9070be360e152d6a98263af7b97a6534b669" ], "markers": "python_version >= '3.8'", - "version": "==1.34.0" + "version": "==1.34.10" }, "botocore": { "hashes": [ - "sha256:6ec19f6c9f61c3df22fb3e083940ac7946a3d96128db1f370f10aea702bb157f", - "sha256:711b406de910585395466ca649bceeea87a04300ddf74d9a2e20727c7f27f2f1" + "sha256:ad0e924bbdd5469b62ea82a205bd3a9e03a00a61b661ed6446739b82849ea8be", + "sha256:e981d2d727f26732753269d60a51a1851ad9de6c1aa823e5443c7b06221aada0" ], "markers": "python_version >= '3.8'", - "version": "==1.34.0" + "version": "==1.34.10" }, "bottleneck": { "hashes": [ @@ -421,9 +413,9 @@ "version": "==1.3.1" }, "catalystcoop.pudl": { - "git": "git+https://github.com/singularity-energy/pudl.git", + "git": "git+https://github.com/singularity-energy/pudl.git@oge_dev", "markers": "python_version >= '3.11' and python_version < '3.12'", - "ref": "5a7e03795158a8cf75d309f75265e2dc80afe7c8" + "ref": "8e7caf179a688c11669eb391a16de3a280f7513f" }, "certifi": { "hashes": [ @@ -752,61 +744,61 @@ "toml" ], "hashes": [ - "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1", - "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63", - "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9", - "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312", - "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3", - "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb", - "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25", - "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92", - "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda", - "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148", - "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6", - "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216", - "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a", - "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640", - "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836", - "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c", - "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f", - "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2", - "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901", - "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed", - "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a", - "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074", - "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc", - "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84", - "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083", - "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f", - "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c", - "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c", - "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637", - "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2", - "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82", - "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f", - "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce", - "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef", - "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f", - "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611", - "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c", - "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76", - "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9", - "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce", - "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9", - "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf", - "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf", - "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9", - "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6", - "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2", - "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a", - "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a", - "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf", - "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738", - "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a", - "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4" + "sha256:04387a4a6ecb330c1878907ce0dc04078ea72a869263e53c72a1ba5bbdf380ca", + "sha256:0676cd0ba581e514b7f726495ea75aba3eb20899d824636c6f59b0ed2f88c471", + "sha256:0e8d06778e8fbffccfe96331a3946237f87b1e1d359d7fbe8b06b96c95a5407a", + "sha256:0eb3c2f32dabe3a4aaf6441dde94f35687224dfd7eb2a7f47f3fd9428e421058", + "sha256:109f5985182b6b81fe33323ab4707011875198c41964f014579cf82cebf2bb85", + "sha256:13eaf476ec3e883fe3e5fe3707caeb88268a06284484a3daf8250259ef1ba143", + "sha256:164fdcc3246c69a6526a59b744b62e303039a81e42cfbbdc171c91a8cc2f9446", + "sha256:26776ff6c711d9d835557ee453082025d871e30b3fd6c27fcef14733f67f0590", + "sha256:26f66da8695719ccf90e794ed567a1549bb2644a706b41e9f6eae6816b398c4a", + "sha256:29f3abe810930311c0b5d1a7140f6395369c3db1be68345638c33eec07535105", + "sha256:316543f71025a6565677d84bc4df2114e9b6a615aa39fb165d697dba06a54af9", + "sha256:36b0ea8ab20d6a7564e89cb6135920bc9188fb5f1f7152e94e8300b7b189441a", + "sha256:3cc9d4bc55de8003663ec94c2f215d12d42ceea128da8f0f4036235a119c88ac", + "sha256:485e9f897cf4856a65a57c7f6ea3dc0d4e6c076c87311d4bc003f82cfe199d25", + "sha256:5040148f4ec43644702e7b16ca864c5314ccb8ee0751ef617d49aa0e2d6bf4f2", + "sha256:51456e6fa099a8d9d91497202d9563a320513fcf59f33991b0661a4a6f2ad450", + "sha256:53d7d9158ee03956e0eadac38dfa1ec8068431ef8058fe6447043db1fb40d932", + "sha256:5a10a4920def78bbfff4eff8a05c51be03e42f1c3735be42d851f199144897ba", + "sha256:5b14b4f8760006bfdb6e08667af7bc2d8d9bfdb648351915315ea17645347137", + "sha256:5b2ccb7548a0b65974860a78c9ffe1173cfb5877460e5a229238d985565574ae", + "sha256:697d1317e5290a313ef0d369650cfee1a114abb6021fa239ca12b4849ebbd614", + "sha256:6ae8c9d301207e6856865867d762a4b6fd379c714fcc0607a84b92ee63feff70", + "sha256:707c0f58cb1712b8809ece32b68996ee1e609f71bd14615bd8f87a1293cb610e", + "sha256:74775198b702868ec2d058cb92720a3c5a9177296f75bd97317c787daf711505", + "sha256:756ded44f47f330666843b5781be126ab57bb57c22adbb07d83f6b519783b870", + "sha256:76f03940f9973bfaee8cfba70ac991825611b9aac047e5c80d499a44079ec0bc", + "sha256:79287fd95585ed36e83182794a57a46aeae0b64ca53929d1176db56aacc83451", + "sha256:799c8f873794a08cdf216aa5d0531c6a3747793b70c53f70e98259720a6fe2d7", + "sha256:7d360587e64d006402b7116623cebf9d48893329ef035278969fa3bbf75b697e", + "sha256:80b5ee39b7f0131ebec7968baa9b2309eddb35b8403d1869e08f024efd883566", + "sha256:815ac2d0f3398a14286dc2cea223a6f338109f9ecf39a71160cd1628786bc6f5", + "sha256:83c2dda2666fe32332f8e87481eed056c8b4d163fe18ecc690b02802d36a4d26", + "sha256:846f52f46e212affb5bcf131c952fb4075b55aae6b61adc9856222df89cbe3e2", + "sha256:936d38794044b26c99d3dd004d8af0035ac535b92090f7f2bb5aa9c8e2f5cd42", + "sha256:9864463c1c2f9cb3b5db2cf1ff475eed2f0b4285c2aaf4d357b69959941aa555", + "sha256:995ea5c48c4ebfd898eacb098164b3cc826ba273b3049e4a889658548e321b43", + "sha256:a1526d265743fb49363974b7aa8d5899ff64ee07df47dd8d3e37dcc0818f09ed", + "sha256:a56de34db7b7ff77056a37aedded01b2b98b508227d2d0979d373a9b5d353daa", + "sha256:a7c97726520f784239f6c62506bc70e48d01ae71e9da128259d61ca5e9788516", + "sha256:b8e99f06160602bc64da35158bb76c73522a4010f0649be44a4e167ff8555952", + "sha256:bb1de682da0b824411e00a0d4da5a784ec6496b6850fdf8c865c1d68c0e318dd", + "sha256:bf477c355274a72435ceb140dc42de0dc1e1e0bf6e97195be30487d8eaaf1a09", + "sha256:bf635a52fc1ea401baf88843ae8708591aa4adff875e5c23220de43b1ccf575c", + "sha256:bfd5db349d15c08311702611f3dccbef4b4e2ec148fcc636cf8739519b4a5c0f", + "sha256:c530833afc4707fe48524a44844493f36d8727f04dcce91fb978c414a8556cc6", + "sha256:cc6d65b21c219ec2072c1293c505cf36e4e913a3f936d80028993dd73c7906b1", + "sha256:cd3c1e4cb2ff0083758f09be0f77402e1bdf704adb7f89108007300a6da587d0", + "sha256:cfd2a8b6b0d8e66e944d47cdec2f47c48fef2ba2f2dff5a9a75757f64172857e", + "sha256:d0ca5c71a5a1765a0f8f88022c52b6b8be740e512980362f7fdbb03725a0d6b9", + "sha256:e7defbb9737274023e2d7af02cac77043c86ce88a907c58f42b580a97d5bcca9", + "sha256:e9d1bf53c4c8de58d22e0e956a79a5b37f754ed1ffdbf1a260d9dcfa2d8a325e", + "sha256:ea81d8f9691bb53f4fb4db603203029643caffc82bf998ab5b59ca05560f4c06" ], "markers": "python_version >= '3.8'", - "version": "==7.3.2" + "version": "==7.4.0" }, "crashtest": { "hashes": [ @@ -829,6 +821,7 @@ "sha256:098abd1d648d9e44f7ad55542b3b7f978b82280f4332ad80a937db6fbe274600", "sha256:0c45f663e40b3ed2e2320e7ae8d50fcf09b5ac72c5af4c66aa523e0045453311", "sha256:22d12b88190e047c0cedde165711222aa0dcdc325a229b876c36f746dd4a6f12", + "sha256:25adbeb0efd50d7ea4f07e5f5bd390a3c807df907f03efb86b018807c2c8cfbe", "sha256:3461fa42c1b2240ba4da1d985ca73503914157fc4c77417327ed6d7d85acdbe6", "sha256:45e702d4649d2d4e73fcd8f244aa5734a04d2b1a3fa3e7c0bff1ab578bf5061e", "sha256:6874e1b9aa002f9d796da9d02bdca76b15aa3d4b2f83ca5064ac4c7894b92ece", @@ -838,11 +831,14 @@ "sha256:994dab68c193bea405a3a89a88b8703dd2c79bb790a330c8d459f0454cca71ef", "sha256:a075e333916da7fc941b36a4f189b88acd291f1d861d97ba876626c277b3e575", "sha256:a459b6ee9f99fc34861cbcf679a196af2d930ec70d95018a94f2e6dbe46c8c24", + "sha256:a92ebfc5df77fea57544f8ad2102bfc45af0e77ac4dfe98ed1b9628e8bba77c3", + "sha256:c10e27cb7a27b55f17e0df30c6b85e98c9672a7bdb7000a7509560eee7679137", "sha256:c237b57845b1e4ac00c012581cde099cd71a91434c117fec763bb4bf5b22601b", "sha256:cd4a1bba537a34808b92f1e793e3499029d339a7a2ab6d989f82e395b7b740ff", "sha256:dcc0c091977b9211ad5086d0dfcc8748a4be3a37b0456c93d11a5d8fe15219e8", "sha256:e2ec16afa3e953159e148b7470159e415108aadb8bb1815baaea2e37ad7e1d8c", "sha256:e3cd2db913b1cf64d84cdb7bc467a8a15adbd1f0f83a7a45a7167ad590f79408", + "sha256:e8bcf71a5016aeb24e597dc099564e8de809e0bc5d6af21e26422586aea26718", "sha256:f4ae2bc20a7d44657cc3ab1e2b80fa07ff3ebe0c1e0fa1f0b27b2ba693eb5072", "sha256:f88dd546d91eb9e0974eee477b76077d001eeeb7b819d8801eb6065376d7d527" ], @@ -888,32 +884,32 @@ }, "dagster": { "hashes": [ - "sha256:1de2373bea87603873de12a8d08862d5c29d53fb145a7ff3fd97ad5874c21972", - "sha256:ea0937f08421c07aa0400b532c35ea25cae39e111aff412f49382692d574749c" + "sha256:af86d901088faec7f638d4d0c064017536be89630d5c0d540bb2c02d537d840f", + "sha256:bd032d3b7c4823533bdae894f22baf3753639f3d8363a904b161603c930457a1" ], - "version": "==1.5.12" + "version": "==1.5.13" }, "dagster-pipes": { "hashes": [ - "sha256:66fcd15a0fd68d7a3be1dc0a384163b6d43cc83adcf868de98b0134315b87c41", - "sha256:aa488ee92ce7b89df2eada9282e6da39f967ee241ff12ab468ebbf2332f090e8" + "sha256:17dbbceb1291175d2c973dd55c4c3daf02b85084484e257f10b66d98244ccd5a", + "sha256:56837cef5c63d2dafcf60c5d3a35895b159300d70742fc599c2f9e2af7d42f46" ], - "version": "==1.5.12" + "version": "==1.5.13" }, "dagster-postgres": { "hashes": [ - "sha256:566b33e3a5e05809eec4501ab4915beced9e1ba125d9e41d988632ffc330562f", - "sha256:e2cadae93f099938d460be7290ef3c330d8b2bcfe666b4ce8593d0f91fb3aca5" + "sha256:1a2eb851d5fac6d2dc576c70b8cc5c59eac7cfc1ce8e61d26d6e47bfe3a9be08", + "sha256:6be23bd8299eb85cffcff91c3abe2c421a126cb8d1a6213344719968f2b622cf" ], - "version": "==0.21.12" + "version": "==0.21.13" }, "dask": { "hashes": [ - "sha256:3f687e647ced0d3f2cadbef113c730b6555b9499b62e3a220535438841001c91", - "sha256:6cef2fa43815adc8fe895dd3ea473a311249ba0e15e1f7eb9b1b68302339d998" + "sha256:0ac3acd5bdbfacb5ad6401ac7663a1135955b3fa051a118e1b8a88e87b6b44a2", + "sha256:55f316f32da9e68fe995e2c0dc460cb8888cd4a1af32096753788e8af45a8d10" ], "markers": "python_version >= '3.9'", - "version": "==2023.12.0" + "version": "==2023.12.1" }, "datapackage": { "hashes": [ @@ -924,11 +920,11 @@ }, "datasette": { "hashes": [ - "sha256:a7370d832a656ff0804e262d79fe16080c2bcba56be5e2873a0b64f465542404", - "sha256:df917896f181ce57e26c6b3b78ff7fdfdc46c322c46673b2276fae1d8e7f19e2" + "sha256:158dbdfab1a4c613da7757518444a7664ecd39f54a617304edff4f119dd057df", + "sha256:85ca3aabca64fd9560052042aec27d3b32a1f85303853da3550434866d0fa539" ], "markers": "python_version >= '3.7'", - "version": "==0.64.5" + "version": "==0.64.6" }, "debugpy": { "hashes": [ @@ -1072,10 +1068,10 @@ }, "fastjsonschema": { "hashes": [ - "sha256:b9fd1a2dd6971dbc7fee280a95bd199ae0dd9ce22beb91cc75e9c1c528a5170e", - "sha256:e25df6647e1bc4a26070b700897b07b542ec898dd4f1f6ea013e7f6a88417225" + "sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0", + "sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d" ], - "version": "==2.19.0" + "version": "==2.19.1" }, "filelock": { "hashes": [ @@ -1116,51 +1112,51 @@ }, "fonttools": { "hashes": [ - "sha256:13ac0cba2fc63fa4b232f2a7971f35f35c6eaf10bd1271fa96d4ce6253a8acfd", - "sha256:156ae342a1ed1fe38e180de471e98fbf5b2b6ae280fa3323138569c4ca215844", - "sha256:1a9f9cdd7ef63d1b8ac90db335762451452426b3207abd79f60da510cea62da5", - "sha256:1c9937c4dd1061afd22643389445fabda858af5e805860ec3082a4bc07c7a720", - "sha256:25852f0c63df0af022f698464a4a80f7d1d5bd974bcd22f995f6b4ad198e32dd", - "sha256:2ae45716c27a41807d58a9f3f59983bdc8c0a46cb259e4450ab7e196253a9853", - "sha256:2c23c59d321d62588620f2255cf951270bf637d88070f38ed8b5e5558775b86c", - "sha256:2cf923a4a556ab4cc4c52f69a4a2db624cf5a2cf360394368b40c5152fe3321e", - "sha256:2d0eba685938c603f2f648dfc0aadbf8c6a4fe1c7ca608c2970a6ef39e00f254", - "sha256:3033b55f401a622de2630b3982234d97219d89b058607b87927eccb0f922313c", - "sha256:49ea0983e55fd7586a809787cd4644a7ae471e53ab8ddc016f9093b400e32646", - "sha256:5200b01f463d97cc2b7ff8a1e3584151f4413e98cb8419da5f17d1dbb84cc214", - "sha256:5b627ed142398ea9202bd752c04311592558964d1a765fb2f78dc441a05633f4", - "sha256:6d4a4ebcc76e30898ff3296ea786491c70e183f738319ae2629e0d44f17ece42", - "sha256:795150d5edc595e1a2cfb3d65e8f4f3d027704fc2579f8990d381bef6b188eb6", - "sha256:7b460720ce81773da1a3e7cc964c48e1e11942b280619582a897fa0117b56a62", - "sha256:7b5636f5706d49f13b6d610fe54ee662336cdf56b5a6f6683c0b803e23d826d2", - "sha256:8485cc468288e213f31afdaf1fdda3c79010f542559fbba936a54f4644df2570", - "sha256:87c214197712cc14fd2a4621efce2a9c501a77041232b789568149a8a3161517", - "sha256:87c3299da7da55394fb324349db0ede38114a46aafd0e7dfcabfecd28cdd94c3", - "sha256:89c2c520f9492844ecd6316d20c6c7a157b5c0cb73a1411b3db28ee304f30122", - "sha256:8be6adfa4e15977075278dd0a0bae74dec59be7b969b5ceed93fb86af52aa5be", - "sha256:8bee9f4fc8c99824a424ae45c789ee8c67cb84f8e747afa7f83b7d3cef439c3b", - "sha256:982f69855ac258260f51048d9e0c53c5f19881138cc7ca06deb38dc4b97404b6", - "sha256:9e6aeb5c340416d11a3209d75c48d13e72deea9e1517837dd1522c1fd1f17c11", - "sha256:a0e94244ec24a940ecfbe5b31c975c8a575d5ed2d80f9a280ce3b21fa5dc9c34", - "sha256:a4a50a1dfad7f7ba5ca3f99cc73bf5cdac67ceade8e4b355a877521f20ad1b63", - "sha256:a9fa52ef8fd14d7eb3d813e1451e7ace3e1eebfa9b7237d3f81fee8f3de6a114", - "sha256:adab73618d0a328b203a0e242b3eba60a2b5662d9cb2bd16ed9c52af8a7d86af", - "sha256:c506e3d3a9e898caee4dc094f34b49c5566870d5a2d1ca2125f0a9f35ecc2205", - "sha256:c779f8701deedf41908f287aeb775b8a6f59875ad1002b98ac6034ae4ddc1b7b", - "sha256:c94564b1f3b5dd87e73577610d85115b1936edcc596deaf84a31bbe70e17456b", - "sha256:c9a0e422ab79e5cb2b47913be6a4b5fd20c4c7ac34a24f3691a4e099e965e0b8", - "sha256:ca9eceebe70035b057ce549e2054cad73e95cac3fe91a9d827253d1c14618204", - "sha256:ce199227ce7921eaafdd4f96536f16b232d6b580ce74ce337de544bf06cb2752", - "sha256:d00fc63131dcac6b25f50a5a129758438317e54e3ce5587163f7058de4b0e933", - "sha256:d3d7b96aba96e05e8c911ce2dfc5acc6a178b8f44f6aa69371ab91aa587563da", - "sha256:d4e69e2c7f93b695d2e6f18f709d501d945f65c1d237dafaabdd23cd935a5276", - "sha256:e26e7fb908ae4f622813e7cb32cd2db6c24e3122bb3b98f25e832a2fe0e7e228", - "sha256:e5b7905fd68eacb7cc56a13139da5c312c45baae6950dd00b02563c54508a041", - "sha256:f5f1423a504ccc329efb5aa79738de83d38c072be5308788dde6bd419969d7f5", - "sha256:f8bc3973ed58893c4107993e0a7ae34901cb572b5e798249cbef35d30801ffd4" + "sha256:084511482dd265bce6dca24c509894062f0117e4e6869384d853f46c0e6d43be", + "sha256:1193fb090061efa2f9e2d8d743ae9850c77b66746a3b32792324cdce65784154", + "sha256:174995f7b057e799355b393e97f4f93ef1f2197cbfa945e988d49b2a09ecbce8", + "sha256:253bb46bab970e8aae254cebf2ae3db98a4ef6bd034707aa68a239027d2b198d", + "sha256:2a78dba8c2a1e9d53a0fb5382979f024200dc86adc46a56cbb668a2249862fda", + "sha256:2d2404107626f97a221dc1a65b05396d2bb2ce38e435f64f26ed2369f68675d9", + "sha256:40bdbe90b33897d9cc4a39f8e415b0fcdeae4c40a99374b8a4982f127ff5c767", + "sha256:495369c660e0c27233e3c572269cbe520f7f4978be675f990f4005937337d391", + "sha256:4a9a51745c0439516d947480d4d884fa18bd1458e05b829e482b9269afa655bc", + "sha256:511482df31cfea9f697930f61520f6541185fa5eeba2fa760fe72e8eee5af88b", + "sha256:52c82df66201f3a90db438d9d7b337c7c98139de598d0728fb99dab9fd0495ca", + "sha256:562681188c62c024fe2c611b32e08b8de2afa00c0c4e72bed47c47c318e16d5c", + "sha256:59a6c8b71a245800e923cb684a2dc0eac19c56493e2f896218fcf2571ed28984", + "sha256:5dde0eab40faaa5476133123f6a622a1cc3ac9b7af45d65690870620323308b4", + "sha256:61df4dee5d38ab65b26da8efd62d859a1eef7a34dcbc331299a28e24d04c59a7", + "sha256:62d8ddb058b8e87018e5dc26f3258e2c30daad4c87262dfeb0e2617dd84750e6", + "sha256:66c92ec7f95fd9732550ebedefcd190a8d81beaa97e89d523a0d17198a8bda4d", + "sha256:843509ae9b93db5aaf1a6302085e30bddc1111d31e11d724584818f5b698f500", + "sha256:854421e328d47d70aa5abceacbe8eef231961b162c71cbe7ff3f47e235e2e5c5", + "sha256:97620c4af36e4c849e52661492e31dc36916df12571cb900d16960ab8e92a980", + "sha256:9acfa1cdc479e0dde528b61423855913d949a7f7fe09e276228298fef4589540", + "sha256:a77a60315c33393b2bd29d538d1ef026060a63d3a49a9233b779261bad9c3f71", + "sha256:b4fabb8cc9422efae1a925160083fdcbab8fdc96a8483441eb7457235df625bd", + "sha256:bf1810635c00f7c45d93085611c995fc130009cec5abdc35b327156aa191f982", + "sha256:c01f409be619a9a0f5590389e37ccb58b47264939f0e8d58bfa1f3ba07d22671", + "sha256:c59227d7ba5b232281c26ae04fac2c73a79ad0e236bca5c44aae904a18f14faf", + "sha256:c75e19971209fbbce891ebfd1b10c37320a5a28e8d438861c21d35305aedb81c", + "sha256:ce0e2c88c8c985b7b9a7efcd06511fb0a1fe3ddd9a6cd2895ef1dbf9059719d7", + "sha256:d6477ba902dd2d7adda7f0fd3bfaeb92885d45993c9e1928c9f28fc3961415f7", + "sha256:d986b66ff722ef675b7ee22fbe5947a41f60a61a4da15579d5e276d897fbc7fa", + "sha256:dd23848f877c3754f53a4903fb7a593ed100924f9b4bff7d5a4e2e8a7001ae11", + "sha256:e3f4d61f3a8195eac784f1d0c16c0a3105382c1b9a74d99ac4ba421da39a8826", + "sha256:e6b968543fde4119231c12c2a953dcf83349590ca631ba8216a8edf9cd4d36a9", + "sha256:e77bdf52185bdaf63d39f3e1ac3212e6cfa3ab07d509b94557a8902ce9c13c82", + "sha256:e79f1a3970d25f692bbb8c8c2637e621a66c0d60c109ab48d4a160f50856deff", + "sha256:e7a0a8848726956e9d9fb18c977a279013daadf0cbb6725d2015a6dd57527992", + "sha256:e869da810ae35afb3019baa0d0306cdbab4760a54909c89ad8904fa629991812", + "sha256:e8acf6dd0434b211b3bd30d572d9e019831aae17a54016629fa8224783b22df8", + "sha256:e8fa20748de55d0021f83754b371432dca0439e02847962fc4c42a0e444c2d78", + "sha256:ea592e6a09b71cb7a7661dd93ac0b877a6228e2d677ebacbad0a4d118494c86d", + "sha256:ec13a10715eef0e031858c1c23bfaee6cba02b97558e4a7bfa089dba4a8c2ebf", + "sha256:f4da089f6dfdb822293bde576916492cd708c37c2501c3651adde39804630538" ], "markers": "python_version >= '3.8'", - "version": "==4.46.0" + "version": "==4.47.0" }, "fqdn": { "hashes": [ @@ -1178,70 +1174,86 @@ }, "frozenlist": { "hashes": [ - "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6", - "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01", - "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251", - "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9", - "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b", - "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87", - "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf", - "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f", - "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0", - "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2", - "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b", - "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc", - "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c", - "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467", - "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9", - "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1", - "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a", - "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79", - "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167", - "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300", - "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf", - "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea", - "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2", - "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab", - "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3", - "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb", - "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087", - "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc", - "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8", - "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62", - "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f", - "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326", - "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c", - "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431", - "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963", - "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7", - "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef", - "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3", - "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956", - "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781", - "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472", - "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc", - "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839", - "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672", - "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3", - "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503", - "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d", - "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8", - "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b", - "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc", - "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f", - "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559", - "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b", - "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95", - "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb", - "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963", - "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919", - "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f", - "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3", - "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1", - "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e" + "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7", + "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98", + "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad", + "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5", + "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae", + "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e", + "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a", + "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701", + "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d", + "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6", + "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6", + "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106", + "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75", + "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868", + "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a", + "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0", + "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1", + "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826", + "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec", + "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6", + "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950", + "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19", + "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0", + "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8", + "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a", + "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09", + "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86", + "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c", + "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5", + "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b", + "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b", + "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d", + "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0", + "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea", + "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776", + "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a", + "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897", + "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7", + "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09", + "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9", + "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe", + "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd", + "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742", + "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09", + "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0", + "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932", + "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1", + "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a", + "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49", + "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d", + "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7", + "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480", + "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89", + "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e", + "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b", + "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82", + "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb", + "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068", + "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8", + "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b", + "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb", + "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2", + "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11", + "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b", + "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc", + "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0", + "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497", + "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17", + "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0", + "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2", + "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439", + "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5", + "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac", + "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825", + "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887", + "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced", + "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74" ], "markers": "python_version >= '3.8'", - "version": "==1.4.0" + "version": "==1.4.1" }, "fsspec": { "hashes": [ @@ -1421,8 +1433,72 @@ "markers": "python_version >= '3.7'", "version": "==1.62.0" }, + "greenlet": { + "hashes": [ + "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67", + "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6", + "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257", + "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4", + "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676", + "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61", + "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc", + "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca", + "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7", + "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728", + "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305", + "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6", + "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379", + "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414", + "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04", + "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a", + "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf", + "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491", + "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559", + "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e", + "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274", + "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb", + "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b", + "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9", + "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b", + "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be", + "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506", + "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405", + "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113", + "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f", + "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5", + "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230", + "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d", + "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f", + "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a", + "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e", + "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61", + "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6", + "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d", + "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71", + "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22", + "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2", + "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3", + "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067", + "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc", + "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881", + "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3", + "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e", + "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac", + "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53", + "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0", + "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b", + "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83", + "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41", + "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c", + "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf", + "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da", + "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33" + ], + "markers": "platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))", + "version": "==3.0.3" + }, "gridemissions": { - "git": "git+https://github.com/gailin-p/gridemissions", + "git": "git+https://github.com/singularity-energy/gridemissions", "ref": "0cbe7620620f02ab91227940ef107b53bd1f9bb4" }, "grpcio": { @@ -1570,11 +1646,11 @@ }, "httpx": { "hashes": [ - "sha256:8b8fcaa0c8ea7b05edd69a094e63a2094c4efcb48129fb757361bc423c0ad9e8", - "sha256:a05d3d052d9b2dfce0e3896636467f8a5342fb2b902c819428e1ac65413ca118" + "sha256:451b55c30d5185ea6b23c2c793abf9bb237d2a7dfb901ced6ff69ad37ec1dfaf", + "sha256:8915f5a3627c4d47b73e8202457cb28f1266982d1159bd5779d86a80c0eab1cd" ], "markers": "python_version >= '3.8'", - "version": "==0.25.2" + "version": "==0.26.0" }, "humanfriendly": { "hashes": [ @@ -1594,11 +1670,11 @@ }, "hypothesis": { "hashes": [ - "sha256:65b72c7dc7da3e16144db54fe093c6b74a33631b933a8063eb754c5a61361ae6", - "sha256:d4577f99b912acc725bea684899b7cb62591a0412e2446c618be0b4855995276" + "sha256:841f89a486c43bdab55698de8929bd2635639ec20bf6ce98ccd75622d7ee6d41", + "sha256:d335044492acb03fa1fdb4edacb81cca2e578049fc7306345bc0e8947fef15a9" ], "markers": "python_version >= '3.8'", - "version": "==6.92.0" + "version": "==6.92.2" }, "identify": { "hashes": [ @@ -1720,11 +1796,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7", - "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67" + "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e", + "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc" ], "markers": "python_version >= '3.8'", - "version": "==7.0.0" + "version": "==7.0.1" }, "iniconfig": { "hashes": [ @@ -1736,20 +1812,20 @@ }, "ipykernel": { "hashes": [ - "sha256:7d5d594b6690654b4d299edba5e872dc17bb7396a8d0609c97cb7b8a1c605de6", - "sha256:dab88b47f112f9f7df62236511023c9bdeef67abc73af7c652e4ce4441601686" + "sha256:69c11403d26de69df02225916f916b37ea4b9af417da0a8c827f84328d88e5f3", + "sha256:c6e9a9c63a7f4095c0a22a79f765f079f9ec7be4f2430a898ddea889e8665661" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==6.27.1" + "version": "==6.28.0" }, "ipython": { "hashes": [ - "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27", - "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397" + "sha256:2f55d59370f59d0d2b2212109fe0e6035cfea436b1c0e6150ad2244746272ec5", + "sha256:ac4da4ecf0042fb4e0ce57c60430c2db3c719fa8bdf92f8631d6bd8a5785d1f0" ], - "markers": "python_version >= '3.9'", - "version": "==8.18.1" + "markers": "python_version >= '3.10'", + "version": "==8.19.0" }, "ipywidgets": { "hashes": [ @@ -1936,11 +2012,11 @@ }, "jsonschema-specifications": { "hashes": [ - "sha256:9472fc4fea474cd74bea4a2b190daeccb5a9e4db2ea80efcf7a1b582fc9a81b8", - "sha256:e74ba7c0a65e8cb49dc26837d6cfe576557084a8b423ed16a420984228104f93" + "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc", + "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c" ], "markers": "python_version >= '3.8'", - "version": "==2023.11.2" + "version": "==2023.12.1" }, "jupyter": { "hashes": [ @@ -1968,11 +2044,11 @@ }, "jupyter-core": { "hashes": [ - "sha256:880b86053bf298a8724994f95e99b99130659022a4f7f45f563084b6223861d3", - "sha256:e11e02cd8ae0a9de5c6c44abf5727df9f2581055afe00b22183f621ba3585805" + "sha256:1553311a97ccd12936037f36b9ab4d6ae8ceea6ad2d5c90d94a909e752178e40", + "sha256:220dfb00c45f0d780ce132bb7976b58263f81a3ada6e90a9b6823785a424f739" ], "markers": "python_version >= '3.8'", - "version": "==5.5.0" + "version": "==5.5.1" }, "jupyter-events": { "hashes": [ @@ -2000,11 +2076,11 @@ }, "jupyter-server-terminals": { "hashes": [ - "sha256:2fc0692c883bfd891f4fba0c4b4a684a37234b0ba472f2e97ed0a3888f46e1e4", - "sha256:ebcd68c9afbf98a480a533e6f3266354336e645536953b7abcc7bdeebc0154a3" + "sha256:16d3be9cf48be6a1f943f3a6c93c033be259cf4779184c66421709cf63dccfea", + "sha256:5e63e947ddd97bb2832db5ef837a258d9ccd4192cd608c1270850ad947ae5dd7" ], "markers": "python_version >= '3.8'", - "version": "==0.5.0" + "version": "==0.5.1" }, "jupyterlab": { "hashes": [ @@ -2210,101 +2286,102 @@ }, "lxml": { "hashes": [ - "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3", - "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d", - "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a", - "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120", - "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305", - "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287", - "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23", - "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52", - "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f", - "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4", - "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584", - "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f", - "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693", - "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef", - "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5", - "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02", - "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc", - "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7", - "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da", - "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a", - "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40", - "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8", - "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd", - "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601", - "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c", - "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be", - "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2", - "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c", - "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129", - "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc", - "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2", - "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1", - "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7", - "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d", - "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477", - "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d", - "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e", - "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7", - "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2", - "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574", - "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf", - "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b", - "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98", - "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12", - "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42", - "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35", - "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d", - "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce", - "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d", - "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f", - "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db", - "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4", - "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694", - "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac", - "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2", - "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7", - "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96", - "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d", - "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b", - "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a", - "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13", - "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340", - "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6", - "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458", - "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c", - "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c", - "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9", - "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432", - "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991", - "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69", - "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf", - "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb", - "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b", - "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833", - "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76", - "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85", - "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e", - "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50", - "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8", - "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4", - "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b", - "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5", - "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190", - "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7", - "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa", - "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0", - "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9", - "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0", - "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b", - "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5", - "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7", - "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4" + "sha256:00e91573183ad273e242db5585b52670eddf92bacad095ce25c1e682da14ed91", + "sha256:01bf1df1db327e748dcb152d17389cf6d0a8c5d533ef9bab781e9d5037619229", + "sha256:056a17eaaf3da87a05523472ae84246f87ac2f29a53306466c22e60282e54ff8", + "sha256:0a08c89b23117049ba171bf51d2f9c5f3abf507d65d016d6e0fa2f37e18c0fc5", + "sha256:1343df4e2e6e51182aad12162b23b0a4b3fd77f17527a78c53f0f23573663545", + "sha256:1449f9451cd53e0fd0a7ec2ff5ede4686add13ac7a7bfa6988ff6d75cff3ebe2", + "sha256:16b9ec51cc2feab009e800f2c6327338d6ee4e752c76e95a35c4465e80390ccd", + "sha256:1f10f250430a4caf84115b1e0f23f3615566ca2369d1962f82bef40dd99cd81a", + "sha256:231142459d32779b209aa4b4d460b175cadd604fed856f25c1571a9d78114771", + "sha256:232fd30903d3123be4c435fb5159938c6225ee8607b635a4d3fca847003134ba", + "sha256:23d891e5bdc12e2e506e7d225d6aa929e0a0368c9916c1fddefab88166e98b20", + "sha256:266f655d1baff9c47b52f529b5f6bec33f66042f65f7c56adde3fcf2ed62ae8b", + "sha256:273473d34462ae6e97c0f4e517bd1bf9588aa67a1d47d93f760a1282640e24ac", + "sha256:2bd9ac6e44f2db368ef8986f3989a4cad3de4cd55dbdda536e253000c801bcc7", + "sha256:33714fcf5af4ff7e70a49731a7cc8fd9ce910b9ac194f66eaa18c3cc0a4c02be", + "sha256:359a8b09d712df27849e0bcb62c6a3404e780b274b0b7e4c39a88826d1926c28", + "sha256:365005e8b0718ea6d64b374423e870648ab47c3a905356ab6e5a5ff03962b9a9", + "sha256:389d2b2e543b27962990ab529ac6720c3dded588cc6d0f6557eec153305a3622", + "sha256:3b505f2bbff50d261176e67be24e8909e54b5d9d08b12d4946344066d66b3e43", + "sha256:3d74d4a3c4b8f7a1f676cedf8e84bcc57705a6d7925e6daef7a1e54ae543a197", + "sha256:3f3f00a9061605725df1816f5713d10cd94636347ed651abdbc75828df302b20", + "sha256:43498ea734ccdfb92e1886dfedaebeb81178a241d39a79d5351ba2b671bff2b2", + "sha256:4855161013dfb2b762e02b3f4d4a21cc7c6aec13c69e3bffbf5022b3e708dd97", + "sha256:4d973729ce04784906a19108054e1fd476bc85279a403ea1a72fdb051c76fa48", + "sha256:4ece9cca4cd1c8ba889bfa67eae7f21d0d1a2e715b4d5045395113361e8c533d", + "sha256:506becdf2ecaebaf7f7995f776394fcc8bd8a78022772de66677c84fb02dd33d", + "sha256:520486f27f1d4ce9654154b4494cf9307b495527f3a2908ad4cb48e4f7ed7ef7", + "sha256:5557461f83bb7cc718bc9ee1f7156d50e31747e5b38d79cf40f79ab1447afd2d", + "sha256:562778586949be7e0d7435fcb24aca4810913771f845d99145a6cee64d5b67ca", + "sha256:59bb5979f9941c61e907ee571732219fa4774d5a18f3fa5ff2df963f5dfaa6bc", + "sha256:606d445feeb0856c2b424405236a01c71af7c97e5fe42fbc778634faef2b47e4", + "sha256:6197c3f3c0b960ad033b9b7d611db11285bb461fc6b802c1dd50d04ad715c225", + "sha256:647459b23594f370c1c01768edaa0ba0959afc39caeeb793b43158bb9bb6a663", + "sha256:647bfe88b1997d7ae8d45dabc7c868d8cb0c8412a6e730a7651050b8c7289cf2", + "sha256:6bee9c2e501d835f91460b2c904bc359f8433e96799f5c2ff20feebd9bb1e590", + "sha256:6dbdacf5752fbd78ccdb434698230c4f0f95df7dd956d5f205b5ed6911a1367c", + "sha256:701847a7aaefef121c5c0d855b2affa5f9bd45196ef00266724a80e439220e46", + "sha256:786d6b57026e7e04d184313c1359ac3d68002c33e4b1042ca58c362f1d09ff58", + "sha256:7b378847a09d6bd46047f5f3599cdc64fcb4cc5a5a2dd0a2af610361fbe77b16", + "sha256:7d1d6c9e74c70ddf524e3c09d9dc0522aba9370708c2cb58680ea40174800013", + "sha256:857d6565f9aa3464764c2cb6a2e3c2e75e1970e877c188f4aeae45954a314e0c", + "sha256:8671622256a0859f5089cbe0ce4693c2af407bc053dcc99aadff7f5310b4aa02", + "sha256:88f7c383071981c74ec1998ba9b437659e4fd02a3c4a4d3efc16774eb108d0ec", + "sha256:8aecb5a7f6f7f8fe9cac0bcadd39efaca8bbf8d1bf242e9f175cbe4c925116c3", + "sha256:91bbf398ac8bb7d65a5a52127407c05f75a18d7015a270fdd94bbcb04e65d573", + "sha256:936e8880cc00f839aa4173f94466a8406a96ddce814651075f95837316369899", + "sha256:953dd5481bd6252bd480d6ec431f61d7d87fdcbbb71b0d2bdcfc6ae00bb6fb10", + "sha256:95ae6c5a196e2f239150aa4a479967351df7f44800c93e5a975ec726fef005e2", + "sha256:9a2b5915c333e4364367140443b59f09feae42184459b913f0f41b9fed55794a", + "sha256:9ae6c3363261021144121427b1552b29e7b59de9d6a75bf51e03bc072efb3c37", + "sha256:9b556596c49fa1232b0fff4b0e69b9d4083a502e60e404b44341e2f8fb7187f5", + "sha256:9c131447768ed7bc05a02553d939e7f0e807e533441901dd504e217b76307745", + "sha256:9d9d5726474cbbef279fd709008f91a49c4f758bec9c062dfbba88eab00e3ff9", + "sha256:a1bdcbebd4e13446a14de4dd1825f1e778e099f17f79718b4aeaf2403624b0f7", + "sha256:a602ed9bd2c7d85bd58592c28e101bd9ff9c718fbde06545a70945ffd5d11868", + "sha256:a8edae5253efa75c2fc79a90068fe540b197d1c7ab5803b800fccfe240eed33c", + "sha256:a905affe76f1802edcac554e3ccf68188bea16546071d7583fb1b693f9cf756b", + "sha256:a9e7c6d89c77bb2770c9491d988f26a4b161d05c8ca58f63fb1f1b6b9a74be45", + "sha256:aa9b5abd07f71b081a33115d9758ef6077924082055005808f68feccb27616bd", + "sha256:aaa5c173a26960fe67daa69aa93d6d6a1cd714a6eb13802d4e4bd1d24a530644", + "sha256:ac7674d1638df129d9cb4503d20ffc3922bd463c865ef3cb412f2c926108e9a4", + "sha256:b1541e50b78e15fa06a2670157a1962ef06591d4c998b998047fff5e3236880e", + "sha256:b1980dbcaad634fe78e710c8587383e6e3f61dbe146bcbfd13a9c8ab2d7b1192", + "sha256:bafa65e3acae612a7799ada439bd202403414ebe23f52e5b17f6ffc2eb98c2be", + "sha256:bb5bd6212eb0edfd1e8f254585290ea1dadc3687dd8fd5e2fd9a87c31915cdab", + "sha256:bbdd69e20fe2943b51e2841fc1e6a3c1de460d630f65bde12452d8c97209464d", + "sha256:bc354b1393dce46026ab13075f77b30e40b61b1a53e852e99d3cc5dd1af4bc85", + "sha256:bcee502c649fa6351b44bb014b98c09cb00982a475a1912a9881ca28ab4f9cd9", + "sha256:bdd9abccd0927673cffe601d2c6cdad1c9321bf3437a2f507d6b037ef91ea307", + "sha256:c42ae7e010d7d6bc51875d768110c10e8a59494855c3d4c348b068f5fb81fdcd", + "sha256:c71b5b860c5215fdbaa56f715bc218e45a98477f816b46cfde4a84d25b13274e", + "sha256:c7721a3ef41591341388bb2265395ce522aba52f969d33dacd822da8f018aff8", + "sha256:ca8e44b5ba3edb682ea4e6185b49661fc22b230cf811b9c13963c9f982d1d964", + "sha256:cb53669442895763e61df5c995f0e8361b61662f26c1b04ee82899c2789c8f69", + "sha256:cc02c06e9e320869d7d1bd323df6dd4281e78ac2e7f8526835d3d48c69060683", + "sha256:d3caa09e613ece43ac292fbed513a4bce170681a447d25ffcbc1b647d45a39c5", + "sha256:d82411dbf4d3127b6cde7da0f9373e37ad3a43e89ef374965465928f01c2b979", + "sha256:dbcb2dc07308453db428a95a4d03259bd8caea97d7f0776842299f2d00c72fc8", + "sha256:dd4fda67f5faaef4f9ee5383435048ee3e11ad996901225ad7615bc92245bc8e", + "sha256:ddd92e18b783aeb86ad2132d84a4b795fc5ec612e3545c1b687e7747e66e2b53", + "sha256:de362ac8bc962408ad8fae28f3967ce1a262b5d63ab8cefb42662566737f1dc7", + "sha256:e214025e23db238805a600f1f37bf9f9a15413c7bf5f9d6ae194f84980c78722", + "sha256:e8f9f93a23634cfafbad6e46ad7d09e0f4a25a2400e4a64b1b7b7c0fbaa06d9d", + "sha256:e96a1788f24d03e8d61679f9881a883ecdf9c445a38f9ae3f3f193ab6c591c66", + "sha256:ec53a09aee61d45e7dbe7e91252ff0491b6b5fee3d85b2d45b173d8ab453efc1", + "sha256:f10250bb190fb0742e3e1958dd5c100524c2cc5096c67c8da51233f7448dc137", + "sha256:f1faee2a831fe249e1bae9cbc68d3cd8a30f7e37851deee4d7962b17c410dd56", + "sha256:f610d980e3fccf4394ab3806de6065682982f3d27c12d4ce3ee46a8183d64a6a", + "sha256:f6c35b2f87c004270fa2e703b872fcc984d714d430b305145c39d53074e1ffe0", + "sha256:f836f39678cb47c9541f04d8ed4545719dc31ad850bf1832d6b4171e30d65d23", + "sha256:f99768232f036b4776ce419d3244a04fe83784bce871b16d2c2e984c7fcea847", + "sha256:fd814847901df6e8de13ce69b84c31fc9b3fb591224d6762d0b256d510cbf382", + "sha256:fdb325b7fba1e2c40b9b1db407f85642e32404131c08480dd652110fc908561b" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==4.9.3" + "version": "==4.9.4" }, "mako": { "hashes": [ @@ -2638,11 +2715,11 @@ }, "nbconvert": { "hashes": [ - "sha256:5b6c848194d270cc55fb691169202620d7b52a12fec259508d142ecbe4219310", - "sha256:b1564bd89f69a74cd6398b0362da94db07aafb991b7857216a766204a71612c0" + "sha256:2dc8267dbdfeedce2dcd34c9e3f1b51af18f43cb105549d1c5a18189ec23ba85", + "sha256:3c50eb2d326478cc90b8759cf2ab9dde3d892c6537cd6a5bc0991db8ef734bcc" ], "markers": "python_version >= '3.8'", - "version": "==7.12.0" + "version": "==7.13.1" }, "nbformat": { "hashes": [ @@ -2936,10 +3013,10 @@ }, "patsy": { "hashes": [ - "sha256:0486413077a527db51ddea8fa94a5234d0feb17a4f4dc01b59b6086c58a70f80", - "sha256:7dabc527597308de0e8f188faa20af7e06a89bdaa306756dfc7783693ea16af4" + "sha256:6067516e97c1d5da5d24603853834e3555e943ffb419ea32020f7ba561fa6d0d", + "sha256:7fbdebd44f1ceb1db2d45d03c19ccb0c424f71dc8e66f0f3eebf87b0ff3a071a" ], - "version": "==0.5.4" + "version": "==0.5.5" }, "pbr": { "hashes": [ @@ -2983,14 +3060,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.7.14" }, - "pexpect": { - "hashes": [ - "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", - "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f" - ], - "markers": "sys_platform != 'win32'", - "version": "==4.9.0" - }, "pillow": { "hashes": [ "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d", @@ -3061,11 +3130,11 @@ }, "pip": { "hashes": [ - "sha256:1fcaa041308d01f14575f6d0d2ea4b75a3e2871fe4f9c694976f908768e14174", - "sha256:55eb67bb6171d37447e82213be585b75fe2b12b359e993773aca4de9247a052b" + "sha256:5052d7889c1f9d05224cd41741acb7c5d6fa735ab34e339624a614eaaa7e7d76", + "sha256:7fd9972f96db22c8077a1ee2691b172c8089b17a5652a44494a9ecb0d78f9149" ], "markers": "python_version >= '3.7'", - "version": "==23.3.1" + "version": "==23.3.2" }, "pkginfo": { "hashes": [ @@ -3143,25 +3212,25 @@ }, "psutil": { "hashes": [ - "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28", - "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017", - "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602", - "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac", - "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a", - "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9", - "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4", - "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c", - "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c", - "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c", - "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a", - "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c", - "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57", - "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a", - "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d", - "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa" + "sha256:032f4f2c909818c86cea4fe2cc407f1c0f0cde8e6c6d702b28b8ce0c0d143340", + "sha256:0bd41bf2d1463dfa535942b2a8f0e958acf6607ac0be52265ab31f7923bcd5e6", + "sha256:1132704b876e58d277168cd729d64750633d5ff0183acf5b3c986b8466cd0284", + "sha256:1d4bc4a0148fdd7fd8f38e0498639ae128e64538faa507df25a20f8f7fb2341c", + "sha256:3c4747a3e2ead1589e647e64aad601981f01b68f9398ddf94d01e3dc0d1e57c7", + "sha256:3f02134e82cfb5d089fddf20bb2e03fd5cd52395321d1c8458a9e58500ff417c", + "sha256:44969859757f4d8f2a9bd5b76eba8c3099a2c8cf3992ff62144061e39ba8568e", + "sha256:4c03362e280d06bbbfcd52f29acd79c733e0af33d707c54255d21029b8b32ba6", + "sha256:5794944462509e49d4d458f4dbfb92c47539e7d8d15c796f141f474010084056", + "sha256:b27f8fdb190c8c03914f908a4555159327d7481dac2f01008d483137ef3311a9", + "sha256:c727ca5a9b2dd5193b8644b9f0c883d54f1248310023b5ad3e92036c5e2ada68", + "sha256:e469990e28f1ad738f65a42dcfc17adaed9d0f325d55047593cb9033a0ab63df", + "sha256:ea36cc62e69a13ec52b2f625c27527f6e4479bca2b340b7a452af55b34fcbe2e", + "sha256:f37f87e4d73b79e6c5e749440c3113b81d1ee7d26f21c19c47371ddea834f414", + "sha256:fe361f743cb3389b8efda21980d93eb55c1f1e3898269bc9a2a1d0bb7b1f6508", + "sha256:fe8b7f07948f1304497ce4f4684881250cd859b16d06a1dc4d7941eeb6233bfe" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==5.9.6" + "version": "==5.9.7" }, "psycopg2-binary": { "hashes": [ @@ -3241,13 +3310,6 @@ "markers": "python_version >= '3.7'", "version": "==2.9.9" }, - "ptyprocess": { - "hashes": [ - "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", - "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" - ], - "version": "==0.7.0" - }, "pure-eval": { "hashes": [ "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", @@ -3257,46 +3319,46 @@ }, "pyarrow": { "hashes": [ - "sha256:0140c7e2b740e08c5a459439d87acd26b747fc408bde0a8806096ee0baaa0c15", - "sha256:01e44de9749cddc486169cb632f3c99962318e9dacac7778315a110f4bf8a450", - "sha256:05fe7994745b634c5fb16ce5717e39a1ac1fac3e2b0795232841660aa76647cd", - "sha256:06ca79080ef89d6529bb8e5074d4b4f6086143b2520494fcb7cf8a99079cde93", - "sha256:097828b55321897db0e1dbfc606e3ff8101ae5725673498cbfa7754ee0da80e4", - "sha256:0f6f053cb66dc24091f5511e5920e45c83107f954a21032feadc7b9e3a8e7851", - "sha256:11e045dfa09855b6d3e7705a37c42e2dc2c71d608fab34d3c23df2e02df9aec3", - "sha256:1a8ae88c0038d1bc362a682320112ee6774f006134cd5afc291591ee4bc06505", - "sha256:1daab52050a1c48506c029e6fa0944a7b2436334d7e44221c16f6f1b2cc9c510", - "sha256:2a145dab9ed7849fc1101bf03bcdc69913547f10513fdf70fc3ab6c0a50c7eee", - "sha256:30d8494870d9916bb53b2a4384948491444741cb9a38253c590e21f836b01222", - "sha256:323cbe60210173ffd7db78bfd50b80bdd792c4c9daca8843ef3cd70b186649db", - "sha256:32542164d905002c42dff896efdac79b3bdd7291b1b74aa292fac8450d0e4dcd", - "sha256:33c1f6110c386464fd2e5e4ea3624466055bbe681ff185fd6c9daa98f30a3f9a", - "sha256:3c76807540989fe8fcd02285dd15e4f2a3da0b09d27781abec3adc265ddbeba1", - "sha256:3f6d5faf4f1b0d5a7f97be987cf9e9f8cd39902611e818fe134588ee99bf0283", - "sha256:450e4605e3c20e558485f9161a79280a61c55efe585d51513c014de9ae8d393f", - "sha256:470ae0194fbfdfbf4a6b65b4f9e0f6e1fa0ea5b90c1ee6b65b38aecee53508c8", - "sha256:4756a2b373a28f6166c42711240643fb8bd6322467e9aacabd26b488fa41ec23", - "sha256:58c889851ca33f992ea916b48b8540735055201b177cb0dcf0596a495a667b00", - "sha256:6263cffd0c3721c1e348062997babdf0151301f7353010c9c9a8ed47448f82ab", - "sha256:78d4a77a46a7de9388b653af1c4ce539350726cd9af62e0831e4f2bd0c95a2f4", - "sha256:7a8089d7e77d1455d529dbd7cff08898bbb2666ee48bc4085203af1d826a33cc", - "sha256:906b0dc25f2be12e95975722f1e60e162437023f490dbd80d0deb7375baf3171", - "sha256:922e8b49b88da8633d6cac0e1b5a690311b6758d6f5d7c2be71acb0f1e14cd61", - "sha256:96d64e5ba7dceb519a955e5eeb5c9adcfd63f73a56aea4722e2cc81364fc567a", - "sha256:981670b4ce0110d8dcb3246410a4aabf5714db5d8ea63b15686bce1c914b1f83", - "sha256:a8eeef015ae69d104c4c3117a6011e7e3ecd1abec79dc87fd2fac6e442f666ee", - "sha256:b8b3f4fe8d4ec15e1ef9b599b94683c5216adaed78d5cb4c606180546d1e2ee1", - "sha256:be28e1a07f20391bb0b15ea03dcac3aade29fc773c5eb4bee2838e9b2cdde0cb", - "sha256:c7331b4ed3401b7ee56f22c980608cf273f0380f77d0f73dd3c185f78f5a6220", - "sha256:cf87e2cec65dd5cf1aa4aba918d523ef56ef95597b545bbaad01e6433851aa10", - "sha256:d0351fecf0e26e152542bc164c22ea2a8e8c682726fce160ce4d459ea802d69c", - "sha256:d264ad13605b61959f2ae7c1d25b1a5b8505b112715c961418c8396433f213ad", - "sha256:e592e482edd9f1ab32f18cd6a716c45b2c0f2403dc2af782f4e9674952e6dd27", - "sha256:fada8396bc739d958d0b81d291cfd201126ed5e7913cb73de6bc606befc30226" + "sha256:059bd8f12a70519e46cd64e1ba40e97eae55e0cbe1695edd95384653d7626b23", + "sha256:06ff1264fe4448e8d02073f5ce45a9f934c0f3db0a04460d0b01ff28befc3696", + "sha256:1e6987c5274fb87d66bb36816afb6f65707546b3c45c44c28e3c4133c010a881", + "sha256:209bac546942b0d8edc8debda248364f7f668e4aad4741bae58e67d40e5fcf75", + "sha256:20e003a23a13da963f43e2b432483fdd8c38dc8882cd145f09f21792e1cf22a1", + "sha256:22a768987a16bb46220cef490c56c671993fbee8fd0475febac0b3e16b00a10e", + "sha256:2cc61593c8e66194c7cdfae594503e91b926a228fba40b5cf25cc593563bcd07", + "sha256:2dbba05e98f247f17e64303eb876f4a80fcd32f73c7e9ad975a83834d81f3fda", + "sha256:32356bfb58b36059773f49e4e214996888eeea3a08893e7dbde44753799b2a02", + "sha256:36cef6ba12b499d864d1def3e990f97949e0b79400d08b7cf74504ffbd3eb025", + "sha256:37c233ddbce0c67a76c0985612fef27c0c92aef9413cf5aa56952f359fcb7379", + "sha256:3c0fa3bfdb0305ffe09810f9d3e2e50a2787e3a07063001dcd7adae0cee3601a", + "sha256:3f16111f9ab27e60b391c5f6d197510e3ad6654e73857b4e394861fc79c37200", + "sha256:52809ee69d4dbf2241c0e4366d949ba035cbcf48409bf404f071f624ed313a2b", + "sha256:5c1da70d668af5620b8ba0a23f229030a4cd6c5f24a616a146f30d2386fec422", + "sha256:63ac901baec9369d6aae1cbe6cca11178fb018a8d45068aaf5bb54f94804a866", + "sha256:64df2bf1ef2ef14cee531e2dfe03dd924017650ffaa6f9513d7a1bb291e59c15", + "sha256:66e986dc859712acb0bd45601229021f3ffcdfc49044b64c6d071aaf4fa49e98", + "sha256:6dd4f4b472ccf4042f1eab77e6c8bce574543f54d2135c7e396f413046397d5a", + "sha256:75ee0efe7a87a687ae303d63037d08a48ef9ea0127064df18267252cfe2e9541", + "sha256:76fc257559404ea5f1306ea9a3ff0541bf996ff3f7b9209fc517b5e83811fa8e", + "sha256:78ea56f62fb7c0ae8ecb9afdd7893e3a7dbeb0b04106f5c08dbb23f9c0157591", + "sha256:87482af32e5a0c0cce2d12eb3c039dd1d853bd905b04f3f953f147c7a196915b", + "sha256:87e879323f256cb04267bb365add7208f302df942eb943c93a9dfeb8f44840b1", + "sha256:a01d0052d2a294a5f56cc1862933014e696aa08cc7b620e8c0cce5a5d362e976", + "sha256:a25eb2421a58e861f6ca91f43339d215476f4fe159eca603c55950c14f378cc5", + "sha256:a51fee3a7db4d37f8cda3ea96f32530620d43b0489d169b285d774da48ca9785", + "sha256:a898d134d00b1eca04998e9d286e19653f9d0fcb99587310cd10270907452a6b", + "sha256:b0c4a18e00f3a32398a7f31da47fefcd7a927545b396e1f15d0c85c2f2c778cd", + "sha256:ba9fe808596c5dbd08b3aeffe901e5f81095baaa28e7d5118e01354c64f22807", + "sha256:c65bf4fd06584f058420238bc47a316e80dda01ec0dfb3044594128a6c2db794", + "sha256:c87824a5ac52be210d32906c715f4ed7053d0180c1060ae3ff9b7e560f53f944", + "sha256:e354fba8490de258be7687f341bc04aba181fc8aa1f71e4584f9890d9cb2dec2", + "sha256:e4b123ad0f6add92de898214d404e488167b87b5dd86e9a434126bc2b7a5578d", + "sha256:f7d029f20ef56673a9730766023459ece397a05001f4e4d13805111d7c2108c0", + "sha256:fc0de7575e841f1595ac07e5bc631084fd06ca8b03c0f2ecece733d23cd5102a" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==14.0.1" + "version": "==14.0.2" }, "pyasn1": { "hashes": [ @@ -3350,122 +3412,122 @@ "email" ], "hashes": [ - "sha256:80c50fb8e3dcecfddae1adbcc00ec5822918490c99ab31f6cf6140ca1c1429f0", - "sha256:ff177ba64c6faf73d7afa2e8cad38fd456c0dbe01c9954e71038001cd15a6edd" + "sha256:b3ef57c62535b0941697cce638c08900d87fcb67e29cfa99e8a68f747f393f7a", + "sha256:d0caf5954bee831b6bfe7e338c32b9e30c85dfe080c843680783ac2b631673b4" ], "markers": "python_version >= '3.7'", - "version": "==2.5.2" + "version": "==2.5.3" }, "pydantic-core": { "hashes": [ - "sha256:038c9f763e650712b899f983076ce783175397c848da04985658e7628cbe873b", - "sha256:074f3d86f081ce61414d2dc44901f4f83617329c6f3ab49d2bc6c96948b2c26b", - "sha256:079206491c435b60778cf2b0ee5fd645e61ffd6e70c47806c9ed51fc75af078d", - "sha256:09b0e985fbaf13e6b06a56d21694d12ebca6ce5414b9211edf6f17738d82b0f8", - "sha256:0f6116a558fd06d1b7c2902d1c4cf64a5bd49d67c3540e61eccca93f41418124", - "sha256:103ef8d5b58596a731b690112819501ba1db7a36f4ee99f7892c40da02c3e189", - "sha256:16e29bad40bcf97aac682a58861249ca9dcc57c3f6be22f506501833ddb8939c", - "sha256:206ed23aecd67c71daf5c02c3cd19c0501b01ef3cbf7782db9e4e051426b3d0d", - "sha256:2248485b0322c75aee7565d95ad0e16f1c67403a470d02f94da7344184be770f", - "sha256:27548e16c79702f1e03f5628589c6057c9ae17c95b4c449de3c66b589ead0520", - "sha256:2d0ae0d8670164e10accbeb31d5ad45adb71292032d0fdb9079912907f0085f4", - "sha256:3128e0bbc8c091ec4375a1828d6118bc20404883169ac95ffa8d983b293611e6", - "sha256:3387277f1bf659caf1724e1afe8ee7dbc9952a82d90f858ebb931880216ea955", - "sha256:34708cc82c330e303f4ce87758828ef6e457681b58ce0e921b6e97937dd1e2a3", - "sha256:35613015f0ba7e14c29ac6c2483a657ec740e5ac5758d993fdd5870b07a61d8b", - "sha256:3ad873900297bb36e4b6b3f7029d88ff9829ecdc15d5cf20161775ce12306f8a", - "sha256:40180930807ce806aa71eda5a5a5447abb6b6a3c0b4b3b1b1962651906484d68", - "sha256:439c9afe34638ace43a49bf72d201e0ffc1a800295bed8420c2a9ca8d5e3dbb3", - "sha256:45e95333b8418ded64745f14574aa9bfc212cb4fbeed7a687b0c6e53b5e188cd", - "sha256:4641e8ad4efb697f38a9b64ca0523b557c7931c5f84e0fd377a9a3b05121f0de", - "sha256:49b08aae5013640a3bfa25a8eebbd95638ec3f4b2eaf6ed82cf0c7047133f03b", - "sha256:4bc536201426451f06f044dfbf341c09f540b4ebdb9fd8d2c6164d733de5e634", - "sha256:4ce601907e99ea5b4adb807ded3570ea62186b17f88e271569144e8cca4409c7", - "sha256:4e40f2bd0d57dac3feb3a3aed50f17d83436c9e6b09b16af271b6230a2915459", - "sha256:4e47a76848f92529879ecfc417ff88a2806438f57be4a6a8bf2961e8f9ca9ec7", - "sha256:513b07e99c0a267b1d954243845d8a833758a6726a3b5d8948306e3fe14675e3", - "sha256:531f4b4252fac6ca476fbe0e6f60f16f5b65d3e6b583bc4d87645e4e5ddde331", - "sha256:57d52fa717ff445cb0a5ab5237db502e6be50809b43a596fb569630c665abddf", - "sha256:59986de5710ad9613ff61dd9b02bdd2f615f1a7052304b79cc8fa2eb4e336d2d", - "sha256:5baab5455c7a538ac7e8bf1feec4278a66436197592a9bed538160a2e7d11e36", - "sha256:5c7d5b5005f177764e96bd584d7bf28d6e26e96f2a541fdddb934c486e36fd59", - "sha256:60b7607753ba62cf0739177913b858140f11b8af72f22860c28eabb2f0a61937", - "sha256:615a0a4bff11c45eb3c1996ceed5bdaa2f7b432425253a7c2eed33bb86d80abc", - "sha256:61ea96a78378e3bd5a0be99b0e5ed00057b71f66115f5404d0dae4819f495093", - "sha256:652c1988019752138b974c28f43751528116bcceadad85f33a258869e641d753", - "sha256:6637560562134b0e17de333d18e69e312e0458ee4455bdad12c37100b7cad706", - "sha256:678265f7b14e138d9a541ddabbe033012a2953315739f8cfa6d754cc8063e8ca", - "sha256:699156034181e2ce106c89ddb4b6504c30db8caa86e0c30de47b3e0654543260", - "sha256:6b9ff467ffbab9110e80e8c8de3bcfce8e8b0fd5661ac44a09ae5901668ba997", - "sha256:6c327e9cd849b564b234da821236e6bcbe4f359a42ee05050dc79d8ed2a91588", - "sha256:6d30226dfc816dd0fdf120cae611dd2215117e4f9b124af8c60ab9093b6e8e71", - "sha256:6e227c40c02fd873c2a73a98c1280c10315cbebe26734c196ef4514776120aeb", - "sha256:6e4d090e73e0725b2904fdbdd8d73b8802ddd691ef9254577b708d413bf3006e", - "sha256:70f4b4851dbb500129681d04cc955be2a90b2248d69273a787dda120d5cf1f69", - "sha256:70f947628e074bb2526ba1b151cee10e4c3b9670af4dbb4d73bc8a89445916b5", - "sha256:774de879d212db5ce02dfbf5b0da9a0ea386aeba12b0b95674a4ce0593df3d07", - "sha256:77fa384d8e118b3077cccfcaf91bf83c31fe4dc850b5e6ee3dc14dc3d61bdba1", - "sha256:79e0a2cdbdc7af3f4aee3210b1172ab53d7ddb6a2d8c24119b5706e622b346d0", - "sha256:7e88f5696153dc516ba6e79f82cc4747e87027205f0e02390c21f7cb3bd8abfd", - "sha256:7f8210297b04e53bc3da35db08b7302a6a1f4889c79173af69b72ec9754796b8", - "sha256:81982d78a45d1e5396819bbb4ece1fadfe5f079335dd28c4ab3427cd95389944", - "sha256:823fcc638f67035137a5cd3f1584a4542d35a951c3cc68c6ead1df7dac825c26", - "sha256:853a2295c00f1d4429db4c0fb9475958543ee80cfd310814b5c0ef502de24dda", - "sha256:88e74ab0cdd84ad0614e2750f903bb0d610cc8af2cc17f72c28163acfcf372a4", - "sha256:8aa1768c151cf562a9992462239dfc356b3d1037cc5a3ac829bb7f3bda7cc1f9", - "sha256:8c8a8812fe6f43a3a5b054af6ac2d7b8605c7bcab2804a8a7d68b53f3cd86e00", - "sha256:95b15e855ae44f0c6341ceb74df61b606e11f1087e87dcb7482377374aac6abe", - "sha256:96581cfefa9123accc465a5fd0cc833ac4d75d55cc30b633b402e00e7ced00a6", - "sha256:9bd18fee0923ca10f9a3ff67d4851c9d3e22b7bc63d1eddc12f439f436f2aada", - "sha256:a33324437018bf6ba1bb0f921788788641439e0ed654b233285b9c69704c27b4", - "sha256:a6a16f4a527aae4f49c875da3cdc9508ac7eef26e7977952608610104244e1b7", - "sha256:a717aef6971208f0851a2420b075338e33083111d92041157bbe0e2713b37325", - "sha256:a71891847f0a73b1b9eb86d089baee301477abef45f7eaf303495cd1473613e4", - "sha256:aae7ea3a1c5bb40c93cad361b3e869b180ac174656120c42b9fadebf685d121b", - "sha256:ab1cdb0f14dc161ebc268c09db04d2c9e6f70027f3b42446fa11c153521c0e88", - "sha256:ab4ea451082e684198636565224bbb179575efc1658c48281b2c866bfd4ddf04", - "sha256:abf058be9517dc877227ec3223f0300034bd0e9f53aebd63cf4456c8cb1e0863", - "sha256:af36f36538418f3806048f3b242a1777e2540ff9efaa667c27da63d2749dbce0", - "sha256:b53e9ad053cd064f7e473a5f29b37fc4cc9dc6d35f341e6afc0155ea257fc911", - "sha256:b7851992faf25eac90bfcb7bfd19e1f5ffa00afd57daec8a0042e63c74a4551b", - "sha256:b9b759b77f5337b4ea024f03abc6464c9f35d9718de01cfe6bae9f2e139c397e", - "sha256:ba39688799094c75ea8a16a6b544eb57b5b0f3328697084f3f2790892510d144", - "sha256:ba6b6b3846cfc10fdb4c971980a954e49d447cd215ed5a77ec8190bc93dd7bc5", - "sha256:bb4c2eda937a5e74c38a41b33d8c77220380a388d689bcdb9b187cf6224c9720", - "sha256:c0b97ec434041827935044bbbe52b03d6018c2897349670ff8fe11ed24d1d4ab", - "sha256:c1452a1acdf914d194159439eb21e56b89aa903f2e1c65c60b9d874f9b950e5d", - "sha256:c2027d05c8aebe61d898d4cffd774840a9cb82ed356ba47a90d99ad768f39789", - "sha256:c2adbe22ab4babbca99c75c5d07aaf74f43c3195384ec07ccbd2f9e3bddaecec", - "sha256:c2d97e906b4ff36eb464d52a3bc7d720bd6261f64bc4bcdbcd2c557c02081ed2", - "sha256:c339dabd8ee15f8259ee0f202679b6324926e5bc9e9a40bf981ce77c038553db", - "sha256:c6eae413494a1c3f89055da7a5515f32e05ebc1a234c27674a6956755fb2236f", - "sha256:c949f04ecad823f81b1ba94e7d189d9dfb81edbb94ed3f8acfce41e682e48cef", - "sha256:c97bee68898f3f4344eb02fec316db93d9700fb1e6a5b760ffa20d71d9a46ce3", - "sha256:ca61d858e4107ce5e1330a74724fe757fc7135190eb5ce5c9d0191729f033209", - "sha256:cb4679d4c2b089e5ef89756bc73e1926745e995d76e11925e3e96a76d5fa51fc", - "sha256:cb774298da62aea5c80a89bd58c40205ab4c2abf4834453b5de207d59d2e1651", - "sha256:ccd4d5702bb90b84df13bd491be8d900b92016c5a455b7e14630ad7449eb03f8", - "sha256:cf9d3fe53b1ee360e2421be95e62ca9b3296bf3f2fb2d3b83ca49ad3f925835e", - "sha256:d2ae91f50ccc5810b2f1b6b858257c9ad2e08da70bf890dee02de1775a387c66", - "sha256:d37f8ec982ead9ba0a22a996129594938138a1503237b87318392a48882d50b7", - "sha256:d81e6987b27bc7d101c8597e1cd2bcaa2fee5e8e0f356735c7ed34368c471550", - "sha256:dcf4e6d85614f7a4956c2de5a56531f44efb973d2fe4a444d7251df5d5c4dcfd", - "sha256:de790a3b5aa2124b8b78ae5faa033937a72da8efe74b9231698b5a1dd9be3405", - "sha256:e47e9a08bcc04d20975b6434cc50bf82665fbc751bcce739d04a3120428f3e27", - "sha256:e60f112ac88db9261ad3a52032ea46388378034f3279c643499edb982536a093", - "sha256:e87fc540c6cac7f29ede02e0f989d4233f88ad439c5cdee56f693cc9c1c78077", - "sha256:eac5c82fc632c599f4639a5886f96867ffced74458c7db61bc9a66ccb8ee3113", - "sha256:ebb4e035e28f49b6f1a7032920bb9a0c064aedbbabe52c543343d39341a5b2a3", - "sha256:ec1e72d6412f7126eb7b2e3bfca42b15e6e389e1bc88ea0069d0cc1742f477c6", - "sha256:ef98ca7d5995a82f43ec0ab39c4caf6a9b994cb0b53648ff61716370eadc43cf", - "sha256:f0cbc7fff06a90bbd875cc201f94ef0ee3929dfbd5c55a06674b60857b8b85ed", - "sha256:f4791cf0f8c3104ac668797d8c514afb3431bc3305f5638add0ba1a5a37e0d88", - "sha256:f5e412d717366e0677ef767eac93566582518fe8be923361a5c204c1a62eaafe", - "sha256:fb2ed8b3fe4bf4506d6dab3b93b83bbc22237e230cba03866d561c3577517d18", - "sha256:fe0a5a1025eb797752136ac8b4fa21aa891e3d74fd340f864ff982d649691867" + "sha256:00646784f6cd993b1e1c0e7b0fdcbccc375d539db95555477771c27555e3c556", + "sha256:00b1087dabcee0b0ffd104f9f53d7d3eaddfaa314cdd6726143af6bc713aa27e", + "sha256:0348b1dc6b76041516e8a854ff95b21c55f5a411c3297d2ca52f5528e49d8411", + "sha256:036137b5ad0cb0004c75b579445a1efccd072387a36c7f217bb8efd1afbe5245", + "sha256:095b707bb287bfd534044166ab767bec70a9bba3175dcdc3371782175c14e43c", + "sha256:0c08de15d50fa190d577e8591f0329a643eeaed696d7771760295998aca6bc66", + "sha256:1302a54f87b5cd8528e4d6d1bf2133b6aa7c6122ff8e9dc5220fbc1e07bffebd", + "sha256:172de779e2a153d36ee690dbc49c6db568d7b33b18dc56b69a7514aecbcf380d", + "sha256:1b027c86c66b8627eb90e57aee1f526df77dc6d8b354ec498be9a757d513b92b", + "sha256:1ce830e480f6774608dedfd4a90c42aac4a7af0a711f1b52f807130c2e434c06", + "sha256:1fd0c1d395372843fba13a51c28e3bb9d59bd7aebfeb17358ffaaa1e4dbbe948", + "sha256:23598acb8ccaa3d1d875ef3b35cb6376535095e9405d91a3d57a8c7db5d29341", + "sha256:24368e31be2c88bd69340fbfe741b405302993242ccb476c5c3ff48aeee1afe0", + "sha256:26a92ae76f75d1915806b77cf459811e772d8f71fd1e4339c99750f0e7f6324f", + "sha256:27e524624eace5c59af499cd97dc18bb201dc6a7a2da24bfc66ef151c69a5f2a", + "sha256:2b8719037e570639e6b665a4050add43134d80b687288ba3ade18b22bbb29dd2", + "sha256:2c5bcf3414367e29f83fd66f7de64509a8fd2368b1edf4351e862910727d3e51", + "sha256:2dbe357bc4ddda078f79d2a36fc1dd0494a7f2fad83a0a684465b6f24b46fe80", + "sha256:2f5fa187bde8524b1e37ba894db13aadd64faa884657473b03a019f625cee9a8", + "sha256:2f6ffc6701a0eb28648c845f4945a194dc7ab3c651f535b81793251e1185ac3d", + "sha256:314ccc4264ce7d854941231cf71b592e30d8d368a71e50197c905874feacc8a8", + "sha256:36026d8f99c58d7044413e1b819a67ca0e0b8ebe0f25e775e6c3d1fabb3c38fb", + "sha256:36099c69f6b14fc2c49d7996cbf4f87ec4f0e66d1c74aa05228583225a07b590", + "sha256:36fa402dcdc8ea7f1b0ddcf0df4254cc6b2e08f8cd80e7010d4c4ae6e86b2a87", + "sha256:370ffecb5316ed23b667d99ce4debe53ea664b99cc37bfa2af47bc769056d534", + "sha256:3860c62057acd95cc84044e758e47b18dcd8871a328ebc8ccdefd18b0d26a21b", + "sha256:399ac0891c284fa8eb998bcfa323f2234858f5d2efca3950ae58c8f88830f145", + "sha256:3a0b5db001b98e1c649dd55afa928e75aa4087e587b9524a4992316fa23c9fba", + "sha256:3dcf1978be02153c6a31692d4fbcc2a3f1db9da36039ead23173bc256ee3b91b", + "sha256:4241204e4b36ab5ae466ecec5c4c16527a054c69f99bba20f6f75232a6a534e2", + "sha256:438027a975cc213a47c5d70672e0d29776082155cfae540c4e225716586be75e", + "sha256:43e166ad47ba900f2542a80d83f9fc65fe99eb63ceec4debec160ae729824052", + "sha256:478e9e7b360dfec451daafe286998d4a1eeaecf6d69c427b834ae771cad4b622", + "sha256:4ce8299b481bcb68e5c82002b96e411796b844d72b3e92a3fbedfe8e19813eab", + "sha256:4f86f1f318e56f5cbb282fe61eb84767aee743ebe32c7c0834690ebea50c0a6b", + "sha256:55a23dcd98c858c0db44fc5c04fc7ed81c4b4d33c653a7c45ddaebf6563a2f66", + "sha256:599c87d79cab2a6a2a9df4aefe0455e61e7d2aeede2f8577c1b7c0aec643ee8e", + "sha256:5aa90562bc079c6c290f0512b21768967f9968e4cfea84ea4ff5af5d917016e4", + "sha256:64634ccf9d671c6be242a664a33c4acf12882670b09b3f163cd00a24cffbd74e", + "sha256:667aa2eac9cd0700af1ddb38b7b1ef246d8cf94c85637cbb03d7757ca4c3fdec", + "sha256:6a31d98c0d69776c2576dda4b77b8e0c69ad08e8b539c25c7d0ca0dc19a50d6c", + "sha256:6af4b3f52cc65f8a0bc8b1cd9676f8c21ef3e9132f21fed250f6958bd7223bed", + "sha256:6c8edaea3089bf908dd27da8f5d9e395c5b4dc092dbcce9b65e7156099b4b937", + "sha256:71d72ca5eaaa8d38c8df16b7deb1a2da4f650c41b58bb142f3fb75d5ad4a611f", + "sha256:72f9a942d739f09cd42fffe5dc759928217649f070056f03c70df14f5770acf9", + "sha256:747265448cb57a9f37572a488a57d873fd96bf51e5bb7edb52cfb37124516da4", + "sha256:75ec284328b60a4e91010c1acade0c30584f28a1f345bc8f72fe8b9e46ec6a96", + "sha256:78d0768ee59baa3de0f4adac9e3748b4b1fffc52143caebddfd5ea2961595277", + "sha256:78ee52ecc088c61cce32b2d30a826f929e1708f7b9247dc3b921aec367dc1b23", + "sha256:7be719e4d2ae6c314f72844ba9d69e38dff342bc360379f7c8537c48e23034b7", + "sha256:7e1f4744eea1501404b20b0ac059ff7e3f96a97d3e3f48ce27a139e053bb370b", + "sha256:7e90d6cc4aad2cc1f5e16ed56e46cebf4877c62403a311af20459c15da76fd91", + "sha256:7ebe3416785f65c28f4f9441e916bfc8a54179c8dea73c23023f7086fa601c5d", + "sha256:7f41533d7e3cf9520065f610b41ac1c76bc2161415955fbcead4981b22c7611e", + "sha256:7f5025db12fc6de7bc1104d826d5aee1d172f9ba6ca936bf6474c2148ac336c1", + "sha256:86c963186ca5e50d5c8287b1d1c9d3f8f024cbe343d048c5bd282aec2d8641f2", + "sha256:86ce5fcfc3accf3a07a729779d0b86c5d0309a4764c897d86c11089be61da160", + "sha256:8a14c192c1d724c3acbfb3f10a958c55a2638391319ce8078cb36c02283959b9", + "sha256:8b93785eadaef932e4fe9c6e12ba67beb1b3f1e5495631419c784ab87e975670", + "sha256:8ed1af8692bd8d2a29d702f1a2e6065416d76897d726e45a1775b1444f5928a7", + "sha256:92879bce89f91f4b2416eba4429c7b5ca22c45ef4a499c39f0c5c69257522c7c", + "sha256:94fc0e6621e07d1e91c44e016cc0b189b48db053061cc22d6298a611de8071bb", + "sha256:982487f8931067a32e72d40ab6b47b1628a9c5d344be7f1a4e668fb462d2da42", + "sha256:9862bf828112e19685b76ca499b379338fd4c5c269d897e218b2ae8fcb80139d", + "sha256:99b14dbea2fdb563d8b5a57c9badfcd72083f6006caf8e126b491519c7d64ca8", + "sha256:9c6a5c79b28003543db3ba67d1df336f253a87d3112dac3a51b94f7d48e4c0e1", + "sha256:a19b794f8fe6569472ff77602437ec4430f9b2b9ec7a1105cfd2232f9ba355e6", + "sha256:a306cdd2ad3a7d795d8e617a58c3a2ed0f76c8496fb7621b6cd514eb1532cae8", + "sha256:a3dde6cac75e0b0902778978d3b1646ca9f438654395a362cb21d9ad34b24acf", + "sha256:a874f21f87c485310944b2b2734cd6d318765bcbb7515eead33af9641816506e", + "sha256:a983cca5ed1dd9a35e9e42ebf9f278d344603bfcb174ff99a5815f953925140a", + "sha256:aca48506a9c20f68ee61c87f2008f81f8ee99f8d7f0104bff3c47e2d148f89d9", + "sha256:b2602177668f89b38b9f84b7b3435d0a72511ddef45dc14446811759b82235a1", + "sha256:b3e5fe4538001bb82e2295b8d2a39356a84694c97cb73a566dc36328b9f83b40", + "sha256:b6ca36c12a5120bad343eef193cc0122928c5c7466121da7c20f41160ba00ba2", + "sha256:b89f4477d915ea43b4ceea6756f63f0288941b6443a2b28c69004fe07fde0d0d", + "sha256:b9a9d92f10772d2a181b5ca339dee066ab7d1c9a34ae2421b2a52556e719756f", + "sha256:c99462ffc538717b3e60151dfaf91125f637e801f5ab008f81c402f1dff0cd0f", + "sha256:cb92f9061657287eded380d7dc455bbf115430b3aa4741bdc662d02977e7d0af", + "sha256:cdee837710ef6b56ebd20245b83799fce40b265b3b406e51e8ccc5b85b9099b7", + "sha256:cf10b7d58ae4a1f07fccbf4a0a956d705356fea05fb4c70608bb6fa81d103cda", + "sha256:d15687d7d7f40333bd8266f3814c591c2e2cd263fa2116e314f60d82086e353a", + "sha256:d5c28525c19f5bb1e09511669bb57353d22b94cf8b65f3a8d141c389a55dec95", + "sha256:d5f916acf8afbcab6bacbb376ba7dc61f845367901ecd5e328fc4d4aef2fcab0", + "sha256:dab03ed811ed1c71d700ed08bde8431cf429bbe59e423394f0f4055f1ca0ea60", + "sha256:db453f2da3f59a348f514cfbfeb042393b68720787bbef2b4c6068ea362c8149", + "sha256:de2a0645a923ba57c5527497daf8ec5df69c6eadf869e9cd46e86349146e5975", + "sha256:dea7fcd62915fb150cdc373212141a30037e11b761fbced340e9db3379b892d4", + "sha256:dfcbebdb3c4b6f739a91769aea5ed615023f3c88cb70df812849aef634c25fbe", + "sha256:dfcebb950aa7e667ec226a442722134539e77c575f6cfaa423f24371bb8d2e94", + "sha256:e0641b506486f0b4cd1500a2a65740243e8670a2549bb02bc4556a83af84ae03", + "sha256:e33b0834f1cf779aa839975f9d8755a7c2420510c0fa1e9fa0497de77cd35d2c", + "sha256:e4ace1e220b078c8e48e82c081e35002038657e4b37d403ce940fa679e57113b", + "sha256:e4cf2d5829f6963a5483ec01578ee76d329eb5caf330ecd05b3edd697e7d768a", + "sha256:e574de99d735b3fc8364cba9912c2bec2da78775eba95cbb225ef7dda6acea24", + "sha256:e646c0e282e960345314f42f2cea5e0b5f56938c093541ea6dbf11aec2862391", + "sha256:e8a5ac97ea521d7bde7621d86c30e86b798cdecd985723c4ed737a2aa9e77d0c", + "sha256:eedf97be7bc3dbc8addcef4142f4b4164066df0c6f36397ae4aaed3eb187d8ab", + "sha256:ef633add81832f4b56d3b4c9408b43d530dfca29e68fb1b797dcb861a2c734cd", + "sha256:f27207e8ca3e5e021e2402ba942e5b4c629718e665c81b8b306f3c8b1ddbb786", + "sha256:f85f3843bdb1fe80e8c206fe6eed7a1caeae897e496542cee499c374a85c6e08", + "sha256:f8e81e4b55930e5ffab4a68db1af431629cf2e4066dbdbfef65348b8ab804ea8", + "sha256:f96ae96a060a8072ceff4cfde89d261837b4294a4f28b84a28765470d502ccc6", + "sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0", + "sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421" ], "markers": "python_version >= '3.7'", - "version": "==2.14.5" + "version": "==2.14.6" }, "pydantic-settings": { "hashes": [ @@ -3539,6 +3601,14 @@ "markers": "python_version >= '3.7'", "version": "==1.0.0" }, + "pyreadline3": { + "hashes": [ + "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae", + "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb" + ], + "markers": "python_version >= '3.8' and sys_platform == 'win32'", + "version": "==3.4.1" + }, "pytest": { "hashes": [ "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac", @@ -3634,6 +3704,46 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2020.1" }, + "pywin32": { + "hashes": [ + "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d", + "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65", + "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e", + "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b", + "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4", + "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040", + "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a", + "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36", + "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8", + "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e", + "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802", + "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a", + "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407", + "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0" + ], + "markers": "platform_system == 'Windows'", + "version": "==306" + }, + "pywin32-ctypes": { + "hashes": [ + "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60", + "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7" + ], + "markers": "sys_platform == 'win32'", + "version": "==0.2.2" + }, + "pywinpty": { + "hashes": [ + "sha256:1617b729999eb6713590e17665052b1a6ae0ad76ee31e60b444147c5b6a35dca", + "sha256:189380469ca143d06e19e19ff3fba0fcefe8b4a8cc942140a6b863aed7eebb2d", + "sha256:21319cd1d7c8844fb2c970fb3a55a3db5543f112ff9cfcd623746b9c47501575", + "sha256:7520575b6546db23e693cbd865db2764097bd6d4ef5dc18c92555904cd62c3d4", + "sha256:8197de460ae8ebb7f5d1701dfa1b5df45b157bb832e92acba316305e18ca00dd", + "sha256:853985a8f48f4731a716653170cd735da36ffbdc79dcb4c7b7140bce11d8c722" + ], + "markers": "os_name == 'nt'", + "version": "==2.0.12" + }, "pyxlsb": { "hashes": [ "sha256:8062d1ea8626d3f1980e8b1cfe91a4483747449242ecb61013bc2df85435f685", @@ -3839,10 +3949,10 @@ }, "readthedocs-sphinx-ext": { "hashes": [ - "sha256:77b5b12e9fa6bb7ab623e7be5bfbd7523c83a2ea72c48f6f6f4d5e3df87ac896", - "sha256:e99ed77d7618b2990d12953ba03722d1f354f7dd0f4097702383d40d2288ce3c" + "sha256:ee5fd5b99db9f0c180b2396cbce528aa36671951b9526bb0272dbfce5517bd27", + "sha256:f8c56184ea011c972dd45a90122568587cc85b0127bc9cf064d17c68bc809daa" ], - "version": "==2.2.4" + "version": "==2.2.5" }, "recordlinkage": { "hashes": [ @@ -3862,97 +3972,102 @@ }, "regex": { "hashes": [ - "sha256:00ba3c9818e33f1fa974693fb55d24cdc8ebafcb2e4207680669d8f8d7cca79a", - "sha256:00e871d83a45eee2f8688d7e6849609c2ca2a04a6d48fba3dff4deef35d14f07", - "sha256:06e9abc0e4c9ab4779c74ad99c3fc10d3967d03114449acc2c2762ad4472b8ca", - "sha256:0b9ac09853b2a3e0d0082104036579809679e7715671cfbf89d83c1cb2a30f58", - "sha256:0d47840dc05e0ba04fe2e26f15126de7c755496d5a8aae4a08bda4dd8d646c54", - "sha256:0f649fa32fe734c4abdfd4edbb8381c74abf5f34bc0b3271ce687b23729299ed", - "sha256:107ac60d1bfdc3edb53be75e2a52aff7481b92817cfdddd9b4519ccf0e54a6ff", - "sha256:11175910f62b2b8c055f2b089e0fedd694fe2be3941b3e2633653bc51064c528", - "sha256:12bd4bc2c632742c7ce20db48e0d99afdc05e03f0b4c1af90542e05b809a03d9", - "sha256:16f8740eb6dbacc7113e3097b0a36065a02e37b47c936b551805d40340fb9971", - "sha256:1c0e8fae5b27caa34177bdfa5a960c46ff2f78ee2d45c6db15ae3f64ecadde14", - "sha256:2c54e23836650bdf2c18222c87f6f840d4943944146ca479858404fedeb9f9af", - "sha256:3367007ad1951fde612bf65b0dffc8fd681a4ab98ac86957d16491400d661302", - "sha256:36362386b813fa6c9146da6149a001b7bd063dabc4d49522a1f7aa65b725c7ec", - "sha256:39807cbcbe406efca2a233884e169d056c35aa7e9f343d4e78665246a332f597", - "sha256:39cdf8d141d6d44e8d5a12a8569d5a227f645c87df4f92179bd06e2e2705e76b", - "sha256:3b2c3502603fab52d7619b882c25a6850b766ebd1b18de3df23b2f939360e1bd", - "sha256:3ccf2716add72f80714b9a63899b67fa711b654be3fcdd34fa391d2d274ce767", - "sha256:3fef4f844d2290ee0ba57addcec17eec9e3df73f10a2748485dfd6a3a188cc0f", - "sha256:4023e2efc35a30e66e938de5aef42b520c20e7eda7bb5fb12c35e5d09a4c43f6", - "sha256:4a3ee019a9befe84fa3e917a2dd378807e423d013377a884c1970a3c2792d293", - "sha256:4a8bf76e3182797c6b1afa5b822d1d5802ff30284abe4599e1247be4fd6b03be", - "sha256:4a992f702c9be9c72fa46f01ca6e18d131906a7180950958f766c2aa294d4b41", - "sha256:4c34d4f73ea738223a094d8e0ffd6d2c1a1b4c175da34d6b0de3d8d69bee6bcc", - "sha256:4cd1bccf99d3ef1ab6ba835308ad85be040e6a11b0977ef7ea8c8005f01a3c29", - "sha256:4ef80829117a8061f974b2fda8ec799717242353bff55f8a29411794d635d964", - "sha256:58837f9d221744d4c92d2cf7201c6acd19623b50c643b56992cbd2b745485d3d", - "sha256:5a8f91c64f390ecee09ff793319f30a0f32492e99f5dc1c72bc361f23ccd0a9a", - "sha256:5addc9d0209a9afca5fc070f93b726bf7003bd63a427f65ef797a931782e7edc", - "sha256:6239d4e2e0b52c8bd38c51b760cd870069f0bdf99700a62cd509d7a031749a55", - "sha256:66e2fe786ef28da2b28e222c89502b2af984858091675044d93cb50e6f46d7af", - "sha256:69c0771ca5653c7d4b65203cbfc5e66db9375f1078689459fe196fe08b7b4930", - "sha256:6ac965a998e1388e6ff2e9781f499ad1eaa41e962a40d11c7823c9952c77123e", - "sha256:6c56c3d47da04f921b73ff9415fbaa939f684d47293f071aa9cbb13c94afc17d", - "sha256:6f85739e80d13644b981a88f529d79c5bdf646b460ba190bffcaf6d57b2a9863", - "sha256:706e7b739fdd17cb89e1fbf712d9dc21311fc2333f6d435eac2d4ee81985098c", - "sha256:741ba2f511cc9626b7561a440f87d658aabb3d6b744a86a3c025f866b4d19e7f", - "sha256:7434a61b158be563c1362d9071358f8ab91b8d928728cd2882af060481244c9e", - "sha256:76066d7ff61ba6bf3cb5efe2428fc82aac91802844c022d849a1f0f53820502d", - "sha256:7979b834ec7a33aafae34a90aad9f914c41fd6eaa8474e66953f3f6f7cbd4368", - "sha256:7eece6fbd3eae4a92d7c748ae825cbc1ee41a89bb1c3db05b5578ed3cfcfd7cb", - "sha256:7ef1e014eed78ab650bef9a6a9cbe50b052c0aebe553fb2881e0453717573f52", - "sha256:81dce2ddc9f6e8f543d94b05d56e70d03a0774d32f6cca53e978dc01e4fc75b8", - "sha256:82fcc1f1cc3ff1ab8a57ba619b149b907072e750815c5ba63e7aa2e1163384a4", - "sha256:8d1f21af4c1539051049796a0f50aa342f9a27cde57318f2fc41ed50b0dbc4ac", - "sha256:90a79bce019c442604662d17bf69df99090e24cdc6ad95b18b6725c2988a490e", - "sha256:9145f092b5d1977ec8c0ab46e7b3381b2fd069957b9862a43bd383e5c01d18c2", - "sha256:91dc1d531f80c862441d7b66c4505cd6ea9d312f01fb2f4654f40c6fdf5cc37a", - "sha256:979c24cbefaf2420c4e377ecd1f165ea08cc3d1fbb44bdc51bccbbf7c66a2cb4", - "sha256:994645a46c6a740ee8ce8df7911d4aee458d9b1bc5639bc968226763d07f00fa", - "sha256:9b98b7681a9437262947f41c7fac567c7e1f6eddd94b0483596d320092004533", - "sha256:9c6b4d23c04831e3ab61717a707a5d763b300213db49ca680edf8bf13ab5d91b", - "sha256:9c6d0ced3c06d0f183b73d3c5920727268d2201aa0fe6d55c60d68c792ff3588", - "sha256:9fd88f373cb71e6b59b7fa597e47e518282455c2734fd4306a05ca219a1991b0", - "sha256:a8f4e49fc3ce020f65411432183e6775f24e02dff617281094ba6ab079ef0915", - "sha256:a9e908ef5889cda4de038892b9accc36d33d72fb3e12c747e2799a0e806ec841", - "sha256:ad08a69728ff3c79866d729b095872afe1e0557251da4abb2c5faff15a91d19a", - "sha256:adbccd17dcaff65704c856bd29951c58a1bd4b2b0f8ad6b826dbd543fe740988", - "sha256:b0c7d2f698e83f15228ba41c135501cfe7d5740181d5903e250e47f617eb4292", - "sha256:b3ab05a182c7937fb374f7e946f04fb23a0c0699c0450e9fb02ef567412d2fa3", - "sha256:b6104f9a46bd8743e4f738afef69b153c4b8b592d35ae46db07fc28ae3d5fb7c", - "sha256:ba7cd6dc4d585ea544c1412019921570ebd8a597fabf475acc4528210d7c4a6f", - "sha256:bc72c231f5449d86d6c7d9cc7cd819b6eb30134bb770b8cfdc0765e48ef9c420", - "sha256:bce8814b076f0ce5766dc87d5a056b0e9437b8e0cd351b9a6c4e1134a7dfbda9", - "sha256:be5e22bbb67924dea15039c3282fa4cc6cdfbe0cbbd1c0515f9223186fc2ec5f", - "sha256:be6b7b8d42d3090b6c80793524fa66c57ad7ee3fe9722b258aec6d0672543fd0", - "sha256:bfe50b61bab1b1ec260fa7cd91106fa9fece57e6beba05630afe27c71259c59b", - "sha256:bff507ae210371d4b1fe316d03433ac099f184d570a1a611e541923f78f05037", - "sha256:c148bec483cc4b421562b4bcedb8e28a3b84fcc8f0aa4418e10898f3c2c0eb9b", - "sha256:c15ad0aee158a15e17e0495e1e18741573d04eb6da06d8b84af726cfc1ed02ee", - "sha256:c2169b2dcabf4e608416f7f9468737583ce5f0a6e8677c4efbf795ce81109d7c", - "sha256:c55853684fe08d4897c37dfc5faeff70607a5f1806c8be148f1695be4a63414b", - "sha256:c65a3b5330b54103e7d21cac3f6bf3900d46f6d50138d73343d9e5b2900b2353", - "sha256:c7964c2183c3e6cce3f497e3a9f49d182e969f2dc3aeeadfa18945ff7bdd7051", - "sha256:cc3f1c053b73f20c7ad88b0d1d23be7e7b3901229ce89f5000a8399746a6e039", - "sha256:ce615c92d90df8373d9e13acddd154152645c0dc060871abf6bd43809673d20a", - "sha256:d29338556a59423d9ff7b6eb0cb89ead2b0875e08fe522f3e068b955c3e7b59b", - "sha256:d8a993c0a0ffd5f2d3bda23d0cd75e7086736f8f8268de8a82fbc4bd0ac6791e", - "sha256:d9c727bbcf0065cbb20f39d2b4f932f8fa1631c3e01fcedc979bd4f51fe051c5", - "sha256:dac37cf08fcf2094159922edc7a2784cfcc5c70f8354469f79ed085f0328ebdf", - "sha256:dd829712de97753367153ed84f2de752b86cd1f7a88b55a3a775eb52eafe8a94", - "sha256:e54ddd0bb8fb626aa1f9ba7b36629564544954fff9669b15da3610c22b9a0991", - "sha256:e77c90ab5997e85901da85131fd36acd0ed2221368199b65f0d11bca44549711", - "sha256:ebedc192abbc7fd13c5ee800e83a6df252bec691eb2c4bedc9f8b2e2903f5e2a", - "sha256:ef71561f82a89af6cfcbee47f0fabfdb6e63788a9258e913955d89fdd96902ab", - "sha256:f0a47efb1dbef13af9c9a54a94a0b814902e547b7f21acb29434504d18f36e3a", - "sha256:f4f2ca6df64cbdd27f27b34f35adb640b5d2d77264228554e68deda54456eb11", - "sha256:fb02e4257376ae25c6dd95a5aec377f9b18c09be6ebdefa7ad209b9137b73d48" + "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5", + "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770", + "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc", + "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105", + "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d", + "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b", + "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9", + "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630", + "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6", + "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c", + "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482", + "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6", + "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a", + "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80", + "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5", + "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1", + "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f", + "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf", + "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb", + "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2", + "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347", + "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20", + "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060", + "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5", + "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73", + "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f", + "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d", + "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3", + "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae", + "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4", + "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2", + "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457", + "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c", + "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4", + "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87", + "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0", + "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704", + "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f", + "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f", + "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b", + "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5", + "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923", + "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715", + "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c", + "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca", + "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1", + "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756", + "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360", + "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc", + "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445", + "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e", + "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4", + "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a", + "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8", + "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53", + "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697", + "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf", + "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a", + "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415", + "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f", + "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9", + "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400", + "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d", + "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392", + "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb", + "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd", + "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861", + "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232", + "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95", + "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7", + "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39", + "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887", + "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5", + "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39", + "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb", + "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586", + "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97", + "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423", + "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69", + "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7", + "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1", + "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7", + "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5", + "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8", + "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91", + "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590", + "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe", + "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c", + "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64", + "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd", + "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa", + "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31", + "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988" ], "markers": "python_version >= '3.7'", - "version": "==2023.10.3" + "version": "==2023.12.25" }, "requests": { "hashes": [ @@ -4018,108 +4133,108 @@ }, "rpds-py": { "hashes": [ - "sha256:06d218e4464d31301e943b65b2c6919318ea6f69703a351961e1baaf60347276", - "sha256:12ecf89bd54734c3c2c79898ae2021dca42750c7bcfb67f8fb3315453738ac8f", - "sha256:15253fff410873ebf3cfba1cc686a37711efcd9b8cb30ea21bb14a973e393f60", - "sha256:188435794405c7f0573311747c85a96b63c954a5f2111b1df8018979eca0f2f0", - "sha256:1ceebd0ae4f3e9b2b6b553b51971921853ae4eebf3f54086be0565d59291e53d", - "sha256:244e173bb6d8f3b2f0c4d7370a1aa341f35da3e57ffd1798e5b2917b91731fd3", - "sha256:25b28b3d33ec0a78e944aaaed7e5e2a94ac811bcd68b557ca48a0c30f87497d2", - "sha256:25ea41635d22b2eb6326f58e608550e55d01df51b8a580ea7e75396bafbb28e9", - "sha256:29d311e44dd16d2434d5506d57ef4d7036544fc3c25c14b6992ef41f541b10fb", - "sha256:2a1472956c5bcc49fb0252b965239bffe801acc9394f8b7c1014ae9258e4572b", - "sha256:2a7bef6977043673750a88da064fd513f89505111014b4e00fbdd13329cd4e9a", - "sha256:2ac26f50736324beb0282c819668328d53fc38543fa61eeea2c32ea8ea6eab8d", - "sha256:2e72f750048b32d39e87fc85c225c50b2a6715034848dbb196bf3348aa761fa1", - "sha256:31e220a040b89a01505128c2f8a59ee74732f666439a03e65ccbf3824cdddae7", - "sha256:35f53c76a712e323c779ca39b9a81b13f219a8e3bc15f106ed1e1462d56fcfe9", - "sha256:38d4f822ee2f338febcc85aaa2547eb5ba31ba6ff68d10b8ec988929d23bb6b4", - "sha256:38f9bf2ad754b4a45b8210a6c732fe876b8a14e14d5992a8c4b7c1ef78740f53", - "sha256:3a44c8440183b43167fd1a0819e8356692bf5db1ad14ce140dbd40a1485f2dea", - "sha256:3ab96754d23372009638a402a1ed12a27711598dd49d8316a22597141962fe66", - "sha256:3c55d7f2d817183d43220738270efd3ce4e7a7b7cbdaefa6d551ed3d6ed89190", - "sha256:46e1ed994a0920f350a4547a38471217eb86f57377e9314fbaaa329b71b7dfe3", - "sha256:4a5375c5fff13f209527cd886dc75394f040c7d1ecad0a2cb0627f13ebe78a12", - "sha256:4c2d26aa03d877c9730bf005621c92da263523a1e99247590abbbe252ccb7824", - "sha256:4c4e314d36d4f31236a545696a480aa04ea170a0b021e9a59ab1ed94d4c3ef27", - "sha256:4d0c10d803549427f427085ed7aebc39832f6e818a011dcd8785e9c6a1ba9b3e", - "sha256:4dcc5ee1d0275cb78d443fdebd0241e58772a354a6d518b1d7af1580bbd2c4e8", - "sha256:51967a67ea0d7b9b5cd86036878e2d82c0b6183616961c26d825b8c994d4f2c8", - "sha256:530190eb0cd778363bbb7596612ded0bb9fef662daa98e9d92a0419ab27ae914", - "sha256:5379e49d7e80dca9811b36894493d1c1ecb4c57de05c36f5d0dd09982af20211", - "sha256:5493569f861fb7b05af6d048d00d773c6162415ae521b7010197c98810a14cab", - "sha256:5a4c1058cdae6237d97af272b326e5f78ee7ee3bbffa6b24b09db4d828810468", - "sha256:5d75d6d220d55cdced2f32cc22f599475dbe881229aeddba6c79c2e9df35a2b3", - "sha256:5d97e9ae94fb96df1ee3cb09ca376c34e8a122f36927230f4c8a97f469994bff", - "sha256:5feae2f9aa7270e2c071f488fab256d768e88e01b958f123a690f1cc3061a09c", - "sha256:603d5868f7419081d616dab7ac3cfa285296735e7350f7b1e4f548f6f953ee7d", - "sha256:61d42d2b08430854485135504f672c14d4fc644dd243a9c17e7c4e0faf5ed07e", - "sha256:61dbc1e01dc0c5875da2f7ae36d6e918dc1b8d2ce04e871793976594aad8a57a", - "sha256:65cfed9c807c27dee76407e8bb29e6f4e391e436774bcc769a037ff25ad8646e", - "sha256:67a429520e97621a763cf9b3ba27574779c4e96e49a27ff8a1aa99ee70beb28a", - "sha256:6aadae3042f8e6db3376d9e91f194c606c9a45273c170621d46128f35aef7cd0", - "sha256:6ba8858933f0c1a979781272a5f65646fca8c18c93c99c6ddb5513ad96fa54b1", - "sha256:6bc568b05e02cd612be53900c88aaa55012e744930ba2eeb56279db4c6676eb3", - "sha256:729408136ef8d45a28ee9a7411917c9e3459cf266c7e23c2f7d4bb8ef9e0da42", - "sha256:751758d9dd04d548ec679224cc00e3591f5ebf1ff159ed0d4aba6a0746352452", - "sha256:76d59d4d451ba77f08cb4cd9268dec07be5bc65f73666302dbb5061989b17198", - "sha256:79bf58c08f0756adba691d480b5a20e4ad23f33e1ae121584cf3a21717c36dfa", - "sha256:7de12b69d95072394998c622cfd7e8cea8f560db5fca6a62a148f902a1029f8b", - "sha256:7f55cd9cf1564b7b03f238e4c017ca4794c05b01a783e9291065cb2858d86ce4", - "sha256:80e5acb81cb49fd9f2d5c08f8b74ffff14ee73b10ca88297ab4619e946bcb1e1", - "sha256:87a90f5545fd61f6964e65eebde4dc3fa8660bb7d87adb01d4cf17e0a2b484ad", - "sha256:881df98f0a8404d32b6de0fd33e91c1b90ed1516a80d4d6dc69d414b8850474c", - "sha256:8a776a29b77fe0cc28fedfd87277b0d0f7aa930174b7e504d764e0b43a05f381", - "sha256:8c2a61c0e4811012b0ba9f6cdcb4437865df5d29eab5d6018ba13cee1c3064a0", - "sha256:8fa6bd071ec6d90f6e7baa66ae25820d57a8ab1b0a3c6d3edf1834d4b26fafa2", - "sha256:96f2975fb14f39c5fe75203f33dd3010fe37d1c4e33177feef1107b5ced750e3", - "sha256:96fb0899bb2ab353f42e5374c8f0789f54e0a94ef2f02b9ac7149c56622eaf31", - "sha256:97163a1ab265a1073a6372eca9f4eeb9f8c6327457a0b22ddfc4a17dcd613e74", - "sha256:9c95a1a290f9acf7a8f2ebbdd183e99215d491beea52d61aa2a7a7d2c618ddc6", - "sha256:9d94d78418203904730585efa71002286ac4c8ac0689d0eb61e3c465f9e608ff", - "sha256:a6ba2cb7d676e9415b9e9ac7e2aae401dc1b1e666943d1f7bc66223d3d73467b", - "sha256:aa0379c1935c44053c98826bc99ac95f3a5355675a297ac9ce0dfad0ce2d50ca", - "sha256:ac96d67b37f28e4b6ecf507c3405f52a40658c0a806dffde624a8fcb0314d5fd", - "sha256:ade2ccb937060c299ab0dfb2dea3d2ddf7e098ed63ee3d651ebfc2c8d1e8632a", - "sha256:aefbdc934115d2f9278f153952003ac52cd2650e7313750390b334518c589568", - "sha256:b07501b720cf060c5856f7b5626e75b8e353b5f98b9b354a21eb4bfa47e421b1", - "sha256:b5267feb19070bef34b8dea27e2b504ebd9d31748e3ecacb3a4101da6fcb255c", - "sha256:b5f6328e8e2ae8238fc767703ab7b95785521c42bb2b8790984e3477d7fa71ad", - "sha256:b8996ffb60c69f677245f5abdbcc623e9442bcc91ed81b6cd6187129ad1fa3e7", - "sha256:b981a370f8f41c4024c170b42fbe9e691ae2dbc19d1d99151a69e2c84a0d194d", - "sha256:b9d121be0217787a7d59a5c6195b0842d3f701007333426e5154bf72346aa658", - "sha256:bcef4f2d3dc603150421de85c916da19471f24d838c3c62a4f04c1eb511642c1", - "sha256:bed0252c85e21cf73d2d033643c945b460d6a02fc4a7d644e3b2d6f5f2956c64", - "sha256:bfdfbe6a36bc3059fff845d64c42f2644cf875c65f5005db54f90cdfdf1df815", - "sha256:c0095b8aa3e432e32d372e9a7737e65b58d5ed23b9620fea7cb81f17672f1fa1", - "sha256:c1f41d32a2ddc5a94df4b829b395916a4b7f103350fa76ba6de625fcb9e773ac", - "sha256:c45008ca79bad237cbc03c72bc5205e8c6f66403773929b1b50f7d84ef9e4d07", - "sha256:c82bbf7e03748417c3a88c1b0b291288ce3e4887a795a3addaa7a1cfd9e7153e", - "sha256:c918621ee0a3d1fe61c313f2489464f2ae3d13633e60f520a8002a5e910982ee", - "sha256:d204957169f0b3511fb95395a9da7d4490fb361763a9f8b32b345a7fe119cb45", - "sha256:d329896c40d9e1e5c7715c98529e4a188a1f2df51212fd65102b32465612b5dc", - "sha256:d3a61e928feddc458a55110f42f626a2a20bea942ccedb6fb4cee70b4830ed41", - "sha256:d48db29bd47814671afdd76c7652aefacc25cf96aad6daefa82d738ee87461e2", - "sha256:d5593855b5b2b73dd8413c3fdfa5d95b99d657658f947ba2c4318591e745d083", - "sha256:d79c159adea0f1f4617f54aa156568ac69968f9ef4d1e5fefffc0a180830308e", - "sha256:db09b98c7540df69d4b47218da3fbd7cb466db0fb932e971c321f1c76f155266", - "sha256:ddf23960cb42b69bce13045d5bc66f18c7d53774c66c13f24cf1b9c144ba3141", - "sha256:e06cfea0ece444571d24c18ed465bc93afb8c8d8d74422eb7026662f3d3f779b", - "sha256:e7c564c58cf8f248fe859a4f0fe501b050663f3d7fbc342172f259124fb59933", - "sha256:e86593bf8637659e6a6ed58854b6c87ec4e9e45ee8a4adfd936831cef55c2d21", - "sha256:eaffbd8814bb1b5dc3ea156a4c5928081ba50419f9175f4fc95269e040eff8f0", - "sha256:ee353bb51f648924926ed05e0122b6a0b1ae709396a80eb583449d5d477fcdf7", - "sha256:ee6faebb265e28920a6f23a7d4c362414b3f4bb30607141d718b991669e49ddc", - "sha256:efe093acc43e869348f6f2224df7f452eab63a2c60a6c6cd6b50fd35c4e075ba", - "sha256:f03a1b3a4c03e3e0161642ac5367f08479ab29972ea0ffcd4fa18f729cd2be0a", - "sha256:f0d320e70b6b2300ff6029e234e79fe44e9dbbfc7b98597ba28e054bd6606a57", - "sha256:f252dfb4852a527987a9156cbcae3022a30f86c9d26f4f17b8c967d7580d65d2", - "sha256:f5f4424cb87a20b016bfdc157ff48757b89d2cc426256961643d443c6c277007", - "sha256:f8eae66a1304de7368932b42d801c67969fd090ddb1a7a24f27b435ed4bed68f", - "sha256:fdb82eb60d31b0c033a8e8ee9f3fc7dfbaa042211131c29da29aea8531b4f18f" + "sha256:0474df4ade9a3b4af96c3d36eb81856cb9462e4c6657d4caecfd840d2a13f3c9", + "sha256:071980663c273bf3d388fe5c794c547e6f35ba3335477072c713a3176bf14a60", + "sha256:07aab64e2808c3ebac2a44f67e9dc0543812b715126dfd6fe4264df527556cb6", + "sha256:088396c7c70e59872f67462fcac3ecbded5233385797021976a09ebd55961dfe", + "sha256:162d7cd9cd311c1b0ff1c55a024b8f38bd8aad1876b648821da08adc40e95734", + "sha256:19f00f57fdd38db4bb5ad09f9ead1b535332dbf624200e9029a45f1f35527ebb", + "sha256:1bdbc5fcb04a7309074de6b67fa9bc4b418ab3fc435fec1f2779a0eced688d04", + "sha256:1be2f033df1b8be8c3167ba3c29d5dca425592ee31e35eac52050623afba5772", + "sha256:24f7a2eb3866a9e91f4599851e0c8d39878a470044875c49bd528d2b9b88361c", + "sha256:290a81cfbe4673285cdf140ec5cd1658ffbf63ab359f2b352ebe172e7cfa5bf0", + "sha256:2946b120718eba9af2b4dd103affc1164a87b9e9ebff8c3e4c05d7b7a7e274e2", + "sha256:2bd82db36cd70b3628c0c57d81d2438e8dd4b7b32a6a9f25f24ab0e657cb6c4e", + "sha256:2ddef620e70eaffebed5932ce754d539c0930f676aae6212f8e16cd9743dd365", + "sha256:2e53b9b25cac9065328901713a7e9e3b12e4f57ef4280b370fbbf6fef2052eef", + "sha256:302bd4983bbd47063e452c38be66153760112f6d3635c7eeefc094299fa400a9", + "sha256:349cb40897fd529ca15317c22c0eab67f5ac5178b5bd2c6adc86172045210acc", + "sha256:358dafc89ce3894c7f486c615ba914609f38277ef67f566abc4c854d23b997fa", + "sha256:35953f4f2b3216421af86fd236b7c0c65935936a94ea83ddbd4904ba60757773", + "sha256:35ae5ece284cf36464eb160880018cf6088a9ac5ddc72292a6092b6ef3f4da53", + "sha256:3b811d182ad17ea294f2ec63c0621e7be92a1141e1012383461872cead87468f", + "sha256:3da5a4c56953bdbf6d04447c3410309616c54433146ccdb4a277b9cb499bc10e", + "sha256:3dc6a7620ba7639a3db6213da61312cb4aa9ac0ca6e00dc1cbbdc21c2aa6eb57", + "sha256:3f91df8e6dbb7360e176d1affd5fb0246d2b88d16aa5ebc7db94fd66b68b61da", + "sha256:4022b9dc620e14f30201a8a73898a873c8e910cb642bcd2f3411123bc527f6ac", + "sha256:413b9c17388bbd0d87a329d8e30c1a4c6e44e2bb25457f43725a8e6fe4161e9e", + "sha256:43d4dd5fb16eb3825742bad8339d454054261ab59fed2fbac84e1d84d5aae7ba", + "sha256:44627b6ca7308680a70766454db5249105fa6344853af6762eaad4158a2feebe", + "sha256:44a54e99a2b9693a37ebf245937fd6e9228b4cbd64b9cc961e1f3391ec6c7391", + "sha256:47713dc4fce213f5c74ca8a1f6a59b622fc1b90868deb8e8e4d993e421b4b39d", + "sha256:495a14b72bbe217f2695dcd9b5ab14d4f8066a00f5d209ed94f0aca307f85f6e", + "sha256:4c46ad6356e1561f2a54f08367d1d2e70a0a1bb2db2282d2c1972c1d38eafc3b", + "sha256:4d6a9f052e72d493efd92a77f861e45bab2f6be63e37fa8ecf0c6fd1a58fedb0", + "sha256:509b617ac787cd1149600e731db9274ebbef094503ca25158e6f23edaba1ca8f", + "sha256:5552f328eaef1a75ff129d4d0c437bf44e43f9436d3996e8eab623ea0f5fcf73", + "sha256:5a80e2f83391ad0808b4646732af2a7b67550b98f0cae056cb3b40622a83dbb3", + "sha256:5cf6af100ffb5c195beec11ffaa8cf8523057f123afa2944e6571d54da84cdc9", + "sha256:5e6caa3809e50690bd92fa490f5c38caa86082c8c3315aa438bce43786d5e90d", + "sha256:5ef00873303d678aaf8b0627e111fd434925ca01c657dbb2641410f1cdaef261", + "sha256:69ac7ea9897ec201ce68b48582f3eb34a3f9924488a5432a93f177bf76a82a7e", + "sha256:6a61226465bda9283686db8f17d02569a98e4b13c637be5a26d44aa1f1e361c2", + "sha256:6d904c5693e08bad240f16d79305edba78276be87061c872a4a15e2c301fa2c0", + "sha256:6dace7b26a13353e24613417ce2239491b40a6ad44e5776a18eaff7733488b44", + "sha256:6df15846ee3fb2e6397fe25d7ca6624af9f89587f3f259d177b556fed6bebe2c", + "sha256:703d95c75a72e902544fda08e965885525e297578317989fd15a6ce58414b41d", + "sha256:726ac36e8a3bb8daef2fd482534cabc5e17334052447008405daca7ca04a3108", + "sha256:781ef8bfc091b19960fc0142a23aedadafa826bc32b433fdfe6fd7f964d7ef44", + "sha256:80443fe2f7b3ea3934c5d75fb0e04a5dbb4a8e943e5ff2de0dec059202b70a8b", + "sha256:83640a5d7cd3bff694747d50436b8b541b5b9b9782b0c8c1688931d6ee1a1f2d", + "sha256:84c5a4d1f9dd7e2d2c44097fb09fffe728629bad31eb56caf97719e55575aa82", + "sha256:882ce6e25e585949c3d9f9abd29202367175e0aab3aba0c58c9abbb37d4982ff", + "sha256:888a97002e986eca10d8546e3c8b97da1d47ad8b69726dcfeb3e56348ebb28a3", + "sha256:8aad80645a011abae487d356e0ceb359f4938dfb6f7bcc410027ed7ae4f7bb8b", + "sha256:8cb6fe8ecdfffa0e711a75c931fb39f4ba382b4b3ccedeca43f18693864fe850", + "sha256:8d6b6937ae9eac6d6c0ca3c42774d89fa311f55adff3970fb364b34abde6ed3d", + "sha256:90123853fc8b1747f80b0d354be3d122b4365a93e50fc3aacc9fb4c2488845d6", + "sha256:96f957d6ab25a78b9e7fc9749d754b98eac825a112b4e666525ce89afcbd9ed5", + "sha256:981d135c7cdaf6cd8eadae1c950de43b976de8f09d8e800feed307140d3d6d00", + "sha256:9b32f742ce5b57201305f19c2ef7a184b52f6f9ba6871cc042c2a61f0d6b49b8", + "sha256:9f0350ef2fba5f34eb0c9000ea328e51b9572b403d2f7f3b19f24085f6f598e8", + "sha256:a297a4d08cc67c7466c873c78039d87840fb50d05473db0ec1b7b03d179bf322", + "sha256:a3d7e2ea25d3517c6d7e5a1cc3702cffa6bd18d9ef8d08d9af6717fc1c700eed", + "sha256:a4b682c5775d6a3d21e314c10124599976809455ee67020e8e72df1769b87bc3", + "sha256:a4ebb8b20bd09c5ce7884c8f0388801100f5e75e7f733b1b6613c713371feefc", + "sha256:a61f659665a39a4d17d699ab3593d7116d66e1e2e3f03ef3fb8f484e91908808", + "sha256:a9880b4656efe36ccad41edc66789e191e5ee19a1ea8811e0aed6f69851a82f4", + "sha256:ac08472f41ea77cd6a5dae36ae7d4ed3951d6602833af87532b556c1b4601d63", + "sha256:adc0c3d6fc6ae35fee3e4917628983f6ce630d513cbaad575b4517d47e81b4bb", + "sha256:af27423662f32d7501a00c5e7342f7dbd1e4a718aea7a239781357d15d437133", + "sha256:b2e75e17bd0bb66ee34a707da677e47c14ee51ccef78ed6a263a4cc965a072a1", + "sha256:b634c5ec0103c5cbebc24ebac4872b045cccb9456fc59efdcf6fe39775365bd2", + "sha256:b6f5549d6ed1da9bfe3631ca9483ae906f21410be2445b73443fa9f017601c6f", + "sha256:bd4b677d929cf1f6bac07ad76e0f2d5de367e6373351c01a9c0a39f6b21b4a8b", + "sha256:bf721ede3eb7b829e4a9b8142bd55db0bdc82902720548a703f7e601ee13bdc3", + "sha256:c647ca87fc0ebe808a41de912e9a1bfef9acb85257e5d63691364ac16b81c1f0", + "sha256:ca57468da2d9a660bcf8961637c85f2fbb2aa64d9bc3f9484e30c3f9f67b1dd7", + "sha256:cad0f59ee3dc35526039f4bc23642d52d5f6616b5f687d846bfc6d0d6d486db0", + "sha256:cc97f0640e91d7776530f06e6836c546c1c752a52de158720c4224c9e8053cad", + "sha256:ccd4e400309e1f34a5095bf9249d371f0fd60f8a3a5c4a791cad7b99ce1fd38d", + "sha256:cffa76b385dfe1e38527662a302b19ffb0e7f5cf7dd5e89186d2c94a22dd9d0c", + "sha256:d0dd7ed2f16df2e129496e7fbe59a34bc2d7fc8db443a606644d069eb69cbd45", + "sha256:d452817e0d9c749c431a1121d56a777bd7099b720b3d1c820f1725cb40928f58", + "sha256:d8dda2a806dfa4a9b795950c4f5cc56d6d6159f7d68080aedaff3bdc9b5032f5", + "sha256:dcbe1f8dd179e4d69b70b1f1d9bb6fd1e7e1bdc9c9aad345cdeb332e29d40748", + "sha256:e0441fb4fdd39a230477b2ca9be90868af64425bfe7b122b57e61e45737a653b", + "sha256:e04e56b4ca7a770593633556e8e9e46579d66ec2ada846b401252a2bdcf70a6d", + "sha256:e061de3b745fe611e23cd7318aec2c8b0e4153939c25c9202a5811ca911fd733", + "sha256:e93ec1b300acf89730cf27975ef574396bc04edecc358e9bd116fb387a123239", + "sha256:e9e557db6a177470316c82f023e5d571811c9a4422b5ea084c85da9aa3c035fc", + "sha256:eab36eae3f3e8e24b05748ec9acc66286662f5d25c52ad70cadab544e034536b", + "sha256:ec23fcad480e77ede06cf4127a25fc440f7489922e17fc058f426b5256ee0edb", + "sha256:ec2e1cf025b2c0f48ec17ff3e642661da7ee332d326f2e6619366ce8e221f018", + "sha256:ed99b4f7179d2111702020fd7d156e88acd533f5a7d3971353e568b6051d5c97", + "sha256:ee94cb58c0ba2c62ee108c2b7c9131b2c66a29e82746e8fa3aa1a1effbd3dcf1", + "sha256:f19afcfc0dd0dca35694df441e9b0f95bc231b512f51bded3c3d8ca32153ec19", + "sha256:f1b9d9260e06ea017feb7172976ab261e011c1dc2f8883c7c274f6b2aabfe01a", + "sha256:f28ac0e8e7242d140f99402a903a2c596ab71550272ae9247ad78f9a932b5698", + "sha256:f42e25c016927e2a6b1ce748112c3ab134261fc2ddc867e92d02006103e1b1b7", + "sha256:f4bd4578e44f26997e9e56c96dedc5f1af43cc9d16c4daa29c771a00b2a26851", + "sha256:f811771019f063bbd0aa7bb72c8a934bc13ebacb4672d712fc1639cfd314cccc" ], "markers": "python_version >= '3.8'", - "version": "==0.13.2" + "version": "==0.16.2" }, "rsa": { "hashes": [ @@ -4195,34 +4310,34 @@ }, "ruff": { "hashes": [ - "sha256:05ffe9dbd278965271252704eddb97b4384bf58b971054d517decfbf8c523f05", - "sha256:5daaeaf00ae3c1efec9742ff294b06c3a2a9db8d3db51ee4851c12ad385cda30", - "sha256:7d076717c67b34c162da7c1a5bda16ffc205e0e0072c03745275e7eab888719f", - "sha256:7de792582f6e490ae6aef36a58d85df9f7a0cfd1b0d4fe6b4fb51803a3ac96fa", - "sha256:a05b0ddd7ea25495e4115a43125e8a7ebed0aa043c3d432de7e7d6e8e8cd6448", - "sha256:aa8ee4f8440023b0a6c3707f76cadce8657553655dcbb5fc9b2f9bb9bee389f6", - "sha256:b6a21ab023124eafb7cef6d038f835cb1155cd5ea798edd8d9eb2f8b84be07d9", - "sha256:bd8ee69b02e7bdefe1e5da2d5b6eaaddcf4f90859f00281b2333c0e3a0cc9cd6", - "sha256:c8e3255afd186c142eef4ec400d7826134f028a85da2146102a1172ecc7c3696", - "sha256:ce697c463458555027dfb194cb96d26608abab920fa85213deb5edf26e026664", - "sha256:db6cedd9ffed55548ab313ad718bc34582d394e27a7875b4b952c2d29c001b26", - "sha256:e49fbdfe257fa41e5c9e13c79b9e79a23a79bd0e40b9314bc53840f520c2c0b3", - "sha256:e6f08ca730f4dc1b76b473bdf30b1b37d42da379202a059eae54ec7fc1fbcfed", - "sha256:f35960b02df6b827c1b903091bb14f4b003f6cf102705efc4ce78132a0aa5af3", - "sha256:f41f692f1691ad87f51708b823af4bb2c5c87c9248ddd3191c8f088e66ce590a", - "sha256:f7ee467677467526cfe135eab86a40a0e8db43117936ac4f9b469ce9cdb3fb62", - "sha256:ff78a7583020da124dd0deb835ece1d87bb91762d40c514ee9b67a087940528b" + "sha256:0e17f53bcbb4fff8292dfd84cf72d767b5e146f009cccd40c2fad27641f8a7a9", + "sha256:104aa9b5e12cb755d9dce698ab1b97726b83012487af415a4512fedd38b1459e", + "sha256:1e63bf5a4a91971082a4768a0aba9383c12392d0d6f1e2be2248c1f9054a20da", + "sha256:28d920e319783d5303333630dae46ecc80b7ba294aeffedf946a02ac0b7cc3db", + "sha256:2aec598fb65084e41a9c5d4b95726173768a62055aafb07b4eff976bac72a592", + "sha256:331aae2cd4a0554667ac683243b151c74bd60e78fb08c3c2a4ac05ee1e606a39", + "sha256:479ca4250cab30f9218b2e563adc362bd6ae6343df7c7b5a7865300a5156d5a6", + "sha256:4d0738917c203246f3e275b37006faa3aa96c828b284ebfe3e99a8cb413c8c4b", + "sha256:69dac82d63a50df2ab0906d97a01549f814b16bc806deeac4f064ff95c47ddf5", + "sha256:744dfe4b35470fa3820d5fe45758aace6269c578f7ddc43d447868cfe5078bcb", + "sha256:8151425a60878e66f23ad47da39265fc2fad42aed06fb0a01130e967a7a064f4", + "sha256:837c739729394df98f342319f5136f33c65286b28b6b70a87c28f59354ec939b", + "sha256:aa8344310f1ae79af9ccd6e4b32749e93cddc078f9b5ccd0e45bd76a6d2e8bb6", + "sha256:b041dee2734719ddbb4518f762c982f2e912e7f28b8ee4fe1dee0b15d1b6e800", + "sha256:c497d769164df522fdaf54c6eba93f397342fe4ca2123a2e014a5b8fc7df81c7", + "sha256:e6837202c2859b9f22e43cb01992373c2dbfeae5c0c91ad691a4a2e725392464", + "sha256:e6a212f436122ac73df851f0cf006e0c6612fe6f9c864ed17ebefce0eff6a5fd" ], "markers": "python_version >= '3.7'", - "version": "==0.1.8" + "version": "==0.1.9" }, "s3transfer": { "hashes": [ - "sha256:01d4d2c35a016db8cb14f9a4d5e84c1f8c96e7ffc211422555eed45c11fa7eb1", - "sha256:9e1b186ec8bb5907a1e82b51237091889a9973a2bb799a924bcd9f301ff79d3d" + "sha256:3cdb40f5cfa6966e812209d0994f2a4709b561c88e90cf00c2696d2df4e56b2e", + "sha256:d0c8bbf672d5eebbe4e57945e23b972d963f07d82f661cabf678a5c88831595b" ], "markers": "python_version >= '3.8'", - "version": "==0.9.0" + "version": "==0.10.0" }, "scikit-learn": { "hashes": [ @@ -4332,11 +4447,11 @@ }, "setuptools": { "hashes": [ - "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2", - "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6" + "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05", + "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78" ], "markers": "python_version >= '3.8'", - "version": "==69.0.2" + "version": "==69.0.3" }, "shapely": { "hashes": [ @@ -4543,59 +4658,59 @@ }, "sqlalchemy": { "hashes": [ - "sha256:0666031df46b9badba9bed00092a1ffa3aa063a5e68fa244acd9f08070e936d3", - "sha256:0a8c6aa506893e25a04233bc721c6b6cf844bafd7250535abb56cb6cc1368884", - "sha256:0e680527245895aba86afbd5bef6c316831c02aa988d1aad83c47ffe92655e74", - "sha256:14aebfe28b99f24f8a4c1346c48bc3d63705b1f919a24c27471136d2f219f02d", - "sha256:1e018aba8363adb0599e745af245306cb8c46b9ad0a6fc0a86745b6ff7d940fc", - "sha256:227135ef1e48165f37590b8bfc44ed7ff4c074bf04dc8d6f8e7f1c14a94aa6ca", - "sha256:31952bbc527d633b9479f5f81e8b9dfada00b91d6baba021a869095f1a97006d", - "sha256:3e983fa42164577d073778d06d2cc5d020322425a509a08119bdcee70ad856bf", - "sha256:42d0b0290a8fb0165ea2c2781ae66e95cca6e27a2fbe1016ff8db3112ac1e846", - "sha256:42ede90148b73fe4ab4a089f3126b2cfae8cfefc955c8174d697bb46210c8306", - "sha256:4895a63e2c271ffc7a81ea424b94060f7b3b03b4ea0cd58ab5bb676ed02f4221", - "sha256:4af79c06825e2836de21439cb2a6ce22b2ca129bad74f359bddd173f39582bf5", - "sha256:5f94aeb99f43729960638e7468d4688f6efccb837a858b34574e01143cf11f89", - "sha256:616fe7bcff0a05098f64b4478b78ec2dfa03225c23734d83d6c169eb41a93e55", - "sha256:62d9e964870ea5ade4bc870ac4004c456efe75fb50404c03c5fd61f8bc669a72", - "sha256:638c2c0b6b4661a4fd264f6fb804eccd392745c5887f9317feb64bb7cb03b3ea", - "sha256:63bfc3acc970776036f6d1d0e65faa7473be9f3135d37a463c5eba5efcdb24c8", - "sha256:6463aa765cf02b9247e38b35853923edbf2f6fd1963df88706bc1d02410a5577", - "sha256:64ac935a90bc479fee77f9463f298943b0e60005fe5de2aa654d9cdef46c54df", - "sha256:683ef58ca8eea4747737a1c35c11372ffeb84578d3aab8f3e10b1d13d66f2bc4", - "sha256:75eefe09e98043cff2fb8af9796e20747ae870c903dc61d41b0c2e55128f958d", - "sha256:787af80107fb691934a01889ca8f82a44adedbf5ef3d6ad7d0f0b9ac557e0c34", - "sha256:7c424983ab447dab126c39d3ce3be5bee95700783204a72549c3dceffe0fc8f4", - "sha256:7e0dc9031baa46ad0dd5a269cb7a92a73284d1309228be1d5935dac8fb3cae24", - "sha256:87a3d6b53c39cd173990de2f5f4b83431d534a74f0e2f88bd16eabb5667e65c6", - "sha256:89a01238fcb9a8af118eaad3ffcc5dedaacbd429dc6fdc43fe430d3a941ff965", - "sha256:9585b646ffb048c0250acc7dad92536591ffe35dba624bb8fd9b471e25212a35", - "sha256:964971b52daab357d2c0875825e36584d58f536e920f2968df8d581054eada4b", - "sha256:967c0b71156f793e6662dd839da54f884631755275ed71f1539c95bbada9aaab", - "sha256:9ca922f305d67605668e93991aaf2c12239c78207bca3b891cd51a4515c72e22", - "sha256:a86cb7063e2c9fb8e774f77fbf8475516d270a3e989da55fa05d08089d77f8c4", - "sha256:aeb397de65a0a62f14c257f36a726945a7f7bb60253462e8602d9b97b5cbe204", - "sha256:b41f5d65b54cdf4934ecede2f41b9c60c9f785620416e8e6c48349ab18643855", - "sha256:bd45a5b6c68357578263d74daab6ff9439517f87da63442d244f9f23df56138d", - "sha256:c14eba45983d2f48f7546bb32b47937ee2cafae353646295f0e99f35b14286ab", - "sha256:c1bda93cbbe4aa2aa0aa8655c5aeda505cd219ff3e8da91d1d329e143e4aff69", - "sha256:c4722f3bc3c1c2fcc3702dbe0016ba31148dd6efcd2a2fd33c1b4897c6a19693", - "sha256:c80c38bd2ea35b97cbf7c21aeb129dcbebbf344ee01a7141016ab7b851464f8e", - "sha256:cabafc7837b6cec61c0e1e5c6d14ef250b675fa9c3060ed8a7e38653bd732ff8", - "sha256:cc1d21576f958c42d9aec68eba5c1a7d715e5fc07825a629015fe8e3b0657fb0", - "sha256:d0f7fb0c7527c41fa6fcae2be537ac137f636a41b4c5a4c58914541e2f436b45", - "sha256:d4041ad05b35f1f4da481f6b811b4af2f29e83af253bf37c3c4582b2c68934ab", - "sha256:d5578e6863eeb998980c212a39106ea139bdc0b3f73291b96e27c929c90cd8e1", - "sha256:e3b5036aa326dc2df50cba3c958e29b291a80f604b1afa4c8ce73e78e1c9f01d", - "sha256:e599a51acf3cc4d31d1a0cf248d8f8d863b6386d2b6782c5074427ebb7803bda", - "sha256:f3420d00d2cb42432c1d0e44540ae83185ccbbc67a6054dcc8ab5387add6620b", - "sha256:f48ed89dd11c3c586f45e9eec1e437b355b3b6f6884ea4a4c3111a3358fd0c18", - "sha256:f508ba8f89e0a5ecdfd3761f82dda2a3d7b678a626967608f4273e0dba8f07ac", - "sha256:fd54601ef9cc455a0c61e5245f690c8a3ad67ddb03d3b91c361d076def0b4c60" + "sha256:00d76fe5d7cdb5d84d625ce002ce29fefba0bfd98e212ae66793fed30af73931", + "sha256:07cc423892f2ceda9ae1daa28c0355757f362ecc7505b1ab1a3d5d8dc1c44ac6", + "sha256:0bb7cedcddffca98c40bb0becd3423e293d1fef442b869da40843d751785beb3", + "sha256:1ca7903d5e7db791a355b579c690684fac6304478b68efdc7f2ebdcfe770d8d7", + "sha256:1d9b3fd5eca3c0b137a5e0e468e24ca544ed8ca4783e0e55341b7ed2807518ee", + "sha256:2587e108463cc2e5b45a896b2e7cc8659a517038026922a758bde009271aed11", + "sha256:29e51f848f843bbd75d74ae64ab1ab06302cb1dccd4549d1f5afe6b4a946edb2", + "sha256:2a479aa1ab199178ff1956b09ca8a0693e70f9c762875d69292d37049ffd0d8f", + "sha256:37e89d965b52e8b20571b5d44f26e2124b26ab63758bf1b7598a0e38fb2c4005", + "sha256:38732884eabc64982a09a846bacf085596ff2371e4e41d20c0734f7e50525d01", + "sha256:396f05c552f7fa30a129497c41bef5b4d1423f9af8fe4df0c3dcd38f3e3b9a14", + "sha256:4a1d4856861ba9e73bac05030cec5852eabfa9ef4af8e56c19d92de80d46fc34", + "sha256:56a0e90a959e18ac5f18c80d0cad9e90cb09322764f536e8a637426afb1cae2f", + "sha256:57ef6f2cb8b09a042d0dbeaa46a30f2df5dd1e1eb889ba258b0d5d7d6011b81c", + "sha256:5f801d85ba4753d4ed97181d003e5d3fa330ac7c4587d131f61d7f968f416862", + "sha256:6db686a1d9f183c639f7e06a2656af25d4ed438eda581de135d15569f16ace33", + "sha256:6db97656fd3fe3f7e5b077f12fa6adb5feb6e0b567a3e99f47ecf5f7ea0a09e3", + "sha256:6f5e75de91c754365c098ac08c13fdb267577ce954fa239dd49228b573ca88d7", + "sha256:7a6209e689d0ff206c40032b6418e3cfcfc5af044b3f66e381d7f1ae301544b4", + "sha256:7ae5d44517fe81079ce75cf10f96978284a6db2642c5932a69c82dbae09f009a", + "sha256:83fa6df0e035689df89ff77a46bf8738696785d3156c2c61494acdcddc75c69d", + "sha256:8f358f5cfce04417b6ff738748ca4806fe3d3ae8040fb4e6a0c9a6973ccf9b6e", + "sha256:9036ebfd934813990c5b9f71f297e77ed4963720db7d7ceec5a3fdb7cd2ef6ce", + "sha256:95bae3d38f8808d79072da25d5e5a6095f36fe1f9d6c614dd72c59ca8397c7c0", + "sha256:9aaaaa846b10dfbe1bda71079d0e31a7e2cebedda9409fa7dba3dfed1ae803e8", + "sha256:9b8d0e8578e7f853f45f4512b5c920f6a546cd4bed44137460b2a56534644205", + "sha256:9bafaa05b19dc07fa191c1966c5e852af516840b0d7b46b7c3303faf1a349bc9", + "sha256:9f29c7f0f4b42337ec5a779e166946a9f86d7d56d827e771b69ecbdf426124ac", + "sha256:9f992e0f916201731993eab8502912878f02287d9f765ef843677ff118d0e0b1", + "sha256:a04191a7c8d77e63f6fc1e8336d6c6e93176c0c010833e74410e647f0284f5a1", + "sha256:a0f611b431b84f55779cbb7157257d87b4a2876b067c77c4f36b15e44ced65e2", + "sha256:a3c2753bf4f48b7a6024e5e8a394af49b1b12c817d75d06942cae03d14ff87b3", + "sha256:a5cd7d30e47f87b21362beeb3e86f1b5886e7d9b0294b230dde3d3f4a1591375", + "sha256:acc58b7c2e40235712d857fdfc8f2bda9608f4a850d8d9ac0dd1fc80939ca6ac", + "sha256:adbd67dac4ebf54587198b63cd30c29fd7eafa8c0cab58893d9419414f8efe4b", + "sha256:b35c35e3923ade1e7ac44e150dec29f5863513246c8bf85e2d7d313e3832bcfb", + "sha256:c6910eb4ea90c0889f363965cd3c8c45a620ad27b526a7899f0054f6c1b9219e", + "sha256:cc889fda484d54d0b31feec409406267616536d048a450fc46943e152700bb79", + "sha256:ccfd336f96d4c9bbab0309f2a565bf15c468c2d8b2d277a32f89c5940f71fcf9", + "sha256:d8e7e8a150e7b548e7ecd6ebb9211c37265991bf2504297d9454e01b58530fc6", + "sha256:db09e424d7bb89b6215a184ca93b4f29d7f00ea261b787918a1af74143b98c06", + "sha256:e17e7e27af178d31b436dda6a596703b02a89ba74a15e2980c35ecd9909eea3a", + "sha256:e69290b921b7833c04206f233d6814c60bee1d135b09f5ae5d39229de9b46cd4", + "sha256:e8398593ccc4440ce6dffcc4f47d9b2d72b9fe7112ac12ea4a44e7d4de364db1", + "sha256:e9d036e343a604db3f5a6c33354018a84a1d3f6dcae3673358b404286204798c", + "sha256:ea490564435b5b204d8154f0e18387b499ea3cedc1e6af3b3a2ab18291d85aa7", + "sha256:f073321a79c81e1a009218a21089f61d87ee5fa3c9563f6be94f8b41ff181812", + "sha256:f0cc0b486a56dff72dddae6b6bfa7ff201b0eeac29d4bc6f0e9725dc3c360d71", + "sha256:fcf84fe93397a0f67733aa2a38ed4eab9fc6348189fc950e656e1ea198f45668" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==2.0.23" + "version": "==2.0.24" }, "stack-data": { "hashes": [ @@ -4606,39 +4721,39 @@ }, "statsmodels": { "hashes": [ - "sha256:0eea4a0b761aebf0c355b726ac5616b9a8b618bd6e81a96b9f998a61f4fd7484", - "sha256:0ef7fa4813c7a73b0d8a0c830250f021c102c71c95e9fe0d6877bcfb56d38b8c", - "sha256:16bfe0c96a53b20fa19067e3b6bd2f1d39e30d4891ea0d7bc20734a0ae95942d", - "sha256:1c7724ad573af26139a98393ae64bc318d1b19762b13442d96c7a3e793f495c3", - "sha256:229b2f676b4a45cb62d132a105c9c06ca8a09ffba060abe34935391eb5d9ba87", - "sha256:3757542c95247e4ab025291a740efa5da91dc11a05990c033d40fce31c450dc9", - "sha256:3b0a135f3bfdeec987e36e3b3b4c53e0bb87a8d91464d2fcc4d169d176f46fdb", - "sha256:4c815ce7a699047727c65a7c179bff4031cff9ae90c78ca730cfd5200eb025dd", - "sha256:575f61337c8e406ae5fa074d34bc6eb77b5a57c544b2d4ee9bc3da6a0a084cf1", - "sha256:582f9e41092e342aaa04920d17cc3f97240e3ee198672f194719b5a3d08657d6", - "sha256:5a6a0a1a06ff79be8aa89c8494b33903442859add133f0dda1daf37c3c71682e", - "sha256:6875c7d689e966d948f15eb816ab5616f4928706b180cf470fd5907ab6f647a4", - "sha256:68b1c768dd94cc5ba8398121a632b673c625491aa7ed627b82cb4c880a25563f", - "sha256:6f7d762df4e04d1dde8127d07e91aff230eae643aa7078543e60e83e7d5b40db", - "sha256:71054f9dbcead56def14e3c9db6f66f943110fdfb19713caf0eb0f08c1ec03fd", - "sha256:76e290f4718177bffa8823a780f3b882d56dd64ad1c18cfb4bc8b5558f3f5757", - "sha256:77b3cd3a5268ef966a0a08582c591bd29c09c88b4566c892a7c087935234f285", - "sha256:7ebe885ccaa64b4bc5ad49ac781c246e7a594b491f08ab4cfd5aa456c363a6f6", - "sha256:8be53cdeb82f49c4cb0fda6d7eeeb2d67dbd50179b3e1033510e061863720d93", - "sha256:8d1e3e10dfbfcd58119ba5a4d3c7d519182b970a2aebaf0b6f539f55ae16058d", - "sha256:9c64ebe9cf376cba0c31aed138e15ed179a1d128612dd241cdf299d159e5e882", - "sha256:a6ad7b8aadccd4e4dd7f315a07bef1bca41d194eeaf4ec600d20dea02d242fce", - "sha256:afe80544ef46730ea1b11cc655da27038bbaa7159dc5af4bc35bbc32982262f2", - "sha256:b587ee5d23369a0e881da6e37f78371dce4238cf7638a455db4b633a1a1c62d6", - "sha256:ce28eb1c397dba437ec39b9ab18f2101806f388c7a0cf9cdfd8f09294ad1c799", - "sha256:d7fda067837df94e0a614d93d3a38fb6868958d37f7f50afe2a534524f2660cb", - "sha256:de489e3ed315bdba55c9d1554a2e89faa65d212e365ab81bc323fa52681fc60e", - "sha256:fb471f757fc45102a87e5d86e87dc2c8c78b34ad4f203679a46520f1d863b9da", - "sha256:fc2c7931008a911e3060c77ea8933f63f7367c0f3af04f82db3a04808ad2cd2c" + "sha256:04293890f153ffe577e60a227bd43babd5f6c1fc50ea56a3ab1862ae85247a95", + "sha256:0a8aae75a2e08ebd990e5fa394f8e32738b55785cb70798449a3f4207085e667", + "sha256:0d5373d176239993c095b00d06036690a50309a4e00c2da553b65b840f956ae6", + "sha256:2260efdc1ef89f39c670a0bd8151b1d0843567781bcafec6cda0534eb47a94f6", + "sha256:2de2b97413913d52ad6342dece2d653e77f78620013b7705fad291d4e4266ccb", + "sha256:3e70a2e93d54d40b2cb6426072acbc04f35501b1ea2569f6786964adde6ca572", + "sha256:43af9c0b07c9d72f275cf14ea54a481a3f20911f0b443181be4769def258fdeb", + "sha256:44ca8cb88fa3d3a4ffaff1fb8eb0e98bbf83fc936fcd9b9eedee258ecc76696a", + "sha256:4fe0a60695952b82139ae8750952786a700292f9e0551d572d7685070944487b", + "sha256:5385e22e72159a09c099c4fb975f350a9f3afeb57c1efce273b89dcf1fe44c0f", + "sha256:709bfcef2dbe66f705b17e56d1021abad02243ee1a5d1efdb90f9bad8b06a329", + "sha256:7562cb18a90a114f39fab6f1c25b9c7b39d9cd5f433d0044b430ca9d44a8b52c", + "sha256:a16975ab6ad505d837ba9aee11f92a8c5b49c4fa1ff45b60fe23780b19e5705e", + "sha256:a532dfe899f8b6632cd8caa0b089b403415618f51e840d1817a1e4b97e200c73", + "sha256:ab3a73d16c0569adbba181ebb967e5baaa74935f6d2efe86ac6fc5857449b07d", + "sha256:b0f727fe697f6406d5f677b67211abe5a55101896abdfacdb3f38410405f6ad8", + "sha256:b3abaca4b963259a2bf349c7609cfbb0ce64ad5fb3d92d6f08e21453e4890248", + "sha256:b6838ac6bdb286daabb5e91af90fd4258f09d0cec9aace78cc441cb2b17df428", + "sha256:b69a63ad6c979a6e4cde11870ffa727c76a318c225a7e509f031fbbdfb4e416a", + "sha256:bc0351d279c4e080f0ce638a3d886d312aa29eade96042e3ba0a73771b1abdfb", + "sha256:bc43765710099ca6a942b5ffa1bac7668965052542ba793dd072d26c83453572", + "sha256:bf293ada63b2859d95210165ad1dfcd97bd7b994a5266d6fbeb23659d8f0bf68", + "sha256:c008e16096f24f0514e53907890ccac6589a16ad6c81c218f2ee6752fdada555", + "sha256:c0564d92cb05b219b4538ed09e77d96658a924a691255e1f7dd23ee338df441b", + "sha256:c3420f88289c593ba2bca33619023059c476674c160733bd7d858564787c83d3", + "sha256:e278fe74da5ed5e06c11a30851eda1af08ef5af6be8507c2c45d2e08f7550dde", + "sha256:eefa5bcff335440ee93e28745eab63559a20cd34eea0375c66d96b016de909b3", + "sha256:f32a7cd424cf33304a54daee39d32cccf1d0265e652c920adeaeedff6d576457", + "sha256:f8c30181c084173d662aaf0531867667be2ff1bee103b84feb64f149f792dbd2" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==0.14.0" + "version": "==0.14.1" }, "stevedore": { "hashes": [ @@ -4867,11 +4982,11 @@ }, "uvicorn": { "hashes": [ - "sha256:09c8e5a79dc466bdf28dead50093957db184de356fcdc48697bad3bde4c2588e", - "sha256:7c84fea70c619d4a710153482c0d230929af7bcf76c7bfa6de151f0a3a80121e" + "sha256:6dddbad1d7ee0f5140aba5ec138ddc9612c5109399903828b4874c9937f009c2", + "sha256:ce107f5d9bd02b4636001a77a4e74aab5e1e2b146868ebbad565237145af444c" ], "markers": "python_version >= '3.8'", - "version": "==0.24.0.post1" + "version": "==0.25.0" }, "validators": { "hashes": [ @@ -5157,6 +5272,14 @@ } }, "develop": { + "colorama": { + "hashes": [ + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" + ], + "markers": "os_name == 'nt'", + "version": "==0.4.6" + }, "iniconfig": { "hashes": [ "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", @@ -5191,26 +5314,26 @@ }, "ruff": { "hashes": [ - "sha256:05ffe9dbd278965271252704eddb97b4384bf58b971054d517decfbf8c523f05", - "sha256:5daaeaf00ae3c1efec9742ff294b06c3a2a9db8d3db51ee4851c12ad385cda30", - "sha256:7d076717c67b34c162da7c1a5bda16ffc205e0e0072c03745275e7eab888719f", - "sha256:7de792582f6e490ae6aef36a58d85df9f7a0cfd1b0d4fe6b4fb51803a3ac96fa", - "sha256:a05b0ddd7ea25495e4115a43125e8a7ebed0aa043c3d432de7e7d6e8e8cd6448", - "sha256:aa8ee4f8440023b0a6c3707f76cadce8657553655dcbb5fc9b2f9bb9bee389f6", - "sha256:b6a21ab023124eafb7cef6d038f835cb1155cd5ea798edd8d9eb2f8b84be07d9", - "sha256:bd8ee69b02e7bdefe1e5da2d5b6eaaddcf4f90859f00281b2333c0e3a0cc9cd6", - "sha256:c8e3255afd186c142eef4ec400d7826134f028a85da2146102a1172ecc7c3696", - "sha256:ce697c463458555027dfb194cb96d26608abab920fa85213deb5edf26e026664", - "sha256:db6cedd9ffed55548ab313ad718bc34582d394e27a7875b4b952c2d29c001b26", - "sha256:e49fbdfe257fa41e5c9e13c79b9e79a23a79bd0e40b9314bc53840f520c2c0b3", - "sha256:e6f08ca730f4dc1b76b473bdf30b1b37d42da379202a059eae54ec7fc1fbcfed", - "sha256:f35960b02df6b827c1b903091bb14f4b003f6cf102705efc4ce78132a0aa5af3", - "sha256:f41f692f1691ad87f51708b823af4bb2c5c87c9248ddd3191c8f088e66ce590a", - "sha256:f7ee467677467526cfe135eab86a40a0e8db43117936ac4f9b469ce9cdb3fb62", - "sha256:ff78a7583020da124dd0deb835ece1d87bb91762d40c514ee9b67a087940528b" + "sha256:0e17f53bcbb4fff8292dfd84cf72d767b5e146f009cccd40c2fad27641f8a7a9", + "sha256:104aa9b5e12cb755d9dce698ab1b97726b83012487af415a4512fedd38b1459e", + "sha256:1e63bf5a4a91971082a4768a0aba9383c12392d0d6f1e2be2248c1f9054a20da", + "sha256:28d920e319783d5303333630dae46ecc80b7ba294aeffedf946a02ac0b7cc3db", + "sha256:2aec598fb65084e41a9c5d4b95726173768a62055aafb07b4eff976bac72a592", + "sha256:331aae2cd4a0554667ac683243b151c74bd60e78fb08c3c2a4ac05ee1e606a39", + "sha256:479ca4250cab30f9218b2e563adc362bd6ae6343df7c7b5a7865300a5156d5a6", + "sha256:4d0738917c203246f3e275b37006faa3aa96c828b284ebfe3e99a8cb413c8c4b", + "sha256:69dac82d63a50df2ab0906d97a01549f814b16bc806deeac4f064ff95c47ddf5", + "sha256:744dfe4b35470fa3820d5fe45758aace6269c578f7ddc43d447868cfe5078bcb", + "sha256:8151425a60878e66f23ad47da39265fc2fad42aed06fb0a01130e967a7a064f4", + "sha256:837c739729394df98f342319f5136f33c65286b28b6b70a87c28f59354ec939b", + "sha256:aa8344310f1ae79af9ccd6e4b32749e93cddc078f9b5ccd0e45bd76a6d2e8bb6", + "sha256:b041dee2734719ddbb4518f762c982f2e912e7f28b8ee4fe1dee0b15d1b6e800", + "sha256:c497d769164df522fdaf54c6eba93f397342fe4ca2123a2e014a5b8fc7df81c7", + "sha256:e6837202c2859b9f22e43cb01992373c2dbfeae5c0c91ad691a4a2e725392464", + "sha256:e6a212f436122ac73df851f0cf006e0c6612fe6f9c864ed17ebefce0eff6a5fd" ], "markers": "python_version >= '3.7'", - "version": "==0.1.8" + "version": "==0.1.9" } } } From 762d5d96cef3bb2f9aaeec0f613ace162a3653d2 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Thu, 28 Dec 2023 15:57:04 -0800 Subject: [PATCH 79/85] feat: update EIA-930 manual adjustments --- src/oge/eia930.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/oge/eia930.py b/src/oge/eia930.py index 99509bf5..e27505fa 100644 --- a/src/oge/eia930.py +++ b/src/oge/eia930.py @@ -395,7 +395,7 @@ def manual_930_adjust(raw: pd.DataFrame): - Interchange - PJM: + 4 hours - TEPC: + 7 hours - - CFE: -11 hours + - IID: + 4 hours - Interchange sign - PJM-{CPLE, CPLW, DUK, LGEE, MISO, NYIS, TVA} before Oct 31, 2019, 4:00 UTC @@ -429,7 +429,6 @@ def manual_930_adjust(raw: pd.DataFrame): # we need to shift all data by +1 hour ba = "PJM" cols = get_columns(ba, raw.columns) - cols = get_columns(ba, raw.columns) new = raw[cols].shift(1, freq="H") raw = raw.drop(columns=cols) raw = pd.concat([raw, new], axis="columns") @@ -496,12 +495,24 @@ def manual_930_adjust(raw: pd.DataFrame): :"2020-06-01 07:00:00+00", all_cols ].sum(axis=1) - # Interchange TEPC is uniformly lagged + # Interchange TEPC is uniformly lagged until 10-25-2021 cols = get_int_columns("TEPC", raw.columns) - new = raw[cols].shift(-7, freq="H") + new = raw[cols].copy() + new.loc[raw.index < "2021-10-25 00:00:00+00", cols] = new.loc[ + raw.index < "2021-10-25 00:00:00+00", cols + ].shift(-7, freq="H") raw = raw.drop(columns=cols) raw = pd.concat([raw, new], axis="columns") + # Interchange IID-CISO is lagged by 4 hours in 2021 + col = get_int_columns("IID", raw.columns, ["CISO"]) + new = raw[col].copy() + new.loc["2021-01-01 08:00:00+00:00":"2022-01-01 07:00:00+00:00", col] = new.loc[ + "2021-01-01 08:00:00+00:00":"2022-01-01 07:00:00+00:00", col + ].shift(4, freq="H") + raw = raw.drop(columns=col) + raw = pd.concat([raw, new], axis="columns") + # Interchange PJM is lagged differently across DST boundary is_dst = raw.index.tz_convert("US/Eastern").to_series().apply( lambda s: s.utcoffset() From 1dea23b00603ed6871cf78e9ef388e0593dd00d8 Mon Sep 17 00:00:00 2001 From: Ben RdO Date: Fri, 29 Dec 2023 00:10:40 -0800 Subject: [PATCH 80/85] refactor: update identify_eia930_time_lags notebook --- .../identify_eia930_time_lags.ipynb | 123 ++++++++---------- 1 file changed, 53 insertions(+), 70 deletions(-) diff --git a/notebooks/manual_data/identify_eia930_time_lags.ipynb b/notebooks/manual_data/identify_eia930_time_lags.ipynb index 37c43fdd..8a619e82 100644 --- a/notebooks/manual_data/identify_eia930_time_lags.ipynb +++ b/notebooks/manual_data/identify_eia930_time_lags.ipynb @@ -9,7 +9,7 @@ "### Generation: \n", "\n", "Check lagged correlation (-11 to +12 hours) between 930 fossil generation and CEMS fossil generation for each BA over different time bounds: \n", - "* 2019, 2020, 2021\n", + "* 2021, 2022\n", "* Daylight savings vs. non- daylight savings\n", "\n", "Run for both raw, shifted, and shifted + basic and rolling filtered 930 data. When shifts are correct, the best correlation in the shifted data should be at lag=0. The best correlation in the non-shifted data can indicate what shift might be appropriate. Manual inspection is required to actually decide whether and how much to lag by. \n", @@ -33,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -84,7 +84,7 @@ "lraw = []\n", "lshift = []\n", "\n", - "for year in [2019, 2020, 2021]:\n", + "for year in [2021, 2022]:\n", " print(year)\n", "\n", " r = eia930.convert_balance_file_to_gridemissions_format(year)\n", @@ -124,11 +124,10 @@ "outputs": [], "source": [ "# Load data after shifting and rolling filter\n", - "\n", "all_rolled = []\n", - "for y in [2019, 2020, 2021]:\n", + "for y in [2021, 2022]:\n", " rolled_930 = pd.read_csv(\n", - " f\"../../data/outputs/{y}/eia930/eia930_rolling.csv\",\n", + " f\"{data_folder()}/outputs/{y}/eia930/eia930_rolling.csv\",\n", " index_col=0,\n", " parse_dates=True,\n", " )\n", @@ -143,8 +142,7 @@ "metadata": {}, "outputs": [], "source": [ - "##### Remove renewables before summing 930\n", - "\n", + "# Remove renewables before summing 930\n", "rolled_930 = (\n", " rolled_930[rolled_930.fuel.isin([\"COL\", \"NG\", \"OIL\"])]\n", " .groupby([\"datetime_utc\", \"BA\"])\n", @@ -162,22 +160,25 @@ "# Load files\n", "# Aggregate by BA during loading to cut down on space\n", "cems = pd.DataFrame()\n", - "for y in [2019, 2020, 2021]:\n", + "for y in [2021, 2022]:\n", " print(f\"loading {y}\")\n", " file = f\"{data_folder()}/outputs/{y}/cems_cleaned_{y}.csv\"\n", - " plant_meta = pd.read_csv(f\"../../data/outputs/{y}/plant_static_attributes_{y}.csv\")\n", + " plant_meta = pd.read_csv(\n", + " f\"{data_folder()}/outputs/{y}/plant_static_attributes_{y}.csv\"\n", + " )\n", " c = pd.read_csv(file, index_col=0, parse_dates=[\"datetime_utc\"])\n", - " c = c.rename(columns={\"datetime_utc\": \"datetime_utc\"})\n", " c = c.merge(\n", " plant_meta[[\"plant_id_eia\", \"plant_primary_fuel\", \"ba_code\"]],\n", " how=\"left\",\n", " left_index=True,\n", " right_on=\"plant_id_eia\",\n", " )\n", - " # exclude solar power for CEMS, since we're just going to look at COL + OIL + NG in the 930 data\n", + " # Exclude solar power for CEMS, since we're just going to look at COL + OIL + NG in the 930 data\n", " c = c[c[\"plant_primary_fuel\"] != \"SUN\"]\n", + " c = c[[\"datetime_utc\", \"ba_code\", \"gross_generation_mwh\"]]\n", + "\n", " print(\"Aggregating\")\n", - " if y == 2021:\n", + " if y in [2021, 2022]:\n", " c = c.rename(columns={\"gross_generation_mwh\": \"net_generation_mwh\"})\n", " cems_aggregated = (\n", " c.groupby([\"datetime_utc\", \"ba_code\"]).sum()[\"net_generation_mwh\"].reset_index()\n", @@ -193,8 +194,10 @@ "metadata": {}, "outputs": [], "source": [ + "year = 2022\n", "plant_attributes = pd.read_csv(\n", - " outputs_folder(f\"{year}/plant_static_attributes_{year}.csv\"), dtype=get_dtypes()\n", + " f\"{data_folder()}/outputs/{year}/plant_static_attributes_{year}.csv\",\n", + " dtype=get_dtypes(),\n", ")" ] }, @@ -245,7 +248,7 @@ "\n", " bas = set(cems.columns).intersection(set(df_eia930.columns))\n", "\n", - " correlations = pd.DataFrame(index=bas, columns=range(-12, 12), dtype=float)\n", + " correlations = pd.DataFrame(index=list(bas), columns=range(-12, 12), dtype=float)\n", "\n", " for ba in correlations.index:\n", " for lag in correlations.columns:\n", @@ -279,23 +282,18 @@ "outputs": [], "source": [ "# Calculate best correlations for shifted (no EBA cleaning) data\n", - "\n", "cems_930_cors = pd.concat(\n", " [\n", " find_best_cor(cems, shifted).best.rename(\"all_years\"),\n", " find_best_cor(\n", - " cems[cems.datetime_utc.dt.year == 2019],\n", - " shifted[shifted.datetime_utc.dt.year == 2019],\n", - " ).best.rename(\"2019\"),\n", - " find_best_cor(\n", - " cems[cems.datetime_utc.dt.year == 2020],\n", - " shifted[shifted.datetime_utc.dt.year == 2020],\n", - " ).best.rename(\"2020\"),\n", - " find_best_cor(\n", " cems[cems.datetime_utc.dt.year == 2021],\n", " shifted[shifted.datetime_utc.dt.year == 2021],\n", " ).best.rename(\"2021\"),\n", " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2022],\n", + " shifted[shifted.datetime_utc.dt.year == 2022],\n", + " ).best.rename(\"2022\"),\n", + " find_best_cor(\n", " cems[(cems.datetime_utc.dt.month >= 4) & (cems.datetime_utc.dt.month <= 9)],\n", " shifted[\n", " (shifted.datetime_utc.dt.month >= 4)\n", @@ -315,8 +313,7 @@ " axis=\"columns\",\n", ")\n", "\n", - "cems_930_cors.to_csv(\"../../data/outputs/2021/cems_SHIFTEDeia930_cor_lags.csv\")\n", - "# cems_930_cors" + "cems_930_cors.to_csv(f\"{data_folder()}/outputs/2022/cems_SHIFTEDeia930_cor_lags.csv\")" ] }, { @@ -326,23 +323,18 @@ "outputs": [], "source": [ "# Calculate best correlations for raw data\n", - "\n", "cems_930_cors = pd.concat(\n", " [\n", " find_best_cor(cems, raw).best.rename(\"all_years\"),\n", " find_best_cor(\n", - " cems[cems.datetime_utc.dt.year == 2019],\n", - " raw[raw.datetime_utc.dt.year == 2019],\n", - " ).best.rename(\"2019\"),\n", - " find_best_cor(\n", - " cems[cems.datetime_utc.dt.year == 2020],\n", - " raw[raw.datetime_utc.dt.year == 2020],\n", - " ).best.rename(\"2020\"),\n", - " find_best_cor(\n", " cems[cems.datetime_utc.dt.year == 2021],\n", " raw[raw.datetime_utc.dt.year == 2021],\n", " ).best.rename(\"2021\"),\n", " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2022],\n", + " raw[raw.datetime_utc.dt.year == 2022],\n", + " ).best.rename(\"2022\"),\n", + " find_best_cor(\n", " cems[(cems.datetime_utc.dt.month >= 4) & (cems.datetime_utc.dt.month <= 9)],\n", " raw[(raw.datetime_utc.dt.month >= 4) & (raw.datetime_utc.dt.month <= 9)],\n", " ).best.rename(\"daylight time\"),\n", @@ -356,8 +348,7 @@ " axis=\"columns\",\n", ")\n", "\n", - "cems_930_cors.to_csv(\"../../data/outputs/2021/cems_RAWeia930_cor_lags.csv\")\n", - "cems_930_cors" + "cems_930_cors.to_csv(f\"{data_folder()}/outputs/2022/cems_RAWeia930_cor_lags.csv\")" ] }, { @@ -372,18 +363,14 @@ " [\n", " find_best_cor(cems, rolled_930).best.rename(\"all_years\"),\n", " find_best_cor(\n", - " cems[cems.datetime_utc.dt.year == 2019],\n", - " rolled_930[rolled_930.datetime_utc.dt.year == 2019],\n", - " ).best.rename(\"2019\"),\n", - " find_best_cor(\n", - " cems[cems.datetime_utc.dt.year == 2020],\n", - " rolled_930[rolled_930.datetime_utc.dt.year == 2020],\n", - " ).best.rename(\"2020\"),\n", - " find_best_cor(\n", " cems[cems.datetime_utc.dt.year == 2021],\n", " rolled_930[rolled_930.datetime_utc.dt.year == 2021],\n", " ).best.rename(\"2021\"),\n", " find_best_cor(\n", + " cems[cems.datetime_utc.dt.year == 2022],\n", + " rolled_930[rolled_930.datetime_utc.dt.year == 2022],\n", + " ).best.rename(\"2022\"),\n", + " find_best_cor(\n", " cems[(cems.datetime_utc.dt.month >= 4) & (cems.datetime_utc.dt.month <= 9)],\n", " rolled_930[\n", " (rolled_930.datetime_utc.dt.month >= 4)\n", @@ -403,8 +390,7 @@ " axis=\"columns\",\n", ")\n", "\n", - "cems_930_cors.to_csv(\"../../data/outputs/2021/cems_RAWeia930_cor_lags.csv\")\n", - "cems_930_cors" + "cems_930_cors.to_csv(f\"{data_folder()}/outputs/2022/cems_RAWeia930_cor_lags.csv\")" ] }, { @@ -414,8 +400,7 @@ "outputs": [], "source": [ "# Visualize a BA for manual inspection\n", - "\n", - "ba = \"SC\"\n", + "ba = \"TEPC\"\n", "\n", "to_plot_930 = shifted[shifted.BA == ba].groupby(\"datetime_utc\").sum()\n", "\n", @@ -453,11 +438,10 @@ "metadata": {}, "outputs": [], "source": [ - "# interchange = pd.read_csv(\"../data/eia930/chalendar/EBA_rolling.csv\",index_col=0, parse_dates=True)\n", "interchanges = []\n", - "for year in [2019, 2020, 2021]:\n", + "for year in [2021, 2022]:\n", " interchange = pd.read_csv(\n", - " f\"../../data/outputs/{year}/eia930/eia930_raw.csv\",\n", + " f\"{data_folder()}/outputs/{year}/eia930/eia930_raw.csv\",\n", " index_col=0,\n", " parse_dates=True,\n", " )\n", @@ -558,13 +542,10 @@ "source": [ "int_cors = interchange_cor(interchange, interchange_cors={}, name=\"all_years\")\n", "int_cors = interchange_cor(\n", - " interchange[\"2019-01-01T00:00\":\"2019-12-30T00:00\"], int_cors, name=\"2019\"\n", - ")\n", - "int_cors = interchange_cor(\n", - " interchange[\"2020-01-01T00:00\":\"2020-12-30T00:00\"], int_cors, name=\"2020\"\n", + " interchange[\"2021-01-01T00:00\":\"2021-12-30T00:00\"], int_cors, name=\"2021\"\n", ")\n", "int_cors = interchange_cor(\n", - " interchange[\"2021-01-01T00:00\":\"2021-12-30T00:00\"], int_cors, name=\"2021\"\n", + " interchange[\"2022-01-01T00:00\":\"2022-12-30T00:00\"], int_cors, name=\"2022\"\n", ")\n", "int_cors = interchange_cor(\n", " interchange[(interchange.index.month >= 4) & (interchange.index.month <= 9)],\n", @@ -585,7 +566,6 @@ "outputs": [], "source": [ "# Inspect interchange correlations\n", - "\n", "int_cors[\"PJM\"]" ] }, @@ -596,8 +576,7 @@ "outputs": [], "source": [ "# Output to md file because that's an easy way to manually scan through BAs and look for anomalies\n", - "\n", - "file = \"../../data/outputs/2021/interchange_corr_summary_adjusted.md\"\n", + "file = f\"{data_folder()}/outputs/2022/interchange_corr_summary_adjusted.md\"\n", "hs = open(file, \"w\")\n", "hs.write(\"\\n\\n\")\n", "hs.close()\n", @@ -624,8 +603,8 @@ "metadata": {}, "outputs": [], "source": [ - "ba1 = \"AEC\"\n", - "ba2 = \"MISO\"\n", + "ba1 = \"IID\"\n", + "ba2 = \"CISO\"\n", "\n", "fig = px.line(interchange[f\"EBA.{ba1}-{ba2}.ID.H\"])\n", "fig.add_trace(\n", @@ -725,7 +704,7 @@ "metadata": {}, "outputs": [], "source": [ - "ba = \"CFE\"\n", + "ba = \"PJM\"\n", "\n", "fig = go.Figure()\n", "fig.add_trace(\n", @@ -800,13 +779,10 @@ "source": [ "int_sign = interchange_sign(interchange, {}, name=\"all_years\")\n", "int_sign = interchange_sign(\n", - " interchange[\"2019-01-01T00:00\":\"2019-12-30T00:00\"], int_sign, name=\"2019\"\n", + " interchange[\"2021-01-01T00:00\":\"2021-12-30T00:00\"], int_sign, name=\"2021\"\n", ")\n", "int_sign = interchange_sign(\n", - " interchange[\"2020-01-01T00:00\":\"2020-12-30T00:00\"], int_sign, name=\"2020\"\n", - ")\n", - "int_sign = interchange_sign(\n", - " interchange[\"2020-01-01T00:00\":\"2020-12-30T00:00\"], int_sign, name=\"2021\"\n", + " interchange[\"2022-01-01T00:00\":\"2022-12-30T00:00\"], int_sign, name=\"2022\"\n", ")\n", "int_sign = interchange_sign(\n", " interchange[(interchange.index.month >= 4) & (interchange.index.month <= 9)],\n", @@ -826,7 +802,7 @@ "metadata": {}, "outputs": [], "source": [ - "file = f\"{outputs_folder('2021')}/interchange_cors_sign.md\"\n", + "file = f\"{outputs_folder('2022')}/interchange_cors_sign.md\"\n", "hs = open(file, \"w\")\n", "hs.write(\"\\n\\n\")\n", "hs.close()\n", @@ -839,6 +815,13 @@ "\n", " out.to_markdown(file, mode=\"a\")" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { From 42348406a06051c8f9f0d816aeb901560f55be09 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 29 Dec 2023 09:04:00 -0800 Subject: [PATCH 81/85] update development instructions --- README.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2df74465..77f44825 100644 --- a/README.md +++ b/README.md @@ -147,10 +147,25 @@ cd open-grid-emissions #### Setup the environment In the root of the directory, create and activate the environment with: ```bash -pipenv sync -pipenv shell +# set up virtual environment (use whichever version of python 3.11 you have installed) +pipenv --python 3.11.4 + +# if you have updated the pipfile and need to update pipfile.lock, run +Pipenv install +# Otherwise, if you just want to install packages from the pipfile.lock, run +Pipenv sync + +# activate virtual environment +Pipenv shell + +# install an editable version of the oge package +pip install build +python -m build +pip install –editable . ``` +If you ever need to remove and reinstall the environment, run `pipenv -rm` from the root directory then follow the directions above. + ### Running the complete data pipeline If you would like to run the full data pipeline to generate all intermediate outputs and results files, navigate to `open-grid-emissions/src`, and run the following (replacing 2021 with whichever year you want to run): ``` From 5c36b7dd60bc978a699c4f268cefc26a574a1ab1 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 29 Dec 2023 09:27:18 -0800 Subject: [PATCH 82/85] zip data --- notebooks/manual_data/zip_data.ipynb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/notebooks/manual_data/zip_data.ipynb b/notebooks/manual_data/zip_data.ipynb index 8e7413c9..b2e7dda4 100644 --- a/notebooks/manual_data/zip_data.ipynb +++ b/notebooks/manual_data/zip_data.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -30,7 +30,8 @@ "metadata": {}, "outputs": [], "source": [ - "years = [2019, 2020, 2021]\n", + "# zip all data for s3 and zenodo\n", + "years = [2019, 2020, 2021, 2022]\n", "\n", "output_data.prepare_files_for_upload(years)" ] @@ -41,7 +42,8 @@ "metadata": {}, "outputs": [], "source": [ - "for year in [2019, 2020, 2021]:\n", + "# option: just zip results for s3\n", + "for year in [2019, 2020, 2021, 2022]:\n", " output_data.zip_results_for_s3(year)" ] }, @@ -51,6 +53,7 @@ "metadata": {}, "outputs": [], "source": [ + "# option: just zip results for zenodo\n", "for year in [2019, 2020, 2021]:\n", " output_data.zip_data_for_zenodo(year)" ] @@ -72,7 +75,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.11.4" }, "orig_nbformat": 4, "vscode": { From 761fa53586b85715f1ecdab251bea1fa47b5f92d Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 29 Dec 2023 09:40:32 -0800 Subject: [PATCH 83/85] update dependencies --- Pipfile | 3 ++- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Pipfile b/Pipfile index 3ee8e796..de456b27 100644 --- a/Pipfile +++ b/Pipfile @@ -20,8 +20,9 @@ seaborn = "*" sqlalchemy = "*" statsmodels = "*" coloredlogs = "*" -"catalystcoop.pudl" = {git = "git+https://github.com/singularity-energy/pudl.git@oge_dev"} +"catalystcoop.pudl" = {git = "git+https://github.com/singularity-energy/pudl.git@oge_release"} gridemissions = {git = "git+https://github.com/singularity-energy/gridemissions"} +oge = {git = "git+https://github.com/singularity-energy/open-grid-emissions"} [dev-packages] ruff = "*" diff --git a/pyproject.toml b/pyproject.toml index aaa51169..91c0d6b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ dependencies = [ "sqlalchemy", "statsmodels", "coloredlogs", - "catalystcoop-pudl@git+https://github.com/singularity-energy/pudl.git@oge_dev", + "catalystcoop-pudl@git+https://github.com/singularity-energy/pudl.git@oge_release", "gridemissions@git+https://github.com/singularity-energy/gridemissions.git", ] From 0f1621e98cadeee0dc819f41475f7bfd9e6290dd Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 29 Dec 2023 09:42:32 -0800 Subject: [PATCH 84/85] remove oge dependency --- Pipfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Pipfile b/Pipfile index de456b27..0c4e88cb 100644 --- a/Pipfile +++ b/Pipfile @@ -22,7 +22,6 @@ statsmodels = "*" coloredlogs = "*" "catalystcoop.pudl" = {git = "git+https://github.com/singularity-energy/pudl.git@oge_release"} gridemissions = {git = "git+https://github.com/singularity-energy/gridemissions"} -oge = {git = "git+https://github.com/singularity-energy/open-grid-emissions"} [dev-packages] ruff = "*" From 1d0e7c72d3567a8755facac4e67c70c95db8f427 Mon Sep 17 00:00:00 2001 From: grgmiller Date: Fri, 29 Dec 2023 10:46:51 -0800 Subject: [PATCH 85/85] respond to Ben's comments --- README.md | 10 +++++----- notebooks/manual_data/zip_data.ipynb | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 77f44825..91800d39 100644 --- a/README.md +++ b/README.md @@ -151,20 +151,20 @@ In the root of the directory, create and activate the environment with: pipenv --python 3.11.4 # if you have updated the pipfile and need to update pipfile.lock, run -Pipenv install +pipenv install # Otherwise, if you just want to install packages from the pipfile.lock, run -Pipenv sync +pipenv sync # activate virtual environment -Pipenv shell +pipenv shell # install an editable version of the oge package pip install build python -m build -pip install –editable . +pip install –-editable . ``` -If you ever need to remove and reinstall the environment, run `pipenv -rm` from the root directory then follow the directions above. +If you ever need to remove and reinstall the environment, run `pipenv --rm` from the root directory then follow the directions above. ### Running the complete data pipeline If you would like to run the full data pipeline to generate all intermediate outputs and results files, navigate to `open-grid-emissions/src`, and run the following (replacing 2021 with whichever year you want to run): diff --git a/notebooks/manual_data/zip_data.ipynb b/notebooks/manual_data/zip_data.ipynb index b2e7dda4..d33b9fbd 100644 --- a/notebooks/manual_data/zip_data.ipynb +++ b/notebooks/manual_data/zip_data.ipynb @@ -54,7 +54,7 @@ "outputs": [], "source": [ "# option: just zip results for zenodo\n", - "for year in [2019, 2020, 2021]:\n", + "for year in [2019, 2020, 2021, 2022]:\n", " output_data.zip_data_for_zenodo(year)" ] }