def generate_upstream_ng(year):
    """
    Generate the annual gas extraction, processing and transportation
    emissions (in kg) for each plant in EIA923.

    Parameters
    ----------
    year: int
        Year of EIA-923 fuel data to use.

    Returns
    ----------
    dataframe
    """
    module_logger.info("Generating natural gas inventory")
    # Get the EIA generation data for the specified year, this dataset includes
    # the fuel consumption for generating electricity for each facility
    # and fuel type. Filter the data to only include NG facilities and on
    # positive fuel consumption. Group that data by Plant Id as it is possible
    # to have multiple rows for the same facility and fuel based on different
    # prime movers (e.g., gas turbine and combined cycle).
    eia_generation_data = eia923_download_extract(year)

    column_filt = ((eia_generation_data['Reported Fuel Type Code'] == 'NG') &
                   (eia_generation_data['Total Fuel Consumption MMBtu'] > 0))
    ng_generation_data = eia_generation_data[column_filt]

    ng_generation_data = ng_generation_data.groupby('Plant Id').agg({
        'Total Fuel Consumption MMBtu':
        'sum'
    }).reset_index()
    ng_generation_data['Plant Id'] = ng_generation_data['Plant Id'].astype(int)

    # Import the mapping file which has the source gas basin for each Plant Id.
    # Merge with ng_generation dataframe.

    ng_basin_mapping = pd.read_csv(data_dir + '/gas_supply_basin_mapping.csv')

    subset_cols = ['Plant Code', 'NG_LCI_Name']

    ng_basin_mapping = ng_basin_mapping[subset_cols]

    ng_generation_data_basin = pd.merge(left=ng_generation_data,
                                        right=ng_basin_mapping,
                                        left_on='Plant Id',
                                        right_on='Plant Code')

    ng_generation_data_basin = ng_generation_data_basin.drop(
        columns=['Plant Code'])

    # Read the NG LCI excel file
    ng_lci = pd.read_csv(data_dir + '/NG_LCI.csv',
                         index_col=[0, 1, 2, 3, 4, 5])
    # sheet_name = 'Basin_Mean_Data')
    ng_lci_columns = [
        "Compartment", "FlowName", "FlowUUID", "Unit", "FlowType", "input",
        "Basin", "FlowAmount"
    ]
    ng_lci_stack = pd.DataFrame(ng_lci.stack()).reset_index()
    ng_lci_stack.columns = ng_lci_columns

    # Merge basin data with LCI dataset
    ng_lci_basin = pd.merge(ng_lci_stack,
                            ng_generation_data_basin,
                            left_on='Basin',
                            right_on='NG_LCI_Name',
                            how='left')

    # Multiplying with the EIA 923 fuel consumption; conversion factor is
    # for MMBtu to MJ
    btu_to_MJ = pq.convert(10**6, 'Btu', 'MJ')
    ng_lci_basin["FlowAmount"] = (
        ng_lci_basin["FlowAmount"] *
        ng_lci_basin['Total Fuel Consumption MMBtu'] * btu_to_MJ)

    ng_lci_basin = ng_lci_basin.rename(
        columns={'Total Fuel Consumption MMBtu': 'quantity'})
    ng_lci_basin["quantity"] = ng_lci_basin["quantity"] * btu_to_MJ
    # Output is kg emission for the specified year by facility Id,
    # not normalized to electricity output

    ng_lci_basin['FuelCategory'] = 'GAS'
    ng_lci_basin.rename(columns={
        'Plant Id': 'plant_id',
        'NG_LCI_Name': 'stage_code',
        'Stage': 'stage'
    },
                        inplace=True)
    ng_lci_basin["Year"] = year
    ng_lci_basin["Source"] = "netl"
    ng_lci_basin["ElementaryFlowPrimeContext"] = "emission"
    ng_lci_basin.loc[ng_lci_basin["Compartment"].str.contains("resource/"),
                     "ElementaryFlowPrimeContext"] = "resource"
    ng_lci_basin.loc[ng_lci_basin["Compartment"].str.contains("Technosphere/"),
                     "ElementaryFlowPrimeContext"] = "technosphere"
    return ng_lci_basin
def generate_upstream_nuc(year):
    """
    Generate the annual uranium extraction, processing and transportation
    emissions (in kg) for each plant in EIA923.

    Parameters
    ----------
    year: int
        Year of EIA-923 fuel data to use.

    Returns
    ----------
    dataframe
    """

    # Get the EIA generation data for the specified year, this dataset includes
    # the fuel consumption for generating electricity for each facility
    # and fuel type. Filter the data to only include NG facilities and on positive
    # fuel consumption. Group that data by Plant Id as it is possible to have
    # multiple rows for the same facility and fuel based on different prime
    # movers (e.g., gas turbine and combined cycle).
    eia_generation_data = eia923_download_extract(year)

    column_filt = (eia_generation_data["Reported Fuel Type Code"] == "NUC") & (
        eia_generation_data["Net Generation (Megawatthours)"] > 0)
    nuc_generation_data = eia_generation_data[column_filt]

    nuc_generation_data = (nuc_generation_data.groupby("Plant Id").agg({
        "Net Generation (Megawatthours)":
        "sum"
    }).reset_index())
    nuc_generation_data["Plant Id"] = nuc_generation_data["Plant Id"].astype(
        int)

    # Read the nuclear LCI excel file
    nuc_lci = pd.read_csv(data_dir + "/nuclear_LCI.csv",
                          index_col=0,
                          low_memory=False)
    nuc_lci.dropna(subset=["compartment"], inplace=True)
    # There is no column to merge the inventory and generation data on,
    # so we iterate through the plants and make a new column in the lci
    # dataframe using the plant id. And add a copy of that dataframe to a
    # running list. Finally we concatenate all of the dataframes in the list
    # together for a final merged dataframe.
    merged_list = list()
    for idx1, plant in nuc_generation_data.iterrows():
        nuc_lci["Plant Id"] = plant["Plant Id"]
        merged_list.append(copy.copy(nuc_lci))
    nuc_lci = pd.concat(merged_list)
    nuc_merged = pd.merge(
        left=nuc_lci,
        right=nuc_generation_data,
        left_on=["Plant Id"],
        right_on=["Plant Id"],
        how="left",
    )

    nuc_merged.rename(columns={"Net Generation (Megawatthours)": "quantity"},
                      inplace=True)

    # Convert the inventory per MWh emissions to an annual emission
    nuc_merged["FlowAmount"] = (nuc_merged["FlowAmount"] *
                                nuc_merged["quantity"])
    nuc_merged["Electricity"] = nuc_merged["quantity"]
    # Filling out some columns to be consistent with other upstream dataframes
    nuc_merged["fuel_type"] = "Nuclear"
    nuc_merged["stage"] = "mine-to-plant"
    nuc_merged["stage_code"] = "NUC"
    nuc_merged.rename(columns={"unit": "Unit"}, inplace=True)
    nuc_merged.rename(
        columns={
            "compartment": "Compartment",
            "Plant Id": "plant_id"
        },
        inplace=True,
    )
    input_dict = {"emission": False, "resource": True}
    nuc_merged["directionality"] = nuc_merged["directionality"].map(input_dict)
    nuc_merged.rename(columns={"directionality": "input"}, inplace=True)
    return nuc_merged
Ejemplo n.º 3
0
def generate_upstream_solarthermal(year):
    """
    Generate the annual emissions.
    
    For solar thermal plant construction for each plant in EIA923. The emissions
    inventory file has already allocated the total emissions to construct the
    entire power plant over its assumed 30 year life. So the emissions returned
    below represent 1/30th of the total site construction emissions.

    Parameters
    ----------
    year: int
        Year of EIA-923 fuel data to use.

    Returns
    ----------
    dataframe
    """
    eia_generation_data = eia923_download_extract(year)
    eia_generation_data['Plant Id']=eia_generation_data['Plant Id'].astype(int)
    column_filt = (eia_generation_data['Reported Fuel Type Code'] == 'SUN')
    solar_generation_data=eia_generation_data.loc[column_filt,:]
    solar_df = pd.read_csv(
        f'{data_dir}/solar_thermal_inventory.csv',
        header=[0,1]
    )
    columns = pd.DataFrame(solar_df.columns.tolist())
    columns.loc[columns[0].str.startswith('Unnamed:'), 0] = np.nan
    columns[0] = columns[0].fillna(method='ffill')
    solar_df.columns = pd.MultiIndex.from_tuples(columns.to_records(index=False).tolist())
    solar_df_t=solar_df.transpose()
    solar_df_t=solar_df_t.reset_index()
    new_columns = solar_df_t.loc[0,:].tolist()
    new_columns[0]='Compartment'
    new_columns[1]='FlowName'
    solar_df_t.columns=new_columns
    solar_df_t.drop(index=0, inplace=True)
    solar_df_t_melt=solar_df_t.melt(
            id_vars=['Compartment','FlowName'],
            var_name='plant_id',
            value_name='FlowAmount'
    )
    solar_df_t_melt = solar_df_t_melt.astype({'plant_id' : int})
    solarthermal_upstream=solar_df_t_melt.merge(
            right=solar_generation_data,
            left_on='plant_id',
            right_on='Plant Id',
            how='left'
    )
    solarthermal_upstream.rename(columns=
            {
                    'Net Generation (Megawatthours)':'Electricity',
            },
            inplace=True
    )
    solarthermal_upstream["quantity"]=solarthermal_upstream["Electricity"]
    solarthermal_upstream.drop(columns=[
            'Plant Id',
            'NAICS Code',
            'Reported Fuel Type Code',
            'YEAR',
            'Total Fuel Consumption MMBtu',
            'State',
            'Plant Name',
            ],inplace=True)
    # These emissions will later be aggregated with any inventory power plant
    # emissions because each facility has its own construction impacts.
    solarthermal_upstream['stage_code']="Power plant"
    solarthermal_upstream['fuel_type']='SOLARTHERMAL'
    compartment_map={
            'Air':'air',
            'Water':'water',
            'Energy':'input'
    }
    solarthermal_upstream['Compartment']=solarthermal_upstream['Compartment'].map(compartment_map)
    # solarthermal_upstream['Compartment']=solarthermal_upstream['Compartment'].str.lower()
    solarthermal_upstream["Unit"]="kg"
    solarthermal_upstream["input"]=False
    return solarthermal_upstream
Ejemplo n.º 4
0
def generate_upstream_wind(year):
    """
    Generate the annual emissions.
    
    For wind farm construction for each plant in EIA923. The emissions inventory
    file has already allocated the total emissions to construct the turbines and
    balance of system for the entire wind farm over the assumed 20 year life of
    the panels. So the emissions returned below represent 1/20th of the total
    site construction emissions.

    Parameters
    ----------
    year: int
        Year of EIA-923 fuel data to use.

    Returns
    ----------
    dataframe
    """
    eia_generation_data = eia923_download_extract(year)
    eia_generation_data["Plant Id"] = eia_generation_data["Plant Id"].astype(
        int
    )
    column_filt = eia_generation_data["Reported Fuel Type Code"] == "WND"
    wind_generation_data = eia_generation_data.loc[column_filt, :]
    wind_df = pd.read_csv(f"{data_dir}/wind_inventory.csv", header=[0, 1])
    columns = pd.DataFrame(wind_df.columns.tolist())
    columns.loc[columns[0].str.startswith("Unnamed:"), 0] = np.nan
    columns[0] = columns[0].fillna(method="ffill")
    wind_df.columns = pd.MultiIndex.from_tuples(
        columns.to_records(index=False).tolist()
    )
    wind_df_t = wind_df.transpose()
    wind_df_t = wind_df_t.reset_index()
    new_columns = wind_df_t.loc[0, :].tolist()
    new_columns[0] = "Compartment"
    new_columns[1] = "FlowName"
    wind_df_t.columns = new_columns
    wind_df_t.drop(index=0, inplace=True)
    wind_df_t_melt = wind_df_t.melt(
        id_vars=["Compartment", "FlowName"],
        var_name="plant_id",
        value_name="FlowAmount",
    )
    wind_df_t_melt = wind_df_t_melt.astype({'plant_id' : int})
    wind_upstream = wind_df_t_melt.merge(
        right=wind_generation_data,
        left_on="plant_id",
        right_on="Plant Id",
        how="left",
    )
    wind_upstream.rename(
        columns={"Net Generation (Megawatthours)": "quantity"}, inplace=True
    )
    wind_upstream["Electricity"]=wind_upstream["quantity"]
    wind_upstream.drop(
        columns=[
            "Plant Id",
            "NAICS Code",
            "Reported Fuel Type Code",
            "YEAR",
            "Total Fuel Consumption MMBtu",
            "State",
            "Plant Name",
        ],
        inplace=True,
    )
    # These emissions will later be aggregated with any inventory power plant
    # emissions because each facility has its own construction impacts.
    wind_upstream["stage_code"] = "Power plant"
    wind_upstream["fuel_type"] = "WIND"
    compartment_map = {"Air": "air", "Water": "water", "Energy": "input"}
    wind_upstream["Compartment"] = wind_upstream["Compartment"].map(
        compartment_map
    )
    wind_upstream["input"]=False
    wind_upstream.loc[wind_upstream["Compartment"]=="input","input"]=True
    wind_upstream["Unit"]="kg"
    # wind_upstream['Compartment']=wind_upstream['Compartment'].str.lower()
    return wind_upstream
Ejemplo n.º 5
0
def generate_upstream_geo(year):
    """
    Generate the annual emissions from geothermal power plants. These emissions
    are from an NETL-developed model that takes into account the insoluble gases
    present in the geothermal fluid and the type of geothermal power to develop
    emission factors for those gases.

    Parameters
    ----------
    year: int
        Year of EIA-923 fuel data to use.

    Returns
    ----------
    dataframe
    """

    geothermal_state_dict = {
        "california": "CA",
        "hawaii": "HI",
        "idaho": "ID",
        "new_mexico": "NM",
        "nevada": "NV",
        "oregon": "OR",
        "utah": "UT",
        "us_average": "US",
    }
    geothermal_states = [
        "california",
        "hawaii",
        "idaho",
        "new_mexico",
        "nevada",
        "oregon",
        "utah",
        "us_average",
    ]
    # Get the EIA generation data for the specified year, this dataset includes
    # the fuel consumption for generating electricity for each facility
    # and fuel type. Filter the data to only include NG facilities and on positive
    # fuel consumption. Group that data by Plant Id as it is possible to have
    # multiple rows for the same facility and fuel based on different prime
    # movers (e.g., gas turbine and combined cycle).
    eia_generation_data = eia923_download_extract(year)

    column_filt = (eia_generation_data["Reported Fuel Type Code"] == "GEO") & (
        eia_generation_data["Net Generation (Megawatthours)"] > 0)
    geo_generation_data = eia_generation_data[column_filt]

    geo_generation_data = (geo_generation_data.groupby(
        ["Plant Id", "State"]).agg({
            "Net Generation (Megawatthours)": "sum"
        }).reset_index())
    geo_generation_data["Plant Id"] = geo_generation_data["Plant Id"].astype(
        int)

    # Read the geothermal LCI excel file
    geo_lci = pd.read_csv(data_dir + "/geothermal_lci.csv", index_col=0)
    geo_lci = geo_lci.melt(
        id_vars=["FlowName", "Compartment", "unit", "Directionality"],
        value_vars=geothermal_states,
        var_name="stage_code",
        value_name="FlowAmount",
    )
    geo_lci["stage_code"] = geo_lci["stage_code"].map(geothermal_state_dict)

    geo_merged = pd.merge(
        left=geo_generation_data,
        right=geo_lci,
        left_on=["State"],
        right_on=["stage_code"],
        how="left",
    )

    geo_merged.rename(columns={"Net Generation (Megawatthours)": "quantity"},
                      inplace=True)
    geo_merged["Electricity"] = geo_merged["quantity"]
    # Convert the inventory per MWh emissions to an annual emission
    geo_merged["FlowAmount"] = (geo_merged["FlowAmount"] *
                                geo_merged["quantity"])
    geo_merged["Electricity"] = geo_merged["quantity"]
    # Filling out some columns to be consistent with other upstream dataframes
    geo_merged["fuel_type"] = "Geothermal"
    geo_merged["stage_code"] = "Power plant"
    #    geo_merged.drop(columns=['unit'])
    geo_merged.rename(columns={"unit": "Unit"}, inplace=True)
    geo_merged.rename(
        columns={
            "compartment": "Compartment",
            "Plant Id": "plant_id"
        },
        inplace=True,
    )
    geo_merged["Compartment"].fillna(geo_merged["Directionality"],
                                     inplace=True)
    input_dict = {"emission": False, "resource": True}
    geo_merged["Directionality"] = geo_merged["Directionality"].map(input_dict)
    geo_merged.rename(columns={"Directionality": "input"}, inplace=True)
    return geo_merged