Skip to content

Commit

Permalink
Merge pull request #10 from USEPA/master
Browse files Browse the repository at this point in the history
Update from recipe
  • Loading branch information
bl-young authored Mar 10, 2020
2 parents 370faa0 + dcccf59 commit 5397a98
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 20 deletions.
9 changes: 1 addition & 8 deletions examples/traci.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import logging as log
import os
from os.path import join
import yaml

import lciafmt

Expand All @@ -10,11 +8,6 @@ def main():
os.path.realpath(__file__)).replace('\\', '/')
outputpath = modulepath + '/../output/'
os.makedirs(outputpath, exist_ok=True)
datapath = modulepath + '/../lciafmt/data/'

with open(join(datapath, "TRACI_description.yaml")) as f:
metadata=yaml.safe_load(f)
method_description = metadata['description']

log.basicConfig(level=log.INFO)
data = lciafmt.get_method(lciafmt.Method.TRACI)
Expand All @@ -29,7 +22,7 @@ def main():
json_pack = outputpath+"traci_2.1_json.zip"
if os.path.exists(json_pack):
os.remove(json_pack)
lciafmt.to_jsonld(mapped_data, json_pack, method_description)
lciafmt.to_jsonld(mapped_data, json_pack)



Expand Down
4 changes: 2 additions & 2 deletions lciafmt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ def clear_cache():
cache.clear()


def to_jsonld(df: pd.DataFrame, zip_file: str, description: str="", write_flows=False):
def to_jsonld(df: pd.DataFrame, zip_file: str, write_flows=False):
log.info("write JSON-LD package to %s", zip_file)
with jsonld.Writer(zip_file) as w:
w.write(df, description, write_flows)
w.write(df, write_flows)


def map_flows(df: pd.DataFrame, system=None, mapping=None,
Expand Down
57 changes: 57 additions & 0 deletions lciafmt/data/ReCiPe2016_description.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
description:
'ReCiPe2016 is built from LCIA Formatter v0.3-beta and mappings from the Federal
Elementary Flow List (FEDEFL) v1.0.2
ReCiPe 1.1 source file: https://www.rivm.nl/sites/default/files/2018-11/ReCiPe2016_CFs_v1.1_20180117.xlsx
Source citation: (Huijbregts 2016)
ReCiPe 1.1 flowable and context input files are maintained in the FEDEFL GitHub Repository:
https://github.com/USEPA/Federal-LCA-Commons-Elementary-Flow-List
The LCIA Formatter (https://github.com/USEPA/LCIAformatter) applies ReCiPe 1.1
characterization factors to flows using the mapping housed in the FEDEFL.
The flowable and context input files for ReCiPe 1.1 are used by the LCIA Formatter
to translate the names from the ReCiPe 1.1 source file and generate a mapping
file for the FEDEFL. This file contains all of the accepted flowable and context
combinations which can be mapped to ReCiPe 1.1 characterization factors. It also
includes target UUID, units, and conversion factors as well as tracking
who mapped and verified each record and when they were last updated.
FEDEFL contexts are mapped to ReCiPe 1.1 to enable impact assessment across most
of the possible contexts available within FEDEFL. Mappings that occur in the
primary contexts (e.g. air) are assigned to all possible sub-contexts which apply.
Where a context is non-specific in FEDEFL relative to the available ReCiPe 1.1
contexts (e.g. rural/urban), the LCIA Formatter applies the average of the
relevant characterization factors from ReCiPe 1.1.
The LCIA Formatter generates a separate impact assement method for each of the
three approaches employed in ReCiPe 1.1, which includes Individualist,
Hierarchist, and Egalitarian. More details on the methods can be found on the
website https://www.rivm.nl/en/life-cycle-assessment-lca/downloads
This mapping is representative of ReCiPe 1.1 midpoint impact factors and
endpoint conversion factors are not included here.
'

ReCiPe 2016 - Midpoint/I:
'
ReCiPe 2016 v1.1 midpoint method, Individualist version. The typical ReCiPe
midpoint method used is the Hierarchist version.'

ReCiPe 2016 - Midpoint/H:
'
ReCiPe 2016 v1.1 midpoint method, Hierarchist version. This is the typical
ReCiPe midpoint method. '

ReCiPe 2016 - Midpoint/E:
'
ReCiPe 2016 v1.1 midpoint method, Egalitarian version. The typical ReCiPe
midpoint method used is the Hierarchist version.'
5 changes: 5 additions & 0 deletions lciafmt/data/ReCiPe2016_split.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
New Flowable,CAS
"Chlordane, technical",12789036
"FENOXYCARB, non-preferred CAS",79127803
"FENPROPATHRIN, non-preferred CAS",64257847
"Mecoprop, non-preferred CAS",93652
2 changes: 2 additions & 0 deletions lciafmt/data/TRACI_description.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ description:
TRACI 2.1 source file:
https://www.epa.gov/sites/production/files/2015-12/traci_2_1_2014_dec_10_0.xlsx
Source citation: (Bare 2012)
TRACI 2.1 flowable and context input files are maintained in the FEDEFL GitHub Repository:
https://github.com/USEPA/Federal-LCA-Commons-Elementary-Flow-List
Expand Down
14 changes: 7 additions & 7 deletions lciafmt/jsonld.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import olca.pack as pack
import pandas

from .util import make_uuid, is_non_empty_str
from .util import make_uuid, is_non_empty_str, get_method_metadata


class Writer(object):
Expand All @@ -25,9 +25,9 @@ def __enter__(self):
def __exit__(self, exc_type, exc_val, exc_tb):
self.__writer.close()

def write(self, df: pandas.DataFrame, description, write_flows=False):
def write(self, df: pandas.DataFrame, write_flows=False):
for _, row in df.iterrows():
indicator = self.__indicator(row, description)
indicator = self.__indicator(row)
factor = olca.ImpactFactor()
flow = self.__flow(row)
unit = row[8]
Expand All @@ -49,7 +49,7 @@ def write(self, df: pandas.DataFrame, description, write_flows=False):
for v in d.values():
self.__writer.write(v)

def __indicator(self, row, description) -> olca.ImpactCategory:
def __indicator(self, row) -> olca.ImpactCategory:
uid = row[3]
if not is_non_empty_str(uid):
uid = make_uuid(row[0], row[2])
Expand All @@ -65,19 +65,19 @@ def __indicator(self, row, description) -> olca.ImpactCategory:
ind.impact_factors = []
self.__indicators[uid] = ind

method = self.__method(row, description)
method = self.__method(row)
ref = olca.ImpactCategoryRef()
ref.id = uid
ref.name = ind.name
ref.ref_unit = ind.reference_unit_name
method.impact_categories.append(ref)
return ind

def __method(self, row, description) -> olca.ImpactMethod:
def __method(self, row) -> olca.ImpactMethod:
uid = row[1]
if not is_non_empty_str(uid):
uid = make_uuid(row[0])

description = get_method_metadata(row[0])
m = self.__methods.get(uid)
if m is not None:
return m
Expand Down
25 changes: 23 additions & 2 deletions lciafmt/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pandas
import xlrd
import os

import lciafmt.cache as cache
import lciafmt.df as df
Expand All @@ -25,6 +26,8 @@
'sea water' : 'water/sea water',
'Sea water' : 'water/sea water',
'marine water' : 'water/sea water'}
datapath = os.path.dirname(os.path.realpath(__file__)).replace('\\', '/')+'/data'
flowables_split = pandas.read_csv(datapath+'/ReCiPe2016_split.csv')

def get(add_factors_for_missing_contexts=True, file=None, url=None) -> pandas.DataFrame:
log.info("get method ReCiPe 2016")
Expand All @@ -39,6 +42,21 @@ def get(add_factors_for_missing_contexts=True, file=None, url=None) -> pandas.Da
if add_factors_for_missing_contexts:
log.info("Adding average factors for primary contexts")
df = util.aggregate_factors_for_primary_contexts(df)

log.info("Handling manual replacements")
""" due to substances listed more than once with the same name but different CAS
this replaces all instances of the Original Flowable with a New Flowable
based on a csv input file according to the CAS"""
for index, row in flowables_split.iterrows():
newCAS = util.format_cas(row['CAS'])
newFlow = row['New Flowable']
df.loc[df['CAS No'] == newCAS, 'Flowable'] = newFlow

length=len(df)
df.drop_duplicates(keep='first',inplace=True)
length=length-len(df)
log.info("%s duplicate entries removed", length)

return df


Expand Down Expand Up @@ -86,7 +104,7 @@ def _read_mid_points(sheet: xlrd.book.sheet, records: list):
flow_unit = flow_unit.split("/")[1].strip()
cas = ""
if cas_col > -1:
util.format_cas(xls.cell_str(sheet, row, cas_col))
cas=util.format_cas(xls.cell_f64(sheet, row, cas_col))

if with_perspectives:
for i in range(0, 3):
Expand Down Expand Up @@ -134,6 +152,9 @@ def _find_data_start(sheet: xlrd.book.sheet) -> (int, int, bool):


def _find_flow_column(sheet: xlrd.book.sheet) -> int:
if _containstr(sheet.name, "land", "occupation"):
ncol = 1
return ncol
ncol = -1
for row, col in xls.iter_cells(sheet):
s = xls.cell_str(sheet, row, col)
Expand Down Expand Up @@ -227,7 +248,7 @@ def _determine_compartments(sheet: xlrd.book.sheet) -> (str, int):
break
s = xls.cell_str(sheet, row, col)
if _containstr(s, "compartment") \
or _containstr(s, "name", "in", "ecoinvent"):
or _containstr(s, "name", "in", "ReCiPe"):
compartment_col = col
break

Expand Down
24 changes: 24 additions & 0 deletions lciafmt/util.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import uuid
import pandas as pd
import numpy as np
import yaml
import os
from os.path import join
import logging as log

def make_uuid(*args: str) -> str:
path = _as_path(*args)
Expand Down Expand Up @@ -97,3 +101,23 @@ def aggregate_factors_for_primary_contexts(df) -> pd.DataFrame:
df = pd.concat([df, df_secondary_agg], ignore_index=True, sort=False)
return df

def get_method_metadata(name: str) -> str:
modulepath = os.path.dirname(
os.path.realpath(__file__)).replace('\\', '/')
datapath = modulepath + '/../lciafmt/data/'
if name == "TRACI 2.1":
method = 'TRACI'
elif "ReCiPe 2016" in name:
method = 'ReCiPe2016'
else:
return ""
with open(join(datapath, method + "_description.yaml")) as f:
metadata=yaml.safe_load(f)
method_description = metadata['description']
detail = ""
try:
detail = metadata[name]
method_description = method_description+detail
except:
log.info("No further detail in description")
return method_description
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name="lciafmt",
version="0.2-beta",
version="0.3-beta",
packages=["lciafmt"],
install_requires=["fedelemflowlist @ git+git://github.com/USEPA/Federal-LCA-Commons-Elementary-Flow-List@v1.0.1.1#egg=fedelemflowlist",
"olca-ipc", "pandas", "xlrd"],
Expand Down

0 comments on commit 5397a98

Please sign in to comment.