From 2f964e513090f949ad5ad4abbb56c4d60813733b Mon Sep 17 00:00:00 2001 From: Ben Young Date: Mon, 13 May 2024 16:58:58 -0400 Subject: [PATCH 01/19] add back develop tags --- requirements.txt | 4 ++-- setup.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index a40f8db..928126e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ -git+https://github.com/USEPA/fedelemflowlist.git#egg=fedelemflowlist -git+https://github.com/USEPA/esupy.git#egg=esupy +git+https://github.com/USEPA/fedelemflowlist.git@develop#egg=fedelemflowlist +git+https://github.com/USEPA/esupy.git@develop#egg=esupy olca-schema>=0.0.11 pandas>=0.23 openpyxl>=3.0.7 diff --git a/setup.py b/setup.py index d0e0e56..65cd8f1 100644 --- a/setup.py +++ b/setup.py @@ -8,8 +8,8 @@ package_data={'lciafmt': ["data/*.*"]}, include_package_data=True, python_requires=">=3.9", - install_requires=["fedelemflowlist @ git+https://github.com/USEPA/fedelemflowlist.git#egg=fedelemflowlist", - "esupy @ git+https://github.com/USEPA/esupy.git#egg=esupy", + install_requires=["fedelemflowlist @ git+https://github.com/USEPA/fedelemflowlist.git@develop#egg=fedelemflowlist", + "esupy @ git+https://github.com/USEPA/esupy.git@develop#egg=esupy", "olca-schema>=0.0.11", "pandas>=0.22", "openpyxl>=3.0.7", From a803d190a9303b88875b7e48768bc17ab0e72ba3 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Tue, 14 May 2024 08:30:08 -0400 Subject: [PATCH 02/19] add zenodo data #113 --- .zenodo.json | 38 ++++++++++++++++++++++++++++++++++++++ README.md | 3 ++- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 .zenodo.json diff --git a/.zenodo.json b/.zenodo.json new file mode 100644 index 0000000..94f10b8 --- /dev/null +++ b/.zenodo.json @@ -0,0 +1,38 @@ +{ + "description": "Standardizes the format and flows of life cycle impact assessment (LCIA) data.", + "license": "MIT", + "title": "LCIA Formatter", + "upload_type": "software", + "creators": [ + { + "affiliation": "Eastern Research Group, Inc.", + "name": "Ben Young", + "orcid": "https://orcid.org/0000-0001-6276-8670" + }, + { + "affiliation": "GreenDelta", + "name": "Michael Srocka" + }, + { + "affiliation": "US Environmental Protection Agency", + "name": "Wesley Ingwersen", + "orcid": "https://orcid.org/0000-0002-9614-701X" + }, + { + "affiliation": "Eastern Research Group, Inc.", + "name": "Ben Morelli", + "orcid": "https://orcid.org/0000-0002-7660-6485" + }, + { + "affiliation": "Eastern Research Group, Inc.", + "name": "Sarah Cashman", + "orcid": "https://orcid.org/0000-0001-9859-9557" + }, + { + "affiliation": "Eastern Research Group, Inc.", + "name": "Andrew Henderson", + "orcid": "https://orcid.org/0000-0003-2436-7512" + } + ], + "access_right": "open" +} diff --git a/README.md b/README.md index 84c32a4..74e6c15 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # LCIA formatter -[![DOI](https://joss.theoj.org/papers/10.21105/joss.03392/status.svg)](https://doi.org/10.21105/joss.03392) +[![JOSS](https://joss.theoj.org/papers/10.21105/joss.03392/status.svg)](https://doi.org/10.21105/joss.03392) +[![DOI](https://zenodo.org/badge/188049640.svg)](https://zenodo.org/doi/10.5281/zenodo.7400857) [![build](https://github.com/USEPA/LCIAformatter/actions/workflows/python-package.yml/badge.svg)](https://github.com/USEPA/LCIAformatter/actions/workflows/python-package.yml) The LCIA formatter, or `lciafmt`, is a Python tool for standardizing the format and flows of life cycle impact assessment (LCIA) data. The tool acquires LCIA data transparently from its original From 447d9b56c7f3a6aa340d619291e24d5f11b09b3e Mon Sep 17 00:00:00 2001 From: Ben Young Date: Tue, 14 May 2024 09:14:04 -0400 Subject: [PATCH 03/19] use `.to_ref()` to avoid unnecessary data for flows within ImpactFactors #114 --- lciafmt/jsonld.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lciafmt/jsonld.py b/lciafmt/jsonld.py index 8eb10a9..8bf2ff6 100644 --- a/lciafmt/jsonld.py +++ b/lciafmt/jsonld.py @@ -74,7 +74,7 @@ def write(self, df: pd.DataFrame, write_flows=False, preferred_only=False): indicator = self.__indicator(row) factor = o.ImpactFactor() unit = row['Unit'] - factor.flow = self.__flow(row) + factor.flow = self.__flow(row).to_ref() factor.flow_property = units.property_ref(unit) factor.unit = units.unit_ref(unit) factor.value = row['Characterization Factor'] From 21cee6527e3b3d489932c4791de1c24b1f20e9ff Mon Sep 17 00:00:00 2001 From: Ben Young Date: Mon, 15 Jul 2024 12:50:19 -0400 Subject: [PATCH 04/19] add initial draft CED method --- lciafmt/__init__.py | 4 +++ lciafmt/ced.py | 56 +++++++++++++++++++++++++++++++++++++++ lciafmt/data/methods.json | 9 +++++++ 3 files changed, 69 insertions(+) create mode 100644 lciafmt/ced.py diff --git a/lciafmt/__init__.py b/lciafmt/__init__.py index 3843c40..5c9868f 100644 --- a/lciafmt/__init__.py +++ b/lciafmt/__init__.py @@ -13,6 +13,7 @@ import pandas as pd import lciafmt.cache as cache +import lciafmt.ced as ced import lciafmt.fmap as fmap import lciafmt.jsonld as jsonld import lciafmt.traci as traci @@ -34,6 +35,7 @@ class Method(Enum): TRACI = "TRACI 2.1" RECIPE_2016 = "ReCiPe 2016" FEDEFL_INV = "FEDEFL Inventory" + CED = "Cumulative Energy Demand" ImpactWorld = "ImpactWorld" IPCC = "IPCC" @@ -122,6 +124,8 @@ def get_method(method_id, add_factors_for_missing_contexts=True, return ipcc.get() if method_id == Method.FEDEFL_INV: return fedefl_inventory.get(subset) + if method_id == Method.CED: + return ced.get() def clear_cache(): diff --git a/lciafmt/ced.py b/lciafmt/ced.py new file mode 100644 index 0000000..90ea19e --- /dev/null +++ b/lciafmt/ced.py @@ -0,0 +1,56 @@ +# ced.py (lciafmt) +# !/usr/bin/env python3 +# coding=utf-8 +""" +Generate method for Cumulative Energy Demand (CED) +""" + +import numpy as np +import pandas as pd + +import lciafmt +from lciafmt.util import store_method + + +def get() -> pd.DataFrame(): + + inv_orig = lciafmt.get_method(method_id = 'FEDEFL_INV', subset = ['energy']) + inv = inv_orig.copy() + inv['Indicator'] = '' + inv['Method'] = 'Cumulative Energy Demand' + + conditions = [ + inv['Flowable'].isin(['Biomass', 'Softwood', 'Hardwood', 'Wood']), + inv['Flowable'].isin(['Energy, hydro']), + inv['Flowable'].str.contains('|'.join(['wind', 'solar', 'geothermal'])), + inv['Flowable'].str.contains('Uranium'), + inv['Flowable'].str.contains('|'.join(['Coal', 'Oil', 'Crude', + 'gas'])), + ] + + indicators = ['Renewable, biomass', + 'Renewable, water', + 'Renewable, wind, solar, geothermal', + 'Non-renewable, nuclear', + 'Non-renewable, fossil', + ] + inv['Indicator'] = np.select(conditions, indicators, default='') + + ## Original CED Method included the + # "Energy, fossil, unspecified" technosphere flow + # https://www.lcacommons.gov/lca-collaboration/National_Renewable_Energy_Laboratory/USLCI_Database_Public/dataset/FLOW/46dc4693-2f24-39d2-b69f-dd059737fd5e + + ## Original CED Method used HHV for biomass/wood flows + + # Dropped flows: "Hydrogen", "Energy, heat" + + inv = inv.query('Indicator != ""').reset_index(drop=True) + + return inv + + +if __name__ == "__main__": + method = lciafmt.Method.CED + df = get() + store_method(df, method) + lciafmt.util.save_json(method, df) diff --git a/lciafmt/data/methods.json b/lciafmt/data/methods.json index d971d5f..135cfa0 100644 --- a/lciafmt/data/methods.json +++ b/lciafmt/data/methods.json @@ -67,6 +67,15 @@ }, "citation": "Forster and Ramaswamy 2007 (AR4), Myhre and Shindell 2013 (AR5), Forster and Storelvmo 2021 (AR6)", "source_type": "csv" + }, + { + "id": "CED", + "name": "Cumulative Energy Demand", + "detail_note": "ADD", + "path": "fedefl", + "url": "", + "citation": "", + "source_type": "" } ] From 33e8aa8a8af6a81dc0ad9543bcb57f7208b8d8ea Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 6 Nov 2024 10:54:37 -0500 Subject: [PATCH 05/19] :heavy_check_mark: implement test to check method urls --- lciafmt/data/methods.json | 2 +- lciafmt/iw.py | 14 +++++++++----- lciafmt/recipe.py | 16 +++++++++++----- lciafmt/traci.py | 11 +++++++---- tests/test_generate_methods.py | 7 +++++++ 5 files changed, 35 insertions(+), 15 deletions(-) diff --git a/lciafmt/data/methods.json b/lciafmt/data/methods.json index d971d5f..4b42e0c 100644 --- a/lciafmt/data/methods.json +++ b/lciafmt/data/methods.json @@ -49,7 +49,7 @@ "ImpactWorld+ - Endpoint":"This method includes all global endpoint flows and their attributes."}, "path": "impactworld", "case_insensitivity": "False", - "url": "http://www.impactworldplus.org/en/writeToFile.php", + "url": "https://www.dropbox.com/sh/2sdgbqf08yn91bc/AABIGLlb_OwfNy6oMMDZNrm0a/IWplus_public_v1.3.accdb?dl=1", "citation": "Bulle, Cecile, Manuele Margni, Laure Patouillard, Anne-Marie Boulay, Guillaume Bourgault, Vincent De Bruille, Viet Cao, et al. IMPACT World+: A Globally Regionalized Life Cycle Impact Assessment Method. The International Journal of Life Cycle Assessment 24, no. 9 (September 2019), 1653–74. https://doi.org/10.1007/s11367-019-01583-0", "source_type": "Access file" }, diff --git a/lciafmt/iw.py b/lciafmt/iw.py index de66529..fdf9f1c 100644 --- a/lciafmt/iw.py +++ b/lciafmt/iw.py @@ -6,6 +6,7 @@ """ import pandas as pd +import lciafmt import lciafmt.cache as cache import lciafmt.df as dfutil from lciafmt.util import log, format_cas @@ -38,13 +39,10 @@ def get(file=None, url=None, region=None) -> pd.DataFrame: "Please install drivers to remotely connect to Access Database. " "Drivers only available on windows platform. For instructions visit: " "https://github.com/mkleehammer/pyodbc/wiki/Connecting-to-Microsoft-Access") - + method_meta = lciafmt.Method.ImpactWorld.get_metadata() f = file if f is None: - fname = "Impact_World.accdb" - if url is None: - url = "https://www.dropbox.com/sh/2sdgbqf08yn91bc/AABIGLlb_OwfNy6oMMDZNrm0a/IWplus_public_v1.3.accdb?dl=1" - f = cache.get_or_download(fname, url) + f = _get_file(method_meta, url) df = _read(f, region) # Identify midpoint and endpoint records and differentiate in data frame. @@ -58,6 +56,12 @@ def get(file=None, url=None, region=None) -> pd.DataFrame: return df +def _get_file(method_meta, url=None): + fname = "Impact_World.accdb" + if url is None: + url = method_meta['url'] + f = cache.get_or_download(fname, url) + return f def _read(access_file: str, region) -> pd.DataFrame: """Read the Access database at passed access_file into DataFrame.""" diff --git a/lciafmt/recipe.py b/lciafmt/recipe.py index 3ddcfa5..1c95a8a 100644 --- a/lciafmt/recipe.py +++ b/lciafmt/recipe.py @@ -9,6 +9,7 @@ import pandas as pd import openpyxl +import lciafmt import lciafmt.cache as cache import lciafmt.df as dfutil import lciafmt.xls as xls @@ -52,13 +53,10 @@ def get(add_factors_for_missing_contexts=True, endpoint=True, :return: DataFrame of method in standard format """ log.info("getting method ReCiPe 2016") + method_meta = lciafmt.Method.RECIPE_2016.get_metadata() f = file if f is None: - fname = "recipe_2016.xlsx" - if url is None: - url = ("http://www.rivm.nl/sites/default/files/2018-11/" + - "ReCiPe2016_CFs_v1.1_20180117.xlsx") - f = cache.get_or_download(fname, url) + f = _get_file(method_meta, url) df = _read(f) if add_factors_for_missing_contexts: log.info("adding average factors for primary contexts") @@ -135,6 +133,14 @@ def get(add_factors_for_missing_contexts=True, endpoint=True, return df +def _get_file(method_meta, url=None): + fname = "recipe_2016.xlsx" + if url is None: + url = method_meta['url'] + f = cache.get_or_download(fname, url) + return f + + def _read(file: str) -> pd.DataFrame: log.info(f"read ReCiPe 2016 from file {file}") wb = openpyxl.load_workbook(file, read_only=True, data_only=True) diff --git a/lciafmt/traci.py b/lciafmt/traci.py index 97d6265..d061633 100644 --- a/lciafmt/traci.py +++ b/lciafmt/traci.py @@ -38,10 +38,7 @@ def get(add_factors_for_missing_contexts=True, file=None, method_meta = lciafmt.Method.TRACI.get_metadata() f = file if f is None: - fname = "traci_2.1.xlsx" - if url is None: - url = method_meta['url'] - f = cache.get_or_download(fname, url) + f = _get_file(method_meta, url) df = _read(f) if add_factors_for_missing_contexts: log.info("adding average factors for primary contexts") @@ -72,6 +69,12 @@ def get(add_factors_for_missing_contexts=True, file=None, return df +def _get_file(method_meta, url=None): + fname = "traci_2.1.xlsx" + if url is None: + url = method_meta['url'] + f = cache.get_or_download(fname, url) + return f def _read(xls_file: str) -> pd.DataFrame: """Read the data from Excel with given path into a DataFrame.""" diff --git a/tests/test_generate_methods.py b/tests/test_generate_methods.py index 4d516e5..67a48fd 100644 --- a/tests/test_generate_methods.py +++ b/tests/test_generate_methods.py @@ -23,6 +23,12 @@ def test_generate_methods(): assert not error_list +def test_url_access(): + import lciafmt.iw as impactworld + f = lciafmt.recipe._get_file(lciafmt.Method.RECIPE_2016.get_metadata()) + f = lciafmt.traci._get_file(lciafmt.Method.TRACI.get_metadata()) + f = impactworld._get_file(lciafmt.Method.ImpactWorld.get_metadata()) + def test_endpoint_method(): method = lciafmt.generate_endpoints('Weidema_valuation', name='Weidema Valuation', @@ -63,4 +69,5 @@ def test_compilation_method(): if __name__ == "__main__": # test_generate_methods() # test_method_write_json() + # test_url_access() test_compilation_method() From a2bff150c954d1680963703a18a6f5d77685c851 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 6 Nov 2024 10:55:20 -0500 Subject: [PATCH 06/19] update recipe url resolves #121 --- lciafmt/data/methods.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lciafmt/data/methods.json b/lciafmt/data/methods.json index 4b42e0c..8a39c39 100644 --- a/lciafmt/data/methods.json +++ b/lciafmt/data/methods.json @@ -25,7 +25,7 @@ "ReCiPe 2016 - Midpoint/E":"ReCiPe 2016 v1.1 midpoint method, Egalitarian version. The typical ReCiPe midpoint method used is the Hierarchist version."}, "path": "recipe", "case_insensitivity": "True", - "url": "http://www.rivm.nl/sites/default/files/2018-11/ReCiPe2016_CFs_v1.1_20180117.xlsx", + "url": "https://www.rivm.nl/sites/default/files/2024-10/ReCiPe2016_CFs_v1.1_20180117.xlsx", "bib_id": "huijbregts_recipe_2017", "citation": "Huijbregts 2017", "source_type": "Excel file" From 18a179f9dc0dcf142f448caf43a892dd92eaaecb Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 13 Nov 2024 13:29:04 -0500 Subject: [PATCH 07/19] update ced method and add metadata --- lciafmt/ced.py | 11 +++++++---- lciafmt/data/lcia.bib | 9 +++++++++ lciafmt/data/methods.json | 6 ++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lciafmt/ced.py b/lciafmt/ced.py index 90ea19e..4e79403 100644 --- a/lciafmt/ced.py +++ b/lciafmt/ced.py @@ -14,21 +14,23 @@ def get() -> pd.DataFrame(): - inv_orig = lciafmt.get_method(method_id = 'FEDEFL_INV', subset = ['energy']) + inv_orig = lciafmt.get_method(method_id = 'FEDEFL_INV', subset = ['ced']) inv = inv_orig.copy() inv['Indicator'] = '' inv['Method'] = 'Cumulative Energy Demand' conditions = [ + inv['Flowable'].isin(['Wood, primary forest']), inv['Flowable'].isin(['Biomass', 'Softwood', 'Hardwood', 'Wood']), inv['Flowable'].isin(['Energy, hydro']), inv['Flowable'].str.contains('|'.join(['wind', 'solar', 'geothermal'])), inv['Flowable'].str.contains('Uranium'), inv['Flowable'].str.contains('|'.join(['Coal', 'Oil', 'Crude', - 'gas'])), + 'gas', 'Methane'])), ] - indicators = ['Renewable, biomass', + indicators = ['Non-renewable, biomass', + 'Renewable, biomass', 'Renewable, water', 'Renewable, wind, solar, geothermal', 'Non-renewable, nuclear', @@ -41,8 +43,9 @@ def get() -> pd.DataFrame(): # https://www.lcacommons.gov/lca-collaboration/National_Renewable_Energy_Laboratory/USLCI_Database_Public/dataset/FLOW/46dc4693-2f24-39d2-b69f-dd059737fd5e ## Original CED Method used HHV for biomass/wood flows + # Some wood flows were removed after the original method in FEDEFLv1.0.8 - # Dropped flows: "Hydrogen", "Energy, heat" + # Dropped flows from FEDEFL inv method: "Hydrogen", "Energy, heat" inv = inv.query('Indicator != ""').reset_index(drop=True) diff --git a/lciafmt/data/lcia.bib b/lciafmt/data/lcia.bib index 5f96129..f6a3bb0 100644 --- a/lciafmt/data/lcia.bib +++ b/lciafmt/data/lcia.bib @@ -45,3 +45,12 @@ @incollection{smith_earths_2021 author = {Smith, Chris and Nicholls, Zebedee R. J. and Armour, Kyle and Collins, William and Forster, Piers and Meinshausen, Malte and Palmer, Matthew D. and Watanabe, Masahiro}, year = {2021}, } + +@report{frischknecht_implementation_2007, + title = {Implementation of life cycle impact assessment methods}, + url = {https://esu-services.ch/fileadmin/download/publicLCI/03_LCIA-Implementation.pdf}, + number = {ecoinvent report No. 3}, + author = {Frischknecht, Rolf and Jungbluth, Niels and Althaus, H. J. and Bauer, C. and Doka, G. and Dones, R. and Hischier, R. and Hellweg, S. and Humbert, S. and Köllner, T.}, + urldate = {2024-11-13}, + year = {2007}, +} diff --git a/lciafmt/data/methods.json b/lciafmt/data/methods.json index 135cfa0..f304435 100644 --- a/lciafmt/data/methods.json +++ b/lciafmt/data/methods.json @@ -71,10 +71,12 @@ { "id": "CED", "name": "Cumulative Energy Demand", - "detail_note": "ADD", + "version": "1.0", + "detail_note": "All heating values are per the FEDEFL, and the list of external references is found on the EPA FEDEFL GitHub at: https://github.com/USEPA/fedelemflowlist. This CED method is based on the categorization scheme used in Frischknecht et al. (2007) found in the ecoinvent report 'Implementation of Life Cycle Impact Assessment Methods.'", "path": "fedefl", + "bib_id": "frischknecht_implementation_2007", "url": "", - "citation": "", + "citation": "Frischknecht et al. 2007", "source_type": "" } From 7dad16e8ae851186dea6a9ba4edc513529a0c03d Mon Sep 17 00:00:00 2001 From: Ben Young Date: Mon, 18 Nov 2024 09:04:56 -0500 Subject: [PATCH 08/19] fix typo in `Ecosystem damage` #124; add missing space for endopint `Water consumption - aquatic ecosystems` --- lciafmt/data/ReCiPe2016_endpoint_to_midpoint.csv | 4 ++-- lciafmt/recipe.py | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lciafmt/data/ReCiPe2016_endpoint_to_midpoint.csv b/lciafmt/data/ReCiPe2016_endpoint_to_midpoint.csv index e3baedf..4684607 100644 --- a/lciafmt/data/ReCiPe2016_endpoint_to_midpoint.csv +++ b/lciafmt/data/ReCiPe2016_endpoint_to_midpoint.csv @@ -8,7 +8,7 @@ ,Toxicity - Human health (non-cancer),Human noncarcinogenic toxicity,Human health ,Water consumption - human health,Water consumption,Human health ,Global Warming - Terrestrial ecosystems,Global Warming,Terrestrial ecosystems -,Photochemical ozone formation - Terrestrial ecosystems,Ecosyste damage ozone formation,Terrestrial ecosystems +,Photochemical ozone formation - Terrestrial ecosystems,Ecosystem damage ozone formation,Terrestrial ecosystems ,Acidification - Terrestrial ecosystems,Terrestrial acidification,Terrestrial ecosystems ,Toxicity - Terrestrial ecosystems,Terrestrial ecotoxicity,Terrestrial ecosystems ,Water consumption - terrestrial ecosystems,Water consumption,Terrestrial ecosystems @@ -16,7 +16,7 @@ ,Global Warming - Freshwater ecosystems,Global Warming,Freshwater ecosystems ,Eutrophication - Freshwater ecosystems,Freshwater eutrophication,Freshwater ecosystems ,Toxicity - Freshwater ecosystems,Freshwater ecotoxicity,Freshwater ecosystems -,Water consumption -aquatic ecosystems,Water consumption,Freshwater ecosystems +,Water consumption - aquatic ecosystems,Water consumption,Freshwater ecosystems ,Toxicity - Marine ecosystems,Marine ecotoxicity,Marine ecosystems ,Eutrophication - Marine ecosystems,Marine eutrophication,Marine ecosystems ,Mineral resource scarcity,Mineral resource scarcity,Resources diff --git a/lciafmt/recipe.py b/lciafmt/recipe.py index 1c95a8a..0bf46bf 100644 --- a/lciafmt/recipe.py +++ b/lciafmt/recipe.py @@ -177,7 +177,7 @@ def _read_endpoints(file: str) -> pd.DataFrame: continue endpoints['Method'] = "ReCiPe 2016 - Midpoint/" + perspectives[i] endpoints['EndpointMethod'] = "ReCiPe 2016 - Endpoint/" + perspectives[i] - endpoints['EndpointIndicator'] = indicator + endpoints['EndpointIndicator'] = indicator.replace(' -a', ' - a') # fix missing space endpoints['EndpointUnit'] = indicator_unit endpoints['EndpointConversion'] = val endpoint = pd.concat( @@ -221,6 +221,7 @@ def _read_mid_points(sheet: openpyxl.worksheet.worksheet.Worksheet, cas_col = _find_cas_column(sheet) indicator_unit, flow_unit, unit_col = _determine_units(sheet) compartment, compartment_col = _determine_compartments(sheet) + sheet_title = sheet.title.replace('Ecosyste damage', 'Ecosystem damage') perspectives = ["I", "H", "E"] factor_count = 0 @@ -244,7 +245,7 @@ def _read_mid_points(sheet: openpyxl.worksheet.worksheet.Worksheet, continue dfutil.record(records, method="ReCiPe 2016 - Midpoint/" + perspectives[i], - indicator=sheet.title, + indicator=sheet_title, indicator_unit=indicator_unit, flow=xls.cell_str(row[flow_col]), flow_category=compartment, @@ -259,7 +260,7 @@ def _read_mid_points(sheet: openpyxl.worksheet.worksheet.Worksheet, for p in perspectives: dfutil.record(records, method="ReCiPe 2016 - Midpoint/" + p, - indicator=sheet.title, + indicator=sheet_title, indicator_unit=indicator_unit, flow=xls.cell_str(row[flow_col]), flow_category=compartment, From 1dfb65c3afd266a570dabb4cec408b15c801de5a Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 4 Dec 2024 11:13:00 -0500 Subject: [PATCH 09/19] fix FutureWarning of mismatched dtypes --- lciafmt/fedefl_inventory.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lciafmt/fedefl_inventory.py b/lciafmt/fedefl_inventory.py index 4b243c4..e72cd92 100644 --- a/lciafmt/fedefl_inventory.py +++ b/lciafmt/fedefl_inventory.py @@ -39,7 +39,7 @@ def get(subset=None) -> pd.DataFrame: axis=1, inplace=True) flows['Indicator'] = inventory flows['Indicator unit'] = subsets.get_inventory_unit(inventory) - flows['Characterization Factor'] = 1 + flows['Characterization Factor'] = 1.0 # Apply unit conversions where flow unit differs from indicator unit flows_w_conversion = pd.merge(flows, alt_units, how='left', @@ -56,3 +56,6 @@ def get(subset=None) -> pd.DataFrame: method['Method'] = 'FEDEFL Inventory' return method + +if __name__ == "__main__": + df = get() From ce98823245e704ef4f36c6320f1172b72f40a940 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 4 Dec 2024 11:13:21 -0500 Subject: [PATCH 10/19] only add mapping description for methods that require mapping --- lciafmt/data/description.yaml | 1 + lciafmt/util.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lciafmt/data/description.yaml b/lciafmt/data/description.yaml index de20bad..225ac34 100644 --- a/lciafmt/data/description.yaml +++ b/lciafmt/data/description.yaml @@ -7,6 +7,7 @@ description: >+ Source citation: [citation] +mapping: >+ [Method] flowable and context input files are maintained in the FEDEFL GitHub Repository: https://github.com/USEPA/fedelemflowlist diff --git a/lciafmt/util.py b/lciafmt/util.py index 6ef28e1..ffa47e7 100644 --- a/lciafmt/util.py +++ b/lciafmt/util.py @@ -187,6 +187,8 @@ def generate_method_description(name: str, else: method_meta = method.get_metadata() desc += generic['description'] + if 'mapping' in method_meta: + desc += generic['mapping'] if 'detail_note' in method_meta: desc += method_meta['detail_note'] if 'methods' in method_meta: From b0c1a41a56ef3c1e92a733e43c6201d171256cf6 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 4 Dec 2024 11:15:18 -0500 Subject: [PATCH 11/19] update urls to be more specific --- lciafmt/data/methods.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lciafmt/data/methods.json b/lciafmt/data/methods.json index f304435..5a51a92 100644 --- a/lciafmt/data/methods.json +++ b/lciafmt/data/methods.json @@ -35,7 +35,7 @@ "name": "FEDEFL Inventory", "version": "1.0.0", "path": "fedefl", - "url": "http://www.github.com/usepa//Federal-LCA-Commons-Elementary-Flow-List", + "url": "https://github.com/USEPA/fedelemflowlist/blob/master/fedelemflowlist/subset_list.py", "citation": "", "source_type": "FEDEFL Python function" }, @@ -75,7 +75,7 @@ "detail_note": "All heating values are per the FEDEFL, and the list of external references is found on the EPA FEDEFL GitHub at: https://github.com/USEPA/fedelemflowlist. This CED method is based on the categorization scheme used in Frischknecht et al. (2007) found in the ecoinvent report 'Implementation of Life Cycle Impact Assessment Methods.'", "path": "fedefl", "bib_id": "frischknecht_implementation_2007", - "url": "", + "url": "https://github.com/USEPA/fedelemflowlist/blob/master/fedelemflowlist/subset_list.py", "citation": "Frischknecht et al. 2007", "source_type": "" } From a5d7c33a5e2801db7c936bfdd0a27a246a9b4316 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 4 Dec 2024 11:19:26 -0500 Subject: [PATCH 12/19] cleanup and add to Readme --- README.md | 1 + lciafmt/ced.py | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 84c32a4..f00782e 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ The LCIA Formatter v1 was peer-reviewed internally at USEPA and externally throu |ImpactWorld+ Endpoint*|International Reference Center for Life Cycle of Products, Services and Systems (CIRAIG)|[ImpactWorld+](http://www.impactworldplus.org/en/team.php)| |IPCC GWP|Intergovernmental Panel on Climate Change (IPCC)| | |FEDEFL Inventory Methods|US Environmental Protection Agency|[FEDEFL Inventory Methods](https://github.com/USEPA/LCIAformatter/wiki/Inventory-Methods)| +|Cumulative Energy Demand|Federal LCA Commons|[FEDEFL Inventory Methods](https://github.com/USEPA/LCIAformatter/wiki/Inventory-Methods)| \* only works on Windows installations diff --git a/lciafmt/ced.py b/lciafmt/ced.py index 4e79403..a6c531c 100644 --- a/lciafmt/ced.py +++ b/lciafmt/ced.py @@ -39,14 +39,14 @@ def get() -> pd.DataFrame(): inv['Indicator'] = np.select(conditions, indicators, default='') ## Original CED Method included the - # "Energy, fossil, unspecified" technosphere flow + # "Energy, fossil, unspecified" technosphere flow; + # this has been dropped # https://www.lcacommons.gov/lca-collaboration/National_Renewable_Energy_Laboratory/USLCI_Database_Public/dataset/FLOW/46dc4693-2f24-39d2-b69f-dd059737fd5e ## Original CED Method used HHV for biomass/wood flows # Some wood flows were removed after the original method in FEDEFLv1.0.8 # Dropped flows from FEDEFL inv method: "Hydrogen", "Energy, heat" - inv = inv.query('Indicator != ""').reset_index(drop=True) return inv @@ -57,3 +57,4 @@ def get() -> pd.DataFrame(): df = get() store_method(df, method) lciafmt.util.save_json(method, df) + # lciafmt.util.save_json(method, df, write_flows=True) From 946e70f7778c92f41eaf89afb3951962f81a9bec Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 4 Dec 2024 16:06:43 -0500 Subject: [PATCH 13/19] differentiate package version and flowlist version --- lciafmt/data/description.yaml | 3 ++- lciafmt/util.py | 1 + setup.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lciafmt/data/description.yaml b/lciafmt/data/description.yaml index 225ac34..70fea4e 100644 --- a/lciafmt/data/description.yaml +++ b/lciafmt/data/description.yaml @@ -1,6 +1,7 @@ base: >+ [Method][version] is built from LCIA Formatter v[LCIAfmt_version] and - flows from the Federal Elementary Flow List (FEDEFL) v[FEDEFL_version] + flows from v[FEDEFL_version] of the Federal Elementary Flow List (FEDEFL), + using fedelemflowlist v[fedelemflowlist_version]. description: >+ [Method] source file: [url] diff --git a/lciafmt/util.py b/lciafmt/util.py index ffa47e7..f4992d0 100644 --- a/lciafmt/util.py +++ b/lciafmt/util.py @@ -210,6 +210,7 @@ def generate_method_description(name: str, desc = (desc .replace('[LCIAfmt_version]', pkg_version_number) .replace('[FEDEFL_version]', flow_list_specs['list_version']) + .replace('[fedelemflowlist_version]', flow_list_specs['package_version']) .replace('[Method]', method_meta['name']) .replace('[version]', version) .replace('[citation]', method_meta['citation']) diff --git a/setup.py b/setup.py index 65cd8f1..dca532c 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ package_data={'lciafmt': ["data/*.*"]}, include_package_data=True, python_requires=">=3.9", - install_requires=["fedelemflowlist @ git+https://github.com/USEPA/fedelemflowlist.git@develop#egg=fedelemflowlist", + install_requires=["fedelemflowlist @ git+https://github.com/USEPA/fedelemflowlist.git@version#egg=fedelemflowlist", "esupy @ git+https://github.com/USEPA/esupy.git@develop#egg=esupy", "olca-schema>=0.0.11", "pandas>=0.22", From acd3c87c54db281f240c12880d6efea54a09a343 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 4 Dec 2024 16:52:21 -0500 Subject: [PATCH 14/19] use tool_version instead of package_version --- lciafmt/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lciafmt/util.py b/lciafmt/util.py index f4992d0..049a94b 100644 --- a/lciafmt/util.py +++ b/lciafmt/util.py @@ -210,7 +210,7 @@ def generate_method_description(name: str, desc = (desc .replace('[LCIAfmt_version]', pkg_version_number) .replace('[FEDEFL_version]', flow_list_specs['list_version']) - .replace('[fedelemflowlist_version]', flow_list_specs['package_version']) + .replace('[fedelemflowlist_version]', flow_list_specs['tool_version']) .replace('[Method]', method_meta['name']) .replace('[version]', version) .replace('[citation]', method_meta['citation']) From f619c58fbf8ca5a401dc3aa7ba11998e15a6f60a Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 4 Dec 2024 17:02:40 -0500 Subject: [PATCH 15/19] point back to develop --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index dca532c..65cd8f1 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ package_data={'lciafmt': ["data/*.*"]}, include_package_data=True, python_requires=">=3.9", - install_requires=["fedelemflowlist @ git+https://github.com/USEPA/fedelemflowlist.git@version#egg=fedelemflowlist", + install_requires=["fedelemflowlist @ git+https://github.com/USEPA/fedelemflowlist.git@develop#egg=fedelemflowlist", "esupy @ git+https://github.com/USEPA/esupy.git@develop#egg=esupy", "olca-schema>=0.0.11", "pandas>=0.22", From add5b789aaea2668121392009f3fa8e30d5d3d81 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 4 Dec 2024 19:03:49 -0500 Subject: [PATCH 16/19] avoid adding CED to base FEDEFL_Inv method; bump v to account for new wood primary forest flow --- lciafmt/data/methods.json | 2 +- lciafmt/fedefl_inventory.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lciafmt/data/methods.json b/lciafmt/data/methods.json index 3739017..1c733cc 100644 --- a/lciafmt/data/methods.json +++ b/lciafmt/data/methods.json @@ -33,7 +33,7 @@ { "id": "FEDEFL_INV", "name": "FEDEFL Inventory", - "version": "1.0.0", + "version": "1.1.0", "path": "fedefl", "url": "https://github.com/USEPA/fedelemflowlist/blob/master/fedelemflowlist/subset_list.py", "citation": "", diff --git a/lciafmt/fedefl_inventory.py b/lciafmt/fedefl_inventory.py index e72cd92..8adedfa 100644 --- a/lciafmt/fedefl_inventory.py +++ b/lciafmt/fedefl_inventory.py @@ -27,7 +27,8 @@ def get(subset=None) -> pd.DataFrame: method['Characterization Factor']) if subset is None: - list_of_inventories = subsets.get_subsets() + list_of_inventories = [s for s in subsets.get_subsets() if s + not in ('ced')] else: list_of_inventories = subset From b5be424a243d8a0792ebdc7d5e13d1ee9393278d Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 4 Dec 2024 19:04:07 -0500 Subject: [PATCH 17/19] :bookmark: bump to v1.1.4 --- lciafmt/util.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lciafmt/util.py b/lciafmt/util.py index 049a94b..f91decb 100644 --- a/lciafmt/util.py +++ b/lciafmt/util.py @@ -21,7 +21,7 @@ # set version number of package, needs to be updated with setup.py -pkg_version_number = '1.1.3' +pkg_version_number = '1.1.4' MODULEPATH = Path(__file__).resolve().parent datapath = MODULEPATH / 'data' diff --git a/setup.py b/setup.py index 65cd8f1..aa93405 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name="lciafmt", - version="1.1.3", + version="1.1.4", packages=["lciafmt"], package_dir={'lciafmt': 'lciafmt'}, package_data={'lciafmt': ["data/*.*"]}, From 9f966c751ca5e54805c301627cecc22b34001f1c Mon Sep 17 00:00:00 2001 From: Ben Young Date: Sat, 28 Dec 2024 07:37:42 -0500 Subject: [PATCH 18/19] drop develop tags --- requirements.txt | 4 ++-- setup.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 928126e..a40f8db 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ -git+https://github.com/USEPA/fedelemflowlist.git@develop#egg=fedelemflowlist -git+https://github.com/USEPA/esupy.git@develop#egg=esupy +git+https://github.com/USEPA/fedelemflowlist.git#egg=fedelemflowlist +git+https://github.com/USEPA/esupy.git#egg=esupy olca-schema>=0.0.11 pandas>=0.23 openpyxl>=3.0.7 diff --git a/setup.py b/setup.py index aa93405..72d7b1c 100644 --- a/setup.py +++ b/setup.py @@ -8,8 +8,8 @@ package_data={'lciafmt': ["data/*.*"]}, include_package_data=True, python_requires=">=3.9", - install_requires=["fedelemflowlist @ git+https://github.com/USEPA/fedelemflowlist.git@develop#egg=fedelemflowlist", - "esupy @ git+https://github.com/USEPA/esupy.git@develop#egg=esupy", + install_requires=["fedelemflowlist @ git+https://github.com/USEPA/fedelemflowlist.git#egg=fedelemflowlist", + "esupy @ git+https://github.com/USEPA/esupy.git#egg=esupy", "olca-schema>=0.0.11", "pandas>=0.22", "openpyxl>=3.0.7", From 8aacb5432e44c43ac518c657fe30cfb3d15e5f03 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Sat, 28 Dec 2024 07:40:17 -0500 Subject: [PATCH 19/19] add python 3.12 and 3.13 to tests --- .github/workflows/python-package.yml | 2 +- .github/workflows/test_methods.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 347bcf6..4ffc7bf 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -31,7 +31,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - py-version: ['3.9', '3.10', '3.11'] + py-version: ['3.9', '3.10', '3.11', '3.12', '3.13'] steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/test_methods.yml b/.github/workflows/test_methods.yml index 140a8ac..87845b7 100644 --- a/.github/workflows/test_methods.yml +++ b/.github/workflows/test_methods.yml @@ -17,7 +17,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.12" - name: Update pip & install testing pkgs run: |