{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
A project by Dénes Csala and Sgouris Sgouridis at Lancaster University
\n", "This workbook will guide you through the mining, processing, formatting and saving the input data for the data analysis and visualizations.\n", "
\n", "This is document has been created using IPython Notebook in the Anaconda distribution and it can be edited and run in active mode by clicking download in top right corner of this page. The code is partitioned into sections, called cells. When you are using this workbook in active mode, double-click on a cell to edit it and then run using Ctrl + Enter
. Hitting Shift + Enter
runs the code and steps into the next cell, while Alt + Enter
runs the code and adds a new, empty cell. If you are running this notebook on a presonal computer, you will need a machine with at least 1GB of memory (2GB recommended) and a processor of 1GHz.
We start with importing the libraries that we are going to use into the Python workspace.
" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy as np, requests, zipfile, StringIO, pandas as pd, json, copy\n", "\n", "#suppres warnings\n", "import warnings\n", "warnings.simplefilter(action = \"ignore\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Afer importing the necessary libraries, we connect to the FAOSTAT database and define indicator paths. Alternatively, the *FAOSTAT* database is mirrored at the project website's data repository (FAOSTAT, has no directory listing access, just on a file-by-file basis). *FAOSTAT* offers the data in the format of zipped *CSV (comma-separated values)* files, and it has a separate file for each of their 17 domains. Should you choose to download the entire database to your local folder, please set the variablelocalpath
to True
and indicate this path in the masterpath
variable. If you choose to use the online resources directly, please set localpath
to False
and use the appropiate masterpath
(*FAOSTAT* or project website), as indicated below. Since the beginning of this project, *FAOSTAT* has changed their database access, this is reflected in the code below. It is recommended to use the alternative database mirror, tested to work with the code as of July 2015."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"masterpath = 'http://faostat3.fao.org/faostat-bulkdownloads/' #new FAOSTAT\n",
"#masterpath = 'http://faostat.fao.org/Portals/_Faostat/Downloads/zip_files/' #old FAOSTAT\n",
"#masterpath = 'https://dl.dropboxusercontent.com/u/531697/datarepo/Food-Energy/db/' #alternative for FAO database\n",
"\n",
"localpath=True\n",
"\n",
"if localpath:\n",
" #local path for downloaded FAO database, only for developer purposes\n",
" masterpath = 'E:/Dropbox (MIT)/Public/Food-Energy/db/' \n",
" savepath = 'E:/Dropbox (MIT)/Public/Food-Energy/json/'\n",
" \n",
"indicators=[] #we store indicator name strings in this string array - do not touch\n",
"indicators.append('Emissions_Agriculture_Energy_E_All_Data') #0\n",
"indicators.append('Inputs_Fertilizers_E_All_Data') #1\n",
"indicators.append('Resources_FertilizersArchive_E_All_Data') #2\n",
"indicators.append('Population_E_All_Data') #3\n",
"indicators.append('FoodBalanceSheets_E_All_Data') #4\n",
"indicators.append('Environment_Energy_E_All_Data') #5\n",
"indicators.append('Resources_Land_E_All_Data') #6\n",
"indicators.append('Trade_Crops_Livestock_E_All_Data') #7"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"After defining the indicator names, we define the function get_data(ind,cols,icols)
that loads the data from the respective *CSV* from inside the corresponding *ZIP* file into a *pandas* dataframe. This can take anywhere from a few seconds to several minutes, depending on your computer's performance. If you are running this notebook live and have access to paralell computing capabilites please turn them on at the *Clusters* tab of the main Ipython window. The syntax is slightly different for locally mirorred data and direct online access. By using compound indexing, we only load the relevant portions of the *CSV* files. The indicator oridnal (defined above) is passed with the argument ind
, the argument cols
defines which columns to load and icols
defines which columns to use as indices and their hierarchy. Make sure you run the cells above first, as the get_data()
function uses their output. The path
variable is an array that containes 3 strings, in the following order: url or directory path, zip file name, csv file name (in case of *FAO*, the two last entries happend to coincide). The elements
, items
and units
arguments are arrays of strings, providing different levels of data filtering, preserving order hierarchy. The new_get_data
is the updated version of the function to support the changed *FAOSTAT API*."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def get_data(path,cols=[],icols=[],elements=[],items=[],units=[]):\n",
" if localpath:\n",
" r = path[0]+path[1]+'.zip' #define name of zip file to read\n",
" z = zipfile.ZipFile(r) #open zip file for access\n",
" else:\n",
" r = requests.get(path[0]+path[1]+'.zip') #define URL path of zip file to read\n",
" z = zipfile.ZipFile(StringIO.StringIO(r.content)) #stream web content of zip file to read\n",
" if elements:\n",
" if items:\n",
" if units:\n",
" return pd.read_csv(z.open(path[2]+'.csv'),usecols=cols,index_col=icols)\\\n",
" .query('Element=='+repr(elements)+'and Item=='+repr(items)+'and Unit=='+repr(units))\\\n",
" .drop('Unit', axis=1)\n",
" else:\n",
" return pd.read_csv(z.open(path[2]+'.csv'),usecols=cols,index_col=icols)\\\n",
" .query('Element=='+repr(elements)+'and Item=='+repr(items))\n",
" else:\n",
" return pd.read_csv(z.open(path[2]+'.csv'),usecols=cols,index_col=icols)\\\n",
" .query('Element=='+repr(elements))\n",
" elif icols:\n",
" return pd.read_csv(z.open(path[2]+'.csv'),usecols=cols,index_col=icols)\n",
" elif cols:\n",
" return pd.read_csv(z.open(path[2]+'.csv'),usecols=cols)\n",
" else:\n",
" return pd.read_csv(z.open(path[2]+'.csv'))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def new_get_data(path,cols=[],icols=[],elements=[],items=[],units=[],years=[1961,2011]):\n",
" if localpath:\n",
" r = path[0]+path[1]+'.zip' #define name of zip file to read\n",
" z = zipfile.ZipFile(r) #open zip file for access\n",
" else:\n",
" r = requests.get(path[0]+path[1]+'.zip') #define URL path of zip file to read\n",
" z = zipfile.ZipFile(StringIO.StringIO(r.content)) #stream web content of zip file to read\n",
" yrrange=['Y'+repr(year) for year in range(years[0],years[1])] #keep only good years, drop fiscal years\n",
" if elements:\n",
" if items:\n",
" if units:\n",
" return pd.read_csv(z.open(path[2]+'.csv'),usecols=cols+yrrange,index_col=icols)\\\n",
" .query('Element=='+repr(elements)+'and Item=='+repr(items)+'and Unit=='+repr(units))\\\n",
" .drop('Unit', axis=1)\n",
" else:\n",
" return pd.read_csv(z.open(path[2]+'.csv'),usecols=cols+yrrange,index_col=icols)\\\n",
" .query('Element=='+repr(elements)+'and Item=='+repr(items))\n",
" else:\n",
" return pd.read_csv(z.open(path[2]+'.csv'),usecols=cols+yrrange,index_col=icols)\\\n",
" .query('Element=='+repr(elements))\n",
" elif icols:\n",
" return pd.read_csv(z.open(path[2]+'.csv'),usecols=cols+yrrange,index_col=icols)\n",
" elif cols:\n",
" return pd.read_csv(z.open(path[2]+'.csv'),usecols=cols+yrrange)\n",
" else:\n",
" return pd.read_csv(z.open(path[2]+'.csv'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For this work, we will use the *Food Balance Sheets*, the *Emissions Agriculture Energy*, the *Fertilizers* and *Fertilizers Archive* and *Population* and *Import* modules of *FAOSTAT*. Prior to processing into a *pandas* dataframe with the above get_data
or new_get_data
function, we will refer to the data contained in the above modules as *datasets* (*Food Balance Sheets, Emissions Agriculture Energy, Fertilizers, Fertilizers Archive, Population, Import*). After processing and cleaning up, we will refer to them as *dataframes* (balance, energy, fertilizers, population, imports
) and they will correspond to the actual *pandas dataframe* objects with idem names in the *Python* workspace. \n",
"\n",
"To optimize for speed, when loading the datasets into the dataframes, we will filter and only save the entries that are needed for the study, for each of the datasets. This is defined by elements
and items
arguments. On top of that, we use further customizations for certain datasets. The entries of the energy
dataframe are provided both in units of *TJ* and *GWh*, but we will only use one of them. After filtering the dataframe for the selected unit, the entries of *Unit* colum can be dropped to conserve memory. For the balance
dataframe, all *Item* entries are needed, hence no filtering is done on this column. \n",
"\n",
"energy
dataframe. Emissions Agriculture Energy is the second largest of the datasets, and processing can take anywhere from a few seconds in case of locally mirrored data, for up to 5 minutes or more in case of direct online access. (The balance
dataframe will be the largest. It needs at least 1GB of memory. We will leave it to load last). We display only the first 5 items of the pandas dataframe returned by the get_data()
function by calling head().
"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Value 49369\n",
"dtype: int64\n"
]
},
{
"data": {
"text/html": [
"\n", " | \n", " | \n", " | \n", " | Value | \n", "
---|---|---|---|---|
Country | \n", "Year | \n", "Element | \n", "Item | \n", "\n", " |
Afghanistan | \n", "1970 | \n", "Consumption in Agriculture | \n", "Electricity | \n", "43.2 | \n", "
1971 | \n", "Consumption in Agriculture | \n", "Electricity | \n", "46.8 | \n", "|
1972 | \n", "Consumption in Agriculture | \n", "Electricity | \n", "57.6 | \n", "|
1973 | \n", "Consumption in Agriculture | \n", "Electricity | \n", "57.6 | \n", "|
1974 | \n", "Consumption in Agriculture | \n", "Electricity | \n", "68.4 | \n", "
energy
dataframe. We are interested in categorizing the food energy flows based on their destinations, which is depicted under the *Element* or *Item* column, depending on the dataframe. In order to have a well-manageable *JSON* output, we will always index the data after countries and years first. Using hierarchical indexing over *Country, Year* and *Element* and/or *Item*, we obtain the reduced dataframes that contain the values of interest to us in the *Value* column. \n",
"\n",
"In the following cell, for demonstration purposes, we will display the data for *Brazil*, for the *earliest* available year. The *pandas* function xs
creates a cross-section of a dataframe, indexed after the first argument (list of strings of indices) and with the hiercharchy defined by the second argument (list of integers *level*)."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"\n", " | \n", " | Value | \n", "
---|---|---|
Element | \n", "Item | \n", "\n", " |
Consumption in Agriculture | \n", "Gas-Diesel oil | \n", "96836.0 | \n", "
Motor Gasoline | \n", "0.0 | \n", "|
Natural gas (including LNG) | \n", "0.0 | \n", "|
Liquefied petroleum gas (LPG) | \n", "0.0 | \n", "|
Fuel oil | \n", "4686.4 | \n", "|
Electricity | \n", "7336.8 | \n", "|
Gas-diesel oils used in fisheries | \n", "0.0 | \n", "|
Fuel oil used in fisheries | \n", "0.0 | \n", "|
Energy for power irrigation | \n", "0.0 | \n", "
fertilizer
dataframes (fertilizers1
, fertilizers2
), the units are implicit (*tonnes*) and hence are not loaded to conserve memory."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"\n", " | \n", " | Value | \n", "
---|---|---|
Element | \n", "Item | \n", "\n", " |
Consumption in nutrients | \n", "Nitrogen Fertilizers (N total nutrients) | \n", "1834733 | \n", "
Phosphate Fertilizers (P205 total nutrients) | \n", "2634552 | \n", "|
Potash Fertilizers (K20 total nutrients) | \n", "2962910 | \n", "
\n", " | \n", " | Value | \n", "
---|---|---|
Element | \n", "Item | \n", "\n", " |
Consumption | \n", "Nitrogenous fertilizers | \n", "55064 | \n", "
Phosphate fertilizers | \n", "144213 | \n", "|
Potash fertilizers | \n", "70727 | \n", "
In order to estimate labor energy, we create the population
dataframe from the Population module of FAOSTAT.
\n", " | \n", " | Value | \n", "
---|---|---|
Element | \n", "Item | \n", "\n", " |
Total Population - Both sexes | \n", "Population - Est. & Proj. | \n", "121740 | \n", "
Total economically active population in Agr | \n", "Population - Est. & Proj. | \n", "16345 | \n", "
balance
dataframe, the categories of interest are stored in the *Element* column. We also need to import the *ItemCode* column for categorization purposes. Hence the indexing order changes to 0,3,2. Just like in for the case of fertilizers
, the units are implicit (*1000 tonnes*) and hence are not loaded to conserve memory. Due to the size of the balance
dataframe, execution of the following cell can take several minutes to complete."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false,
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"\n", " | ItemCode | \n", "Value | \n", "
---|---|---|
Element | \n", "\n", " | \n", " |
Production | \n", "2514 | \n", "9036.00 | \n", "
Import Quantity | \n", "2514 | \n", "6.00 | \n", "
Stock Variation | \n", "2514 | \n", "0.00 | \n", "
Export Quantity | \n", "2514 | \n", "4.00 | \n", "
Feed | \n", "2514 | \n", "5961.00 | \n", "
Seed | \n", "2514 | \n", "184.00 | \n", "
Waste | \n", "2514 | \n", "904.00 | \n", "
Processing | \n", "2514 | \n", "4.00 | \n", "
Food | \n", "2514 | \n", "1985.00 | \n", "
Food supply quantity (kg/capita/yr) | \n", "2514 | \n", "26.47 | \n", "
Food supply (kcal/capita/day) | \n", "2514 | \n", "227.00 | \n", "
imports
dataframe, the categories of interest are stored in the *Element* column. Just like the balance
dataframe, execution of the following cell can take several minutes to complete."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"\n", " | \n", " | Value | \n", "
---|---|---|
Element | \n", "Item | \n", "\n", " |
Import Value | \n", "Agricult.Products,Total | \n", "2470870 | \n", "
\n", " | \n", " | \n", " | Value | \n", "
---|---|---|---|
Year | \n", "Element | \n", "Item | \n", "\n", " |
1961 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "3752 | \n", "
1962 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "4065 | \n", "
1963 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "4245 | \n", "
1964 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "4459 | \n", "
1965 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "4815 | \n", "
1966 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "11588 | \n", "
1967 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "13642 | \n", "
1968 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "22958 | \n", "
1969 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "22221 | \n", "
1970 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "31980 | \n", "
1971 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "36035 | \n", "
1972 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "52867 | \n", "
1973 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "98894 | \n", "
1974 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "239046 | \n", "
1975 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "297260 | \n", "
1976 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "370719 | \n", "
1977 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "432747 | \n", "
1978 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "594019 | \n", "
1979 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "879103 | \n", "
1980 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1077400 | \n", "
1981 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1148590 | \n", "
1982 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1044390 | \n", "
1983 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1018400 | \n", "
1984 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1100640 | \n", "
1985 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1118290 | \n", "
1986 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1216010 | \n", "
1987 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1285020 | \n", "
1988 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1352900 | \n", "
1989 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1762340 | \n", "
1990 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1693330 | \n", "
1991 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1747280 | \n", "
1992 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1906260 | \n", "
1993 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "1739830 | \n", "
1994 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "2146840 | \n", "
1995 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "2459460 | \n", "
1996 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "2643060 | \n", "
1997 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "2245120 | \n", "
1998 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "2443370 | \n", "
1999 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "2642640 | \n", "
2000 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "2693230 | \n", "
2001 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "3112450 | \n", "
2002 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "3767700 | \n", "
2003 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "4296530 | \n", "
2004 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "4941250 | \n", "
2005 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "3730570 | \n", "
2006 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "7164150 | \n", "
2007 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "8161290 | \n", "
2008 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "10926500 | \n", "
2009 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "10489900 | \n", "
2010 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "11913800 | \n", "
2011 | \n", "Import Value | \n", "Agricult.Products,Total | \n", "14018000 | \n", "
In the following section we convert the dataframes defined above into JSON format that can be read by the D3.js javascript framework for web visualization. Aside form the data manipulation, we also compute and add additional information such as caloric values and food category sums into the JSON files. The Sankey plugin of D3.js requires the input JSONs to be in a very specific format. All of them have to inclue at least the following key-value pairs:
\n", "nodes
\n",
" name
: name of the node (the order or these entries (groupdict
) automatically assigns an index (count
) to the names)links
\n",
" source
: the index of the source nodetarget
: the index of the target nodevalue
: value of the linknodes
\n",
" color
: color of the nodelayer
: sets a fixed node x-index from the leftvalue
: sets a fixed node heightsupply
) or secondary flow values for a different type of category (stored under the key prod
). As a first step, we define the function add_to_json(i,k,source,target,value,prod,supply)
which will take numeric entries and create the JSON-like structure presented above. The conversion is made easy using Python dictionaries. The argument i
defines the detail level at which we are passing the data and it is one of the following:\n",
"k
corresponds to the Python dictionary in the global variable data[i][k]
to which the data will be written to. We will generate the following datasets:\n",
"data[i][0]
variable - includes food-system and crop residuesdata[i][1]
variable - includes agri-system and food trade and scondary food productsdata[i][2]
variable - includes primary cropsdata[i][3]
variablefor
cycles that loop over all countries and years. All code parts take as arguments country
and year
. In the following we present the code parts one by one. Throughout code development it has been assumed that the order in which the *IPython cells* corresponding to the code parts defined below are run is preserved. Therefore we define the main
procedure in *Section 3*, after everything else has been defined, including the save data
procedure in *Section 2.6*. \n",
"\n",
"supergroup
array since the *FAOSTAT* entries in the *Food Balance Sheets* dataset are already aggregated, such as *Apples & Products or Wheat & Products*. We will refer to individual entries of the balance
dataframe as *food items* or *food item groups* bearing in mind that these do not represent individual crop types, but an already aggregated category, as per the FAOSTAT handbook. However, it is possible to retrive the production data for individual crops such as *Apples* or *Wheat Bran* from the *Production Crops* database by calling get_data(10)
, but this is outside the scope of this work and we will exclusively use the balance
dataframe. \n",
"\n",
"To create our own classification with a comfortable detail level, as well as to doublecheck the *FAOSTAT* groupings, we use the *FAOSTAT* item codes, as per their handbook. Likewise, within a for
loop we define the corresponding *supergroups* for all items for all abstraction levels and where applicable, also their *parent* groups: secondary food items have their origin in another food item, called a *parent*, such as *Feed* for *Animal Products* or *Processing* for *Oils*. This information will be stored in the supergroup
and parent
array variables, accesible globally."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def food_groups(country, year):\n",
" \n",
" ###############################################################################################\n",
" ###### FOOD PART - define food groups ######\n",
" ###############################################################################################\n",
" \n",
" # associate food items to their respective groups\n",
"\n",
" global supergroup #supergroup to which the food item group belongs to, \n",
" #i.e. Fruits is the supergroup for Apples & Products\n",
" global parent #certain food items have their origin in another food item, called a parent\n",
" #i.e. Feed is the parent for Animal Products and Processing is the parent for Oils\n",
" global gross #this is necessary for recording crop residues on the gross energy details level\n",
" #precentage of crop that is unused but has energy residues remaining inside it, husk\n",
" #http://www.sciencedirect.com/science/article/pii/S0160412004001564\n",
" #crop residue average energy content for burning 300kcal/100g\n",
" #another possibility is to estimate from emissions and back-calculate\n",
" #energy content from carbon\n",
" #http://www.gutenberg.org/files/22657/22657-h/chapters/value.html#equn_18\n",
"\n",
" for element in elements1+elements2:\n",
" for i in balance.xs([country,year,element], level=[0,1,3]).T.iteritems():\n",
" fooditem = i[0] #choose column in which food item names are stored, might need to change it\n",
" if \"+\" in fooditem: #simplify food names for the sake of visualization\n",
" fooditem=fooditem[0:fooditem.find(\"+\")-1]\n",
" if \"(\" in fooditem:\n",
" fooditem=fooditem[0:fooditem.find(\"(\")-1]\n",
" if \"and products\" in fooditem:\n",
" fooditem=fooditem[0:fooditem.find(\"and products\")-1]\n",
"\n",
" # if fooditem has not been encountered yet, assing its properties\n",
" if fooditem not in supergroup[3].keys():\n",
" index = i[1][0] #choose column in which food group codes are stored, might need to change it\n",
" parent[fooditem]='None'\n",
" supergroup[3][fooditem]=fooditem #default supergroup is self\n",
" supergroup[0][fooditem]='Fruits, Roots & Vegetables' \n",
" for i in range (1,3): #assign default supergroup to all aggregate food items\n",
" supergroup[i][fooditem]='Others'\n",
" if ((2511<=index<=2659) | (index==2745) | (index==2805) | (index==2899) | (index==2912)):\n",
" if ((2511<=index<=2520) | (index==2805)):\n",
" supergroup[2][fooditem] = 'Cereals - Excluding Beer'\n",
" supergroup[1][fooditem] = 'Cereals'\n",
" supergroup[0][fooditem] = 'Cereals'\n",
" parent[fooditem] = 'None'\n",
" gross[fooditem] =gross[supergroup[0][fooditem]]\\\n",
" =gross[supergroup[1][fooditem]]\\\n",
" =gross[supergroup[2][fooditem]] = 1.0\n",
" elif (2531<=index<=2535):\n",
" supergroup[2][fooditem] = 'Starchy Roots'\n",
" supergroup[1][fooditem] = 'Starchy Roots'\n",
" supergroup[0][fooditem] = 'Fruits, Roots & Vegetables'\n",
" parent[fooditem] = 'None'\n",
" gross[fooditem] =gross[supergroup[0][fooditem]]\\\n",
" =gross[supergroup[1][fooditem]]\\\n",
" =gross[supergroup[2][fooditem]] = 0.25\n",
" elif (2536<=index<=2537):\n",
" supergroup[2][fooditem] = 'Sugar Crops'\n",
" supergroup[1][fooditem] = 'Sugar Crops'\n",
" supergroup[0][fooditem] = 'Sugar Crops'\n",
" parent[fooditem] = 'None'\n",
" gross[fooditem] =gross[supergroup[0][fooditem]]\\\n",
" =gross[supergroup[1][fooditem]]\\\n",
" =gross[supergroup[2][fooditem]] = 0.2\n",
" elif ((2541<=index<=2543)|(index==2745)):\n",
" supergroup[2][fooditem] = 'Sugar & Sweeteners'\n",
" supergroup[1][fooditem] = 'Sugar'\n",
" supergroup[0][fooditem] = 'Sugar'\n",
" parent[fooditem] = 'Processing'\n",
" elif (2546<=index<=2549):\n",
" supergroup[2][fooditem] = 'Pulses'\n",
" supergroup[1][fooditem] = 'Fruits & Vegetables'\n",
" supergroup[0][fooditem] = 'Fruits, Roots & Vegetables'\n",
" parent[fooditem] = 'None'\n",
" gross[fooditem] =gross[supergroup[0][fooditem]]\\\n",
" =gross[supergroup[1][fooditem]]\\\n",
" =gross[supergroup[2][fooditem]] = 0.5#1.0\n",
" elif (2555<=index<=2570):\n",
" supergroup[2][fooditem] = 'Oilcrops'\n",
" supergroup[1][fooditem] = 'Oilcrops'\n",
" supergroup[0][fooditem] = 'Oilcrops'\n",
" parent[fooditem] = 'None'\n",
" gross[fooditem] =gross[supergroup[0][fooditem]]\\\n",
" =gross[supergroup[1][fooditem]]\\\n",
" =gross[supergroup[2][fooditem]] = 0.5#1.0\n",
" elif (2571<=index<=2586):\n",
" supergroup[2][fooditem] = 'Vegetable Oils'\n",
" supergroup[1][fooditem] = 'Vegetable Oils'\n",
" supergroup[0][fooditem] = 'Vegetable Oils'\n",
" parent[fooditem] = 'Processing'\n",
" elif (2601<=index<=2605):\n",
" supergroup[2][fooditem] = 'Vegetables'\n",
" supergroup[1][fooditem] = 'Fruits & Vegetables'\n",
" supergroup[0][fooditem] = 'Fruits, Roots & Vegetables'\n",
" parent[fooditem] = 'None'\n",
" gross[fooditem] =gross[supergroup[0][fooditem]]\\\n",
" =gross[supergroup[1][fooditem]]\\\n",
" =gross[supergroup[2][fooditem]] = 0.5#1.0\n",
" elif (2611<=index<=2625):\n",
" supergroup[2][fooditem] = 'Fruits - Excluding Wine'\n",
" supergroup[1][fooditem] = 'Fruits & Vegetables'\n",
" supergroup[0][fooditem] = 'Fruits, Roots & Vegetables'\n",
" parent[fooditem] = 'None'\n",
" elif (2630<=index<=2635):\n",
" supergroup[2][fooditem] = 'Stimulants'\n",
" supergroup[1][fooditem] = 'Others'\n",
" supergroup[0][fooditem] = 'Fruits, Roots & Vegetables'\n",
" parent[fooditem] = 'None'\n",
" elif (2640<=index<=2645):\n",
" supergroup[2][fooditem] = 'Spices'\n",
" supergroup[1][fooditem] = 'Others'\n",
" supergroup[0][fooditem] = 'Fruits, Roots & Vegetables'\n",
" parent[fooditem] = 'None'\n",
" elif (2655<=index<=2659):\n",
" supergroup[2][fooditem] = 'Alcoholic Beverages'\n",
" supergroup[1][fooditem] = 'Other Processed'\n",
" supergroup[0][fooditem] = 'Other Processed'\n",
" parent[fooditem] = 'Processing'\n",
" elif (index==2899):\n",
" supergroup[2][fooditem] = 'Miscellaneous'\n",
" supergroup[1][fooditem] = 'Others'\n",
" supergroup[0][fooditem] = 'Fruits, Roots & Vegetables'\n",
" parent[fooditem] = 'None'\n",
" elif (index==2912):\n",
" supergroup[2][fooditem] = 'Treenuts'\n",
" supergroup[1][fooditem] = 'Fruits & Vegetables'\n",
" supergroup[0][fooditem] = 'Fruits, Roots & Vegetables'\n",
" parent[fooditem] = 'None'\n",
"\n",
" elif ((2731<=index<=2782) | (index==2945)| (index==2948) | (index==2949) | (index==2961)):\n",
" if (2731<=index<=2736):\n",
" supergroup[2][fooditem] = 'Meat'\n",
" supergroup[1][fooditem] = 'Animal Products'\n",
" supergroup[0][fooditem] = 'Animal Products'\n",
" parent[fooditem] = 'Feed'\n",
" elif (2737<=index<=2743):\n",
" supergroup[2][fooditem] = 'Animal Fats' \n",
" supergroup[1][fooditem] = 'Other Processed' \n",
" supergroup[0][fooditem] = 'Other Processed' \n",
" parent[fooditem] = 'Processing'\n",
" elif (index==2744):\n",
" supergroup[2][fooditem] = 'Eggs'\n",
" supergroup[1][fooditem] = 'Animal Products'\n",
" supergroup[0][fooditem] = 'Animal Products'\n",
" parent[fooditem] = 'Feed'\n",
" elif (2761<=index<=2768):\n",
" supergroup[2][fooditem] = 'Fish, Seafood'\n",
" supergroup[1][fooditem] = 'Aquatic Products'\n",
" supergroup[0][fooditem] = 'Aquatic Products'\n",
" parent[fooditem] = 'Feed'\n",
" elif ((2769<=index<=2775)|(index==2961)):\n",
" supergroup[2][fooditem] = 'Aquatic Products, Other'\n",
" supergroup[1][fooditem] = 'Aquatic Products'\n",
" supergroup[0][fooditem] = 'Aquatic Products'\n",
" parent[fooditem] = 'Feed'\n",
" elif (2781<=index<=2782):\n",
" supergroup[2][fooditem] = 'Animal Fats'\n",
" supergroup[1][fooditem] = 'Other Processed'\n",
" supergroup[0][fooditem] = 'Other Processed'\n",
" parent[fooditem] = 'Processing'\n",
" elif (index==2948):\n",
" supergroup[2][fooditem] = 'Milk - Excluding Butter'\n",
" supergroup[1][fooditem] = 'Animal Products'\n",
" supergroup[0][fooditem] = 'Animal Products'\n",
" parent[fooditem] = 'Feed'\n",
"\n",
" #section for variables which only have a secondary flow (from Feed or Processing)\n",
" #currently only Palm Oil because it only belongs to Processing, no other categories\n",
" #need to create (practically non-food) super crop flow\n",
" supergroup[0][\"Oil Palm\"]=supergroup[1][\"Oil Palm\"]=supergroup[2][\"Oil Palm\"]='Oilcrops'\n",
" supergroup[3][\"Oil Palm\"]='Oil Palm'\n",
" parent[\"Oil Palm\"]='None'\n",
"\n",
" #create supergroups of supergroups\n",
" supergroup[2][supergroup[2][fooditem]] = supergroup[2][fooditem]\n",
" supergroup[2][supergroup[1][fooditem]] = supergroup[2][fooditem]\n",
" supergroup[2][supergroup[0][fooditem]] = supergroup[2][fooditem]\n",
" supergroup[1][supergroup[2][fooditem]] = supergroup[1][fooditem]\n",
" supergroup[1][supergroup[1][fooditem]] = supergroup[1][fooditem]\n",
" supergroup[1][supergroup[0][fooditem]] = supergroup[1][fooditem]\n",
" supergroup[0][supergroup[2][fooditem]] = supergroup[0][fooditem]\n",
" supergroup[0][supergroup[1][fooditem]] = supergroup[0][fooditem]\n",
" supergroup[0][supergroup[0][fooditem]] = supergroup[0][fooditem]\n",
" \n",
" #create parents of supergroups\n",
" parent[supergroup[0][fooditem]]=parent[supergroup[1][fooditem]]=\\\n",
" parent[supergroup[2][fooditem]]=parent[fooditem]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Before every section, we conduct a data profiling - this meas we interpolate the missing values of the dataframe using data from the neighboring countries or global values. This is the food_profiling
, which eliminates *0* and *NaN* values from the dataframes. Food values are an exception compared to the rest of energy data as they are not interpolated."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def food_profiling(country):\n",
" y={}\n",
" \n",
" for i in balance.loc[country].T.iteritems(): #make just one call, filter to country, superfast\n",
" foodvalue=i[1][0] #choose column in which food item values are stored\n",
" if (~np.isnan(foodvalue)&(foodvalue!=0)):\n",
" year = int(i[0][0]) #choose column in which years are stored\n",
" element = i[0][2] #choose column in which element names are stored\n",
" fooditem = i[0][1] #choose column in which food item names are stored, might need to change it\n",
" if \"+\" in fooditem: #simplify food names for the sake of visualization, remove +,(),'and products'\n",
" fooditem=fooditem[0:fooditem.find(\"+\")-1]\n",
" if \"(\" in fooditem:\n",
" fooditem=fooditem[0:fooditem.find(\"(\")-1]\n",
" if \"and products\" in fooditem:\n",
" fooditem=fooditem[0:fooditem.find(\"and products\")-1]\n",
" if element not in y: y[element]={}\n",
" if year not in y[element]: y[element][year]={}\n",
" y[element][year].update({fooditem:foodvalue})\n",
"\n",
" #no interpolation for indiviudal food items \n",
" return y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"food_cal
returns caloric value for food items and their supergroups on all detail levels, using the per capita food supply information in *kcal/day/person* and *kg/year/person* from the balance
dataframe. It starts by filtering the dataframe to the country and year of interest and then extracts the values under query using an auxiliary array of length 2 counter
. If an exact match is not found in either of dataframe columns (energy or supply values), then the supergroup value is attributed. E.g. if is there is no data for *Maize* in either of the columns, then the values of the aggregate group *Cereals* are attrbiuted, trying for the smaller supergroup (detail level 2) first. If data is completely non-existent for an entire supergroup for one country, then global values are used. In the very rare case that even global values do not exist, then a standard *100kcal/100g* caloric value is attributed to the food item. The function returns the *dictionary* foodcalorie
which has the food items as *keys* and their respective caloric values as entries."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def food_cal_profiling(country):\n",
" \n",
" ###############################################################################################\n",
" ###### FOOD PART - Calculate caloric values of food items ######\n",
" ###############################################################################################\n",
" \n",
" #extract food item caloric values\n",
" foodcalorie={}\n",
" \n",
" if (set(food_extended.keys()).intersection(set(elements2))==set(elements2)):\n",
" for year in food_extended[elements2[0]].keys():\n",
" if year in food_extended[elements2[1]].keys():\n",
" for fooditem in food_extended[elements2[0]][year].keys():\n",
" if fooditem in food_extended[elements2[1]][year].keys():\n",
" if fooditem not in {'Grand Total'}:\n",
" if fooditem not in foodcalorie: foodcalorie[fooditem]={}\n",
" energy = food_extended[elements2[0]][year][fooditem]\n",
" weight = food_extended[elements2[1]][year][fooditem]\n",
" foodcalorie[fooditem].update({year:[100*energy/(weight*1000/365.25)]})\n",
" #kcal / 100g : energy / supply, need to transfrom from kg/year/capita to g/day/capita\n",
" for k in range(3):\n",
" if supergroup[k][fooditem] not in foodcalorie: foodcalorie[supergroup[k][fooditem]]={}\n",
" if year not in foodcalorie[supergroup[k][fooditem]]:\n",
" foodcalorie[supergroup[k][fooditem]][year]=[]\n",
" foodcalorie[supergroup[k][fooditem]][year].append(100*energy/(weight*1000/365.25))\n",
" \n",
" #create supergroup values\n",
" for i in foodcalorie.keys():\n",
" for j in foodcalorie[i].keys():\n",
" foodcalorie[i][j]=np.median(foodcalorie[i][j])\n",
"\n",
" return foodcalorie"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"food_part
function extract food item flows from the balance
dataframe and saves them into the global variable data
using the add_to_json
function, effectively creating the core structure of the *FEF* *Sankey* diagram. The function iteratively adds the flows by filtering the dataframe after the entries of elements
string array, which contains the designations of the nodes (such as *Feed* or *Processing*) and looping through it item-by-item. The core logic of the food_part
function follows the following sequence:\n",
"\n",
"- Access and extract food item name and value in *1000 tonnes*.\n",
"- Using the specific energy content from the foodcalorie
variable, calculate energy values (and subsequently convert to *TWh*).\n",
"- Populate item dictionary isum
with numeric entries, for all detail levels.\n",
"- After all food items have been parsed, create links from them to the element
(i.e. node) under iteration. \n",
"\n",
"This will create the links for the highest detail level where the supergroups will only contain the food items tehmselves. In the next section of the function, aggregated and special links are added:\n",
"\n",
"- Supergroup item aggregations are calculated and saved in the supersum
variable for all remaining detail levels.\n",
"- Aggregations are also calculated for non-primary food items (i.e. those with a *parent*) and the parent-to-fooditem links are added.\n",
"- Eventually special links are dealt with:\n",
" - Crop residues (which only exist for a certain detail level)\n",
" - Processed foods of animal origin (which would have two *parents*, both *Processed* and *Feed*)\n",
" - Oil palm (Only the end product *Palm Oil* is included in the *FAO* database, with oil palm not being a food item, but necessary to maintain the energy balance of the model). \n",
" \n",
"Finally the share of primary crops is calculated and saved in the global variable share
for all detail levels, necessary for the proportionate distribution of fossil inputs."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def food_part(country, year):\n",
" \n",
" ###############################################################################################\n",
" ###### FOOD PART - Extract supply data and calculate energy data ######\n",
" ###############################################################################################\n",
"\n",
" global foodinput #summation variables for EROEI calculation\n",
" global foodoutput\n",
"\n",
" #extract supply data and calculate energy data\n",
" global data\n",
" global supersum\n",
"\n",
" #auxiliary dictionaries for use, with accurate preassigned dimensions\n",
" #dictionary to record item parent sums\n",
" helperdict = [[{} for k in range(m)] for i in range(n)] \n",
" palmsum = 0\n",
" \n",
" for element in elements1:\n",
" \n",
" #discard world level imports and exports. they should balance out.\n",
" if ((country==\"World\") & (element in {\"Import Quantity\", \"Export Quantity\"})):\n",
" continue\n",
"\n",
" #dictionary to keep track of item sums in case of aggregations, based on the supergroup\n",
" isum=[[{} for i in range(m)] for j in range(n)] \n",
"\n",
" if element in food_extended.keys():\n",
" if year in food_extended[element].keys():\n",
" for fooditem in food_extended[element][year].keys():\n",
" \n",
" foodvalue = food_extended[element][year][fooditem]\n",
" \n",
" #try to set default caloric value equal to global values\n",
" try: foodcal=food_cal_world[fooditem][year]\n",
" #fooditem was not found, set default caloric value, necessary to handle exceptions\n",
" except: foodcal=100 \n",
" #check if caloric value has been obtained for fooditem, attempt to get from supergroup otherwise\n",
" if fooditem in foodcalorie.keys():\n",
" if year in foodcalorie[fooditem].keys():\n",
" foodcal=foodcalorie[fooditem][year]\n",
" else:\n",
" if supergroup[2][fooditem] in foodcalorie.keys():\n",
" if year in foodcalorie[supergroup[2][fooditem]].keys():\n",
" foodcal=foodcalorie[supergroup[2][fooditem]][year]\n",
" elif supergroup[1][fooditem] in foodcalorie.keys():\n",
" if year in foodcalorie[supergroup[1][fooditem]].keys():\n",
" foodcal=foodcalorie[supergroup[1][fooditem]][year]\n",
" elif supergroup[0][fooditem] in foodcalorie.keys():\n",
" if year in foodcalorie[supergroup[0][fooditem]].keys():\n",
" foodcal=foodcalorie[supergroup[0][fooditem]][year]\n",
"\n",
" energyvalue=foodvalue*foodcal*0.00116222222/100\n",
" #TWh = 1000tons * kcal/100g # 10^9) /100g * 0.00116222222 kwh/kcal *10^-9 TWh/kWh\n",
"\n",
" #define sequence of variable assignemt over k axis\n",
" sequence=[]\n",
" for k in range(m-1): sequence.append(energyvalue)\n",
" sequence.append(foodvalue)\n",
"\n",
" #sum all links going into food for small Sankey EROEI representation\n",
" if (element==\"Food\"):\n",
" for k in range(m-1):\n",
" if (k!=2): foodoutput[\"Food\"][k]+=sequence[k]\n",
" if (element==\"Export Quantity\"):\n",
" for k in range(m-1):\n",
" if (k!=2): foodoutput[\"Export\"][k]+=sequence[k]\n",
" if (element==\"Import Quantity\"):\n",
" for k in range(m):\n",
" #foodinput[k]+=sequence[k] #old, discounted version\n",
" foodimport[k]+=sequence[k]\n",
" #auxiliary variable for Palm Oil processing\n",
" if fooditem==\"Palm Oil\":\n",
" palmsum=energyvalue\n",
" if (element==\"Stock Variation\"):\n",
" if (sequence[0]<0): #decide whether is a stock deposit or withdrawal\n",
" for k in range(m-1): #food weight handled sepparately\n",
" if (k!=2): foodoutput[\"Stock Deposit\"][k]+=-sequence[k]\n",
" else:\n",
" for k in range(m-1): #food weight handled sepparately\n",
" if (k!=2): \n",
" foodinput[k]+=sequence[k]\n",
" foodinput2[\"Stock Draw\"][k]+=sequence[k]\n",
" if (element==\"Other uses\"):\n",
" for k in range(m-1):\n",
" if (k!=2): foodoutput[\"Biofuels & Other\"][k]+=sequence[k]\n",
" if (element==\"Production\"):\n",
" if parent[fooditem]==\"None\":\n",
" foodoutput[\"Food\"][2]+=sequence[2]\n",
" foodoutput[\"Food\"][m-1]+=sequence[m-1]\n",
" \n",
" #for WROWI - Seeds are input\n",
" if (element==\"Seed\"): \n",
" if (parent[fooditem]==\"None\"):\n",
" foodinput[m-1]+=sequence[m-1]\n",
" foodinput2[\"Seed\"][m-1]+=sequence[m-1]\n",
" \n",
" #save food item values for detail levels 1-3 (level 4 is currently not in use)\n",
" isum = food_isum(country,year,element,fooditem,sequence,isum)\n",
"\n",
" #create links \n",
" food_links(country,year,element,isum)\n",
"\n",
" #create aggregate values for all items detail levels 1-4\n",
" helperdict = food_aggregate(country,year,element,isum,helperdict)\n",
"\n",
" #create parent links\n",
" parentsum = food_parent(country,year,helperdict)\n",
"\n",
" #create special links\n",
"\n",
" #add extra links needed for processed foods of animal origin\n",
" food_animal(country,year,parentsum)\n",
" #add links for crop residues\n",
" food_residue(country,year) \n",
" #Palm Oil only belongs to Processing, no other categories\n",
" #Create Oil Palm (practically non-food) parent crop flow \n",
" food_palm(country,year,palmsum)\n",
"\n",
" #calculate crops share for energy input distribution\n",
" food_share(country,year)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"food_isum
progressively (has itself as an argument) creates a *dictionary* that eventually will contain food item names as *keys* and their values as entries. This process is repeatd for every element
. Food item names are passed through the fooditem
argument, whereas their values in the sequence
variable of length *m*, corresponding to the number of different datasets the user wants to create. Currently *m = 4* and it contains food item energy values on indices *0,1,2* and weight values on the last index position. Based on the element
, some modifications are made:\n",
"\n",
"- Import becomes a source not a sink node.\n",
"- Stock Variation is treated either as sink or source, based on its polarity. The node name is also modified correspondigly."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def food_isum(country,year,element,fooditem,sequence,isum):\n",
"#save fooditem values for detail levels 1-3 (level 4 is currently not in use) - was put back in\n",
" \n",
" for i in range(n): #save food item values over different groups\n",
" #save components for the piechart breakdown (isum)\n",
" for k in range(m):\n",
" if (element==\"Import Quantity\"): \n",
" if parent[fooditem]!=\"None\":\n",
" target=parent[fooditem]\n",
" else: target=supergroup[i][fooditem]\n",
" target=\"Import\"+target\n",
" elif (element==\"Stock Variation\"): \n",
" if sequence[k]<0:\n",
" target=\"Stock Deposit\"+supergroup[i][fooditem]\n",
" else:\n",
" if parent[fooditem]!=\"None\":\n",
" target=parent[fooditem]\n",
" else: target=supergroup[i][fooditem]\n",
" target=\"Stock Draw\"+target\n",
" else: target=supergroup[i][fooditem]\n",
" if target in isum[i][k].keys():\n",
" isum[i][k][target].append({\"l\":fooditem, \"v\":abs(sequence[k])})\n",
" else:\n",
" isum[i][k][target]=[{\"l\":fooditem, \"v\":abs(sequence[k])}]\n",
" \n",
" return isum"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"food_links
function iterates through the entries of the isum
dictionary (i.e. food items for which data exists and it has been added for certain country, for a certain year) and saves them in the global data
variable by invoking the add_to_json
function. In some cases, node names (given by the element
argument) are altered for clarity and better legibility."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def food_links(country,year,element,isum):\n",
"#create links\n",
" for i in range(n):\n",
" for k in range(m):\n",
" for j in isum[i][k].keys(): #second index for isum can be any, keys dont change over k\n",
" source=j\n",
" if (element==\"Seed\"): #replace 'Seed' group with self-loops\n",
" if ((k==m-1)&(parent[j]==\"None\")): #except in weight view \n",
" target=element\n",
" else:\n",
" target=j\n",
" elif (element==\"Other uses\"): #rename 'Other uses' group to Biofuels & Other\n",
" target=\"Biofuels & Other\"\n",
" elif (element==\"Export Quantity\"): #rename 'Export Quantity' group to Export\n",
" target=\"Export\"\n",
" elif (\"Import\" in j): #rename 'Import Quantity' group to Import and reverse links\n",
" source=\"Import\"\n",
" target=j[j.find(\"Import\")+6:len(j)]\n",
" elif (\"Stock Draw\" in j): #identify 'Stock Draw' and reverse links\n",
" source=\"Stock Draw\"\n",
" target=j[j.find(\"Stock Draw\")+10:len(j)]\n",
" elif (\"Stock Deposit\" in j): #identify 'Stock Deposit' links\n",
" target=\"Stock Deposit\"\n",
" source=j[j.find(\"Stock Deposit\")+13:len(j)]\n",
" else:\n",
" target=element\n",
" if (k==m-1): c=0\n",
" else: c=m-1 \n",
" if (element!=\"Production\"):\n",
" if (k!=m-2): #if not only agri-system\n",
" add_to_json(i,k,source,target,sum([w['v'] for w in isum[i][k][j]]),\\\n",
" sum([w['v'] for w in isum[i][c][j]]),isum[i][k][j])\n",
" #Production\n",
" elif (k==m-2): #if only agri-system\n",
" if (parent[j]==\"None\"):\n",
" add_to_json(i,k,source,target,sum([w['v'] for w in isum[i][k][j]]),\\\n",
" sum([w['v'] for w in isum[i][c][j]]),isum[i][k][j])\n",
" elif (k==m-1): #if onlyfood weight\n",
" if (parent[j]==\"None\"): \n",
" add_to_json(i,k,target,source,sum([w['v'] for w in isum[i][k][j]]),\\\n",
" sum([w['v'] for w in isum[i][c][j]]),isum[i][k][j])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"food_aggregate
function populates the supersum
dictionary by aggregating links for all detail levels into their supergroups (themselves for detail level 3). In additions, it also creates sums of the links going into a certain node and saves these into the helperdict
dictionary. This is necessary for adding parent links and special links later on."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def food_aggregate(country,year,element,isum,helperdict):\n",
"#create aggregate values for all items\n",
" \n",
" for i in range(n):\n",
" for k in range(m):\n",
" for j in isum[i][k].keys():\n",
" #if link is not a parent aggregation itself\n",
" if ((\"Import\" not in j) and (\"Stock Draw\" not in j)):\n",
" if (\"Stock Deposit\" in j): p=j[13:]\n",
" else: p=j\n",
" if ((k!=m-2)&(element!=\"Production\")): #if not only agri-system\n",
" #do not include seed values in parent links\n",
" if not ((parent[p]!=\"None\")&(element==\"Seed\")):\n",
" if p in supersum[i][k].keys():\n",
" supersum[i][k][p]+=sum([w['v'] for w in isum[i][k][j]])\n",
" else:\n",
" supersum[i][k][p]=sum([w['v'] for w in isum[i][k][j]])\n",
" #create breakdowns for parent links detail levels 1-4 \n",
" if (parent[p]!=\"None\"):\n",
" if parent[p] in helperdict[i][k].keys():\n",
" if supergroup[i][p] in helperdict[i][k][parent[p]]:\n",
" helperdict[i][k][parent[p]][supergroup[i][p]].append(isum[i][k][j])\n",
" else:\n",
" helperdict[i][k][parent[p]][supergroup[i][p]]=[isum[i][k][j]]\n",
" else:\n",
" helperdict[i][k][parent[p]]={supergroup[i][p]:[isum[i][k][j]]}\n",
" \n",
" #on agri-system level only include production values for crops with no parent links\n",
" elif ((parent[p]==\"None\")&(element==\"Production\")):\n",
" if p in supersum[i][k].keys():\n",
" supersum[i][k][p]+=sum([w['v'] for w in isum[i][k][j]])\n",
" else:\n",
" supersum[i][k][p]=sum([w['v'] for w in isum[i][k][j]])\n",
"\n",
" return helperdict"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"food_parent
function iterates through the entries of the helperdict
dictionary (i.e. food items with parent nodes) and saves them in the global data
variable by invoking the add_to_json
function. The diagram has been designed so that flows which terminate at nodes that are parents for other flows will represent the breakdown of the aggregate of items departing from the parent node. Therefore a flow containing the food item *Milk* going from *Feed* to *Animal Products* might have *Milk* in the *Animal Products* to *Food* and *Animal Products* to *Waste* flows, but it's depicted proportion in the *Feed* to *Animal Products* flow will correspond to the sum of the *Animal Products* to *Food* and *Animal Products* to *Waste* flows. Also in order to preserve the energetic equilibrium of the flows, a flow with source in the nodes *Import* or *Stock Draw* that cocntains *Milk* among its elements will have *Feed* as its sink."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def food_parent(country,year,helperdict):\n",
"#create parent links\n",
" global parentsum\n",
" \n",
" parentsum = [[{} for k in range(m)] for i in range(n)] \n",
" for i in range(n):\n",
" for k in range(m):\n",
" for d in helperdict[i][k].keys():\n",
" for e in helperdict[i][k][d].keys():\n",
" mydict={}\n",
" for f in helperdict[i][k][d][e]:\n",
" for j in f:\n",
" if j['l'] in mydict:\n",
" mydict[j['l']]+=j['v']\n",
" else:\n",
" mydict[j['l']]=j['v']\n",
" if d in parentsum[i][k]:\n",
" if e in parentsum[i][k][d]:\n",
" parentsum[i][k][d][e]=[{'l':p,'v':mydict[p]} for p in mydict.keys()]\n",
" else:\n",
" parentsum[i][k][d].update({e:[{'l':p,'v':mydict[p]} for p in mydict.keys()]})\n",
" else:\n",
" parentsum[i][k].update({d:{e:[{'l':p,'v':mydict[p]} for p in mydict.keys()]}})\n",
" if (k==m-1): c=0\n",
" else: c=m-1\n",
" if (k!=m-2): #if not only agri-system\n",
" try: add_to_json(i,k,d,e,supersum[i][k][e],supersum[i][c][e],parentsum[i][k][d][e]) \n",
" except: pass\n",
"\n",
" return parentsum"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"food_residue
function calculates food residues and add the corresponding links from food items to the *Crop Residue* node. Cros residue fractions are stroed in the global variable gross
and they represent the fraction of the plant mass that can be further used for energy harvesting (mainly through combustion) pruposes. This is logcially restricted to primary crops only. \n",
"\n",
"Detail levels 0 and 1 differ by the the former incorporating crop residue links into the diagram. However, the estimation of crop residue fraction is highly subejctive and uncertain and it depends on the type of crop and the measuring method used. Therefore the scope of this detail level is only orientative. It can provide the reader with a very accurate general picture of the food energy system, but the actual crop residue mass values might differ. Estimating the accurate energy content of crop residues also repsents a challenge as it depends on the type of energy-extraction method used. Here we estimate the energy that a crops may yield after only stage of energy conversion - which in most of the cases will be conversion to heat energy through burning. An average heat energy content of *300kcal/100g* has been used throughout the crop spectrum, corresponding to typical caloric values of rice husk/straw/dry grass. Therefore, the calculated crop residue mass is multiplied by the *300* / foodcalorie
ratio, where foodcalorie
is the energy content of the each food item. \n",
"\n",
"Crop residue values are saved in the residue
dictionary and subsequently added to the global data
variable. For detail level 0, the crop residues are counted as usable energy, therefore they influence the *EROEI* - this is reflected by adding their sum to the global variable foodoutput
."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def food_residue(country,year):\n",
"#add links for crop residues\n",
"\n",
" global foodoutput\n",
" \n",
" residue=[{} for i in range(n)] \n",
" for i in range(n):\n",
" for j in supersum[3][m-1].keys():\n",
" #process only primary crops\n",
" if (parent[j]==\"None\"):\n",
" if j in gross.keys():\n",
" #adjust for fact that crop residues are burnt\n",
" #therefore have a rather uniform energy content (300)\n",
" try: calorie_multiplier=300/foodcalorie[j][year]\n",
" except: \n",
" try: calorie_multiplier=300/foodcalorie[supergroup[1][j]][year]\n",
" except: calorie_multiplier=1\n",
" cr_en=supersum[3][0][j]*gross[j]*calorie_multiplier\n",
" if supergroup[i][j] in residue[i].keys():\n",
" residue[i][supergroup[i][j]].append({'l':j,'v':cr_en})\n",
" else:\n",
" residue[i][supergroup[i][j]]=[{'l':j,'v':cr_en}]\n",
" for j in residue[i].keys():\n",
" try: calorie_multiplier=300/foodcalorie[j][year]\n",
" except: \n",
" try: calorie_multiplier=300/foodcalorie[supergroup[1][j]][year]\n",
" except: calorie_multiplier=1\n",
" cr_en=supersum[i][0][j]*gross[j]*calorie_multiplier\n",
" cr_su=supersum[i][m-1][j]*gross[j]\n",
" add_to_json(i,0,j,\"Crop Residue\",cr_en,cr_su,residue[i][j])\n",
" if (i==0):\n",
" foodoutput[\"Crop Residue\"][0]+=cr_en"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"food_animal
looks for the existence of such a key in the supersum
dictionary and saves the extra links into data
if needed."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def food_animal(country,year,parentsum):\n",
"#add extra links needed for processed foods of animal origin\n",
" for i in range(n): \n",
" for k in range(m): \n",
" if (k==m-1): c=0\n",
" else: c=m-1\n",
" if (k!=m-2): #if not only agri-system\n",
" if \"Animal Fats\" in supersum[1][k].keys():\n",
" add_to_json(i,k,\"Feed\",\"Processing\",supersum[1][k][\"Animal Fats\"],\\\n",
" supersum[1][c][\"Animal Fats\"],parentsum[1][k][\"Processing\"][\"Animal Fats\"]) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"share
variable, for all dimensions and all crops."
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def food_share(country,year): \n",
"#calculate crops share for energy input distribution\n",
" \n",
" global foodinput #summation variable for EROEI calculation\n",
" global share\n",
"\n",
" for i in range(n):\n",
" crop=[0 for k in range(m)]\n",
" for k in range(m):\n",
" for j in supersum[i][k].keys():\n",
" if (parent[j]=='None'): #calculate primary crops share - parentless entries\n",
" crop[k]+=supersum[i][k][j]\n",
"\n",
" for k in range(m):\n",
" for j in supersum[i][k].keys():\n",
" if (parent[j]=='None'):\n",
" share[i][k][j] = supersum[i][k][j]/crop[k]\n",
"\n",
" if (supergroup[0][j]==\"Aquatic Products\"): # calculate aquatic products share\n",
" share[i][k][j] = supersum[i][k][j]/supersum[0][k][\"Aquatic Products\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Define global regions for interpolation.
" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#South Asia\n", "SAS={'Afghanistan',\n", "'Maldives',\n", "'Bangladesh',\n", "'Nepal',\n", "'Bhutan',\n", "'Pakistan',\n", "'India',\n", "'Sri Lanka'}\n", "\n", "#East Asia and Pacific\n", "EAP={'American Samoa',\n", "'Myanmar',\n", "'Cambodia',\n", "'Palau',\n", "'China',\n", "'Papua New Guinea',\n", "'Fiji',\n", "'Philippines',\n", "'Indonesia',\n", "'Samoa',\n", "'Kiribati',\n", "'Solomon Islands',\n", "'Korea, Dem. Rep.',\n", "'Thailand',\n", "'Lao PDR',\n", "'Timor-Leste',\n", "'Malaysia',\n", "'Tonga',\n", "'Marshall Islands',\n", "'Tuvalu',\n", "'Micronesia, Fed. Sts.',\n", "'Vanuatu',\n", "'Mongolia',\n", "'Vietnam'}\n", "\n", "#South America\n", "SA={'Argentina',\n", "'Guyana',\n", "'Belize',\n", "'Haiti',\n", "'Bolivia',\n", "'Honduras',\n", "'Brazil',\n", "'Jamaica',\n", "'Colombia',\n", "'Mexico',\n", "'Costa Rica',\n", "'Nicaragua',\n", "'Cuba',\n", "'Panama',\n", "'Dominica',\n", "'Paraguay',\n", "'Dominican Republic',\n", "'Peru',\n", "'Ecuador',\n", "'St. Lucia',\n", "'El Salvador',\n", "'St. Vincent and the Grenadines',\n", "'Grenada',\n", "'Suriname',\n", "'Guatemala',\n", "'Venezuela, RB'}\n", "\n", "#Low income food deficit countries\n", "LIFDC={'Afghanistan',\n", "'Korea, Dem. Rep.',\n", "'Bangladesh',\n", "'Liberia',\n", "'Benin',\n", "'Madagascar',\n", "'Burkina Faso',\n", "'Malawi',\n", "'Burundi',\n", "'Mali',\n", "'Cambodia',\n", "'Mozambique',\n", "'Central African Republic',\n", "'Myanmar',\n", "'Chad',\n", "'Nepal',\n", "'Comoros',\n", "'Niger',\n", "'Congo, Dem. Rep.',\n", "'Rwanda',\n", "'Eritrea',\n", "'Sierra Leone',\n", "'Ethiopia',\n", "'Somalia',\n", "'Gambia, The',\n", "'Tajikistan',\n", "'Guinea',\n", "'Tanzania',\n", "'Guinea-Bissau',\n", "'Togo',\n", "'Haiti',\n", "'Uganda',\n", "'Kenya',\n", "'Zimbabwe'}\n", "\n", "#EU\n", "EU={'Austria',\n", "'Italy',\n", "'Belgium',\n", "'Latvia',\n", "'Bulgaria',\n", "'Lithuania',\n", "'Croatia',\n", "'Luxembourg',\n", "'Cyprus',\n", "'Malta',\n", "'Czech Republic',\n", "'Netherlands',\n", "'Denmark',\n", "'Poland',\n", "'Estonia',\n", "'Portugal',\n", "'Finland',\n", "'Romania',\n", "'France',\n", "'Slovak Republic',\n", "'Germany',\n", "'Slovenia',\n", "'Greece',\n", "'Spain',\n", "'Hungary',\n", "'Sweden',\n", "'Ireland',\n", "'United Kingdom'}\n", "\n", "#Carribean\n", "CAR={'Antigua and Barbuda',\n", "'Jamaica',\n", "'Bahamas, The',\n", "'St. Kitts and Nevis',\n", "'Barbados',\n", "'St. Lucia',\n", "'Belize',\n", "'St. Vincent and the Grenadines',\n", "'Dominica',\n", "'Suriname',\n", "'Grenada',\n", "'Trinidad and Tobago',\n", "'Guyana'}\n", "\n", "#Least developed countries\n", "LDC={'Afghanistan',\n", "'Madagascar',\n", "'Angola',\n", "'Malawi',\n", "'Bangladesh',\n", "'Mali',\n", "'Benin',\n", "'Mauritania',\n", "'Bhutan',\n", "'Mozambique',\n", "'Burkina Faso',\n", "'Myanmar',\n", "'Burundi',\n", "'Nepal',\n", "'Cambodia',\n", "'Niger',\n", "'Central African Republic',\n", "'Rwanda',\n", "'Chad',\n", "'Sao Tome and Principe',\n", "'Comoros',\n", "'Senegal',\n", "'Congo, Dem. Rep.',\n", "'Sierra Leone',\n", "'Djibouti',\n", "'Solomon Islands',\n", "'Equatorial Guinea',\n", "'Somalia',\n", "'Eritrea',\n", "'South Sudan',\n", "'Ethiopia',\n", "'Sudan',\n", "'Gambia, The',\n", "'Tanzania',\n", "'Guinea',\n", "'Timor-Leste',\n", "'Guinea-Bissau',\n", "'Togo',\n", "'Haiti',\n", "'Tuvalu',\n", "'Kiribati',\n", "'Uganda',\n", "'Lao PDR',\n", "'Vanuatu',\n", "'Lesotho',\n", "'Yemen, Rep.',\n", "'Liberia',\n", "'Zambia'}\n", "\n", "#North America\n", "NA={'Canada','United States'}" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def get_pcountry(country):\n", " if country in LDC: return 'Least Developed Countries'\n", " elif country in LIFDC: return 'Low Income Food Deficit Countries'\n", " elif country in CAR: return 'Caribbean'\n", " elif country in EU: return 'European Union'\n", " elif country in NA: return 'Northern America'\n", " elif country in SA: return 'South America'\n", " elif country in SAS: return 'Southern Asia'\n", " elif country in EAP: return 'Eastern Asia'\n", " else: return 'World'" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def get_ptcountry(country):\n", " if country in LDC: return 'Least Developed Countries + (Total)'\n", " elif country in LIFDC: return 'Low Income Food Deficit Countries + (Total)'\n", " elif country in CAR: return 'Caribbean + (Total)'\n", " elif country in EU: return 'European Union + (Total)'\n", " elif country in NA: return 'Northern America + (Total)'\n", " elif country in SA: return 'South America + (Total)'\n", " elif country in SAS: return 'Southern Asia + (Total)'\n", " elif country in EAP: return 'Eastern Asia + (Total)'\n", " else: return 'World + (Total)'" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def country_name_converter6(country):\n", " #convert country names for new FAOSTAT \n", " \n", " #aggregate regions \n", " if \"+\" in country: return country[0:country.find(\"+\")-1]\n", " \n", " else: return country" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define interpolation function which interpolates proportionally with the change of a country's GDP." ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def gdp_interpolate(y,years,fit=2,depth=1,order=1,override=False):\n", " if 'GDP (current US$)' in wdi_import_extended:\n", " ratio={}\n", " w={}\n", " for year in y:\n", " try:\n", " ratio[year]=y[year]/(wdi_import_extended['GDP (current US$)'][year]/1000000)\n", " except: pass\n", " ratio=interpolate(ratio,years,1)\n", " for year in ratio:\n", " w[year]=ratio[year]*(wdi_import_extended['GDP (current US$)'][year]/1000000)\n", " return w\n", " else: return interpolate(y,years,fit,depth,order,override)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "agrienergyshare
variable. This code is invoked each years, for each country."
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def remove_total(agrienergyshare):\n",
" newindex=[]\n",
" agrienergyshare=agrienergyshare.unstack()\n",
" for i in agrienergyshare.index:\n",
" if '+ (Total)' in i: newindex.append(i[:-10])\n",
" else: newindex.append(i)\n",
" agrienergyshare.index=newindex\n",
" agrienergyshare=agrienergyshare.stack()\n",
" return agrienergyshare"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def fuel_preprofiling(years,fit=2):\n",
"\n",
" elements=['Agriculture and forestry energy use as a % of total Energy use']\n",
" agrienergyshare = get_data([masterpath,indicators[5],indicators[5]],\\\n",
" ['Country','Element','Year','Value'],[0,2],elements).drop(\"Element\",axis=1)\n",
" agrienergyshare=remove_total(agrienergyshare)\n",
" x={} #load agriculture energy share from the FAO database\n",
" \n",
" for i in agrienergyshare.T.iteritems(): #make just one call, filter to country, superfast\n",
" v=i[1][0] #choose column in which food item values are stored\n",
" if (~np.isnan(v)&(v!=0)): #in FAOSTAT, NaN and 0 are the same thing\n",
" year = int(i[0][1]) #choose column in which years are stored\n",
" country = i[0][0] #choose column in which country names names are stored\n",
" v = i[1][0] #choose column in which values are stored, might need to change it\n",
" if country not in x: x[country]={}\n",
" if year not in x[country]: x[country][year]={}\n",
" x[country].update({year:v})\n",
" \n",
" #extrapolate from regional or global values for missing countries\n",
" for country in countries:\n",
" if ((country not in x)&(country!='World')):\n",
" if country!='World':\n",
" pcountry=get_pcountry(country)\n",
" x[country]=x[pcountry]\n",
" \n",
" for j in x.keys():\n",
" #interpolate missing values\n",
" if set(x[j].keys()).intersection(years):\n",
" x[j].update(interpolate(x[j],years,1))\n",
" \n",
" #as a last resort try GDP proportionality\n",
" elsources_backup=['GDP (current US$)',\\\n",
" 'Energy use (kt of oil equivalent)','Electric power consumption (kWh)',\\\n",
" 'Electric power consumption (kWh per capita)','Energy use (kg of oil equivalent per capita)'\\\n",
" 'Population, total']\n",
" electricity2=get_data([wdipath,'WDI_csv',wdindicators[0]])\n",
" electricity2.columns=['Country','Code','Indicator','ICode']+[1960+i for i in range(55)] #range(54) old\n",
" electricity2=electricity2.drop('Code', axis=1).drop('ICode', axis=1)\\\n",
" .query('Indicator=='+repr(elsources_backup)).set_index(['Country','Indicator'],drop=True)\n",
" \n",
" y={} #load data from the WDI database\n",
" for i in electricity2.T.iteritems():\n",
" country=i[0][0]\n",
" item=i[0][1]\n",
" if country not in y: y[country]={}\n",
" for j in range(len(i[1])):\n",
" v=i[1][i[1].index[j]]\n",
" if (~np.isnan(v)&(v!=0)):\n",
" if item not in y[country]: y[country][item]={}\n",
" y[country][item].update({int(i[1].index[j]):v})\n",
" \n",
" for j in y.keys():\n",
" for k in y[j].keys():\n",
" #interpolate missing values\n",
" if set(y[j][k].keys()).intersection(years):\n",
" y[j][k].update(interpolate(y[j][k],years,fit))\n",
" \n",
" z={}\n",
" w={}\n",
" for country in countries:\n",
" if ((country_name_converter(country) in y.keys()) and (country in x.keys())):\n",
" #if both interpolations sccessful, there should be a complete overlap of years\n",
" for year in x[country].keys():\n",
" v1=v2=0\n",
" #fill electricity data, try agriculture energy share\n",
" if elsources_backup[2] in y[country_name_converter(country)]:\n",
" v1=x[country][year]/100*\\\n",
" y[country_name_converter(country)][elsources_backup[2]][year]*1E-9\n",
" #if not try GDP proportionality\n",
" elif elsources_backup[0] in y[country_name_converter(country)]:\n",
" pcountry=country_name_converter(get_pcountry(country)) \n",
" if pcountry in y.keys():\n",
" if ((elsources_backup[2] in y[pcountry].keys()) and \\\n",
" (elsources_backup[0] in y[pcountry].keys())):\n",
" helpervalue=y[pcountry][elsources_backup[2]][year]*\\\n",
" y[country_name_converter(country)][elsources_backup[0]][year]/\\\n",
" y[pcountry][elsources_backup[0]][year]\n",
" v1=x[country][year]/100*helpervalue*1E-9 \n",
" \n",
" #same for energy\n",
" if elsources_backup[1] in y[country_name_converter(country)]:\n",
" v2=x[country][year]/100*\\\n",
" y[country_name_converter(country)][elsources_backup[1]][year]\n",
" elif elsources_backup[0] in y[country_name_converter(country)]:\n",
" pcountry=country_name_converter(get_pcountry(country)) \n",
" if pcountry in y.keys():\n",
" if ((elsources_backup[1] in y[pcountry].keys()) and \\\n",
" (elsources_backup[0] in y[pcountry].keys())):\n",
" helpervalue=y[pcountry][elsources_backup[1]][year]*\\\n",
" y[country_name_converter(country)][elsources_backup[0]][year]/\\\n",
" y[pcountry][elsources_backup[0]][year]\n",
" v2=x[country][year]/100*helpervalue\n",
" \n",
" #record into dictionary\n",
" if (~np.isnan(v1)&(v1!=0)):\n",
" if country not in z: z[country]={}\n",
" if year not in z[country]: z[country][year]={}\n",
" z[country].update({year:v1/0.000277777778}) #convert from Wh to J\n",
" if (~np.isnan(v2)&(v2!=0)):\n",
" if country not in w: w[country]={}\n",
" if year not in w[country]: w[country][year]={}\n",
" w[country].update({year:v2*41.868}) #convert from ktoe to TJ\n",
" \n",
" return [z,w]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"years
argument of the function). During the process, data quality indicators are collected in the missing
and integrity
global variables. The fuel_profiling
returns a dictionary which has elements of the years
array as (secondary) keys and profiled values as values, for all fuel types (primary keys)."
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def fuel_profiling(country,years):\n",
" global integrity\n",
" global missing\n",
" zerodata=[]\n",
" y={}\n",
" country=country_name_converter6(country) #need to convert old FAOSTAT country names to new FAOSTAT\n",
" for year in years: #fill exiting data\n",
" for fuel in fuels1+fuels2+fuels3:\n",
" try: \n",
" for i in energy.xs([country,year,fuel], level=[0,1,3]).T.iteritems():\n",
" fuelvalue=i[1][0] #choose column in which fuel item values are stored\n",
" if (~np.isnan(fuelvalue)&(fuelvalue!=0)):\n",
" if fuel not in y: y[fuel]={}\n",
" y[fuel].update({year:fuelvalue})\n",
" else:\n",
" zerodata.append(fuel)\n",
" except: pass\n",
" \n",
" for i in y.keys():\n",
"\n",
" #update data integrity\n",
" for j in set(years).difference(y[i].keys()):\n",
" integrity[j].append(i)\n",
"\n",
" #interpolate missing dataframe values\n",
" if set(y[i].keys()).intersection(years):\n",
" if i in fuels1: y[i].update(gdp_interpolate(y[i],years,2)) #electricity values change with GDP\n",
" else: y[i].update(interpolate(y[i],years,1))\n",
" else: print country, 'no data in the entire time range', i \n",
" \n",
" if set(fuels1+fuels2+fuels3).difference(y.keys()):\n",
" for i in set(fuels1+fuels2+fuels3).difference(y.keys()):\n",
" if i not in zerodata:\n",
" print country, 'no data in the entire time range', i\n",
" missing.add(i)\n",
" \n",
" return y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"y
argument), using a different approach to obtain values not yet present in the dataframe - and then interpolated and normalized for a certain country in a similar manner to the main profiling function, for a given time period (given by the years
argument of the function). During the process, data quality indicators are updated in the missing
, estimated
and integrity
global variables. The fuel_reprofiling
returns a dictionary which has elements of the years
array as (secondary) keys and profiled values as values, for all fuel types (primary keys).\n",
"\n",
"- Electricity for irrigation - this data comes from *FAOSTAT*, where available. Otherwise we have calculated a characteristic energy requirement per acre of irrigated land for each climate belt based on the irrigation intensities of neighboring countries and global values based on geographical latitude bands.\n",
"- Fossil fuels for fishing - this data comes from *FAOSTAT* for larger fishing nations. For smaller ones, we calculate a characteristic fossil energy requirement per ton of fish for the neighboring countries or global values based on geographical latitude bands."
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def fuel_reprofiling(country,years,y):\n",
" global integrity\n",
" global missing\n",
" global estimated\n",
" zerodata=[]\n",
" fuels=['Electricity','Energy for power irrigation']+fuels3+fuels2\n",
" for fuel in fuels:\n",
" if (fuel not in y):\n",
" if fuel=='Electricity':\n",
"\n",
" for year in years: #fill exiting data\n",
" try: \n",
" fuelvalue=agrienergy[0][country][year]\n",
" if (~np.isnan(fuelvalue)&(fuelvalue!=0)):\n",
" if fuel not in y: y[fuel]={}\n",
" y[fuel].update({year:fuelvalue})\n",
" except: pass\n",
" \n",
" if fuel=='Energy for power irrigation':\n",
" for year in years: #fill exiting data\n",
" try: \n",
" #try assigning irrigation belt characteristic value (area*irrigation intensity for latitude)\n",
" fuelvalue=land.xs([country,year], level=[0,1]).values[0][0]*\\\n",
" irrig_intensity[(int)(country_lat[country])]\n",
" if (~np.isnan(fuelvalue)&(fuelvalue!=0)):\n",
" if fuel not in y: y[fuel]={}\n",
" y[fuel].update({year:fuelvalue}) #no need to convert data already in TJ\n",
" except: pass\n",
" \n",
" if [i for i in fuels3 if i not in y]:#if none of fuels for fishing is in y\n",
" #old fuel=fuels3[0] #assume all fishery fuel is Gas-diesel\n",
" fuel=\"Fossil fuels in fisheries\"\n",
" missing.add(fuel)\n",
" for year in years: #fill exiting data\n",
" try: \n",
" #try assigning fishery characteristic value\n",
" try: fuelvalue=fishing_energy(country,year)\n",
" except: pass\n",
" if (~np.isnan(fuelvalue)&(fuelvalue!=0)):\n",
" if fuel not in y: y[fuel]={}\n",
" y[fuel].update({year:fuelvalue}) #no need to convert data already in TJ\n",
" except: pass\n",
" \n",
" if [i for i in fuels2 if i not in y]:#if none of fossil fuels is in y\n",
" #old fuel=fuels2[0] #assume all fossil fuel is Gasoline\n",
" fuel=\"Other fossil fuels\"\n",
" missing.add(fuel)\n",
" for year in years: #fill exiting data\n",
" try: \n",
" #try assigning fossil characteristic value\n",
" fuelvalue=agrienergy[1][country][year]\n",
" if (~np.isnan(fuelvalue)&(fuelvalue!=0)):\n",
" if fuel not in y: y[fuel]={}\n",
" y[fuel].update({year:fuelvalue}) #no need to convert data already in TJ\n",
" except: pass\n",
"\n",
" for i in fuels+[\"Other fossil fuels\",\"Fossil fuels in fisheries\"]:\n",
" if ((i in y)&(i in missing)):\n",
" #update data integrity\n",
" for j in set(years).difference(y[i].keys()):\n",
" integrity[j].append(i)\n",
"\n",
" #interpolate missing dataframe values\n",
" if set(y[i].keys()).intersection(years):\n",
" y[i].update(interpolate(y[i],years,1))\n",
" print country, 'tried alternate source for', i,', success'\n",
" if i in [\"Fossil fuels in fisheries\"]: #if fishing fuel, then remove all\n",
" for j in fuels3+[\"Fossil fuels in fisheries\"]:\n",
" if j in missing:\n",
" missing.remove(j)\n",
" elif i in [\"Other fossil fuels\"]: #if fossil fuel, then remove all\n",
" for j in fuels2+[\"Other fossil fuels\"]:\n",
" if j in missing:\n",
" missing.remove(j)\n",
" elif i in missing:\n",
" missing.remove(i)\n",
" estimated.add(i)\n",
" \n",
" else: print country, 'tried alternate source for', i,', no luck' \n",
" \n",
" \n",
" if \"Fossil fuels in fisheries\" in missing.copy(): #if fishing fuel, then remove all\n",
" for j in fuels3:\n",
" if j in missing:\n",
" missing.remove(j)\n",
" elif \"Other fossil fuels\" in missing.copy(): #if fossil fuel, then remove all\n",
" for j in fuels2:\n",
" if j in missing:\n",
" missing.remove(j) \n",
" \n",
" return y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"electricity_extended
global dictionary, which has been returned by the fuel_reprofiling
function. Using the add_to_json
function, the electricity-to-primary crops (irrigation) and electricity-to-processing flows are saved into the data
variable and effectively added to the visualization structure."
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def fuels_part1(country, year):\n",
"#if True: # placeholder dummy\n",
" \n",
" ###############################################################################################\n",
" ###### FUELS PART - Electricity ######\n",
" ###############################################################################################\n",
" \n",
" if True: # placeholder dummy\n",
" \n",
" global foodinput #summation variable for EROEI calculation\n",
" global eltotal\n",
" global eltotal_n\n",
"\n",
" #distribute electricity input for crop irrigation\n",
" for fuel in [fuels1[1]]:\n",
" if fuel in energy_extended.keys():\n",
" try:\n",
" fuelvalue=energy_extended[fuel][year]\n",
" if (~np.isnan(fuelvalue)&(fuelvalue!=0)):\n",
" electricityvalue=fuelvalue*0.000277777778 #1 joule = 0.000277777778 Wh\n",
" for i in range(n):\n",
" for k in range(m-1): #supply data (k=3) does not have non-food inputs\n",
" #distribute electricity input by locally grown crops share only (arg 2 instead of k)\n",
" for j in supersum[i][2]:\n",
" if (parent[j]=='None'):\n",
" #distribute total input based on supply-based share\n",
" add_to_json(i,k,fuels1[0],j,electricityvalue*share[i][3][j],0,\\\n",
" '[{\"l\":'+repr(fuel)+',\"v\":'+repr(electricityvalue*share[i][3][j])+'}]')\n",
" eltotal+=electricityvalue\n",
" eltotal_n+=electricityvalue\n",
" except: pass\n",
" \n",
" #electricity not used for irrigation goes for food processing\n",
" for fuel in [fuels1[0]]:\n",
" if fuel in energy_extended.keys():\n",
" try:\n",
" fuelvalue=energy_extended[fuel][year]\n",
" if (~np.isnan(fuelvalue)&(fuelvalue!=0)):\n",
" electricityvalue=fuelvalue*0.000277777778 #1 joule = 0.000277777778 Wh\n",
" for i in range(n): #exclude level 4 for now - was put back in\n",
" for k in range(m-1): #supply data (k=3) does not have non-food inputs\n",
" if (k!=m-2): #if not only agri-system\n",
" add_to_json(i,k,fuel,\"Processing\",electricityvalue,0,\\\n",
" '[{\"l\":'+repr(fuel)+',\"v\":'+repr(electricityvalue)+'}]')\n",
" eltotal+=electricityvalue\n",
" except: pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"electricity
, country-specific electricty mixes and primary-energy (fossil fuels and renewables and nuclear) specific energy conversion factors are used to calculate the priamry energy inputs entering into electricity. Essentially, this is a profiling process, therefore the data is loaded, interpolated and normalized for a certain country - or extrapolated from the neighbors or global values, for a given time period (given by the years
argument of the function). During the process, data quality indicators are collected in the missing
, estimated
and integrity
global variables. The electricity_profiling
returns a dictionary which has elements of the years
array as (secondary) keys and profiled values as values, for all fuel types (primary keys)."
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def electricity_profiling(country,years): \n",
" global integrity\n",
" global missing\n",
" global estimated\n",
" zerodata=[]\n",
" #locally convert country names between databases\n",
" country=country_name_converter(country)\n",
" y={}\n",
" for year in years: #fill exiting data\n",
" for t in range(2):\n",
" if (t<1): elsources=elsources1\n",
" else: elsources=elsources2\n",
" for c in range(len(elsources)):\n",
" try: \n",
" #choose column in which fuel item values are stored\n",
" fuelvalue=electricity.xs([country,elsources[c]])[year] \n",
" #WDI database consistently reports 0 values if that's the case\n",
" #if (~np.isnan(fuelvalue)&(fuelvalue!=0)): \n",
" if (~np.isnan(fuelvalue)):\n",
" if elsources[c] not in y: y[elsources[c]]={}\n",
" y[elsources[c]].update({year:fuelvalue})\n",
" else:\n",
" zerodata.append(elsources[c])\n",
" except: pass\n",
"\n",
" for i in y.keys():\n",
"\n",
" #update data integrity\n",
" for j in set(years).difference(y[i].keys()):\n",
" label=i\n",
" try: label=\"Electricity from \"+label[label.find(\"Elec\")+28:label.find(\"sources\")-1].capitalize()\n",
" except: pass\n",
" integrity[j].append(label)\n",
"\n",
" #interpolate missing dataframe values\n",
" if set(y[i].keys()).intersection(years):\n",
" y[i].update(interpolate(y[i],years,1)) #electricity share, changes linearly\n",
" \n",
" if set(elsources1+elsources2).difference(y.keys()):\n",
" for i in set(elsources1+elsources2).difference(y.keys()):\n",
" if i not in zerodata:\n",
" label=i\n",
" try: label=label[label.find(\"Elec\")+28:label.find(\"sources\")-1].capitalize()+\" Electricity\"\n",
" except: pass\n",
" print country, 'no data in the entire time range', label\n",
" missing.add(label)\n",
"\n",
" #if all fuel sources missing data, then take regional/global average for fuel sources\n",
" if ((y=={})&(country!='World')):\n",
" if country!='World':\n",
" if country in LDC: \n",
" pcountry='Least Developed Countries'\n",
" elif country in LIFDC: \n",
" pcountry='Low Income Food Deficit Countries'\n",
" elif country in CAR: \n",
" pcountry='Caribbean'\n",
" elif country in EU: \n",
" pcountry='European Union'\n",
" elif country in NA: \n",
" pcountry='Northern America'\n",
" elif country in SA: \n",
" pcountry='South America'\n",
" elif country in SAS: \n",
" pcountry='Southern Asia'\n",
" elif country in EAP: \n",
" pcountry='Eastern Asia'\n",
" else: \n",
" pcountry='World'\n",
" \n",
" print country, 'no data in the entire time range','All electricity sources, extrapolating from', pcountry\n",
" \n",
" y=electricity_profiling(pcountry,years)\n",
" estimated.add(\"All electricity sources\")\n",
" \n",
" for year in years: #renormalize shares to 100%\n",
" \n",
" s=0\n",
" for fuel in y.keys():\n",
" s+=y[fuel][year]\n",
" \n",
" for fuel in y.keys():\n",
" y[fuel][year]=(y[fuel][year]/s)*100\n",
" \n",
" return y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"electricity_extended
global dictionary, which has been updated by the electricity_profiling
function. Using the add_to_json
function, the fossil-to-electrcity and renewable-to-electricity flows are saved into the data
variable and effectively added to the visualization structure."
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def fuels_part2(country, year, eltotal2, it):\n",
"#if True: # placeholder dummy\n",
" \n",
" ###############################################################################################\n",
" ###### FUELS PART - Fossil to Electricity ######\n",
" ###############################################################################################\n",
" \n",
" if True: # placeholder dummy\n",
" \n",
" global foodinput #summation variable for EROEI calculation\n",
" global foodinput2 #summation variable for EROEI calculation\n",
" global electricity_to_fossil #summation for primary equivalent of electricity\n",
" electricity_to_fossil=0\n",
" \n",
" #create fossil to electricity links\n",
" #need to define fossil-to-electrcity conversion efficiencies\n",
" #http://www.eurelectric.org/Download/Download.aspx?DocumentID=13549\n",
" #http://www.ecofys.com/files/files/ecofys-2012-international-comparison-fossil-power-efficiency.pdf \n",
" \n",
" #locally convert country names between databases\n",
" country=country_name_converter(country)\n",
" \n",
" for t in range(2):\n",
" ffsum={}\n",
" if (t<1):\n",
" elsources=elsources1\n",
" #conversion efficiency of fossil source into electrcity\n",
" conv_eff=[0.39,0.38+((year-1960)/60.0)*0.2,0.38]\n",
" src=\"Fossil Fuels\"\n",
" else:\n",
" elsources=elsources2\n",
" #conversion efficiency of renewables & nucelar into electricity, currently outside of scope\n",
" conv_eff=[1,1,1] #[0.34,0.93,0.3]\n",
" src=\"Renewables & Nuclear\"\n",
" for c in range(len(elsources)):\n",
" if elsources[c] in electricity_extended.keys():\n",
" try:\n",
" if elsources[c] in ffsum:\n",
" ffsum[elsources[c]]+=eltotal2*(1/conv_eff[c])\\\n",
" *electricity_extended[elsources[c]][year]/100.0\n",
" else:\n",
" ffsum[elsources[c]]=eltotal2*(1/conv_eff[c])\\\n",
" *electricity_extended[elsources[c]][year]/100.0\n",
" if (it==0): #sum primary equivalent of electricity\n",
" electricity_to_fossil+=eltotal2*(1/conv_eff[c])\\\n",
" *electricity_extended[elsources[c]][year]/100.0\n",
" except: pass\n",
" \n",
" mydata=[]\n",
" for c in range(len(elsources)):\n",
" if elsources[c] in electricity_extended.keys():\n",
" try:\n",
" label=elsources[c]\n",
" label=label[label.find(\"Elec\")+28:label.find(\"sources\")-1].capitalize()\n",
" mydata.append({\"l\":label, \"v\":ffsum[elsources[c]]})\n",
" except: pass\n",
" if (~np.isnan(sum(ffsum.values()))&(sum(ffsum.values())!=0)):\n",
" for i in range(n): #exclude level 4 for now - was put back in\n",
" for k in range(m-1):\n",
" if (k!=2):\n",
" if (it==0):\n",
" add_to_json(i,k,src,\"Electricity\",sum(ffsum.values()),0,mydata) \n",
" elif (it==1):\n",
" add_to_json(i,k,src,\"Electricity\",sum(ffsum.values()),0,mydata) \n",
"\n",
" if (it==0):\n",
" for k in range(m-2):\n",
" foodinput[k]+=sum(ffsum.values())\n",
" foodinput2[src][k]+=sum(ffsum.values())\n",
" else: \n",
" foodinput[2]+=sum(ffsum.values())\n",
" foodinput2[src][2]+=sum(ffsum.values())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"energy_extended
global dictionary, which has been created by the fuel_profiling
function. Using the add_to_json
function, the fossil-to-primary crops and fossil-to-aquatic products flows are saved into the data
variable and effectively added to the visualization structure. Fossil fuels not reported in *FAOSTAT* are estimated from *WDI*."
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def fuels_part3(country, year):\n",
"#if True: # placeholder dummy\n",
"\n",
" ###############################################################################################\n",
" ###### FUELS PART - Fossil fuels ######\n",
" ###############################################################################################\n",
" \n",
" if True: # placeholder dummy\n",
" \n",
" global foodinput\n",
" \n",
" ### FOSSIL FUELS DIRECT INTO AGRICULTURE\n",
" fuelsum=[[{} for k in range(m-1)] for i in range(n)] \n",
" #supply data (k=3) does not have non-food inputs\n",
" \n",
" #distribute fossil fuel input for crop cultivation\n",
" for fuel in fuels2:\n",
" if fuel in energy_extended.keys():\n",
" try:\n",
" fuelvalue=energy_extended[fuel][year]\n",
" if (~np.isnan(fuelvalue)&(fuelvalue!=0)):\n",
" fuelvalue*=0.000277777778 #1 joule = 0.000277777778 Wh\n",
" for i in range(n): #sum fuel item values over all groups\n",
" supergroup[i][fuel]=\"Fossil Fuels\"\n",
" #save sum, but also components for the piechart breakdown\n",
" for k in range(m-1):\n",
" if supergroup[i][fuel] in fuelsum[i][k]:\n",
" fuelsum[i][k][supergroup[i][fuel]].append({\"l\":fuel, \"v\":fuelvalue})\n",
" else:\n",
" fuelsum[i][k][supergroup[i][fuel]]=[{\"l\":fuel, \"v\":fuelvalue}]\n",
" except: pass\n",
" \n",
" #add any mising fossil fuels\n",
" if 'Other fossil fuels' in energy_extended.keys():\n",
" if year in energy_extended['Other fossil fuels']:\n",
" fuelvalue=energy_extended['Other fossil fuels'][year]*0.000277777778 #1 joule = 0.000277777778 Wh\n",
" if \"Fossil Fuels\" in fuelsum[0][0]:\n",
" if (sum([w['v'] for w in fuelsum[0][0][\"Fossil Fuels\"]])<(fuelvalue-electricity_to_fossil)):\n",
" fuel='Other fossil fuels'\n",
" fuelvalue=energy_extended['Other fossil fuels'][year]*0.000277777778-\\\n",
" electricity_to_fossil-sum([w['v'] for w in fuelsum[0][0][\"Fossil Fuels\"]])\n",
" #save sum, but also components for the piechart breakdown\n",
" for i in range(n): #sum fuel item values over all groups\n",
" supergroup[i][fuel]=\"Fossil Fuels\"\n",
" for k in range(m-1):\n",
" if supergroup[i][fuel] in fuelsum[i][k]:\n",
" fuelsum[i][k][supergroup[i][fuel]].append({\"l\":fuel, \"v\":fuelvalue})\n",
" else:\n",
" fuelsum[i][k][supergroup[i][fuel]]=[{\"l\":fuel, \"v\":fuelvalue}]\n",
" else:\n",
" fuel='Other fossil fuels'\n",
" fuelvalue=energy_extended['Other fossil fuels'][year]*0.000277777778-electricity_to_fossil\n",
" #save sum, but also components for the piechart breakdown\n",
" for i in range(n): #sum fuel item values over all groups\n",
" supergroup[i][fuel]=\"Fossil Fuels\"\n",
" for k in range(m-1):\n",
" fuelsum[i][k][supergroup[i][fuel]]=[{\"l\":fuel, \"v\":fuelvalue}]\n",
" \n",
" #return fuelsum\n",
" for i in range(n):\n",
" for k in range(m-1):\n",
" #distribute electricity input by locally grown crops share only (arg 2 instead of k)\n",
" for j in supersum[i][2]:\n",
" if (parent[j]=='None'):\n",
" for p in fuelsum[i][k]:\n",
" helper=[]\n",
" for w in fuelsum[i][k][p]:\n",
" #distribute total input based on supply-based share\n",
" helper.append({\"l\":w['l'],\"v\":w['v']*share[i][3][j]})\n",
" add_to_json(i,k,p,j,sum([w['v'] for w in fuelsum[i][k][p]])*share[i][3][j],0,helper)\n",
" \n",
" for k in range (m-1):\n",
" if fuelsum[0][k]:\n",
" foodinput[k]+=sum([w['v'] for w in fuelsum[0][k][\"Fossil Fuels\"]])\n",
" foodinput2[\"Fossil Fuels\"][k]+=sum([w['v'] for w in fuelsum[0][k][\"Fossil Fuels\"]])\n",
"\n",
" #########################################################################################################\n",
" \n",
" ### FOSSIL FUELS IN FISHERIES\n",
" #reinitialize fuelsum for fishery data\n",
" fuelsum=[[{} for k in range(m-1)] for i in range(n)]\n",
" \n",
" #distribute fossil fuel input for fisheries\n",
" for fuel in fuels3:\n",
" if fuel in energy_extended.keys():\n",
" try:\n",
" fuelvalue=energy_extended[fuel][year]\n",
" if (~np.isnan(fuelvalue)&(fuelvalue!=0)):\n",
" fuelvalue*=0.000277777778 #1 joule = 0.000277777778 Wh\n",
" for i in range(n): #sum fuel item values over all groups\n",
" supergroup[i][fuel]=\"Fossil Fuels\"\n",
" #save sum, but also components for the piechart breakdown\n",
" for k in range(m-1):\n",
" if supergroup[i][fuel] in fuelsum[i][k]:\n",
" fuelsum[i][k][supergroup[i][fuel]].append({\"l\":fuel, \"v\":fuelvalue})\n",
" else:\n",
" fuelsum[i][k][supergroup[i][fuel]]=[{\"l\":fuel, \"v\":fuelvalue}]\n",
" except: pass\n",
" \n",
" #add any mising fossil fuels\n",
" if 'Fossil fuels in fisheries' in energy_extended.keys():\n",
" if year in energy_extended['Fossil fuels in fisheries']:\n",
" fuelvalue=energy_extended['Fossil fuels in fisheries'][year]*0.000277777778 #1 joule = 0.000278 Wh\n",
" if \"Fossil Fuels\" in fuelsum[0][0]:\n",
" if (sum([w['v'] for w in fuelsum[0][0][\"Fossil Fuels\"]])<(fuelvalue)):\n",
" fuel='Fossil fuels in fisheries'\n",
" fuelvalue=energy_extended['Fossil fuels in fisheries'][year]*0.000277777778-\\\n",
" sum([w['v'] for w in fuelsum[0][0][\"Fossil Fuels\"]])\n",
" #save sum, but also components for the piechart breakdown\n",
" for i in range(n): #sum fuel item values over all groups\n",
" supergroup[i][fuel]=\"Fossil Fuels\"\n",
" for k in range(m-1):\n",
" if supergroup[i][fuel] in fuelsum[i][k]:\n",
" fuelsum[i][k][supergroup[i][fuel]].append({\"l\":fuel, \"v\":fuelvalue})\n",
" else:\n",
" fuelsum[i][k][supergroup[i][fuel]]=[{\"l\":fuel, \"v\":fuelvalue}]\n",
" else:\n",
" fuel='Fossil fuels in fisheries'\n",
" fuelvalue=energy_extended['Fossil fuels in fisheries'][year]*0.000277777778\n",
" #save sum, but also components for the piechart breakdown\n",
" for i in range(n): #sum fuel item values over all groups\n",
" supergroup[i][fuel]=\"Fossil Fuels\"\n",
" for k in range(m-1):\n",
" fuelsum[i][k][supergroup[i][fuel]]=[{\"l\":fuel, \"v\":fuelvalue}]\n",
" \n",
" #return fuelsum\n",
" for i in range(n):\n",
" for k in range(m-2):\n",
" #distribute electricity input by locally grown crops share only (arg 2 instead of k)\n",
" for p in fuelsum[i][k]:\n",
" add_to_json(i,k,p,\"Feed\",sum([w['v'] for w in fuelsum[i][k][p]]),0,fuelsum[i][k][p])\n",
" \n",
" for k in range (m-1):\n",
" if (k!=2):\n",
" if fuelsum[0][k]:\n",
" foodinput[k]+=sum([w['v'] for w in fuelsum[0][k][\"Fossil Fuels\"]])\n",
" foodinput2[\"Fossil Fuels\"][k]+=sum([w['v'] for w in fuelsum[0][k][\"Fossil Fuels\"]])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"years
argument of the function). During the process, data quality indicators are collected in the missing
and integrity
global variables. The fert_profiling
returns a dictionary which has elements of the years
array as (secondary) keys and profiled values as values, for all fertilizer types (primary keys). Remember that the fertilizers database is composed of two sepparate dataframes, fertilizers1
and fertilizers2
. This combines the two to yield a single, unified dictionary."
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def fert_profiling(country,years):\n",
" global integrity\n",
" global missing\n",
" zerodata=[]\n",
" y={}\n",
" for year in years: #fill exiting data\n",
" if (year<2003):\n",
" fertilizers=fertilizers2 #inverted on purpose\n",
" fertnames=fert1\n",
" fertelement='Consumption'\n",
" else:\n",
" fertilizers=fertilizers1\n",
" fertnames=fert2\n",
" fertelement='Consumption in nutrients'\n",
" country=country_name_converter6(country) #convert country names from old FAOSTAT to new FAOSTAT\n",
"\n",
" for fert in fertnames:\n",
" try:\n",
" for i in fertilizers.xs([country,year,fertelement,fert], level=[0,1,2,3]).T.iteritems():\n",
" fertvalue=i[1][0] #choose column in which fert item values are stored\n",
" if fert in ['Phosphate fertilizers', 'Phosphate Fertilizers (P205 total nutrients)']:\n",
" fertitem='Phosphate'\n",
" if fert in ['Potash fertilizers', 'Potash Fertilizers (K20 total nutrients)']:\n",
" fertitem='Potash' \n",
" if fert in ['Nitrogenous fertilizers', 'Nitrogen Fertilizers (N total nutrients)']:\n",
" fertitem='Nitrogen'\n",
" if (~np.isnan(fertvalue)&(fertvalue!=0)): #in FAOSTAT, NaN and 0 are the same thing\n",
" if fertitem not in y: y[fertitem]={}\n",
" y[fertitem].update({year:fertvalue})\n",
" else:\n",
" zerodata.append(fert)\n",
" except: pass\n",
" \n",
" for i in y.keys():\n",
"\n",
" #update data integrity\n",
" for j in set(years).difference(y[i].keys()):\n",
" integrity[j].append(i)\n",
"\n",
" #interpolate missing dataframe values\n",
" if set(y[i].keys()).intersection(years):\n",
" #old y[i].update(interpolate(y[i],years,1)) #value, use linear\n",
" y[i].update(gdp_interpolate(y[i],years,1)) #fertilizer values change with GDP\n",
" \n",
" label=[]\n",
" for i in fert1+fert2: \n",
" if i in ['Phosphate fertilizers', 'Phosphate Fertilizers (P205 total nutrients)']:\n",
" label='Phosphate'\n",
" if i in ['Potash fertilizers', 'Potash Fertilizers (K20 total nutrients)']:\n",
" label='Potash' \n",
" if i in ['Nitrogenous fertilizers', 'Nitrogen Fertilizers (N total nutrients)']:\n",
" label='Nitrogen'\n",
" if label:\n",
" if label not in y.keys():\n",
" if label not in zerodata:\n",
" if label not in missing:\n",
" print country, 'no data in the entire time range', label\n",
" missing.add(label)\n",
"\n",
" return y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"fertilizers_extended
global dictionary, which has been created by the fuel_profiling
function. Using the add_to_json
function, the fossil-to-fertilizer and fertilizer-to-primary crop flows are saved into the data
variable and effectively added to the visualization structure."
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def fertilizers_part(country, year):\n",
"#if True: # placeholder dummy\n",
" \n",
" ###############################################################################################\n",
" ###### FERTILIZERS PART ######\n",
" ###############################################################################################\n",
" \n",
" if True: # placeholder dummy\n",
" \n",
" global foodinput\n",
" \n",
" #need to save fertilizer weight and fossil sources\n",
" fertsum=[[{} for k in range(m-1)] for i in range(n)]\n",
" fertweight=[[{} for k in range(m-1)] for i in range(n)]\n",
" #supply data (k=3) does not have non-food inputs\n",
" fertfossil=[\"Natural gas (including LNG)\",\"Fuel oil\",\"Liquefied petroleum gas (LPG)\",\"Coal\"]\n",
" ngratio=[0 for i in range(n)]\n",
" ffsum={}\n",
" \n",
" if (year<2003):\n",
" fertilizers=fertilizers2 #inverted on purpose\n",
" fertnames=fert1\n",
" fertelement='Consumption'\n",
" else:\n",
" fertilizers=fertilizers1\n",
" fertnames=fert2\n",
" fertelement='Consumption in nutrients'\n",
" \n",
" for fertitem in fertilizers_extended:\n",
" fertvalue=fertilizers_extended[fertitem][year]\n",
" if (~np.isnan(fertvalue)&(fertvalue!=0)):\n",
" #define energy content+packaging and transport (http://www.engr.usask.ca/societies/csae/c9915.pdf page10)\n",
" #define production energy requirement (http://www.sswm.info/sites/default/files/reference_attachments/\n",
" #GELLINGS%20et%20al%202004%20Energy%20Efficiency%20in%20Fertiliser%20Production.pdf\n",
" #(http://bioscience.oxfordjournals.org/content/63/4/263/F3.expansion.html)\n",
" if fertitem=='Phosphate':\n",
" fertenergycontent=6.82 #MJ/kg \n",
" fertenergyprod=7.7 #MJ/kg \n",
" fertenergytrans=8.33 #MJ/kg\n",
" ngratio[0]=0.75\n",
" ngratio[1]=0.25\n",
" ngratio[2]=0\n",
" ngratio[3]=0\n",
" if fertitem=='Potash':\n",
" fertenergycontent=2.88 #MJ/kg\n",
" fertenergyprod=6.4 #MJ/kg\n",
" fertenergytrans=6.35 #MJ/kg\n",
" ngratio[0]=0.5\n",
" ngratio[1]=0.5\n",
" ngratio[2]=0\n",
" ngratio[3]=0\n",
" if fertitem=='Nitrogen':\n",
" fertenergycontent=59 #MJ/kg\n",
" fertenergyprod=69.53 #MJ/kg \n",
" fertenergytrans=7.05 #MJ/kg\n",
" ngratio[0]=0.85*0.8\n",
" ngratio[1]=0.85*0.2\n",
" ngratio[2]=0.15*0.5\n",
" ngratio[3]=0.15*0.5\n",
"\n",
" fertvalue=fertvalue/1000 #model units are in 1000 tonnes\n",
" fertenergy=fertvalue*(fertenergycontent+fertenergytrans)* 0.000277777778 #TWh \n",
" #MJ/kg / TJ/1000tonne * #1 joule = 0.000277777778 Wh\n",
" fertratio=fertenergyprod/fertenergycontent\n",
" for i in range(n): #sum fert item values over all groups\n",
" supergroup[i][fertitem]=\"Fertilizers\"\n",
" #save sum, but also components for the piechart breakdown\n",
" for k in range(m-1):\n",
" if supergroup[i][fertitem] in fertsum[i][k]:\n",
" fertsum[i][k][supergroup[i][fertitem]].append({\"l\":fertitem, \"v\":fertenergy})\n",
" fertweight[i][k][supergroup[i][fertitem]].append({\"l\":fertitem, \"v\":fertvalue})\n",
" else:\n",
" fertsum[i][k][supergroup[i][fertitem]]=[{\"l\":fertitem, \"v\":fertenergy}]\n",
" fertweight[i][k][supergroup[i][fertitem]]=[{\"l\":fertitem, \"v\":fertvalue}]\n",
" #save fossil to fertilizer link data\n",
" for c in range(len(fertfossil)):\n",
" if fertfossil[c] in ffsum:\n",
" ffsum[fertfossil[c]]+=fertenergy*fertratio*ngratio[c]\n",
" else:\n",
" ffsum[fertfossil[c]]=fertenergy*fertratio*ngratio[c]\n",
" for i in range(n):\n",
" for k in range(m-1):\n",
" #distribute fertilizer input by locally grown crops share only (arg 2 instead of k)\n",
" #distribute total input based on supply-based share\n",
" for j in supersum[i][2]:\n",
" if (parent[j]=='None'): \n",
" for p in fertsum[i][k]:\n",
" add_to_json(i,k,p,j,sum([w['v'] for w in fertsum[i][k][p]])*share[i][3][j],\\\n",
" sum([w['v'] for w in fertweight[i][k][p]])*share[i][3][j],fertsum[i][k][p])\n",
" \n",
" #create fossil to fertilizer links\n",
" mydata=[]\n",
" try:\n",
" for c in range(len(fertfossil)):\n",
" mydata.append({\"l\":fertfossil[c], \"v\":ffsum[fertfossil[c]]})\n",
" for i in range(n): #exclude level 4 for - now added back in\n",
" for k in range(m-1):\n",
" add_to_json(i,k,\"Fossil Fuels\",\"Fertilizers\",sum(ffsum.values()),0,mydata)\n",
" except: pass\n",
" \n",
" for k in range(m-1):\n",
" foodinput[k]+=sum(ffsum.values())\n",
" foodinput2[\"Fossil Fuels\"][k]+=sum(ffsum.values())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"years
argument of the function). During the process, data quality indicators are collected in the missing
and integrity
global variables. The labor_profiling
returns a dictionary which has elements of the years
array as keys and profiled values as values. If direct numbers about the number of people working in agriculture cannot be found in the population
dataframe, total population numbers (mostly available) are multiplied by a regionally characteristic population fraction."
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def labor_profiling(country,years):\n",
" global integrity\n",
" global missing\n",
" y={}\n",
" x={}\n",
" w={}\n",
" country=country_name_converter6(country) #convert country names from old FAOSTAT to new FAOSTAT\n",
" try:\n",
" for i in population.xs([country,'Total economically active population in Agr'],level=[0,2]).T.iteritems():\n",
" year = i[0][0] \n",
" popvalue = i[1][0]\n",
" if (~np.isnan(popvalue)&(popvalue!=0)):\n",
" x[year]=popvalue\n",
" except: pass \n",
" try:\n",
" for i in population.xs([country,'Total Population - Both sexes'],level=[0,2]).T.iteritems():\n",
" year = i[0][0] \n",
" popvalue = i[1][0]\n",
" if (~np.isnan(popvalue)&(popvalue!=0)):\n",
" w[year]=popvalue\n",
" except: pass\n",
" \n",
" #caclulate agricultural population share\n",
" for year in set(x.keys()).intersection(w.keys()):\n",
" y[year]=x[year]/w[year]\n",
" \n",
" if set(y.keys()).intersection(years):\n",
" #update data integrity\n",
" for i in set(years).difference(y.keys()):\n",
" integrity[i].append(\"Labor\")\n",
" #interpolate missing dataframe values\n",
" \n",
" y.update(interpolate(y,years,1)) #share, use linear\n",
" else: \n",
" print country, 'no data in the entire time range for Labor'\n",
" missing.add(\"Labor\")\n",
" \n",
" #convert share back to number of people\n",
" for year in set(y.keys()).intersection(w.keys()):\n",
" y[year]=y[year]*w[year]\n",
" #interpolate again, if necessary\n",
" if set(y.keys()).intersection(years):\n",
" y.update(interpolate(y,years,2)) #population, use exponential\n",
" \n",
" return y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"hoursperday
) and workdays/year (workyear
) are used alongside a characteristic average energy expenditure intensity for the activity of farming (hourlycalorieburn
). Then the fraction of population working in agriculture (*FAOSTAT* or extrapolated from neighbors) gets multiplied by the population (*FAOSTAT* or *WDI*) to get the number of people involved in agriculture (popvalue
). Using the energy intensity calculated above, we get the total energy input as labor. For countries where the daily food energy intake does not meet the necessary minimum for the agricultural activity-specific energy expenditure, it is assumed that all food energy intake is expended for the activity. Profiled labor inputs are loaded from the unified population_extended
global dictionary, which has been created by the labor_profiling
function. Using the add_to_json
function, the labor-to-primary crop flows are saved into the data
variable and effectively added to the visualization structure."
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def labor_part(country, year):\n",
"#if True: # placeholder dummy\n",
" \n",
" ###############################################################################################\n",
" ###### LABOR PART ######\n",
" ###############################################################################################\n",
" \n",
" if True: # placeholder dummy\n",
" \n",
" global foodinput\n",
"\n",
" #old version, without extrapolation, slow\n",
" #calorietotal=balance.xs([country,year,'Food supply','Grand Total'],level=[0,1,3,2]).values[0][1]\n",
" #second index: choose column in which calorie item values are stored, might need to change it\n",
" \n",
" try:\n",
" calorietotal=food_extended['Food supply (kcal/capita/day)'][year]['Grand Total']\n",
" except:\n",
" try:\n",
" sum(food_extended['Food supply (kcal/capita/day)'][year].values())\n",
" except:\n",
" pass\n",
" \n",
" #old version, without extrapolation, slow\n",
" #popvalue=population.xs([country,year,'Total economically active population in Agr'],level=[0,1,2]).values[0][0]\n",
" #second index: choose column in which pop item values are stored, might need to change it\n",
" \n",
" #new version, after extrapolation\n",
" if year in population_extended.keys():\n",
" try:\n",
" popvalue = population_extended[year]\n",
"\n",
" if (~np.isnan(popvalue)&(popvalue!=0)):\n",
" workyear=5.0/7.0*365.25 #working days spent with farming per year\n",
"\n",
" hourlycalorieburn=372 #calories needed per hour of farming\n",
" #http://calorielab.com/burned/?mo=se&gr=11&ti=Occupation&wt=150&un=lb&kg=68\n",
" #http://www.nutristrategy.com/activitylist.htm, \n",
" #for 155 pound, average of 4 types of activities 372 cal/hour\n",
" hoursperday=12 #hours per day spent farming\n",
" minimumcalorieburn=hourlycalorieburn*hoursperday\n",
" calorieburn=0.9 #percent of calorie intake burned for farming, if above minimum\n",
"\n",
" laborenergy=min(minimumcalorieburn,calorieburn*calorietotal)\\\n",
" *workyear\\\n",
" *popvalue\\\n",
" *1000\\\n",
" *0.00116222222/1000000000\n",
" # 0.00116222222 kwh/kcal *10^-9 TWh/kWh\n",
"\n",
" for i in range(n):\n",
" for k in range(m-1): #supply data (k=3) does not have non-food inputs, but supply-based share\n",
" for j in supersum[i][k]:\n",
" if (parent[j]=='None'):\n",
" add_to_json(i,k,\"Labor\",j,laborenergy*share[i][3][j],0,\\\n",
" '[{\"l\":'+repr(\"Labor\")+',\"v\":'+repr(laborenergy*share[i][3][j])+'}]')\n",
"\n",
" for k in range(m-1):\n",
" foodinput[k]+=laborenergy\n",
" foodinput2[\"Labor\"][k]+=laborenergy\n",
" except: pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"depth
nereast values."
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def interpolate(d,years,gfit=2,depth=1,polyorder=1,override=False):\n",
" #depth * length of interpolation substrings will be taken to the left and right\n",
" #for example for {1971:5,1972:6,1973:7,1974:5} interpolating it over 1969-1990\n",
" #for the section 1960-1970 (2 elements) the values from 1972,1973,1974 (3 elements) will be taken with depth 1.5\n",
" #for the section 1974-1990 (15 elements) all values (4 elements) will be taken to extrapolate\n",
" if (gfit>2): \n",
" print 'interpolate takes only 1 (polynomial) or 2 (exponential) as 3rd argument [default=2]'\n",
" return\n",
" mydict={}\n",
" missing_points=[[]]\n",
" for year in years:\n",
" if year not in d.keys():\n",
" missing_points[-1].append(year)\n",
" else:\n",
" missing_points.append([])\n",
" for m in missing_points:\n",
" if m:\n",
" fit=gfit\n",
" if ((m[-1]years
argument of the wdi_impot_profiling
function). During the process, data quality indicators are collected in the missing
, estimated
and integrity
global variables. The wdi_import_profiling
parses the value added food imports, calculates the equivalent enegrgy expenditure in the country
's economy, distributes this energy over the primary energy mix and returns a dictionary which has elements of the years
array as (scondary) keys and profiled values as values for each primary energy type (primary keys)."
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"#create global energy intensity of the economy values\n",
"def wdi_global(country):\n",
" y={}\n",
" years=range(1961,2012)\n",
" country=country_name_converter(country)\n",
" \n",
" for year in years:\n",
" w=wdi_import.loc[country]\n",
" if ((year in w.loc['Energy use (kt of oil equivalent)']) and (year in w.loc['GDP (current US$)'])):\n",
" y[year]=w.loc['Energy use (kt of oil equivalent)'][year]/w.loc['GDP (current US$)'][year]\n",
" if np.isnan(y[year]): y.pop(year);\n",
" y.update(interpolate(y,years,1)) #energy/GDP ratio is quasilinear\n",
"\n",
" return y"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def wdi_import_profiling(country,years): \n",
" global integrity\n",
" global missing\n",
" global estimated\n",
" zerodata=[]\n",
" temp=set()\n",
" #locally convert country names between databases\n",
" country=country_name_converter(country)\n",
" y={}\n",
" \n",
" #create global primary energy share\n",
" fuelsources={'Fossil fuel energy consumption (% of total)':'Fossil Fuels',\\\n",
" 'Alternative and nuclear energy (% of total energy use)':'Renewables & Nuclear',\\\n",
" 'Combustible renewables and waste (% of total energy)':'Renewables & Nuclear'}\n",
" \n",
" for year in years: #fill exiting data\n",
" for fuel in wdi_import_indicators:\n",
" try: \n",
" fuelvalue=wdi_import.xs([country,fuel])[year] #choose column in which fuel item values are stored\n",
" #if (~np.isnan(fuelvalue)&(fuelvalue!=0)):\n",
" if (~np.isnan(fuelvalue)): #accept 0 data, except for energy use and GDP\n",
" if (fuelvalue==0):\n",
" if fuel not in {'Energy use (kt of oil equivalent)','GDP (current US$)'}:\n",
" if fuel not in y: y[fuel]={}\n",
" y[fuel].update({year:fuelvalue})\n",
" else:\n",
" if fuel not in y: y[fuel]={}\n",
" y[fuel].update({year:fuelvalue})\n",
" else:\n",
" zerodata.append(fuel)\n",
" except: pass\n",
"\n",
" for i in y.keys():\n",
"\n",
" #remove all zero values\n",
" if not any(y[i].values()): y.pop(i)\n",
" \n",
" else:\n",
" #update data integrity\n",
" for j in set(years).difference(y[i].keys()):\n",
" label=i\n",
" try: label=label[:label.find(\"(\")-1]\n",
" except: pass\n",
" integrity[j].append(label)\n",
"\n",
" #interpolate missing dataframe values\n",
" if set(y[i].keys()).intersection(years):\n",
" if i in {'Energy use (kt of oil equivalent)','GDP (current US$)'}: \n",
" fit=2 #consumption, exponential\n",
" override=True\n",
" else: \n",
" fit = 1 #share, linear\n",
" override=False\n",
" y[i].update(interpolate(y[i],years,fit,1,1,override)) \n",
" \n",
" if set(wdi_import_indicators).difference(y.keys()):\n",
" for i in set(wdi_import_indicators).difference(y.keys()):\n",
" #if i not in zerodata:\n",
" label=i\n",
" try: label=label[:label.find(\"(\")-1]\n",
" except: pass\n",
" print country, 'no data in the entire time range', label\n",
" #missing.add(label)\n",
" temp.add(i)\n",
" \n",
" #if all fuel sources missing data, then take regional/global average for fuel sources\n",
" if not set(fuelsources).difference(temp):\n",
" if country!='World':\n",
" if country in LDC: \n",
" pcountry='Least Developed Countries'\n",
" elif country in LIFDC: \n",
" pcountry='Low Income Food Deficit Countries'\n",
" elif country in CAR: \n",
" pcountry='Caribbean'\n",
" elif country in EU: \n",
" pcountry='European Union'\n",
" elif country in NA: \n",
" pcountry='Northern America'\n",
" elif country in SA: \n",
" pcountry='South America'\n",
" elif country in SAS: \n",
" pcountry='Southern Asia'\n",
" elif country in EAP: \n",
" pcountry='Eastern Asia'\n",
" else: \n",
" pcountry='World'\n",
" \n",
" print country, 'no data in the entire time range','All primary energy sources, extrapolating from', pcountry\n",
" \n",
" w=wdi_import_profiling(pcountry,years)\n",
" estimated.add(\"All primary energy sources\")\n",
" for i in fuelsources:\n",
" y[i]=w[i]\n",
" \n",
" for year in years: #renormalize shares to 100%\n",
" \n",
" s=0\n",
" for fuel in fuelsources.keys():\n",
" if fuel in y.keys():\n",
" s+=y[fuel][year]\n",
" \n",
" for fuel in fuelsources.keys():\n",
" if fuel in y.keys():\n",
" y[fuel][year]=(y[fuel][year]/s)*100\n",
"\n",
" return y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"imports
dataframe, where available. Where necessary, values are interpolated using a GDP-driven interpolation."
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def fao_import_profiling(country,years):\n",
" y={}\n",
" country=country_name_converter6(country) #convert country names from old FAOSTAT to new FAOSTAT\n",
" try:\n",
" for i in imports.xs([country,'Import Value'],level=[0,2]).T.iteritems():\n",
" year = i[0][0] \n",
" impvalue = i[1][0]\n",
" if (~np.isnan(impvalue)&(impvalue!=0)):\n",
" y[year]=impvalue\n",
" except: pass \n",
" \n",
" if set(y.keys()).intersection(years):\n",
" #interpolate missing dataframe values\n",
" y.update(gdp_interpolate(y,years,2)) #food imports change with GDP, is exponentially\n",
" \n",
" return y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The import_profiling
function calculates and combines the output of the *WDI* and *FAOSTAT* profilings. The values for the *Value Added Imports* of all food products are loaded, first from *FAOSTAT*, if not available then *WDI*, then interpolated values in the same manner, then they are complied and interpolated and normalized for a certain country, for a given time period (given by the years
argument of the wdi_impot_profiling
function). During the process, data quality indicators are collected in the missing
, estimated
and integrity
global variables. The import_profiling
function returns a dictionary which has elements of the years
array as keys and profiled value added food imports values as values."
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def import_profiling(country,years):\n",
" global integrity\n",
" global missing\n",
" global estimated\n",
" y={}\n",
" \n",
" w=wdi_import_extended\n",
" u=fao_import_profiling(country,years)\n",
" \n",
" #calculate value added total food import value\n",
" for year in years:\n",
" if year not in u: #data not found in FAOSTAT, try WDI\n",
" if (('Merchandise imports (current US$)' in w) and \\\n",
" ('Food imports (% of merchandise imports)' in w)):\n",
" if ((year in w['Merchandise imports (current US$)']) and \\\n",
" (year in w['Food imports (% of merchandise imports)'])):\n",
" v=w['Food imports (% of merchandise imports)'][year]/\\\n",
" 100*w['Merchandise imports (current US$)'][year]\n",
" print country, 'tried alternate source for Value Added Imports , success' \n",
" else: \n",
" v=0\n",
" print country, 'tried alternate source for Value Added Imports , no luck' \n",
"\n",
" else:\n",
" v=u[year]*1000\n",
" if (('Energy use (kt of oil equivalent)' in w) and \\\n",
" ('GDP (current US$)' in w)): \n",
" if ((year in w['Energy use (kt of oil equivalent)']) and \\\n",
" (year in w['GDP (current US$)'])): #energy intenity of GDP is needed no matter what\n",
" if (w['GDP (current US$)'][year]!=0):\n",
" if (v!=0): y[year]=v*w['Energy use (kt of oil equivalent)'][year]/\\\n",
" w['GDP (current US$)'][year]*0.01163 # %/100 * $ * ktoe / $ * ktoe/TWh = TWh\n",
" \n",
" else: #otherwise use regional/global energy intensity values\n",
" if (v!=0): \n",
" \n",
" if country!='World':\n",
" if country in LDC: \n",
" pcountry='Least Developed Countries'\n",
" elif country in LIFDC: \n",
" pcountry='Low Income Food Deficit Countries'\n",
" elif country in CAR: \n",
" pcountry='Caribbean'\n",
" elif country in EU: \n",
" pcountry='European Union'\n",
" elif country in NA: \n",
" pcountry='Northern America'\n",
" elif country in SA: \n",
" pcountry='South America'\n",
" elif country in SAS: \n",
" pcountry='Southern Asia'\n",
" elif country in EAP: \n",
" pcountry='Eastern Asia'\n",
" else: \n",
" pcountry='World'\n",
"\n",
" print country, year, 'no data Value added imports, extrapolating from', pcountry\n",
" \n",
" y[year]=v*wdi_global(pcountry)[year]*0.01163 # %/100 * $ * ktoe / $ * ktoe/TWh = TWh \n",
" if \"Value Added Imports\" not in integrity[year]:\n",
" integrity[year].append(\"Value added imports\") \n",
"\n",
" if set(y.keys()).intersection(years):\n",
" #update data integrity\n",
" for i in set(years).difference(y.keys()):\n",
" if \"Value Added Imports\" not in integrity[i]:\n",
" integrity[i].append(\"Value added imports\")\n",
" \n",
" #interpolate missing dataframe values\n",
" y.update(interpolate(y,years,2,1,1,True)) #economy is exponential\n",
" \n",
" else: \n",
" if \"Value Added Imports\" not in missing:\n",
" print country, 'no data in the entire time range Value Added Imports' \n",
" missing.add(\"Value added imports\")\n",
" \n",
" return y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"import_extended
global dictionary, which has been created by the import_profiling
function. Then, the value added food imports are use to calculate the equivalent enegrgy expenditure in the country
's economy, distributes this energy over the primary energy mix (calculated by wdi_import_profiling
and stored in wdi_import_extended
). Then, using the add_to_json
function, the imports-to-primary crop flows (from fao_import_profiling
) and primary energy sources-to-imports are saved into the data
variable and effectively added to the visualization structure."
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def import_part(country, year):\n",
"#if True: # placeholder dummy\n",
" \n",
" ###############################################################################################\n",
" ###### IMPORTS PART ######\n",
" ###############################################################################################\n",
" \n",
" if country not in {\"World\"}:\n",
" \n",
" global foodinput\n",
" \n",
" if year in import_extended.keys():\n",
" \n",
" fuelsources={'Fossil fuel energy consumption (% of total)':'Fossil Fuels',\\\n",
" 'Alternative and nuclear energy (% of total energy use)':'Renewables & Nuclear',\\\n",
" 'Combustible renewables and waste (% of total energy)':'Renewables & Nuclear'}\n",
" \n",
" if set(fuelsources.keys()).intersection(wdi_import_extended.keys()):\n",
" \n",
" try:\n",
" impvalue = import_extended[year]*\\\n",
" wdi_import_extended['Fossil fuel energy consumption (% of total)'][year]/100\n",
"\n",
" if (~np.isnan(impvalue)&(impvalue!=0)):\n",
"\n",
" for i in range(n):\n",
" for k in range(m-1): #supply data (k=3) does not have non-food inputs\n",
" if (k!=m-2): #if not only agri-system\n",
" add_to_json(i,k,\"Fossil Fuels\",\"Import\",impvalue,0,\\\n",
" '[{\"l\":'+repr(\"Fossil Fuels\")+',\"v\":'+repr(impvalue)+'}]')\n",
"\n",
" for k in range(m-1):\n",
" if (k!=2): \n",
" foodinput[k]+=impvalue\n",
" foodinput2[\"Fossil Fuels\"][k]+=impvalue\n",
" except: pass\n",
" impvalue1 = 0\n",
" try: impvalue1 = import_extended[year]*\\\n",
" wdi_import_extended['Alternative and nuclear energy (% of total energy use)'][year]/100\n",
" except: pass\n",
" impvalue2 = 0\n",
" try: impvalue2 = import_extended[year]*\\\n",
" wdi_import_extended['Combustible renewables and waste (% of total energy)'][year]/100\n",
" except: pass\n",
" try:\n",
" if ((~np.isnan(impvalue1+impvalue2))&(impvalue1+impvalue2!=0)):\n",
" for i in range(n):\n",
" for k in range(m-1): #supply data (k=3) does not have non-food inputs\n",
" if (k!=m-2): #if not only agri-system\n",
" add_to_json(i,k,\"Renewables & Nuclear\",\"Import\",impvalue1+impvalue2,0,\\\n",
" '[{\"l\":'+repr(\"Renewables & Nuclear\")+\\\n",
" ',\"v\":'+repr(impvalue1)+'},{\"l\":'+\\\n",
" repr(\"Biomass & Waste\")+',\"v\":'+repr(impvalue2)+'}]')\n",
"\n",
" for k in range(m-1):\n",
" if ((~np.isnan(impvalue1+impvalue2))&(impvalue1+impvalue2!=0)):\n",
" if (k!=2):\n",
" foodinput[k]+=impvalue1+impvalue2\n",
" foodinput2[\"Renewables & Nuclear\"][k]+=impvalue1+impvalue2\n",
" except: pass\n",
" else:\n",
" try:\n",
" impvalue = import_extended[year]\n",
" if (~np.isnan(impvalue)&(impvalue!=0)):\n",
" for i in range(n):\n",
" for k in range(m-1): #supply data (k=3) does not have non-food inputs\n",
" if (k!=m-2): #if not only agri-system\n",
" add_to_json(i,k,\"Fossil Fuels\",\"Import\",impvalue,0,\\\n",
" '[{\"l\":'+repr(\"Fossil Fuels\")+',\"v\":'+repr(impvalue)+'}]')\n",
"\n",
" for k in range(m-1):\n",
" if (k!=2): \n",
" foodinput[k]+=impvalue\n",
" foodinput2[\"Fossil Fuels\"][k]+=impvalue\n",
" except: pass\n",
" print country, year, \"no data for Energy composition, using 100% Fossil\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"i
as the detail level at which we are passing the data and it is one of the following: k
corresponds to the *Python* dictionary in the global variable data[i][k]
to which the data will be written to. We will generate the following datasets:data[i][0]
variable - includes food-system and crop residuesdata[i][1]
variable - includes agri-system and food trade and scondary food productsdata[i][2]
variable - includes primary cropsdata[i][3]
variablen
throughout the code) different values of i
and 4 (defined as m
throughout the code) different values of k
, this leads to a total of 16 files for each country and each year. The naming convetion we us is:\n",
"\n",
" - [country]+[year]+[i]+[k].json
, without spaces\n",
"\n",
"On top of that, for each dataset, we calculate a sepparate *EROEI* and *NAEC*, storing them in 4 files indexed after k
and prefixed with k
:\n",
"\n",
" - [country]+[year]+
k+[k].json
, without spaces\n",
" \n",
"Finally, the data integriy for each country is stored in one file per country, listing the contents of the missing, etimated
and integrity
(interpolated) dictionaries over time.\n",
"\n",
"This leads to a grand total of (number of countries and regions)·(years·m·n+1)
number of files. This equals 197·(51·4·4+1)=160949"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def save_data(country, year):\n",
" \n",
" ###############################################################################################\n",
" ###### SAVE DATA ######\n",
" ###############################################################################################\n",
"\n",
" global eroei\n",
"\n",
" for k in range(m):\n",
" \n",
" #if ((sum([foodoutput[i][k] for i in foodoutput.keys()])!=0) & (foodinput[k]!=0)): \n",
" #old, deprecated - null foodinput condition was needed to avoid Inf EROEI\n",
" if ((sum([foodoutput[i][k] for i in foodoutput.keys()])!=0)):\n",
"\n",
" #save main Sankey data \n",
" for i in range(n):\n",
" file(savepath+country+repr(year)+repr(i)+repr(k)+'.json','w').write(json.dumps(data[i][k]))\n",
"\n",
" #create global input-output graph (top right corner)\n",
" fooddata={\"nodes\":[{\"name\": \"Balance\",\"fill\":\"#9edae5\"}],\"links\":[]}\n",
" for j in range(len(foodoutput.keys())):\n",
" if foodoutput[foodoutput.keys()[j]][k]:\n",
" nodes_innerdict={}\n",
" nodes_innerdict[\"name\"] = foodoutput.keys()[j]\n",
" if (color(k,foodoutput.keys()[j])!=\"\"): nodes_innerdict[\"fill\"]=color(k,foodoutput.keys()[j])\n",
" fooddata[\"nodes\"].append(nodes_innerdict)\n",
" for j in range(len(foodinput2.keys())):\n",
" if foodinput2[foodinput2.keys()[j]][k]:\n",
" nodes_innerdict={}\n",
" nodes_innerdict[\"name\"] = foodinput2.keys()[j]\n",
" if (color(k,foodinput2.keys()[j])!=\"\"): nodes_innerdict[\"fill\"]=color(k,foodinput2.keys()[j])\n",
" fooddata[\"nodes\"].append(nodes_innerdict)\n",
" \n",
" for j in range(1,len(fooddata[\"nodes\"])):\n",
" if fooddata[\"nodes\"][j][\"name\"] in foodinput2:\n",
" links_innerdict={} \n",
" links_innerdict[\"source\"]=j\n",
" links_innerdict[\"target\"]=0\n",
" links_innerdict[\"value\"]=foodinput2[fooddata[\"nodes\"][j][\"name\"]][k]\n",
" fooddata[\"links\"].append(links_innerdict)\n",
" else:\n",
" links_innerdict={} \n",
" links_innerdict[\"source\"]=0\n",
" links_innerdict[\"target\"]=j\n",
" links_innerdict[\"value\"]=foodoutput[fooddata[\"nodes\"][j][\"name\"]][k]\n",
" fooddata[\"links\"].append(links_innerdict)\n",
"\n",
" #if (k!=m-1):\n",
" #eroei[k][year]=sum([foodoutput[i][k] for i in foodoutput])/(foodinput[k])\n",
" #old discounted imports for WROWI\n",
" #else: eroei[k][year]=(sum([foodoutput[i][k] for i in foodoutput])-foodimport[k])/(foodinput[k])\n",
" \n",
" if (foodinput[k]!=0):\n",
" eroei[k][year]=sum([foodoutput[i][k] for i in foodoutput])/(foodinput[k])\n",
" else: eroei[k][year]=0\n",
" \n",
" #calculate aec\n",
" global aec\n",
" aec[k][year]=0\n",
" aec1=0\n",
" aec2=0\n",
" \n",
" for item in foodoutput.keys()+[\"Production\"]:\n",
" if item in groupdict[0][k]:\n",
" try:\n",
" aec1+=sum([z['prod'] for z in data[0][k]['links'] if \\\n",
" z['target']==groupdict[0][k][item]])\n",
" aec2+=sum([z['value'] for z in data[0][k]['links'] if \\\n",
" z['target']==groupdict[0][k][item]])\n",
" except:pass #division by zero, interpolate later\n",
" \n",
" if (k!=m-1): aec[k][year]=aec2/aec1*100*859.845 #convert TWh/ktonnes to kcal/100g\n",
" else: aec[k][year]=aec1/aec2*100*859.845\n",
" \n",
" #save mini-Sankey data \n",
" file(savepath+country+repr(year)+'k'+repr(k)+'.json','w').write(json.dumps(fooddata))\n",
" \n",
" #safety switch\n",
" else:\n",
" aec[k][year]=0\n",
" eroei[k][year]=0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"country_name_converter
functions. We used a nromalization over the *FAO* country names, hence all other database country names are converted to *FAO* names. For saving we use a simplified version of the *FAO* nameset."
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def country_name_converter(country):\n",
" #convert country names between FAO and WDI databases\n",
" if \"\\xf4\" in country: return country[0:country.find(\"\\xf4\")]+\"o\"+country[country.find(\"\\xf4\")+1:len(country)]\n",
" elif \"of America\" in country: return country[0:country.find(\"of America\")-1]\n",
" elif country == 'China, Hong Kong SAR': return 'Hong Kong SAR, China'\n",
" elif country == 'China, Macao SAR': return 'Macao SAR, China'\n",
" elif country == 'Democratic Republic of the Congo': return 'Congo, Dem. Rep.'\n",
" elif country == 'Egypt': return 'Egypt, Arab Rep.'\n",
" elif country == 'Faroe Islands': return 'Faeroe Islands'\n",
" elif country == 'Iran': return 'Iran, Islamic Rep.'\n",
" elif country == 'Iran (Islamic Republic of)': return 'Iran, Islamic Rep.'\n",
" elif country == 'Kyrgyzstan': return 'Kyrgyz Republic'\n",
" elif country == \"Lao People's Democratic Republic\": return 'Lao PDR'\n",
" elif country == 'Occupied Palestinian Territory': return 'West Bank and Gaza'\n",
" elif country == 'Republic of Korea': return 'Korea, Rep.'\n",
" elif country == 'Republic of Moldova': return 'Moldova'\n",
" elif country == 'Slovakia': return 'Slovak Republic'\n",
" elif country == 'The former Yugoslav Republic of Macedonia': return 'Macedonia, FYR'\n",
" elif country == 'Yemen': return 'Yemen, Rep.'\n",
" elif country == 'Viet Nam': return 'Vietnam'\n",
" elif country == 'Venezuela': return 'Venezuela, RB'\n",
" elif country == 'Venezuela (Bolivarian Republic of)': return 'Venezuela, RB' \n",
" elif country == 'United Republic of Tanzania': return 'Tanzania'\n",
" \n",
" #special countries, existing in the past, electricity generation values estimated from contemporary countries\n",
" elif country == 'Serbia and Montenegro': return 'Serbia'\n",
" elif country == 'Saint Vincent and the Grenadines': return 'St. Vincent and the Grenadines'\n",
" elif country == 'China, mainland': return 'China'\n",
" elif country == 'Ethiopia PDR': return 'Ethiopia'\n",
" elif country == 'USSR': return 'Russian Federation'\n",
" elif country == 'Yugoslav SFR': return 'Serbia'\n",
" elif country == 'Bahamas': return 'Bahamas, The'\n",
" elif country == 'Saint Lucia': return 'St. Lucia'\n",
" elif country == 'Belgium-Luxembourg': return 'Belgium'\n",
" elif country == 'Gambia': return 'Gambia, The'\n",
" elif country == \"Democratic People's Republic of Korea\": return 'Korea, Dem. Rep.'\n",
" elif country == 'Saint Kitts and Nevis': return 'St. Kitts and Nevis'\n",
" elif country == 'Congo': return 'Congo, Rep.'\n",
" elif country == 'Czechoslovakia': return 'Czech Republic'\n",
" \n",
" #aggregate regions \n",
" elif country == 'Central America': return 'Mexico and Central America'\n",
" elif country == 'Eastern Asia': return 'East Asia & Pacific (all income levels)'\n",
" elif country == 'Least Developed Countries': return 'Least developed countries: UN classification'\n",
" elif country == 'Low Income Food Deficit Countries': return 'Low income'\n",
" elif country == 'Northern Africa': return 'Middle East & North Africa (all income levels)'\n",
" elif country == 'Northern America': return 'North America'\n",
" elif country == 'South America': return 'Latin America & Caribbean (all income levels)'\n",
" elif country == 'Southern Africa': return 'Sub-Saharan Africa (all income levels)'\n",
" elif country == 'Southern Asia': return 'South Asia'\n",
" elif country == 'Caribbean': return 'Caribbean small states'\n",
" elif country == 'Small Island Developing States': return 'Pacific island small states'\n",
" elif \"+\" in country: return country[0:country.find(\"+\")-1]\n",
" elif \"(\" in country: return country[0:country.find(\"(\")-1]\n",
" \n",
" else: return country"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def country_name_converter2(country):\n",
" #convert country names between databases: FAO to latitude bands map/info\n",
" if country=='Serbia and Montenegro': return 'Serbia'\n",
" elif country=='Russian Federation': return 'Russia'\n",
" elif country=='United States Virgin Islands': return 'Virgin Islands'\n",
" elif country=='Iran (Islamic Republic of)': return 'Iran'\n",
" elif country=='Viet Nam': return 'Vietnam'\n",
" elif country=='China, mainland': return 'China'\n",
" elif country=='United States of America': return 'United States'\n",
" elif country=='Falkland Islands (Malvinas)': return 'Falkland Islands (Islas Malvinas)'\n",
" elif country=='Ethiopia PDR': return 'Ethiopia'\n",
" elif country=='Bolivia (Plurinational State of)': return 'Bolivia'\n",
" elif country=='USSR': return 'Russia'\n",
" elif country=='World': return 'Pacific Ocean'\n",
" elif country=='Yugoslav SFR': return 'Serbia'\n",
" elif country=='Republic of Moldova': return 'Moldova'\n",
" elif country=='Bahamas': return 'Bahamas, The'\n",
" elif country=='Pacific Islands Trust Territory': return 'Pacific Ocean'\n",
" elif country==\"Lao People's Democratic Republic\": return 'Laos'\n",
" elif country=='Belgium-Luxembourg': return 'Belgium'\n",
" elif country=='China, Hong Kong SAR': return 'Hong Kong'\n",
" elif country=='Gambia': return 'Gambia, The'\n",
" elif country=='China, Macao SAR': return 'Macau'\n",
" elif country=='United Republic of Tanzania': return 'Tanzania'\n",
" elif country=='Wallis and Futuna Islands': return 'Wallis and Futuna'\n",
" elif country=='Venezuela (Bolivarian Republic of)': return 'Venezuela'\n",
" elif country=='Occupied Palestinian Territory': return 'West Bank'\n",
" elif country=='Syrian Arab Republic': return 'Syria'\n",
" elif country=='Republic of Korea': return 'Korea, South'\n",
" elif country==\"Democratic People's Republic of Korea\": return 'Korea, North'\n",
" elif country=='Brunei Darussalam': return 'Brunei'\n",
" elif country=='Democratic Republic of the Congo': return 'Congo, Democratic Republic of the'\n",
" elif country=='Micronesia (Federated States of)': return 'Micronesia, Federated States of'\n",
" elif country=='Holy See': return 'Holy See (Vatican City)'\n",
" elif country=='The former Yugoslav Republic of Macedonia': return 'Macedonia'\n",
" elif country=='R\\xe9union': return 'Reunion'\n",
" elif country=='China, Taiwan Province of': return 'Taiwan'\n",
" elif country==\"C\\xf4te d'Ivoire\": return \"Cote d'Ivoire\"\n",
" elif country=='Myanmar': return 'Burma'\n",
" elif country=='Sudan (former)': return 'Sudan'\n",
" elif country=='Congo': return 'Congo, Republic of the'\n",
" elif country=='Netherlands Antilles': return 'Aruba'\n",
" elif country=='Czechoslovakia': return 'Czech Republic'\n",
" else: return country"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def country_name_converter3(country):\n",
" #convert country names for Sankey app\n",
" \n",
" #aggregate regions \n",
" if \"+\" in country: return \"~ \"+country[0:country.find(\"+\")-1]\n",
" elif \"(\" in country: return country[0:country.find(\"(\")-1]\n",
" regions={'Small Island Developing States','Caribbean','Eastern Asia',\\\n",
" 'European Union','Least Developed Countries',\\\n",
" 'Low Income Food Deficit Countries','Northern Africa','Northern America',\\\n",
" 'South America','Southern Africa','Southern Asia','World'}\n",
" if country in regions: return \"~ \"+country\n",
" \n",
" #countries\n",
" elif \"\\xf4\" in country: return country[0:country.find(\"\\xf4\")]+\"o\"+country[country.find(\"\\xf4\")+1:len(country)]\n",
" elif \"of America\" in country: return country[0:country.find(\"of America\")-1]\n",
" elif country == 'China, Hong Kong SAR': return 'Hong Kong SAR, China'\n",
" elif country == 'China, Macao SAR': return 'Macao SAR, China'\n",
" elif country == 'China, Taiwan province of': return 'Taiwan'\n",
" elif country == 'Democratic Republic of the Congo': return 'Congo, DRC'\n",
" elif country == \"Lao People's Democratic Republic\": return 'Lao PDR'\n",
" elif country == 'Republic of Korea': return 'Korea, South'\n",
" elif country == 'Republic of Moldova': return 'Moldova'\n",
" elif country == 'The former Yugoslav Republic of Macedonia': return 'Macedonia, FYR'\n",
" elif country == 'Viet Nam': return 'Vietnam'\n",
" elif country == 'United Republic of Tanzania': return 'Tanzania'\n",
" elif country == \"Democratic People's Republic of Korea\": return 'Korea, North'\n",
" elif country == \"Syrian Arab Republic\": return 'Syria'\n",
" \n",
" #special countries, existing in the past, electricity generation values estimated from contemporary countries\n",
" elif country == 'Serbia and Montenegro': return '{former} Serbia and Montenegro'\n",
" elif country == 'China, mainland': return '{former} China, mainland'\n",
" elif country == 'Ethiopia PDR': return '{former} Ethiopia, PDR'\n",
" elif country == 'USSR': return '{former} USSR'\n",
" elif country == 'Yugoslav SFR': return '{former} Yugoslav SFR'\n",
" elif country == 'Belgium-Luxembourg': return '{former} Belgium-Luxembourg'\n",
" elif country == 'Czechoslovakia': return '{former} Czechoslovakia'\n",
" \n",
" else: return country"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def country_name_converter4(country):\n",
" #convert country names for World Map app\n",
" \n",
" #from FAO\n",
" if country == 'China, Hong Kong SAR': return 'Hong Kong'\n",
" #elif country == 'China, mainland': return 'China'\n",
" elif country == 'China, Macao SAR': return 'Macao, China'\n",
" elif country == \"Lao People's Democratic Republic\": return \"Lao People's Dem. Rep.\"\n",
" elif country == 'Sao Tome and Principe': return 'S\\xe3o Tom\\xe9 and Principe'\n",
" elif country == 'Cabo Verde': return 'Cape Verde'\n",
" elif country == 'Iran (Islamic Republic of)': return 'Iran'\n",
" elif country == 'Viet Nam': return 'Vietnam'\n",
" elif country == 'United States of America': return 'United States'\n",
" elif country == 'Bolivia (Plurinational State of)': return 'Bolivia'\n",
" elif country == 'Central African Republic': return 'Cent African Rep'\n",
" elif country == 'Occupied Palestinian Territory': return 'Palestinian Territories'\n",
" elif country == 'Republic of Moldova': return 'Rep. of Moldova'\n",
" elif country == 'Libya': return 'Libyan Arab Jamahiriya'\n",
" elif country == 'United Republic of Tanzania': return 'Tanzania'\n",
" elif country == 'Venezuela (Bolivarian Republic of)': return 'Venezuela'\n",
" elif country == 'Republic of Korea': return 'Rep. of Korea'\n",
" elif country == \"Democratic People's Republic of Korea\": return \"People's Republic of Korea\"\n",
" elif country == 'The former Yugoslav Republic of Macedonia': return 'FYR of Macedonia'\n",
" elif country == 'China, Taiwan Province of': return 'Taiwan'\n",
" elif country == 'Sudan (former)': return 'Sudan'\n",
" elif country == 'Myanmar': return 'Myanmar (Burma)'\n",
" \n",
" #from WDI\n",
" elif country == 'Bahamas, The' :return 'Bahamas'\n",
" elif country == 'Congo, Dem. Rep.':return 'Dem. Rep. of Congo'\n",
" elif country == 'Congo, Rep.':return 'Congo'\n",
" elif country == \"Cote d'Ivoire\": return \"C\\xf4te d'Ivoire\"\n",
" elif country == 'Egypt, Arab Rep.':return 'Egypt'\n",
" elif country == 'Gambia, The':return 'Gambia'\n",
" elif country == 'Hong Kong SAR, China': return 'Hong Kong'\n",
" elif country == 'Iran, Islamic Rep.': return 'Iran'\n",
" elif country == 'Korea, Dem. Rep.' : return \"People's Republic of Korea\"\n",
" elif country == 'Korea, Rep.': return 'Rep. of Korea'\n",
" elif country == 'Kyrgyz Republic':return 'Kyrgyzstan'\n",
" elif country == 'Lao PDR': return \"Lao People's Dem. Rep.\"\n",
" elif country == 'Macao SAR, China': return 'Macao, China'\n",
" elif country == 'Macedonia, FYR': return 'FYR of Macedonia'\n",
" elif country == 'Micronesia, Fed. Sts.' :return 'Micronesia (Federated States of)'\n",
" elif country == 'Moldova':return 'Rep. of Moldova'\n",
" elif country == 'Slovak Republic':return 'Slovakia'\n",
" elif country == 'St. Kitts and Nevis':return 'Saint Kitts and Nevis'\n",
" elif country == 'St. Lucia':return 'Saint Lucia'\n",
" elif country == 'St. Vincent and the Grenadines':return 'Saint Vincent and the Grenadines'\n",
" elif country == 'Venezuela, RB': return 'Venezuela'\n",
" elif country == 'Virgin Islands (U.S.)':return 'US Virgin Islands'\n",
" elif country == 'West Bank and Gaza':return 'Palestinian Territories'\n",
" elif country == 'Yemen, Rep.':return 'Yemen'\n",
" \n",
" else: return country"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"balance
dataframe."
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"#fishing profiling\n",
"fishing = balance.xs(['Production','Fish, Seafood'],level=[3,2]).drop('ItemCode',axis=1)\n",
"points=[]\n",
"\n",
"#get available fishing data\n",
"fish_diesel1=energy.xs([fuels3[0]],level=[3]).reset_index().drop('Element', axis=1).set_index(['Country', 'Year'])\n",
"fish_diesel2=energy.xs([fuels3[1]],level=[3]).reset_index().drop('Element', axis=1).set_index(['Country', 'Year'])\n",
"for country in countries:\n",
" if '+ (Total)' not in country:\n",
" fishing_list={}\n",
" land_list={}\n",
" try:\n",
" years=range(1961,2012)\n",
" for year in years:\n",
" try:\n",
" #power for fishing per area (TJ/ktonnes of fish)\n",
" land_list[year]=fishing.xs([country,year],level=[0,1]).values[0][0]\n",
" if (land_list[year]!=0):\n",
" if (fish_diesel1.xs([country,year],level=[0,1]).values[0][0]+\\\n",
" fish_diesel2.xs([country,year],level=[0,1]).values[0][0] != 0): \n",
" fishing_list[year]=(fish_diesel1.xs([country,year],level=[0,1]).values[0][0]+\\\n",
" fish_diesel2.xs([country,year],level=[0,1]).values[0][0])\\\n",
" /land_list[year]\n",
" except: pass\n",
" try: \n",
" points.append([country,pd.DataFrame(fishing_list.values()).mean().values[0],\\\n",
" pd.DataFrame(land_list.values()).mean().values[0]])\n",
" except: pass\n",
" except: pass"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEaCAYAAAAcz1CnAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsnXd8VceV+L/nvt7UexeI3osxNgaXYGziErfEsePETjaO\nk/w2cepudjebeHfTNj3Z9MSx49hO7BCwgwvYGAM2mA6iVyFAXag9vafX3/z+eAKrIZ6kJ4TR/X4+\n7wN37tyZM/c9zZmZc+aMKKXQ0dHR0Rm9aCMtgI6Ojo7OyKIrAh0dHZ1Rjq4IdHR0dEY5uiLQ0dHR\nGeXoikBHR0dnlKMrAh0dHZ1Rjq4IdM4hIk+KyMo48z4kIu1DzaNzeaB/1+9tdEUwyujs7KN9fKYD\nnwM+ksDq/gqUJrC8PhGRkvO0KSoiS4a7/uFCRNaJyP8N8JlKEfnycMnUD92+axF5TET2joAcOoPA\nONIC6Fx0FPA68NEe6U1KqUhCK1LKD/gTWeYFuAko75HWMpwViohJKRUapuJV52egz1x0RuC71kkg\n+oxg9CFAQCnV0OMT6bk0JCKLRGSziLSLSKuIbBGRKd0KE7lBRPaJiEdE1opISZd73ZYLzo4SReTD\nInJcRNwiskJE0rvkMYrIT0SkWUSaROQHIvIrEXkzjrY19dGuULx1d+b7uIgcEBGfiBwWkS+IiHS5\nHxWRz4rIchHxAN/uTP83EanvLPePIvINETnR5T0GRSS7R13fFpGeiuu8dM4Qfiki3xGRxs76fnBW\nPhFZBxQDP+iUM9Ll2atFZL2IeEWkqvOduuItuzPPXSKyR0Q6Or+bdSKS1Xnv3HctIg8B3wCmdJmZ\nPdj5XrotPYqIJiKnROQL8b4HncSjK4LRiZwn/dwIVESMwIvABmA6MA/4CdB11mABvgY8BFwFpAC/\nuUDdJcAHgQ8AS4BZdHamnXwFeBD4J2A+YALuJ76R7vnaFVfdIvJw5/XXgYnAl4F/BT7bo5xvAi8B\nU4FficiHiXV8/wbMBo4AXzwrs1JqA3Ac+FiXurTO6z/E0a6ufAQIEnvf/wx8Abi3896dQBXwX0AO\nkNtZ1zRgNfACse/yLmAm8Md4yxaRHGLLP090vptFwFPnkfGvwI+Aw51y5ADPAb8Dbu4s6yw3AtnA\nnwfyEnQSjFJK/4yiD/AkEALau3xe7nJvZef/04AosOg85TzUeX9cl7T7AX+PPO1drh8DfICrS9q/\nA0e7XNcC/9KjrkPA2n7aVNIpi7dHu9rP1hVn3aeAj/Qo+wvA/i7XUeBnPfK8A/yqR9pqoKLL9ZeB\nA12ulxJbSkntp11vAj/vcr0O2Ngjz2vA77tcnwC+1CPPU8AfeqTN7GxLRjxlE1NwUaCon99Dz+96\nbx/59gL/2uX6OeD5kf67GO0ffUYwOlkPzOjy+WTPDEqpZmKKYbWIvCQiXxSRwh7ZAkqpo12uawGz\niKT0U/dJpVRX75Ja4OzyQjKx0eHWHs9s5cKjfYD76N6uGYAnzrozgQLgd51LYe2dSx3fBcb0qGd7\nj+sJccj8FDBGROZ3Xn8CWKGUGogNQwF7eqSda0M/zAEe6NGutzvLGxtn2buBNcA+EVkmIp8WkYwB\nyH6W3wMfBxCRNOB24PFBlKOTQHRj8ejEp5SquFAmpdQnROSnwM3E/mC/LSJ3KKVe68wS7vlI57/9\nDTB6GlbVBfJDfEoAoOoC7eqv7rP/PgJsukA93jjlebcipRpF5B/AP4nIUeA24NaBlsPg39/viS3t\n9aQmnrKVUlFgSaciW0Js6e67InKtUqqnAumPp4H/FZEFxGYZDUqp1QN4XmcY0BWBTk+6rcV3/pHv\nAb4vIq8QW79/ra8Hh1yxUm0iUkfMHrEOoNNYeQXdO6zhqLteRGqAMqXU0wN8/BAxmZ/skjaP3naN\n3wPLiC3f1Cql1gxS3P4IAoYeaTuBqfEo/z7o+XvYDGwG/ltE9gMfovdM4nxyoJRqFpHlxBTJTOBP\ng5BJJ8HoikCnJ2c9UEqJjY5fJNYJjyFmaPzVMNf/M+BfROQIcLBThhygOo5nM3oYIgFaVcy1MR6+\nCfyfiLQCrxIzVM8G8pRS37uAzE+IyDZiSy53ElMEzV0zKaVeF5EmYobl78Yhj9B9NtTzui8qgUUi\n8gwQVEqdAf4X2CwivyZmsG0nZvC9VSn16QuUffb3MB9YDKwCGogZ2guBA+eR4wRQLCKzgNOAWykV\n7Lz3e2I2FAMxw7XOCKPbCEYf/fmmd73nBcYBfyPm/fEkndP6Hvn7KuN81+eru2vaD4l5kDxBzAir\ngBVA4Dwyd2UVMaXV9XN/vHUrpR4ntnb/UWJr4huI2U/6HUkrpZ4D/gf4HrHR92Ri3lN9yfwkMQXz\nRBzt6SlzX23omfYNYh30caC+U769xLx8SojNtHYD3wHqBlB2K3A1MW+pI8APgP9WSj3bI/9Z/g68\nArxBTHF8+FwmpdYRUw7rlFKVvVqtc9ERpUbuhDIR+TfgAWLeCHuBjyul4vmD1xlFiMguYINS6tGR\nliVeRGQFoCmlPtAj/dfAGKXUTSMj2cgjIjZibq7/rJT6y0jLozOCS0MS23j0MDBJKRUQkeeIjRr0\nNcNRjIgUETNOryc2cn6YmL/+P42kXP3R2bF9ltiMJAzcTcy4fleXPMnEZgofJbaXYdTRae/JBB4F\nOoDnR1YinbOMpI3ATcxLwd65A9JOfOvAOpc3UWKd5feJLV3uB5YqpXaOqFT9o4gpr38DbMSWTj6i\nlHqxS54XiRm9/6CUevXii3hJUExsme00sdl/QkOa6AyekV4a+hSxHYg+YLVSqmf8Gx0dHR2dYWbE\njMUiMpbYrs0SIA9wikgiI1/q6Ojo6MTBSC4NzQU2KaWaADp9i68Gnjmb4TOf+Yw6ePDguQdKSkoo\nKSm5yGIOH2VlZRw7dmykxRg29Pa9d7mc2waXX/sqKyuprKw8d71+/XqUUvFuxBxRRXAI+M9OQ5uf\nmI9yt236Bw8eZMWKFSMh20Xhhz/8IV/5yldGWoxhQ2/fe5fLuW1w+bcvLS1tQPn7VQQiYiK2nfys\nD7ICThLzr16tlOoZYiBulFLlIvIUsbgtUWL+178bbHk6Ojo6OoPjvIpARP6TmBvcO8RG6muJ2RRy\nicVJ+baILFNKfWuwlSulvk/MO0RHR0dHZ4Tob0ZQDnxL9e1W9MfOeOqDCZoVN5eTPaAvFi1aNNIi\nDCt6+967XM5tg8u/fQNlRN1HL8Rjjz2mHn30PbOZdMBYrVb8/sv3dD+9fe9dLue2weXfvrS0tAEZ\ni/VYQzo6OjqjHF0R6Ojo6IxydEWgo6OjM8rpz2toZRzPNyulHkygPDo6Ojo6F5n+vIYmEovF3pfB\nQXWm/3I4hNLR0dHRuXj0pwi+rpRa39/DIvLfCZZHR0dHR+cic14bQeepS90QEU1EkvrLo6Ojo6Pz\n3uKCxmIR+YuIJImIA9gHHBSRfxl+0XR0dHR0LgbxeA1NVkq5gTuIHehdQuzgEB0dHR2dy4B4FIGx\nM/jcHcBKpVSI8x9+rqOjo6PzHiMeRfBboBJwAhs6zxpuGz6RdHR0dHQuJhdUBEqpnyul8pVSS5VS\nUWJhqK8fftF0dHR0dC4GFzyYRkRygG8D+Uqpm4FJwFXA48Ms26ikra2NY8eOUVVfRV1zHeFIGIvJ\nQl5GHgU5BZSVlWG320daTB0dncuIeE4oexJ4AviPzuujwPPoiiCh1NXV8ebGtRyqOUT6xHRSipPJ\nmZuFwWggFAxR31DL4dOHWL5uObPGzuK6a64jOTl5pMXW0dG5DIhHEWQopZ4Tka8BKKVCIjLok8l0\nuhOJRHhr41us37uOkmtLeN8Hb8BkNvXKl1OSA/PA3+Hn2PZj/Pypn3HrwtuYOWMmInFHm9XR0dHp\nRTyKwCMi6WcvRGQ+urE4ISileP6F5zmlTnLNpxZgd114ycdqtzJ10VQKJhbw8vKXONN8hsXXL9aV\ngY6OzqCJx2voy8BKYIyIbAL+DHx+WKUaJRw+epgaUzUL7rs6LiXQlZSsFK55cAFbq7awacumYZJQ\nR0dnNBCP19AO4FpgAfApYhvMyhNRuYikiMgyETkoIgc6ZxujgoMHD9LgrWfenVdgMBgGVYbFZmH+\nh6/k9e2vU19fn2AJdXR0RgvxnkcwD5gBzAHuE5GPJaj+nwGvKKUmAdOBgwkq95ImFArxwtoXyJmQ\ng9EUz+rc+bEn2SlbPJYXX3sxQdLp6OiMNuKJNfQ08ANiM4K5wBWdnyEhIsnAQqXUHwGUUmGl1Kiw\nPRw6dAhTnhF7UmLcQEunl1Dnr6WmpiYh5eno6Iwu4hmOziG2HJTosBKlQKOIPEFstrEDeFQp1ZHg\nekaMtrY2KioqOF1fS11rE+FoFJvJzOGD5Yy9cwyJeqWappE/J49de3eSl5eXkDJ1dHRGD/Eogn1A\nLpDo4aYRmA38s1Jqm4j8FPga8I0E13PRqa6uZu07b7Gn9iTW8fnY8jNwTB+HZtBo8nawf+cq7OZs\nKmuqqPCdoKigEKNxaEtE2SXZVJSfSFALdHR0RhPx9D6ZwAER2QoEOtOUUur2IdZdBVQppbZ1Xi8j\npgjeFc5o5Ic//OG560WLFrFo0aIhVjt8RKNRKk+epKK5nkk3LWRe1h1oPQzBAW8H0x4yUXBFMQUq\nA1rMaM0hstLSsVltg657bEGU9FmZmM1mNO3SOIraaDRitVpHWoxh43Ju3+XcNrj82rdhwwY2bNgw\n6OfjUQSPDbr0flBK1YnIaREZr5Q6AiwG9nfNEw6H+cpXvtLtOb/fPxziDJlQKMTTy5/niDXA+FsX\nYnEAqgl6bL1rqqtm/97XmD3nKhZoU9mVUkUHbty732BKQQl5ObmDlmHV268xfdx0HA7H0BqTIKxW\n6yX7fSWCy7l9l3Pb4PJr37x585g3b9656+985zsDev6CikAptW7AUsXP54BnRMQMHAc+Pox1DRtK\nKf764nIqUhRTbrux3xG5iNDTNGBPScI0s4z95ccwGU1kZmQMVhB9Y5mOjs6Aicdr6G4ROSoibhFp\n7/y4E1G5UqpcKXWFUmqGUuqu96rX0I5dO9kbOMOE26694LKM1eXA39p7JGKyWkmZUsq+iqMEgsEB\nyxD0B5GwdllNd3V0dC4O8Swmfx+4XSmVpJRydX6SLvjUKMHr9fLCxrWMvX1RXGvztpQkVFAIeHor\nA6vTgSE/laMnKgYsR3NdM/lZeZeMfUBHR+e9Qzy9Rp1SalRs9BoMu/fuQZuYhyszLa78IkJGcQmN\nR/p2wkoqyKG2rYlAINDn/fNRc6iWcYXjB/SMjo6ODsSnCLaLyHMicl/nMtHdInLXsEv2HuHtvTvJ\nmT1pQM8Uz55JzbbqPu8ZDAZMWcnUNzbEXV4oGKJxbyOzZswakBw6Ojo6EJ8iSAZ8wBLg1s7PbcMp\n1HsFr9fLGV87yXlZA3ouo7QAI0m017X2ed+SkkSzO35zyf4NB5hWPF0/n0BHR2dQxOM19NBFkOM9\nSX19PZbctAF76ogIM2+5mZaKFnxmL7aU7u6eFqedNm/fM4aeNJxqoLW8jY899OCAZNDR0dE5Szxe\nQ4UiskJEGjs/fxeRgosh3KWOz+fD4BzcJrCknAwyCkvY/fQ2/O7uUTWMFhOB0IXP/mmubWb3sj3c\nu/TeS2bvgI6OznuPeJaGngD+AeR1flZ2po16YnsCBh8vKCU/hzEzF7Dj8c2cOVp7Ll0p6G+SoZTi\n2K7jbH9mJ/ctvo8xY8YMWgYdHR2duEJMKKW6dvxPisgXh0ug9xJOp5NIm3dIZYydP5vk7Ex2v7yK\n2oJqCueVYEu3YzWbe+WNRqPUHq/l+DsVpPhS+Oy9nyUzM3NI9evo6OjEowiaROSjwLOAAB8Gzgyr\nVO8RsrOzCdS3EI1Gh+S/n1FayLUPP8jp3Qc4/MJ22lvqybab2NvhwGDUCAcjeGu9uGvayXHl8P6Z\ntzB58uRBH2ijo6Oj05V4FMEngP8Dftx5vYn3aCiIRGOxWChKy6LpRBWZY4uGVJbJYmbMlTMpnTeD\nHU++yJWGDLI7sglHwphNZjInZJJ7XS4pKSkJkn7kcbvd1NTUUF9Xi9/rRkQjKTWD7Jwc8vLysFgs\nIy2ijs6oIB5FkK+U6uYuKiILgFPDI9J7i4XT57Bs+64hK4KzBL0+LI0ePvCpf7osw0UopTh+/Dg7\nNr1J44lyClKEPGeUdIsRpaD1dIStG4W6DhMTZi9i7vxryBhs7CUdHZ24iEcR/ALouVOpr7RRyZTJ\nU3h503qaTlaTXpw/5PIq1m5h0eTZl6US8Hg8vPbyC7Qd38Q1Y61MuikPo6HvJTWPL8ju42/w11+t\nZdb19zD/6gX6UpiOzjBxXkUgIlcBVwOZIvIlYvYBABfxn3V82WM2m/nwklv5zT9eJOnhOzFZB7+c\nUX/kBI4TLbzv4x9KoISXBo2Njfztyf9jVmoLH7qh4LwK4CxOm5lrpuYzrTTAS1v/wrITR7jzwx/D\n3IcRXUdHZ2j099doJtbpGzr/dXZ+3MA9wy/ae4eysjJuKJnGgb+uJhQYeORQgObTtTSsfIcHbrnz\nsuvs2tra+NsTP+fGYi/Xz8i/oBLoSrLDwn3XFJHStoMVz/+ZaDQ6jJLq6IxOzjsjUEqtB9aLyFNK\nqW7hMEVkyIfXX24sXXwj0dcibHhyJWM+cC1JOfGtayulOL19P+3r9vCpW++hoODy2qunlOLl5c9y\nVbabaaWDO3RH04Tb5hXxzIZtbN0ykflXLUiwlDo6o5t4hmbLuu4kFpFr0TeU9UJEuGXJzTww+zqq\nn36dw6s34mnqO5YQxPYEeJta2PunlSTvruFL93+C0tLSiyjxxaF89y6ksZwrJ+YMqRxNE26bm8P2\n1/9GS0tLgqTT0dGB+IzFjwAviMitxA6b/y6wdFileo8iIkyfNp3SklK27NjOW0+sIphixZyXjjkj\nCU0zEA4ECdY2EzjdwPT33cpHplzDlClTLttzBLatf4U7pqShaUM/OS3FaWVObpgd2zazeIn+E9TR\nSRTxBJ3bJiKfB14nFoX0RqVU/DGSRyEul4vF113PddcspK6ujrq6OhrrmwlHI9jMDnJLx5B7dS55\neXmX1bmpPWlra8Psq6UgM3HLXbPKMvjdxrVcd8ONGI3xjGN0dHQuRH9eQyt7JNmAVuBxEVFKqduH\nVbLLAKPRSEFBwWW37h8vba2tTMgkoecopzitpJiaqK+vJz9/6O66Ojo6/c8IftRHmiLmRjr4SGs9\nEBEDsB2o6rlxTefSobW1ldOnT1NXfYr21tiE0OZIJiuvmIKCArKysnp1+J62JnJS7QmXJc8Z1RWB\njk4C6c9raN1FkuFR4AAxF1WdS4zKykq2blxDQ8VuxmZAbrJQ5rQgInh8Qep2hNmxGixpY5i9YAlT\np049pxCCgQ6yHYkPE5FsVXja3QkvV0dntDKii6yd3kjvB74NfGkkZdHpjt/vZ+3rr1C1dw3XTbQy\n+ZY8jMa+DdpKKSqqG1i/+lfs3zWLm2//0LDGRBpq+G8dHZ3ujLS17SfAV4GkEZZDpwsej4fnn/oN\nRcYKHlmSh8Xc/89ERBhbkEppXgpbDuznmd99n7s++jlMJgte/+A22PVHe1Bw2C/Pg3iUUrS3t1Nf\nX4/f70dEcLlcZGdnX5ZhR3QuDfozFv8OeBVYo5RqT3TFne6oDUqpXSJyXZ/CGY388Ic/PHe9aNEi\nFi1alGhRRgyj0XjJ/XFHIhFOVx7lA4vnUJx93YCfX1gKk9p8HK2pYPzUOXjVzRizE6vnCwztFE2Z\nMeLvLpHfXyAQoKa2jhN1DfijIDYXymIHFI3tfo43HCLVYWNMfg6ZmZnD7m58Kf42E8nl1r4NGzaw\nYcOGQT8v55tii8h8YvsFbgBCwGpglVKqfNC1dS//O8BHgTBgJTYr+LtS6mNn8zz22GPq0UcfTUR1\nlyRWq/WScx99fdVLRE68zAeuLhqSt8/WA7VEyu7j8JtP8dB1iYnMCtDhD/GLN5t45F//d8TDVCfi\n+wuFQqzb8BYvbiknOmYW6ZNnY0/L7PXuVTRKy+kKPAe2kd1Rz4O330xJScmQ6u6PS/G3mUgu9/al\npaWhlIr7D7g/Y/FmYDPwTRHJAJYAXxaR6cAu4FWl1PODFVQp9e/Av8O53cpf6aoEdC4+1dXVHN+x\nikeW5A3Z5fOKSTnsj3g4VBeisbWDzJTEeA+VVzQydsaiEVcCZzm7lBOJRDAYDLhcrgu+u6amJrZv\nL2fXrmO88c5mmjJLsU2/DpPXTtLharKyPOTl5mB3vPvORNNIKy4jrbiMllPH+f6yl7h77kRuuHZR\nQt1zdUYncdkIlFJniJ1Q9qzEfnVzgJsSLItu/Rthdmx5m6vHGrBZTEMuS0QozbYRVBpv7mvkgwuG\nNsMA8AVCbD4Z5Y4lIxtrKBAIsHfvPiz2ZP7015fxR0yIwYyKBLEaQpQWZTN/1nimTp3STWG53W6W\nL1/Ftm1VRKNlnGhswz/tfnKn3thpAI/g83Vw5EgrR47sISfHweRJ47Daui9hpBaNxZn5MH9b9SyR\n6DqW3HD9xX4FQ6a5uTnmjlx7Eq/nDEqB3ZFCdk7JOXdknYvHgI3FKraWtL3zkxDOBrhLVHk6A8fn\n81F5YBO335S4M5CTnRbGZmoc60hl/8kmppYM/oAZpRSrd9VSduUt5OYOLnjdUIlGo2x6ZysrVm/F\nbxnLh++cRvLMz5FheXfkHvR7OdlSw4FXy7G++DZ3L53H/CvncfDgQf74x9WEQjPIz7+RQyfW4i2b\nQlKnEgAQMWCxuLBYXCiVT0NDPY2Nu5gxvZSc3O6xmkw2O/k338+KFx+ntLCAcePGXdR3MViOHTvG\nti2v0XJmP2OLhNxMjeT8mLJs9wSpPfUG2zaCI2k8s6+4kUmTJukznovASHsN6Vwi1NbWkuuKYrUk\n9icxIUejJX0+q8rfJNnupjBrcIbjjftrqdHG8MD1NyZUvnhxu908+ewLHKyzkz31YTIdqdhcRkyW\ncLd8ZquDtNxxpOWOw+9t4c+rX+Ifr6yjqU4jJ+ceHI5MmptPUBGuJ2nap87byYloOJ25hMMp7Nh5\nmOnTIxQWdt9AZ7LZSVn0Af700jL+49MF2Gy2c/eUUrS1tVFbW8uZM00Ew2HMRiPp6Wnk5saOPL2Y\nHWxHRwevvfYiTTUbuO4qOxPH5WM4TzjyaFRxrKKKdW//nH175nHz++8hKUl3LBxOdEWgA0BdpyJI\nNLmpVhp9LdzywOd57pn/Y8m4ANNKM+LuhELhCGvKa6gIF/OhBx8ZkbMa3G43P//tX2gwzqVo7tVx\ny251pJI87jbeeOE5Uv0NFBTElniO1m3FPGcJmvHCbTEabTidk9iz5yAOu4209LRu95PzijiVOZbd\n5eVcNX8+kUiE/fv3s+ad3VQ0epDkPCKuHDSjHRUJoe05TrRlPcWpVhZfNZPp06cNe8ymtrY2nnv2\nF0wqreXuBwowmfo/aU7ThPFl6YwtTWXj1t08/VQlH7z3c2RmJm62qtOd/txH7+bdkBI98QPHlVKH\nhkswnYuL19NGti3xR0G67GY6mlooLS3lgw//K6/8/WkOVB9j0eQ08tLPv5k8EolypKqZNw56yZpy\nHfcvvb3biPdiEYlEeOKZFTSariBv3NUDfnZP+VGS8u8g0HqA3ftfZvK462jS/LiyyuIux2CwYLWO\nYXf5URYtnIPR1P3PNnXyXF7buIyS4mKefWEVx/wuXONvIH/eGKQPN1OlFM21lfz+rc0Ub9zBR+9a\nOmzhOnw+H889+0vmT29k3uyBxdwyGDQWXZVHakojy577OR/52Ff1mcEw0d9Q4NYLPDdJRN5RSn0u\nwTLpXHbExhLZ2dl87JEvsH3bVp7fuBpnuIrSVEVOqhWH1YRS0OLxU9sa4sgZSMqfxHX33UxZWfyd\nZiIIhUKcOnWKmpo61r65mY3HDGRNySBSVYXL6SIpKQmJI6x2TXUt7R47ycmpKOvVNB6r5PCR1TBp\nSp8ddH9YLEm43cmcOl3FmDEl3e45s/LY39DGY7/4M87Zd1A0dlq/sxYRISWvlJS8Us6cOMD3nniR\nT9y6gFkzZwxIpnhY8/pKxhVVM2924aDLmDYpk9a2ala9sowP3vtx3WYwDPSnCF5SSv39fDdFRAP2\nJl4knZHA6UqhrTqS8HLdHUEcrneXMwwGA1fOv4or5l0Z62yrq9hz+jj+BjeiaThTMskZP4Z7iosv\n+lKA2+1m48atrH3zID5/NqFwBuVHvVjGP0J1jYNTp72gTmG1+hk7Jpvo1JLzlqWU4nhFDTZrTImJ\nCM6iWzi8/Wukzx+cl4/dnktFxUFKSoq6bShramrmoEdj3oyFZJZNH1CZGaWT8aVl8/uXn+YzBgPT\npk0dlGx9UVlZSd3pN3nkgaFH3736ilwO/WUrBw/OZ/LkyQmQTqcr/SmCrwPnVQRKqaiIjIzl7j2G\nNDeT0mNUG1yyBL77XcjKAsfIh0vIzslh+9bE71atbfaTPXFsr3RN0ygpKencFHVNwusdCEop9u7d\nx9PPrMfrm0lm9sOkZ6dQXbUVU+Z8XCnd5Q+FvOw7UM2paXW0tJhITU3tVWZ7ezsdHRpJSc5zaUZL\nCkFrMkEZnC3GaLTR0WGlrbWN1LRYnYFAgF2HjmMqu4LY2Gzg2JLTybjmfp74x5/4z4L8PtszGLZt\neYNF86yYzUNfcjQYNK6/Oom1W1bpimAYGJKVSClVkyhBLmd6KgEA82uvwVVXYf6v/zqXFk1OJnjP\nPQTvvpvIlVfCRZwC5+bmUucx0OEPYbcOfR/BWY41CjcuSdzOYoitvdfW1lJXV0dNTTPBYBir1URe\nXjo5OTnk5ubGvXyglGLVqjd4cWUVGdkPkJb1rptmVf1BLGnX9XrGZHKQnDKeKEE2vbOTmTPyyM/P\n65bH0+4BnL2e1SyZePztpPW6Ey8O2j3t5xTBoaMVhF35mLxhopFYXKdoJEJHWyPepjqCPi8ohcnm\nwJmegz0lC83Qu2O2p2TSNmYhz724ikce/PCgpTuL2+2mvmYXk5cmztV3TEkqr7x5nPr6erKzsxNW\nrk7/imAT4xlJAAAgAElEQVSCiJxv6UcppQY2B9W5IFpbG9bHH8f6+OO97kUzM/E8/TSRK64Ylrpt\nNhulU69mz/G3mT8l78IPxEGbJ0DUkZ8wQ6TP52Pr1h28/voeWludKFWAwZCDppmIRkNEIvWIlJOZ\nGWTJkhnMmTP7gl5Ga9e+xQsr6yksfgij8d2NW0pFafU0YCs6/7KG0WjF4ZzJ7vI9GAwGcnLe7Zzc\nbi+a9N5Nbbak4eto5fx+GP1jNDpobXVTVBRzyaxu9uAaNwX3qUNEtQgnNr1C4/Y1mP0dOJXC0hlC\nxqtp1CkIWm1kzH0fudOuxpbUXR3lTLyCPa9upba2ljFjxgxYtq5UVVVRlCcX9BAaCJomjC2Kla0r\ngsTSnyI4QcxgrFtmhkj78uW47rprSGVojY0k3dR7M3fwttvo+OlPUQmYzs+9ciErHt/A9LFDnxVE\no4qKeh9zr1maEOPe0aNH+dOfXqe5eRzp6R+hoKDvjkAphcdTw1NPbWHNmid48MGlFBX1PSM5ffo0\ny1fsp6DokV5KoKX5OL6AD4OnCs3kwGTNRLTenZrRaMXumEp5+W5SkpPP7QIOh6N95rdZc/F4WwiH\nA93q7NKCzn/Pv78gHI7Zcmpq65DkXFDgK19PTf0Jiq12Zqdk9Orkz+IP+ql5eyV7N71C7uJ7KZix\n8JzhWjQNY/Fc3tm+e8iKoL6uhrzsxAcLyMkyUllbQSy4gU6i6E8RBJVSJy+aJJcx4euuo6WuDvOK\nFZj/9jdMa9cmrGzzypWYV/Y8VRQ6vvc9Ag8/PKDlpdzcXCZceSuvbnuRu64ZWkiILQfqcM3JZfr4\noa/nrl+/kb/+dT8pKfect1M/Syxscz4u1100Nx/l+99/iY9/fD5z5szqli8ajfLnP6/C7no/JpMd\npaI0Nx2lpnkzbcEKsIeR0kaCzhWEPX6CDT6MWiE2+3xsqVPQDO8qSpPJTsBfzIGDx5k9ewoAmkFQ\nqrctwGrNRTXtP3cvFOrA42mkw+fFH+ggGo118kajGZvVjsOejMORgabF/lSVUhgMse+lrtmNKbmE\nphW/IHnHGubNWojD3v/5TlazlTHZheQF/Rx59Sn2Hd/LpNs/idEcU0qpheMp37aVj/RbyoXxdbSQ\nm524JcazJDktdJxsSXi5o53+FMHGiybFaMBsJnjvvQTvvfdcktVqJXjbbZj//nfMy5ZhOHo0YdXZ\nv/Y17F/7Wre0aG5ubHlp1qzzPAWLrnsfz5w4yJu7j3P9zPxBKYP9J87wTrWL//eRqUM+QOadd7by\nl78cIS/vE5jNTsLhAGfO7Kep4zTNwToCkQ5AsBodpJtzSXcUkZ4+CYPBRFraOOz2h/jDH57CZDIx\nffq7HjHHjh2jqtZJUckE3O4qDlctQ3KDZNw4loLCW1AS5WTtfsyZ8wCIhkJ0NNTSsucNGo+/jCvl\nbuBdJedw5lFXd5oObwd2h50kl51o1NerPbbUCcj2XxLwtnDGdxKPzw+GHAzGLIw2JyKxP8lo1I83\n6KG94wxaYzmpqRmkphQQDvtISrITjURxu72Etj5L+u43mZhTdEEl0BWr2cq03BKOHd/DgRd/z5Q7\nP43BaMKalEaVx08oFOrzuWg0SltbG4FAAIPBQEpKCiZT4jv8/tDdRxNPf4pg9YUeFpFblVIvJVCe\nUUd0zBj8X/0q/q9+9d3ESATjpk3YH30UQ2VlwurSamtJet/7eqUH77qLjh/9CJWcjMlk4oMf+RR/\ne+Z3uDcd4aa5eXEHoYtEomzcV8f2umTuefBzWCyWIYX6raur49lnt5Gb+0k0zcTRytc44d1LqLQU\nw+QxmNPmY7LGOr9ARxuVLbWcOHkI06E1lLlmU5S/AKs1lYyM+/jTn57iP/+z4NzJaW+9XY7FOptT\np9dTFXyT/FtnklZSeq5upRREg6hoBNEMaCYTzvwinPlF+BrqqH79r/jc9xMNlwBREA1FDtXVdYwb\nPwanywk09mqTIJi8Xk5t+wfmCR/C4shFARF3NcGWcuyBw5hDdUCUiObEZx5L2F7ImYgfj2cfTge4\nXKUEQ0G8R3aRc3QX+ZEQqbkD99MXEcqyCjlwrJxT29ZQelVsGU+zpRAMBjF0GpUDgQD79+9n48Y9\nVFRUEwqZEDHF2k0HeXkZzJs3iblzZ5GcnAyA3ZFGu6dvZTIU2toD2B2DN7Xr9E1/iuAHIlLN+Q+r\nF+C7gK4IEo3BQHjhQtw7d3ZLlqoqHJ/5DKaNiZ2smZcvx7x8+bnrVOCLwI5PPMRvm2pZOMHMtDGZ\nmM9j+ItGFUdON7PhoAdbwTweeOTuIe8AVUrx7LOvYjbfiN/fyq6qf+CdOBbnjE9jt/Ue+RpsTizp\n+VA2l7CnhQO71lJ9+A/MKPwALlcebvcCli1bzSc/eS9KKQ4cqKbdl05z0m4mfugmTLbuhl0RwWq2\nEwy1Y7R0OXZTgSnZSs5N44haj3Jo639jTJ6KoJCo4GsCu7aIzIKpmE0BwiE/RtO7toDG2p1Eg0mY\nT3gxlELIfQh7/QvkOiqYNEFIzbBhc9nQNCEU8OJuPk51VZjDFRYazXPpyLRj0MrwNNRi3LWOHKuL\nZKsNq2twnaOIMC4jjx0bVpBRNg1XZgF0HgWqlGLHjh0899waOjrScDjKSE+/AqPx3Yiq0WgYj6eZ\nFStOsGLFJt73vuksXbqYnNx8Du1O/Mi9riFMTmHphTPqDIj+FEEd8KMLPH8kgbLoXABVUICnD3uA\nafVqHPffjyT4HN85f3yyl0nOl+bg+OduwFecgdcXpKZVUdmkSMqdyBW3LWbixIkJmbqfPHmS48c1\nrDYzm+qXY7zpDpJze+9H6AujM5XkhXfjLd7PO+ue48q8u8jOnseuXZtpaGjAaDTS0OCmPWMH429f\ngslqRSlF2O9DRRUGkwmD2YzLkU5DR/05RRAOtNLRfpywUUF6Lo5J00i9oZx2z1VI/jwivmYaW/bx\nTtVxLOVvkOosps2bRHJKzH3Y017PmdPbycv+MEZjEnVvfI1JMxTz359JRl7fNpnU7GSKJ8HsjgCH\nd69n+z4rG1dDkcFNvs+Dxe8jecw0gsEAmmgYTaYBex2bTWaKDEaqt7/BxKUPogJeAH7/+6fZubOZ\nrKzFpKf3fQa1phlxubJwubIIh2exZs02du/+DQ88cAunayAYjCRkHwHEBhzHT8GMqwe/S1mnb/o7\nmOa6iyiHzhAI3XQTrU1N3RODQazf+x62n/40oXXZmr1M/a/eygigdd/dqASt327aVE4wWMj+jlex\n3HI/5tSB+6M7iqbgv8nO1lXLWVDyUTRtDlu3ljNhQgm1vpOMv/Zemo4ewN9wmFBrDWZTCM0gBANR\nMKdgSCqgwxzF6Cgi2FGDL3wGySnDYM8AFBhMpCyaRevTK/HachBnLpHUGbidFshtoWb/q3DqcaLF\nD+BKHUtt3RFM/g4cmVMIeR7njnktlMxQmDILLqg8LVYj067MYvKMCCv/9hz7t55iksdNIH8GVU1e\nQEBFERXGajGR7HLgcDjQ4giFAZCdmkXl3s145t2EWfnZu/cwe/ZoFBcvjXujmtFoprBwAU1Nlfz2\nt8uZNKGMfYcrmT0tMa6eRyuacSRP0IPPDQN69NHLFbMZ/ze+gf8b3+iWrJ08ieNTn8K4bVvCq0yZ\n2iM8wTe/iemVV2hftWpA3ktKKXbvruS014K2ZOmglMBZrNmleK5ayL4tLzExbzF7967E421Gpfto\n2fkcZZM0Sm5MIiUrB4vNdK5+T4ufpppKdm9u4PiKLTDzfbhm3wAGI9FImGDIRySqMCRnkX3tDKo2\n70HSJkPYgMXuRBzpmBd8Fk/22xzf9GdcSVcRbq0hN2UeIc9TXL+wmsmT5xAM1OM9sZtoViGG5Hzo\nw+UUpYhE/JhNUF15gmTPbkINjaSakpCGg2jtNShbKhFHJoakXIKiUdfSjtbURlZ6Mi6ns5c3qlIK\nn8+P19uB3x8mGAzhaa3n5af/hPP0NhZOvRKHo4DBeI+np5fQ3Czs2bcev9fLlPFhLEMMbx4OR3lz\nUzvzr10ypHJ0+kZXBKOMaHEx7at7+wGYXn4Z50c/mvD6jNu2kZqe3ivd96Uv4f/61/t8pr29nYrK\najwTFpJcMGnIMjjGXUFDxQEKvfXU1Z1k15EtzLrawFW3lp3r/LsiIrjSbLjSbGSPNXOispZ3Nmyi\nZbNgm3M1YaKIwY5oJkSMOCZMwPTWS4QCt4JBnRvda5qBpPHXopSBptd/jt3jhzwXM2YdZdKkmBus\n2ZKN0ZiMr+EEgTOnISUbsacgZidiMKFUFL/nDKd3HaJtz3Em2sLMwkKwyEFuNErYGEFLsuAPtuL1\nNFB3Zj9+Rz6m3CkoLYXapiY8Xh/ZWemEQ2Ha2z20uT243R1EIkbAgaaZMJnsOFSAqhMnUS0L8PuL\n2LTpeZKTtzB58hzS0ooH9M7T0oqpqppA3Zkwr6+v4dYlRTQ1+9i7v56Kg/VUHKmnvb2DcDSEI9lI\nRqGdsWVpTJuQS0Z6Gqkpqd1mSW9trsWVdjUTJkwY/A9B57zoikAHgNAtt9DS3Nw90e/H9j//g/XX\nv054fbYf/xjbj3/cK71t507cRiO1IR+O6QsTYm8QESwzruHQyuWYApu45ZMWsq/IwWjqf8kjHA7Q\nEfaSO2U8N5d42PbqRg6sa8Z5/T3n3DwBNLOFpLIMGpoOY8odj1KKSHMl0fotGDuO4ApW45rQDs1e\nbPwPU6YWE/AHMJnyMBidaAYrDsckbJEAodYGQi01hJWXcMRPS7OH0+WNTDH7WTAzB1dSOqu21ZPk\njOKKBmhr9yCRAA6bHYfNRqZStLTXcvJYPeHcmVhT8mhrP0PL4QoMmplgUBEKCQZDIebOvQNKKSKR\nCJGOAO1nTpGVcSdmcy5JSR/D5zvFpk1vMGbMCSZMuAaDIf4uIzd3DqdPV7J1T5itG99EWj2ktntw\naQGuSLNizzOhGW20BxVNJ4PsPlrFxrdqmTjHxeTSZMYWlJKbk8vOvQ2UH8nggQfv0l1Hh4kLfqsi\nsgP4I/CsUkrfyTGasFrxffvb+L797W7Jhh07SLpxeOINJs+ezTTgAMD6Z86lL3jeN6TYS6aUHNqD\nb3D7zYrSmZmIw4K3w4/ZfP6Afx3+FsSRimYwYbPbmfP+dKIvH+DQ9g24rryhW15bXgrq5Ck0XwqR\nYytITm4kd142towMjLZMxLiYpleXsaDQR86UCCpwBk99FUFfKhbzRDSDDc1gwWzNRwv5MUW9uD1t\ntO0/yF35GsUFZQSViY5AlEhEYRSwOcz4/GEC3jNopgIQDREhLcmF0xbieN02mvyTCZiziEZdiL8d\nIRmjsftoW0RACbRVYQ7PwONx0NbWSCDgx2YrxmJ5gBMn1tLRsZpZs5ZgMMTnTqxpBtpahIqqQxS2\nt1HsbGLspCScKcndwnA77JCTYmUK0OQJse1tD2eahLbQYU6uOozHP4cHHvwcTmfv2E06iSEe9f5h\n4OPANhHZDjwBvKaGulMIEJFC4Ckgi5iL6u+UUj8fark6w0tkzpzeswfA8dBDmP/xj2Gpc+OHeh9K\n8+xtX+CXH/teXM937HmB2TfYSMl0Y3ZasSfHgrdB34ogEgkSIoLR7EApRSgcwGRJZe5SG/V/WEP7\nyWxU0dmfrWBMTkGrX0ey4S3KlhTjKJiKFunAZncSDBmJRC1o7kYmTU/GYleYkjQc6el4m920nFwH\nHaWYzCmIRLHbLWiamb1vHmecoZmDJ4VNe6rQwhEMCAfP+MjoCBNONWM3gRmNYHsDRlf2OWVpNpko\nTbXhrysnkHE1mF0EAz6smq3XqFqpKJGmg+A3IcaxWCwFKOWiquoABQWlWK1JJCXdRH39GvbvX8e0\naYsvODJXSnHi6Hqsp8spCTeRVZRCxJ7K0cpGCvMDpGdY0Qy9y0h3mlhsM/DO9hZ+95aB1LmzKXS6\nuoXdvhBKKWpra6mpqeFUVSMebwCDppGbk0xebjZFRUVYrX2F9xi9XFARKKWOAv8uIl8nFnvoj0BU\nRP4I/Ewp1btHiJ8Q8EWl1G4RcQI7ROR1pdTBIZSpM0J4n3wSb5drq9VK4P77SRmmdd37V/6U+1f2\n9op64Ec7OFE05dx1oKmKtNBGxl5dhJyux2AwYLPZsJjbCIU6MJl6B4cLBr1gcYII0XAAJUZEM2Jx\nOFnw/lxWr34Lrr6SqPcUSgx4yteRn3mQCfe8H4vTicVqxGzJQ9MMBNraCbrbSUszYrYHMFpyIFhP\nWloWKakuMvL81B+qxmFwkZJaRCgc5ulfrcJ58hRJ1jBXJrnISTHgMMZG4rsssOGYm0xPgNpQlHaE\n9Iw0cNdhcGWCaISDASLBEMUuA57aTbSlz0Iz2AmGGrFqBec8gVQkQKTpMFa/UKdSEXMJAJpmxmAo\npbr6BEVFEzCZrCQl3cCpU8+SnX2M7Oxx/X431VW7iB55kxkmG20SJG96ESaLmZaGVI6erubgkRaS\nkxTJTsFmM6EZDIRDCo8XWt0KpyubeekO6swO0hfl88fnn+T/PfgZLBbLeeuMRCLs2rWb19buorpR\nA3MxRmsRJpONqIoQONCCFjmEFn6Nz3/6DlxOK1lZWRf8nY0G4lrwE5EZxGYFS4mdUfAssSDya4GZ\ng61cKVVHbL8CSimPiBwE8gBdEVwmqMzMPmcPlp//HPtjjw1LnU9/ue+AZI/d8SmsNjORSARByM5O\n5fSpZqIGC1oPb51wNIhmiu2SDUWCoL07I8kcm06a6QQS0rA5C3Ef3ENy9DRj776S5MJxSA9PG0Hw\nN7VQmGMAzYAIRDERCndgMjmwORwUTCuiZt9R/LVG3ly2m7Jjp/h4kYbV7EB6LMXk24z4DRrZFsix\nCPWeIJVNbsRmxu6rIGpxETU5wWjFYtIoCLbhCXmIOrIISwhfqAYjVrSgD2mpwkEWZkseze1HMJvf\njRRrMDiIRLJpaKgkP38CIgbs9iXs27eMzMzSc/GPeuL1NnNm/6tcY0um1XOY5LJsGpua8PsjiBiR\n1BwMriyaO/w0NHkhEgAVweZykp6dQf64FMxWC4WA72Qd3jOtUGpmzfq13LJkaZ911tfX88xfX+Fo\nTTIpObdTMKXwvLOWUNDHqcY2VvzmGe66ZQYLr7nq3C7q0Uq8NoI24A/AvyqlAp23NovIgkQJIiIl\nwCxgS6LK1Ll0CXz+8wQ+//le6alpwxc+4LHrf9f5v3d/YqfvLGXVt+ZjsWZ185cPR0OIwYxSUVRU\nIV2MpJomTJxhIdzaRLjdR/DAOqbdMg6TZPVSAgAGo0bY78dhV2A0x84NMNgJhfyYTLGlKaPZjJbi\nYN3PXmN+EywutGLVfIjWe+kq06KR6jBQ5w+RbzGQZISpmuJwaytNjmRSTYC3GcwOlNFMqs2Cs6kS\nt7MQogoVaCPsPozm85FkHo/Fmo8n3IbXkItZ6z5CNpsz6ehooaOjFbs9FbM5m7a2XM6cOUFWVt+z\nglOH1zAZwe+tw5hpJhCO0tEhWG1p774fC9gc7+4+V0oRCvlo9fnQvF5SLSY00ZiVl8HqlZtY+J8P\nsuVv25hTN4ucnJxu9R0/fpxf/P5VJOlGiiZNv+Cylclsw5XiIn3sw/z1pZWcqPw7D9x/50WPmXQp\nIRda6heRMUqpih5ppUqpEwkTIrYstA74llLqhbPp3/rWt5TP927grkWLFrFo0aJEVTviGI1GwuHw\nSIsxbAy2fUcrKjhqtNESNhAJp5ESDHDvy78YBgnPz+77ygjkxDaOhSMRROveSXS0+kmJTmZLVQ2p\naX6sDiOipaH1YXwOR8K4a5vIlRPk5wsGZQAxoEV9WKwxA2g4FOXY1gaKfX6MrRHyk4xEomHE0Pd5\nCvW+CBUtfkrMGoFAFCVmMBhpDkUImK3YrTZUNIyKhFBK4Q6EaSEFMdoRFcVoTouFkfA1YopaaAOa\nomWYzTE30auusvPOOx1ALACe0diBy5UBQCjUhM1WQ15e7wOXQiE/zZVbKDZaaPXUYMtKQSSMxWI+\n7wyiO4pIJIjRCC6XAxGNBreX6PhCTDYLSV4bE8rGn8vtdrvZtPUwZtcUzNb4w5qMKdCoqIqCUrSd\nOURBVpiJE8bg9Xrx+XwopdA0DYcjtjHPaLy0HSw3bNjAhg0bzl1/5zvfQSkVt3dFPIpgp1Jqdo+0\nHUqphAQEl1j0qpeAV5VS3RZ8H3vsMfXoo48moppLEqvVOqSgbJc6g23f3r17+e2RU7gW3sDbbx/F\n5ZrbZyfypT98gbtX/yYRosbND098CVAEPH7STy7i12+8zBWfnEX7kWochYv6PIMgEolwet8xCutW\ns2QJmJUVzWhD+atJTY2FS3j7H5UU7KxnulXh2d/IlGwXwUgIMfVtzI5GI/z5eBtGd5C8iAHNHttt\nG4xE2O0J4MorwWaxEg4HATNt3nb2RcehksehvFXYzLHDh1Q0RFPt21SbJhA2fJpoNAmDwcQXv5jO\nT35ydre6IhDYx5gxkzEYzEQiXoLBJ1i8+P5eo++TlZtx7VuFubEZQ36QlMICIpEzpKRmoEn8yy/B\noAeLNUp+fg6+QJg1HX5u/q9PsPWX6/jG5/4dg8FAMBjkf3/0BG7jUtKzxl+40C4snm9kzeYw0UiY\n+uo9nN74PaZnhZiWm06mFvPKCiihPirUhRT502cz65pFjB079j3hwpqWljYgRXBeNScik4jF2U0R\nkbt4N/hcEpAQk7vE3ujjwIGeSkBn9FJcXIy8/ibOJbcwcWIGBw/uIylpWq91/B9/8qf8+JM9fjZK\n9elhlCi+Utpl78M3s/j0T55m656d/Oyr/9SnEgAwGAy4slOp3R1BhcOIqXvQvMb6Djxb67im2E5T\nrRenWaFUhP529QpRPlBs4Vd7AhixcnaxxIBQajJwvLkRa24BSsXcQ81GE2ZvM4EenVhH2EtlygSC\nWiaucAder60P91AB7ASDHdhsZgwGB6GQkWDQi8XS3aXTd6aSZE+AYDRIarILpSKxiKYDUAIAZrMT\nv89NS3ML6enpGBtbiATDGJKNNDY2kpOTw9p1b1PrLqFo4sCUwFnaW6uo2fYnir0nWJiWTkawkhtK\nsnqdaheKRNh/ai8bf72dHVPnsPTuDw45qOKlRr9HVQK3Acmd/56lHXg4QfUvAB4A9ojIrs60f1NK\nrUpQ+TojgFKK1tZWTCYThw8fBsDhcJCbm0tSUtIFR1RJSUlcUZzPzgP7GDtjNuHwMY4eLcfhmNin\nh083RFjwt9gsJBhsp/nISyzMfI070wN84L7l/T87SOa9cYBn3vhyr/T/+PuvqCuNjfiT0lNpEhdN\nNVUUluaiVPicTeLo9gbmWgSTQYiGFWZj34fanEWpKEKEZC3M7XlOnq824A8EKTabUEqRYjJh8HWc\nOzMAQNM0RIVBRYFYdFG3/wzHUESnfwVDoIXg4U3EQoz19Y5tBIM+bLZY8DmR2GyjpxNPS30FmV6F\nwRzFaLESjfqx2QY3bjSbXTQ3N+N0OklGaG1owZ6bRENDA6mpqby+bh/ZJZ8eVNmethrOrP0f3p9k\noSS/GBHB3dxBbW09xcXdg9qZDAZm5mczPVfxzolynvr+ET7wyD9TWHj5BL/rL+jcC8ALInKVUuqd\n4ahcKfU2EL+DsM4ljdvtZnf5TvbsfQPR2li69G4a3csBoeI0rHkzikYa06ffwMwZs/vdIPS++fPZ\nuuwFguMnMGF8GS5XLXv37sbvz8duz8VwnrVzgEgkgNdbjdlcx9xrJuHbtpYzk70ca/oPbLbYbMHj\n8bDt4C5u/+ftJO1tOm9ZQ+Hbd3+2d+JPYdn2PCKhNgziw91ezanNJ7k120IkHIzFjhMA1dlp90SB\nCmHQwB/SSDfa+dD4AlZX1VHf4WOcppFkMJGjCQ0+L0nOztmHUijRUNEQ4UiYk8FT1DtL0MY9hNGe\ng3IUErRvQPM0EIn09b0YuiknpaL/n73zjo+rOvP+90zvGmlURr0Xd7liY2PAgLEpBkIxCSSEkk3Z\nZJNNsptN3mw2W95ks8num15JgCUQCKF3TLOxjXuVmyxbVu9lNL3d8/4xclUbS7Kxnfv9fPyx5s4t\n596ZOc8553me3zNsbH9/bw8GbRpxuhBaDRDCaBy/RLZGY6G/34NBQDQUQWfSEwqFOHjwICGlmIyz\n8Ascp6NpB9LRzuqsdBzGk7NHkzWbo8f2UliQP+xkTKMRLC7MIaenn2d/8f+49YtfJS9v5JrWFxOj\nLQ19Q0r5A+ATQohPnPG2lFIODflQ+atESsnWbVv4cPMzVE2Lcue96WRkFmHWOSiqPF2jpqPdx87t\nz/L7R17miiV3M7t6zrAzhNzcXG6eMYXn17xG4ao7yMnJJi0tlfr6ZhobtxKPOwE7en3CoShlnGjU\nDwyg0w1QVpZBUVE1GinZ+vsGyldVnjACADabjelFVbz4c0iflofFcUrnp0iuNJ27vMY75p2u3nor\n0D/TRvuKNIQ+hD862OFKyeDazonXihLBYNASjwTx+gWKIZ10o4HVxfns6vOwta0LfSiEOa7Q6xtA\nazIhEPQGfHRFDXQNHGVAY4GSuzFkLUEM+l6E0IB7DuZgM35PBnCm0J9yMvdAxhDCO3RZKBgkFIqh\ntRiIS0E85sNqNybpJB4end6E19tLTG9Ao9WcMEC1dc3obcnJkp9KwNeFd+vDVF22mhbj6UuIBqON\nAY8gHA5jNI2cr1DscnJzvIdXHvs993/9n0bNbbhYGO0T2j/4/3aGVtSe/KrUKhclkUiE5194goiy\njXvuzybNNfrSTZbbxoobbcyd7+f1lx+hvv4At6y6e9iojGuWLqX+qT+z563XyL9uJSaTiSlTyigv\nK6Kvv4+BAR8eT39CckGnwem0YLdnkJpagVarRYnFaHr1BcrTivH1Dz1/RkYG1VotNfsO4HfbcBVk\nodFqQSNYG/kyfr+fll4visVJKKql+IM2Vt3z/KQ9u1Nx7vHh3OM7ZUsiWq59mR7Fbkn4DGQMg0GL\nTtJ5sYQAACAASURBVKtlwB8hGM9Aa0mMiHUawTyXk+l2C/XeEI2BEB/2eenSaEFCj87E7qyVyJQC\nnKlL0emH1hfQ2ouJ62pISTESj4dPe0+IEHp9YmQfiXThcDiGdPAejwepSyOsRCAuIR7AbJ7YiDkR\nbqqjNxqlKtVOx94WnPlODr+3B5vj8rM6l5SSpm2Pc61Ng1E3fKio0Nrw+ryjGgKAykwXtYebWPf2\nW1x3482j7nsxMNrS0MuD/z96fJsQQgvYpJSec980lQudWCzGs88/js25m9tvLkla+x4gI9PKPZ8u\n4pUXNvP8C3Fu/9gnhyw16HQ67r/zdh5/7gW2P/MEWdffhMmZik6vIyMjY1Rden9XB11vvsLSNBvz\n7/sC7274BTOqhy5npKWlsdA2n7r6IzRvrsWU5cDqcmCymbFYrTgCAfpCPqJ+hQMVRna+vJK+dh3v\nrC3nc4vu5tWHzbz20D+N0IqJ4363e9jtR+akoHENlefWa7UUWcwUWKzs1JiYt3ApobDk2QPdiNJb\n0If60Q0myp2J1pxJWOkjN92JXg/h8ABGo52ETyGAXp/o1MPhWoqLc4Yc7/H4UEz59Pt34ySAXmNP\nupbBaMQVDT2xECmZTvxtA2Qtz8IzEMCaP/aykBKPEYn4QEq8nnbSeg9QkV8w4v5SGEes13wm1xS6\n+fn7b3P5VcuwWkfWrLoYSCah7Engc0Ac2AqkCCF+IqX8r3PdOJULm/Ub1qI17mTlzcVnZQSOo9Vq\nuOnWQp55cgubNpdy+aIlQ/YxGo08sPpOpm3dyp+f/ANdlTNwVc/B4kof9py+zg76dm/DUneQz121\nlFmzZgKwZdtUdmw5xryFQ0eoBoOBqZVTKAmX0N7eRk99H63+FhShoEiJr6uXABaiplxMaXPZ+3YL\nuspPojWlMNDi48EdQwv1aGJxfrfg1rN+Jskyf4cHON1158lIo272VCBGXAo0Gg1anYHO9mO0WeZC\npAeLoZiRopGERo/U6pAyjt1uxW4XDAz0otFoMRq16PUmFCUM7CMn56Yhx3u9A8SEj3ZNL9PdFfh7\nO8A99DpnS48viKkqi762HjIsLux2e2LJbASC/l46Wrbi9+8lEmnBZBEIAR3797My2k9f9wCx6Ci5\nsEmud5j1OooiXp5/9i9k57qJR8No9UbS09243W4yMzMvilBTSE5iYpqUckAIcQ/wOvBPwA5ANQR/\nxbS3t7On5kU+/dm8cRmB42i1Gm5Ylctjv/sLFeVVpKcP7eA1Gg2LLruMaVOmsG3nLt7+y+M0Cy0i\nKxtpTThDhdeD7GzHpYWPz66m+qH7T3NG37jyLh55/Pvk5g+QnTv8SNJkNFJUWEQRRYmC8rEYEpCK\nwq59B6hp7Wfv2lo649fjyJ2GzqrQczRANBhCf0ZkTCTq445nPkdKeQYORyZ6owVFiTPzqTf51D88\nO+7nNRopXb3MfWv9iddXAezZyco5N+LJLcSGA51u+NnASeSgS0Lgdmdit/tpatqD1aohGOwnFNpC\nWVkuJlPiucfjUXy+bgYGjuL1rqWsrAiNZzoIDYq3g0ggiMEy/nBeKSX14Qh5l1XRsPUI11YnBgsp\nKVYCoQEMxpMj8UjYT8PhlwhFN1NabSWnJIMU10y0Oi1SStb/eD9LMtKRwT5isRY6WtfjTJ2B0Xzy\nmQgZRm8YWhP7VOKxOG3trXS0HsXo7eXIh41Mv30KOpOGaDRO20HYulYiddlUz1tO9ezZF3zWcjKG\nQDeY9HUr8AspZVQIofoI/srZtPldFl1hwGYbOXonWRwpJuYt0rB5yzpuvOFjI+/ncLDsyqVcvfQK\n+vv7aWtrIxAIIITAWppDdvayEcNTnU4nN6/8DC899QtuXq2Qkzd8Dd7jCI7LHkQRQjBr6hQO79rG\nrpdqCZUtwNDTiNAUonHOp7Omjtz5iepsSixCdKCTYPMWnJVZpKblodHqiMciRINdNN+/mJ9/ecWJ\n6wQHAqz99MO88sre8T28JHh9x6uw49Uh2/M/2X/aayUWQBOXCHFyfVyjiVJW5qCysoC6uh1Eo69j\nsZTT0vICUipotREKCrJYubKKpiYTW7YIZHYpNTtfYprRTX9DO5lVBeOWEG/3eOnPTKPcakYcDTPj\n+hkAlBVnsvFgG7aUxPJYX9cRGo/9gYr5gqp5s9DqTs9b8A/4scaipNjsYDOTmmUjr1LQeuRD9IFS\nnGllIAQy7sNuKx6xPf19/dTV7sJp8TO12Mw0fRp1rREum51z2vdOSklzm5cPdz3Cru1vs/LmT13Q\nEUbJGILfAMeAPcC6QU0g1UfwV4zP56O+YTPLb8kde+ckmVmdycO/WM+y4MrTonuGQwhBamoqqamp\nZ3WNsrIyVokv8vJTv2fafA8Ll+Sj1Z5cw5bAgMdDW0cznoFuYvEQeoOGgf4oa1/vw9+Xw+fvvYfd\ne47y4SvfIZB9H7K9mSO1m7CZBjCZBRoljkVnRJ/mIC2/jFg0RMDbiVR82GxmApEw0b4YJoMBo8mE\n2WEh+8ZqHi1KIUdAx74eMkuK0AiBr62L216Z/JKix2l6fKgx/EPqFfw+PRGbH49HiEYbWbBgGorS\nS2XlEb761e/hcDiIRqNoNBocDseJXIXt27ezceN28vIWsL/tIF2dR7H7TQx09OBwD7+UNxrBSIQ9\n0SiZV1TTvqGev7/riyeSvSrL81m77Qgwh57OWtpafs3SO/JxZQ+thgcQ9AVJ1Z3ur7Cl2Cidaaal\nrp7e7gg2RyFmIyNGAbW0NNPWuIfKIgOpzpOzCCUYJRKJn1aOUwhBfo6D/BwHB+t6eOnpH7D4mgeY\nVT17yHkDgQAHDhygrrWJY53t+IKJwU2q3UFpVg5l+YVUVlaeU2G8ZGSofwqciKUTQjQAV5+zFqlc\n8DQ2NlJQLDCZJk9/xWo1kJ2r0NzcTHn56BLHE6G0tJQH7/smb7z1An/42XZmzDNROTUdnT7O4SP7\niDNARo6RtDwjvd0a9u/w03hUww13XENekYvGI430BQNkZWVQ4tJTru2nVzeNrvePMu/uqzHbHHR3\nHECk6unrOYKikxjsVky2LBSdjiDgj8WQoRD092MzGEhfVMLW9Qe5whumeM5MrKmJpStXUQ5r3OmE\n6+rIN8dJUwR6nQFNTRuZDf2j3+g4eaDvAx7YWAjX/QsPbv7XxMYa+Pv7vsH9X/3EqKPaxHuJMqhl\nM1ZwYNOTVHhjiNpGfL1d6PSgDGpPabQ6dCYzepMNS5oT7RlRY8FIhE29HlKuW0Lzxl18/oZ7KC4u\nJhKJ0N3djcViIebfSVfbVNpaHuXKuwpJzRx5YCAVyXArmFqdlvyKTBoPNdPT3s+C6pxhXShtra10\nNO9m9hQbRuPpHbIAlFF8FlVlLjJcQf748u/Q6/+WqdMSEumBQIC31r7HxsP70FQUYK3IxbF0Cg6r\nGSklIY+X7a0drN+/CdN7b7J87kIWzV9wTgxCMs5iE3A7UHTK/hL4t0lvjcoFSzwep62tjY6ODta+\n8yY6cyNr346SmW3HnW0nNW3isg7uHGhrbz2nhgDAbrdz5+2fpKNjOdt3fMjP//MV2rv3UzHDQqrL\nwq4tfgb6/bgyUqmcNptlK3IwmhJrvOmZdmYvlNRsb8GkeLn75qmYjFZeeqOfgy+8TNW1JfQPtGKv\nKsOSnYnRakUz3LKIPbF84Pf78ct+dvWGKTc7qEw96b8QCNKL8wikpXB01z6a2tuZW5yLbVEFrVP6\naOkNgNkFCCSwYO3uc/bM/t9jP4DHfjBk+6kS41lZWZSWumhvb8HhyMScU8K6/buoskeYkiKwZ5iw\npWcghCAWjRP2Rwj099B9pA2DNRWH241Gq6Xd42VPNIpx4Wyathym0p5PSkoq3//NH2jp8yBSXGAw\n0pFm5sN3v8zVt6YTF2YiYcNpPoNT0Rv19CrDd9ZCI3AXpVDXfRiHY6hcRcAfoOnYHmZPsQ4xAtG4\nQlwjMOhH75xdqWbuvsHF/778B3LzvkNnZyePv/UK8ZnFlHzxE8P6UUx2G868bFhQjb+7lxff2sCO\nx/fziZtuGdaXNhGSGdK9CPSTyCe4dBXSVIbF6/WyY+sWata/jSPqI8eoUNJ+BFf6AMZNvRwJC94P\nSOxF6cy+qpQp0zLH7TxOTTPQWNc+yXcwMpmZmZiMFgrKHdz31buIxRQURcFg0JGabkWnG/7HLYRg\nxrw8LNEU1m95joUz7+K/v//vPP3MUzzx7DO4rsykoLQ4qapaPQe6qXu3DdOtK1nz1iYq+724nac7\nKy0pdgquWMDRd7dTH7UR7vNg1poYiPiJKkEUrQlfVFK36HL2aGwcnH0jFTc8lNAYCvj499vPXfGV\nM2XD/x14eMoinikvJ79aw4J7bqdh71H2fHiQ3M4AOZFe7GkWDGYT+jQLtjQL6YUK3c0DHNy3ly67\nC09WOvqcQry7/MjuMJ65Np5qC+C8YhU5mdmJXA9Ad7AGjaWOjOvm0Bf00dddQ4rOgctVhvaMPAFH\nmoN9MYgpCrphPhepeKiqdtHS1nT6kqOEusN7Kc4RmIeZAXf4orjcjtOWGEciK93K4pkD/P53P6bZ\naidv9fJER58E1vQ0qj5+Ey079/OTpx/nb2//+BA57omQjCHIlVJeP2lXVLkokFKyr6aG9599nGl6\nP/cVuUi3J3wC+zXdZOXETySPKYqkrsPDhsc3sbs4ixV3zRwzsWw4NBqBooyssTPZ7K3Zy/6G17nt\n01WYzGcf1WEy61n1yTJeePQvKIpga3sn+R/7Arv+8lsC8a3kznWTWpqBwXGyPKSUklCvn57aTlq2\ntyFNGZTcdy+m9FRa8tz89nfP8jcV+bhTTs/a1Wg0WNNSKCueitVqxe/309fXx/Z9R7HkzyTVnsr2\nznYOZJRReu29J64Xsdj4xusB4rE4nV2dNDS009fn5+82PsZD254Yck+TwUMHPuShAx/CGVVLv/TN\nu9i4+wiaeh9WpQ+DViD0WnwaGJDANBstrV6sfcVkG6axq209TC/FOPcGOjU6xJFWTC09uFwpOJ0p\n9O5fx8KVpcQ0QbRpbjTp+Xg6juFr3U5OxhRMp0QDaXVajG4XHQM+cp2nfzdDgW5SbBrS0zPYt6mD\ncOhkZvGAd4B4uJvszOGjrRo9EXKqk/eVVRQZ+Plf3qP8mz9I2ggcRwhB3pxpdFiM/OrZp/j6px5M\nhNJOAskYgo1CiJlSyj2TckWVCx4pJWtee4XW9a9yT0U62c7TR306nYFo9GSHrdEIKrItlLvNbKvv\n5k8/WsuNf7OQKWe5whMKxjCOUkx+MhkYGODttU9zw72F4zICx7GnmFl6Uyb//e8/IvsL3yKvuJim\nw3NIXbqA5p01HH53D0JGMNiNICXhgTDCaMVSUID7ptux5p2MNc9dtpimUIiHn1/L9Z4Ac/LS0Z4x\nek3o72iw2+3Y7XY0Wh3rD9axtS+dtrIFlK54EL1x6DKDVqclOzub7OxsFEVh55JqPhv7If6+NiJ7\nn+cbD91KW0sTN91y27ifxVj87Pt/Hnb713/1ALY0KyaThUhQ4a3HdrNm04soSxaTM/t6fBE7usER\nfjAYobOzl1joMKb961n8sUUYTQZa2rqIa1MxZpcQs6fSfOwAeemnG4P0OVOoWfPBCUOgKHEiwR4c\nVklmZjpCCFIydXR3d5Obl+jc29uayMnUDOs3kFKyPaBw86zkDEEsFmNffR2Lr8/hcP1RsqqG1nNI\nhqyqMuo7unnhzde59/Y7JyVXIRlDcAVwvxCiHjiedy6llDMnfHWVC5J33nyd3o2vcv/sPIz6oV8R\nq8WJ39c0ZLsQgvkldjK7Qjzz643k/cuN6M5iYtDRHic38/woOm7c9AFlsyHDPQlywvogWXP1RAM+\n9FYLMhjFXpRDSllBIgTVFyDmD4IQGOxWdJbh1TiFgJxrr6DfpGfLwTZ27z3IHJOWsnQnNpOeeChy\nImomFldo9XrZEY6xxW7hiDmNwrkrhjUCZ6LRaLDarHTW7UB39D3+7v6baWtpom7rn+h6/yvYLAZ0\nOYuJ3fiPiQO8IczXnDvtpR99/g+nvf4O8ND06exeeicG0+kzI73ehNnsIBgI4HSn0Nk1gMWiI8ft\npKfXQ9DvR2dKQVM0hdb6AxTmzEGrSzyzvPJ8trxjYJ4vSFYsTCzYRqbLSkpKyonoVqvdgLenH0h0\n7gN9HZRUDv9MazqDGPNc5LpHFk88lYbmJmIuOxUlmexeux9YnvQzOpPCJfPZ9btnWHTkCGVl4zMo\np5KMIRi+SKjKJUldXR3177/MZ+YMbwQg4WztqB85SqIww8TN0QC1u9somxvHYBg7ykFKSXOjwryZ\nZzddHg/hcJi9Bz7gzs+PLDWQLIqicKS9jZk3z+TdF9+nYNHlWFJdBDt6seYmRvsGuxWDPbmZjs5o\nQF9aSEZhPumrlrH3w12s37YXebQDQ3eA1pYuQkCPAql5+Uy9+1b+eeZM2tvbefTZl2loKiS1bAH2\n9NxhR4pSUehtrcN/5EOqnGE+/vnV+P1+ajY+zYMrc7BZhskLsZsIbvnHoW19eAP6324420eWFA/X\n1MBn5wzZfuXva4jpDES9vbhyjJhMKYRCQdrbu8nNzSISidDb101ECCJ2C81N28jIqEBKhVg0iHNe\nJq+/u41qfYyC/AwMhtNng2arkZ6mASCho6XEQ5iMQwcLvnCcN/ti3PnxaUmNyBVFoaGzHcecKQi9\nnmhvB/FoFO04E800Wi3ORTP5YMfW82MIpJTHhBBXAGVSykeEEBlAciZQ5aIiEonw1tP/y+2lTkwj\nGAFIJHYpMSvegTB2x/Ax15U5Fo7Ewqx/p45lKyvHvHbDsX702nyysrLG3f5kqa+vJyNfYneMTyc/\nEonR3eElahrgg+17qPUEyM7QYNL2MtDahiu/BE9tE9bc8TlprW43x3bupnRBMal3LIc7lrP//a24\n9nu57JrlGAwG0tPTT8tWLS4u5ltfeoBdu3fz1obnaN4lEI5cpDkDodWhxMJo/e0oAy1UZDu45obZ\nTJ06NaEX9cQvuXmBfXgjMAqxhxYTe2gxSNi2exNpRTqe3xDk2/96TlTrAVj74PQh22oXV/Lwj++l\npaWDgoJcCm12wpEIIZeJtg0b8LfuRMY1mEx6Zk53UR+eTmsQcob5jmu1AkWJA4nfg9EghiwLRWIK\nTx/1Mvv6aeS6k1uj7+3tRXGY0Q36HqxmSdgXwJI6Vqb3yLinllPz1iZ8Pt+oku7JkEz46HeBuSQK\n1TwCGIA/kigqo3IJsX/fPnKj3RSmjz1SznaX0tS4m6nTR5HrTTPw7Ct1XH516ag5B1JKNq3vY3b1\nbedFm6WtvYXMvLMbiUkpaTrWS80HdbTsOEaGHpbfVID2ta24NVr6dnQSrfNwqP6nZN60iv5t23Ev\nrT4R4XI26ExGYgYDAb8fm82WCDPd38Knrrtr1GIoRqORyxYsYMH8+XR3d9PR0UF3dw/RWByDQU9W\nZhXZ2VeTknKy89lXU0OOuYPSUYTYxsIf8BNR/DhdOSyfr+Gb//dGPvaV0z9Lba+X2XlfGfc1RqNi\nwyH+a/4/D9n+7bsW0BEOYREx8uwOBIlM2KiicMgd4PE3j3D/ojyyUk4OCBRFnoz2kkMTovuCMZ49\n5iNjcRlLFxcl3UaP14s25aTREEKMqpeUDFq9Hn1OOu3t7ROeFSSzNHQbMJtE+ChSyhYhxOS4qlUu\nKHZ/8A7XZSf30WZnZ9PR2UBXp5+MzBFit7UCl9fHI7/ejMMKkVBCrsGRZiUrL53ikjSyc+3s3tlB\nNFhJ9azqybydEenubaGgKHmntM8b4v1ndxHYXc+CNB13zXRg0Gkwp5sR+UYizhT0JhPLnLC3oZ6j\nLz3B0Z4AjS9/QNGtV42rjcJuOzHSa9hxkHy9M2mJAiHEmOqsx9m1+W1WTp2Yn8Q74CUi4NARL8FQ\nnL5jnWxde5AZ80swWxMDhXianW2B3w851v7NP1L5k/cmdP2R+I8/bxmyrX96Di03z8Se46Q2CP/8\n5F6umePm9rm56HQaAv4IVnPieegNeiLRRGcdiSnsbA+wLgiLVs3isnl5ZzVo6Q94MaQnPg9FkQSC\nCvoJaDAdR5OdTkdnx3kxBGEppXL8poUQF7feqsqwhEIh+lqOUbQguQgIjUZDRflM9h3YgNkcxmY/\nOTOIRhWajvVic/aSFemhvznIdR/LxmTUoCjQ5/HT1tLK65sgoFjo6s3my1/6h6Ti7ieDaDSEfowE\noOO0Nffzxi/fZ742zOJZqWjPyJGIKcrJuHadhtxUC9PLC5hyrJUnf/Y4LRYDucvPTjcfQBr0RKNR\nfL0eut7by1fv/sykz5a8Xi/+vgYKc8angdPTH2THvhY+WL8Lk95HSaYRix6mhsM0PP0aR99wYsxM\np2LpDMpn5GMwnjkLk7x2Qxk/zXbT90EtU/z9lBUXYDaZuPVXr0/8BofBWdOKs6YVDJfxnXWHExtr\nu/nejnYKrirG4A1RaMukLxAiHItxqD9K+6E+aqWWvOm53HtNORnjCI2OxuMnsqc9fSGEzYV+jJoH\nyaA1Gwn0hcfecQySMQTPCCF+Q6KI/d8ADwAPT/jKKhcUnZ2dZBnFWSWD2Ww2ykvns79mK+WVCqlp\nZnp7ghw92EqGPUZOuoYl08w0tkJh7snpd3amganlMKvLz7r1/Qi9i/Xr1nD9yluxWM7+R3a2JMJf\n42Pu19Hq4c2fvcNtGRpKMkcXqQNQ4hKh0SKEoKI4l89qJY/91+9o0+vJvnr+Wbcz5Auw/8Wt3LH4\n+knPJIWEgmy2U5y1gYnFFD7Ydozd2w8xO1Py0CyBM82ExZb4jPs8Wo4NQGm1i6YOPzvWvMcLb9i5\nbPVSCstPJkF5PB62vXYQ1z4Pq102YiYz2sHO8YXPryTk8dNyRGDMTQjNmcJBHnp16KxiMvhWbTfU\nHq/9kBAAPFRVwaE506iYGeLB5RWk2CfWccvBpaDWpgHMBWf/fRj2nIoyIfXf4yTjLP6hEGI5iaL1\nFcA/SynXTPjKgBBiBfBjQAs8PFgaU+UjwOv14hyHkGhaWhpTdIuord2JQiuEB5hWoifFYUKjFTgt\nGnwDkdOOCYdiNBzz4fXYWH7lZZjMFt7dvIE//W8zq+/9woQdX2OR4cqnt6sOqkbeJxKJ8dYfNnBD\nKpRkjmycdBoNkVgcrV5PyB9HZzm5tJZdkMenFIVf/d/fIAw63IuHCo6NhLe2kSPrDvHgdR9j7uyh\n0TOTQX9/P2ln+ah9gQhPvbSD1FAPn7vMhs2kpac3ipQni7mYTVrC7SGEEBS4rRS4rTS2+3n10Vdo\nv2I+C66fiRCCtc9swbWrnZvzs9EK6IvBqZ5ZKSUI7Ym/j4b8fHzaQsLeflyAORykO9rHFU4Tnz/a\nOfEHcgaVB2v54cFaeBL4xskZSuTfriP+8eqzUlS1mcz0hkIY7TZ27I+Sddu8SWljvMdDWsZQWYyz\nJRln8Q+klN8A3hpm27gZrHb2c+BaoAXYKoR4SUp5YCLnVTn/OBwOCgqmsH/nu5RkC6LhGD6vgjUu\nUeIKsbjENxDG54vQ1xdnoF+HO6uS8uoiNIOp+dcvyceyrZlnnvwtn3zg74YtXdnb20tbWxttnR0E\nIhG0Gg0ZKU6ys7Nxu91Ja75nu3PZfCA26j6b3jpIiddD1bTRC6+bDUaCkQh6swn/QBxL+ukrpzlF\nBdwRjPHkT5/D39BN5qKp2Ipyhg/tlJJASyfdmw/Q/dIGvv7QF5k7d25S9zQeFEVhBBWNYQmGojzx\n3FammQe4ctpJuW+9Tk8o6j+x33CO0AK3lU+nmvjzxi1slhJ3qZueN/eyMtM5KPkgBwvCSI4bg2go\nCroUgtEwexoPEe3toEynJ8NsS+g3Wexk9YTY0eXhF9PzMRl1xKWk2R+mXkh+fqyHlFBy1cbOBsN3\n1sB3Th8LK/kpRH55G3LK8JFiqVY7HV4vR/t6GTAVUVowOcq98bYe3DMmLjWRzNLQcuDMTv+GYbad\nLQuAOinlMQAhxFPALYBqCD4CzGYzvnH+ZqLRKA1H9rJgZiZ2i55AIEAoFEATgIaGGD4v1NXqsVoz\ncTldVJalD6uguGRuNu1rDvPBune5elki2UZRFA4cOMA7O7dS7/WgzXejzc5Ea3QgFYVYTyfKur0Y\nege4etosFs6bh8MxuvOzuLiYl99MOIFt9qEhpMFAhMPvHeALVWOH9pmNRqR3gJDWSDhqJHWYlP+Z\nVcXUhBoZMObR8/o+WqKbMeelYchMQWvQocTihDsHCLX0olcMZJZOoaDcQ3X1uXWeG41GPJHkI1de\ne+8gpToPV1We/nwNBgPegZOZ5rGYgmYYC2M2arlrkYtH1m1h9/NarrcaMJzYT6DVaJCxKGIwASzk\njeJHx84DWymIhimx2IcI+IW1ZgrCfcT7/ZCVglYICiwG8jXw72VZeFPMXJVvYHpRHhqNBhGNU/z4\nJibupj0dTZMH082PnrYtvqKS2KopKFeW4HQ68e46xpo6HaX33T4p/h5fVw8mX5jMzIlrSY1oCIQQ\nnwe+AJQKIU6tmmEHJiOLJBc4NT21GbhsEs6rMg4yMzNpD0uklGf9JT1WX0dWShiHLdFBWG1WrDYr\nGlsKWLOpnpPO7OqxlzeEENywJJtfP/8yM2bOQaPR8OfXX+WgJkrq0vmUlo0s5Bbo7eOt7bt557Hf\ns/qKq5g9q3rE+zAajUyvWszebZtZdHXJkPcP7GqmShfDahx7uGwym9H19dJ+rB9zVtWwywVCCOam\nGVk30M9lD3yWQE8PvrZ2fF2dKPEYGo0Wd24ZtnlurBkZNL23lutmzz6n+vOQ+Mz39CfnoD9wtJvu\nhkZuXzTUyBoNRpRIwgDodBr8gTgm+/DG2GzUUuWU9L1bT+bcPEKnrBrqNDrCsQhanQElHqerM8RO\n3xGqpCTHPHQNS0pJMOSnwGTH0+MjmmJBP6gSq9MIZjvMHPQEeM8/QFVBLgYNSL2Wow8sJuOKu6sV\ntQAAIABJREFUcrq+tRJFkdQf7MLVY2DxB5Ob/6B94xDaNw4l7hv4OLDCYeOIx8mB1avorJ467oI9\nAG3balg+Y86kfE+EHCGWVQiRAqQC/0li9H+8xV4pZc+ELyzE7cAKKeVnBl/fC1wmpfzS8X3+4z/+\nQwaDwRPHLF26lKVLl0700hcMOp2OWGz0JYrzyfYNa5lqiWM3J+8sUOIKbS1Hyc3QD3FaibzZ1O7e\nhCE3k/yc5BNnjrV46Ytm0xEMoSnMwZ6bfLZxxB/Ae+gIhWYbVWXlIxqDcDjMjt3rqZhlw2I9/X4P\nbW8kP+THNUb1NV3OTGKtexgY8NPaHiGltBIxgqGKxuLs6AuTuey6kUoGAxALhgjs2sOVs2ZhMo0v\n4S1ZFEVhy4a3uKzSgv6Moi0aewmK9+iJ1zv2NlFii5JmHX7sGAoFiYsIRpOeXk8MrCnYHMOPu/fu\n78XeHcRktyK0OrRa/WB74oRlDI3ZRtgX5HBbEBsaUnXDfw5RJUY04CVNoyUSixLWgNGqR2PQoNVo\n0Gg0KPEoXZEYjowUitNPGhNr8Qz6Du7E0xPCpLfjSks/8V05MjBA6pw5uN1utLW1GJ5/PvmHOk68\nuW66p1fSPaWcqHXsgImwz49/z2GuqJ6LwWBg3bp1rFu37sT73/ve95BSJm1lRpwRSCk9JPIv7h5c\nz88a3N8qhLBKKRuTvcgItACnZsfkk5gVnCAWi/H1r3/9tINCoUtHCdtkMl1Q9zMQivL2a3/i5unJ\n6/20tbXh79oBxSmcqRsqlft59qlf89DfLiPWmXzEheju5ts/3s2MH/6UtCwbxLxJH4sRYlU5vPDn\nl7h63z5uWTGyQoqQVh595DFu+3TliXoDUkpe+tPzfK7ESHCMwjtmPkn/xkc4sLOXYNhGU1kpNvfI\nmdGv7m4ha+o0zGnDF1CRisLRJ5/mnuJS4Px815tbO6FpPQtn5py2XZdzLbHWtxP7dHjZ8Nw6Zi9x\noIxgWLWxOO0dTTjSjew5EqNy0XTkkHDRhEbSS7/aw6fNWvZ0xbHmp2M8IeEg6ff3ErOlsnlLG80e\nhUX21OHrOQB9AS/G/i5y9EaiSowejQ5p0KORPuxpRkxWI4T9WCwWnvdH+djScjKsBrz9QdKvvJc9\nD/+B8uJp2NPTGTj1mbS1sb+/nxs/9jEoKMD/5S8nWicl27ZuYdt7T3DP3m0Uvnbw7B72KNgH/x0v\nknnkhmW8+evvE0wf6qOKRSIceOw57p9zBYqiEAqFWLBgAQsWLDixz/e+972zun4yzuIvAf8CdAKn\nxtzNOKsrDWUbUD5Y+rIVWE1i9qTyETGzejZ/ePN5FnkDpNuTC+P0enpIsw3/NWrqj1I8LQ+HLXkj\noMQV6luPkVGZgWGcoaQ6g4GSu1bxzsN/ovLgQaqqhg8PmjVzFl1d1/HiH9dw493lWG1GIpE4SiCC\n3TR2ukwsFufQ7l7y3VNJS3WxsWYvQaMB8wglNJ16QcjjGdYQSEWh4bU3mKPRsvCUH/S5Zs78Jbz8\n+FrmTImPWFzlaGMPU12jh5lqdVrSHOkcrGvBmpE3TM5Agu7+CKlSkmbTY+iMEA2HMBjtCAQgsOgt\n1NUco95vYrrJMqIRAIjFozgG39dptIhYFI0rh1jERCQC/u5ujBoFxRomPRzh5XePsjAjA7stlRJr\nFgvmXjHsUmOqyURT+9C6GEII5i+4jNKyctauf5v6WRsoyYmTlyXISLNgDEYwv3ME65u1pB6YWBRT\n6WvvcuU3/5M3fvdfp99zJMKhp1/jyoxCZkyfaBd8kmScxV8BKidjOehUpJQxIcQXSdS20wK/VyOG\nPlqsViuXr/o4Lz3/MJ+eU5hUfLLf10dB/tAffZsnQmtUw7VXn11o27GmBgIpFoqLLfR3dGHLGjs7\ndjh0BgPuVdfxx6df5dtFRcMuswghuPaaFZg2mHnmty+zeIWLvKK0YUsanoqU0NXmxZAZJt89g5yc\nxGj6silT2XJgP978XOw5OUPWfzUikYB2JmGvl5bX32BWJM4nb7/jvCXWAeTk5JA3ZRnvbH2XlZcP\nPxNsa+tldsrYXYXQGukcsGF3aIjHlWGLtfhDMeyDz8Vh1BDQaIlGQxj0ifKMPS1+utu1KGEfLtcY\nGc/y5CqbQCCkQjwexWy1okPBbHGQk5mBoig4FYU1oRCz51yBxWDAarEQG+E5CyFQ4iPnmaSlpXHz\nqrvw+2/k6NGjtLc1cejAMWKxKLqySlyXf57s7AJKSkowm81o9u/H8NxzGP7yF7SNyS+kpNSfrvDb\n39xG00vvcXVOKTctXzGpCYbJGIJGOG3mNGlIKV8Hzk0Kocq4mDN3LkcP7OWVfVu4aVrBmMYgFo1g\nOCPUsy8Q4+nDQe650409fnSEI4cSj8U52tGOfd5MrF1ddIeCYx80Cs68HLqLsqnZV8O8ucPHbQsh\nuGLJVZQUl/Pqm0+zTVNLV08Qn8+C1Wo80ZdLCaFglP7eAF2tEYzaVGYtz0fknFxSsTvsLJ41i32H\nD9PR3YMpPy8xOxg8STAuMZ9ikKKBAB179hLfvJXbZ1Wz9PLF59xBPBzXLL+RR3+9j+xDnVRXDo1A\n8Xj8uEpG7yqi0Tj7G/zMnHMlXv8Atdsbya9Mw5Zy+qzu1G+TRQdxg4mIEiQcFLTXe5BBJ4bUDLIb\na1B8fWhtqSM6VDUaLXFO+jgTf8XQxBW0QS/ZWZknwpANQFo0SpvXS6lr+AL3xwnFYpiSyGWxWq3M\nmDGDGTNGH5krU6cSmjqV0Le/fWJbPBSi9te/QvPCcyzcs2/IMXGdju1fuh8pJZ6Wdjq31WA40sbf\nLFvBlClTxmzb2ZKMIagH3hNCvAoc9/FLKeX/THprVD5yhBDcsvoenn08yl/27OCmKblYRpjmDx7B\nqeEG9T0hXqgPs2hlNRkuC7GzmCF3dXcRT7WjMxpIlJed+IjHNW8W7766bkRDcJzc3Fw+c//f09DQ\nwC83fpvNm1pJM0t0hsSoMRpW0OvMOB2ZTCnLw2F3oNPrOdPVbzKZmDt9Bl1dXRxpaKav7igixYFi\nMdPU4SGnvZ3+ujpoa0e0tHF5WRlX3nX3pIQAjheTycSdn/xbnnr0x4TCrVw243TnvKIooy7RBEJR\n9tX7ceVNx53txo2btG4Xtfv3YXQM4Mq1Y0+xIITAatYxMPiNEUhiUYWgN0pzXSsuxxRsqS4OdBzF\nbbZjDEcJRzrQONIQ+qEOY4Nej19CBon1e0Uq6MJ+LIoG9ylG4DgOKWlPwhB0BYNklZYm+fTGh9Zk\nYspX/p6++z7N0zt3sm7fTkImHU6rkYKuHpqK8/H6w0T/5zEyDGZumzWPmVfegtk82YGvCZKdETSS\nMKoGEr/OicnmqVzQGAwG7rzvAda9W8Cv332Zq916pudmoB8mNtxoshAK+wnEJBsbAxySZlauXkR5\n0eiJWMPRM+BBP7h+3ucTmFImXjTGWZBHrddDIBAYU75CCEFRURHLbroD1553mZuXTjQaRSDQG/RJ\nJ6whICMzg4zMDAKBAF6vl4OtnWRrjVzW0k6mw0FO9Vxyb8w9L5IayeByubjnwa/x8rOPU/vGPlZ/\nIspxz47RaCAYDQw5Jh6XtHb5aOrVUlA6F3f2SQPiSnexwLmYzq5OWusaaQg1Y7LpETpBU3+I9liM\nrs4wXm+UirJZ6IJteDyJRJZgNEymRofVYMEQDePv6yKu14PZhkZvQGgT3ZZJZ6BDSpR4lEg4iBCS\nXIcVpzNl2CGEWQj8STjgW4Ercycn4WssUlNTWb5sGdddfTW9vb10dHQQCASYJgR2ux33tW7sdvs5\nV+VNRmLiu+e0BSoXJDqdjmXLV1AxdTqb3lvDO9u3U2GVZFt0pNvNaIUgFIuxv0+ytqWPqNPJzPkV\nfGZ+IWbT+Ipt9Pp8GAvcSClp75UUuyc+ShZCoMvOoL29nZKSoTkDwzF9zjzeXP8WC/X6ExXBxovF\nYsFisbCxJ8LqBz7Fgssu3FQZp9PJPff/Ldu2bWFPo8KBDU1MydehNZlo6e0jJ0VPNKbgC0Tw+KN0\nDggcaXnMnFcxrA/m1PKYsVgMv89PJBqhpEBhoM+H2aGhatYiUlJSyHZns2PHHrq7m1DkST+KXm/E\nqTcSjYUJ+7zElFhiOUgINFJCLIo35Mek05BfUEiqc/Qw5bE61C6/H19qKkVFReN6huNFCIHL5cI1\nxmzlXDFaQtnLoxwnpZSrzkF7VC4w8vLyuOOT99Pffxv19fU0N9ZT09GKEouhN1mIzJuO/9gavnbf\nlKQVPUciFAnjMBnoavcRtbkxOiZH7VzjdODz+ZLePzc3F11eGfvbWpiWMz5n9al0+wIcliaumnnh\nV3fVaDQsWLAQo9GI3pzGsSMHqB1YT2NDPfGIDr1Oj8WeiT3NxayqTIzG5CLCdDodKYOd9BVLprHj\nhS0UxjVYrYnoLL1ez/z5s2loaGTrxhYGwiHStU40IrE0p9cZ0esS15JSoigxorEwmeYY3rgGs8GA\nI2V0IxCUkowxcjO2dXcz5+Mf/0h8NR8lo80I/nuU99Slob8ynE4ns2fPhtmnC6fF43F+89PD9HpC\nZKVPhkK5YM8+D87Lbpy06fDZnkcIwbW3r+bFn3yfIlcEq3H8swJFkbx0pJPFdz50ztZ3zwVCCKqq\nqqiqquKqa1by2//8JtPnpWI7i2TDkZiSn86fEKRZU09bx9doNBQXF7FMibN10xZiUQ9SCpBaJAmD\nIFBAxNEIicvloNiewcamZnxaLboxOm+PEGSN4gSu6+mhJy+P2xYtmvA9XmyMllD2/nlsh8pFilar\nZd7im3hr02Pce6NlQp23Qa+nrbGXg90Ops4aWpJwvCheP+ais+uEc3NzmXb9rTzz1l/4xLT8UzRx\nkkdKyZu1zWir5jPnHIrHnWtMJhMV865k8+F3uGbmxNfOpZQYCovY1SNYEothOsOpW5aZyYYUByV2\nO9FolEg0SnwwnFOr1WIwGDDo9Qgh8EYi6DIy8AtBXzBI6gjGNqIoDAhB9jBaUJBYEno/FOLO++5L\n3hd0CXH+ApZVLlnmzVtAyDCVrXs7JnQeq8HMq2+1k73qHvSTNHqWUhJr6xxXLeSly67BsWg5T+xr\nwhM8u+IfkViclw400pw9hVs/ce95KcF5Llly1bXs8tho6TmLLO8RWLuvjarLb2DOJz7Bs43NhM+Q\nWcm22XCmOmkLRzAajdhtNpwpKThTUrDbbBgNBoQQBKJRDgZDVM6bx/RFi6gn0aEPt1xxNBCgIjcX\nyzA+n8b+fl7s72fFF76QdBW4Sw3VEKhMGI1Gw0233sv6gzZqThT3ODvCkRhrt4boMVWSOWXi+urH\n8XV0karRYx9hJDgaQghW3nIbRTffy+9qe9jW2E50lEQjSBiewx29/GZvM7G513LXA59Jeh39QsZm\ns3HNxz7Fs7t78fjHXxGr5lg3ewJpXHfDKpZdfz3pN9zAE01NdPpPl7FeUlZGTTiEMoIWWncgSE0w\nROG8eaSnp+NwOJhx+eV02O3UejwETzEu4XicI4rC/MLC087hC4d5p6mJd41Gbvva185JfP7FQjIS\nEzOklHvH2k/lr5vU1FTuvPfLPPPEz2jvbubK+dlJxSYDtHR4eWldD/kzVuM+1kA0GJy0GUHXjj2s\nmjmyEulYCCFYtGQJpRUVrH39Fd7fs4MZFkmuzUTFrCihYJiYotDtC9A6EGCvX2LILeXqz/7NhOvI\nXmhUTZmC94b7eOzVx7hztovss6hqI6VkW10HH3RaufOhL51wEl9/883sLijgqSf+yIzePuZkpJNi\nMjE9M5PdOTnUdHQwc9CIS8AbjtAaDOJ3OKiaNes0yXGr1Ur1woU0NzVx8PBhzIEADuBAJEJ5eTkO\no5EOr5dOv59Mj4cXPR5mrFjBZ6677pwL/F3ojKg+emIHIdYDRuAR4IlBMbrzwne/+1355UHBp0uR\nC010bjLw+/2sefMluo99wOrVd+GIrMdoGN4ktHf72FbTy8E2O8tWfoopU6fy3Guvstmpp+iaKybc\nlkBPH52P/Jl/vu+hcc0IhqOvr4+DBw7QXn+Yysoq3n/1JbQ6LU53Du6SCsoqKsnJGb7wzMXEaN/N\n/fv28e7zjzEvNcjCyixMI3y+x+nyBHizpotAWhU33flJ0tKG5pgMDAywZcMGat59h/RQiBwkBil5\nZc9eSiIRXAYjXkCxWskqLSUnJ2dUKQ5FUeju7mbrkSMc1WiYWlGBVqPB4nCQXVbGkuuuw2w2XxKz\nteFIS0s7K/XRMQ0BgBCigkSt4juBLcAjUsq3Rj9q4qiG4OKloaEBGQ/z4tM/w50G2akKZoNEkdDj\n1dDaI4mKNGbNX86s6jknRoh+v5/vP/owltU34szLGeMqI6MoCof/9xnuKZvOgnmTUx/2TC7lz2+s\ne/N6vby/5nXqd61namqMQpcJd6oNq0mPokj6fSFa+3wc7IrRJZ3MvfpGFly2aEwdpUgkQnNzM+3t\n7fS2tNDX28um99+nBJhbWEiqc+za0QCRWIztra0oJSV86nOfG1L+9FL+7OAcGQIAIYQOuBX4KQl5\nag3wLSnls+NpaDKohuDixmQy0dfXR0dHBx0dHYRDQTRaHSkpKbjdblwu17AdQ21tLb9853XyPnUH\nFtfwSp6jIaXk6KtvM60nyP13rT5no/NL+fNL9t58Ph/79u2j7VgtnU1HCQV8CI2GlLR0MgvKKSyt\npKKiYkJx+V6vl1eee47GTZuoslrJT0tDO4JBicXjHO3qojYSoXr5cq5duXLYUf+l/NnBOTAEQohZ\nwKeBm4A1JIrM7xBC5ACbpJQFE2jvqKiG4OJmIve3a89uHtvwPmmrrsVVWjz2AYNEAkEaXl1DlTfG\n/XfcNeHM4NG4lD+/C+3epJQcOnSIDW+/TduBA7iEIEUIzIOfrz8cxiMEvVJSOncuS665hoKCkbum\nC+3+JpuzNQTJ+PN+BjwM/B8p5QnBESllqxDi2yMfpqIyfqpnzsLpSOHxl17hSNlh3IvmYR2mSMdx\n4tEoHTUH8b33ISsqZ3DNiqV/lfHglyqnJrj19PTQ0tJCa2Mjvv5+hBBkpaczJz+fvLy8MWtWqwwl\nGa2hEWtDSin/d3Kbo6JykqKiIv7xgc+wftOHvPfYs7RnONEW5GDJykBnNiHjcQI9fUTbOokfPsYs\ndx7XrrrjrzYW/K+F45o8My8CyY6LhWTCR/eSiNw6dZrhAbYC/zHZBWtUVE7FaDRyzZVXceXiJdTX\n19PS1sqxHYfxhUPotVrcKakUuksoXngNKWNozaioqAxPMktDbwAx4EkSxuBuwAJ0AI8CN5+rxqmo\nHEen01FeXk55eflH3RQVlUuOZAzBtVLKU5XG9gghdkopZw/OFlRUVFRULmKSkZjQCiFOiKgLIRac\nctyZBZpUVFRUVC4ykpkRPAg8IoQ4npHhBR4UQliB74/3wkKIH5IISY0AR4D7z2fWsoqKiopKglFn\nBEIILbBESjkdqAaqpZQzpJRbpJR+KeWfJ3Dtt4BpUspZQC3wzQmcS0VFRUVlnIxqCKSUceATg3/3\nSyn7J+vCUso1Up6oSbcZUGP+VFRUVD4CklkaWi+E+DnwNOBnsHi9lHLHJLbjAeBPk3g+FRUVFZUk\nScYQzCaRR/BvZ2y/eqwDhRBrAPcwb31LSvny4D7/B4hIKZ8c0jidjh/96EcnXi9dupSlS0fMb7vo\n0Ol0l7T8rXp/Fy+X8r3BpXd/69atY926deM+PmnRuXOBEOLTwGeAa6SUQ4Q/VK2hixv1/i5eLuV7\ng0v//s5Wa2jM8FEhhFsI8XshxBuDr6cKIR6cSCMHz7MC+AfgluGMgIqKiorK+SGZPIJHSUT4HBeH\nPwz8/SRc+2eADVgjhNgphPjlJJxTRUVFReUsScZHkC6lfFoI8U8AUsqoEGLCiWRSSlUrQEVFReUC\nIJkZgU8I4Tr+QgixkITonIqKiorKJUAyM4KvAS8DJUKIjUAGcMc5bZWKioqKynkjmXoE24UQVwKV\ng5sOSSmj57ZZKioqKirni2RmBAALgKLB/ecIIdSiNCoqKiqXCMkUpvkjUALsAuKnvKUaAhUVFZVL\ngGRmBHOBqfKjzDxTUVFRUTlnJBM1VANkn+uGqKioqKh8NCQzI8gA9gshtgDhwW1SSrnq3DVLRUVF\nReV8kYwh+O4w29RlIhUVFZVLhBENgRCiSkp5UEr5vhDCdKoekBBi0flpnoqKiorKuWY0H8Gp9QE2\nnvGeqgukoqKicomQjLMYEsVoVFRUVFQuQZI1BCoqKioqlyijOYvzhBA/JTEbyD3lb4Dcc94yFRUV\nFZXzwmiG4B84GR20/ZS/BbDtXDZKRUVFReX8MaIhkFI+eh7boaKioqLyEaH6CFRUVFT+ylENgYqK\nispfOcnKUKuoqJwHpJR0dHTQ2tpKe0MDgYEBNFotTrcbd04OBQUF2Gy2j7qZKpcYychQ/4yEo/h4\nxJAEBoCtUsoXJ3JxIcTXgB+SqIvcO5FzqahczCiKwu7du9m6Zg2BhgbcgEunI0uvBynxhMNsEYJX\nhKBs4UIWXX012dmqFqTK5JDMjMBEojrZMySMwe1APTBTCHG1lPIr47mwECIfuA5oGM/xKiqXCj09\nPbz05JNE9u1jjtNJXl4eQgyfwxmJxTiweTN/3LiRuatWsXTZMnQ6dWKvMjGS+QbNBBZLKWMAQohf\nAuuBJcDeCVz7f4B/BCY0q1BRuZhpamrizz/9KTOiUWYUFo5oAI5j0OmYlZ1NeSTCuuee48kjR1j9\nwAMYjcbz1GKVS5FknMVO4NRFSRuQNmgYQsMfMjpCiFuAZinlnvEcr6JyKdDR0cHTP/kJS7Xa/9/e\n3cdHVd15HP988wCRZwiQCASQB0EtCCiC0EbEx7aoLYq2tSq62q7aytrtg13blXV322rZ7Vpr99V2\na2212PqEFbUqKBhFRVEQfBZbHgRCCMiDIgGS3/5xT2QIk2RI7jDJ5Pd+veaVO3funPs7cydz7jn3\nnnMYWVzcaCGQqEO7dpwxYADtVqzgnjvuoKamJo2RumyXSo3gZmCppKfD85OAH0nqCMyv702S5gHF\nSV66Hvg+cHri5kmDy8tj1qxZnzwvLS2ltLQ0hZBbh7y8PAoKCjIdRtp4/upXU1ND5bp1XHT22RR2\n6NDkGM4D3tm2jc2VlZT079/kdOryY9e6lJWVUVZW1uT3K5UZKCX1IZrA3oguEq9v8g6lTwFPAjvD\nqn7AOuAEM6tI3HbmzJk2Y8aMpu6qxSsoKGDXriZVqloFz1/9FpWV8e7dd3NG//4HVRNIZkdVFQ9u\n2cLlM2fSvXv3ZqVVy49d69ajRw/MLOUv1sGMProJ2AoMkdTk03Ize83MiszsCDM7AngfGFO3EHAu\nW1VXV7P4scc4oVevZhcCAJ3bt2dIdTUvL14cQ3SuLUrl9tGbgAuAN4DqhJeaXg/Zn8925tqUd999\nl87bttGjpCS2NI/u2ZO5Tz3FyaedRm5ubmzpurYhlWsEXwSGmVlVo1s2gZkNSke6zrVUa/72N/rm\nxNupv2tBAe0qK6msrKSoqCjWtF32S+Xb+B7QLt2BONdWrF+5kt4dO8aebiFQXl4ee7ou+6VSI/gY\nWCbpSaC2VmBmdk36wnIue320dSud0nDff4eaGnbu3Nn4hs7VkUpB8FB4JPJ2feecyxKNFgQ+L4Fz\n8erYtSsfbthAt8MOizXdnTk5dGhGnwTXdtVbEEi618ymSUo2jISZ2cg0xuVc1uozdCgVK1fSr1u3\nWNPdDBQXJ+vDGT8zY/v27ezYsQMzo6CggMLCQnJivgjuDo2GagS1PbnOOhSBONdW9B80iGdqahgT\nY5rbdu1id4cO9OzZM8ZU92dmrF69mpeWvcDKNW9h+Xvp0K0dSOz+aA9V22voVzSAsSNPZPjw4T4Y\nXivS0FSV68PfVYcsGufagKFDh/Jo165s2bmTHjE15bxRWcmoKVPS1oegoqKCBx+9l23ayODjizj1\n8yPp0Hn/pq3dVXvYsGoTC16ew2NluUyZPJXhw4enJR4Xr0brcZLOlfSupO2SdoTH9kMRnHPZKDc3\nl3FnnsniTZtIZYiXxuyoqmJlbi7HjRsXQ3QHWvLyEn5z78/pPT6Hz35tPMOOG3RAIQDQrn0+A4b1\nYfJXjmfM+f15cNFd/OWROVRXVydJ1bUkqTTo3QycbWZdzKxzeHRJd2DOZbNxEyawe9Ag3qmsbFY6\nZsbCDRuYOG1abOMMJXph8fPMWzqHU/5hFENHDUx5SIyifoV89mvjWLv3Ne7/yz0+OmoLl0pBUG5m\nb6Y9EufakLy8PL5w8cW8JLF269YmpWFmPL12LQWjRzN+woSYI4RVq1bx1NKHmXzRGDp3O/gOcHn5\neZSeN4YNNe/wzKJnYo/PxafegiA0CZ0LLJH0Z0lfrl0naeohjNG5rFRUVMQFM2ZQVl3N8vLyg2om\n2rl7N4+vXs3uESM4f/r02O/Wqa6uZs5j9zBmyhA6dW36dYzc3BwmnDOCZ5fPY+PGjTFG6OLU0Lfn\nLGAK0IWod/Hp4fkU/E4i52JRUlLC9OuuY93gwcxds4a1W7c2WCBU7d3Lqxs2cH9FBf2nTuUrV1yR\nltnJysvLKSjZQ8mQ5t+O2qHzYQwrLWbhoidjiMylQ0N3DU0/hHE412YVFhZyydVXfzJ5/aLVqymW\nKMzNpSA/P7pnv6qKSomKMHn9V9M4eb2Z8f7GNQwbNyC2NIccO4CHF77A9u3b6dLFLzG2NKkMQ30z\n8B9EtYLHgGOBa83szjTH5lybkZOTw+jRoxk1ahQbN25k/fr1lK9ezfYdO1BODt2KixnXty8lJSV0\n6tSp8QSbobKykj3sonffHrGlmd8uj97DOrNy5UrGjImzB4WLQyo9Ps4ws+9K+iKwCpgKPAN4QeBc\nzCRRXFwc9RDO0A9meXk5Bd3yY5k0J1GPPp14f80axsTalc7FIZUrTLWFxRTgPjPbhg/Cr1PJAAAP\n7UlEQVQ651zW2rxlM+07xt8xrXvvLlRs2RB7uq75UqkRzJX0FrALuFJS77DsnMtCe/fuRmkYMyg3\nN5fqmr2xp+uar9GjbWbXAROB48xsN/ARcE66A3POZUZ+fjtqquPvALZnz17y83yOq5aoodFHTzGz\nJ0NfAgvrahsNDXigOTuW9E3gKqJ5kB8xs+81Jz3nXDx69ezN7g8/It4rBPBBxTYO7zk45lRdHBpq\nGioFniTqM5DsmkCTCwJJJwNnAyPNbI+kXk1NyzkXr8MPP5yV696koKYm1o5qW9Z+yPCSktjSc/Fp\nqCCohKg/gaRPmdlrMe73SuDHZrYn7GNTjGk755qhe/fudKjozNq/vR1LhzKAXTurqHxvJ0NOHhJL\nei5eDRX3lyUs/yHm/Q4FSiW9IGmhpONjTt851wz9ivvz9vNrYhkdFeCtJX9nxKDjfAa1FirVmSMO\nurlQ0jwg2enE9WG/3c1svKSxwD3AoIPdh3MuPXr37k3Bhz1Z+epqho4a2Ky0PqjYxprFW7nq4snx\nBOdi11BB0DUMLqc6yxBNVdngNQIzO62+1yRdSbjGYGYvSaqRVGhmm/cLLi+PWbNmffK8tLSU0tLS\nBjPUmuTl5VFQUJDpMNLG89d65eXlcfnF/8grr79Iz1096dCpafMr791bTdWG9Vx50RkUFRXFHGXT\nZduxKysro6ysrMnvV31VP0l3sO8isahzwdjMLm3yTqWvA33M7AZJRwLzzax/3e1mzpxpM2bMODCB\nLFFQUMCuXdnbJcPz13rV5u3Nt97kgafu4sRpwykqObhpMHfu+Jin/7SMY/t8mlMnnxZ7T+XmyOZj\nB9CjRw/MLOUPPFODzt0O3C5pBbAbuDiN+3LONdFRw4/iS/mXcf89sykeVcGxpUeSl99wi7KZ8d7y\n1bw2fx2TxpzJhPETW1Qh4A6Ukdmlw91CF2Vi3865gzN48GCunv4tHp//KHNveYF+I7vRb1gRhcXd\naNc+H4Dq6ho+2LiNDas3sWrJJgrb9+Xy877ZopqDXP0yUhA451qXjh07MvWcaZyy7XSWLnuZlfPe\n5vmKt1E7A4ma3UZh114M7DOEiz53Hn369PFaQCviBYFzLmVdu3Zl0kmTmcRkampq+PjjjzEz2rdv\nT35+fqbDc03U0FSVkxp7c+gh7Jxrg3JycujYsSOdOnXyQqCVa6hGMCVMSjMfWAJsICo4ioHjgVOB\nBeHhnHOulWrorqFvS+pMNNLoaUDtvHWrgWeB/zSzD9MfonPOuXRq8BqBme0A7goP55xzWSj+2Sec\nc861Kl4QOOdcG+cFgXPOtXGN9iNInKEswTZghZlVpCUq55xzh0wqHcouA05k322ik4BXgCMk3Whm\ncc9V4Jxz7hBKpSDIB44ys40AkoqAO4FxQBnxT1rjnHPuEErlGkFJbSEQVIR1m4lGDnXOOdeKpVIj\nWCDpEaJZxAScCyyU1BHYms7gnHPOpV8qBcE3gKnAxPD898D9Fs1o42MNOedcK9doQWBmNZKeBarC\nqsUW14zWzjnnMq7RawSSzgcWA9PC40VJ09IdmHPOuUMjlaahHwBja/sMSOoFPAncm87AnHPOHRqp\n3DUkYFPC881hnXPOuSyQSo3gMeBxSbOJCoALgL82Z6eSTgB+QdRHYS9wlZm91Jw0nXPONU0qNYLv\nAr8CjgVGAL8ys+82c783Az80s9HAv4bnB1i1alUzd9OylZWVZTqEtPL8tV7ZnDfI/vwdrEYLAovc\nb2bXmtm3zGxODPvdAHQNy92Adck28oKgdfP8tV7ZnDfI/vwdrHqbhiR9yIGDzdUyM+vSjP1eBzwr\naRZRYXRiM9JyzjnXDA1NVdmpOQlLmkc0v3Fd1wPXANeY2ZxwK+rtRNNhOuecO8SUib5hkrbX1igk\nCdhqZl2TbOcd15xzrgnMLOW7O1O5aygdVko6ycyeBiYD7yTb6GAy4pxzrmkyVRB8DbhNUnvg4/Dc\nOedcBmSkacg551zL0WLnLJZ0pqS3JL0r6XuZjidOkkokLZD0uqTXJF2T6ZjiJilX0lJJczMdS9wk\ndZN0n6Q3Jb0haXymY4qTpO+H7+YKSbNDzb3VknS7pI2SViSs6yFpnqR3JD0hqVsmY2yOevL30/D9\nfFXSA5IOuAabqEUWBJJyiXoenwkcDXxZ0lGZjSpWe4BrzewYYDxwdZblD2AG8Ab134Lcmt0CPGpm\nRwEjgTczHE9sJA0ErgDGmNkIIBf4UiZjisHviH5LEl0HzDOzI4nGTrvukEcVn2T5ewI4xsyOJboG\n+/2GEmiRBQFwArDSzFaZ2R7gT8A5GY4pNmZWbmbLwvKHRD8kfTIbVXwk9QM+B/wfWTYuVTiz+oyZ\n3Q5gZnvNbFuGw4rTdqITlQ6S8oAO1NPhs7Uws2eAD+qsPptobhXC3y8c0qBilCx/ZjbPzGrC08VA\nv4bSaKkFQV9gbcLz98O6rBPOwEYTHaxs8TPgO0BNYxu2QkcAmyT9TtIrkn4jqUOmg4qLmW0B/gtY\nA6wnurV7fmajSouihCl4NwJFmQwmzS4DHm1og5ZaEGRjc8IBJHUC7gNmhJpBqydpClBhZkvJstpA\nkAeMAX5pZmOAj2jdzQr7kTQY+CdgIFEttZOkCzMaVJqFibay8jdH0vXAbjOb3dB2LbUgWAeUJDwv\nIaoVZA1J+cD9wF1m9mCm44nRBOBsSX8H7gYmS/pDhmOK0/vA+wmj5d5HVDBki+OB58xss5ntBR4g\nOqbZZqOkYgBJhwMVGY4ndpKmEzXRNlqQt9SCYAkwVNJASe2Ihr5+KMMxxSb0pv4t8IaZ/U+m44mT\nmf2LmZWY2RFEFxmfMrOLMx1XXMysHFgr6ciw6lTg9QyGFLe3gPGSDgvf01OJLvpnm4eAS8LyJUA2\nnYwh6Uyi5tlzzGxXY9u3yIIgnIl8A3ic6Ev4ZzPLmjszgInAV4GTwy2WS8OBy0bZWOX+JvBHSa8S\n3TX0owzHExszexX4A9HJ2PKw+teZi6j5JN0NPAcMk7RW0qXAT4DTJL1DNLrBTzIZY3Mkyd9lwK1A\nJ2Be+H35ZYNpeIcy55xr21pkjcA559yh4wWBc861cV4QOOdcG+cFgXPOtXFeEDjnXBvnBYFzzrVx\nXhBkGUmxDVUhaZakSXXW/SLcl/y6pJ0J/SCmJnn/SZJOTGE/0yXdWs/6TQn7+L2ksxoalry+tOrZ\n9tchH8sbGkpa0pQwrtCysH2TJ1KSdHcYGnhGU9MI6QxMHHY4Yf0kSdskPZzw/IChwFM9Nukm6YIw\n1HyyGM+W9MNMxNXWZGqGMpc+sXQMkdQZKDWzb++XuNk3wusDgIfNbHQDyZwM7ACeb2R39cVswN1m\nVne+hobmOEgp/5I+Awwxs2MkFQBd6tkuH/gVMNbM1ofnR6SyjyRpFQPHm9nQprz/IJSZ2VmNbJPq\nsUkrM/uzpHLg20lengvcKOknYRRilyZeI8hSivxU0eQiyyWdH9bnSPplmLTiCUmPSDo3SRLnAA2N\nOvnJgHKKJvl4MJzpPi9pRBhV9evAteFs/tPhzPqFcHY9T1LvVLJSJ1+fnPFLmhbyt0zSwoTt+0j6\nq6JJR26qJ90qoEhSvpntMrP6xprpTHTCtAXAzPaY2Tth/70UTVDzYnhMCOtPkPRcyOeihOEongD6\nJnweo8LnUTt5SLfw/vrWHxfWLQOuSuGz2/+DlMaGmAax/7GZGGoYT4X050sqCe+5Q9ItIR/v1X5X\nQk1joaR7w3fproT9HBdeWyLpMe0b0+eaUKN6VVFv2E/ekizeMBjc88DpB5tXd5DMzB9Z9AB2hL/n\nEv3wCOgNrAaKgfOAR8I2RUQ/cFOTpPO/ydYnvD4QWBGWbwV+GJZPBpaG5RuAbyW8p1vC8uXArLA8\nHbg1yT6mEw0GtjQ8phONC3NreH05cHhY7pLwnveIfsDbA6uAvvXEvwP4Ywqf6W+IhiqeDXyFfT3y\nZwMTw3J/orGjCPvODcunAveF5QG1n1lC/J8Jy/8G/CyF9Z8OyzcnppWQ5iRgbt3nRAPHLQH61XNs\n5gIXheVLgTlh+Q6iIV4AjgLeTUh3K9EIpSIa4mAikB+WC8N2FwC/DcvrgPzE45Us5jr5uRS4KdP/\nV9n+8BpB9vo0MNsiFcDTwFiif9Z7ACwaj31BPe8fAGxIcV8TgTtDmguAwtC0BPuf7ZWEWshyoqaA\noxtJ14A/mdno8LijzuuLgN9Lupx9zZwGPGlmO8ysimisqoFJ0n6AaFTGEkk/A5B0m6TPHxCE2RXA\nKcCLIe7bw0unAr+QtBT4C9BZ0dwE3YD7Qhv+fwPH1P0sFE1w09WiSUUgmhylVFKXetbXbv9sWH9n\n8o8sqaOImremmFniKL6Jx2Y8UcEGcBfR9weiz/PB8Dm8yf7j9r9oZust+sVeRvQ5Dwv5nR8+l+vZ\nN5fIcmC2omGtq1OMfT3Jj5+LkRcE2cuofz6AVOcJOJjvRypp3gr83MxGEjVNHNacdM3sSuAHRMOU\nvyypR9i+KmGzaqLpFvclGDVJFZrZQ8BngTGSbiAagvmpevb1mkUjxZ5GVNuqjW1cQkFVYmY7gX8n\nKoxGAGcBBc3IZ3OPoREV6B/T+HDZ9aW5u55t6n7OtYXx6wmfyUgzqx1Q8fPAbSGOlySl8v3KITsH\nLmxRvCDIXs8AF4RrAr2AUqJZ0BYB54ZrCEVE1fJkapuSUt3XhRC1HQObzGwHUdNL54TtuhCd4UHU\nhNOYZD9MiWfVg83sRTO7AdhEVCAk+9Gom84moEbSBDP7iGi47BnAy2b28X5vlDpq/zunRhM1N0HU\n9HZNwrbHhsXEfF6aLGMWTW/5gaTaM++LgIVmtr2e9duArZImhvWpThYjoiacKcCPJZ0U1tc9Ns+x\nb27iC4GyFNNPZMDbQC+Fu7Ak5Us6WpKA/ma2kGgin65Eo2M25nCi76JLIy8Iso8BmNkcoqr4q0ST\nc38nNBHdTzS5yhtEzQuvAMnm3H2W6Ay50X0BM4HjFA3L/CP2jfM+F/hi7cXRsN29kpYQ/RhbQjrJ\nfsCTrU9cd7OiC+ErgEUWDaFMPe/Z9yRqyjgP+GlovriP6OLriTrwNlgB35H0Vtj2BvYVYtcAx4eL\nn68T1XIgar//saRXiGojiftPXL4kxFA7nPWNjay/FLgtxJEsn8lYyHIFUWFwm6Sx7H9sJhINrX1p\n2OeFRAVjspjrW45WRHf3nAfcFC5qLwVOJPoc7gzNgq8At4RCr7F8nEDTCiV3EHwY6jZIUkcz+0hS\nIVEtYYLVuWtG0TSaC8xsbEaCdE0Sai//bI3fPtpi1BdzaDp6heiW272ZiK2t8BpB2/RwOKssA26s\nWwgAWDSH8gJJJx/y6FxzVAGfUuhQ1tJJuoDousGWJC9PIbrjyguBNPMagXPOtXFeI3DOuTbOCwLn\nnGvjvCBwzrk2zgsC55xr47wgcM65Ns4LAueca+P+H0Xidw+4ZE5KAAAAAElFTkSuQmCC\n",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
""
],
"text/plain": [
"supergroups
and parents
, defines a basic agriculture energy share for countries and defines a basic calorie content for all products."
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"firstrun configuration finished\n"
]
}
],
"source": [
"#code to execture only once, on startup\n",
"if (firstrun):\n",
" try: \n",
" \n",
" n = 4 #number of grouping variations = number of detail levels\n",
" m = 4 #number of data variations = number of data levels\n",
"\n",
" #group to which food item entry belongs to. defined in food_groups()\n",
" #custom groups possible, along the FAO official ones \n",
" #i.e. Cereals for Wheat, Meat for Poultrymeat, Alcoholic Beverages for Wine\n",
" supergroup=[{} for i in range(n)]\n",
" #food item parent(source) node, where applicable (secondary food items) \n",
" #i.e. Feed for Animal Products, Milk for Cheese, Processing for Vegetable Oils & Sugar\n",
" parent={}\n",
" #precentage of crop that is unused but has energy residues remaining inside it, husk\n",
" #this is necessary for recording crop residues on the gross energy details level\n",
" gross={}\n",
"\n",
" #define food categories. this is done globally, from World 2008 data \n",
" #presumed to be one of the most comprehensive\n",
" food_groups('World',2008)\n",
" #afer processing we can drop the itemcode column from balance, unless it has already been done\n",
" balance.drop('ItemCode', axis=1, inplace=True)\n",
" \n",
" #agri preprofiling: load agriculture energy share from dataframe and extrapolate where necessary \n",
" agrienergy=fuel_preprofiling(range(1960,2015))\n",
" \n",
" #food calorie profiling for world to set benchmark crop calorific values\n",
" food_extended = food_profiling('World') \n",
" food_cal_world = food_cal_profiling('World')\n",
" \n",
" firstrun=False\n",
" print 'firstrun configuration finished'\n",
" except: print 'firstrun configuration error'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"food_profiling
, the rest of code is invoked only for those years."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"scrolled": false
},
"outputs": [],
"source": [
"###############################################################################################\n",
"###### MAIN ######\n",
"###############################################################################################\n",
" \n",
"#define countries and regions to iterate over\n",
"countries={i for i in balance.index.get_level_values('Country').unique() if \"+\" not in i}\n",
"regions={'Small Island Developing States','Caribbean','Eastern Asia',\\\n",
" 'European Union','Least Developed Countries',\\\n",
" 'Low Income Food Deficit Countries','Northern Africa','Northern America',\\\n",
" 'South America','Southern Africa','Southern Asia','World'}\n",
"#countries={\"Afghanistan\"}\n",
"#countries=set(list({i[0][0] for i in population.T.iteritems() if \"+\" not in i[0][0]} | {\"World\"})[0:200])\n",
"#countries={\"Saint Helena, Ascension and Tristan da Cunha\",\"Sao Tome and Principe\"}\n",
"#countries={\"United States\"}\n",
"#countries={\"Romania\"}\n",
"#countries={\"C\\xf4te d'Ivoire\",'Ghana','Zambia','Rwanda','India','China'}\n",
"#countries={\"Russian Federation\",\"United States of America\",\"Brazil\",\"Hungary\",\"Romania\",\"United Arab Emirates\"}\n",
"#countries={\"United States of America\"}\n",
"#countries={\"China\",\"Canada\"}\n",
"#countries={'China, Hong Kong SAR'}\n",
"#countries={\"China, Taiwan Province of\"}\n",
"#countries={\"United Arab Emirates\"}\n",
"#countries={\"Iran (Islamic Republic of)\"}\n",
"countries={\"Turkmenistan\", \"Malaysia\"}\n",
"#countries={'World'}\n",
"#countries={'Belize','Barbados','Burkina Faso'}\n",
"#regions={'Northern America'}\n",
"#countries=set([])\n",
"regions=set([])\n",
"c=[] \n",
"t0=0 \n",
"progress=0\n",
"problematic=[]\n",
"\n",
"#main loop - double check the countries!\n",
"for country in set(list(countries.union(regions))):\n",
" \n",
" try: \n",
" pc=json.loads(file(savepath+country+'m.json','r').read())\n",
" print country, \"data already exists, overwriting\"\n",
" \n",
" raise KeyError() #uncomment only if you want to overwrite existingdata\n",
" \n",
" except:\n",
" \n",
" try: \n",
" \n",
" #######################################################################\n",
" ###### MAIN SETUP ######\n",
" #######################################################################\n",
"\n",
" \n",
" #food (meta) profiling independent of years, processes all data \n",
" food_extended = food_profiling(country) \n",
" #load food item caloric values\n",
" foodcalorie = food_cal_profiling(country) \n",
" \n",
" #extract years of data availalibity for country under iteration or use predefined range\n",
" years = {i for a in food_extended for i in food_extended[a].keys()}\n",
" #years = range(1961,1963) #for developer purposes only\n",
"\n",
" #create metadata variable to save EROEIs for years with available data\n",
" eroei=[{} for k in range(m)]\n",
" eroei_adj=[{} for k in range(m)]\n",
"\n",
" #create metadata variable to save average energy content years with available data\n",
" aec=[{} for k in range(m)]\n",
"\n",
" #helper variables to monitor data integrity\n",
" missing=set([])\n",
" estimated=set([])\n",
" integrity={}\n",
" for year in years: integrity[year]=[]\n",
" \n",
" #conduct data profiling, interpolate and extrapolate database values where missing\n",
" #also, after it has been indexed, load the data from pandas dataframes into python dictionaries, \n",
" #which are much faster to work with in case of sparse operations\n",
" \n",
" wdi_import_extended = wdi_import_profiling(country,years) \n",
" energy_extended = fuel_profiling(country, years) \n",
" energy_extended = fuel_reprofiling(country, years,energy_extended)\n",
" if (energy_extended=={}):\n",
" print 'progress:',progress*100,'%',country, \"no energy input data for any year, skipping\"\n",
" raise KeyError() \n",
" electricity_extended = electricity_profiling(country, years)\n",
" fertilizers_extended = fert_profiling(country, years)\n",
" population_extended = labor_profiling(country, years)\n",
" if country not in {'World'}:\n",
" import_extended = import_profiling(country ,years)\n",
" \n",
" #raise KeyError() #uncomment only if you want to do data-profiling\n",
" \n",
" for year in years: \n",
" \n",
" # initialize global variables\n",
" at_least_one=False\n",
" #initialize food import variable for sum collection and processing for EROEI\n",
" foodimport=[0 for k in range(m)]\n",
" #initialize food input variable for sum collection and processing for EROEI\n",
" foodinput=[0 for k in range(m)]\n",
" #initialize food output variable for sum collection and processing for EROEI\n",
" foodoutput={\"Food\":[0 for k in range(m)],\\\n",
" \"Biofuels & Other\":[0 for k in range(m)],\\\n",
" \"Export\":[0 for k in range(m)],\\\n",
" \"Stock Deposit\":[0 for k in range(m)],\\\n",
" \"Crop Residue\":[0 for k in range(m)]}\n",
" foodinput2={\"Fossil Fuels\":[0 for k in range(m)],\\\n",
" \"Renewables & Nuclear\":[0 for k in range(m)],\\\n",
" \"Labor\":[0 for k in range(m)],\\\n",
" \"Seed\":[0 for k in range(m)],\\\n",
" \"Stock Draw\":[0 for k in range(m)]}\n",
" #counter for the groupdict below\n",
" count = [[0 for k in range(m)] for i in range(n)]\n",
" #initialize dictionary for item order of addition - necessary format for sankey.js\n",
" groupdict=[[{} for k in range(m)] for i in range(n)]\n",
" #dictionary to keep track of food item sums in case of aggregations, based on the supergroup \n",
" supersum=[[{} for k in range(m)] for i in range(n)] \n",
" #initialize dictionary array for later JSON export for D3 & sankey.js visualization\n",
" data=[[{\"nodes\":[],\"links\":[]} for k in range(m)] for i in range(n)]\n",
" #save source crop share for supply input distribution later\n",
" share=[[{} for k in range(m)] for i in range(n)]\n",
" #elelctricity counters reset\n",
" eltotal=0\n",
" eltotal_n=0\n",
" electricity_to_fossil=0\n",
"\n",
" #run code by parts\n",
"\n",
" #######################################################################\n",
" ###### MAIN CODE ######\n",
" #######################################################################\n",
"\n",
" food_data_ok=True\n",
" try: \n",
" food_part(country, year)\n",
" except:\n",
" print country, year, 'food error, skipping year' \n",
" food_data_ok=False\n",
" \n",
" #check for food data availability, part of data quality profiling criterion\n",
" if food_data_ok: \n",
" try: fuels_part1(country, year)\n",
" except: print country,year,\"fuel1 error\"\n",
" try: fuels_part2(country, year, eltotal, 0)\n",
" except: print country,year,\"fuel2a error\"\n",
" try: fuels_part2(country, year, eltotal_n, 1)\n",
" except: print country,year,\"fuel2b error\"\n",
" try: fuels_part3(country, year)\n",
" except: print country,year,\"fuel3 error\"\n",
" try: fertilizers_part(country, year)\n",
" except: print country,year,\"fertilizers error\"\n",
" try: labor_part(country, year)\n",
" except: print country,year,\"labor error\" \n",
" if country not in {'World'}:\n",
" try: import_part(country, year)\n",
" except: print country,year,\"import error\" \n",
" try:\n",
" save_data(country_name_converter3(country), year)\n",
" at_least_one=True\n",
" except:\n",
" print country, year, 'save error'\n",
" food_data_ok=False\n",
" \n",
" #shorten country names if aggregate, such as World, solve unicode conflicts \n",
" country=country_name_converter3(country)\n",
" progress+=1.0/len(countries.union(regions))\n",
" \n",
" #save EROEI values for years with available data\n",
" if at_least_one:\n",
" c.append(country)\n",
" print 'progress:',progress*100,'%',country,'save OK for',eroei[0].keys()\n",
" \n",
" #normalize eroei\n",
" for k in range(m):\n",
" keys=eroei[k].keys()\n",
" for year in keys:\n",
" pass\n",
" #if (np.isnan(eroei[k][year])|(eroei[k][year]==0)): eroei[k].pop(year);\n",
" if set(eroei[k].keys()).intersection(years):\n",
" #interpolate null or NaN eroei values\n",
" eroei[k].update(interpolate(eroei[k],years,1))\n",
" \n",
" #normalize aec\n",
" for k in range(m):\n",
" keys=aec[k].keys()\n",
" for year in keys:\n",
" pass\n",
" #if (np.isnan(aec[k][year])|(aec[k][year]==0)): aec[k].pop(year);\n",
" if set(aec[k].keys()).intersection(years):\n",
" #interpolate null or NaN aec values\n",
" aec[k].update(interpolate(aec[k],years,1))\n",
" \n",
" #calculate adjusted EROEI\n",
" for k in range(m):\n",
" keys=aec[k].keys()\n",
" minyear=min(keys) #first available year - to normalize after\n",
" for year in keys:\n",
" try: eroei_adj[k][year]=eroei[k][year]/(aec[k][year]/aec[k][minyear])\n",
" except: eroei_adj[k][year]=0\n",
" \n",
" \n",
" #save missing, estimated & interpolated data item list and EROEI\n",
" file(savepath+country+'m.json','w').write(json.dumps({\"missing\":list(missing),\n",
" \"estimated\":list(estimated),\n",
" \"interpolated\":integrity,\n",
" \"eroei\":eroei_adj,\n",
" \"eroei_raw\":eroei,\n",
" \"aec\":aec}))\n",
" else:\n",
" print 'progress:',progress*100,'%',country, \"no food data for any year, skipping\"\n",
" raise KeyError() \n",
"\n",
" except: \n",
" print 'progress:',progress*100,'%',country, \"major data insufficiency, skipping country\"\n",
" problematic.append(country)\n",
"\n",
"prev_countries={'countries':[]}\n",
"try: prev_countries=json.loads(file(savepath+'countries.json','r').read())\n",
"except: print 'country list does not exist, creating one'\n",
"for i in c:\n",
" if i not in prev_countries['countries']:\n",
" prev_countries['countries'].append(i)\n",
"prev_countries['countries'].sort()\n",
"file(savepath+'countries.json','w').write(json.dumps(prev_countries))\n",
"if problematic: print \"Errors encountered for the following countries\",problematic"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We would like to express our gratitude to all of the developers of the libraries used and especially to the affiliates of FAOSTAT for their great database and openly accesible data. The data manipulation algorithms and visualization techniques are open sourced and freely reproducible, forks are welcome on GitHub (soon to be made public under MIT license). The concept and methodology are subject to copyright of the authors.