This notebook shows how to import the World Food database from a SimaPro CSV export. Because there are substantial differences between the world models of ecoinvent and SimaPro, some work is needed to get proper linking to ecoinvent and to the biosphere flows used by the LCIA methods that we use.
from brightway2 import *
Start a new project, and install base data
projects.set_current("world-food")
bw2setup()
ei22 = SingleOutputEcospold1Importer(
"/Users/cmutel/Documents/LCA Documents/Ecoinvent/2.2/processes",
"ecoinvent 2.2"
)
ei22.apply_strategies()
ei22.write_database()
sp = SimaProCSVImporter("/Users/cmutel/Downloads/WFLDB2.0_v3.CSV", "world-food")
Change all variables names "yield" (and "Yield") to "yield_"; "yield" is a python reserved word.
sp = SimaProCSVImporter("/Users/cmutel/Downloads/WFLDB2.0_v3-yield.CSV", "world-food")
Apply strategies to get data into a the normal state, and link internal flows:
sp.apply_strategies()
sp.statistics()
To match against ecoinvent using the unit
field, we need to have everything in the right units. We accomplish this by applying migrations that converts units to ecoinvent defaults.
sp.migrate('unusual-units')
sp.migrate('default-units')
sp.match_database("ecoinvent 2.2", ignore_categories=True)
sp.statistics()
There are some flows specific to SimaPro that we can't match perfectly yet. Let's look at what we still have to do.
First, export only the unlinked exchanges:
sp.write_excel(only_unlinked=True)
Then the entire database, to see what the names, categories, or units should be:
sp.write_excel()
Water, BR
¶Biosphere flows occur in the location their processes do, and don't need country codes. The mangling in the database file comes from SimaPro not being agle to do regionalization yet.
We can define a new strategy to remove these country codes:
import re
def remove_country_codes(db):
expressions = [
re.compile("^Water, [A-Z]{2}$"),
re.compile("^Water, river, [A-Z]{2}$"),
re.compile("^Water, well, in ground, [A-Z]{2}$"),
]
pattern = ", [A-Z]{2}$"
for ds in db:
for exc in ds.get('exchanges', []):
if exc.get('input') or not exc['type'] == 'biosphere':
continue
for expression in expressions:
if expression.match(exc['name']):
exc['name'] = re.sub(", [A-Z]{2}$", "", exc['name'])
return db
sp.apply_strategy(remove_country_codes)
sp.match_database("biosphere3", kind='biosphere')
sp.statistics()
We define two separates migration
s to fix some incorrect data.
biosphere_units_data = {
'fields': ['name', 'unit'],
'data': [
(
('Water, cooling, unspecified natural origin/kg', 'kilogram'),
{
'name': 'Water, cooling, unspecified natural origin',
'unit': 'cubic meter',
'multiplier': 1e-3
}
),
(
('Sodium sulphate', 'kilogram'),
{'name': 'Sodium sulphate, various forms, in ground'}
),
(
('Occupation, industrial area', 'square meter-year'),
{'categories': ('natural resource', 'land')}
),
(
('Carbon dioxide, in air', 'kilogram'),
{'categories': ('natural resource', 'in air')}
),
(
('Glyphosate', 'kilogram'),
{'categories': ('soil', 'agricultural')}
),
(
('Occupation, permanent crop', 'square meter-year'),
{'categories': ('natural resource', 'land')}
),
(
('Occupation, industrial area', 'square meter-year'),
{'categories': ('natural resource', 'land')}
),
(
('Occupation, construction site', 'square meter-year'),
{'categories': ('natural resource', 'land')}
),
(
# Typo in discontinuously - how???
('transformation, to urban, discontinously built', 'square meter'),
{'name': 'Transformation, to urban, discontinuously built'}
),
(
('wood, primary forest, standing', 'square meter'),
{'categories': ('natural resource', 'biotic')}
),
(
('Water, river', 'cubic meter'),
{'categories': ('natural resource', 'in water')}
),
(
('Water, unspecified natural origin', 'cubic meter'),
{'categories': ('natural resource', 'in water')}
),
(
('Water, well, in ground', 'cubic meter'),
{'categories': ('natural resource', 'in water')}
),
(
('transformation, from permanent crop', 'square meter'),
{'categories': ('natural resource', 'land')}
),
(
('transformation, to permanent crop', 'square meter'),
{'categories': ('natural resource', 'land')}
),
(
('Methane', 'kilogram'),
{'name': 'Methane, fossil'}
),
(
('Wood, primary forest, standing', 'cubic meter'),
{'categories': ('natural resource', 'biotic')}
),
(
('Water, cooling, well, in ground', 'kilogram'),
{
'name': 'Water, well, in ground',
'unit': 'cubic meter',
'multiplier': 1e-3
}
),
(
('Water, well, in ground', 'litre'),
{
'unit': 'cubic meter',
'multiplier': 1e-3
}
),
(
('Water, river', 'litre'),
{
'unit': 'cubic meter',
'multiplier': 1e-3
}
),
(
('Treatment, sewage, to wastewater treatment, class 4', 'litre'),
{
'unit': 'cubic meter',
'multiplier': 1e-3
}
),
(
('Solved solids', 'kilogram'),
{'name': 'Dissolved solids'} # ???
),
(
('Water, unspecified natural origin/m3', 'cubic meter'),
{
'name': 'Water, unspecified natural origin',
'categories': ('natural resource', 'in water')
}
),
(
('Transformation, to arable land, unspecified use', 'square meter'),
{'categories': ('natural resource', 'land')} # Was "in ground"?
),
(
('Transformation, from arable land, unspecified use', 'square meter'),
{'categories': ('natural resource', 'land')}
),
(
('Water, river', 'litre'),
{
'unit': 'cubic meter',
'multiplier': 1e-3
}
),
(
('Water, well, in ground', 'litre'),
{
'unit': 'cubic meter',
'multiplier': 1e-3
}
),
(
('Water', 'kilogram'),
{
'unit': 'cubic meter',
'multiplier': 1e-3
}
),
]
}
biosphere_units_migration = Migration(
"food-migration-biosphere-units"
)
biosphere_units_migration.write(
biosphere_units_data,
description="Fix biosphere units and categories from World Food database"
)
sp.migrate("food-migration-biosphere-units")
sp.match_database("biosphere3", kind='biosphere')
sp.statistics()
food_technosphere_migration_data = {
'fields': ['name', 'unit'],
'data': [
(
('Tied housing system, cattle', 'unit'),
{'unit': 'livestock unit'}
),
(
('Loose housing system, cattle', 'unit'),
{'unit': 'livestock unit'}
),
(
('Water supply network', 'meter'),
{
'unit': 'kilometer',
'multiplier': 0.001
}
),
(
('Transmission network, long-distance', 'meter'),
{
'unit': 'kilometer',
'multiplier': 0.001
}
),
(
('Distribution network, electricity, low voltage', 'meter'),
{
'unit': 'kilometer',
'multiplier': 0.001
}
),
(
('Transmission network, electricity, medium voltage', 'meter'),
{
'unit': 'kilometer',
'multiplier': 0.001
}
),
(
('Transmission network, electricity, high voltage', 'meter'),
{
'unit': 'kilometer',
'multiplier': 0.001
}
),
(
('Electricity, low voltage, production RER, at grid', 'megajoule'),
{
'unit': 'kilowatt hour',
'multiplier': 1/3.6
}
),
(
('Electricity, medium voltage, production UCTE, at grid', 'megajoule'),
{
'unit': 'kilowatt hour',
'multiplier': 1/3.6
}
),
(
('Electricity, medium voltage, at grid', 'megajoule'),
{
'unit': 'kilowatt hour',
'multiplier': 1/3.6
}
),
(
('Electricity mix', 'megajoule'),
{
'unit': 'kilowatt hour',
'multiplier': 1/3.6
}
),
(
('Refinery gas, burned in furnace/MJ', 'megajoule'),
{'name': 'refinery gas, burned in furnace'}
),
]
}
food_technosphere_migration = Migration("food-technosphere")
food_technosphere_migration.write(
food_technosphere_migration_data,
description="Specific technosphere fixes for World Food DB"
)
sp.migrate("food-technosphere")
sp.match_database("ecoinvent 2.2", ignore_categories=True)
sp.statistics()
sp.write_excel(only_unlinked=True)
The missing flows and technosphere processes are truly missing - they have no analogue in ecoinvent or our biosphere flow list. We can then add the missing activities and biosphere flows, and write the database. Here is a screenshot of the missing links; the full file can also be downloaded at https://bitbucket.org/cmutel/brightway2/src/tip/notebooks/files/?at=2.0 (click on "view raw" to download).
from IPython.display import Image
Image(filename='files/food-unlinked-selection.png')
sp.add_unlinked_flows_to_biosphere_database()
sp.add_unlinked_activities()
sp.statistics()
sp.write_database()