# Path: edisgo/tools/tools.py
# def select_worstcase_snapshots(edisgo_obj):
# def calculate_relative_line_load(
#     edisgo_obj, lines=None, timesteps=None
# ):
# def calculate_line_reactance(line_inductance_per_km, line_length,
#                              num_parallel):
# def calculate_line_resistance(line_resistance_per_km, line_length,
#                               num_parallel):
# def calculate_apparent_power(nominal_voltage, current, num_parallel):
# def drop_duplicated_indices(dataframe, keep="first"):
# def drop_duplicated_columns(df, keep="first"):
# def select_cable(edisgo_obj, level, apparent_power):
# def assign_feeder(edisgo_obj, mode="mv_feeder"):
#     def _assign_to_busses(graph, station):
#     def _assign_to_lines(lines):
# def get_path_length_to_station(edisgo_obj):
# def assign_voltage_level_to_component(edisgo_obj, df):
# def get_weather_cells_intersecting_with_grid_district(edisgo_obj):
# 
# Path: edisgo/flex_opt/check_tech_constraints.py
# def mv_line_load(edisgo_obj):
# def lv_line_load(edisgo_obj):
# def lines_allowed_load(edisgo_obj, voltage_level):
# def lines_relative_load(edisgo_obj, lines_allowed_load):
# def _line_load(edisgo_obj, voltage_level):
# def hv_mv_station_load(edisgo_obj):
# def mv_lv_station_load(edisgo_obj):
# def _station_load(edisgo_obj, grid):
# def mv_voltage_deviation(edisgo_obj, voltage_levels="mv_lv"):
# def lv_voltage_deviation(edisgo_obj, mode=None, voltage_levels="mv_lv"):
# def _mv_allowed_voltage_limits(edisgo_obj, voltage_levels):
# def _lv_allowed_voltage_limits(edisgo_obj, lv_grid, mode):
# def voltage_diff(edisgo_obj, buses, v_dev_allowed_upper, v_dev_allowed_lower):
# def _voltage_deviation(edisgo_obj, buses, v_limits_upper, v_limits_lower):
#     def _append_crit_buses(df):
# def check_ten_percent_voltage_deviation(edisgo_obj):
# 
# Path: edisgo/flex_opt/costs.py
# def grid_expansion_costs(
#     edisgo_obj, without_generator_import=False
# ):
#     def _get_transformer_costs(trafos):
#     def _get_line_costs(lines_added):
# def line_expansion_costs(edisgo_obj, lines_names):
# 
# Path: edisgo/tools/plots.py
# def histogram(data, **kwargs):
# def add_basemap(ax, zoom=12):
# def get_grid_district_polygon(config, subst_id=None, projection=4326):
# def mv_grid_topology(
#     edisgo_obj,
#     timestep=None,
#     line_color=None,
#     node_color=None,
#     line_load=None,
#     grid_expansion_costs=None,
#     filename=None,
#     arrows=False,
#     grid_district_geom=True,
#     background_map=True,
#     voltage=None,
#     limits_cb_lines=None,
#     limits_cb_nodes=None,
#     xlim=None,
#     ylim=None,
#     lines_cmap="inferno_r",
#     title="",
#     scaling_factor_line_width=None,
#     curtailment_df=None,
#     **kwargs
# ):
#     def get_color_and_size(connected_components, colors_dict, sizes_dict):
#     def nodes_by_technology(buses, edisgo_obj):
#     def nodes_charging_park(buses, edisgo_obj):
#     def nodes_by_voltage(buses, voltages):
#     def nodes_by_voltage_deviation(buses, voltages):
#     def nodes_storage_integration(buses, edisgo_obj):
#     def nodes_curtailment(buses, curtailment_df):
#     def nodes_by_costs(buses, grid_expansion_costs, edisgo_obj):


import networkx as nx
import pandas as pd
import numpy as np
import logging
from networkx.algorithms.shortest_paths.weighted import (
    _dijkstra as dijkstra_shortest_path_length,
)
from math import sqrt, ceil
from edisgo.tools import tools
from edisgo.flex_opt import check_tech_constraints, costs
from edisgo.tools import plots

                        if debug:
                            storage_repr.append(repr(storage_obj))
                            storage_size.append(storage_obj.nominal_power)

                        total_grid_expansion_costs = (
                            total_grid_expansion_costs_new
                        )

                    else:
                        logger.debug(
                            "Storage integration in feeder {} did not reduce "
                            "network expansion costs (costs increased by {} "
                            "kEuro).".format(feeder, -costs_diff)
                        )

                        tools.disconnect_storage(edisgo.network, storage_obj)
                        p_storage = 0

                        if debug:
                            storage_repr.append(None)
                            storage_size.append(0)

                            edisgo.integrate_storage(
                                timeseries=storage_timeseries.p * 0,
                                position=battery_node,
                                voltage_level="mv",
                                timeseries_reactive_power=storage_timeseries.q
                                * 0,
                            )

# Path: edisgo/tools/tools.py
# def select_worstcase_snapshots(edisgo_obj):
# def calculate_relative_line_load(
#     edisgo_obj, lines=None, timesteps=None
# ):
# def calculate_line_reactance(line_inductance_per_km, line_length,
#                              num_parallel):
# def calculate_line_resistance(line_resistance_per_km, line_length,
#                               num_parallel):
# def calculate_apparent_power(nominal_voltage, current, num_parallel):
# def drop_duplicated_indices(dataframe, keep="first"):
# def drop_duplicated_columns(df, keep="first"):
# def select_cable(edisgo_obj, level, apparent_power):
# def assign_feeder(edisgo_obj, mode="mv_feeder"):
#     def _assign_to_busses(graph, station):
#     def _assign_to_lines(lines):
# def get_path_length_to_station(edisgo_obj):
# def assign_voltage_level_to_component(edisgo_obj, df):
# def get_weather_cells_intersecting_with_grid_district(edisgo_obj):
# 
# Path: edisgo/flex_opt/check_tech_constraints.py
# def mv_line_load(edisgo_obj):
# def lv_line_load(edisgo_obj):
# def lines_allowed_load(edisgo_obj, voltage_level):
# def lines_relative_load(edisgo_obj, lines_allowed_load):
# def _line_load(edisgo_obj, voltage_level):
# def hv_mv_station_load(edisgo_obj):
# def mv_lv_station_load(edisgo_obj):
# def _station_load(edisgo_obj, grid):
# def mv_voltage_deviation(edisgo_obj, voltage_levels="mv_lv"):
# def lv_voltage_deviation(edisgo_obj, mode=None, voltage_levels="mv_lv"):
# def _mv_allowed_voltage_limits(edisgo_obj, voltage_levels):
# def _lv_allowed_voltage_limits(edisgo_obj, lv_grid, mode):
# def voltage_diff(edisgo_obj, buses, v_dev_allowed_upper, v_dev_allowed_lower):
# def _voltage_deviation(edisgo_obj, buses, v_limits_upper, v_limits_lower):
#     def _append_crit_buses(df):
# def check_ten_percent_voltage_deviation(edisgo_obj):
# 
# Path: edisgo/flex_opt/costs.py
# def grid_expansion_costs(
#     edisgo_obj, without_generator_import=False
# ):
#     def _get_transformer_costs(trafos):
#     def _get_line_costs(lines_added):
# def line_expansion_costs(edisgo_obj, lines_names):
# 
# Path: edisgo/tools/plots.py
# def histogram(data, **kwargs):
# def add_basemap(ax, zoom=12):
# def get_grid_district_polygon(config, subst_id=None, projection=4326):
# def mv_grid_topology(
#     edisgo_obj,
#     timestep=None,
#     line_color=None,
#     node_color=None,
#     line_load=None,
#     grid_expansion_costs=None,
#     filename=None,
#     arrows=False,
#     grid_district_geom=True,
#     background_map=True,
#     voltage=None,
#     limits_cb_lines=None,
#     limits_cb_nodes=None,
#     xlim=None,
#     ylim=None,
#     lines_cmap="inferno_r",
#     title="",
#     scaling_factor_line_width=None,
#     curtailment_df=None,
#     **kwargs
# ):
#     def get_color_and_size(connected_components, colors_dict, sizes_dict):
#     def nodes_by_technology(buses, edisgo_obj):
#     def nodes_charging_park(buses, edisgo_obj):
#     def nodes_by_voltage(buses, voltages):
#     def nodes_by_voltage_deviation(buses, voltages):
#     def nodes_storage_integration(buses, edisgo_obj):
#     def nodes_curtailment(buses, curtailment_df):
#     def nodes_by_costs(buses, grid_expansion_costs, edisgo_obj):


# Path: edisgo/flex_opt/storage_positioning.py
import networkx as nx
import pandas as pd
import numpy as np
import logging
from networkx.algorithms.shortest_paths.weighted import (
    _dijkstra as dijkstra_shortest_path_length,
)
from math import sqrt, ceil
from edisgo.tools import tools
from edisgo.flex_opt import check_tech_constraints, costs
from edisgo.tools import plots


                        if debug:
                            storage_repr.append(repr(storage_obj))
                            storage_size.append(storage_obj.nominal_power)

                        total_grid_expansion_costs = (
                            total_grid_expansion_costs_new
                        )

                    else:
                        logger.debug(
                            "Storage integration in feeder {} did not reduce "
                            "network expansion costs (costs increased by {} "
                            "kEuro).".format(feeder, -costs_diff)
                        )

                        tools.disconnect_storage(edisgo.network, storage_obj)
                        p_storage = 0

                        if debug:
                            storage_repr.append(None)
                            storage_size.append(0)

                            edisgo.integrate_storage(
                                timeseries=storage_timeseries.p * 0,
                                position=battery_node,
                                voltage_level="mv",
                                timeseries_reactive_power=storage_timeseries.q
                                * 0,
                            )

                            tools.assign_mv_feeder_to_nodes(