Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/extend steel example #85

Draft
wants to merge 69 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
d5928b4
remove outdated Bus mapping
FelixMau Apr 15, 2024
9eb22c2
Using np.unique
FelixMau Apr 15, 2024
123a832
Adding `ind_demand` to helper set
FelixMau Apr 15, 2024
0b65776
Merge branch 'feature/routine-for-decomissioning-of-existing-capacity…
FelixMau May 6, 2024
4af49ce
Adding model creation and solving
FelixMau May 14, 2024
272e87b
Update struct with new x2x
FelixMau May 15, 2024
e5c501c
Update struct with new x2x
FelixMau May 23, 2024
138bb89
Use Process adaper mapping from excel sheet
FelixMau Jun 5, 2024
ab4dac0
Include nan value handler
FelixMau Jun 10, 2024
c8e476f
Adjust test goals
FelixMau Jun 10, 2024
7a9a272
Updating dependencies
FelixMau Jun 18, 2024
c4abeff
Moving utils to utils
FelixMau Jun 18, 2024
ea12b6b
Raise Error on nan values
FelixMau Jun 18, 2024
05d99de
Linting
FelixMau Jun 18, 2024
fe86936
Bugremoval
FelixMau Jun 19, 2024
dd61e45
Apply Comments, adjust test
FelixMau Jun 19, 2024
92635d0
Adjust test files
FelixMau Jun 19, 2024
91a4eab
Merge branch 'feature/routine-for-decomissioning-of-existing-capacity…
FelixMau Jun 19, 2024
4aae473
Extend handling nans
FelixMau Jun 24, 2024
59e20ad
Linting
FelixMau Jun 25, 2024
a1a4f62
Extend handling nans
FelixMau Jun 24, 2024
3cd5dd0
Linting
FelixMau Jun 25, 2024
07b12fe
Merge branch 'feature/handle_nans' of github.com:sedos-project/data_a…
FelixMau Jun 25, 2024
5185b60
Add Documentation
FelixMau Jul 5, 2024
f494cc8
Bugfix
FelixMau Jul 5, 2024
faaca01
Dependencies
FelixMau Jul 5, 2024
4d017e0
Linting
FelixMau Jul 5, 2024
b3402f9
Addin .env for example
FelixMau Jul 5, 2024
18328d3
More docu
FelixMau Jul 5, 2024
45c3ff0
Commenting
FelixMau Jul 9, 2024
5730321
Typo and uncomment
SabineHaas Jul 9, 2024
55c3792
Add results processing
SabineHaas Jul 9, 2024
876eed3
Adding color logging
FelixMau Jul 9, 2024
f63c921
Linting and adding .env file
FelixMau Jul 9, 2024
98e0725
Using pd.DataFrame.where
FelixMau Jul 10, 2024
90c55be
Remove unnecessary checks update doc
FelixMau Jul 10, 2024
ff1b1e9
Add test skript
FelixMau Jul 10, 2024
e2596f4
bugfix
FelixMau Jul 10, 2024
f125bc5
Add test collection and struct
FelixMau Jul 10, 2024
d276d80
Also return df if no values missing
FelixMau Jul 10, 2024
866d83e
Bugfix
FelixMau Jul 18, 2024
69889e0
Simplify Logic to old approach
FelixMau Jul 18, 2024
825334d
Simplify Logic to old approach
FelixMau Jul 18, 2024
7137b82
Super Easy, super Readable, super Performance
FelixMau Jul 18, 2024
6e07cfc
Super Easy, super Readable, super Performance
FelixMau Jul 18, 2024
91b6efd
Linting
FelixMau Jul 18, 2024
22f0dd4
Merge branch 'dev' into feature/handle_nans
FelixMau Jul 23, 2024
a576a53
Merge branch 'feature/handle_nans' into feature/extend_steel_example
FelixMau Jul 23, 2024
b98074d
Extend `parameter_name` mapping
FelixMau Jul 30, 2024
59f71d0
Better warning
FelixMau Jul 30, 2024
547e963
Better loggin in builder
FelixMau Jul 30, 2024
525bde6
Update dependencies
FelixMau Jul 30, 2024
80bf167
pre commit
FelixMau Jul 31, 2024
c4cd98a
Start adapters for GHG facades
SabineHaas Aug 20, 2024
5ece641
Write adapters for GHG facades
SabineHaas Aug 22, 2024
47f554e
Check that needed buses are defined
SabineHaas Aug 22, 2024
816fc42
Rename emission_factors from ef_.. in MimoAdapter
SabineHaas Aug 22, 2024
c990867
Add Modelstruktur.xlsx with GHG Adapters
SabineHaas Aug 22, 2024
b12b415
Merge branch 'feature/extend_steel_example' into feature/add_adapters
SabineHaas Aug 22, 2024
2b0dc5c
Apply black
SabineHaas Aug 22, 2024
9a03cf9
Add debug mode with 5 time steps per period
SabineHaas Aug 26, 2024
7fa288c
apply black
SabineHaas Aug 26, 2024
1a51d3c
Remove check that does not work
SabineHaas Aug 26, 2024
97429b0
Merge pull request #97 from sedos-project/feature/add_adapters
SabineHaas Aug 26, 2024
2775034
Add to .gitignore
SabineHaas Sep 4, 2024
345f2dc
Remove hard coded number
SabineHaas Sep 4, 2024
a1daa73
Bugfix in debug mode
SabineHaas Oct 10, 2024
be539f1
Add 'infite' amount 9999999999999 to commodities that are missing amount
SabineHaas Oct 14, 2024
c065665
Adapt emission factors to naming convention of oemof.tabular
SabineHaas Oct 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ __pycache__/
/tests/_files/tabular_datapackage_hack_a_thon/data/
/tests/_files/tabular_datapackage_hack_a_thon/datapackage.json
/tests/_files/tabular_datapackage_mininmal_example/
/tests/_files/tsam/*
/examples/industry/collections/*
/examples/industry/datapackage/*
109 changes: 102 additions & 7 deletions data_adapter_oemof/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import itertools
import json
import logging
import warnings
from typing import Optional, Type, Union

import pandas as pd
Expand Down Expand Up @@ -159,7 +158,10 @@ def get_data(self, key, field_type: Optional[Type] = None):
f"Using existing timeseries column '{timeseries_key}'."
)
return timeseries_key
logger.warning(f"Could not find timeseries entry for mapped key '{key}'")
logger.warning(
f"For Process {self.process_name}"
f"Could not find timeseries entry for mapped key '{key}'"
)
return None

# 2 Use defaults
Expand Down Expand Up @@ -228,11 +230,6 @@ def get_busses(self) -> dict:
struct = self.structure["default"]
else:
struct = self.structure
warnings.warn(
"Please check structure and provide either one set of inputs/outputs "
"or specify as default Parameter specific busses not implemented yet. "
f"No Bus found for Process {self.process_name} in Adapter {self}"
)

# 2. Check for default busses
if bus in ("bus", "from_bus", "to_bus", "fuel_bus"):
Expand All @@ -242,6 +239,11 @@ def get_busses(self) -> dict:
busses = struct["inputs"]
if bus == "to_bus":
busses = struct["outputs"]
if (
self.__class__.type == "storage"
and struct["inputs"] == struct["outputs"]
):
busses = struct["outputs"]
if len(busses) != 1:
raise MappingError(
f"Could not map {bus} to default bus - too many options"
Expand Down Expand Up @@ -426,6 +428,57 @@ def get_default_parameters(
if self.get("carrier") == "carrier":
defaults["carrier"] = self.get_busses()["bus"]

if self.get("amount") == None:
amount = 9999999999999
logger.warning(
f"Adding parameter 'amount' with value {amount} to commodity "
f"{self.process_name}. \n "
f"This is beneficial if your commodity is functioning as "
f"shortage or unlimited import/source. "
f"Otherwise please add 'amount' to your commodity!"
)
defaults["amount"] = amount

return defaults


class CommodityGHGAdapter(CommodityAdapter):
"""
CommodityGHGAdapter
"""

type = "commodity_ghg"
facade = facades.CommodityGHG

def get_busses(self) -> dict:
bus_list = self.structure["outputs"]
bus_dict = {}
counter = 0
for bus in bus_list:
if not bus.startswith("emi"):
bus_dict["bus"] = bus
elif bus.startswith("emi"):
bus_dict[f"emission_bus_{counter}"] = bus
counter += 1

# check that bus is defined
if bus_dict.get("bus") is None:
raise KeyError(f"{self.process_name} is missing 'bus', the input.")
return bus_dict

def get_default_parameters(self) -> dict:
defaults = super().get_default_parameters()
for key, value in self.data.items():
if key.startswith("ef"):
# adapt to the naming convention in oemof.tabular commodityGHG facade: emission_factor_<emission_bus_label>
target_label = None
emission_bus_labels = [key for item, key in defaults.items() if item.startswith("emission_bus")]
for label in emission_bus_labels:
if label in key:
target_label = label
if target_label == None:
raise ValueError(f"Emission factor of {self.process_name} is named {key} but None of the emission buses matches: {emission_bus_labels}.")
defaults[f"emission_factor_{target_label}"] = value
return defaults


Expand All @@ -439,6 +492,44 @@ class ConversionAdapter(Adapter):
facade = facades.Conversion


class ConversionGHGAdapter(Adapter):
"""
ConversionGHGAdapter
"""

type = "conversion_ghg"
facade = facades.ConversionGHG

def get_busses(self) -> dict:
def get_bus_from_struct(bus_list: list, bus_key: str) -> dict:
bus_dict = {}
counter = 0
for bus in bus_list:
if not bus.startswith("emi"):
bus_dict[f"{bus_key}"] = bus
elif bus.startswith("emi"):
bus_dict[f"emission_bus_{counter}"] = bus
counter += 1
return bus_dict

return_bus_dict = get_bus_from_struct(
self.structure["inputs"], bus_key="from_bus"
) | get_bus_from_struct(self.structure["outputs"], bus_key="to_bus")

# check that from_bus and to_bus is defined
for key in ["from_bus", "to_bus"]:
if return_bus_dict.get(key) is None:
raise KeyError(f"{self.process_name} is missing {key}.")
return return_bus_dict

def get_default_parameters(self) -> dict:
defaults = super().get_default_parameters()
for key, value in self.data.items():
if key.startswith("ef"):
defaults[key.replace("ef", "emission_factor")] = value
return defaults


class LoadAdapter(Adapter):
"""
LoadAdapter
Expand Down Expand Up @@ -492,6 +583,7 @@ class MIMOAdapter(Adapter):
Field(name="region", type=str),
Field(name="year", type=int),
Field(name="groups", type=dict),
Field(name="lifetime", type=float),
Field(name="capacity_cost", type=float),
Field(name="capacity", type=float),
Field(name="expandable", type=bool),
Expand All @@ -518,10 +610,13 @@ def get_default_parameters(self) -> dict:
"emissions_factor_",
"conversion_factor_",
"flow_share_",
"ef_",
)
for key, value in self.data.items():
for keyword in keywords:
if key.startswith(keyword):
if key.startswith("ef"):
key = key.replace("ef", "emission_factor")
defaults[key] = value
return defaults

Expand Down
43 changes: 26 additions & 17 deletions data_adapter_oemof/build_datapackage.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import dataclasses
import logging
import os
import warnings
from typing import Optional, Type
Expand All @@ -11,9 +12,12 @@

from data_adapter_oemof.adapters import FACADE_ADAPTERS
from data_adapter_oemof.adapters import Adapter as FacadeAdapter
from data_adapter_oemof.calculations import handle_nans
from data_adapter_oemof.settings import BUS_MAP, PARAMETER_MAP, PROCESS_ADAPTER_MAP
from data_adapter_oemof.utils import convert_mixed_types_to_same_length

logger = logging.getLogger()


# Define a function to aggregate differing values into a list
def _listify_to_periodic(group_df) -> pd.Series:
Expand Down Expand Up @@ -48,10 +52,11 @@ def _listify_to_periodic(group_df) -> pd.Series:


"""

group_df = handle_nans(group_df)
if "year" not in group_df.columns:
return group_df
unique_values = pd.Series(dtype=object)

for col in group_df.columns:
if isinstance(group_df[col][group_df.index[0]], dict):
# Unique input/output parameters are not allowed per period
Expand All @@ -64,21 +69,6 @@ def _listify_to_periodic(group_df) -> pd.Series:
):
values = group_df[col].explode().unique()
else:
# FIXME: Hotfix "if not" statement to replace nan values from lists:
# in final data only complete datasets are expected.
if not all(group_df[col].isna()) and any(group_df[col].isna()):
group_df.loc[group_df[col].isna(), col] = (
group_df[col]
.dropna()
.sample(
group_df[col]
.isna()
.sum(), # get the same number of values as are missing
replace=True,
random_state=0,
)
.values
) # throw out the index
values = group_df[col].unique()
if len(values) > 1:
if isinstance(group_df[col].iloc[0], list):
Expand All @@ -90,7 +80,6 @@ def _listify_to_periodic(group_df) -> pd.Series:
unique_values[col] = group_df[col].iat[0][0]
else:
unique_values[col] = group_df[col].iat[0]
unique_values["name"] = "_".join(group_df.name)
unique_values.drop("year")
return unique_values

Expand Down Expand Up @@ -463,6 +452,7 @@ def build_datapackage(
parameter_map: Optional[dict] = PARAMETER_MAP,
bus_map: Optional[dict] = BUS_MAP,
location_to_save_to: str = None,
debug=False,
):
"""
Creating a Datapackage from the oemof_data_adapter that fits oemof.tabular Datapackages.
Expand Down Expand Up @@ -508,6 +498,9 @@ def _reduce_lists(x):
+ _reduce_lists(timeseries.columns.get_level_values(1))
)
facade_adapter_name: str = process_adapter_map[process_name]
logger.info(
f"Adaptering process {process_name} into adapter {facade_adapter_name}"
)
facade_adapter: Type[FacadeAdapter] = FACADE_ADAPTERS[facade_adapter_name]
component_adapter: Optional[FacadeAdapter] = None
components = []
Expand Down Expand Up @@ -553,6 +546,22 @@ def _reduce_lists(x):
)
periods = cls.get_periods_from_parametrized_sequences(parametrized_sequences)

def reduce_data_frame(data_frame, steps=4):
"""reduces `df` to 5 time steps per period"""
df = data_frame.copy()
df["ind"] = df.index
df["ind"] = df["ind"].apply(
lambda x: True if x.month == 1 and x.day == 1 and x.hour <= steps else False
)
df_reduced = df.loc[df["ind"] == 1].drop(columns=["ind"])
return df_reduced

if debug:
periods = reduce_data_frame(data_frame=periods)
for key, value in parametrized_sequences.items():
df_short = reduce_data_frame(data_frame=value)
parametrized_sequences.update({key: df_short})

return cls(
parametrized_elements=parametrized_elements,
parametrized_sequences=parametrized_sequences,
Expand Down
Loading
Loading