def test_get_simbench_net(sb_codes=None, n=8, scenarios=None, input_path=None): """ Test nets exctracted from csv (shortened) folder. 'shortened' and 'test' must be set properly in extract_simbench_grids_from_csv.py If sb_codes is None, randomn simbench codes are tested in the number of n. If in input_path is None, no input_path will be given to get_simbench_net() """ shortened = input_path is not None and "shortened" in input_path scenarios = scenarios if scenarios is not None else [0, 1, 2] if not sb_codes: sb_codes = [] for scenario in scenarios: sb_codes += sb.collect_all_simbench_codes(scenario=scenario, shortened=shortened) first = 2 # always test the first 2 (complete_data and complete_grid) np.random.seed(int(time.time())) sb_codes = [ sb_codes[i] for i in np.append( np.random.randint(first, len(sb_codes) - first, n), range(first)) ] else: sb_codes = sb.ensure_iterability(sb_codes) for sb_code_info in sb_codes: sb_code, sb_code_params = sb.get_simbench_code_and_parameters( sb_code_info) logger.info("Get SimBench net '%s'" % sb_code) net = sb.get_simbench_net(sb_code, input_path=input_path) logger.info("Now test validity...") _test_net_validity(net, sb_code_params, shortened, input_path=input_path)
def _get_connected_buses_via_bus_bus_switch(net, buses): """ Returns a set of buses which are connected to 'buses' via bus-bus switches. """ buses = set(ensure_iterability(buses)) add_buses = [1] # set anything to add_buses to start the while loop while(len(add_buses)): add_buses = pp.get_connected_buses(net, buses, consider=("s")) buses |= add_buses return buses
def test_ensure_iterability(): assert len(sb.ensure_iterability(2)) assert len(sb.ensure_iterability("df")) == 1 assert len(sb.ensure_iterability(2, 4)) == 4 assert len(sb.ensure_iterability("df", 5)) == 5 a = [2, 3.1, "df"] assert sb.ensure_iterability(a) == a a = np.array(a) assert all(sb.ensure_iterability(a) == a) assert all(sb.ensure_iterability(a, 3) == a) try: sb.ensure_iterability(a, 5) bool_ = False except ValueError: bool_ = True assert bool_
def _extract_csv_table_by_subnet(csv_table, tablename, relevant_subnets, bus_bus_switches={}): """ Extracts csv table by subnet names. INPUT: **csv_table** (DataFrame) **tablename** (str) **relevant_subnets** (tuple) - first item is hv_subnet (str), second lv_subnets (list of strings) OPTIONAL: **bus_bus_switches** (set, {}) - indices of bus-bus-switches in csv DataFrame. Only used if tablename == "Switch". """ hv_subnets = ensure_iterability(relevant_subnets[0]) lv_subnets = relevant_subnets[1] if "complete_data" in hv_subnets or \ isinstance(csv_table, pd.DataFrame) and not csv_table.shape[0]: return csv_table # no extraction needed csv_table = deepcopy(csv_table) if isinstance(csv_table, pd.DataFrame) and "subnet" in csv_table.columns: logger.debug("Start extracting %s" % tablename) subnet_split = csv_table.subnet.str.split("_", expand=True) # --- hv_elms: all elements starting with hv_subnet hv_elms = set(subnet_split.index[subnet_split[0].isin(hv_subnets)]) if tablename in ["Node", "Coordinates", "Measurement", "Switch", "Substation"]: # including elements that subnet data is hv_subnet between 1st "_" and 2nd "_" or end hv_elms_to_add = set(subnet_split.index[subnet_split[1].isin(hv_subnets)]) if tablename == "Switch": hv_elms_to_add = hv_elms_to_add & bus_bus_switches elif tablename == "Measurement": bus_measurements = set(csv_table.index[ pd.isnull(csv_table[["element1", "element2"]]).any(axis=1)]) hv_elms_to_add = hv_elms_to_add & bus_measurements hv_elms |= hv_elms_to_add # --- lv_elms: all elements starting with lv_subnet lv_elms = set(subnet_split.index[subnet_split[0].isin(lv_subnets)]) lv_hv_elms = set() hv_lv_elms = set() if 1 in subnet_split.columns: # --- lv_hv_elms if tablename in ["Node", "Coordinates", "Measurement", "Switch", "Substation"]: # all elements with a higher voltage level before 1st "_" than after the first "_" subnet_split_level = pd.DataFrame(None, index=subnet_split.index, columns=subnet_split.columns) subnet_split.loc[[0, 1]] = subnet_split.loc[[0, 1]].replace( {"EHV": 1, "HV": 3, "MV": 5, "LV": 5} ) # for col in [0, 1]: # for level_str, level_int in zip(["EHV", "HV", "MV", "LV"], [1, 3, 5, 7]): # subnet_split_level.loc[ # subnet_split[col].fillna("").str.contains(level_str), col] = level_int lv_hv_elms = set(subnet_split_level.index[ subnet_split_level[0] > subnet_split_level[1]]) else: # all elements with lv_subnet before 1st "_" # and is hv_subnet between 1st "_" and 2nd or end lv_hv_elms = set(subnet_split.index[ (subnet_split[0].isin(lv_subnets)) & (subnet_split[1].isin(hv_subnets))]) # --- hv_lv_elms: all elements with hv_subnet before 1st "_" # and is lv_subnet between 1st "_" and 2nd or end if tablename not in ["Node", "Coordinates", "Switch", "Substation"]: hv_lv_elms = set(subnet_split.index[ (subnet_split[0].isin(hv_subnets)) & (subnet_split[1].isin(lv_subnets))]) if tablename == "Measurement": hv_lv_elms -= bus_measurements # --- determine indices to drop and examine dropping drop_idx = (set(csv_table.index) - hv_elms - lv_elms) | hv_lv_elms | lv_hv_elms csv_table.drop(drop_idx, inplace=True) no_extraction = False else: no_extraction = "Profile" not in tablename and "Type" not in tablename and \ tablename != "StudyCases" if no_extraction: logger.warning("From %s no extraction can be made by 'subnet'." % tablename) return csv_table
def _test_net_validity(net, sb_code_params, shortened, input_path=None): """ This function is to test validity of a simbench net. """ # --- deduce values from sb_code_params to test extracted csv data # lv_net_extent: 0-no lv_net 1-one lv_net 2-all lv_nets lv_net_extent = int(bool(len(sb_code_params[2]))) if bool(lv_net_extent) and sb_code_params[4] == "all": lv_net_extent += 1 # net_factor: how many lower voltage grids are expected to be connected if shortened: net_factor = 8 else: if sb_code_params[1] == "HV": net_factor = 10 else: net_factor = 50 # --- test data existence # buses expected_buses = {0: 12, 1: 80, 2: net_factor*12}[lv_net_extent] if sb_code_params[1] != "EHV" \ else {0: 6, 1: 65, 2: 125}[lv_net_extent] assert net.bus.shape[0] > expected_buses # ext_grid assert bool(net.ext_grid.shape[0]) # switches if sb_code_params[6]: if int(sb_code_params[5]) > 0: if net.switch.shape[0] <= net.line.shape[0] * 2 - 2: logger.info( "There are %i switches, but %i " % (net.switch.shape[0], net.line.shape[0]) + "lines -> some lines are not surrounded by switches.") else: assert net.switch.shape[0] > net.line.shape[0] * 2 - 2 else: assert not net.switch.closed.any() assert (net.switch.et != "b").all() # all buses supplied if sb_code_params[1] != "complete_data": unsup_buses = unsupplied_buses(net, respect_switches=False) if len(unsup_buses): logger.error("There are %i unsupplied buses." % len(unsup_buses)) if len(unsup_buses) < 10: logger.error("These are: " + str(net.bus.name.loc[unsup_buses])) assert not len(unsup_buses) # lines assert net.line.shape[0] >= net.bus.shape[0]-net.trafo.shape[0]-(net.switch.et == "b").sum() - \ 2*net.trafo3w.shape[0]-net.impedance.shape[0]-net.dcline.shape[0]-net.ext_grid.shape[0] # trafos if sb_code_params[1] == "EHV": expected_trafos = {0: 0, 1: 2, 2: 8}[lv_net_extent] elif sb_code_params[1] == "HV": expected_trafos = {0: 2, 1: 4, 2: net_factor * 2}[lv_net_extent] elif sb_code_params[1] == "MV": expected_trafos = {0: 2, 1: 3, 2: net_factor * 1}[lv_net_extent] elif sb_code_params[1] == "LV": expected_trafos = {0: 1}[lv_net_extent] elif sb_code_params[1] == "complete_data": expected_trafos = 200 assert net.trafo.shape[0] >= expected_trafos # load expected_loads = {0: 10, 1: net_factor, 2: net_factor*10}[lv_net_extent] if \ sb_code_params[1] != "EHV" else {0: 3, 1: 53, 2: 113}[lv_net_extent] assert net.load.shape[0] > expected_loads # sgen if sb_code_params[1] == "LV": expected_sgen = {0: 0}[lv_net_extent] elif sb_code_params[2] == "LV": expected_sgen = {1: 50, 2: 50 + net_factor * 1}[lv_net_extent] else: expected_sgen = expected_loads assert net.sgen.shape[0] > expected_sgen # measurement if pd.Series(["HV", "MV"]).isin([sb_code_params[1], sb_code_params[2]]).any(): assert net.measurement.shape[0] > 1 # bus_geodata assert net.bus.shape[0] == net.bus_geodata.shape[0] # check_that_all_buses_connected_by_switches_have_same_geodata for bus_group in bus_groups_connected_by_switches(net): first_bus = list(bus_group)[0] assert all( np.isclose(net.bus_geodata.x.loc[bus_group], net.bus_geodata.x.loc[first_bus]) & np.isclose(net.bus_geodata.y.loc[bus_group], net.bus_geodata.y.loc[first_bus])) # --- test data content # substation for elm in ["bus", "trafo", "trafo3w", "switch"]: mentioned_substations = pd.Series( net[elm].substation.unique()).dropna() if not mentioned_substations.isin(net.substation.name.values).all(): raise AssertionError( str( list(mentioned_substations. loc[~mentioned_substations.isin(net.substation.name. values)].values)) + " from element '%s' misses in net.substation" % elm) # check subnet input_path = input_path if input_path is not None else sb.complete_data_path( sb_code_params[5]) hv_subnet, lv_subnets = sb.get_relevant_subnets(sb_code_params, input_path=input_path) allowed_elms_missing_subnet = [ "gen", "dcline", "trafo3w", "impedance", "measurement", "shunt", "storage", "ward", "xward" ] if not sb_code_params[6]: allowed_elms_missing_subnet += ["switch"] if sb_code_params[1] != "complete_data": hv_subnets = sb.ensure_iterability(hv_subnet) for elm in pp.pp_elements(): if "subnet" not in net[elm].columns or not bool(net[elm].shape[0]): assert elm in allowed_elms_missing_subnet else: # subnet is in net[elm].columns and there are one or more elements subnet_split = net[elm].subnet.str.split("_", expand=True) subnet_ok = set() subnet_ok |= set( subnet_split.index[subnet_split[0].isin(hv_subnets + lv_subnets)]) if elm in ["bus", "measurement", "switch"]: if 1 in subnet_split.columns: subnet_ok |= set(subnet_split.index[ subnet_split[1].isin(hv_subnets)]) assert len(subnet_ok) == net[elm].shape[0] # check profile existing assert not sb.profiles_are_missing(net) # --- check profiles and loadflow check_loadflow = sb_code_params[1] != "complete_data" check_loadflow &= sb_code_params[2] != "HVMVLV" if check_loadflow: try: pp.runpp(net) converged = net.converged except: sb_code = sb.get_simbench_code_from_parameters(sb_code_params) logger.error("Loadflow not converged with %s" % sb_code) converged = False assert converged