Skip to content

Commit

Permalink
EODC
Browse files Browse the repository at this point in the history
  • Loading branch information
romainsacchi committed Jul 22, 2023
1 parent f59c940 commit 186f1b3
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 124 deletions.
130 changes: 56 additions & 74 deletions premise/activity_maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,59 @@ def get_mapping(filepath: Path, var: str) -> dict:

return mapping

def act_fltr(
database: List[dict],
fltr: Union[str, List[str]] = None,
mask: Union[str, List[str]] = None,
) -> List[dict]:
"""Filter `database` for activities matching field contents given by `fltr` excluding strings in `mask`.
`fltr`: string, list of strings or dictionary.
If a string is provided, it is used to match the name field from the start (*startswith*).
If a list is provided, all strings in the lists are used and results are joined (*or*).
A dict can be given in the form <fieldname>: <str> to filter for <str> in <fieldname>.
`mask`: used in the same way as `fltr`, but filters add up with each other (*and*).
`filter_exact` and `mask_exact`: boolean, set `True` to only allow for exact matches.
:param database: A lice cycle inventory database
:type database: brightway2 database object
:param fltr: value(s) to filter with.
:type fltr: Union[str, lst, dict]
:param mask: value(s) to filter with.
:type mask: Union[str, lst, dict]
:return: list of activity data set names
:rtype: list
"""
if fltr is None:
fltr = {}
if mask is None:
mask = {}

# default field is name
if isinstance(fltr, (list, str)):
fltr = {"name": fltr}
if isinstance(mask, (list, str)):
mask = {"name": mask}

assert len(fltr) > 0, "Filter dict must not be empty."

# find `act` in `database` that match `fltr`
# and do not match `mask`
filters = []
for field, value in fltr.items():
if isinstance(value, list):
filters.extend([ws.either(*[ws.contains(field, v) for v in value])])
else:
filters.append(ws.contains(field, value))

for field, value in mask.items():
if isinstance(value, list):
filters.extend([ws.exclude(ws.contains(field, v)) for v in value])
else:
filters.append(ws.exclude(ws.contains(field, value)))

return list(ws.get_many(database, *filters))


class InventorySet:
"""
Expand Down Expand Up @@ -181,90 +234,19 @@ def generate_material_map(self) -> dict:
"""
return self.generate_sets_from_filters(self.materials_filters)

@staticmethod
def act_fltr(
database: List[dict],
fltr: Union[str, List[str]] = None,
mask: Union[str, List[str]] = None,
filter_exact: bool = False,
mask_exact: bool = False,
) -> List[dict]:
"""Filter `database` for activities matching field contents given by `fltr` excluding strings in `mask`.
`fltr`: string, list of strings or dictionary.
If a string is provided, it is used to match the name field from the start (*startswith*).
If a list is provided, all strings in the lists are used and results are joined (*or*).
A dict can be given in the form <fieldname>: <str> to filter for <str> in <fieldname>.
`mask`: used in the same way as `fltr`, but filters add up with each other (*and*).
`filter_exact` and `mask_exact`: boolean, set `True` to only allow for exact matches.
:param database: A lice cycle inventory database
:type database: brightway2 database object
:param fltr: value(s) to filter with.
:type fltr: Union[str, lst, dict]
:param mask: value(s) to filter with.
:type mask: Union[str, lst, dict]
:param filter_exact: requires exact match when true.
:type filter_exact: bool
:param mask_exact: requires exact match when true.
:type mask_exact: bool
:return: list of activity data set names
:rtype: list
"""
if fltr is None:
fltr = {}
if mask is None:
mask = {}
result = []

# default field is name
if isinstance(fltr, (list, str)):
fltr = {"name": fltr}
if isinstance(mask, (list, str)):
mask = {"name": mask}

def like(item_a, item_b):
if filter_exact:
return item_a.lower() == item_b.lower()
return item_a.lower().startswith(item_b.lower())

def notlike(item_a, item_b):
if mask_exact:
return item_a.lower() != item_b.lower()
return item_b.lower() not in item_a.lower()

assert len(fltr) > 0, "Filter dict must not be empty."

# find `act` in `database` that match `fltr`
# and do not match `mask`
filters = []
for field, value in fltr.items():
if isinstance(value, list):
filters.extend([ws.either(*[ws.contains(field, v) for v in value])])
else:
filters.append(ws.contains(field, value))

for field, value in mask.items():
if isinstance(value, list):
filters.extend([ws.exclude(ws.contains(field, v)) for v in value])
else:
filters.append(ws.exclude(ws.contains(field, value)))

return list(ws.get_many(database, *filters))

def generate_sets_from_filters(self, filtr: dict, database=None) -> dict:
"""
Generate a dictionary with sets of activity names for
technologies from the filter specifications.
:param filtr:
:func:`activity_maps.InventorySet.act_fltr`.
:param filtr:
:func:`activity_maps.InventorySet.act_fltr`.
:return: dictionary with the same keys as provided in filter
and a set of activity data set names as values.
:rtype: dict
"""

database = database or self.database

techs = {tech: self.act_fltr(database, **fltr) for tech, fltr in filtr.items()}
techs = {tech: act_fltr(database, **fltr) for tech, fltr in filtr.items()}
return {tech: {act["name"] for act in actlst} for tech, actlst in techs.items()}
35 changes: 18 additions & 17 deletions premise/ecoinvent_modification.py
Original file line number Diff line number Diff line change
Expand Up @@ -765,31 +765,32 @@ def update_electricity(self) -> None:
use_absolute_efficiency=self.use_absolute_efficiency,
)

electricity.adjust_coal_power_plant_emissions()
electricity.create_missing_power_plant_datasets()
#electricity.adjust_coal_power_plant_emissions()

# datasets in 3.9 have been updated
if self.version not in ["3.9", "3.9.1"]:
electricity.update_ng_production_ds()
#if self.version not in ["3.9", "3.9.1"]:
# electricity.update_ng_production_ds()

electricity.update_efficiency_of_solar_pv()
#electricity.update_efficiency_of_solar_pv()

if scenario["iam data"].biomass_markets is not None:
electricity.create_biomass_markets()
#if scenario["iam data"].biomass_markets is not None:
# electricity.create_biomass_markets()

electricity.create_region_specific_power_plants()
#electricity.create_region_specific_power_plants()

if scenario["iam data"].electricity_markets is not None:
electricity.update_electricity_markets()
else:
print("No electricity markets found in IAM data. Skipping.")
#if scenario["iam data"].electricity_markets is not None:
# electricity.update_electricity_markets()
#else:
# print("No electricity markets found in IAM data. Skipping.")

if scenario["iam data"].electricity_efficiencies is not None:
electricity.update_electricity_efficiency()
else:
print("No electricity efficiencies found in IAM data. Skipping.")
#if scenario["iam data"].electricity_efficiencies is not None:
# electricity.update_electricity_efficiency()
#else:
# print("No electricity efficiencies found in IAM data. Skipping.")

scenario["database"] = electricity.database
self.modified_datasets = electricity.modified_datasets
#scenario["database"] = electricity.database
#self.modified_datasets = electricity.modified_datasets

def update_dac(self) -> None:
"""
Expand Down
36 changes: 36 additions & 0 deletions premise/electricity.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@
ws,
)
from .utils import DATA_DIR, eidb_label, get_efficiency_solar_photovoltaics
from .activity_maps import act_fltr

LOSS_PER_COUNTRY = DATA_DIR / "electricity" / "losses_per_country.csv"
IAM_BIOMASS_VARS = VARIABLES_DIR / "biomass_variables.yaml"
POWERPLANT_TECHS = VARIABLES_DIR / "electricity_variables.yaml"

LOG_CONFIG = DATA_DIR / "utils" / "logging" / "logconfig.yaml"
# directory for log files
Expand All @@ -55,6 +57,19 @@
logger = logging.getLogger("electricity")


def load_electricity_variables() -> dict:
"""
Load the electricity variables from a YAML file.
:return: a dictionary with the electricity variables
:rtype: dict
"""

with open(POWERPLANT_TECHS, "r", encoding="utf-8") as stream:
techs = yaml.full_load(stream)

return techs


def get_losses_per_country_dict() -> Dict[str, Dict[str, float]]:
"""
Create a dictionary with ISO country codes as keys and loss ratios as values.
Expand Down Expand Up @@ -1926,6 +1941,27 @@ def adjust_coal_power_plant_emissions(self) -> None:

# self.write_log(dataset=dataset, status="updated")

def create_missing_power_plant_datasets(self) -> None:
"""
Create missing power plant datasets.
We use proxy datasets, copy them and rename them.
"""
for tech, vars in load_electricity_variables().items():
if not vars.get("exists in database", True):
datasets = act_fltr(
self.database,
vars["proxy"]["filter"],
vars["proxy"].get("mask", {}),
)

print(tech, len(datasets))







def update_electricity_markets(self) -> None:
"""
Delete electricity markets. Create high, medium and low voltage market groups for electricity.
Expand Down
2 changes: 2 additions & 0 deletions premise/iam_variables_mapping/biomass_variables.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ biomass wood - purpose grown:
message: Primary Energy|Biomass|Fuelwood
ecoinvent_aliases:
name:
- market for wood chips
reference product:
- wood chips
biomass - residual:
iam_aliases:
message: Primary Energy|Biomass|Residues
Expand Down
Loading

0 comments on commit 186f1b3

Please sign in to comment.