def export_network(nw, mode=''):
    """
    Export all nodes and lines of the network nw as DataFrames

    Parameters
    ----------
    nw: :any:`list` of NetworkDing0
        The MV grid(s) to be studied
    mode: str
        If 'MV' export only medium voltage nodes and lines
        If 'LV' export only low voltage nodes and lines
        else, exports MV and LV nodes and lines

    Returns
    -------
    pandas.DataFrame
        nodes_df : Dataframe containing nodes and its attributes
    pandas.DataFrame
        lines_df : Dataframe containing lines and its attributes
    """

    # close circuit breakers
    nw.control_circuit_breakers(mode='close')
    # srid
    srid = str(int(nw.config['geo']['srid']))
    ##############################
    # check what to do
    lv_info = True
    mv_info = True
    if mode == 'LV':
        mv_info = False
    if mode == 'MV':
        lv_info = False
    ##############################
    # from datetime import datetime
    run_id = nw.metadata['run_id']  # datetime.now().strftime("%Y%m%d%H%M%S")
    ##############################
    #############################
    # go through the grid collecting info
    lvgrid_idx = 0
    lv_grid_dict = {}
    lvloads_idx = 0
    lv_loads_dict = {}
    mvgrid_idx = 0
    mv_grid_dict = {}
    mvloads_idx = 0
    mv_loads_dict = {}
    mvgen_idx = 0
    mv_gen_dict = {}
    mvcb_idx = 0
    mvcb_dict = {}
    mvcd_idx = 0
    mv_cd_dict = {}
    mvstations_idx = 0
    hvmv_stations_dict = {}
    mvtrafos_idx = 0
    hvmv_trafos_dict = {}
    lvgen_idx = 0
    lv_gen_dict = {}
    lvcd_idx = 0
    lv_cd_dict = {}
    lvstations_idx = 0
    mvlv_stations_dict = {}
    lvtrafos_idx = 0
    mvlv_trafos_dict = {}
    areacenter_idx = 0
    areacenter_dict = {}
    lines_idx = 0
    lines_dict = {}
    LVMVmapping_idx = 0
    mvlv_mapping_dict = {}

    def aggregate_generators(gen, aggr):
        """Aggregate generation capacity per voltage level
        Parameters
        ----------
        gen: ding0.core.GeneratorDing0
            Ding0 Generator object
        aggr: dict
            Aggregated generation capacity. For structure see
            `_determine_aggregated_nodes()`.
        Returns
        -------
        """

        if gen.v_level not in aggr['generation']:
            aggr['generation'][gen.v_level] = {}
        if gen.type not in aggr['generation'][gen.v_level]:
            aggr['generation'][gen.v_level][gen.type] = {}
        if gen.subtype not in aggr['generation'][gen.v_level][gen.type]:
            aggr['generation'][gen.v_level][gen.type].update(
                {gen.subtype: {'ids': [gen.id_db],
                               'capacity': gen.capacity}})
        else:
            aggr['generation'][gen.v_level][gen.type][gen.subtype][
                'ids'].append(gen.id_db)
            aggr['generation'][gen.v_level][gen.type][gen.subtype][
                'capacity'] += gen.capacity

        return aggr

    def aggregate_loads(la_center, aggr):
        """Aggregate consumption in load area per sector
        Parameters
        ----------
        la_center: LVLoadAreaCentreDing0
            Load area center object from Ding0
        Returns
        -------
        """
        for s in ['retail', 'industrial', 'agricultural', 'residential']:
            if s not in aggr['load']:
                aggr['load'][s] = {}

            for t in ['nominal','peak']:
                if t not in aggr['load'][s]:
                    aggr['load'][s][t] = 0

        aggr['load']['retail']['nominal'] += sum(
            [_.sector_consumption_retail
             for _ in la_center.lv_load_area._lv_grid_districts])
        aggr['load']['industrial']['nominal'] += sum(
            [_.sector_consumption_industrial
             for _ in la_center.lv_load_area._lv_grid_districts])
        aggr['load']['agricultural']['nominal'] += sum(
            [_.sector_consumption_agricultural
             for _ in la_center.lv_load_area._lv_grid_districts])
        aggr['load']['residential']['nominal'] += sum(
            [_.sector_consumption_residential
             for _ in la_center.lv_load_area._lv_grid_districts])

        aggr['load']['retail']['peak'] += sum(
            [_.peak_load_retail
             for _ in la_center.lv_load_area._lv_grid_districts])
        aggr['load']['industrial']['peak'] += sum(
            [_.peak_load_industrial
             for _ in la_center.lv_load_area._lv_grid_districts])
        aggr['load']['agricultural']['peak'] += sum(
            [_.peak_load_agricultural
             for _ in la_center.lv_load_area._lv_grid_districts])
        aggr['load']['residential']['peak'] += sum(
            [_.peak_load_residential
             for _ in la_center.lv_load_area._lv_grid_districts])

        return aggr

    for mv_district in nw.mv_grid_districts():

        mv_grid_id = mv_district.mv_grid.id_db
        mv_grid_id_db = '_'.join(
            [str(mv_district.mv_grid.__class__.__name__), 'MV', str(mv_grid_id), str(mv_district.mv_grid.id_db)])

        if mv_info:
            lv_grid_id = 0

            # MV-grid
            # ToDo: geom <- Polygon
            mvgrid_idx += 1
            mv_grid_dict[mvgrid_idx] = {
                'MV_grid_id': mv_district.mv_grid.id_db,
                'id_db': '_'.join([str(mv_district.mv_grid.__class__.__name__), 'MV', str(mv_grid_id),
                                   str(mv_district.mv_grid.id_db)]),
                # 'network': mv_district.mv_grid.network,
                'geom': wkt_dumps(mv_district.geo_data),
                'population':  # None,
                    sum([_.zensus_sum
                         for _ in
                         mv_district._lv_load_areas  # ding0_grid.grid_district._lv_load_areas
                         if not np.isnan(_.zensus_sum)]),
                'voltage_nom': mv_district.mv_grid.v_level,  # in kV
                'run_id': run_id
            }

            # id_db: Classname_MV/LV_mvgridid/lvgridid_id
            # excemptions: class LVStations: LVStationDing0_MV_mvgridid_id(=lvgridid)

            # MVGrid
            for node in mv_district.mv_grid.graph_nodes_sorted():
                geom = wkt_dumps(node.geo_data)
                # geom = from_shape(Point(node.geo_data), srid=srid)
                db_id = node.id_db

                # LVStation
                if isinstance(node, LVStationDing0):
                    if not node.lv_load_area.is_aggregated:
                        lvstations_idx += 1
                        mvlv_stations_dict[lvstations_idx] = {
                            'id_db': '_'.join([str(node.__class__.__name__), 'MV', str(mv_grid_id), str(node.id_db)]),
                            'LV_grid_id_db': '_'.join(['LVGridDing0', 'LV', str(node.id_db), str(node.id_db)]),
                            'geom': geom,
                            'run_id': run_id,
                        }

                        # LV-MV mapping
                        LVMVmapping_idx += 1
                        mvlv_mapping_dict[LVMVmapping_idx] = {
                            'MV_grid_id': mv_grid_id,
                            'MV_grid_id_db': mv_grid_id_db,
                            'LV_grid_id': node.id_db,
                            'LV_grid_id_db': '_'.join(['LVGridDing0', 'LV', str(node.id_db), str(node.id_db)]),
                            'run_id': run_id,
                        }

                        # Trafos LV
                        for t in node.transformers():
                            lvtrafos_idx += 1
                            mvlv_trafos_dict[lvtrafos_idx] = {
                                'id_db': '_'.join([str(t.__class__.__name__), 'LV', str(mv_grid_id), str(node.id_db)]),
                                'geom': geom,
                                'LV_grid_id_db': '_'.join(['LVGridDing0', 'LV', str(node.id_db), str(node.id_db)]),
                                'voltage_op': t.v_level,
                                'S_nom': t.s_max_a,
                                'X': t.x,
                                'R': t.r,
                                'run_id': run_id,
                            }

                # MVStation
                elif isinstance(node, MVStationDing0):
                    mvstations_idx += 1
                    hvmv_stations_dict[mvstations_idx] = {
                        'id_db': '_'.join([str(node.__class__.__name__), 'MV', str(mv_grid_id), str(node.id_db)]),
                        'MV_grid_id_db': mv_grid_id_db,
                        'geom': geom,
                        'run_id': run_id,
                    }

                    # Trafos MV
                    for t in node.transformers():
                        mvtrafos_idx += 1
                        hvmv_trafos_dict[mvtrafos_idx] = {
                            'id_db': '_'.join([str(t.__class__.__name__), 'MV', str(mv_grid_id), str(node.id_db)]),
                            'geom': geom,
                            'MV_grid_id_db': mv_grid_id_db,
                            'voltage_op': t.v_level,
                            'S_nom': t.s_max_a,
                            'X': t.x,
                            'R': t.r,
                            'run_id': run_id,
                        }

                # MVGenerator
                elif isinstance(node, GeneratorDing0):
                    if node.subtype == None:
                        subtype = 'other'
                    else:
                        subtype = node.subtype
                    type = node.type
                    mvgen_idx += 1
                    mv_gen_dict[mvgen_idx] = {
                        'id_db': '_'.join([str(node.__class__.__name__), 'MV', str(mv_grid_id), str(node.id_db)]),
                        'MV_grid_id_db': mv_grid_id_db,
                        'geom': geom,
                        'type': type,
                        'subtype': subtype,
                        'v_level': node.v_level,
                        'nominal_capacity': node.capacity,
                        'run_id': run_id,
                        'is_aggregated': False,
                    }

                # MVBranchTees
                elif isinstance(node, MVCableDistributorDing0):
                    mvcd_idx += 1
                    mv_cd_dict[mvcd_idx] = {
                        'id_db': '_'.join([str(node.__class__.__name__), 'MV', str(mv_grid_id), str(node.id_db)]),
                        'MV_grid_id_db': mv_grid_id_db,
                        'geom': geom,
                        'run_id': run_id,
                    }

                # LoadAreaCentre
                elif isinstance(node, LVLoadAreaCentreDing0):

                    # type = 'Load area center of aggregated load area'

                    areacenter_idx += 1
                    aggr_lines = 0

                    aggr = {'generation': {}, 'load': {}, 'aggregates': []}

                    # Determine aggregated generation in LV grid
                    for lvgd in node.lv_load_area._lv_grid_districts:

                        for aggr_gen in lvgd.lv_grid.generators():
                            aggr = aggregate_generators(aggr_gen, aggr)

                            if aggr_gen.subtype == None:
                                subtype = 'other'
                            else:
                                subtype = aggr_gen.subtype
                            type = aggr_gen.type

                    # Determine aggregated load in MV grid
                    # -> Implement once loads in Ding0 MV grids exist

                    # Determine aggregated load in LV grid
                    aggr = aggregate_loads(node, aggr)

                    # Collect metadata of aggregated load areas
                    aggr['aggregates'] = {
                        'population': node.lv_load_area.zensus_sum,
                        'geom': node.lv_load_area.geo_area}
                    aggr_line_type = nw._static_data['MV_cables'].iloc[
                        nw._static_data['MV_cables']['I_max_th'].idxmax()]
                    geom = wkt_dumps(node.lv_load_area.geo_area)

                    for aggr_node in aggr:
                        if aggr_node == 'generation':
                            mvgenaggr_idx = 0

                            for v_level in aggr['generation']:
                                for type in aggr['generation'][v_level]:
                                    for subtype in aggr['generation'][v_level][type]:
                                        mvgen_idx += 1
                                        mvgenaggr_idx += 1
                                        mv_gen_dict[mvgen_idx] = {
                                            'id_db': '_'.join(
                                                [str(aggr_gen.__class__.__name__), 'MV', str(mv_grid_id),
                                                 str(aggr_gen.id_db), str(mvgenaggr_idx)]),  # , str(mvgen_idx)
                                            'MV_grid_id_db': mv_grid_id_db,
                                            'geom': geom,#from_shape(Point(mv_district.mv_grid.station().geo_data), srid=srid),#lv_load_area.geo_area,#geom, #?? Polygon # hvmv_stations_dict[mvstations_idx]['geom'], #
                                            'type': type,
                                            'subtype': subtype,
                                            'v_level': v_level,
                                            'nominal_capacity': aggr['generation'][v_level][type][subtype]['capacity'],
                                            'is_aggregated': True,
                                            'run_id': run_id,
                                        }

                                        lines_idx += 1
                                        aggr_lines += 1
                                        lines_dict[lines_idx] = {
                                            # ToDo: Rename edge_name
                                            'edge_name': '_'.join(
                                                [str(mv_grid_id), 'aggr', str(node.lv_load_area.id_db),
                                                 str(aggr_lines)]),
                                            # , 'vlevel', str(v_level), 'subtype', str(subtype)]),#}'.format(v_level=v_level, subtype=subtype),
                                            'grid_id_db': mv_grid_id_db,
                                            # ToDo: read type_name from aggr_line_type
                                            'type_name': 'NA2XS2Y 3x1x500 RM/35',  # aggr_line_type.name,
                                            'type_kind': 'cable',  # branch['branch'].kind,
                                            'length': 1,
                                            'U_n': aggr_line_type.U_n,
                                            'I_max_th': aggr_line_type.I_max_th,
                                            'R': aggr_line_type.R,
                                            'L': aggr_line_type.L,
                                            'C': aggr_line_type.C,
                                            'node1': '_'.join(
                                                [str(aggr_gen.__class__.__name__), 'MV', str(mv_grid_id),
                                                 str(aggr_gen.id_db), str(mvgenaggr_idx)]),
                                            'node2': '_'.join([
                                                'MVStationDing0', 'MV', str(mv_grid_id), str(mv_grid_id)]),
                                            'run_id': run_id,
                                        }

                        elif aggr_node == 'load':
                            for type in aggr['load']:
                                mvloads_idx += 1
                                mv_loads_dict[mvloads_idx] = {
                                    'id_db': '_'.join(
                                        ['AggregatedLoad', 'MV', str(mv_grid_id), str(mvloads_idx)]),
                                    'MV_grid_id_db': mv_grid_id_db,
                                    'geom': geom,
                                    # from_shape(Point(mv_district.mv_grid.station().geo_data), srid=srid),
                                    'consumption_{}'.format(type): aggr['load'][type]['nominal'],
                                    'is_aggregated': True,
                                    'run_id': run_id,
                                }

                                lines_idx += 1
                                aggr_lines += 1
                                lines_dict[lines_idx] = {
                                    # ToDo: Rename edge_name
                                    'edge_name': '_'.join(
                                        [str(mv_grid_id), 'aggr', str(node.lv_load_area.id_db), str(aggr_lines)]),
                                    # 'edge_name': '_'.join(
                                    #    ['line_aggr_load', str(node.lv_load_area), 'vlevel', str(v_level),
                                    #     'subtype', str(subtype)]),  # }'.format(v_level=v_level, subtype=subtype),
                                    'grid_id_db': mv_grid_id_db,
                                    # ToDo: read type_name from aggr_line_type
                                    'type_name': 'NA2XS2Y 3x1x500 RM/35',  # aggr_line_type.name,
                                    'type_kind': 'cable',  # branch['branch'].kind,
                                    # 'type': aggr_line_type,
                                    'length': 1e-3,  # in km
                                    'U_n': aggr_line_type.U_n,
                                    'I_max_th': aggr_line_type.I_max_th,
                                    'R': aggr_line_type.R,
                                    'L': aggr_line_type.L,
                                    'C': aggr_line_type.C,
                                    'node1': '_'.join(
                                        ['AggregatedLoad', 'MV', str(mv_grid_id), str(mvloads_idx)]),
                                    'node2': '_'.join([
                                        'MVStationDing0', 'MV', str(mv_grid_id), str(mv_grid_id)]),
                                    'run_id': run_id,
                                }

                    # areacenter_dict[areacenter_idx] = {
                    #    'id_db': '_'.join([str(node.__class__.__name__), 'MV', str(mv_grid_id), str(node.id_db)]),#node.id_db,
                    #    'MV_grid_id':node.grid,
                    #    'geom':node.geo_data,
                    #    'lv_load_area': node.lv_load_area,
                    #    'run_id': run_id,#

                    # }

                # DisconnectingPoints
                elif isinstance(node, CircuitBreakerDing0):
                    mvcb_idx += 1
                    mvcb_dict[mvcb_idx] = {
                        'id_db': '_'.join([str(node.__class__.__name__), 'MV', str(mv_grid_id), str(node.id_db)]),
                        'MV_grid_id': mv_grid_id,
                        'MV_grid_id_db': mv_grid_id_db,
                        'geom': geom,
                        'status': node.status,
                        'run_id': run_id,
                    }
                else:
                    type = 'Unknown'

            # MVedges
            for branch in mv_district.mv_grid.graph_edges():
                # geom = wkt_dumps(node.geo_data)
                geom = from_shape(LineString([branch['adj_nodes'][0].geo_data, branch['adj_nodes'][1].geo_data]),
                                  srid=srid)
                if not any([isinstance(branch['adj_nodes'][0], LVLoadAreaCentreDing0),
                            isinstance(branch['adj_nodes'][1], LVLoadAreaCentreDing0)]):
                    lines_idx += 1
                    lines_dict[lines_idx] = {
                        'edge_name': branch['branch'].id_db,
                        'grid_id_db': mv_grid_id_db,
                        'type_name': branch['branch'].type['name'],
                        'type_kind': branch['branch'].kind,
                        'length': branch['branch'].length / 1e3,
                        'U_n': branch['branch'].type['U_n'],
                        'I_max_th': branch['branch'].type['I_max_th'],
                        'R': branch['branch'].type['R'],
                        'L': branch['branch'].type['L'],
                        'C': branch['branch'].type['C'],
                        'node1': '_'.join([str(branch['adj_nodes'][0].__class__.__name__), 'MV', str(mv_grid_id),
                                           str(branch['adj_nodes'][0].id_db)]),
                        'node2': '_'.join([str(branch['adj_nodes'][1].__class__.__name__), 'MV', str(mv_grid_id),
                                           str(branch['adj_nodes'][1].id_db)]),
                        'run_id': run_id,
                    }

        if lv_info:
            for LA in mv_district.lv_load_areas():
                for lv_district in LA.lv_grid_districts():
                    if not lv_district.lv_grid.grid_district.lv_load_area.is_aggregated:

                        # ding0_grid.grid_district._lv_load_areas._lv_grid_districts    _.lv_grid
                        # LV-grid
                        # ToDo: geom <- Polygon
                        lvgrid_idx += 1
                        lv_grid_dict[lvgrid_idx] = {
                            'LV_grid_id': lv_district.lv_grid.id_db,
                            'id_db': '_'.join(
                                [str(lv_district.lv_grid.__class__.__name__), 'LV', str(lv_district.lv_grid.id_db),
                                 str(lv_district.lv_grid.id_db)]),
                            'geom': wkt_dumps(lv_district.geo_data),
                            'population': lv_district.population,
                            'voltage_nom': lv_district.lv_grid.v_level / 1e3,
                            'run_id': run_id
                        }

                        lv_grid_id = lv_district.lv_grid.id_db
                        lv_grid_id_db = '_'.join(
                            [str(lv_district.lv_grid.__class__.__name__), 'LV', str(lv_district.lv_grid.id_db),
                             str(lv_district.lv_grid.id_db)])

                        # geom = from_shape(Point(lv_district.lv_grid.station().geo_data), srid=srid)
                        # geom = wkt_dumps(lv_district.geo_data)# lv_grid.station() #ding0_lv_grid.grid_district.geo_data
                        for node in lv_district.lv_grid.graph_nodes_sorted():
                            # geom = wkt_dumps(node.geo_data)

                            # LVGenerator
                            if isinstance(node, GeneratorDing0):
                                if node.subtype == None:
                                    subtype = 'other'
                                else:
                                    subtype = node.subtype
                                type = node.type
                                lvgen_idx += 1
                                lv_gen_dict[lvgen_idx] = {
                                    'id_db': '_'.join(
                                        [str(node.__class__.__name__), 'LV', str(lv_grid_id), str(node.id_db)]),
                                    'LV_grid_id_db': lv_grid_id_db,
                                    'geom': wkt_dumps(node.geo_data),
                                    'type': type,
                                    'subtype': subtype,
                                    'v_level': node.v_level,
                                    'nominal_capacity': node.capacity,
                                    'run_id': run_id,
                                }

                            # LVcd
                            elif isinstance(node, LVCableDistributorDing0):
                                lvcd_idx += 1
                                lv_cd_dict[lvcd_idx] = {
                                    'id_db': '_'.join(
                                        [str(node.__class__.__name__), 'LV', str(lv_grid_id), str(node.id_db)]),
                                    'LV_grid_id_db': lv_grid_id_db,
                                    'geom': None,
                                    # wkt_dumps(lv_district.geo_data),#wkt_dumps(node.geo_data), Todo: why no geo_data?
                                    'run_id': run_id,
                                }

                            # LVload
                            elif isinstance(node, LVLoadDing0):
                                consumption_dict = {}
                                for k in ['residential', 'retail', 'agricultural', 'industrial']:
                                    if k in node.consumption.keys():
                                        consumption_dict[k] = node.consumption[k]
                                    else:
                                        consumption_dict[k] = None
                                lvloads_idx += 1
                                lv_loads_dict[lvloads_idx] = {
                                    'id_db': '_'.join(
                                        [str(node.__class__.__name__), 'LV', str(lv_grid_id), str(node.id_db)]),
                                    'LV_grid_id_db': lv_grid_id_db,
                                    'geom': None,#wkt_dumps(lv_district.geo_data),#wkt_dumps(node.geo_data), Todo: why no geo_data?
                                    # 'consumption': json.dumps(node.consumption),
                                    'consumption_residential': consumption_dict['residential'],
                                    'consumption_retail': consumption_dict['retail'],
                                    'consumption_agricultural': consumption_dict['agricultural'],
                                    'consumption_industrial': consumption_dict['industrial'],
                                    'run_id': run_id,
                                }
                                del consumption_dict

                            else:
                                type = 'Unknown'

                        # LVedges
                        for branch in lv_district.lv_grid.graph_edges():
    #                        geom = from_shape(
    #                            LineString([branch['adj_nodes'][0].geo_data, branch['adj_nodes'][1].geo_data]), srid=srid)
                            if not any([isinstance(branch['adj_nodes'][0], LVLoadAreaCentreDing0),
                                        isinstance(branch['adj_nodes'][1], LVLoadAreaCentreDing0)]):
                                lines_idx += 1
                                lines_dict[lines_idx] = {
                                    'edge_name': branch['branch'].id_db,
                                    'grid_id_db': lv_grid_id_db,
                                    'type_name': branch['branch'].type.to_frame().columns[0],
                                    'type_kind': branch['branch'].kind,
                                    'length': branch['branch'].length / 1e3,  # length in km
                                    'U_n': branch['branch'].type['U_n'] / 1e3,  # U_n in kV
                                    'I_max_th': branch['branch'].type['I_max_th'],
                                    'R': branch['branch'].type['R'],
                                    'L': branch['branch'].type['L'],
                                    'C': branch['branch'].type['C'],
                                    'node1': '_'.join(
                                        [str(branch['adj_nodes'][0].__class__.__name__), 'LV', str(lv_grid_id),
                                         str(branch['adj_nodes'][0].id_db)])
                                    if not isinstance(branch['adj_nodes'][0], LVStationDing0) else '_'.join(
                                        [str(branch['adj_nodes'][0].__class__.__name__), 'MV', str(mv_grid_id),
                                         str(branch['adj_nodes'][0].id_db)]),
                                    'node2': '_'.join(
                                        [str(branch['adj_nodes'][1].__class__.__name__), 'LV', str(lv_grid_id),
                                         str(branch['adj_nodes'][1].id_db)])
                                    if not isinstance(branch['adj_nodes'][1], LVStationDing0) else '_'.join(
                                        [str(branch['adj_nodes'][1].__class__.__name__), 'MV', str(mv_grid_id),
                                         str(branch['adj_nodes'][1].id_db)]),
                                    'run_id': run_id,
                                }

    lv_grid       = pd.DataFrame.from_dict(lv_grid_dict, orient='index')
    lv_gen        = pd.DataFrame.from_dict(lv_gen_dict, orient='index')
    lv_cd         = pd.DataFrame.from_dict(lv_cd_dict, orient='index')
    mvlv_stations = pd.DataFrame.from_dict(mvlv_stations_dict, orient='index')
    mvlv_trafos   = pd.DataFrame.from_dict(mvlv_trafos_dict, orient='index')
    lv_loads      = pd.DataFrame.from_dict(lv_loads_dict, orient='index')
    mv_grid       = pd.DataFrame.from_dict(mv_grid_dict, orient='index')
    mv_gen        = pd.DataFrame.from_dict(mv_gen_dict, orient='index')
    # mv_cb         = pd.DataFrame.from_dict(mvcb_dict, orient='index')
    mv_cd         = pd.DataFrame.from_dict(mv_cd_dict, orient='index')
    hvmv_stations = pd.DataFrame.from_dict(hvmv_stations_dict, orient='index')
    # mv_areacenter= pd.DataFrame.from_dict(areacenter_dict, orient='index')
    hvmv_trafos   = pd.DataFrame.from_dict(hvmv_trafos_dict, orient='index')
    mv_loads      = pd.DataFrame.from_dict(mv_loads_dict, orient='index')
    lines         = pd.DataFrame.from_dict(lines_dict, orient='index')
    mvlv_mapping  = pd.DataFrame.from_dict(mvlv_mapping_dict, orient='index')

    lines = lines[sorted(lines.columns.tolist())]

    return run_id, lv_grid, lv_gen, lv_cd, mvlv_stations, mvlv_trafos, lv_loads, mv_grid, mv_gen, mv_cd, \
           hvmv_stations, hvmv_trafos, mv_loads, lines, mvlv_mapping
def export_network ( nw , mode = '' ) : nw . control_circuit_breakers ( mode = 'close' ) srid = str ( int ( nw . config [ 'geo' ] [ 'srid' ] ) ) lv_info = True mv_info = True if mode == 'LV' : mv_info = False if mode == 'MV' : lv_info = False run_id = nw . metadata [ 'run_id' ] lvgrid_idx = 0 lv_grid_dict = { } lvloads_idx = 0 lv_loads_dict = { } mvgrid_idx = 0 mv_grid_dict = { } mvloads_idx = 0 mv_loads_dict = { } mvgen_idx = 0 mv_gen_dict = { } mvcb_idx = 0 mvcb_dict = { } mvcd_idx = 0 mv_cd_dict = { } mvstations_idx = 0 hvmv_stations_dict = { } mvtrafos_idx = 0 hvmv_trafos_dict = { } lvgen_idx = 0 lv_gen_dict = { } lvcd_idx = 0 lv_cd_dict = { } lvstations_idx = 0 mvlv_stations_dict = { } lvtrafos_idx = 0 mvlv_trafos_dict = { } areacenter_idx = 0 areacenter_dict = { } lines_idx = 0 lines_dict = { } LVMVmapping_idx = 0 mvlv_mapping_dict = { } def aggregate_generators ( gen , aggr ) : if gen . v_level not in aggr [ 'generation' ] : aggr [ 'generation' ] [ gen . v_level ] = { } if gen . type not in aggr [ 'generation' ] [ gen . v_level ] : aggr [ 'generation' ] [ gen . v_level ] [ gen . type ] = { } if gen . subtype not in aggr [ 'generation' ] [ gen . v_level ] [ gen . type ] : aggr [ 'generation' ] [ gen . v_level ] [ gen . type ] . update ( { gen . subtype : { 'ids' : [ gen . id_db ] , 'capacity' : gen . capacity } } ) else : aggr [ 'generation' ] [ gen . v_level ] [ gen . type ] [ gen . subtype ] [ 'ids' ] . append ( gen . id_db ) aggr [ 'generation' ] [ gen . v_level ] [ gen . type ] [ gen . subtype ] [ 'capacity' ] += gen . capacity return aggr def aggregate_loads ( la_center , aggr ) : for s in [ 'retail' , 'industrial' , 'agricultural' , 'residential' ] : if s not in aggr [ 'load' ] : aggr [ 'load' ] [ s ] = { } for t in [ 'nominal' , 'peak' ] : if t not in aggr [ 'load' ] [ s ] : aggr [ 'load' ] [ s ] [ t ] = 0 aggr [ 'load' ] [ 'retail' ] [ 'nominal' ] += sum ( [ _ . sector_consumption_retail for _ in la_center . lv_load_area . _lv_grid_districts ] ) aggr [ 'load' ] [ 'industrial' ] [ 'nominal' ] += sum ( [ _ . sector_consumption_industrial for _ in la_center . lv_load_area . _lv_grid_districts ] ) aggr [ 'load' ] [ 'agricultural' ] [ 'nominal' ] += sum ( [ _ . sector_consumption_agricultural for _ in la_center . lv_load_area . _lv_grid_districts ] ) aggr [ 'load' ] [ 'residential' ] [ 'nominal' ] += sum ( [ _ . sector_consumption_residential for _ in la_center . lv_load_area . _lv_grid_districts ] ) aggr [ 'load' ] [ 'retail' ] [ 'peak' ] += sum ( [ _ . peak_load_retail for _ in la_center . lv_load_area . _lv_grid_districts ] ) aggr [ 'load' ] [ 'industrial' ] [ 'peak' ] += sum ( [ _ . peak_load_industrial for _ in la_center . lv_load_area . _lv_grid_districts ] ) aggr [ 'load' ] [ 'agricultural' ] [ 'peak' ] += sum ( [ _ . peak_load_agricultural for _ in la_center . lv_load_area . _lv_grid_districts ] ) aggr [ 'load' ] [ 'residential' ] [ 'peak' ] += sum ( [ _ . peak_load_residential for _ in la_center . lv_load_area . _lv_grid_districts ] ) return aggr for mv_district in nw . mv_grid_districts ( ) : mv_grid_id = mv_district . mv_grid . id_db mv_grid_id_db = '_' . join ( [ str ( mv_district . mv_grid . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( mv_district . mv_grid . id_db ) ] ) if mv_info : lv_grid_id = 0 mvgrid_idx += 1 mv_grid_dict [ mvgrid_idx ] = { 'MV_grid_id' : mv_district . mv_grid . id_db , 'id_db' : '_' . join ( [ str ( mv_district . mv_grid . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( mv_district . mv_grid . id_db ) ] ) , 'geom' : wkt_dumps ( mv_district . geo_data ) , 'population' : sum ( [ _ . zensus_sum for _ in mv_district . _lv_load_areas if not np . isnan ( _ . zensus_sum ) ] ) , 'voltage_nom' : mv_district . mv_grid . v_level , 'run_id' : run_id } for node in mv_district . mv_grid . graph_nodes_sorted ( ) : geom = wkt_dumps ( node . geo_data ) db_id = node . id_db if isinstance ( node , LVStationDing0 ) : if not node . lv_load_area . is_aggregated : lvstations_idx += 1 mvlv_stations_dict [ lvstations_idx ] = { 'id_db' : '_' . join ( [ str ( node . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( node . id_db ) ] ) , 'LV_grid_id_db' : '_' . join ( [ 'LVGridDing0' , 'LV' , str ( node . id_db ) , str ( node . id_db ) ] ) , 'geom' : geom , 'run_id' : run_id , } LVMVmapping_idx += 1 mvlv_mapping_dict [ LVMVmapping_idx ] = { 'MV_grid_id' : mv_grid_id , 'MV_grid_id_db' : mv_grid_id_db , 'LV_grid_id' : node . id_db , 'LV_grid_id_db' : '_' . join ( [ 'LVGridDing0' , 'LV' , str ( node . id_db ) , str ( node . id_db ) ] ) , 'run_id' : run_id , } for t in node . transformers ( ) : lvtrafos_idx += 1 mvlv_trafos_dict [ lvtrafos_idx ] = { 'id_db' : '_' . join ( [ str ( t . __class__ . __name__ ) , 'LV' , str ( mv_grid_id ) , str ( node . id_db ) ] ) , 'geom' : geom , 'LV_grid_id_db' : '_' . join ( [ 'LVGridDing0' , 'LV' , str ( node . id_db ) , str ( node . id_db ) ] ) , 'voltage_op' : t . v_level , 'S_nom' : t . s_max_a , 'X' : t . x , 'R' : t . r , 'run_id' : run_id , } elif isinstance ( node , MVStationDing0 ) : mvstations_idx += 1 hvmv_stations_dict [ mvstations_idx ] = { 'id_db' : '_' . join ( [ str ( node . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( node . id_db ) ] ) , 'MV_grid_id_db' : mv_grid_id_db , 'geom' : geom , 'run_id' : run_id , } for t in node . transformers ( ) : mvtrafos_idx += 1 hvmv_trafos_dict [ mvtrafos_idx ] = { 'id_db' : '_' . join ( [ str ( t . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( node . id_db ) ] ) , 'geom' : geom , 'MV_grid_id_db' : mv_grid_id_db , 'voltage_op' : t . v_level , 'S_nom' : t . s_max_a , 'X' : t . x , 'R' : t . r , 'run_id' : run_id , } elif isinstance ( node , GeneratorDing0 ) : if node . subtype == None : subtype = 'other' else : subtype = node . subtype type = node . type mvgen_idx += 1 mv_gen_dict [ mvgen_idx ] = { 'id_db' : '_' . join ( [ str ( node . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( node . id_db ) ] ) , 'MV_grid_id_db' : mv_grid_id_db , 'geom' : geom , 'type' : type , 'subtype' : subtype , 'v_level' : node . v_level , 'nominal_capacity' : node . capacity , 'run_id' : run_id , 'is_aggregated' : False , } elif isinstance ( node , MVCableDistributorDing0 ) : mvcd_idx += 1 mv_cd_dict [ mvcd_idx ] = { 'id_db' : '_' . join ( [ str ( node . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( node . id_db ) ] ) , 'MV_grid_id_db' : mv_grid_id_db , 'geom' : geom , 'run_id' : run_id , } elif isinstance ( node , LVLoadAreaCentreDing0 ) : areacenter_idx += 1 aggr_lines = 0 aggr = { 'generation' : { } , 'load' : { } , 'aggregates' : [ ] } for lvgd in node . lv_load_area . _lv_grid_districts : for aggr_gen in lvgd . lv_grid . generators ( ) : aggr = aggregate_generators ( aggr_gen , aggr ) if aggr_gen . subtype == None : subtype = 'other' else : subtype = aggr_gen . subtype type = aggr_gen . type aggr = aggregate_loads ( node , aggr ) aggr [ 'aggregates' ] = { 'population' : node . lv_load_area . zensus_sum , 'geom' : node . lv_load_area . geo_area } aggr_line_type = nw . _static_data [ 'MV_cables' ] . iloc [ nw . _static_data [ 'MV_cables' ] [ 'I_max_th' ] . idxmax ( ) ] geom = wkt_dumps ( node . lv_load_area . geo_area ) for aggr_node in aggr : if aggr_node == 'generation' : mvgenaggr_idx = 0 for v_level in aggr [ 'generation' ] : for type in aggr [ 'generation' ] [ v_level ] : for subtype in aggr [ 'generation' ] [ v_level ] [ type ] : mvgen_idx += 1 mvgenaggr_idx += 1 mv_gen_dict [ mvgen_idx ] = { 'id_db' : '_' . join ( [ str ( aggr_gen . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( aggr_gen . id_db ) , str ( mvgenaggr_idx ) ] ) , 'MV_grid_id_db' : mv_grid_id_db , 'geom' : geom , 'type' : type , 'subtype' : subtype , 'v_level' : v_level , 'nominal_capacity' : aggr [ 'generation' ] [ v_level ] [ type ] [ subtype ] [ 'capacity' ] , 'is_aggregated' : True , 'run_id' : run_id , } lines_idx += 1 aggr_lines += 1 lines_dict [ lines_idx ] = { 'edge_name' : '_' . join ( [ str ( mv_grid_id ) , 'aggr' , str ( node . lv_load_area . id_db ) , str ( aggr_lines ) ] ) , 'grid_id_db' : mv_grid_id_db , 'type_name' : 'NA2XS2Y 3x1x500 RM/35' , 'type_kind' : 'cable' , 'length' : 1 , 'U_n' : aggr_line_type . U_n , 'I_max_th' : aggr_line_type . I_max_th , 'R' : aggr_line_type . R , 'L' : aggr_line_type . L , 'C' : aggr_line_type . C , 'node1' : '_' . join ( [ str ( aggr_gen . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( aggr_gen . id_db ) , str ( mvgenaggr_idx ) ] ) , 'node2' : '_' . join ( [ 'MVStationDing0' , 'MV' , str ( mv_grid_id ) , str ( mv_grid_id ) ] ) , 'run_id' : run_id , } elif aggr_node == 'load' : for type in aggr [ 'load' ] : mvloads_idx += 1 mv_loads_dict [ mvloads_idx ] = { 'id_db' : '_' . join ( [ 'AggregatedLoad' , 'MV' , str ( mv_grid_id ) , str ( mvloads_idx ) ] ) , 'MV_grid_id_db' : mv_grid_id_db , 'geom' : geom , 'consumption_{}' . format ( type ) : aggr [ 'load' ] [ type ] [ 'nominal' ] , 'is_aggregated' : True , 'run_id' : run_id , } lines_idx += 1 aggr_lines += 1 lines_dict [ lines_idx ] = { 'edge_name' : '_' . join ( [ str ( mv_grid_id ) , 'aggr' , str ( node . lv_load_area . id_db ) , str ( aggr_lines ) ] ) , 'grid_id_db' : mv_grid_id_db , 'type_name' : 'NA2XS2Y 3x1x500 RM/35' , 'type_kind' : 'cable' , 'length' : 1e-3 , 'U_n' : aggr_line_type . U_n , 'I_max_th' : aggr_line_type . I_max_th , 'R' : aggr_line_type . R , 'L' : aggr_line_type . L , 'C' : aggr_line_type . C , 'node1' : '_' . join ( [ 'AggregatedLoad' , 'MV' , str ( mv_grid_id ) , str ( mvloads_idx ) ] ) , 'node2' : '_' . join ( [ 'MVStationDing0' , 'MV' , str ( mv_grid_id ) , str ( mv_grid_id ) ] ) , 'run_id' : run_id , } elif isinstance ( node , CircuitBreakerDing0 ) : mvcb_idx += 1 mvcb_dict [ mvcb_idx ] = { 'id_db' : '_' . join ( [ str ( node . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( node . id_db ) ] ) , 'MV_grid_id' : mv_grid_id , 'MV_grid_id_db' : mv_grid_id_db , 'geom' : geom , 'status' : node . status , 'run_id' : run_id , } else : type = 'Unknown' for branch in mv_district . mv_grid . graph_edges ( ) : geom = from_shape ( LineString ( [ branch [ 'adj_nodes' ] [ 0 ] . geo_data , branch [ 'adj_nodes' ] [ 1 ] . geo_data ] ) , srid = srid ) if not any ( [ isinstance ( branch [ 'adj_nodes' ] [ 0 ] , LVLoadAreaCentreDing0 ) , isinstance ( branch [ 'adj_nodes' ] [ 1 ] , LVLoadAreaCentreDing0 ) ] ) : lines_idx += 1 lines_dict [ lines_idx ] = { 'edge_name' : branch [ 'branch' ] . id_db , 'grid_id_db' : mv_grid_id_db , 'type_name' : branch [ 'branch' ] . type [ 'name' ] , 'type_kind' : branch [ 'branch' ] . kind , 'length' : branch [ 'branch' ] . length / 1e3 , 'U_n' : branch [ 'branch' ] . type [ 'U_n' ] , 'I_max_th' : branch [ 'branch' ] . type [ 'I_max_th' ] , 'R' : branch [ 'branch' ] . type [ 'R' ] , 'L' : branch [ 'branch' ] . type [ 'L' ] , 'C' : branch [ 'branch' ] . type [ 'C' ] , 'node1' : '_' . join ( [ str ( branch [ 'adj_nodes' ] [ 0 ] . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( branch [ 'adj_nodes' ] [ 0 ] . id_db ) ] ) , 'node2' : '_' . join ( [ str ( branch [ 'adj_nodes' ] [ 1 ] . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( branch [ 'adj_nodes' ] [ 1 ] . id_db ) ] ) , 'run_id' : run_id , } if lv_info : for LA in mv_district . lv_load_areas ( ) : for lv_district in LA . lv_grid_districts ( ) : if not lv_district . lv_grid . grid_district . lv_load_area . is_aggregated : lvgrid_idx += 1 lv_grid_dict [ lvgrid_idx ] = { 'LV_grid_id' : lv_district . lv_grid . id_db , 'id_db' : '_' . join ( [ str ( lv_district . lv_grid . __class__ . __name__ ) , 'LV' , str ( lv_district . lv_grid . id_db ) , str ( lv_district . lv_grid . id_db ) ] ) , 'geom' : wkt_dumps ( lv_district . geo_data ) , 'population' : lv_district . population , 'voltage_nom' : lv_district . lv_grid . v_level / 1e3 , 'run_id' : run_id } lv_grid_id = lv_district . lv_grid . id_db lv_grid_id_db = '_' . join ( [ str ( lv_district . lv_grid . __class__ . __name__ ) , 'LV' , str ( lv_district . lv_grid . id_db ) , str ( lv_district . lv_grid . id_db ) ] ) for node in lv_district . lv_grid . graph_nodes_sorted ( ) : if isinstance ( node , GeneratorDing0 ) : if node . subtype == None : subtype = 'other' else : subtype = node . subtype type = node . type lvgen_idx += 1 lv_gen_dict [ lvgen_idx ] = { 'id_db' : '_' . join ( [ str ( node . __class__ . __name__ ) , 'LV' , str ( lv_grid_id ) , str ( node . id_db ) ] ) , 'LV_grid_id_db' : lv_grid_id_db , 'geom' : wkt_dumps ( node . geo_data ) , 'type' : type , 'subtype' : subtype , 'v_level' : node . v_level , 'nominal_capacity' : node . capacity , 'run_id' : run_id , } elif isinstance ( node , LVCableDistributorDing0 ) : lvcd_idx += 1 lv_cd_dict [ lvcd_idx ] = { 'id_db' : '_' . join ( [ str ( node . __class__ . __name__ ) , 'LV' , str ( lv_grid_id ) , str ( node . id_db ) ] ) , 'LV_grid_id_db' : lv_grid_id_db , 'geom' : None , 'run_id' : run_id , } elif isinstance ( node , LVLoadDing0 ) : consumption_dict = { } for k in [ 'residential' , 'retail' , 'agricultural' , 'industrial' ] : if k in node . consumption . keys ( ) : consumption_dict [ k ] = node . consumption [ k ] else : consumption_dict [ k ] = None lvloads_idx += 1 lv_loads_dict [ lvloads_idx ] = { 'id_db' : '_' . join ( [ str ( node . __class__ . __name__ ) , 'LV' , str ( lv_grid_id ) , str ( node . id_db ) ] ) , 'LV_grid_id_db' : lv_grid_id_db , 'geom' : None , 'consumption_residential' : consumption_dict [ 'residential' ] , 'consumption_retail' : consumption_dict [ 'retail' ] , 'consumption_agricultural' : consumption_dict [ 'agricultural' ] , 'consumption_industrial' : consumption_dict [ 'industrial' ] , 'run_id' : run_id , } del consumption_dict else : type = 'Unknown' for branch in lv_district . lv_grid . graph_edges ( ) : if not any ( [ isinstance ( branch [ 'adj_nodes' ] [ 0 ] , LVLoadAreaCentreDing0 ) , isinstance ( branch [ 'adj_nodes' ] [ 1 ] , LVLoadAreaCentreDing0 ) ] ) : lines_idx += 1 lines_dict [ lines_idx ] = { 'edge_name' : branch [ 'branch' ] . id_db , 'grid_id_db' : lv_grid_id_db , 'type_name' : branch [ 'branch' ] . type . to_frame ( ) . columns [ 0 ] , 'type_kind' : branch [ 'branch' ] . kind , 'length' : branch [ 'branch' ] . length / 1e3 , 'U_n' : branch [ 'branch' ] . type [ 'U_n' ] / 1e3 , 'I_max_th' : branch [ 'branch' ] . type [ 'I_max_th' ] , 'R' : branch [ 'branch' ] . type [ 'R' ] , 'L' : branch [ 'branch' ] . type [ 'L' ] , 'C' : branch [ 'branch' ] . type [ 'C' ] , 'node1' : '_' . join ( [ str ( branch [ 'adj_nodes' ] [ 0 ] . __class__ . __name__ ) , 'LV' , str ( lv_grid_id ) , str ( branch [ 'adj_nodes' ] [ 0 ] . id_db ) ] ) if not isinstance ( branch [ 'adj_nodes' ] [ 0 ] , LVStationDing0 ) else '_' . join ( [ str ( branch [ 'adj_nodes' ] [ 0 ] . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( branch [ 'adj_nodes' ] [ 0 ] . id_db ) ] ) , 'node2' : '_' . join ( [ str ( branch [ 'adj_nodes' ] [ 1 ] . __class__ . __name__ ) , 'LV' , str ( lv_grid_id ) , str ( branch [ 'adj_nodes' ] [ 1 ] . id_db ) ] ) if not isinstance ( branch [ 'adj_nodes' ] [ 1 ] , LVStationDing0 ) else '_' . join ( [ str ( branch [ 'adj_nodes' ] [ 1 ] . __class__ . __name__ ) , 'MV' , str ( mv_grid_id ) , str ( branch [ 'adj_nodes' ] [ 1 ] . id_db ) ] ) , 'run_id' : run_id , } lv_grid = pd . DataFrame . from_dict ( lv_grid_dict , orient = 'index' ) lv_gen = pd . DataFrame . from_dict ( lv_gen_dict , orient = 'index' ) lv_cd = pd . DataFrame . from_dict ( lv_cd_dict , orient = 'index' ) mvlv_stations = pd . DataFrame . from_dict ( mvlv_stations_dict , orient = 'index' ) mvlv_trafos = pd . DataFrame . from_dict ( mvlv_trafos_dict , orient = 'index' ) lv_loads = pd . DataFrame . from_dict ( lv_loads_dict , orient = 'index' ) mv_grid = pd . DataFrame . from_dict ( mv_grid_dict , orient = 'index' ) mv_gen = pd . DataFrame . from_dict ( mv_gen_dict , orient = 'index' ) mv_cd = pd . DataFrame . from_dict ( mv_cd_dict , orient = 'index' ) hvmv_stations = pd . DataFrame . from_dict ( hvmv_stations_dict , orient = 'index' ) hvmv_trafos = pd . DataFrame . from_dict ( hvmv_trafos_dict , orient = 'index' ) mv_loads = pd . DataFrame . from_dict ( mv_loads_dict , orient = 'index' ) lines = pd . DataFrame . from_dict ( lines_dict , orient = 'index' ) mvlv_mapping = pd . DataFrame . from_dict ( mvlv_mapping_dict , orient = 'index' ) lines = lines [ sorted ( lines . columns . tolist ( ) ) ] return run_id , lv_grid , lv_gen , lv_cd , mvlv_stations , mvlv_trafos , lv_loads , mv_grid , mv_gen , mv_cd , hvmv_stations , hvmv_trafos , mv_loads , lines , mvlv_mapping
Export all nodes and lines of the network nw as DataFrames

    Parameters
    ----------
    nw: :any:`list` of NetworkDing0
        The MV grid(s) to be studied
    mode: str
        If 'MV' export only medium voltage nodes and lines
        If 'LV' export only low voltage nodes and lines
        else, exports MV and LV nodes and lines

    Returns
    -------
    pandas.DataFrame
        nodes_df : Dataframe containing nodes and its attributes
    pandas.DataFrame
        lines_df : Dataframe containing lines and its attributes