Skip to content

Commit

Permalink
Merge pull request #398 from openego/features/minor_improvements
Browse files Browse the repository at this point in the history
Features/minor improvements
  • Loading branch information
birgits authored Apr 24, 2024
2 parents 0f603cc + fd75b51 commit cb9307e
Show file tree
Hide file tree
Showing 12 changed files with 239 additions and 90 deletions.
12 changes: 9 additions & 3 deletions .github/workflows/tests-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
python-version: ${{ matrix.python-version }}

- name: Set up julia
if: runner.os == 'Linux' && matrix.python-version == 3.8 && matrix.name-suffix == 'coverage'
if: runner.os == 'Linux'
uses: julia-actions/setup-julia@v1
with:
version: "1.6"
Expand All @@ -58,8 +58,14 @@ jobs:
environment-file: eDisGo_env_dev.yml
python-version: ${{ matrix.python-version }}

- name: Run tests
if: ${{ !(runner.os == 'Linux' && matrix.python-version == 3.8 && matrix.name-suffix == 'coverage') }}
- name: Run tests Linux
if: runner.os == 'Linux' && matrix.name-suffix != 'coverage'
run: |
python -m pip install pytest pytest-notebook
python -m pytest --runslow --runonlinux --disable-warnings --color=yes -v
- name: Run tests Windows
if: runner.os == 'Windows'
run: |
python -m pip install pytest pytest-notebook
python -m pytest --runslow --disable-warnings --color=yes -v
Expand Down
104 changes: 94 additions & 10 deletions edisgo/flex_opt/costs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import os

import pandas as pd
Expand All @@ -7,6 +8,8 @@

from edisgo.tools.geo import proj2equidistant

logger = logging.getLogger(__name__)


def grid_expansion_costs(edisgo_obj, without_generator_import=False):
"""
Expand Down Expand Up @@ -67,7 +70,8 @@ def _get_transformer_costs(trafos):
costs_trafos = pd.DataFrame(
{
"costs_transformers": len(hvmv_trafos)
* [float(edisgo_obj.config["costs_transformers"]["mv"])]
* [float(edisgo_obj.config["costs_transformers"]["mv"])],
"voltage_level": len(hvmv_trafos) * ["hv/mv"],
},
index=hvmv_trafos,
)
Expand All @@ -77,13 +81,14 @@ def _get_transformer_costs(trafos):
pd.DataFrame(
{
"costs_transformers": len(mvlv_trafos)
* [float(edisgo_obj.config["costs_transformers"]["lv"])]
* [float(edisgo_obj.config["costs_transformers"]["lv"])],
"voltage_level": len(mvlv_trafos) * ["mv/lv"],
},
index=mvlv_trafos,
),
]
)
return costs_trafos.loc[trafos.index, "costs_transformers"].values
return costs_trafos.loc[trafos.index, :]

def _get_line_costs(lines_added):
costs_lines = line_expansion_costs(edisgo_obj, lines_added.index)
Expand All @@ -107,9 +112,8 @@ def _get_line_costs(lines_added):
# costs for transformers
if not equipment_changes.empty:
transformers = equipment_changes[
equipment_changes.index.isin(
[f"{_}_station" for _ in edisgo_obj.topology._grids_repr]
)
equipment_changes.equipment.str.contains("Transformer")
| equipment_changes.equipment.str.contains("transformer")
]
added_transformers = transformers[transformers["change"] == "added"]
removed_transformers = transformers[transformers["change"] == "removed"]
Expand All @@ -129,15 +133,16 @@ def _get_line_costs(lines_added):
)
trafos = all_trafos.loc[added_transformers["equipment"]]
# calculate costs for each transformer
transformer_costs = _get_transformer_costs(trafos)
costs = pd.concat(
[
costs,
pd.DataFrame(
{
"type": trafos.type_info.values,
"total_costs": _get_transformer_costs(trafos),
"total_costs": transformer_costs.costs_transformers,
"quantity": len(trafos) * [1],
"voltage_level": len(trafos) * ["mv/lv"],
"voltage_level": transformer_costs.voltage_level,
},
index=trafos.index,
),
Expand All @@ -161,6 +166,19 @@ def _get_line_costs(lines_added):
.sum()
.loc[lines_added_unique, ["quantity"]]
)
# use the minimum of quantity and num_parallel, as sometimes lines are added
# and in a next reinforcement step removed again, e.g. when feeder is split
# at 2/3 and a new single standard line is added
lines_added = pd.merge(
lines_added,
edisgo_obj.topology.lines_df.loc[:, ["num_parallel"]],
how="left",
left_index=True,
right_index=True,
)
lines_added["quantity_added"] = lines_added.loc[
:, ["quantity", "num_parallel"]
].min(axis=1)
lines_added["length"] = edisgo_obj.topology.lines_df.loc[
lines_added.index, "length"
]
Expand All @@ -176,9 +194,9 @@ def _get_line_costs(lines_added):
].values,
"total_costs": line_costs.costs.values,
"length": (
lines_added.quantity * lines_added.length
lines_added.quantity_added * lines_added.length
).values,
"quantity": lines_added.quantity.values,
"quantity": lines_added.quantity_added.values,
"voltage_level": line_costs.voltage_level.values,
},
index=lines_added.index,
Expand Down Expand Up @@ -288,3 +306,69 @@ def line_expansion_costs(edisgo_obj, lines_names=None):
]
)
return costs_lines.loc[lines_df.index]


def transformer_expansion_costs(edisgo_obj, transformer_names=None):
"""
Returns costs per transformer in kEUR as well as voltage level they are in.
Parameters
-----------
edisgo_obj : :class:`~.EDisGo`
eDisGo object
transformer_names: None or list(str)
List of names of transformers to return cost information for. If None, it is
returned for all transformers in
:attr:`~.network.topology.Topology.transformers_df` and
:attr:`~.network.topology.Topology.transformers_hvmv_df`.
Returns
-------
costs: :pandas:`pandas.DataFrame<DataFrame>`
Dataframe with names of transformers in index and columns 'costs' with
costs per transformer in kEUR and 'voltage_level' with information on voltage
level the transformer is in.
"""
transformers_df = pd.concat(
[
edisgo_obj.topology.transformers_df.copy(),
edisgo_obj.topology.transformers_hvmv_df.copy(),
]
)
if transformer_names is not None:
transformers_df = transformers_df.loc[transformer_names, ["type_info"]]

if len(transformers_df) == 0:
return pd.DataFrame(columns=["costs", "voltage_level"])

hvmv_transformers = transformers_df[
transformers_df.index.isin(edisgo_obj.topology.transformers_hvmv_df.index)
].index
mvlv_transformers = transformers_df[
transformers_df.index.isin(edisgo_obj.topology.transformers_df.index)
].index

costs_hvmv = float(edisgo_obj.config["costs_transformers"]["mv"])
costs_mvlv = float(edisgo_obj.config["costs_transformers"]["lv"])

costs_df = pd.DataFrame(
{
"costs": costs_hvmv,
"voltage_level": "hv/mv",
},
index=hvmv_transformers,
)
costs_df = pd.concat(
[
costs_df,
pd.DataFrame(
{
"costs": costs_mvlv,
"voltage_level": "mv/lv",
},
index=mvlv_transformers,
),
]
)
return costs_df
10 changes: 8 additions & 2 deletions edisgo/io/powermodels_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -957,10 +957,16 @@ def _build_load(
)
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "storage")
p_d = -min(
[psa_net.storage_units_t.p_set[inflexible_storage_units[stor_i]][0], 0]
[
psa_net.storage_units_t.p_set[inflexible_storage_units[stor_i]][0],
np.float64(0.0),
]
)
q_d = -max(
[psa_net.storage_units_t.q_set[inflexible_storage_units[stor_i]][0], 0]
[
psa_net.storage_units_t.q_set[inflexible_storage_units[stor_i]][0],
np.float64(0.0),
]
)
pm["load"][str(stor_i + len(loads_df.index) + 1)] = {
"pd": p_d.round(20) / s_base,
Expand Down
47 changes: 20 additions & 27 deletions edisgo/io/timeseries_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,7 @@ def get_residential_electricity_profiles_per_building(building_ids, scenario, en
List of building IDs to retrieve electricity demand profiles for.
scenario : str
Scenario for which to retrieve demand data. Possible options
are 'eGon2035' and 'eGon100RE'.
are 'eGon2021', 'eGon2035' and 'eGon100RE'.
engine : :sqlalchemy:`sqlalchemy.Engine<sqlalchemy.engine.Engine>`
Database engine.
Expand Down Expand Up @@ -1220,30 +1220,21 @@ def _get_scaling_factors_of_zensus_cells(zensus_ids):
column factor.
"""
with session_scope_egon_data(engine) as session:
if scenario == "eGon2035":
query = session.query(
egon_household_electricity_profile_in_census_cell.cell_id,
egon_household_electricity_profile_in_census_cell.factor_2035.label(
"factor"
),
).filter(
egon_household_electricity_profile_in_census_cell.cell_id.in_(
zensus_ids
)
)
else:
query = session.query(
egon_household_electricity_profile_in_census_cell.cell_id,
egon_household_electricity_profile_in_census_cell.factor_2050.label(
"factor"
),
).filter(
egon_household_electricity_profile_in_census_cell.cell_id.in_(
zensus_ids
)
)
return pd.read_sql(query.statement, engine, index_col="cell_id")
if scenario == "eGon2021":
return pd.DataFrame(index=zensus_ids, data={"factor": 1.0})
else:
with session_scope_egon_data(engine) as session:
if scenario == "eGon2035":
query = session.query(
hh_profile.cell_id,
hh_profile.factor_2035.label("factor"),
).filter(hh_profile.cell_id.in_(zensus_ids))
else:
query = session.query(
hh_profile.cell_id,
hh_profile.factor_2050.label("factor"),
).filter(hh_profile.cell_id.in_(zensus_ids))
return pd.read_sql(query.statement, engine, index_col="cell_id")

def _get_profile_ids_of_buildings(building_ids):
"""
Expand Down Expand Up @@ -1302,7 +1293,9 @@ def _get_profiles(profile_ids):

saio.register_schema("demand", engine)
from saio.demand import (
egon_household_electricity_profile_in_census_cell,
egon_household_electricity_profile_in_census_cell as hh_profile,
)
from saio.demand import (
egon_household_electricity_profile_of_buildings,
iee_household_load_profiles,
)
Expand Down Expand Up @@ -1350,7 +1343,7 @@ def get_industrial_electricity_profiles_per_site(site_ids, scenario, engine):
List of industrial site and OSM IDs to retrieve electricity demand profiles for.
scenario : str
Scenario for which to retrieve demand data. Possible options
are 'eGon2035' and 'eGon100RE'.
are 'eGon2021', 'eGon2035' and 'eGon100RE'.
engine : :sqlalchemy:`sqlalchemy.Engine<sqlalchemy.engine.Engine>`
Database engine.
Expand Down
2 changes: 1 addition & 1 deletion edisgo/network/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ def _add_line_to_equipment_changes(self, line):
"iteration_step": [0],
"change": ["added"],
"equipment": [line.type_info],
"quantity": [1],
"quantity": [line.num_parallel],
},
index=[line.name],
),
Expand Down
4 changes: 2 additions & 2 deletions edisgo/tools/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def setup_logger(

def create_dir(dir_path):
if not os.path.isdir(dir_path):
os.mkdir(dir_path)
os.makedirs(dir_path)

def get_default_root_dir():
dir_path = str(cfg_edisgo.get("user_dirs", "root_dir"))
Expand All @@ -140,9 +140,9 @@ def create_home_dir():
log_dir = os.path.join(
get_default_root_dir(), cfg_edisgo.get("user_dirs", "log_dir")
)
create_dir(log_dir)

if log_dir is not None:
create_dir(log_dir)
file_name = os.path.join(log_dir, file_name)

if reset_loggers:
Expand Down
6 changes: 2 additions & 4 deletions examples/electromobility_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,7 @@
" url = (f\"https://github.com/openego/eDisGo/tree/dev/\" +\n",
" f\"tests/data/simbev_example_scenario/{ags}/\")\n",
" page = requests.get(url).text\n",
" items = json.loads(page)[\"payload\"][\"tree\"][\"items\"]\n",
" filenames = [f[\"name\"] for f in items if \"csv\" in f[\"name\"]]\n",
" filenames = [_ for _ in page.split('\"') if \".csv\" in _ and \"/\" not in _]\n",
"\n",
" for file in filenames:\n",
" req = requests.get(f\"{raw_url}/{ags}/{file}\")\n",
Expand Down Expand Up @@ -470,8 +469,7 @@
" url = (\"https://github.com/openego/eDisGo/tree/dev/\" +\n",
" \"tests/data/tracbev_example_scenario/\")\n",
" page = requests.get(url).text\n",
" items = json.loads(page)[\"payload\"][\"tree\"][\"items\"]\n",
" filenames = [f[\"name\"] for f in items if \"gpkg\" in f[\"name\"]]\n",
" filenames = [_ for _ in page.split('\"') if \".gpkg\" in _ and \"/\" not in _]\n",
"\n",
" for file in filenames:\n",
" req = requests.get(\n",
Expand Down
Loading

0 comments on commit cb9307e

Please sign in to comment.