From c00d00461ca0c3aae3626294a2323854810bceb3 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 23 Apr 2024 18:47:36 +0200 Subject: [PATCH 01/21] 1st change to support pandapower geojson --- CHANGELOG.rst | 5 +++++ pyproject.toml | 2 +- simbench/converter/csv_data_manipulation.py | 10 ++++++---- simbench/converter/csv_pp_converter.py | 5 ----- simbench/converter/format_information.py | 3 ++- simbench/converter/pp_net_manipulation.py | 14 +++++++++++--- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6651259..e66f059 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,12 +1,17 @@ Change Log ============= +[1.6.0] - 2024-xx-xx +---------------------- +- [CHANGED] support pandapower geojson, released with pandapower version 3.0.0 + [1.5.3] - 2024-04-23 ---------------------- - [FIXED] Bringing together develop and master with all changes of the release process - [ADDED] generalization and test for auxiliary function :code:`to_numeric_ignored_errors()` [1.5.2] - 2024-04-09 +---------------------- - [CHANGED] readded copyright notice to setup.py and updated date - [CHANGED] added prune to MANIFEST.in to exclude doc and tutorials from wheel builds - [CHANGED] removed gitlab ci files from MANIFEST.in to keep them out of wheel builds diff --git a/pyproject.toml b/pyproject.toml index 93dcee1..200e5e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ classifiers = [ "Programming Language :: Python :: 3.12" ] dependencies = [ - "pandapower>=2.12.1" + "pandapower>=3.0.0" ] keywords = [ "benchmark grid", "power system", "network", "grid planning", "grid operation", "grid generation methodology", "comparability", "reproducibility", "electricity", "energy", "engineering", "simulation", "simbench", "time series", "future scenarios" diff --git a/simbench/converter/csv_data_manipulation.py b/simbench/converter/csv_data_manipulation.py index 148c24e..1a940be 100644 --- a/simbench/converter/csv_data_manipulation.py +++ b/simbench/converter/csv_data_manipulation.py @@ -154,10 +154,12 @@ def _add_phys_type_and_vm_va_setpoints_to_element_tables(csv_data): def _extend_coordinates_to_node_shape(csv_data): """ Extends the Coordinates table to the shape of Nodes to enable copying simply to bus_geodata. """ - bus_geodata = pd.DataFrame([], index=csv_data["Node"].index, columns=["x", "y"]) + geo = pd.Series(None, index=csv_data["Node"].index, name="geo") with_coord = ~csv_data["Node"]["coordID"].isnull() idx_in_coordID = idx_in_2nd_array(csv_data["Node"]["coordID"].loc[with_coord].values, csv_data["Coordinates"]["id"].values) - bus_geodata.loc[with_coord, ["x", "y"]] = csv_data["Coordinates"].loc[idx_in_coordID, - ["x", "y"]].values - csv_data["Coordinates"] = bus_geodata + geo.loc[with_coord] = [f'{{"type":"Point", "coordinates":[{x}, {y}]}}' for x, y in zip( + csv_data["Coordinates"].loc[idx_in_coordID, "x"].values, + csv_data["Coordinates"].loc[idx_in_coordID, "y"].values, + )] + csv_data["Node"]["geo"] = geo diff --git a/simbench/converter/csv_pp_converter.py b/simbench/converter/csv_pp_converter.py index e0c77ab..99da19f 100644 --- a/simbench/converter/csv_pp_converter.py +++ b/simbench/converter/csv_pp_converter.py @@ -233,11 +233,6 @@ def pp2csv_data(net1, export_pp_std_types=False, drop_inactive_elements=True, str(["%s" % elm for elm in check_results.keys()]) + ". Only the standard " + "type values are converted to csv.") convert_parallel_branches(net) - if net.bus.shape[0] and not net.bus_geodata.shape[0] or ( - net.bus_geodata.shape[0] != net.bus.shape[0]): - logger.info("Since there are no or incomplete bus_geodata, generic geodata are assumed.") - net.bus_geodata = net.bus_geodata.iloc[0:0] - create_generic_coordinates(net) merge_busbar_coordinates(net) move_slack_gens_to_ext_grid(net) diff --git a/simbench/converter/format_information.py b/simbench/converter/format_information.py index 3104140..a654c89 100644 --- a/simbench/converter/format_information.py +++ b/simbench/converter/format_information.py @@ -54,9 +54,10 @@ def csv_tablenames(which): def _csv_table_pp_dataframe_correspondings(type_): csv_tablenames_ = csv_tablenames(['elements', 'types', 'res_elements']) + csv_tablenames_.remove("Coordinates") # corresponding pandapower dataframe names pp_dfnames = ['ext_grid', 'line', 'load', 'shunt', 'bus', 'measurement', 'gen', 'sgen', - 'storage', 'substation', 'switch', 'trafo', 'trafo3w', 'bus_geodata', + 'storage', 'substation', 'switch', 'trafo', 'trafo3w', 'std_types|line', 'dcline', 'std_types|trafo', 'std_types|trafo3w', "res_bus"] # append table name lists by combinations of generating elements diff --git a/simbench/converter/pp_net_manipulation.py b/simbench/converter/pp_net_manipulation.py index 31a4ff9..ab32d63 100644 --- a/simbench/converter/pp_net_manipulation.py +++ b/simbench/converter/pp_net_manipulation.py @@ -181,8 +181,19 @@ def convert_parallel_branches(net, multiple_entries=True, elm_to_convert=["line" net["switch"] = net["switch"].drop(switch_dupl) +def convert_geojson_to_bus_geodata_xy(net): + def notnone(val): + return isinstance(val, str) and bool(len(val)) + net.bus_geodata = pd.DataFrame(np.nan, index=net.bus.index, columns=["x", "y"]) + # x = + idxs = net.bus.index[net.bus.geo.apply(notnone)] + net.bus_geodata.loc[idxs, ["x", "y"]] = np.r_[[pd.read_json(net.bus.geo.at[ + i]).coordinates.values for i in idxs]] + + def merge_busbar_coordinates(net): """ merges x and y coordinates of busbar node connected via bus-bus switches """ + convert_geojson_to_bus_geodata_xy(net) bb_nodes_set = set(net.bus.index[net.bus.type == "b"]) bb_nodes = sorted(bb_nodes_set) all_connected_buses = set() @@ -509,9 +520,6 @@ def create_branch_switches(net): net.bus = net.bus.drop(aux_bus_df["aux_buses"]) idx_in_res_bus = aux_bus_df["aux_buses"][aux_bus_df["aux_buses"].isin(net.res_bus.index)] net.res_bus = net.res_bus.drop(idx_in_res_bus) - idx_in_bus_geodata = aux_bus_df["aux_buses"][aux_bus_df["aux_buses"].isin( - net.bus_geodata.index)] - net.bus_geodata = net.bus_geodata.drop(idx_in_bus_geodata) def _add_coordID(net, highest_existing_coordinate_number): From 3a332c2ea92dc24cfe70414cbaaf2ff5a75cea22 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Wed, 24 Apr 2024 11:59:11 +0200 Subject: [PATCH 02/21] fix all tests with applied geojson changes of pandapower --- simbench/converter/csv_data_manipulation.py | 2 +- simbench/converter/csv_pp_converter.py | 24 ++++++++++--------- simbench/converter/format_information.py | 8 ++++--- simbench/converter/pp_net_manipulation.py | 24 ++++++++++++------- .../test/converter/test_csv_pp_converter.py | 6 ++--- .../test_network_output_folder/LineType.csv | 4 ++-- .../TransformerType.csv | 2 +- .../converter/test_pp_net_manipulation.py | 8 ++----- .../networks/test_extract_grids_from_csv.py | 9 +------ 9 files changed, 43 insertions(+), 44 deletions(-) diff --git a/simbench/converter/csv_data_manipulation.py b/simbench/converter/csv_data_manipulation.py index 1a940be..88b8e72 100644 --- a/simbench/converter/csv_data_manipulation.py +++ b/simbench/converter/csv_data_manipulation.py @@ -154,7 +154,7 @@ def _add_phys_type_and_vm_va_setpoints_to_element_tables(csv_data): def _extend_coordinates_to_node_shape(csv_data): """ Extends the Coordinates table to the shape of Nodes to enable copying simply to bus_geodata. """ - geo = pd.Series(None, index=csv_data["Node"].index, name="geo") + geo = pd.Series(None, index=csv_data["Node"].index, name="geo", dtype=object) with_coord = ~csv_data["Node"]["coordID"].isnull() idx_in_coordID = idx_in_2nd_array(csv_data["Node"]["coordID"].loc[with_coord].values, csv_data["Coordinates"]["id"].values) diff --git a/simbench/converter/csv_pp_converter.py b/simbench/converter/csv_pp_converter.py index 99da19f..6f250e1 100644 --- a/simbench/converter/csv_pp_converter.py +++ b/simbench/converter/csv_pp_converter.py @@ -233,7 +233,7 @@ def pp2csv_data(net1, export_pp_std_types=False, drop_inactive_elements=True, str(["%s" % elm for elm in check_results.keys()]) + ". Only the standard " + "type values are converted to csv.") convert_parallel_branches(net) - merge_busbar_coordinates(net) + merge_busbar_coordinates(net, True) move_slack_gens_to_ext_grid(net) scaling_is_not_1 = [] @@ -314,7 +314,8 @@ def _log_nan_col(csv_data, tablename, col): def _is_pp_type(data): - return "name" in data.keys() # used instead of isinstance(data, pp.auxiliary.pandapowerNet) + return isinstance(data, pp.auxiliary.pandapowerNet) + # return bool("name" in data.keys()) def convert_node_type(data): @@ -674,7 +675,7 @@ def _rename_and_split_input_tables(data): split_ppelm_into_type_and_elm = ["dcline"] if _is_pp_type(data) else [] input_elm_col = "pp" if _is_pp_type(data) else "csv" output_elm_col = "csv" if _is_pp_type(data) else "pp" - corr_df = _csv_table_pp_dataframe_correspondings(pd.DataFrame) + corr_df = _csv_table_pp_dataframe_correspondings(pd.DataFrame, not _is_pp_type(data)) corr_df["comb_str"] = corr_df["csv"] + "*" + corr_df["pp"] # all elements, which need to be converted to multiple output element tables, (dupl) need to be @@ -721,7 +722,7 @@ def _get_split_gen_val(element): def _rename_and_multiply_columns(data): """ Renames the columns of all dataframes as needed in output data. """ - to_rename_and_multiply_tuples = _get_parameters_to_rename_and_multiply() + to_rename_and_multiply_tuples = _get_parameters_to_rename_and_multiply(True) for corr_str, tuples in to_rename_and_multiply_tuples.items(): # --- remove "type" from data if "std_type" exists too if "std_type" in data[corr_str].columns and "type" in data[corr_str].columns and \ @@ -751,7 +752,7 @@ def _rename_and_multiply_columns(data): data[corr_str].loc[:, col] *= factors -def _get_parameters_to_rename_and_multiply(): +def _get_parameters_to_rename_and_multiply(drop_bus_geodata): """ Returns a dict of tuples and a dict of dataframes where csv column names are assigned to pandapower columns names which differ. """ # --- create dummy_net to get pp columns @@ -765,8 +766,8 @@ def _get_parameters_to_rename_and_multiply(): dummy_net[elm]["va_degree"] = np.nan # --- get corresponding tables and dataframes - corr_strings = _csv_table_pp_dataframe_correspondings(str) - csv_tablenames_, pp_dfnames = _csv_table_pp_dataframe_correspondings(list) + corr_strings = _csv_table_pp_dataframe_correspondings(str, drop_bus_geodata) + csv_tablenames_, pp_dfnames = _csv_table_pp_dataframe_correspondings(list, drop_bus_geodata) # --- initialize tuples_dict tuples_dict = dict.fromkeys(corr_strings, [("id", "name", None)]) @@ -798,7 +799,7 @@ def _replace_name_index(data): indices. This function replaces the assignment of the input data. """ node_names = {"node", "nodeA", "nodeB", "nodeHV", "nodeMV", "nodeLV"} bus_names = {"bus", "from_bus", "to_bus", "hv_bus", "mv_bus", "lv_bus"} - corr_strings = _csv_table_pp_dataframe_correspondings(str) + corr_strings = _csv_table_pp_dataframe_correspondings(str, True) corr_strings.remove("Measurement*measurement") # already done in convert_measurement() if _is_pp_type(data): @@ -838,8 +839,9 @@ def _copy_data(input_data, output_data): """ Copies the data from output_data[corr_strings] into input_data[element_table]. This function handles that some corr_strings are not in output_data.keys() and copies all columns which exists in both, output_data[corr_strings] and input_data[element_table]. """ - corr_strings = _csv_table_pp_dataframe_correspondings(str) - output_names = _csv_table_pp_dataframe_correspondings(list)[int(_is_pp_type(output_data))] + out_is_pp = _is_pp_type(output_data) + corr_strings = _csv_table_pp_dataframe_correspondings(str, out_is_pp) + output_names = _csv_table_pp_dataframe_correspondings(list, out_is_pp)[int(out_is_pp)] for corr_str, output_name in zip(corr_strings, output_names): if corr_str in input_data.keys() and input_data[corr_str].shape[0]: @@ -864,7 +866,7 @@ def _copy_data(input_data, output_data): output_data[output_name] = pd.concat([output_data[output_name], input_data[ corr_str][cols_to_copy]], ignore_index=True).reindex_axis(output_data[ output_name].columns, axis=1) - if "std_types" in corr_str and _is_pp_type(output_data): + if "std_types" in corr_str and out_is_pp: output_data[output_name].index = input_data[corr_str]["std_type"] _inscribe_fix_values(output_data, output_name) diff --git a/simbench/converter/format_information.py b/simbench/converter/format_information.py index a654c89..c129cdb 100644 --- a/simbench/converter/format_information.py +++ b/simbench/converter/format_information.py @@ -52,18 +52,20 @@ def csv_tablenames(which): return csv_tablenames -def _csv_table_pp_dataframe_correspondings(type_): +def _csv_table_pp_dataframe_correspondings(type_, drop_bus_geodata): csv_tablenames_ = csv_tablenames(['elements', 'types', 'res_elements']) - csv_tablenames_.remove("Coordinates") # corresponding pandapower dataframe names pp_dfnames = ['ext_grid', 'line', 'load', 'shunt', 'bus', 'measurement', 'gen', 'sgen', - 'storage', 'substation', 'switch', 'trafo', 'trafo3w', + 'storage', 'substation', 'switch', 'trafo', 'trafo3w', 'bus_geodata', 'std_types|line', 'dcline', 'std_types|trafo', 'std_types|trafo3w', "res_bus"] # append table name lists by combinations of generating elements csv_tablenames_ += ['ExternalNet', 'ExternalNet', 'PowerPlant', 'PowerPlant', 'RES', 'RES', 'ExternalNet', 'ExternalNet', 'Line'] pp_dfnames += ['gen', 'sgen', 'ext_grid', 'sgen', 'ext_grid', 'gen', 'ward', 'xward', 'dcline'] + if drop_bus_geodata: + csv_tablenames_.remove("Coordinates") + pp_dfnames.remove("bus_geodata") assert len(csv_tablenames_) == len(pp_dfnames) if type_ is list: return csv_tablenames_, pp_dfnames diff --git a/simbench/converter/pp_net_manipulation.py b/simbench/converter/pp_net_manipulation.py index ab32d63..4c96d9c 100644 --- a/simbench/converter/pp_net_manipulation.py +++ b/simbench/converter/pp_net_manipulation.py @@ -2,6 +2,7 @@ # Institute for Energy Economics and Energy System Technology (IEE) Kassel and individual # contributors (see AUTHORS file for details). All rights reserved. +from io import StringIO import numpy as np import pandas as pd import pandapower as pp @@ -187,13 +188,14 @@ def notnone(val): net.bus_geodata = pd.DataFrame(np.nan, index=net.bus.index, columns=["x", "y"]) # x = idxs = net.bus.index[net.bus.geo.apply(notnone)] - net.bus_geodata.loc[idxs, ["x", "y"]] = np.r_[[pd.read_json(net.bus.geo.at[ - i]).coordinates.values for i in idxs]] + net.bus_geodata.loc[idxs, ["x", "y"]] = np.r_[[pd.read_json(StringIO(net.bus.geo.at[ + i])).coordinates.values for i in idxs]] -def merge_busbar_coordinates(net): +def merge_busbar_coordinates(net, on_bus_geodata): """ merges x and y coordinates of busbar node connected via bus-bus switches """ - convert_geojson_to_bus_geodata_xy(net) + if on_bus_geodata: + convert_geojson_to_bus_geodata_xy(net) bb_nodes_set = set(net.bus.index[net.bus.type == "b"]) bb_nodes = sorted(bb_nodes_set) all_connected_buses = set() @@ -202,8 +204,11 @@ def merge_busbar_coordinates(net): continue connected_nodes = pp.get_connected_buses(net, bb_node, consider=("t", "s")) if len(connected_nodes): - net.bus_geodata.loc[list(connected_nodes), "x"] = net.bus_geodata.x.at[bb_node] - net.bus_geodata.loc[list(connected_nodes), "y"] = net.bus_geodata.y.at[bb_node] + if on_bus_geodata: + net.bus_geodata.loc[list(connected_nodes), "x"] = net.bus_geodata.x.at[bb_node] + net.bus_geodata.loc[list(connected_nodes), "y"] = net.bus_geodata.y.at[bb_node] + else: + net.bus.loc[list(connected_nodes), "geo"] = net.bus.at[bb_node, "geo"] all_connected_buses |= connected_nodes @@ -434,11 +439,12 @@ def replace_branch_switches(net, reserved_aux_node_names=None): else: # if replace_branch_switches() is called out of pp2csv_data(), this else statement is given subnets = net.bus.zone[idx_bus].values - geodata = net.bus_geodata.loc[idx_bus, ["x", "y"]].values if net["bus_geodata"].shape[0] else \ - np.empty((len(idx_bus), 2)) aux_buses = pp.create_buses( net, n_branch_switches, net.bus.vn_kv[idx_bus].values, name=names.values, type="auxiliary", - geodata=geodata, zone=subnets) + zone=subnets) + if "bus_geodata" in net.keys() and net["bus_geodata"].shape[0]: + net.bus_geodata = pd.concat([net.bus_geodata, pd.DataFrame(net.bus_geodata.loc[ + idx_bus, ["x", "y"]].values, index=aux_buses, columns=["x", "y"])]) for col in ["min_vm_pu", "max_vm_pu", "substation", "voltLvl"]: if col in net.bus.columns: net.bus.loc[aux_buses, col] = net.bus[col][idx_bus].values diff --git a/simbench/test/converter/test_csv_pp_converter.py b/simbench/test/converter/test_csv_pp_converter.py index 651e8fb..974d1af 100644 --- a/simbench/test/converter/test_csv_pp_converter.py +++ b/simbench/test/converter/test_csv_pp_converter.py @@ -219,9 +219,9 @@ def test_example_simple(): avoid_duplicates_in_column(net, i, 'name') # --- create geodata - net.bus_geodata["x"] = [0, 1, 2, 3, 4, 5, 5, 3.63] - net.bus_geodata["y"] = [0]*5+[-5, 5, 2.33] - merge_busbar_coordinates(net) + net.bus["geo"] = list(map(lambda xy: f'{{"type":"Point", "coordinates":[{xy[0]}, {xy[1]}]}}', + zip([0., 1., 2., 3., 4., 5., 5., 3.63], [0.]*5+[-5., 5., 2.33]))) + merge_busbar_coordinates(net, False) # --- convert csv_data = pp2csv_data(net, export_pp_std_types=True, drop_inactive_elements=True) diff --git a/simbench/test/converter/test_network_output_folder/LineType.csv b/simbench/test/converter/test_network_output_folder/LineType.csv index f23c8ad..0042ae1 100644 --- a/simbench/test/converter/test_network_output_folder/LineType.csv +++ b/simbench/test/converter/test_network_output_folder/LineType.csv @@ -1,3 +1,3 @@ id;r;x;b;iMax;type -HV OHL 1;0.05;0.4;3;500;ohl -MV OHL 1;0.25;0.2;1;500;ohl +HV OHL 1;0.05;0.4;2.9999999999999996;500.0;ohl +MV OHL 1;0.25;0.2;0.9999999999999999;500.0;ohl diff --git a/simbench/test/converter/test_network_output_folder/TransformerType.csv b/simbench/test/converter/test_network_output_folder/TransformerType.csv index 9f87716..c7c9a3d 100644 --- a/simbench/test/converter/test_network_output_folder/TransformerType.csv +++ b/simbench/test/converter/test_network_output_folder/TransformerType.csv @@ -1,2 +1,2 @@ id;sR;vmHV;vmLV;va0;vmImp;pCu;pFe;iNoLoad;tapable;tapside;dVm;dVa;tapNeutr;tapMin;tapMax -T1;25;110;20;150;12;70;30;0;1;HV;0;0;0;-5;5 +T1;25.0;110.0;20.0;150.0;12.0;70.00000000000001;30.0;0.0;1;HV;0.0;0;0;-5;5 diff --git a/simbench/test/converter/test_pp_net_manipulation.py b/simbench/test/converter/test_pp_net_manipulation.py index 60a0bb7..a60387e 100644 --- a/simbench/test/converter/test_pp_net_manipulation.py +++ b/simbench/test/converter/test_pp_net_manipulation.py @@ -51,10 +51,8 @@ def _net_to_test(): pp.create_switch(net, lv_buses[2], l0, "l") pp.create_switch(net, lv_buses[3], l1, "l") -# create_generic_coordinates(net) - net.bus_geodata["x"] = [1, 2, 1, 3, 0, 1, 2] - net.bus_geodata["y"] = [0, 1, -1, 0, 0, 1, 0] - net.bus_geodata.index = list(range(6))+[8] + net.bus["geo"] = list(map(lambda xy: f'{{"type":"Point", "coordinates":[{xy[0]}, {xy[1]}]}}', + zip([1., 2., 1., 3., 0., 1., 2], [0., 1., -1., 0., 0., 1., 0]))) return net @@ -65,8 +63,6 @@ def test_branch_switch_changes(): net1 = deepcopy(net_orig) replace_branch_switches(net1) - net1.bus_geodata = net1.bus_geodata.astype({coord: net_orig.bus_geodata.dtypes[ - coord] for coord in ["x", "y"]}) assert net_orig.switch.shape == net1.switch.shape assert (net_orig.switch.bus == net1.switch.bus).all() diff --git a/simbench/test/networks/test_extract_grids_from_csv.py b/simbench/test/networks/test_extract_grids_from_csv.py index e0005ba..4393f34 100644 --- a/simbench/test/networks/test_extract_grids_from_csv.py +++ b/simbench/test/networks/test_extract_grids_from_csv.py @@ -393,14 +393,7 @@ def _test_net_validity(net, sb_code_params, shortened, input_path=None): 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 np.all(np.isclose(net.bus_geodata.x.loc[bus_group].astype(float), - # net.bus_geodata.x.loc[first_bus].astype(float))) \ - # and np.all(np.isclose(net.bus_geodata.y.loc[bus_group].astype(float), - # net.bus_geodata.y.loc[first_bus].astype(float))) + assert not net.bus.geo.isnull().any() # --- test data content # substation From 48849621bad7519146588c66886fd1a604e4ebdd Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Wed, 24 Apr 2024 12:05:08 +0200 Subject: [PATCH 03/21] adjust simbench version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 200e5e7..c0a8edd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "simbench" -version = "1.5.3" +version = "1.6.0" authors = [ { name = "Steffen Meinecke", email = "steffen.meinecke@uni-kassel.de" } ] From 0e08d34545c742c48c3025d7c5c6b7d68d4257e2 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Wed, 24 Apr 2024 12:06:20 +0200 Subject: [PATCH 04/21] remove deprecated requirements.txt (now included in pyproject.toml) --- requirements.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 1fb6481..0000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -# pip only: -pandapower>=2.12.1 \ No newline at end of file From 51f69a6eb5b506b8930a97f610970433a59b87ce Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Fri, 3 May 2024 16:30:46 +0200 Subject: [PATCH 05/21] add *git to MANIFEST --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index f6ab14c..d91d0d0 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,5 +4,6 @@ global-include *.csv global-include *.json global-include *.txt +prune .git* prune doc* prune tutorials* From 70e0a0143d431f8a97636158529632951af3ccca Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Thu, 30 May 2024 11:01:49 +0200 Subject: [PATCH 06/21] reduce pp requirements as long as 3.0 does not exist --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c0a8edd..d415be9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ classifiers = [ "Programming Language :: Python :: 3.12" ] dependencies = [ - "pandapower>=3.0.0" + "pandapower>=2.14.6" ] keywords = [ "benchmark grid", "power system", "network", "grid planning", "grid operation", "grid generation methodology", "comparability", "reproducibility", "electricity", "energy", "engineering", "simulation", "simbench", "time series", "future scenarios" From 95401f8edbab4fa3fc1a3a841fbdea0e69fc0808 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Wed, 23 Oct 2024 18:30:31 +0200 Subject: [PATCH 07/21] link related pandas discussion --- simbench/converter/auxiliary.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/simbench/converter/auxiliary.py b/simbench/converter/auxiliary.py index c6d2fef..d2115a7 100644 --- a/simbench/converter/auxiliary.py +++ b/simbench/converter/auxiliary.py @@ -33,6 +33,9 @@ def to_numeric_ignored_errors(data, **kwargs): """Wrapper function for pandas.to_numeric(). Needed to emulate previous behavior with deprecated errors="ignore". + The issue covered by this function is discussed at https://github.com/pandas-dev/pandas/issues/54467. + `df2 = df1.apply(pd.to_numeric, errors='coerce')` and `df2=df2.fillna(df1)` is an alternative way. + Parameters ---------- data : Series|DataFrame From 16656464b0c42f4fe722e0cc7811fb2db427821f Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Wed, 23 Oct 2024 18:30:52 +0200 Subject: [PATCH 08/21] add EHVHV powerflow example tutorial --- tutorials/EHVHV_powerflow_expl.ipynb | 1 + 1 file changed, 1 insertion(+) create mode 100644 tutorials/EHVHV_powerflow_expl.ipynb diff --git a/tutorials/EHVHV_powerflow_expl.ipynb b/tutorials/EHVHV_powerflow_expl.ipynb new file mode 100644 index 0000000..b97ea51 --- /dev/null +++ b/tutorials/EHVHV_powerflow_expl.ipynb @@ -0,0 +1 @@ +{"cells":[{"cell_type":"markdown","metadata":{},"source":["# Power Flow Example for the EHV and HV grids\n","\n","This tutorial is a quick answer related to multiple more or less similar questions regarding \"Making the complete SimBench grid run\".\n","\n","First of all, during the research project, most use cases were identified to be covered by power system data that models one or two voltage levels at the same time. Accordingly, the SimBench codes include those combinations of the base grids of SimBench (1 EHV grid, 2 HV grids, 4 MV grids, and 6 LV grids) which were expected most relevant for users' application. For reasons of completeness, the complete data sets \"1-complete_data-mixed-all-0-sw\" (no option to perform a proper power flow), \"1-EHVHVMVLV-mixed-all-0-sw\" (not tested for proper power flow results), and related data sets for futures scenarios 1 and 2 were provided, as well.\n","\n","In contrast, this tutorial provides a simple example of a combined power flow for the German EHV and the two HV Grids provided by SimBench."]},{"cell_type":"markdown","metadata":{},"source":["First get the SimBench grid of the code \"1-EHVHV-mixed-all-0-no_sw\"."]},{"cell_type":"code","execution_count":5,"metadata":{},"outputs":[],"source":["import pandas as pd\n","import matplotlib.pyplot as plt\n","import pandapower as pp\n","import simbench as sb\n","\n","net = sb.get_simbench_net(\"1-EHVHV-mixed-all-0-no_sw\")"]},{"cell_type":"markdown","metadata":{},"source":["Note that the nuclear power units (which were active at the time of the project and are thus included in the scenario 0) were set as slack elements, i.e. in `pandapower` as external grid elements (`ext_grid`). For simplicity of the code, we replace these to `gen` elements.\n","\n","On top of this, we need to assume some kind of simultaneity factor of the loads and sgens (`scaling`). Let's assume `0.35`. Accordingly, we adjust the active power of generators so that the total electric power consumption equals the total feed-in (we start with a DC power flow which disregards branch losses)."]},{"cell_type":"code","execution_count":6,"metadata":{},"outputs":[],"source":["# --- convert ext_grids to gen elements and set some assumed active power setpoints\n","nuclear_gens = pp.toolbox.replace_ext_grid_by_gen(net, add_cols_to_keep=[\"slack_weight\"])\n","net.gen.at[net.gen.index[-1], \"slack\"] = True\n","gens_with_p_2bset = pd.Index(nuclear_gens).difference([342])\n","net.gen.loc[gens_with_p_2bset, \"p_mw\"] = net.gen.loc[gens_with_p_2bset, \"max_p_mw\"]\n","\n","# --- set scalings\n","scaling = {\n"," \"load\": 0.35,\n"," \"sgen\": 0.35,\n","}\n","gen_xg_scaling = ((net.load.p_mw *scaling[\"load\"]).sum() - (net.sgen.p_mw *scaling[\"sgen\"]).sum()) / (\n"," net.gen.p_mw.sum() + net.ext_grid.max_p_mw.sum())\n","scaling[\"gen\"] = gen_xg_scaling\n","\n","# --- apply the assumed and calculated scaling values\n","for et, scale in scaling.items():\n"," net[et][\"scaling\"] = scale"]},{"cell_type":"markdown","metadata":{},"source":["## DC Power Flow Results"]},{"cell_type":"code","execution_count":7,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":["hp.pandapower.toolbox.result_info - INFO: Max voltage in vm_pu:\n","hp.pandapower.toolbox.result_info - INFO: 1.092 at busidx 0 (EHV Bus 1)\n","hp.pandapower.toolbox.result_info - INFO: Min voltage in vm_pu:\n","hp.pandapower.toolbox.result_info - INFO: 1.0 at busidx 3748 (HV2 Bus 361)\n","hp.pandapower.toolbox.result_info - INFO: Max loading trafo in %:\n","hp.pandapower.toolbox.result_info - INFO: 51.08204436767962 loading at trafo 34 (EHV Trafo 35)\n","hp.pandapower.toolbox.result_info - INFO: 51.08204436767962 loading at trafo 35 (EHV Trafo 36)\n","hp.pandapower.toolbox.result_info - INFO: Max loading line in %:\n","hp.pandapower.toolbox.result_info - INFO: 92.73344755050144 loading at line 824 (EHV Line 825)\n","hp.pandapower.toolbox.result_info - INFO: 85.93217745798063 loading at line 768 (EHV Line 769)\n"]}],"source":["# --- perform DC power flow\n","pp.rundcpp(net, distributed_slack=True)\n","\n","# --- log some results\n","pp.toolbox.lf_info(net)"]},{"cell_type":"markdown","metadata":{},"source":["The log shows that the DC power flow results of this simple example include no line or transformer overloadings (max. line loading is around 93 %)."]},{"cell_type":"markdown","metadata":{},"source":["## AC Power Flow Results\n","\n","In addition to a realistic load case (here equal scaling factors are applied all over the grid), several adjustments for the volt-var control are required for realistic AC power flows.\n","Again, only tap controllers for EHV-HV transformers and a distributed slack (to balance the branch losses) are applied here."]},{"cell_type":"code","execution_count":8,"metadata":{},"outputs":[],"source":["ehv_hv_trafos = sb.voltlvl_idx(net, \"trafo\", [3], \"lv_bus\")\n","pp.control.ContinuousTapControl(net, ehv_hv_trafos, 1.0)\n","pp.runpp(net, run_control=True, distributed_slack=True)"]},{"cell_type":"markdown","metadata":{},"source":["After calculating the AC power flow, we can analyze the voltage range and branch with the highest loading, cf. log and plot. As expected, the loadings increase. However, even this very simple assumptions result in acceptable voltages and almost no branch overloadings.\n","In actual grid operations, security margins for n-1 security must be added, especially regarding the few highly loaded lines."]},{"cell_type":"code","execution_count":9,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":["hp.pandapower.toolbox.result_info - INFO: Max voltage in vm_pu:\n","hp.pandapower.toolbox.result_info - INFO: 1.1070887174089667 at busidx 56 (EHV Bus 57)\n","hp.pandapower.toolbox.result_info - INFO: Min voltage in vm_pu:\n","hp.pandapower.toolbox.result_info - INFO: 0.9933431959987652 at busidx 3477 (HV2 Bus 90)\n","hp.pandapower.toolbox.result_info - INFO: Max loading trafo in %:\n","hp.pandapower.toolbox.result_info - INFO: 48.65530642371104 loading at trafo 34 (EHV Trafo 35)\n","hp.pandapower.toolbox.result_info - INFO: 48.65530642371104 loading at trafo 35 (EHV Trafo 36)\n","hp.pandapower.toolbox.result_info - INFO: Max loading line in %:\n","hp.pandapower.toolbox.result_info - INFO: 101.5984172475295 loading at line 768 (EHV Line 769)\n","hp.pandapower.toolbox.result_info - INFO: 91.14251627977873 loading at line 824 (EHV Line 825)\n"]},{"data":{"image/png":"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1cjIyEBCQgLCwsLE9oCAAGRkZECtVkuYHZHpsagjIiLZUKvVGDp0KHeUIKvEoo6IiGRFqVQiIiJC6jSIHjqOqSMiIiKSARZ1RERERDLAoo6IiIhIBljUEREREckAJ0qQRSm6XIWqmroHusbJ0kqD/z6I5ipbBLRq/sDXISIielAs6shiFF2uQmRqttGuF7epwCjX2ZUYwcKOiIgkx6KOLEZ9D136c10Q5OH0h69z46YO565Ww9fNAfbN/vjaVSdLKxG3qeCBew6JiIiMgUUdWZwgDycEt3F9oGt09zdOLkREROaCEyWIiIiIZIBFHREREZEMsKgjIiIikgEWdUREREQywKKOiIiISAZY1BERERHJAIs6IiIiIhlgUUdEREQkAyzqiIiIiGSARR0RERGRDLCoIyIiIpIBFnVEREREMsCijoiIiEgGWNQRERERyQCLOiIiIiIZYFFHREREJAMs6oiIiIhkgEUdERERkQywqCMiIiKSARZ1RERERDLAoo6IiIhIBljUEREREckAizoiIiIiGWBRR0Qksbq6OsyaNQsBAQFwcHDAI488grlz50Kv14sxgiBgzpw58PHxgYODAyIiInDkyBEJsyYic8OijohIYu+//z5WrFiBpUuX4ujRo5g/fz4WLFiADz74QIyZP38+Fi1ahKVLl2L//v3w8vJCv379UFFRIWHmRGROWNQREUksLy8PQ4cOxaBBg+Dv74/Y2Fj0798f+fn5AG710qWnp2PmzJlQq9UIDg7GunXrcP36daxfv17i7InIXLCoIyKSWO/evbFz504cP34cAPDTTz9hz549GDhwIACgqKgIJSUl6N+/v/gclUqFPn36YO/evZLkTETmx1bqBIiIrN3f//53lJWV4bHHHoNSqYROp8N7772HF154AQBQUlICAPD09DR4nqenJ06fPn3X69bU1KCmpkY8Li8vN0H2RGQu2FNHRCSxTZs24dNPP8X69etx8OBBrFu3DqmpqVi3bp1BnEKhMDgWBKFB2+1SUlLg6uoqPvz8/EySPxGZBxZ1REQSmzZtGt588008//zzCAkJwejRozF16lSkpKQAALy8vAD8r8euXmlpaYPeu9slJSWhrKxMfJw9e9Z0L4KIJMfbr2QxanQ3YGN/HkXlx2Bj7yR1Oigqr4SN/XnU6G4AcJU6HbJg169fh42N4d/YSqVSXNIkICAAXl5e2LFjB7p27QoAqK2tRU5ODt5///27XlelUkGlUpkucSIyKyzqyGJcqDqN5gEfYMY+qTP5n+YBwIWqLuiGu/eWEP2ewYMH47333kPbtm3x+OOP49ChQ1i0aBH+9re/Abh12zUuLg7Jyclo37492rdvj+TkZDg6OmLkyJESZ09E5oJFHVkMn+btUFU0GYuf64JAD+l76k6VVuKNTQXwiWwndSpk4T744AO89dZbmDhxIkpLS+Hj44Px48fj7bffFmOmT5+O6upqTJw4EVevXkWPHj2wfft2ODs7S5g5EZkTSYu63bt3Y8GCBThw4AC0Wi02b96MmJiYez4nJycH8fHxOHLkCHx8fDB9+nRMmDDBICY9PR3Lly/HmTNn0KpVK8TGxiIlJQX29vYmfDVkaiqlPfQ32iDA5VF0dJf+dqf+Rhn0Ny5BpeT/V/RgnJ2dkZ6ejvT09LvGKBQKzJkzB3PmzHloeRGRZZF0okRVVRU6d+6MpUuXNim+qKgIAwcORHh4OA4dOoQZM2ZgypQp+OKLL8SYzz77DG+++SZmz56No0ePYvXq1di0aROSkpJM9TKIiIiIJCdpT11UVBSioqKaHL9ixQq0bdtW/Gu2Q4cOyM/PR2pqKoYPHw7g1srsvXr1EseZ+Pv744UXXsC+fWY0EIuIiIjIyCxqSZO8vDyDFdUBYMCAAcjPz8fNmzcB3FqZ/cCBA2IR9+uvv2Lr1q0YNGjQQ8+XiIiI6GGxqIkSJSUlja6oXldXh8uXL8Pb2xvPP/88Ll26hN69e0MQBNTV1eG1117Dm2++edfrctV1IiIisnQW1VMHNL6i+u3t2dnZeO+997Bs2TIcPHgQGo0GWVlZePfdd+96Ta66TkRERJbOonrqvLy8Gl1R3dbWFu7u7gCAt956C6NHj8arr74KAAgJCUFVVRXGjRuHmTNnNljgE7i16np8fLx4XF5ezsKOiIiILIpFFXU9e/bEV199ZdC2fft2dO/eHc2aNQNw95XZBUEQe/XuxFXXiYiIyNJJevu1srISBQUFKCgoAHBryZKCggKcOXMGwK0etJdeekmMnzBhAk6fPo34+HgcPXoUa9aswerVq5GYmCjGDB48GMuXL8fGjRtRVFSEHTt24K233sKQIUOgVCof6usjIiIielgk7anLz89HZGSkeFx/C/Tll1/G2rVrodVqxQIPuLX/4datWzF16lR8+OGH8PHxwZIlS8TlTABg1qxZUCgUmDVrFs6fP4/WrVuLW/AQERERyZWkRV1ERMRdb4kCwNq1axu09enTBwcPHrzrc2xtbTF79mzMnj3bGCkSERERWQSLm/1KRERERA2xqCMiIiKSARZ1RERERDLAoo6IiIhIBljUEREREckAizoiIiIiGWBRR0RERCQDLOqIiIiIZIBFHREREZEMsKgjIiIikgEWdUREREQywKKOiIiISAZspU6AiIjImHQ6HXJzc6HVauHt7Y3w8HAolUqp0yIyOfbUERGRbGg0GgQFBSEyMhIjR45EZGQkgoKCoNFopE6NyORY1BERkSxoNBrExsYiJCQEeXl5qKioQF5eHkJCQhAbG8vCjmSPRR0REVk8nU6HhIQEREdHIzMzE6GhoXByckJoaCgyMzMRHR2NxMRE6HQ6qVMlMhkWdUREZPFyc3NRXFyMGTNmwMbG8FebjY0NkpKSUFRUhNzcXIkyJDI9FnVERGTxtFotACA4OLjR8/Xt9XFEcsSijoiILJ63tzcAoLCwsNHz9e31cURyxKKOiIgsXnh4OPz9/ZGcnAy9Xm9wTq/XIyUlBQEBAQgPD5coQyLTY1FHREQWT6lUYuHChcjKykJMTIzB7NeYmBhkZWUhNTWV69WRrHHxYSIikgW1Wo2MjAwkJCQgLCxMbA8ICEBGRgbUarWE2RGZHos6IiKSDbVajaFDh3JHCbJKLOqIiEhWlEolIiIipE6D6KHjmDoiIiIiGWBRR0RERCQDLOqIiIiIZIBFHREREZEMsKgjIiIikgEWdUREREQywKKOiIiISAa4Th0REcmKTqfj4sNkldhTR0REsqHRaBAUFITIyEiMHDkSkZGRCAoKgkajkTo1IpNjTx0REcmCRqNBbGwsBg0ahGnTpsHBwQHV1dXYtm0bYmNjuf8ryR6LOrIY1Td1AIDC82UPdJ0bN3U4d7Uavm4OsG/2x2/JnCytfKA8iMh4dDodEhIS0K1bNxw+fBhZWVniuXbt2qFbt25ITEzE0KFDeSuWZItFHVmMU/8tot7UHJY4E0PNVXwbEUktNzcXxcXFKC4uxuDBg7Fx40YEBwejsLAQycnJ+Oqrr8Q47gtLcsXfRmQx+j/uBQAI9HCCwwP2sMVtKkD6c10Q5OH0QDk1V9kioFXzB7oGET248+fPAwCioqKQmZkJG5tbQ8ZDQ0ORmZmJ6OhobNu2TYwjkiMWdWQxWja3w/NPtTXa9YI8nBDcxtVo1yMi6Vy6dAkAoFarxYKuno2NDWJiYrBt2zYxjkiOOPuViIgsXuvWrQHcmiyh1+sNzun1emRmZhrEEckRizoiIrJ4bdq0AQB88803iImJQV5eHioqKpCXl4eYmBh88803BnFEcsTbr0REZPHCw8Ph7++PVq1a4fDhwwgLCxPPBQQEoFu3brhy5QrCw8MlzJLItFjUERGRxVMqlVi4cCFiY2OhUqkMzmm1WhQXFyMjI4PLmZCs8fYrERHJhiAIUCgUBm02NjYQBEGijIgeHhZ1RERk8eoXHx48eDB+++03pKWlYdKkSUhLS8OVK1cwePBgJCYmQqfTSZ0qkcnw9isREVm8+sWHx48fjw4dOqC4uFg8t3jxYowbNw5fffUVFx8mWWNPHRERWTytVgsAmDFjBkJCQgxmv4aEhGDmzJkGcURyxJ46IiKyeB4eHgCAXr16NbqjRJ8+fbBnzx4xjkiO2FNHRESyx4kSZA1Y1BERkcUrLS0FAOzZs6fRxYe///57gzgiOWJRR0REFs/b2xsAkJKSIi4+7OLigrCwMBQWFiI5OdkgjkiOOKaOiIgsXv2OEnv37sXx48fx/fffQ6vVwtvbG7169cLw4cMREBDAHSVI1thTR0REFq9+R4msrCyo1WocOXIE1dXVOHLkCNRqNbKyspCamsodJUjW2FNHRESyoFarkZiYiEWLFiErK0tsVyqVSExMhFqtljA7ItNjTx0RURNUVlaivLxc6jToHjQaDRYsWAA7OzuDdjs7OyxYsAAajUaizIgeDhZ1RET38PPPP6N79+5wcXGBm5sbQkJCcODAAanTojvodDpMmDABANC3b1+D2a99+/YFALz22mvcJoxkjUUdEdE9jB8/HpMmTUJlZSWuXLkCtVqNl156Seq06A7Z2dm4dOkSevfujS+//BKhoaFwcnJCaGgovvzyS/Tu3RulpaXIzs6WOlUik2FRR0R0m6FDh+L8+fPi8aVLlzBkyBA4OjqiRYsWGDhwIC5evGj073v+/HmMGjUK7u7ucHR0RJcuXQx6BAVBwJw5c+Dj4wMHBwdERETgyJEjRs/DUtUXa++88464m0Q9GxsbzJ492yCOSI4kLep2796NwYMHw8fHBwqFApmZmb/7nJycHHTr1g329vZ45JFHsGLFigYx165dw+uvvw5vb2/Y29ujQ4cO2Lp1qwleARHJzYsvvojIyEgsWbIEgiBg0qRJePzxx/H8889j+PDhePbZZxEXF2fU73n16lX06tULzZo1w7Zt2/Dzzz9j4cKFaNGihRgzf/58LFq0CEuXLsX+/fvh5eWFfv36oaKiwqi5EJHlkrSoq6qqQufOnbF06dImxRcVFWHgwIEIDw/HoUOHMGPGDEyZMgVffPGFGFNbW4t+/fqhuLgYGRkZOHbsGFatWoU2bdqY6mUQkYyMGDEC+/btw5EjR9CjRw/06tUL27dvR69evRAeHo7t27dj1qxZRv2e77//Pvz8/PDRRx/hqaeegr+/P/r27YvAwEAAt3rp0tPTMXPmTKjVagQHB2PdunW4fv061q9fb9RcLFVERAQAYPbs2dDr9Qbn9Ho95syZYxBHJEuCmQAgbN68+Z4x06dPFx577DGDtvHjxwuhoaHi8fLly4VHHnlEqK2t/cO5lJWVCQCEsrKyP3wNMl+Hz10T2v09Szh87prUqZAJGPP9m5ubK4SEhAjx8fFCVVWVEbJrXIcOHYS4uDghNjZWaN26tdClSxdh5cqV4vlTp04JAISDBw8aPG/IkCHCSy+9dNfr3rhxQygrKxMfZ8+ele1nW11dneDh4SEAEKKjo4W9e/cK5eXlwt69e4Xo6GgBgODh4SHU1dVJnSrRfWvq55pFjanLy8tD//79DdoGDBiA/Px83Lx5EwCwZcsW9OzZE6+//jo8PT0RHByM5ORkzngioia7evUqDhw4IM50dXZ2RteuXfH111+b5Pv9+uuvWL58Odq3b49vv/0WEyZMwJQpU/Dxxx8DAEpKSgAAnp6eBs/z9PQUzzUmJSUFrq6u4sPPz88k+ZsDpVKJ5cuXQ6FQYOfOnQbbhP373/+GQqHA8uXLufgwyZpFFXUlJSWNfqjV1dXh8uXLAG59OGZkZECn02Hr1q2YNWsWFi5ciPfee++u162pqUF5ebnBg4is06ZNm9CmTRsMGjQI7dq1w7Zt2zBnzhx8+eWXmD9/PkaMGGH0iRJ6vR5PPPEEkpOT0bVrV4wfPx5jx47F8uXLDeIUCoXBsSAIDdpul5SUhLKyMvFx9uxZo+ZtbtRqNTIyMhr9PZGRkcHFh0n2LKqoAxr/ULu9Xa/Xw8PDAytXrkS3bt3w/PPPY+bMmQ0+HG9nTX/NEtG9/f3vf8eaNWtQUlKCnTt34q233gIAPPbYY8jJycEzzzyDnj17GvV7ent7o2PHjgZtHTp0wJkzZwAAXl5eANCgV660tLRBAXM7lUoFFxcXg4fcqdVqnDx5Ert27cL69euxa9cunDhxggUdWQWLKuq8vLwa/VCztbWFu7s7gFsfjn/6058Mutg7dOiAkpIS1NbWNnpda/trlojurqKiAo8++igAIDAwENevXzc4P27cOPzwww9G/Z69evXCsWPHDNqOHz+Odu3aAQACAgLg5eWFHTt2iOdra2uRk5ODsLAwo+YiB0qlEhEREXjhhRcQERHBW65kNSxq79eePXviq6++Mmjbvn07unfvjmbNmgG49eG4fv166PV6ca2i48ePw9vbu8HWMfVUKhVUKpVpkycii/Dyyy9j0KBBiIiIQH5+PkaPHt0gxsPDw6jfc+rUqQgLC0NycrI4+3blypVYuXIlgFt3IuLi4pCcnIz27dujffv2SE5OhqOjI0aOHGnUXIjIgj2UaRt3UVFRIRw6dEg4dOiQAEBYtGiRcOjQIeH06dOCIAjCm2++KYwePVqM//XXXwVHR0dh6tSpws8//yysXr1aaNasmZCRkSHGnDlzRnBychImTZokHDt2TMjKyhI8PDyEefPmNTkvzn6VN85+lTdjvH+3bNkizJ8/X/j222+NmNm9ffXVV0JwcLCgUqmExx57zGD2qyAIgl6vF2bPni14eXkJKpVKePrpp4XDhw/f1/fgZxuRZWrqe1chCP8dlCaB7OxsREZGNmh/+eWXsXbtWowZMwbFxcUGK4Dn5ORg6tSpOHLkCHx8fPD3v/9d3O+vXl5eHqZOnYqCggK0adMGr7zyCv7+9783uQu+vLwcrq6uKCsrs4oxKNam8HwZoj/Yg6zJvRHcxlXqdMjI+P69O/5siCxTU9+79337de7cufc8//bbbzf5WhEREbhXTbl27doGbX369MHBgwfved2ePXsafcwLERERkTm776Ju8+bNBsc3b95EUVERbG1tERgYeF9FHREREREZx30XdYcOHWrQVl5ejjFjxmDYsGFGSYqIiIiI7o9RljRxcXHB3LlzxfWciIiIiOjhMtqSJteuXUNZWZmxLkdEJDm9Xo+TJ0+itLS0wSbxTz/9tERZERE17r6LuiVLlhgcC4IArVaLTz75BM8++6zREiMiktIPP/yAkSNH4vTp0w0mdCkUCu4nTURm576LurS0NINjGxsbtG7dGi+//DKSkpKMlhgRkZQmTJiA7t274+uvv4a3t/c991glIjIH913UFRUVmSIPIiKzcuLECWRkZCAoKEjqVIiImuSBJkqcPXsW586dM1YuRERmo0ePHjh58qTUaRARNdl999TV1dXhnXfewZIlS1BZWQkAcHJywuTJkzF79mxxD1YiIks2efJkJCQkoKSkBCEhIQ0+2zp16iRRZkREjbvvom7SpEnYvHkz5s+fj549ewK4tS3XnDlzcPnyZaxYscLoSRIRPWzDhw8HAPztb38T2xQKBQRB4EQJIjJL913UbdiwARs3bkRUVJTY1qlTJ7Rt2xbPP/88izoikgWOHyYiS3PfRZ29vT38/f0btPv7+8POzs4YORERSa5du3ZSp0BEdF/uu6h7/fXX8e677+Kjjz6CSqUCANTU1OC9997DpEmTjJ4gEdHDsmXLFkRFRaFZs2bYsmXLPWOHDBnykLIiImqaP7T3686dO+Hr64vOnTsDAH766SfU1taib9++UKvVYqxGozFepkREJhYTE4OSkhJ4eHggJibmrnEcU0dE5ui+i7oWLVqIA4jr+fn5GS0hIiKp3L4V2J3bghERmbv7Luo++ugjU+RBRERERA/ggRYfJiIiIiLzwKKOiIiISAZY1BERERHJAIs6IiIiIhm474kSRETWoLy8vNF2hUIBlUrFxdaJyOz8oaJu586d2LlzJ0pLSxtM+1+zZo1REiMiklKLFi2gUCjuet7X1xdjxozB7NmzYWPDmx7mRKfTITc3F1qtFt7e3ggPD4dSqZQ6LSKTu++i7p133sHcuXPRvXt3eHt73/NDj4jIUq1duxYzZ87EmDFj8NRTT0EQBOzfvx/r1q3DrFmzcOnSJaSmpkKlUmHGjBlSp0v/pdFokJCQgOLiYrHN398fCxcuNFgcn0iO7ruoW7FiBdauXYvRo0ebIh+iB1Jdq8OpS5X3jDlZWmnw33sJbO0EBzv+hW+N1q1bh4ULF2LEiBFi25AhQxASEoL/+7//w86dO9G2bVu89957LOrMhEajQWxsLKKjo7FhwwYEBwejsLAQycnJiI2NRUZGBgs7kjWFIAjC/TzB3d0d+/btQ2BgoKlyklx5eTlcXV1RVlYGFxcXqdOh+1B4vgzRH+wx2vWyJvdGcBtXo12PTM9Y719HR0f89NNPaN++vUH7iRMn0LlzZ1y/fh1FRUV4/PHHcf369QdN+6GQ82ebTqdDUFAQQkJCkJmZaXBLXK/XIyYmBoWFhThx4gRvxZLFaep797576l599VWsX78eb7311gMlSGQKga2dkDW59z1jbtzU4dzVavi6OcC+2b0/3ANbOxkzPbIgvr6+WL16Nf7xj38YtK9evVrcGvHKlStwc3OTIj26Q25uLoqLi7Fhw4YGYxxtbGyQlJSEsLAw5ObmIiIiQpokiUzsvou6GzduYOXKlfjuu+/QqVMnNGvWzOD8okWLjJYc0f1ysFM2qWetu7/pcyHLlpqair/85S/Ytm0bnnzySSgUCuzfvx+//PILMjIyAAD79+/Hc889J3GmBABarRYAEBwc3Oj5+vb6OCI5uu+i7j//+Q+6dOkCACgsLDQ4x0kTRCQXQ4YMwbFjx7BixQocP34cgiAgKioKmZmZ8Pf3BwC89tpr0iZJIm9vbwC3fi+FhoY2OF//+6o+jkiO7ntMnTWQ87gTIrnj+/fu5Pyz4Zg6kjOTjakjIrIW165dw759+xpdk/Oll16SKCtqjFKpxMKFCxEbG4uYmBgkJSWJs19TUlKQlZWFjIwMFnQka00q6tRqNdauXQsXF5ffnQ6u0WiMkhgRkZS++uorvPjii6iqqoKzs7PB8BKFQsGizgyp1WpkZGQgISEBYWFhYntAQACXM5GR2tpaLFu2DKdOnUJgYCAmTpzIHV7+q0lFnaurq/iB5urK5R2ISP4SEhLwt7/9DcnJyXB0dJQ6HWoitVqNoUOHckcJmZo+fTrS0tJQV1cntk2bNg1Tp07F/PnzJczMPHBMXSPkPO6ESO6M9f5t3rw5Dh8+jEceecSI2UmLn21kyaZPn44FCxbA09MT8+bNQ3R0NLKysjBr1ixcvHgR06ZNk21h19T3Lou6RvCDj8hyGev9q1ar8fzzzxvsKGHprOWzjXu/yk9tbS2aN28Od3d3nDt3Dra2/7vRWFdXB19fX1y5cgVVVVWyvBXLiRJERA9g0KBBmDZtGn7++WeEhIQ0WJNzyJAhEmVG98K9X+Vp2bJlqKurw7x58wwKOgCwtbXF3LlzMX78eCxbtgxxcXHSJGkGWNQRETVi7NixAIC5c+c2OKdQKKDT6R52SvQ7uPerfJ06dQoAEB0d3ej5+vb6OGtl8/shRETWR6/X3/XBgs786HQ6JCQkIDo6GpmZmQgNDYWTkxNCQ0ORmZmJ6OhoJCYm8t/OQtXvN5+VldXo+fp2Oe9L3xQcU9cIaxl3QiRHfP/enZx/NtnZ2YiMjEReXl6jO0rk5eUhLCwMu3bt4t6vFohj6kw4pm7fvn3Izs5udEFO7v1KRJZqyZIlGDduHOzt7bFkyZJ7xk6ZMuUhZUVNwb1f5c3Ozg5Tp07FggUL4Ovri7lz54qzX99++21x9qscC7r7cd9FXXJyMmbNmoVHH30Unp6eDRbkJCKyVGlpaXjxxRdhb2+PtLS0u8YpFAoWdWaGe7/KX/1yJWlpaRg/frzYbmtrK+vlTO7Hfd9+9fT0xPvvv48xY8aYKCXpyfkWBZHc8f17d3L+2XDvV+thjTtKmOz2q42NDXr16vVAyRERERkT9361HnZ2dla9bMm93HdRN3XqVHz44YdIT083QTpERNKJj49vcizHD5sf7v1K1u6+i7rExEQMGjQIgYGB6NixY4MFOTUajdGSIyJ6mA4dOmRwfODAAeh0Ojz66KMAgOPHj0OpVKJbt25SpEdNwL1fyZrdd1E3efJk7Nq1C5GRkXB3d+fkCCKSjV27dolfL1q0CM7Ozli3bh3c3NwAAFevXsVf//pXhIeHS5UiNYFSqeSyJWSV7nuihLOzMzZu3IhBgwaZKifJyXkwMZHcGev926ZNG2zfvh2PP/64QXthYSH69++PCxcuPGiqD521fLZx71eSm6a+d+97R4mWLVta/YrNRCR/5eXluHjxYoP20tJSVFRUSJARNYVGo0FQUBAiIyMxcuRIREZGIigoiEODyCrcd1E3Z84czJ49G9evXzdFPkREZmHYsGH461//ioyMDJw7dw7nzp1DRkYGXnnlFQ64N1P1e7+GhIQgLy8PFRUVyMvLQ0hICGJjY1nYkezd9+3Xrl274tSpUxAEAf7+/g0mShw8eNCoCUrBWm5REMmRsd6/169fR2JiItasWYObN28CuLXI6SuvvIIFCxagefPmxkr5oZHzZxvXqSM5M9k6dTExMQ+SFxGRRXB0dMSyZcuwYMEC8Q/ZoKAgiyzmrEFubi6Ki4uxYcMGg4IOuLW+alJSEsLCwpCbm8tJFCRb913UzZ492xR5EBGZpebNm6NTp05Sp0G/g3u/Ev2Bou6vf/0rRo0ahT//+c9czoSIZG3//v3417/+hTNnzqC2ttbgHMdnmRfu/Ur0ByZKXLlyBYMGDYKvry8SEhJQUFBggrSIiKS1ceNG9OrVCz///DM2b96Mmzdv4ueff8a///1vuLq6Sp0e3SE8PBz+/v5ITk6GXq83OKfX65GSkoKAgACuMUiydt9F3ZYtW1BSUoLZs2fjwIED6NatGzp27Ijk5GQUFxebIEUioocvOTkZaWlpyMrKgp2dHRYvXoyjR49ixIgRaNu2rdTp0R3q937NyspCTEyMwezXmJgYZGVlITU1lZMkSNbue/brnc6dO4cNGzZgzZo1OHHiBOrq6oyVm2TkPEOMSO6M9f5t3rw5jhw5An9/f7Rq1Qq7du1CSEgIjh49ij//+c8WOTbLGj7bNBoN4uPjcfr0abHN398fCxcu5FI0ZLFMtvjw7W7evIn8/Hz8+OOPKC4uhqen54NcjojIbLRs2VJcZLhNmzbimKxr165xnU4zx/HeZK3+UFG3a9cujB07Fp6ennj55Zfh7OyMr776CmfPnjV2fkREkggPD8eOHTsAACNGjMAbb7yBsWPH4oUXXkDfvn0lzo4aU7/4cHBwMD788EOsWbMGH374IYKDg7n4MFmF+7796uvriytXrmDAgAF48cUXMXjwYNjb2/+hb757924sWLAABw4cgFarxebNm393HbycnBzEx8fjyJEj8PHxwfTp0zFhwoRGYzdu3IgXXngBQ4cORWZmZpPzsoZbFERyZaz372+//YYbN27Ax8cHer0eqamp2LNnD4KCgvDWW2/Bzc3NiFk/HHL+bKtffLhVq1a4dOmSwe3Xdu3aoXXr1rhy5QoXHyaLZLLbr2+//TYuXLiAzMxM/OUvf/nDBR0AVFVVoXPnzli6dGmT4ouKijBw4ECEh4fj0KFDmDFjBqZMmYIvvviiQezp06eRmJjImU5E9Ie0bNkSPj4+AG4tXjt9+nRs2bIFixYtssiCTu7qFx/Oz89Hp06dDCZKdOrUCfn5+SgqKkJubq7UqRKZzH2vUzdu3DijffOoqChERUU1OX7FihVo27Yt0tPTAQAdOnRAfn4+UlNTMXz4cDFOp9PhxRdfxDvvvIPc3Fxcu3bNaDkTkfXQ6XTIzMzE0aNHoVAo0LFjRwwZMoQ9PWbo/PnzAG79Xrl9m7DQ0FBkZmYiOjoa27ZtE+OI5OiBJko8bHl5eejfv79B24ABA5Cfny/uzQgAc+fORevWrfHKK6887BSJSCZOnjyJjh074qWXXoJGo0FGRgZGjRqFxx9/HKdOnZI6PbrDpUuXAABqtbrRbcLqh/bUxxHJkUUVdSUlJQ1m2Hp6eqKurg6XL18GAHz//fdYvXo1Vq1a1eTr1tTUoLy83OBBRNZtypQpeOSRR3D27FkcPHgQhw4dwpkzZxAQEIApU6ZInR7doXXr1gBuTZZobPHh+nHV9XFEcmRRRR3QcKp6/TwPhUKBiooKjBo1CqtWrUKrVq2afM2UlBS4urqKDz8/P6PmTESWJycnB/Pnz0fLli3FNnd3d/zjH/9ATk6OhJlRY9q0aQMA+OabbxpdfPibb74xiCOSo/seUyclLy8vlJSUGLSVlpbC1tYW7u7uOHLkCIqLizF48GDxfP1fbLa2tjh27BgCAwMbXDcpKQnx8fHicXl5OQs7IiunUqnEdepuV1lZCTs7Owkyonup3yasVatWOHz4MMLCwsRzAQEB6NatG65cucLJcyRrFtVT17NnT3HdqHrbt29H9+7d0axZMzz22GM4fPgwCgoKxMeQIUMQGRmJgoKCuxZqKpUKLi4uBg8ism7R0dEYN24cfvzxRwiCAEEQ8MMPP2DChAkYMmSISb93SkoKFAoF4uLixDZBEDBnzhz4+PjAwcEBEREROHLkiEnzsCT124Tl5+c3+ONfq9WKk+o4yYXkTNKirrKyUiy+gFtLlhQUFODMmTMAbvWgvfTSS2L8hAkTcPr0acTHx+Po0aNYs2YNVq9ejcTERACAvb09goODDR4tWrSAs7MzgoOD+dc1ETXZkiVLEBgYiJ49e8Le3h729vbo1asXgoKCsHjxYpN93/3792PlypXo1KmTQfv8+fOxaNEiLF26FPv374eXlxf69evXaG+iNVMoFA2G6djY2HCXCbIKkhZ1+fn56Nq1K7p27QoAiI+PR9euXfH2228DuPXXVX2BB9zqQt+6dSuys7PRpUsXvPvuu1iyZInBciZERMbQokULfPnllzh27BgyMjLwr3/9C8eOHcPmzZvh6upqku9ZWVmJF198EatWrTJYC08QBKSnp2PmzJlQq9UIDg7GunXrcP36daxfv94kuVganU6HhIQEREdH47fffkNaWhomTZqEtLQ0XLlyBdHR0UhMTIROp5M6VSKTue8dJayBnFddJ5I7S37/vvzyy2jZsiXS0tIQERGBLl26ID09Hb/++isCAwNx8OBB8Y9gABg6dChatGiBdevWNXq9mpoa1NTUiMf144Ut8Wfze7KzsxEZGYmUlBT83//9H4qLi8Vz/v7+GDduHGbMmIFdu3YhIiJCsjyJ/oimfq5Z1EQJIiJTun3C1O9ZtGiRUb/3xo0bcfDgQezfv7/BufoxYo0t6XT7dlh3SklJwTvvvGPUPM2VVqsFcGvYTnR0NKZNmwYHBwdUV1dj27ZtmDFjhkEckRyxqCMi+q9Dhw41Kc7Y47POnj2LN954A9u3b7/n1ouNLel0r1ysaWa/h4cHAOCxxx5DYWEhsrKyxHP+/v547LHH8Msvv4hxZLlqa2uxbNkynDp1CoGBgZg4cSLHzP8Xizoiov/atWuXJN/3wIEDKC0tRbdu3cQ2nU6H3bt3Y+nSpTh27BiAWz123t7eYkxpaWmD3rvbqVQqqFQq0yVuhn755RdER0djw4YNCA4ORmFhId577z2DIo8s1/Tp05GWloa6ujqxbdq0aZg6dSrmz58vYWbmwaKWNCEikqO+ffs2WI6pe/fuePHFF1FQUIBHHnkEXl5eBks61dbWIicnx2A9Nmt2+zImgiDgwIED+Pzzz3HgwAHcPnT8zuVOyHJMnz4dCxYsgLu7O1atWgWtVotVq1bB3d0dCxYswPTp06VOUXLsqSMiklj9sku3a968Odzd3cX2uLg4JCcno3379mjfvj2Sk5Ph6OiIkSNHSpGy2anf03XAgAH49ttv8fXXX4vnbG1t0a9fP+zYsYN7v1qo2tpapKWlwdPTE+fOnYOt7a3y5dVXX8WYMWPg6+uLtLQ0zJs3z6pvxbKnjojIAkyfPh1xcXGYOHEiunfvjvPnz2P79u1wdnaWOjWzUL+n67fffotmzZoZnGvWrJnYy8m9Xy3TsmXLUFdXh3nz5okFXT1bW1vMnTsXdXV1WLZsmUQZmgf21BERmaHs7GyDY4VCgTlz5mDOnDmS5GPuvLy8xK+dnJwwceJEPPLII/j111/x8ccfo7q6ukEcWY5Tp04BuLXTS2Pq2+vjrBWLOiIisnj1+3yrVCr89ttvWLhwoXhOqVRCpVKhpqZGjCPLUr9ve1ZWFl599dUG5+snwjS2v7s14e1XIiKyeLt37wZwa8HlVq1aISEhAR9++CESEhLQqlUrcRHm+jiyLBMnToStrS1mzZplMPMVAOrq6vD222/D1tYWEydOlChD88CijoiILF59D9yf/vQnqFQqLFy4EK+//joWLlwIe3t7/OlPfzKII8tiZ2eHqVOn4uLFi/D19cXKlStx4cIFrFy5Er6+vrh48SKmTp1q1ZMkAN5+JSIiGWjZsiWAW7Mk79z9Uq/Xiz119XFkeerXoUtLS8P48ePFdltbW0ybNo3r1IFFHRERyUD9BIjb93ytd/bs2QZxZJnmz5+Pt99+G6NHjxZ3lPjkk0/g5OQkdWpmgbdfiYjI4jW1WGNRZ9mmT58ONzc3ZGZm4vDhw8jMzISbmxsXHv4vFnVERGTxamtrAdya6err62twzs/PD0ql0iCOLA93lPh9CuHOwQeE8vJyuLq6oqysDC4uLlKnQ0T3ge/fu5Pzz2b06NH49NNPoVAoEBUVBQcHB1y9ehVubm6orq7Gtm3bIAgCRo0ahU8++UTqdOk+1dbWirus3L6jBHBr9quvry+uXLmCqqoqWU6WaOp7l2PqiIjI4lVWVgIAnnzySWzdurXB+aeeegr79u0T48iyNGVHifHjx2PZsmWIi4uTJkkzwKKOiIgsXu/evZGZmYl9+/bB3d0dISEhEAQBCoUChw8fxr59+8Q4sjzcUaJpOKaOiIgs3u1LXPz222/Izs5GTk4OsrOz8dtvvzUaR5bj9h0lGsMdJW5hUUdERBbvn//8p/j1nUPFbz++PY4sB3eUaBoWdUREZPGOHTsGAHcdJF/fXh9HloU7SjQNx9QREZHFKykpAXBrluSgQYMQFBSE6upqODg44OTJk/j6668N4sjycEeJ38eijoiILJ6npyeAWz06//rXv/Djjz9Cq9XC29sbPXr0gKurK27evCnGkWWaP38+5s2bh2XLlok7SkycONHqe+jqsagjIiKLV7/MRW1tLZycnKDX68VzNjY24vGdy2GQ5bGzs7PqZUvuhWPqiIjI4vXo0UP8+vaC7s7j2+OI5IZ/shARkcXz8fERv27dujUef/xx6PV62NjY4MiRI7h06VKDOCK5YVFHRESy0bJlS1y6dAnZ2dkN2m9fr45Ijnj7lYiILF5paSmAWwsP29gY/mqzsbERC7r6OCI5YlFHREQWz8PDQ/z6zpmQtx/fHkckNyzqiIjI4tVPhlCpVLhx44bBuRs3bkClUhnEEckRizoiIrJ4u3fvBgDU1NQ0er6+vT6OLJdOp0N2djY2bNiA7Oxs6HQ6qVMyGyzqiIjI4jX1FzsLAMum0WgQFBSEyMhIjBw5EpGRkQgKCoJGo5E6NbPAoo6IiCxeU2e2cgas5dJoNIiNjUVISAjy8vJQUVGBvLw8hISEIDY2loUdWNQREZEMXLhwweDYxcVFfNwrjiyDTqdDQkICoqOj8fnnn+OHH35AUlISfvjhB3z++eeIjo5GYmKi1ffEcp06IiKyeJWVlQbH5eXlTYojy5Cbm4vi4mL06tULzs7OqKurE89NmzYNI0aMQFFREXJzcxERESFdohJjTx0REVm8a9euGTWOzItWqwUAfPbZZ3B3d8eqVaug1WqxatUquLu7Y/369QZx1oo9dUREZPFu77lRKBQQBKHR49vjyHK0atUKAODm5oZz587B1vZW+fLqq69izJgx8PDwwNWrV8U4a8WeOiIisnjnzp0Tv769oLvz+PY4shyHDx8GALRt27bRHUP8/PwM4qwVizoiIiIya0VFRQCA//znP4iJiTGY/RoTEyMWc/Vx1opFHRERWTxXV1ejxpF5CQwMBABMmDABhw8fRlhYGFxcXBAWFobCwkKMGzfOIM5asagjIiKL9+abbxo1jszLxIkTYWtrC41Gg19++QW7du3C+vXrsWvXLhw9ehSZmZmwtbXFxIkTpU5VUizqiIjI4jV1qRIuaWKZ7OzsMHXqVFy8eBHt2rXD8ePH0adPHxw/fhzt2rXDxYsXMXXqVNjZ2UmdqqQ4+5WIiCwed5SQv/nz5wMA0tLSMH78eLHd1tYW06ZNE89bMxZ1REQkKwMGDMCJEydw9epVuLm5oX379vj222+lTouMYP78+Zg3bx6WLVuGU6dOITAwEBMnTrT6Hrp6LOqIiMjiubu7AwDatWuHY8eOobi4GABw9epVCIKAdu3a4fTp02IcWS47OzvExcVJnYZZYlFHVkWn0yE3NxdarRbe3t4IDw+HUqmUOi0iekBu7q0BAKdPn8bTfQfgL399DdV6JRxsdPhx97+xe+etnrraZs6ortXBwY7ve5IfFnVkNTQaDRISEsS/4AHA398fCxcuhFqtli4xInpwjm7il7k5u8QiDgAUtirx6/S8y4hWVyK4DZc2Ifnh7FeyChqNBrGxsQgJCTFYtDIkJASxsbHQaDRSp0hED+Av0f3Rxq8tHu/UBV5engbnvL088XinLmjTth2+/cd4BLZ2kihLItNSCHfup0IoLy+Hq6srysrK4OLiInU69IB0Oh2CgoIQEhKCzMxMgy1m9Ho9YmJiUFhYiBMnTvBWrAzw/Xt3cv/Z1P/xNmjQIHQK7YMVe85iQm8//OeHHHz99dfIyMhgrzxZpKa+d3n7lWQvNzcXxcXF2LBhQ6N7BiYlJSEsLAy5ubmIiIiQJkkiemBqtRoZGRlISEhAVlYWACD5GyAgIIAFHVkF3n4l2dNqtQCA4ODgRs/Xt9fHEZHlUqvVOHnyJNZ8/hVaDZ6GNZ9/hRMnTrCgI6vAnjqSPW9vbwBAYWEhQkNDG5wvLCw0iCMiy6ZUKvFkWDiaH1DgybDeHFYhA9W1Opy69L/dQG7c1OHc1Wr4ujnAvpnhv29gayernd3Moo5kLzw8HP7+/khOTm50TF1KSgoCAgIQHh4uYZZERHQ3py5VIvqDPU2KzZrc22pnN7OoI9lTKpVYuHAhYmNjERMTg6SkJAQHB6OwsBApKSnIyspCRkYG/5onIjJTga2dkDW5t3h8srQScZsKkP5cFwR5ODWItVYs6sgq3D6AOiwsTGznAGoiIvPnYKdstPctyMPJanvlGsOijqyGWq3G0KFDuaMEERHJEos6sipKpZLLlhARkSxxSRMiIiIiGWBRR0RERCQDkhZ1u3fvxuDBg+Hj4wOFQoHMzMzffU5OTg66desGe3t7PPLII1ixYoXB+VWrViE8PBxubm5wc3PDM888g3379pnoFRARERGZB0mLuqqqKnTu3BlLly5tUnxRUREGDhyI8PBwHDp0CDNmzMCUKVPwxRdfiDHZ2dl44YUXsGvXLuTl5aFt27bo378/zp8/b6qXQURERCQ5SSdKREVFISoqqsnxK1asQNu2bZGeng4A6NChA/Lz85Gamorhw4cDAD777DOD56xatQoZGRnYuXMnXnrpJaPlTkRERGROLGpMXV5eHvr372/QNmDAAOTn5+PmzZuNPuf69eu4efMmWrZsedfr1tTUoLy83OBBREREZEksqqgrKSmBp6enQZunpyfq6upw+fLlRp/z5ptvok2bNnjmmWfuet2UlBS4urqKDz8/P6PmTURERGRqFlXUAYBCoTA4FgSh0XYAmD9/PjZs2ACNRgN7e/u7XjMpKQllZWXi4+zZs8ZNmoiIiMjELGrxYS8vL5SUlBi0lZaWwtbWFu7u7gbtqampSE5OxnfffYdOnTrd87oqlQoqlcro+RIRERE9LBbVU9ezZ0/s2LHDoG379u3o3r07mjVrJrYtWLAA7777Lr755ht07979YadJRERE9NBJWtRVVlaioKAABQUFAG4tWVJQUIAzZ84AuHVb9PYZqxMmTMDp06cRHx+Po0ePYs2aNVi9ejUSExPFmPnz52PWrFlYs2YN/P39UVJSgpKSElRWVj7U10ZERET0MEla1OXn56Nr167o2rUrACA+Ph5du3bF22+/DQDQarVigQcAAQEB2Lp1K7Kzs9GlSxe8++67WLJkibicCQAsW7YMtbW1iI2Nhbe3t/hITU19uC+OiIiI6CGSdExdRESEONGhMWvXrm3Q1qdPHxw8ePCuzykuLjZCZkRERESWxaLG1BERERFR41jUEREREckAizoiIiIiGWBRR0QksZSUFDz55JNwdnaGh4cHYmJicOzYMYMYQRAwZ84c+Pj4wMHBAREREThy5IhEGROROWJRR0QksZycHLz++uv44YcfsGPHDtTV1aF///6oqqoSY+bPn49FixZh6dKl2L9/P7y8vNCvXz9UVFRImDkRmROL2lGCiEiOvvnmG4Pjjz76CB4eHjhw4ACefvppCIKA9PR0zJw5E2q1GgCwbt06eHp6Yv369Rg/frwUaRORmWFPHRGRmSkrKwMAtGzZEsCthdlLSkrQv39/MUalUqFPnz7Yu3evJDkSkflhTx0RkRkRBAHx8fHo3bs3goODAUDc89rT09Mg1tPTE6dPn77rtWpqalBTUyMel5eXmyBjIjIX7KkjIjIjkyZNwn/+8x9s2LChwTmFQmFwLAhCg7bbpaSkwNXVVXz4+fkZPV8iMh8s6oiIzMTkyZOxZcsW7Nq1C76+vmK7l5cXgP/12NUrLS1t0Ht3u6SkJJSVlYmPs2fPmiZxIjILLOqIiCQmCAImTZoEjUaDf//73wgICDA4HxAQAC8vL+zYsUNsq62tRU5ODsLCwu56XZVKBRcXF4MHEckXizqyKpWVlRg2bBg6deqEYcOGobKyUuqUiPD666/j008/xfr16+Hs7IySkhKUlJSguroawK3brnFxcUhOTsbmzZtRWFiIMWPGwNHRESNHjpQ4eyIyF5woQVbjqaeewv79+8Xjw4cPw9nZGU8++ST27dsnYWZk7ZYvXw4AiIiIMGj/6KOPMGbMGADA9OnTUV1djYkTJ+Lq1avo0aMHtm/fDmdn54ecLRGZK/bUkVWoL+gUCgVGjx6Nn376CaNHj4ZCocD+/fvx1FNPSZ0iWTFBEBp91Bd0wK3eujlz5kCr1eLGjRvIyckRZ8cSEQHsqSMrUFlZKRZ0169fh729PQDg448/xsqVK+Ho6Ij9+/ejsrISTk5OEmdLRET0x7CnjmRv9OjRAIBRo0aJBV09e3t7cUxSfRwREZElYlFHsnfq1CkAQGJiYqPn4+PjDeKIiIgsEYs6kr3AwEAAQGpqaqPnFy1aZBBHRERkiVjUkex98sknAIBPP/0UN27cMDh348YNrF+/3iCOiIjIErGoI9lzcnLCk08+CUEQ4OjoiFGjRuHgwYMYNWoUHB0dIQgCnnzySU6SICIii8aijqzCvn37xMLus88+Q7du3fDZZ5+JBR3XqSMiIkvHoo6sxr59+3Dt2jX06tULfn5+6NWrF65du8aCjoiIZIFFHVkNjUaDLl264Pvvv8fZs2fx/fffo0uXLtBoNFKnRkRE9MBY1JFV0Gg0iI2NRUhICPLy8lBRUYG8vDyEhIQgNjaWhR0REVk8FnUkezqdDgkJCYiOjkZmZiZCQ0Ph5OSE0NBQZGZmIjo6GomJidDpdFKnSkRE9IexqCPZy83NRXFxMWbMmAFBEJCdnY0NGzYgOzsbgiAgKSkJRUVFyM3NlTpVIiKiP4x7v5LsabVaALd2jHjhhRdQXFwsnvP398e8efMM4oiIiCwRe+pI9ry9vQHc2vu1sTF1o0aNMogjIiKyROypI9kLCwuDra0t3N3dodFoYGt763/70NBQaDQa+Pr64sqVKwgLC5M4UyIiAoCiy1Woqqm76/mTpZUG/72b5ipbBLRqbtTczBmLOpK9vXv3oq6uDqWlpRg2bBieffZZODg4oLq6Gt988w1KS0shCAL27t2LiIgIqdMlIrJqRZerEJma3aTYuE0FvxuzKzHCago7FnUke/Vj5aZMmYIPP/wQWVlZ4jlbW1tMmTIFixcv5pg6IiIzUN9Dl/5cFwR5NL59442bOpy7Wg1fNwfYN1M2GnOytBJxmwru2eMnNyzqSPbqx8otWbIEgwYNQlRUlNhTt23bNixZssQgjoiIpBfk4YTgNq53Pd/d/+HlYilY1JHs3T6mbvPmzeKYOgAYN24cx9QRWSCOuSJqiEUdyV79mLqLFy82Oqbu4sWLYhzH1BGZP465ImocizqSvfqxcm+88QaWLl1qMKZOqVTijTfe4Jg6IgvCMVdEjWNRR7JXP1Zu8eLFYg9dPTs7OyxevNggjogsA8dcERliUUeyFxYWBhsbG+j1ekRERMDR0RFXr16Fm5sbrl+/jm3btsHGxoZj6oiIyKKxqCPZy83NhV6vBwBs27at0Ri9Xo/c3Fz07dv3YaZGRERkNNwmjGQvOzvbqHFERETmiEUdyV5tba34dbNmzQzO3X58exwREZGl4e1Xkr2jR4+KX/fr1w/t27dHdXU1HBwccOLECWzdurVBHBERkaVhUUeyd/78efHr+gLu9+KIiIgsDW+/EhEREckAizqSvabuEsHdJIiIyJKxqCPZu3btmlHjiIiIzBGLOpK9nTt3GjWOiIjIHLGoI9krLy83ahwREZE54uxXkj0HBwdcvXq1SXFERCStGt0N2NifR1H5MdjYO/3h6xSVV8LG/jxqdDcA3H2PYDlhUUey17ZtW1y4cKFJcUREJK0LVafRPOADzNj34NdqHgBcqOqCbvB88ItZABZ1JHv29vZGjSMiItPxad4OVUWTsfi5Lgj0+OM9dadKK/HGpgL4RLYzYnbmjUUdyR5nvxIRWQ6V0h76G20Q4PIoOrr/8dum+htl0N+4BJXSev5g50QJkj1OlCAiImvAoo5krymTJO4njoiIyByxqCPZq66uNmocERGROWJRR7JXU1Nj1DgiIiJzxKKOZE8QBKPGERERmSPOfiUiIovCxWmJGidpUbd7924sWLAABw4cgFarxebNmxETE3PP5+Tk5CA+Ph5HjhyBj48Ppk+fjgkTJhjEfPHFF3jrrbdw6tQpBAYG4r333sOwYcNM+EqIiOhh4eK0RI2TtKirqqpC586d8de//hXDhw//3fiioiIMHDgQY8eOxaefforvv/8eEydOROvWrcXn5+Xl4bnnnsO7776LYcOGYfPmzRgxYgT27NmDHj16mPolERGRiXFxWqLGSVrURUVFISoqqsnxK1asQNu2bZGeng4A6NChA/Lz85GamioWdenp6ejXrx+SkpIAAElJScjJyUF6ejo2bNhg9NdAREQPFxenJWqcRU2UyMvLQ//+/Q3aBgwYgPz8fNy8efOeMXv37r3rdWtqalBeXm7wICIiIrIkFlXUlZSUwNPTcNyDp6cn6urqcPny5XvGlJSU3PW6KSkpcHV1FR9+fn7GT56IiIjIhCyqqAMAhUJhcFy/DMXt7Y3F3Nl2u6SkJJSVlYmPs2fPGjFjIiIiItOzqKLOy8urQY9baWkpbG1t4e7ufs+YO3vvbqdSqeDi4mLwIPkIDQ01ahwREZE5sqh16nr27ImvvvrKoG379u3o3r07mjVrJsbs2LEDU6dONYgJCwt7qLmS+aitrTVqHBERmU71TR0AoPB82V1jbtzU4dzVavi6OcC+mbLRmJOllSbJz5xJWtRVVlbi5MmT4nFRUREKCgrQsmVLtG3bFklJSTh//jw+/vhjAMCECROwdOlSxMfHY+zYscjLy8Pq1asNZrW+8cYbePrpp/H+++9j6NCh+PLLL/Hdd99hz549D/31kXlo6sQXTpAhIpLeqf8WY29qDhvles1VFtV/9UAkfaX5+fmIjIwUj+Pj4wEAL7/8MtauXQutVoszZ86I5wMCArB161ZMnToVH374IXx8fLBkyRKDNe7CwsKwceNGzJo1C2+99RYCAwOxadMmrlFnxep7cY0VR0REptP/cS8AQKCHExzu0QsXt6kA6c91QdA91ipsrrJFQKvmJsnTHEla1EVERNxzv821a9c2aOvTpw8OHjx4z+vGxsYiNjb2QdMjmWjZsqVR44iIyHRaNrfD80+1bVJskIcTgttwi7d6FjVRguiPGDRokFHjiIiIzBGLOpI9pbLx7vs/GkdERGSOWNSR7N1rN5E/EkdERGSOrGdKCFmtqqoqAEBgYCBOnTrV4PwjjzyCX3/9VYwjIvPGJS+IGseijmSve/fu+O6773Dq1CkMHDgQ7du3R3V1NRwcHHDixAls3bpVjCMi88clL4gax/+TSfYiIyPxj3/8A8CtZXSGDh2K6OhoZGVlGaxxePvyOkRkvrjkBVHjWNSR7N0+AeLSpUsYP368eHz7nsCcKEFkGbjkBVHjOFGCZK+0tFT82s7OzuCcSqVqNI6IiMjSsKgj2fP29gYApKSkwMvLy+Ccl5cXkpOTDeKIiIgsEW+/kuyFh4fD398fe/fuxYkTJ/D9999Dq9XC29sbvXr1wvDhwxEQEIDw8HCpUyUiIvrD2FNHsqdUKrFw4UJkZWVBrVbjyJEjqK6uxpEjR6BWq5GVlYXU1FSOqSMiIovGnjqyCmq1GomJiVi0aBGysrLEdltbWyQmJkKtVkuYHVHTLVu2DAsWLIBWq8Xjjz+O9PR09jITEQD21JGV0Gg0SE1NbTBRolmzZkhNTYVGo5EoM6Km27RpE+Li4jBz5kwcOnQI4eHhiIqKwpkzZ6ROjYjMAIs6kj2dTofXXnsNgiCgb9++yMvLQ0VFBfLy8tC3b18IgoDXXnsNOp1O6lSJ7mnRokV45ZVX8Oqrr6JDhw5IT0+Hn58fli9fLnVqRGQGWNSR7GVnZ6O0tBS9e/fGl19+idDQUDg5OSE0NBRffvklevXqhdLSUmRnZ0udKtFd1dbW4sCBA+jfv79Be//+/blvMREB4Jg6sgL1xdo777wDGxvDv2NsbGwwZ84c9OvXD9nZ2ejbt68EGRL9vsuXL0On08HT09Og3dPTEyUlJY0+p6amBjU1NeJxeXm5SXOUUnWtDqcu/W8v1/p9XRvb3zWwtRMc7DgxypLw37dpWNQREVmQ23dBAQBBEBq01UtJScE777zzMNKS3KlLlYj+YE+D9rhNBQ3asib35i4TFob/vk3Doo5kLyIiAvPmzcPs2bMRERFh0Fun1+vFX3oRERESZUj0+1q1agWlUtmgV660tLRB7129pKQkxMfHi8fl5eXw8/MzaZ5SCWzthKzJvcXjGzd1OHe1Gr5uDrC/Y3/YwNZ33wuWzBP/fZuGRR3JXkREBFq3bo09e/Zg6NChmDFjBoKDg1FYWIjk5GTs2bMHHh4eLOrIrNnZ2aFbt27YsWMHhg0bJrbv2LEDQ4cObfQ5KpXKYCs8OXOwUzbonenuL00uZHz8920aFnUke0qlEitWrMDw4cOxc+dOg3XqHB0dAQDLly/n4sNk9uLj4zF69Gh0794dPXv2xMqVK3HmzBlMmDBB6tSIyAxw9itZBbVajS+++AIeHh4G7R4eHvjiiy+4+DBZhOeeew7p6emYO3cuunTpgt27d2Pr1q1o166d1KkRkRlQCIIgSJ2EuSkvL4erqyvKysrg4uIidTpkRDqdDrm5ueLer+Hh4eyhkxm+f++OPxsiy9TU9y5vv5JVUSqVHDtHRESyxNuvRERERDLAoo6IiIhIBljUEREREckAizoiIiIiGWBRR0RERCQDLOqIiIiIZIBFHREREZEMsKgjIiIikgEWdUREREQywKKOiIiISAZY1BERERHJAPd+bYQgCABubaBLRJal/n1b/z6m/+FnG5FlaurnGou6RlRUVAAA/Pz8JM6EiP6oiooKuLq6Sp2GWeFnG5Fl+73PNYXAP2cb0Ov1uHDhApydnaFQKKROh4ysvLwcfn5+OHv2LFxcXKROh4xMEARUVFTAx8cHNjYcYXI7a/ps4/tc3qzt37epn2vsqWuEjY0NfH19pU6DTMzFxcUqPgysEXvoGmeNn218n8ubNf37NuVzjX/GEhEREckAizoiIiIiGWBRR1ZHpVJh9uzZUKlUUqdCRCbC97m88d+3cZwoQURERCQD7KkjIiIikgEWdUREREQywKKOiIiISAZY1JFsREREIC4uTuo0iMiEbn+f+/v7Iz09XdJ8yHxcv34dw4cPh4uLCxQKBa5duyZ1Sg8dFx8mIiKLtH//fjRv3lzqNOgBREREoEuXLkYpztetW4fc3Fzs3bsXrVq1sspFyFnUERGRRWrdurXUKZCJCYIAnU4HW9vfL1dOnTqFDh06IDg4+CFkZp54+5Vkpa6uDpMmTUKLFi3g7u6OWbNmoX7VHoVCgczMTIP4Fi1aYO3atQCA2tpaTJo0Cd7e3rC3t4e/vz9SUlIe8isgoqa68/arQqHAP//5TwwbNgyOjo5o3749tmzZYvCcn3/+GQMHDoSTkxM8PT0xevRoXL58+SFnTgAwZswY5OTkYPHixVAoFFAoFFi7di0UCgW+/fZbdO/eHSqVCrm5uTh16hSGDh0KT09PODk54cknn8R3330nXisiIgILFy7E7t27oVAoEBERAQC4evUqXnrpJbi5ucHR0RFRUVE4ceKERK/Y9FjUkaysW7cOtra2+PHHH7FkyRKkpaXhn//8Z5Oeu2TJEmzZsgWff/45jh07hk8//RT+/v6mTZiIjOqdd97BiBEj8J///AcDBw7Eiy++iN9++w0AoNVq0adPH3Tp0gX5+fn45ptvcPHiRYwYMULirK3T4sWL0bNnT4wdOxZarRZarRZ+fn4AgOnTpyMlJQVHjx5Fp06dUFlZiYEDB+K7777DoUOHMGDAAAwePBhnzpwBAGg0GowdOxY9e/aEVquFRqMBcKtwzM/Px5YtW5CXlwdBEDBw4EDcvHlTstdtSrz9SrLi5+eHtLQ0KBQKPProozh8+DDS0tIwduzY333umTNn0L59e/Tu3RsKhQLt2rV7CBkTkTGNGTMGL7zwAgAgOTkZH3zwAfbt24dnn30Wy5cvxxNPPIHk5GQxfs2aNfDz88Px48fxpz/9Saq0rZKrqyvs7Ozg6OgILy8vAMAvv/wCAJg7dy769esnxrq7u6Nz587i8bx587B582Zs2bIFkyZNQsuWLeHo6Ag7OzvxWidOnMCWLVvw/fffIywsDADw2Wefwc/PD5mZmfjLX/7ysF7qQ8OeOpKV0NBQKBQK8bhnz544ceIEdDrd7z53zJgxKCgowKOPPoopU6Zg+/btpkyViEygU6dO4tfNmzeHs7MzSktLAQAHDhzArl274OTkJD4ee+wxALfGY5H56N69u8FxVVUVpk+fjo4dO6JFixZwcnLCL7/8IvbUNebo0aOwtbVFjx49xDZ3d3c8+uijOHr0qMlylxJ76shqKBQK3Lkr3u1d8E888QSKioqwbds2fPfddxgxYgSeeeYZZGRkPOxUiegPatasmcGxQqGAXq8HAOj1egwePBjvv/9+g+d5e3s/lPyoae6c1Txt2jR8++23SE1NRVBQEBwcHBAbG4va2tq7XuNuu6AKgmDwx7+csKgjWfnhhx8aHLdv3x5KpRKtW7eGVqsVz504cQLXr183iHdxccFzzz2H5557DrGxsXj22Wfx22+/oWXLlg8lfyIynSeeeAJffPEF/P39mzSbkkzPzs6uSXdScnNzMWbMGAwbNgwAUFlZieLi4ns+p2PHjqirq8OPP/4o3n69cuUKjh8/jg4dOjxw7uaIt19JVs6ePYv4+HgcO3YMGzZswAcffIA33ngDAPDnP/8ZS5cuxcGDB5Gfn48JEyYY/FWflpaGjRs34pdffsHx48fxr3/9C15eXmjRooVEr4aIjOn111/Hb7/9hhdeeAH79u3Dr7/+iu3bt+Nvf/tbkwoLMj5/f3/8+OOPKC4uxuXLl8Ve1TsFBQVBo9GgoKAAP/30E0aOHHnX2Hrt27fH0KFDMXbsWOzZswc//fQTRo0ahTZt2mDo0KGmeDmSY1FHsvLSSy+huroaTz31FF5//XVMnjwZ48aNAwAsXLgQfn5+ePrppzFy5EgkJibC0dFRfK6TkxPef/99dO/eHU8++SSKi4uxdetW2NjwbUIkBz4+Pvj++++h0+kwYMAABAcH44033oCrqyvf5xJJTEyEUqlEx44d0bp167uOkUtLS4ObmxvCwsIwePBgDBgwAE888cTvXv+jjz5Ct27dEB0djZ49e0IQBGzdurXBbXq5UAh3u+lMRERERBaDf5oQERERyQCLOiIiIiIZYFFHREREJAMs6oiIiIhkgEUdERERkQywqCMiIiKSARZ1RERERDLAoo6IiIhIBljUEREREckAizoiIiIiGWBRR0RERCQDLOqIiIiIZOD/AeFqH91FKlz2AAAAAElFTkSuQmCC","text/plain":["
"]},"metadata":{},"output_type":"display_data"}],"source":["pp.lf_info(net)\n","\n","# --- plot voltages and loadings of the AC power flow results\n","fig, axs = plt.subplots(ncols=2)\n","net.res_bus.vm_pu.rename(\"bus\").plot(kind=\"box\", ax=axs[0])\n","branch_loadings = pd.concat([\n"," net.res_line.loading_percent, net.res_trafo.loading_percent],\n"," axis=1, keys=[\"line\", \"trafo\"])\n","branch_loadings.plot(kind=\"box\", ax=axs[1])\n","axs[0].set_ylabel(\"vm in pu\")\n","axs[1].set_ylabel(\"loading in %\")\n","plt.tight_layout()"]}],"metadata":{"kernelspec":{"display_name":"Python 3.10.11 ('base')","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"},"orig_nbformat":4,"vscode":{"interpreter":{"hash":"19d1d53a962d236aa061289c2ac16dc8e6d9648c89fe79f459ae9a3493bc67b4"}}},"nbformat":4,"nbformat_minor":2} From 708967b0f33d19aaefba03e37aa8bf28441c1c81 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 4 Feb 2025 13:59:51 +0100 Subject: [PATCH 09/21] renaming of e2n --- doc/index.rst | 2 +- doc/pics/e2n.png | Bin 30817 -> 46719 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index 604dd49..94beec8 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -31,7 +31,7 @@ More information about pandapower can be found on `www.pandapower.org 8 z-}_zHz}(lw4QHQy_E~G~b;9IjC10Zwp#lJa*PlO$D*^xrSg`AH`hqg9L-X}fm!|sIpty(Tckpj>`4v*~u^PXhuxn3SyuyaX3F4`X{(BF}P0vME^*1ewM;q`r@Jb z7{Wva%60Zl{+v*HQE_Ae^EX)bDB$pZTKfA8q5U%c6Y>?Al+bWrrjrxzjF8>rQlT;)$wj*`4|n zXB0X`z9)X)LKCuQb(M25bNr_KOxx@;7;w}Xpeqz3`7$F|_t8xeMs~eF%1U(-&{bx< zZ`3TORS`=d&{#zY2!(hU*0)JyUhHhJ=%^C{NQ>#o$vq?}6Z##Z|2&LfgEZbR6di1l z*sEFi;erk*XCH9f0imz?lwS|y8~fQT+&Z_~Rq)2wWpN6z8$B@E}Ga!|PvfAG?Y-vM4l((b>*76AdyINg{*6nZ&69e` z$hBITRiz%QklaxnF};YzQ~eLkiQOGFxQFdk7wp07kR;-7KtNah-LCX0)<^@}PnB|n z*w^94%WnJOsw6!`z{RCjv!`@6FRW_~^A2uGiz!FA?9AcXVK=+DLq^7P1OBJi1y<@x)!*<{^l zWAq7nQLMzljZ3(sA4brgxJAK?t5u$x5j=H|Gj`)X<=-0)iTMmMKJK_su*{dSt?ckp zOX|%y9#1r{l2f{B-1mPHaN)J*d4p}Ps{bD)4-fdR1de z1T_00iw969;zVOFC)@T%jylI@`wC-jxU4D(K=9aP=ettY3mC&ppmL;bZZ1@yw;Y)!# zqn+J?#v#EBPn8|fc2e_Ig!3`7feStSjTkucqW+gsnt z+{UL4@oqS<>|8`sDdogG2Bbx_u?Otx=fbD@#`}A}`YlMy&JGl~h&$Iyovc{qdPF1~ zd$Pp%jaE-XSA4q^;v6kGk=AMZxz?sFYFv2yC&gCR;1yWU^Hxp56#pmm^Mq`ncBK7_ zr(L`!v;ymws+2hIw$(g}6HW7&S%lR4mQ9YSbJON|RQ3@mIx)Bxv(?T!v1xA%|65rk zgnt)w;Ct)AMM;Tzp3^N4o}a=Q@zs?sZ5s{6V~BIkSw4ueLjKaKfCzCDMU@hvtwdF( zWiFd5i&`5Q0RM>{P6qQri`m}9=!|`#Da*hfO-{LzQjcLV>Kx>YE*k`Y?99%m9RHDI-wqqe9@qdXPiJgk_mLS+c zjNp6IwPTRrL#Ff+bHw%pC{~qx-ptvv=Z?;v4+wo=Kzt7@)7oDffP$| zbKw%^ZxxfpCD-1V;W9b4?c?KBTAk=g7}Jm6QG8I%zN6`fP(1(?H$$uDI>Wyz=StLk z4^7K^nju3%5$=ch3$M~U&K+jcyuG+kTFC=f?2BMPyWN?qw)_vHj=-<~E}}?mzrTZ8 z{x+<$)-T%jvJ}lth11!(4R6T5@5IAt>s{^6h-iJ$?5|>pqYGqks7dpPzTij{{DIn5kqnw<-nnILwV+9$RwJsi+>^#IA__O=Mw;a*5&}5`6G+O8TjHTsOw)R?E zd}jkrHqe|1DIr1o9aY`cr;JQ;>wd<;$ef%5BmX>sAS?D*{APzeSL=VpIrQ%`-Lk!j ztBHM6_EO{$oaW7(flNls?K~o);2xavBNBBOE~9@yih+01D%#CV2L5Vr1{n&_3?x~M z=?I>FINPR&&%yP6k?cl|+&{ibk5*~wlw@JoX zOhGN9(g%kh%$exl9DFWi+IO2tw(s?4+f`u1MIb=bF3;2xv7J#o7-Q5rRSo?V{KIy) zvHOW2^kpqtMwRE!;Z>)fbN}jT6#3r;P*0T7)EXNU8x6hK+nTpats5J~GcyNAf5)5I z@;meg;i6Wibr{{(J{*~kQ4465{!l&i$c@}=X9if|5DIe_-wuyI1?bYBchk~FerRAG z-v)F!{{E4{zvwiimE!PXk7PX#mf#2DO=bm%hac`oG#48h48Of7n_r_p`arnlFmO|r zIJ^d`-sQH__?R;{tI%$PFld5$#~gKiJYg{*<(rJSPc2SJnlxUO{O-aIxOnkj-C>I& z{rCT8G+l!zURN;pHMm`>Fat^1L7?WL!(jlwKa|)<+N3|J#FUlV@zc&L47Dt*?$;C; zFJ4j5 zcL#BxP1?QL`Ak7OZj9EfZF9CBPl{&^ByzgtszPhh-s5EtTjzc`e_VKdG~-}kprAlJ zmJr^Ui5R8Q6FYJ@=3>iEc}Qztxz*4QHXOSO)lTSUEp&;lMM>_Q?_qOsf5zp9WmIw+0tYuI2n#!mEf{p(0_PeUVgWR`;HVm zoM25iZ#MeF_R6MG55Z$D?cE6N<)F4an7?tReQ0ieU$h0`jk)pDK9f(xOtqIjThFNbA)f z>W|3AqeT<^Mo0G(FZat!$q4SQ4^$J3WO8WNd~-YZCRaSkkYD4x^07M3>@lnr0|7+; z^oW1F92gbMdyvnNuyL1eT7G%X`4ku&Zm(y0?hg&TPS%K7m5EdH{pgpE6(hi*^hfTd zrqT@OD_>9E1XP`7E6Pxn* zC~Zhh-8AEkNq#BzosOIGjA8uHR~fy8#GaQsyV-9jC1$E_!4>I{&29AHv_f(2LsnP7 zoRYd_L(NGNqt?+HH{1Df4Ku0aA3tu4>oZjWp^S!nle3d#d0o*vA^MIiKMZ4eb9)io zWR)0URJWM+-Fgv9UU<)+Oq#A0?+bPddYgnc)He1+0$oUMccGg4KO}d8%1C$Zet}Ng zn~|+uZ?$bm5J}S035@*oiT2RRK{r=89Il<(++0US&}w)%w(%aqo^kl$uMX(I;va6q`GZ zM~JYz#6o8;l}PB{n*gOU3(hkHVJfK=@LRUvHMe$tOx)6be^-=nUrcc$t-*hRY&`-H zc0oS8mM&(n9Mbx6W+zUL{Gd+B@aXY14JhE|^-*+8U7C?ju`0f!__TbG*_mu;FvW6? zY%J4vg6q}giO95Q#u7f2R}OkH;%q=dXumElogzsN>CZ|Ev+$mVqMv}Un%+Y3r1kSg zveI-2g`Gw3R+cNGxAuX;{t501!0k=G2`%fMC;eFWKm1eq7ZdmORQ$5i#feV^NYLO; z1c?w-^wpLEh4``-Fz)YVHDXOs#uyxB``_Twb4+i(E~eu58E*e*LXvZ2U2~n@)LNQn zOyz<5U~K`FJW&78t2=YlwYa-_KRVbr(^~Pa-GuU@p0dDaGPOe((p*W|adtInD8HyLsp6i=@P{I{oN9>MqHrGf z{BAUJNvac^r?az|Q?}2?)W)PZPo^njWI16o`>?0puy%TyK$7n4eUwgOybv_L5~S|@Nea0Lqt=OvO? z9g8#s(Fxg8t#;t^2FYK0T+`dSg@BKJinpI&VBi2AY;>^LR(ww4SA<$q%w@c56UFeW z&<%eNi`V4a(9TbxiGrOcX228vxd|)7^19vkbb7*U)_Gw0YCBF&XZe_Qs;kITC~VhU z>E77a9Kddq-&h?+NBi@r=-5r29lnigtWCXVo|O&7o2T1rCmTRByW5TbPE(}x5JIoK z_ojaC(1-E;&%Z<@*kSYiGxLdRFt96c{X}x81W>6B8<)=}(HbKY$m)syuzI&aGW2^l zXj@D@qRTg}_=hkb-Uac~>>{wZhj#(miAIs>2a-8vkLz01TpRtJmYh99H27sPa`~du6HNM4n^_q8?J;7-N4u=}ZB#s+}*A z=UY~{x197bYH@@TCNl(aT7|dTYr%u?xLRAfeCpu9TpJH>%jPB0Co1zck=Sp8rOBkb zZ3r=SoJN>?CVrl8021UU$-hrCfF8F0YT1Ozf0Nf$P}YKFqFMT<0ES+IUybR2Sk%b@ zR}UlnQ{P@al&T=R%IeOIZ&i*t#8iprQGR+QFR3!*hbnE%vFEX5Qcg0rI~<_O&Ffnf z*{`!UhDl0_HD35;#+#d zpT|$nriL~RX2a(p5A8Gn%uO{om1?MPzTy8A8&{NEpy?z+^Hf<#=&otQjZ3O|3#vff zLbk@l+=(J1#TVo_47ik@&Upjq2-(ErtdktQfOm ziXFoxCW$6Zv$87d=Ea`Knhf4`USdHrL`cNe7N};t1!9GpLyAg_kWw|j3KpU2@jeGlSaj6BAD)(>>~?Yvr{N#VcXM&Jk{w(BTFkgXV3lkrRJh;Kfe9lU3$`! z`pZkI7m^cJFr~qZ!_FenD@IvV1yjMfWv*&#c{Ie$=3hJz4E~Epc?*xBi{X6Yil}<) zmO_!2vuSTa!(F1dz!1t?u+l_g@3l;0g9~Br#?&mAN+vqy2GMo7CNC9wOgTfjhtct` zv9ER-&K0tLj`3p(O5EpkeVgG9pxAJK5F85LT6TU;*Gr^hL6+hkqEjU7P3%qDOk7~L zUBD-3Q>&qkN@D(Hqwy1w@3Tpf1X)nSe^`~EFXk_h8J5uz)Yk~KQuFjJcU>Ed8k`076@O|C@&?b(O4T)Tt4hxA$mvd4pM-{K<%Yfcrb=EA zF!RcRMJ$ih9_5XKm8F(~doOzI+4E=Yj@^;|oD%tM$A}u{9{#6JhOlt+GxKQaGH9A@S(gB)it444+{rQUKx_R`j=n^&U9-E~R zp-uoWte!B@X(GUZ!^bmTtrK+ULCcz?<=I-)f7Dr~R>)87=Yn*r;>9e#hn!h&t?Fse zvUDDI{VBPHuAH7@Pz4;Jdd2;_$2s4GZ?{M@U4*rxZIWVIvT!wV!C}KQ`&(7Q*M^T0 zw3|?^s?ppZN4PqO-EcQ)pVn~GP2K*7ei{Cv-}i}iZy!t7dBAJnmX1|jZwI~ZWHR37 zMO?7Wg?M?DG=;pSgV~gT!pKWQvEbW}D!R@B;DNSUu8qXVq-fdpPEm1K8HnWj#=U1m)I!#02m(C$lklOg*o|k_PzLfl@I=|! zN|*c{Kv|&DBoo}s*f?2+RPk=GW#c^JQ0N*#tPzT{vi^HH5pjqfZX4I-bKm#6LJi!? zPM7)|*8)V~Y-^i{tiMBh4-$#|Bf?M$^7ZiWwgj?g|Kh?^oOM`SG+G0& ziYV8H8foAY`$WNK?(q5$f>eg&UIhOsI<?>{_fsVeu}l^1dlWDQ2K?x&`Ba@K16f0vuyq*JpN zgB{|$a>Du4!Dd^=OJ7S_StuSg;G?X@l&C~L(hvjOlFHZZ`PR?n=lSvtbVY$@QyM_h zS2f_MqVprU+1v=G;l}U!aGgEe?3Tf}C99x4r!|)W?z@)7mbwuj!Vk5ivx>qe4*S={ zJFCM{XdgpHX@I~PolW#6t#x6`S~6bx@+RxK$86ECT${hj_h#f=ieqvS!-9~&D3qst z*njj`yi}}R(YX|_QVY&4y>OFJpv6iRCVKtVyp8{|Vu*3-6esmd= zA=6J~TwXd4(=|(cmD*SvLf?R(8;Y2$79?a3MY|)ne&*0rs|qlm5Jf|qUwQK=ebI%C&Nw>V&j!7>_Jzo3Ea?QgqBOTh^nWnA<0ihcDt-fY zH~Jt}voxp6#D}!=#h%Dd9R3V-MD!8rX$(m%hZCcqtM449A z{kUUHd+Imuyi1JbYb|W5xht!5wmVD(Xzioe7*A1w|)r0?RdC^KNbw0 zlrg=XcY4z>ntE=Fj%p3}gXl*p%!4&Cv(9b;@Jw=!#MG$=U5gs2s-`+;+PME5VN43} z zw?3X>Es;7DDedr&b!fhQgUE|o7d;~70oFHqHKH@sDfW~<{^8;Nq;!q%n+!#j3MZ>9 zBfha&O_8uUs|w-Sb)$gFEe4kgnYVq+)7I}4ACe;&GI_&?S>3k8unQ{+N9tp}>(Uqa zx)GP1GGi-n4?{NbQ~Vq6=vb_c>_^FOy%coNT(7p>-tL|c#N1;Xr5)}DEKO63i8x<~n%tuMnOWefGL zH5RB57-s4>rzyHXvA&i6F6l`-)@C<5$)bcafO@SIKbb+g+czt`_CF%}SBURh);d{} z$2q>OlsVlcmu|u>TbwG6UMkIe@$Cfyp&)JXtq%sTg38D3vXhO_D4b8XK^vs{0`f19 z5Od(6L`t!5P62QNBs;GYBhGT~X-O}MA((chd~(dm2-w6tzn`ZQ&|)sQ z3K`49hEB@7C-ael%ludx{#8wT^6JNJ(+jZAZf=NHPn(-wWS^dSNAbj(c%X{zWXsC3 zq3?YGGx-$5#?D5^mN1=T%MODaIKJ85$0U3~npI$`gA1NlU|gAs?Wg3RzZyC>Wcgt_ z>66@zbNkia6Egu)6)8R9^*Y8MaroCa?#aVhnew3CN~+Amc)_Z-mm;gbFRLm|-kA#l zM60AgGTIYh^0imjm88)tO;bk!PqP10*c1O@8m;BsM>e(3nx|%&*pJQ~wePk3M*Z^p zU>pGaTF6WsoFa`&h*Vw1wJg_8g*#H$eJ7YN-a7W=Sv9ygH#|D#ng}*`X$%KpG8~IE zt?LcE8GNx?L$do_e}>mk|HfyurZw_|N3VW0WX!JXBr4XnT0DRKaSaT7fJZX&v5?r&oVCbq!%;@t;d4_odM)#Y z{P4S@1Y?0~uJ#cG)tH;z+_lBQEL~E3yq8OGCXAUc=*w(Xbq(gCEeZD5FcrZz^2^Z4 z&$J6U|F!f!_ab1y8mNCvnMZCibLK*7ZOW~?>O5_icYh1*zSLWll+{VxER=mIi}v*b zrFq-G51mG1^W?qZ;NmC)Kiu2&l(Ak#2{I)?qdt>#UCc!vH*g9!#R*)&%xh?ZY8Wd& zo=S%oJT|c;xY6PK?%iC(pj)(xp^o~==Wi}H=#j+{U4waj51_FXrWovv#Q}+{UW@t~ z0k@R~+_E3Sm!% zo|<3YW%JK68EhVj#pjGpUg$h$ z&B|J~Wuq*f`bq4Mi%pi&YJZx1Rt_ZHSw$6zkF94HY%H-k4SL!jtRm-c8tuOC((wco zRv)s=-L+1as45jdSFo)z<}KP?nqZ&9m!}r>a}%MhAby#2LjFWP>BgD59&gM&(#dA6 zxTB8>O&J&~j`r2e+Vc&v5o6lBI)duvcSTuCcMsuFb8at)hs=66<>12ge zD*-oY{hN&ZBW#SYtaz^9vh4pMVMy0I4T-v7E<>S(vC>0 z0ef9Hz+4h>@`zH%R^d@K=i2+^tfE(*p2utAI|^{|NC3&82?xzv{bwcVFHyw3>h)Xw z1C&%(noP_bWMNj_7_5Yms#Kl%mS0Bqc$C$Ec_n9bz2k-+2jn)s0=&FZ|$gKd%Tiuf1*uZ=9 zzQPNV*B1ay)`KC1-5GZ<-a3x2;>j=a()rslAY%gJ{FwpcNmB)Q$_Hr_PJVd}RR5@_ zX+rn1j_D}!>&cx~(;dW&VOeVZLOW|5?=V<*;6n9rv1RA~-`hgyX1nub*7yJMwmeSO zpLoZ3Hx3!H_yv9!rhAw&S<2*HqM1=RCSEPTo4JRA=~W%Z;@qFp=owM|zZgjk|67_a z&qKtc^eJ$S%WyZyxsP66ukyxgPX1b@j$SlR^7t6x4KkVdKa)(GcE;)4|Lu}_Q0&WY zI26#}Eq@_nBnWi$-n^i^ef2fKWa9oD9SunS-sE_N;el?kMM859^uvBgFCAc@DIu2L z=6!kP(@4!uv)DpY;=EFTTz8Gg`o7XoI{gqh-G>yq7f26Lg&>B>VS*Ql(+)O6rH+L_ zV@fVKnB@$YVUBh?4}rT}lP%0Qd|=#}qw~_UXfqR;8Vnb54pfg`P0bnnOVkHkb}Edm zh8JG%`i+OoS|)^Sz;ZPhqgn~y_iCKE{o-*17+Kd3TX?2w!CPpCg2a;nk2uB6W`oUp zU1CTtb1%(mTWVc5Ezy&D)zwB4O|ScHqUPRXm5u$P z5hZ)~^~mG;ODSupQ zF%vl`Q>*B9r$oU=(0DJFPotlsUapL7;>E5oDc!N&LJY^f&%%hIY4o{z9w5#wwZxps zY7r5tMVbz|JO1o&B79sag^)G9blIh1QQ(41OG}atS**Zw;OMJ|?~`sW@WIw=Xpn(` zor>W&;tT#XvsHdRTDDr=9D}Nx(8a~wVwE@7UN}XdUpJdE?Jq8x?8~bhhxp|6c4RDh zK!NX6zG8^Q(NEBS^X0Ho@j-U{KhC8PvZUs{-e5Adg%o5+8G$eJ&H!U~k$1I1ci)sh z$oh4ar)%1d@O;|;nq)8>_8_YKoltsG4ts(&!GsIZ298sdkCYeQ9FD}I){%G~)fzBM zagKsM!X_&|m3W=8l`mKidZE?D&9ri-EKxO|Y=#7xh&T#(>D@wb+=yxy2ejh4`IpTA3I*#u+ZU z*K5gI%)W&0c15;o=|xKI6kaj`@Kz1 zSDbcFzv_p^xlGiAKk1Kw+F$CE2(J=e(lFCLEs~Mr~^|BKphuzeYm`{wH2c^CQtmFiej%W+e9$RwewCDB#$v2 zg80Q71!WUGXEfm@F0T($Nh+nOeNmpDzcT?cu{$6=a}_N)uiO7G--4 zLIm+ke)Z-MTFq(q)WC|9YY3*gd4%p9qx;4m%##v}Ea7C-uhv*qzNVEYSn9~zzUV_= zG;XH*e;q24%xJvNAm3v7;l7D-kh0)?MHe0J`OSOvj#e9N#pS=El<`?Ew*9mx0l7%QZPcXmUVf3 z(#!AU@bV^o2{7E~@{_UZA9pi45(nK1Wsf{-y1$*T&NBK=I45=-UJL)QqkO$(o?KfG ztuiPRf&vO1v5GrOS2h4zg8~m`^1X#V=nM?!U*|7o3&Jqia5Dm*n#l*~ z%Wk*zyJf~Kx<2o)WsLlhPK6rQuI)wBVdV+E+2*fPMimKK$#T@&4;tXPBB(T6zH~6- z{LG|IY#Og#8(b`1gwVb#j-xkWk+1Rn|Dc1wuB`B3hEHqX+Qb(JjB899nzUC9MuWG6 zFt?z!b8Agoc{dd&wg~gPHf5C=-wZe4=hYS5KORP3FF&%6L*n-G-uB4$(A?vbAIVQ3 zF<@`f8P}v}f+{MJTI9EX#md*QM6oVbz9kz{G4=daeRxwVIMre@(=qDz$Om{Cac~^C z&AOoBPH825C%;jQR55PiS>|ad5<7B&lh0$%s3ftE{1lI^chV398#rHkMOw+v0#jV$ zpM?h{>u$h!ox#P;*22M?w30t{W15RJIz1_}SstB@n~d}73Fw2^e2=l!Y0AJ#)#j@N(sj?UwT>RWnI1Yr}u=g6w zJ`NK84D3}E(ng7v2O9k@K10qW>VX`&NNuHEer9!8+TT^2z=+t8Ky3XYEH`D z9bFW;BpFaAyp{qAFN&wlAwAutwfIOOC(4X!4X28F_rCu;=`NnU+TryrTED2%TVF0t zpCKP&RK-~87Yojo#!p+!TLsIqpP~X)?#n>#((X-1>ovrZ%$^q|{N-kF?_q-dN+NLe z>GWwksz4lfRG@0~r!rg~qjZamF4Lm>$rB06>s;XsciD$PS$aQwo4HH>(k(CHtD~{+ zF>jt$jPTzIIunY?L?IYI%xOKHZOe`}VHCzwivn?KbR7o3%W=I>>uhs6WtNZi6sOB# zC%|b_eO$5cVo%qTs^lOoL0*kY$#Pv6|$6d!z+jXa$pP&Fw z5LvOcPy9=XaL@cfP0`0lDSSJpZ>m4M{ zX>8b){xFlJ&KQOd?Pvp-;LHhb6;^)oPi0aNh`(8d1TXlIO>7-VVjd&L%|zVzCpfQ? zh){$A1jm6_BdOgJEbZ5@9>qk?sFuzd5~i|vFnayvPO8J+tD`dFGcL0pnF9@M@fb6; zx6r(kEzsBjYbWqUf$dEq_yQ}V4fr;+LM3Pj=5AW^wo@(V;?wx-gVdrP<9-uB-yLjY zJqNojtM2l8m=LN21t0RGU)Ajn1>B9A_|NP}9242cJr#km2p@}&E2rg?a7#dCgWt!F z=@&Qg_(EE(4YK6pb1#^Rh;?B~C-On@?=3nqwj#|xPW^wm+}2xT)wd-1$kGE4&^L?phR>_Hr|nUqhqw^kAMD zrR8q}YwNxhSgo>*qu~xeRnj;JKi)WAG=Z5Es1N%B&l>OJB0`->A(dUT&tW%zhV$HwD|0)zNR@_II=0*^%QaI1 z=s62BpA;`DLcpKKRw*}T!QG2}q|0$CnK>#hVqtS(D;tFc%Lx@N{@65|5spd;1RJY~ z1pAABP+X567dXltH>DX`P>e>SSnuS_Q3fPUnJnkun)asLRH(cM^vsN?T9@12n=1}4 zP5IAQ*!+jIpBA$I;X9NO1T6HaqrAlQ{dG;}=3NH_Ddxl^A*g#74$1I$Z;o&&5!22BTID?V%jiY??!Z+4W|3DK8ee+>aAc{%WrX1aE95;pzJt zPxWL%V?;Q!hI7kS0t%1J0K>q(FkFrNB_jL0+=l4&aTFUOvQi+|eVL(>yQH|u=1U8g z$C_`GNQM0f?WM?8;Z?Bq7;3*E&tj9zBk|EEx%pyx(1TLVS7!&{8KfgZ>iVO__02R> zWfj+wWmWa5hxl(lr4M$^lWKLwo+?YB>GAk(Qq3~*&ZLv@5noTsF5VYOrLRMNd7gU~e@M{Cj5M@P6xwr>>%3|Ed`cSAJl3gJF52DaT&MPs zY_o$uhRWIJ%VGDh+?P?Svl`z)0hbl!aqgo0^v*{Yue;E)sBkspJlJPI7zo!< zJ~kxpLg^JW_+|b5I3siBecY1;_LfiKp0`v`-4mO>OqNelXQ_eu8q{eKA2O=G$R#Ph zit!Tj&8@ZM%mQhhs`hW*@wQ*gE*skryR_0hqZ_@lVu-sOdE+lZ6KY?v%=tpO1j=nV z17Fqo0^xetiyXe;=tnpgU$euTgMkJ)IvX}$A^E?jMJg1Py0n*ok@gba+OT4jj*haz z6Q3Ui(SyUtiB21B#L(5@b<|JwH(`9^9+pBO_O8FGuzEl7+H^UJS*1}}{Gf?Y#6iG+i~+*+)4cC7Q{2bXw23>N11#o_bIJ;3JsfV_T;){{ zQXgHf1ZjD@RPV;6m#Tg)c5YGlh_cvdu-(TQ0ZNS7d5Fr%WyIbhAGYMG@pwLX3e&yB$#;Y}L)<`BDKU-}#~K z&uqkL*^X7<^itwuF+ zbNV}Yb+8d}qpXD)P?W}B@~+jRQ%J~T#rFoApt;6veVu-;wg3?kcQ)ZtqhW4;f*W?G z#L@TNtr`$#f7QJ$i??2*1yZz=hiju)Ri&u{KdjE5Rc!e=L%L`MAiyvNv1I};@ifWZ zCud(|H2#Ff*uNuXc3T02!&v#X3Q+ay9i-OgeXd?}Lun$gU&zk-Q)tBPdC;FqJ4nR! zP2Kx>A_W@(a2ZH(ZD1^;<#O05M^BeuX+dK#ZK7dJDRA?X(eb-cxkVb`7e zh65HwvQ{z1sWdi6~8f4wC za9mrXeStrHRsqN>zRRRQlug7eFFC`2 zpRHKIg95&Sou?q>WbH4>BTUEr=$nsyW34PW1C0AxWUaDz^(H>7$J2FfK6j?&xf{_gCf>H>RBBy%gGLdN$6h2^VCvIE z_!gpvSiHUTlqvBEV9Brz z`Dl!B-8|M zR@s(f=?boUNv_be@Q;QG%%A*MQ(&jyl0`Z(`?V6hxw#pwxK3WSirwJN*ol|et)QpC4gHE@0WPD zR)KVB6l3z58ZBZp%4f?g_6d-U!)GHGEK;m=WV_2KI6#&rnN3w!`)G{{vaHtBW*-bfW( zZ0Ry()^y_W#vEmw(`7Wp^u7DY+3s(Jz16*d+NuW(T{ch3d7T#?a7*qWcz7M#Jit0fMalb=Keut(Q{m1LoR^1nmlUm4O zV5uzH)5FzjYMU_YQ;$p*Apn@*Y+!R1|JRj|SO>Uar0Z8-m&-O%;d7qXa^`++Lrl98 z?X(6XsA7Z>{qccXdhWU}(67 z@I<5O-|z7Kk#7~>rN%{jimN~*WBe1FJW3t41S?$Md9b+2ej0_ zR$@Wj4dfON8dh~)c2^KJl9>W*MoPt^?nPdj8*t`x>Y;(TY5(x;jS`4S@>mnkc zb`Z`}n@lvWhyC@4@1CKnZL8MB(Q$`rispvybO%4Sf6xE;>vYCQYe#QhF+nUIyG?pR za_hj(i(mbZqp9d!sJ<>jIrdOEDFjC^>1J37Gout^TF~0nxjf3LGuoW$AC`P?cHm0x zXFcHZMDA%uMlSJP==9`pU>iN~UOrAqxmo?I1Yd59J)$^e{a{gXSzXziW>vMVMlwcm zQb+cI>3|6~&-lx1?%*;AIZc~S<;ElsKamZ#o%sHy#RF)DIMUA%V zW#I*Y`5?_tw$mXFZ-3#y@zol^_@`!cysz2j8UzS(zq;a!JFML$@rH$K7 zXKd}5o6n7PdDU)Y%e|{^auv=J+Dt`&q}tke8N_(3++Mt7)vTgNRbHp&vu_=hz(lAnQgY8E4=QOznJoTdG)vS zk+b(sAeK?B4et?xI5yXEt=W66jEt$uj!2}aZ|*#khudc%`OyzIBVfi>p_&O}k~5@x zAWj`qM2}&mIuo8WsR1)q6c&3GHjk1}75Lm*7F@GlpOVmLxImt~0MFh|O88L1i#X&h zixF{c{Ti6NzjYu_<%{Ma?O0w?&?l>txsEKy=%{#_L_b!W!(FLym@45-wBdYRy$di3 zs(14qVBWv!!nkeGvSHn2?CsDKDU5$GL=aY`2*K*qKf zTE1d&#iPPIqdd8_C*Ft#IKFG&PJJ3KXve@mq5yiIl4!4OJ+_>wJb=EL_K@OZ9=;|i z{ud>o7k|+AW-mv55a8<@iNH|H-ESG`J#+xCkgZpOZ8NX)yyu|Y_NcyN-yJ|&$ z)3}tLDjd_~yAi|veoGIv#%*~#d&fse$G;~SI9tH&5l)M#2M;?rF?X<6k=fWCQVyTh zKF8#v+!Yoik162)ZeQ!g@ob-d1Ec_%}zut#KA^&eR-#L znB;nb&`crs=-RQO=GBsFTZAR=HRytyUft(2{L?D-sS=)ou~@Hb6S=X87s22O?SEbX zIsq}WAUq0(tTT}pQrWyP59|W{-W)Gjvde>I-dNmSQIUiD8fzjIhozgTaSX3d#~Ui3 z;bdwGBs}@#5dFqM@63}pYJl0sll7E`f?-&RQ^F_ABeY`02Hx45f!>1K(e-m5lHY3k zK533w3Eo7$-{Wmho{Z!%!~R!Rd+r>wy0GLYW^;Rk*5dl=2?>D+IRdm-FBf|~+cY+u za9ye~@>xey0SV^BSmee&RUtif z9iNnhO;HJ9e=o~AMz9D`Na$w7;f)EY=yG;u?$mT%jy@q?Wkrg#noE{W)cM)J_Wq38 z5R+_0+x}>#(qKsw?9Ra(Nt(6H|JkPN8BVvdA?dm9Nv`=U_p$ET+Jhief z!;c0|i|VW`6a?K%3mhvKoze230=cOB{KpZWJs$nQLRrLqW*a&9^0Rh&XCp_}ql<*s zwdVf<8TedJ@ZwC7e&O+}OTUcR$$EFmGeOYzmi^sno&8oPw`XU%*Qm7@l-oB*D`Uih zq=6O^_YsP}<9u$8bM|_dvyBep43xZVBnob``dsED+k78VNZJHcaAtYq0O@s@*Y!d@ zbkS?h>t8c>ruYR10BJ5)Xr3M6opHg(4xS&T&)F{SM=!tBski%d*g2dR(2D8x|1kDe zVQp?*7bvd9-6<4zcPj*^xVshi;_k(v#ofJlA!veYaVhTZ?r^gA|Ly0T%X9l)B`fb7 zYsj24uh4#upQ=0zK|-L1Fr~@h@}$~5_djp^gGtkFQ1UAX)k`kh@nqqH??|U|3bGe} z40tcNTwb-I3X#_L(OmdW<(|I14B^}jBpj@|oM^Eyzp3R5LBqR5fuPrS>5k`n+(6Ex zUBrwzw!5bwBtefS^{S2?C(!~^>6pEwJWSf~?CA$xg0zXBGJiY=J#^oDiQ;mLRr`py zI!Nxxk7aEfzFYhU4VKk_9#!$ZAH`x+ZG}gfc$6J!D{c}wh_OvCU0&Xs>1o6=)m@~N zpc@@h1{%Q=E2#C<9`dy6RURMCN$#G-KMZksZ#?7e0teVZJ@OiFDJynwW0^j^qE6mw z=6QJ_MjzBkL7g+Vq5z%7=jaRLm@lYpq`1*XIXG&9iX#Ss8x#2x*x$428Xx*XG=*wo z?(E>egI(W4cHZLD&$WU0;M$}TV|!44mi`jDNzp=MnQ_8ig$-pO0{vY2kBI;>0;3H( zH2FNycFIQ3c?;AnOW(9SdNtKDYn7ZXw=?Vj4R<);zW_z^pCD=5v&SGAi#_hVN! z(W!lDg#8EX4R;rdtuU-pP<0dsEKr2HtkD>VIyVKk#oiR9o4(Ms8B3^&^H+_>{^VIq zsjaYpZ@;NVY4F^wqbj$L!C~|tgoT`D>XTwP)) zzJj~+90}2j&_H{5_RD6s^}A_YFUVU&5hV)-_nAZ(bhl7!F75>H3Jo`oJJn*vqGTY# zByR%h`s7Vr;k6AgC4m3*4d*Wcd0e99|kJkYC+?#7{2x6SO^W(0%l~=UAYhH- zp|izgEniy8Tbu^TK&W^jWZzbWJElb5DDZx1*JYDr0y)5_<#{V5hgi`#>Y)bquhBPR zqF`|@s zXlPeT;uue7lWGcm(4EmiogM+$b8;nb)5EZ3s!5Z!OBUH)@|7hm@7@+?!iv*HL{YUY|0pw0*Woc)U8@USg;- zW&F+VwqJ_LPkByO9*>=J8(FES*2PYXAJTq~-uZe^m4rsz89aOhr^nus_2z7i;gEEF zGn*M=3)!jw2XZrRHJhx2iSPdq6tUuG+!nu&_e81^Pet`B9uah3joYl@drwkGSkFjp zrSY*cQqAVe#;=(sy0K7w(%^I)1+28w#hx_r>#z$6*#sF|rhY$mLEgSTZF!q4nW};e zE{lobRc}`=@KxX2LtaMRe~ClA&JhQ%bPtwPW~snxD%)`+)50bl(M=*q40KS&^D(R6 zmC{S3_1Vu6Ckt>lfg@~~Rg81Is`zt=?Qr=D-wNjX-c|_lCKrVFaJ+m@_cpUV^eew8 zIDb@vK&tI~$ag}#3Y;%rJ*a4c7WyB=k-op}(Ew39A}@Z>EpYiy=C}6a4QEe2AvnXw z8ikti2>T$8D$u;^Zva>L+nzXG&7lX2K57M+C-vs z^WKVjXvGC4Z`c-o{mWmxAA4K|QqA~=(IRpn5$>o&aT)IGfvBC% z*7qb|qa>?y!n8gxlCs*NkCOE%>c~V2o1W{u7JXStC!TYVP0&tfqM9W|b8O^jp^kmT zTRwTJyFsLDe%-(R)yY9&#e`Nm=VEZ+-A|ZtYhO{L9R{}@%}wm}_70){Z2(G$n#NQ1 zUduBU(2A7b7q@(USlcp)`i7nfoKE0oQ zEbp?5mX9T#Bo;7gwd`bPbmBxxTFaAPG@~vUptkrJ3&Dlmf*oPJi2NJ0Sbg_%c%h(v zdff;AnHjdj7dt?TTA2e7(-H-9vBETh9H&zjsu?fm@@MFBgIqE4j0$9kRjBg3iq|gm ze@KB9;ZLTaoKe5^Lc2+m8xu4-tDL}y!Ow35X=_q2q>NWDK1%h+zio;#1V617`HA7* z5zn!D%yWrzZH)NUw)E@AJjJt~+dA)M^Qn{zZ2~my&aOk(YH$ z-x;=YDmYZ^E;WKC?SXhb!THyBkZPH9EsHdA=A~0#)PeSn(+`A~Me6>+?7!^W)E2d) z11;!pZ}25bwFH~2!T%6*t3vejKq#Yyi$B@~w%e@eaG{W;Ay*PdvuHR9@~en+ac51n zhluPPB}yOJh3Z_6^+~o%l4sxpg(Q{=q^PiKE8*j*z4L`s<{zh=NCH+r(y=J5TscI1 z$SnT4vl7jjE4~sI*B%)wK&72{(fFL~MV0qxXmtbMxgS8rO#CzH zdQckc_^W$VV6!gpCq__}={eprYDCE==5ZNK$Gon+%b(ltz6uvC9mhU_--P@3Y3~hy z3@l1Hh3X)m-PwnCgC$Bo$&H5#_b`Gx;`!IrJZQ(P=C{3Omkec60xoSBS76PkVXx0b zAUC~?-d^g#OHU6n%7Q9y?K?B$`-9O^Cp!yZYrpF)tS$i9D8>q`guL+@9pK#h`L z8_YQ=ISyW16g|u5=72&Qce4qD z_4QglVS6;Eh5If|nhZ84z^JL*Nhjd%t)T=Qc+Oet9JsV-l5QatLrgeL$l>_pieOl&QI>846-J_^`K}Q< z)!x6YHoq(ueniSA7`P3e!^0%KIwjP@&a z`j3F5epjHE0Ml*CK$7t*5k%l-WAo)cT>So8#>v@wA94sqR3#H3bH4KWov}rY*Z357 zN{+_pei(Hk!1K9aq%hjz>-{;))(Vo(N6S=k#vu~MH=$Aevvl}?KDbE`{IMg$!Ru?= zDnW}T^`3HEp{sQ6y!A_H;SB=)E#HIt?p=E({_{5U)pqu|jJw_CP$zg13h-76s$TKX zcFVhr|BE+>LEvupT3cWKf!Ec?RczUXsg;HdHW+)COZbB_sQmT5prORF8hv7}Twm&j zobtxuUAt1)=o5hGr+V8C#St)WOl9J-!L+#Y1=0p@u^(Qy$U3-Pt$;8eocJYrYfq_=O_DPjK709QY66GA!&XB9N*V9Ua|)!}|r zj3iS9UbZtJ$5eIlf0^Mf)4xNsiat;Yk3lXqq&E+b_O%1l;BskYulMO=^WxpSh^rP9 zYWug{Uh-Xk_ksVWk**FtjLW+i^yY(4!8T47{KWcvDYgK8A1MHzJ%51QBJog~Ki7+r z$L0fWa5#KdAta%N&tCKTA;$V5gh9A~?oJ4_n3*Z5+3p}CMGSVR0;bKd9Lf_@6EH3TDK%&4`Un$~~C(?$ub; z4_cc&O?SHE&kd6h*>fzHBx1&2^E$6g;aK~#8j{Dik73|pFt$>`D2yC*ky6`K>}eg; zpTgAc-Ga~4DL*NsVWVFoM{$t^-bY!l9Jvq4VxwyBqZv5=IH0;j-voPz;=_w+Y{VMO z?EbAM(XFw85k)F9LnNOK$kw~I5tF4tl)K{lR%U`fer7`<>ZbPc{>n4|9Ezn_1d2mp z67~eQUVB2VaGCdm+WN#iJ*z#rph}1v1vxtoRwP#U_h448_YiT~xP3%x%6%jM3rjdw+hP_MgXM?XZa}wyu`I7(-E1HGGi* zNzy0-JO#I;o(<#NNcDh|y2(F-bKy9p!&JVHT$A&iB+0ygTM=DkQ!A^<3zDrQ()S1H z&&cG(+y?N`0N2lbUI}h891KtXUv#7@NKNOmG6`dw4-DOQR)CMmZ8O2|`T_bx$6Uj1 z2qBdG-fowG^KjoQ?2tTv$FWLOACUV}wPn;y$RU+GD``7k*9*YmB<~ zVrt{lj{3jn3B&@X8qbR6e>QZHvawd)cgM3(ULAMpZj$eG8wt>C49O% zQhK)FKQ3a6GNavNR50WBWCLImZhie=rLwPaPbD%+z;Aym>UyvY<43Z)MF{-bKz8PP z)5WZXPsG9fVjGNtUGB5-fpBUnnLeWk*)%mmS>oXC&w-7#Vrw1~ay1dC8%~5>kEu0E zs=lcuUOE-&wn9jb8SA0hAm(9M*&pbWQ8e#wFjtl2< z`-+))45?lCe9L@#icltFjIZCm58MviWxDl@)1?38ctcMxx0 zEoC+~?!B+i8fwVRpv7q{Gd^!WufudM>XI#ImgbU~ zj1xUYg+bx!#CM$5YKEgQC#p$wg($BHcjq8yPeWAm`Y=w2!UjbfwK`QODxC3%S!&&F zNXsAko)`j0^#*Sf2v@8&wKacd)t5WjC(~`gk+zg<^$Av9mg58Y!?%)HzC<;;IQL}d zRoWt&j7P$fJSeQT!$RXxgZmgU#nLd&8cp)j;Tju%A^;D#M;dB6rWtLY=W3m@eM-s| z?*zTaiIgZ72q#j(*^rSdREwdP)%R8{N|EVnCc~^Rvq)Al&R=r%4~E+hdMV02V9jZV zzA`;&gw_hZu&^lINi+Y8gwEOf^lt7@UfQHYLZ(vBY*lVGd=}O5ag+@?G9@gSC0hek zg76_(=ltUy8uM|=Hrl(u)x>&1UU}*~3E=FI0(8&hptOe<9}l$^+(8q>(&Mk+w1a{e z5_@q6LVpnSoBmI%2=vrNhY_32H}t8`T9Q8_P*kD1YCI?dsoCKC8(31G2C`z-=WFw?xxRtKQoKp|~G0QLikDq_2uI2zFA)uskQcVpujlk_U;N5IU zeFpmdQ?2q-gAD3l9{}FuwQE9~J@Fuw(c-Vw=LlEC&V>v~r$-}+gRGACrg{TM7k*Tt z+B?PRbxI{xJidQXH{6O`Bk#Qj^*;Si!jYQl06wE(vilpsaMw^{U1@qP7jf=x=k7C? zpN6OQyOt|@pFdfVc<~v)svHc|Cb)XILrIzLmWfP=2q{e);G}{5QRb>7(G54F*SM># z=0`G98I)$S#Vi8Z4W!QDzbv;)>axX`q911Pa5cUCEA&vazQA>IsO*HqE1jj>O4W^@ zScb-XzIKIwcOm<$>xT^iv~l++Ag{m0^FAyG-WqH?{6oosV%Oqhnwk`A7JI`sNw>#9 zSCU&B{~2lGd~hKf`~*CX+LGgklwmln8%0b)ac;wI*f&e$4CPFSGu%^>l-CE->s{d~dq9=Ke{v>`j zcr8YUVZ@JNSKbT^|FSlg>?TGpJO<$;h<_AxD{6V7UXIkDv^$r{7&2h5tf0a`boT~z zeE8xJTv8CHEAm~3Y*sV?P(Z%&?;REMK*)}czbnT_)*3Y!tPij!*gMAXaU_Z;dWdit zjTReZrO#coj+$iL4mGu477!CKI$ofzv%P$4V!;BGFg%npGCGb(7d@5=!q^)g* zV|Hb?O2S(@=RR%4bc()yAzU@2$Ve9t7sV2AlAU;5?0)_Cmh$n#!DKaE_hv%$B6Hbq ziC$@?;(pkCOV9CtLkqx93h`W9S~ke}E&x(W8^q%M|oBV+RDhA)>_}sZS<4+ae-bL4$CiZ1+!~ zb6?~Z?uS#JT0eRD|LB^?AcXb?>n=vE;)<4f45|j>zVHm60Az&gW;?p|A8Lw{ZI4;Pj=Row>ZcUE+_f#kRwKOP@AyhwNq906 zqhkM>l+G8C*AAlvVaYGXUj)`16q|}PHotsrp~_f{YKgwU#3Z5*STD*=DnN-Gqmc`g zN=IAbcHXI~@0w=9!Nz}v8nEi}QIAA$5<7Iif`gdn4;UaN{!*Dq8k>_@G=iuLK}<); z;tz5Kn|G7%l$^Zgy&_aU@Cli4*Rb=>Gj9|G-)TGT{=p#wDpo9u4+X3wmdQ}Y`PFz+ z=PJW)WUDkaQq+9~P2&8}KYui6!VlI;+$I6{vdW5SK0SnlF9^3!lPr`^34z6-!UzoJ zBFQWqYEuJo5+F_!Fi_`Q*A%bG=0E>`PzTWSF)<^DAB|8|;ZLoaS8w<0I>hQ=8bfue zC#_I4{C4?pP)D}?IePxny`Hn$SC1`Nu!srgr{q*Y8WFd(W4P1aJ~Odbwb6O=vm<04s$Wu%+G9KCbi^K65U7Lz7x2_Vb8!CfJUiyYcb{9&|-UY7E#VmTbsrREU zZ19bIP|e08T$D}4a@UNPHku#5_? z>7_Pb7HAZdJxS$M4n7VIr>Dbh;%R7a$OJnDC1`x}F8B#5uY91&P{5HXP^2YP)LcY2 zARxworsNVje&=ri<#R(Q&mU`#Q;t&Qbr+5f^nSXp#jhZ|pEk-qcAU6miOO;V5v0>mLjQPxr94hfX4$NGqNHlmv}+|tnh~4 zoH3!%URJ|FGo(|4;u9FD$QF-)TKe-Rb_jVx2T<^8GLEcGzJFM7ZwNU{)~@lDL5%KE#u+G?X?0iBg!g{$I-spVcz)XEx2`W_b#8tCH!c%R@FIUb2!6J z^5v+`<&RN)3cxyBPJz+5^b)_v|P$_m; zXML)B7z(ZJm*08eD{bjFgFHcp*FWXLMErr;-4fm${u+@?RWy)QqyN@f$(jisGNK&h zQhR4gOFa`GR{z#;JTgOYqg&TH0N1D!4+TSn2E!`UhO(0kUMHZvAMs&=&;dsUF)z+f zzo}r}(XNM1VaIcfw;4W2X4Es+d#8`W!f30ej@KdGjDHkq%>AHwXIV{7MBZtB{}W{a zAvzk16+_b}JsnvvtrH*ZX*SVFw*_vQh|gV8OxuetaSm#u>n0if{R4U6@jGwxt=CE` zI4ZbMvu052A0czHeU{~;(dYlUoXHvaxhh>%x}GX_E;a58*vp4yQu-lBvR5#{hKlCztb3~j}8m{#3kfH zGkKbij=y%@#<_&>rRl|pBRXXFQ9M~Z^|Mo~?rZ4<%$G0ndUc4DZZ^~IfeL`U$MXc3c9j>Do6K(yI<$o&Z4Ce zJ!eil3-)NPIw=2_CpYCl48bB&hA)6!^gFrXA)%1xgRtZ;6r{5oCy~pgkUc5UT%vuQ zFj8Fd(YLifr9DS@_FGIFdTya@N>Ac)@&$$cH3nPk^l1OPz)sEnc_qGjn2}pz93ci( zv)t_Ds-_q>_q#T6x!G(z7v4xO)=*6#`S1mO@8B-pe*wWA!<(UY^mGv+@>X$9?VFDL zqibF3IE!sEXIOl7VTOz`rR$txgC@F(ey-T9ZCwp^UI&0`;-f1 zv%B2(8knW`EK-7DrZy8%Y(0ws$RUVUcvTOLc?s>d2>DJ-dGJg8^H9xdeoI-|H$PS# zOe9hPR5!@(LB>(do7x~j{$GP-P0xoWyLJENAZS`i&X~-4vwWOl%rE)4&{UjXA*3cj z+i=EAplx{UO9zH5EZAinZ{fWo(e*)I0YgtAA7Uo705^d(0v8 z;fE%AZ5o;INYPW5vzTss)aRj2?n|}g zeWW%jr1KP?R|bOI*Rwm599@NH49%1eBe*#4vXG`EW6d}@u!t$S1Rv67xYE*FrVWGH zxSZyI(nPCzN+6a7=JyU#0wQlofXfFpu6a+K>_CRhzOHM3tb=EyM%C2))0Nv@w}o6? zy|)Jy$M^Np`GB$}j05lQ22k8+i@#9b-9&O-5{zd(YD?zGh)CkEyXk`4MDb3k8Ec`) zg60kx$i7tAD*oq?-X=Vi%YKJjG9wob)sJz_%QCY_C>+}n_+bL(yuKhu+kxGsh`$ah z1iwFubJUSM@K`J(yujI`*grR2jz{jdILnJ5-r_6ui&$Atgj0}@)u$4deRTdn8y%pa zDBrawjx+X|70A;gwUyBSGTxECu8b*`81tBOf^Odqv+S`Uv*A1DbQmeVc%Hks7-iLt z3B>0%?DtmH5bH5$r{T}cUZJ*=IN)%CVEOs2kCT?WBQgRjvrJU}G2SEjC*!G{!amAA zC`XN=OXSK#;Jy zZQBfn*%m(-H%TM$m#M)(L^p~${pdm6fcwLB9~POG)>5gl6M#^zKUJe2ENxOG-bE#( z8mF41BcX4$#mZf|!7nz#t?gxPCLig~X}9uEd6$SfHB-?+e|If2wnz%CffDBtft07q z|A!at&z4Yq#5b>8!Q&@8fcw_Rd~)vV4o?OG6b&%|1H{Jwv zO?gpQ88oV0y+0x$;>*uWrFC6H512gYJj7<@;5m0nnVg>)IX5f^$l!S`)#ZeBz1eS{ zDr-&mg8ZC+FuAhmKwNi=E;>J?9!qhtk>u})A!Y-jGq*#@ru*Z@#=89(3QzY~o0f^& zuz+w%KHB@tcQfnGt3?uxn}`Ak{EMh`tCcwkV=Wkd&%l7zC5T;qks^*R2x2ysnG0pXw!3egq$VgNl6NMM*!jU)e#v7t#54kO#@Vx9A*7Q6JP@b*_0!H6WMd!C=opJg>lwr`Ry-!!MWF>llK>949y;uLkmqtgsTzf z9RGnJxs_|o;0M2S*apdqnP%%Z>+?q^t@(j$0a$9k`mQtd8Xy$R)5hNw-^WQ`F6WYO#P@q>S2ctIUDOkr0lXNCN7 zspQef8>5SX?sz3i{a)dGxBLT0W-i43Z8H~=n+w+FI}7*R!tJ?*Tbd4OCX_b4djy`A zbpknDm8)}iJq1XnYC@V|9b!~R(p^IRBs_uqc7R)bcMHpkCjw>p!=_&i9_s630!A-q zE1juG2ha7s!m!PQ4_iGhyk;=+0U5c|n>V3kB>&w3t7^;9VfbL@4XW5HN_)`nW3e)r zs;`}SUNwTG8iJ5DV=_%kttS|W@%&<%m@NgYc*sQHaz;Bce(GSWioa6rqN*Rp;Bt#R zSh$X|iI~QnwpcFx5c@)^<8JXhdetFkAX8)q%o1EIc6aE9XHWUaRr4}O zFWInmD2pX1vpYYJNl}w@pKZ1F{@PuNUMd6ZKpJvs&6wiL=zbtpRX?*g7 z%Qg%><$=zHmYy}qii}a_fJWvz)`{1n=4yY3OVs$wM|fC$(#JGM9}o+pc59B+8X#K> zpEp}6tnhr>mokVcz*Ov2wC&ozA&QzBHt)aRd#&#!F9KN_i-haoPD;iNl+lXIILWd{ z3nxkkCqfC4CB+OT*n^Z`zGrdG^PmoTqjQ}jECyTat;HKoXy7ScssPj?-j4phmH?{*at4D!$MM~hF{QzoP1tYfFSI(hs$cwDTgbF* z)si-#2w?BkzDD~tnc^WwM&<=+@yu!kZU9Es7%3_`Vp1;>jYrIzh~F4fY8iaCB0)BtQ?4YV$EDrJb=oTo|#M-Ugso-3V}<|R@u zYO(qFxov*FV}FH!=;7RUI7Ge>LT7%GKlgKbkOZGXK?Dp47HGfs|gT8*IhR!Q%mE(^!RfhM!XqNH(%Ox6>lq1@hV{@9{43cGFDLj#L?d(i- zY=2a-?`7&A>tX)y=$^(3fV>~TI+Pm8KVPl;+jvPuv4g8&g=s$kQ6CUxwC&@gb>fMN ziUtOK1{(VIjM669Mfafs6(AIJcv7%(sM_)svCvg$GAnwYy+1v6-(1aM0Ipd}qegg@ zw#P0&hE_Wj!S!EtWLF9s#4AX=wU>(czx!{So!H!CKjT_u=zG53 zB$0h3-KZc(BIDp7ZbN8(h1dMkYjIotT_#uvJ%62+P$9wu^n8uH7AE)jM0A1l%!ekT z7c~&8&KE0Y1E4*L?0sqcD9zwYOWQnPgE#vq0_5ce$4c5zO zut|_Ema>{y`7@FCBG{A00U))xq+}lQlG~<{?k3CSV~rfB__{WQjL*?$+~(*AKAqAI zk;`$tD6{0kC)7!>BQKQ}gj~)|Yu;OdE{IXg6ZBn}-PGdQ7o#puvKv;hSGYLU3QAh; z5rOung10M&jhQEz#d?C;<<_;BPASJX9|D=qpocB*qS_>m9S*cVjZ$YL3PUFJP=Y|5`iHaMCjBQT#aOI@ zI2R$pJZ?5>$I8Ch*9qKm%U0cj#S1;88vz?{)ztxLG1LcVTiGW_Ie2?PBe^!>ema_jknVG7FkFNbv`Kx>Ha zryc!o$9{HQ-Pv~O-iqMIlGP@Y><|^&SnGEh+R{H_PX7ejwe%;7Qf(p4IK^bry4bZU z8{*_W=nHedk?iKS14xfPt72_)&gYd~(8>x2MZXz84WUP>M?ulX_Yr7R%RXS^C_RmX z->&Yv5z+xOZ&YgM3G2WG|6Mh}r80yOwP2)Yf(WJriy%smh zXgG`uVQ0YUceDBv$v{Q<&R5-l>@ZdP98jL1j1c4kPxfo9fv;ddxX%=Gn*UL}$(RW( z6?3#cVbJzc4T&h=gzK#sr#^z|p zeeuFmQ;yntH($~5!aXtz2m_dlnQ7UZIk_c9nR2`{NDXbh`a$Xci%FB=S7VM8hpYF~v0{S?L?_U-f z&mQ4id6;fI<$JaMKp1C=ZCvTE)yUX6>Rt%7cVf6b7TmxOsppll+P=)uT2Drj7%*P3 zku+#L_hoX$!2H0yIOC$5B*?N~vb=8KY430+=JC{4<4xzJ1NqYiLYk16e+*B-6`iDG zNs%qA5nR*)?(TF8edg5O3B8S<^3AL6^lANO9P}y1MR_Wh{&TLlYKDLwJaK>DDhq)p zo2W~=C)SJiXD|kMFnxWe;47Jco^`k`CYk1k)7A^g+7Y4?fBhOIfVU{bc9DTx(P&k2 z;XNI@a&cCcbgNju&F`gSDSXYLBtRaC!NVer5ufs&*AjT_mkP1$LE?xF~X)iET2LDkL(1yW)USIf4$uk_ZcHQ#TBKCx0 z&UQhG@*R#CDLd+5xiOVCfQw1r=&tqY3Em&yUUaf~|6d(6FBKf4@G2NPIR^Jn<3P-1 zil{IDwBY=we+mrwVdk&RFMIn3I6v+#@7gv?%s>AFDNu@S|p5-*?Ql1p(FqC!t z>QtYP;S=IcfTVM06*F!TMVzddV$d7RfQhT_V#wF}|JNriJ}gj)ty|N+OLevinNMI5 z9V^qt@k3&U_tC05M_1%cf7;5$3P+Auq~CGs*2%+#7Gh5-v{Nub{5j1+`W@p?h;Q

kLSmEe^Ll43!hbj_REuC-PX>y!R*e*1`%Syff#AK8F+YBahu`?m zqQuVZpe+1k-EE)pT()~wM!vZ~YnK7-PlVXo;3jW}(EVbr4 z+_Cc-C^r^_zyzMv^YhcSJ+vFVgw_Bm*w-ia{me+Yk}l&)PP8`y=lhRQ-rrmp>ndx) z`NzVbb2z+JC0njgkrh@O5zSj&G{h9UUIWZX5~y23;s=DsC>U8U$a@rW4JK|RLigrx z&?=4C@8aTCFCS`gQ&cswi=M<8R4rJKL@)oA$48P@*W&{*WUKN!@GjI_8@j>O@=HWf zQ44B@tO#$~65bRhay;?(For>mLFz%x={L;|6~a)4^rEq-e^FvXb^=LXvNxcygK=Zk z9;L=$tOIwTvtX86z_zida)1go^K$-tO8`T|k02}dZ53UR9eV|InaV3XIe3vUT+N$N z{@sgbAf;N4#=&7wm~IRl>z{&Q_OZ`Itsyt6^}M;??|x8SBs>6%mT(irgHE?9y?d@8`Gj%(>L2}hhOc&wTBxDL_+|z7 zR)b!Veq14pnE6(Zkr*p?>yNED5hWU1vPZ1gw%@`r5`J{SjAzv^n0}LhVRnYLi@e=p zgWV~fg>t0zyDkek7Ww5BlfCkX&oW19^llVb=OC`&ir`PJ8BBq8KeC4MCMJdf%+0`9 z@8DV4Ic0QfB;q-j9s7McTM(Lta?+b`YfJbv5|Dnr=<e=U)jGGT!#ik{TbLL zsG*&7!SS5%H-K^l>V@v&ej&Yo^NldtJAaL$DEKnH#rL-yAUcd)(RR@#S;UT_z`NdQ;is`4trN!5lBvKN|L?J|Y38H}oSc-lIn?B`39y#ozfUUy%DG2sTW z0OfmL_Tz_Vm{-yx9VckVGR4Ps<6jeCO~httr*UYYb{z=*uM8=AfWrD)RjYT zW;LB;Y#jXFJv1qCZOWc`zQHq-&Pk)el#e3~t6w#BS=H?vKo=dxHSto6dyVgn56-56 z&8m1(b_EE=Y&UDTo8iUDFksU6C9!NZU|j}sL5O4M+yVKeBE&*M8bh~Vd72;aV%YuG zz5XT9gFfkdUzKg}wk-Jpda`@K&2ogX=TODIE+Kk2a@Y!~BtPu+UZJ#Fj8?an?b;F( z_H~^HYohqvy;^q%S;YbLlZn7&izglIpy}F{Xt+1OFeX)y3nEtsa&#V#G*lP#V*LowI zqzgpT={4yEaeb3D$C|$4leglCCFTjVba;Cu0}AvDt1OmOn z*ROHuj}4W4S0;)t7*v>@PWVhiVzH(fw3HIJ3(9 zNjO#&zJE3`N6S?%r+WD^V&<#ian=I=CYC7b2>AuIZ*xwZy4vdzCIr4M1M@^T587M8 zyAEn%;eXTjB9*_ybeW1h+x`$BbQ_IUJUoJB9l&)*9snJhGTsYR+SF`x?IwZI(cXk&D%&!i%C+xCBDzqP6-WqIIm;-u5A ztHszun{UudHKiMPzj^@gQ^gKn41k;A%~@L!%~OfFf5i{dV=DKL38XxpuLr5t;l2ez zb|HL~(cF7i7F3`so{`gONEGkEm(&TtB$UE>h}z;D;kTz|q(qADMH0jEgv_F=NE12} zz!9imVohNIRJD@)H7Vg>g2R}_+k|pDf98sHX}URS=c%_;I?k;=y$UOfz0>@OqcJs%*F%jAZ{On$0DC0Z4lvK^LciWWm-LI0K*Fo)0-P2uyY2I=Uq zl$)PCoHpJqv8sGDND$?hs8M>sTOyu>5I&{$K^>amkUyXOpzsC@P(+{%-r?rZ8NA`5 zLhy8&Cj)v#kuUVCn&QFeZ=fy0D{I-hw-&&8a94b_d7uqNbG>$E3o=O1s`gKgOeT#Q zw_$Zg9yY5V6(9nk_h1B#su;M@)K+3yCz*YkMu{Q*V9>GbZoLqz0Wu}&;< z?F48;sR8azP%F>bhMlnvoJQ55mvndHtU8%KI1kZVBxc2YC~4;(`Ag1E{@%xkS~Llh zbnNr3$j%4jD8|S#zh%yP=c5ot>vQ{uAw;N1Dr(iW?D%EpaIVc>o`n9NGMbG7WUp1lLllK#D8bK$zRW&Y>zV zY8r_@s^y@p5aFOQbri#dnPclYPkn=<`y!RRtu57^lqX!ho7fRp#m^s)on!{|)4ER; zy!I+ihx%(|6-Jnb$SR2hklpJ5MtK1@4c1NU!SeP1mj&uLLggZk4@42RF6%ey(R@6y z1!IfAyaXWd(1Tmolgv}S$EWI27K$I*+w;%IET(gv9jx7BiY={gAab`A&nXjTmYE9- zZvQIYmf~u2>`WElNE=W0rD#G}6YEvuA%6O>|fr`XaIIf$v)av^mHS~ z!j_^5v=Q|a&}IMi0?64Q*4!rJ5oG1|Q*Vmonx9eUy!FGqy!N7T3|ijG@*}rcE!yH5 zX+`Pg`miZGSI6*qLyU4FqP55yPNM{avlbcuJE?Cup3)%&kt&%@kt=5m%PoYRk^9fr z70gXX<|LoGh^z>0`aSh&rgV)1y#$AOh{RvNl*7{JBEkNAC#`i|c%DTiBKe_6m!IVRTGa;X$!5YO%O!?Gx?(;t5wSN> zu&IiyCZ#5EUt};_TSdq}^j8*F^6#p$>QA35MJ0O{xSFF zbAEcr?d6vYal&G*VDb^*OCx)SyCe!3*hC)&GD&tqz3?)Kk zLU-U6#rTNoJLR2z51w`-me%SD)mO14y!?3~T}S~Oxz1n$Pzs0CUhM z8wGtbV+sum=?*Rb79|M;R01dPDKg%EFivEPaK%q1dxx+$mwR~tc@ zys3?7XH8qWwG0o-*|bf)gGsXyz9c4#uCot$TZQ@MZ!2d)VZ%kh~<-A)L z-@9NXY~Ubi`<;zPmqi2{3|SO4qKZ|0ccP3#ux$U(anaxd)t39-3Pe2U`g>MFbbN-~ zOs|V3f#c$9*Viho-IK=4!Dc=;p8E>IURVqdy9c)!S3jg zf?1oGFk3-byqwAsWxcD`>(Ve;yfuT4US;Fd+z!SqqPLq(K%?Kg`2lmBu4}RwF?GZ& zgK|jW=H~(9%sOm#US*09?XZg0%I;AJ?eq;gAC@Sms2I)Z%0`A+UiXX0r4q3n+0m|T z1?xj zVr9e5m?r|xcrUF(*eSZLly$nf74m;f@B!l+qF%5gU{mR^;D@u;pGht2Xa_lsFyRCa zNX>Kf#ieQkcm$G{tEu$7 zv-zY|fY*4y)o3|z<+l~R8t>l)Jg-v4PuR6q!!1oF2{vfu`#2HmVF5f4w^^m#xHBQb z_jA%LToCZu=);Sh0qTqkFw?Z?&r8T>f4OrW}s zTPlgR{5N8}2*cYfwlG<6a(^?c`OiMA*yoQd6uo5Q&Y!+YIbUL4rMh)Gp`$nR`_Pxj z8-#SAI0BwU{CDaEz4IDtZoySo-B!5tDDin|2))AxDa@B7Z5lXIVwoO@?>XE%G#Ue{zMMWvBg zQW`SuwnF76M1SRN<d6+*bS>JE>D z3?Uyk-Ha()`{;2{b%lrsJ=gLx^ufV&mIKSWYph8F%i>sfKl}#ln8cXhc1ce!mePaz z>p{AJ$UJv1ZWFitGcXS=r2{yL} zz#&vRD{g$rN=sFJhzK*yky0+aV$B4XQuQIZ{c9(2ar{%%yIUoNKPXgdN+X{Vu%!~a zleN>%Ow5`s19^^XEjxJp*04K^jt9bvtkDf+-b6#sT-c6}I-z_GcDz#lakbYAcNlyd zTcQ<%CBGRSKfiwkdt#d$m=-}dW;Bv|;Pj7`10l6J+@W^lx?g;mHyi~CcTwrtiuZx5 z?>P2Tg}m-V4{vYspyYJj2QRUqy=>j7u>r*s;%oq>lN@Q1 zYfrzJic3cZ)sANy%keVV1!AgX&w7qhBX+^afQ$?$DBPXyjB7y6v@^J=k(ib({G73Twmq-2bP>ZdP5z$*$rZLHKq6O(RiV z)dE=_SZ&DPv7Mmq%y;nm(&HyZl!mYIM<5loCwlv!Sz@21rm4SA>cNM1K0(5HPZHx3 za>fe@CD$8XX=XYj$364>W2vi;mcEVju_Zi`^_Q&Rc^d5Q>?h~QKxhF)1W1UUv+*vA zO=`M8%Qw4|Zt^R3j~2mq)thP71_pE04HdA9`UUNu`9Lb_gztiQqslk_FbuP| zL#{FIF_@QEewR{YCdp}0^BI#F|W=^R3BYL4ruLb;IFu{#?B5b#yV3sc}3HvSaw}D7#;Pp}|26l0#FR% zFpRWKh#dGWn%aO?#+^fTMwfHz3)y*plYOxB*_vt9-VI_j={kxUusSCl<0oqv!ET@E zvL{N$_$ZuWy^%3^wqq(epcZ`>h+L~i{u7i~k>YRF?3B_oyt=G8Su6K}Yd2`a-0T?< zT7l#g`t?YoG69@`pb{g$h(DHG{v1qoe2hUbN~w|vN6OFFWPSEGi`z0xyC}BI|+MDoI^fzk{2!Gh?A|dFCoI z#DzvD&GzjUxz$cI$@C57=cD>>lG1q$U7OlpDHPOGsG}I6HHIfN5EnLWdHxE&(FpTv z%sEflpNMI=js?KLx(Vb=7?S7n>ID;hj;l9UAVT7Jx#!}E076)W9)lPSAe-G_scF~4 zZTFha$v1zyk(BDf6I&`~3F4n0xOwef9rtVIZfQQ|{kb1DS;oqz)=$1k*W_f_FuU`7 z{Xjhx_^Zx}amjQHSPj`T4}m4D>YWRk&qqSAZpA}?Z9AnomZOki@2bvfnkYu&sh7|6 z>$Oai2(+sw9MH9T?5xTMj?Ay9R4m>b^y=t=FQEmVpk8wCg(_^43ck->MV6Be46%C> zh=J+aXC#7mxGd=Xr`1p)h(Zpg-6_B+p6Ln%bJLGnboLc*rSKw;@`01?wUt=%GYfIYd54)i*IwGGr-SEV?@2pH{5T{QIGDw8!J z&L_ZjLLvHD?Uxe=q%QB5tP;Tp4~VJA-+!gFEBP^CZ9b6iIOlEAfl#(ZzfuF5Em$fe zZUR^DvrZtUSAC12l&V5C_OaN{v&uP=Wk5M!ejWkRd#NY$!b;WJG2GWvnC}_8z&=MO zfHY?Cf4gc-WizA;WGwVs1@0lo(lZ$Uw9{du{4N0M#Vs$I0_c{$IXPj1J1j9;OUr}0 zs@pY=uvb>+0tHnPFMKy{>gmCJ9vF)vwS4?cb2bppH&UVf4g$wsZ5r+2+C;#wVOT6) zxww-$b{CF>EVC259#gt9zOodj#-Xl(o2;`G6-`XkJ4FVcC_|+;H%)r+rH|IZ{0zq-j^P`H}R9S*^h5bIgOc%~D-4y6dru`r(2M37-`u@z3ys>K zjc=MEk7E0u$tKrV^zbDS@roQ(!aA;^^x+ueHo0ywd}tk>vqo^?Z0JLDSMqSrn4~`k zdK>BKmOX1P+aDQ$zX?{xnNL63^|@0O>R&ro+422(@A-PxPyN^n_nY^-9$C0ptp)w2 zNXpt}Lvaq6{6a8qz>20>y5aTJV!e!S_vLSS&<6L_lq8yDDEAg)L*N(gPJotlo0rui zFZ`?%cgN(K=}&x`rjM>-?zW{w^Xzv>JCDPeJNz}ATcf2P4z+2ZI4;=c4^j;|6YDye zrymsGcnddQ+Fr)yv~ZT@qqr9MqtO%4K)5Vili(FQJPo@tf+|2&XG-NrPdbh+yLl)P z@2sA~f_k+mP=FUZ!tv7$(ZG9*SMA11JSZ=*YYt zxa|WuoU!_hYe+wMQAcQbtpuAqfU*-2d{bw?Qar*kIQ*?dUs`ht57$!@<~~l2$L--4 zAKg`-KH`>9OTS-Dzu39DAwS{Jqkt$I7QzCa4j}?GotHXtaYxqh1}^eZXDKWfDp`)v z1zzE}d9>93R>IhONsvitVvt7&cB;r%zCV#!K9W6}{lZS$Kusku8rwvK&z^FE_l-I1 z5jNNfyPWLI8GkNbo@s42;rq7WVSqIAk-B#99mw}775MNqRD0)m~AHeQ6yP5bZ(TcQMV6kF& zNSdqX#3j!^6{}{Pii43C-bnuzQSaJ5Vm(%g|) z9VcSG%L%MMRY(dfkhuJ;bT7Q+Ot@ZOHz?ODtVI>2`!c$?g<5aJl_>YLS8CWZ15!Sq zop!>ckrB^u@0M+a$cB`c-bY2V4L*POBj${5;4qRP9<-pH{rMWf7Ju>MPVsAE^-=&9 z^&L=qEj10ZGg3-~e%rBPjtlzl&wFDcNqE4;cyEbVq z@&?Bu45MnP`ZX<{87dEET-cpH8a=bVqvIm-BcXcAJ*wHSVs+k_H$kBTcN-SyowUPz zRWb*#3lH$xSPA4e#4Q#4vPwP}%>*4=0Bq@}MUQt<9Q#^3$gdKbJ`ZHrlyqa?uCPn; z@lxLm-)FaSf%)SmcB()Z##-c)4XTBTr&bXf`)Kz#+rF@0aCErv( zTuxWggAFr-EppcNqh(o6jl!C6!}qQQo}aG0xtp&Q%EN`L59WGdJFT{=gjs-0f!!Ii zR;)b(ej8YUtjEUHg*>M55=sFv+ScS*S!+&Ktm0^enu zKocdGrXOy&)*aSHwg(YOJbOq51a(}~469G7HxlkiXU{BF?4-aFX9`K5(OqX<>gEMI zv-_A+_iLJQ?n>^gmxf(An2; zgF1u~Sgw!NRHN=-4cr7Qc9or)PTX4aKx%903c7g!0i6K zr(1pS!skt8EYQMLa>vML42gKHVYUuaMVym*%3dv6A!`Dgj-?%%y;oMItw;*C65HkD zI8XAk5Jp?(G0$koXU1#Fp71!3U7*ERN{f@S57dsLO6f~c+{v#tx8gKJB?{LShQQWY zHu}h)y;+KI-(_6CZEywV+OiW4e-duhczx8swv#2CouqGbO&h`3BU$|D9jDD|R#&^w z!iAfaa$5i@=D|a>IbmHY^W;kXvOm8k>g!d%UK2D-1^wN35{K;}mejbrqMz5w=N0X} z>Hp?j9%mhy2Xdhco0VL*B`z)OQM2A>W}$V0n1Sja1n>=deg3W6z|^?0<4hW$l$DBJd&2ur&8B~ z&Z5Uw>YK>Aw*r!Nyv%omBINq|^&bU}8Q>h9y&-!apEd6-qx>hid<>SgRHfJP(Jv)l z7n0Mr=`k_*S$0b_f&%X78CpUS)=If23RdZr1cXQ%5&@ro49+*|N@MCy|;weqBr7#S!wb22^_E;@ZZRRgCnOaKvDYf zvZT6cjuqgC4m>cx9ebd(yV~G?n-cco2pDjEZhdhx928B5P(*u=N@^h#(qaC-9}N-` z7?1a0Ix41;d?lqaTLjo)N0?|Fx2>23Y8)S}z|+f-0Xn_5p#LLn6bHVEHVi<5r@6|v z6K4GXV;%yC*#fI4$%+XQR{bB7m`|nW6XLGpaW4L|l>c61sC8-?%(a89kxT8rg0(Cc zSaq4qUH`u?ftsa?-7#pxLVuej{OY9l`00!8teEvj=!5FZ%AD<*=}t*Ohv>gzregDJ zghse49sVvP98sLcdUcPAPT89XycU$ebH7WnN_)aZi@*9jAcQ->&|Jn!il6_Z-@NvT zV;8IlpFNPqEHY&1ufBiZkbWe5QG{2zuJ#v;LpDbl4zdk?@Dc9)&mE9ys;77Ut({^- zXaU-0H-AUuB3{W)(zA%&NH({8(&o{*khym_)Fjcv`|ZmSy07@<5w=6Q%X_4FJSG8V z34JrVBdiGY47}3+s6;`=)1!2BJ1Sih9Y=kuALNb6>*cf>5g_QX1IfyD_q;Zpe>}4y zIRq?2{@MNG1Z6JHAhkg7G9u_k6w_OYnzR3DMG1|KG3oXJHZ5w?uII3%gxD;C# zH9Dv$xFraNji}*66G6dcIEs)Zeu-i^T<^r(y@cM1!HM&yg9?|Z|HOuDVrM;hCo_Ma zz>jL~DJ6Cc?n60-i5%5;bvIgJd~b1H>^b^$)EFWu8fd3NvI#rSHwP5mFZYi&a50VL zO-{_w^5ZOIb@&EUx8QkJ|6ToaUv~^gV?b>S_B|1P5F%)CupUK#PUOiP#T;sSNLUr_ zAJ`}D0?*WYrMiV7gq z(aV`=_1+b`8R&w{npE2)MUF-xa@j$2jrXVLMZWDvj6&bbS8ylz2P`Q)Ep;@huxtcw zm+6>fBlSJK26`ZR!27&Xm0Hv@&Cj=@J6~~f+N!!bS~QzSoz5MkNv8twkBy#r&;W;B zssC7gUWzN8pQo&Q;YUSLwXENBR?MQPwIqnJBZT(wQpeV~NK?RyWtM3qJgy+Y9x3Z% zW`eslZ6wzs-!KaENY$qF3W_ygiX17cDzRR)eB8ZsR|A8uBGKY?UAUDS za?p-cj@w>ZmMfXJ5FW{+9XT;&O>tt@Gy({w1OOsEfEnv8^J`ZQtyAsmyBH zFR##2&@ROUn#wOT5o7YMN4fjUuB!=F`yDr9TbB18fVF-lI6KUHHJ}B2 zt!&TvLg(c)x=qrs2~whrXyrdkABkM#u(KA7(<$~dwV4-Vx)4ZWShY*iaGi7z$KIUn zPT-CBbBi-81h^7uouDiy2Ga&fhy@`3g-w$%fI9eEJJ$S6nBZLGv*k@7Zh;?S4SY zfv=cHfZQkGoHHylD^11mh%j@ze8b-R>Y%P{T;+b}D-`MP)mNH@2P|Yxi33fU>eeq3 zI~W9)%9S-c%xjsszvPw#_289zVUc)AQ1_`(A@@082`_#hj2^`=y$k)ajjc)XBQW`{ z+-wh++@08&w&O3#^u2sC*q)YZ8JXVU8MA~W>*IX2 zzaHZ(4BWY@gr1w(lMwA~*nR2GxFz23yypz9mb#5v&8PnLD>wsbh-c=ryGQ>{K*-Uh z=nx%lD}C0axgCojR|U2d&Do8m9peMZ1YqvdVZ0~VV>{F5Gp{nEc)4sMMNz31oDLgB z=}HWc*Es}%x&h+lEA~QbrhrJS&v`wWFqtD>MwCy%;&Z)ku*dw@)(&xdZzllp84=~$Eu_oJXZ8&j5-dE31GGJkK^$A(;cqEJ6NCPd3- zl?dSM-;nt`@i7p^JAS*xUj_`#ciWX)AYuw}q_NWXK|ic|Q17G~tb8^>L(5MbzLF`g zT=d-P(G2}Uhl6s?%Te}f_^mq~5WFBAJMpm@m#T0^YhqKMB88uR+4nto2sK>Q=<}f| zz*KI5lG`Wouv>K}8|TU+ciRT31|}U^?3~^RuqN;(g=;Kpg#XovkRxTdNtIZE2#gLZECJ zLo7!M)-#~!qZJ-^d&A?*<1EQ1pBee$q6lL#std+H{_)0RBWf&IniKAZ3uW2Jt+tFW zJ6?8OaIP5CJymL)ad{){3XS6@Pvs|y!n^H%JC1wxc4^jLkmM>uiLXER*LK&ASJS5< zjxN)aTK=-)t8IzRYYfQ&MlJc-iyO`Wh+&E+^KMu=g{5`o+z zp1}?!=!urNKnRE-z2UXJ+USLBjEC?%2E&Oc&fcQu_*m?_M9P~YU>Uku88pUc8vUBZX^3C+mmsD7AK?W>kq?jBdctC*d42G=HZ?#aZOTk z_qp~5>>pq4hR=RarR#{h-lOb$#!h0ZL>cMpiV)eQ(20ONn_|9yXpw}8N3Y$q799!~ zaBdT5h)SIt3VXLdUZh;uYzk@Ig9vbaeTS|UA}-(LZn%&vuTZ*WYGib6T9ZUVbI*HH zkOh$Y74-~W_S0S|BjYT{-xHmuOso3HB_jRp_Kb&?L4_Z>BUl09OUqK~x9UHiQpHY) z-qW}Wx8f4kHwSm*H+D`Yc)$wHmSdRf5^VDzoz;8FiL)a`BMy|nvnu+>pL&^E-F3GJ zzWJD%4%zY%EgMY|4GwD4PkqLXawKc4@h2Y@IkFYPJ?T5mgk8q0ergYOux1?NJC4TQ z!5VJqe+P}LI2_Ew-fZumEgXYXddI`1@7R1g$bxyeY!|AIzNc4DTn5`~>Ax{N#CSkb zALJdtD05_PSGjI`yJwJ@ecU@?*M?gA zS56y@+ZND#8bhXfp2~e@C->i6hlLzfHJ~ zsZw*Gnlmp1@^GkPV^~1ON6D2rwvS9y!!6JnX|e2Ms+37;<8M*ABDS#mQ|JEEq!k{8 zV_L(i_$2F?(_-6>3S!y_grQWdL|8SvCC%506UzH7O+>gedVHgiJ~{Der+5fqt&c0Q zE64}SLj{^g*_Ur8m;H27GsgVdORV|DVqR)uV{3;p2ve@xc_TodtS0fQ-w|_0%l-u_ zfV1)rlAyX;^7p(2JaGQ85lVo?Z4!x)JmPqX+s+$N;Iciv=DTf^MRv|Nrej8MN|K&f zB>|AitN+5E_T}8m8JvL9O6ARHxg4v$B>LEtM)(75_P!dG>)bkT1$v;3Woz#S-g(=7 z)p~u~$<`<-T_feC`DhQKB$Uf!$fJm&MgCQxzW3F$>sd37?RU%%wMj`k?{3WUi94#y zCHTk*6szt@6P~r8dx#|~0X}|Bl}wlx7{=3*q>6r9Obkq(VI*Yi(HyGW8-ES2P+AuI z>AJM@Mt0^zE^*?h0B!GE9M(V%REOYRJxxFu#GxU13aj{KI&LGwKo;+jxsFJd5?s6@sAP5 zSb{<~&%QlT`?l-U5trIlLf*6DORf7_JC7n`aA)7n)t|nPMi^O-cIS7a=YB=H$*|UL z6~E1b19UIhvy8%&!_Y<{&wSf*(m?88y3?n81U$;ROVVK$NrvX#D}y72RRp*?3FSSl zW{aU#Y(5`;i4=$!m5a5KH3Ir7mm@G5KlB+{x#L%S)gUX)euMcSI`N22D)W1K$nFN9|75$vf7_S9XcsvMV zLGsS82nfGRf5NI&_#lKlTD|u>Y%kF&*4K#h=qoGOj)KAio*RPIdbG0dp#_}CUmy7-N^iO z^8RMo^k3^v^xp1TQ5|93u@yCcuvYR$12HM= z%CkL9Zl(Yb`3;@TA5bm4!~L>&PF?V|h6m4Okm;a)&&wO_egzzPJ|dru+vCP9OiZ4) zPXmq=R|lGR7=)oEuentPl2MIpp_noQVj~SD8!ozMu}vbfqh=Y7QYGvzkiYy;B_?%u zZXa{XKFw&Oc4S}r$GU`H8PnhS<9gE=8k-#6l*b3uuC+WVdo!ytSVw&QeY=Kf9OD$2 zqH>ESuzKr$d=woF$dfo0UdtvZm*L(AuitX{utp8sV{ozF1)q1j?s;$hE(c2h zq|ugQ7Acd%g>xNnVh4Map4@t$`y%8iC#yM*vonWWSACs&F0UA}BGJc0zYDUSGk#p} zm~8$kF3WxqT)_w}Sl0?nPvcJUxqJ!_Cm5gs>LkD5kddBHr6i(#|HdssKs+y%ti}!r zI#Gh*(WX4a@AeeU)xIE)A(Sb7cFcv-_Yb+HYIdhB!MDxwftY1O^as}tjHg0_Ltv{6 z&A0i{T`G6u30(>)wFEDoQ(TP?mPyf8lqp0Y1Nyy+nMw3UsmZFZ@8OT{^PM|SWc=3? zZ3nJ%SE^Db%#I=~&W&k_?pVxeKKus42fDDt8h)gV3QJtM?5rH2)C0F$IRd61d$fQB zj5}Ri2~=&S^sn=Z%rC3r;NqmLQN$6lNqL`aDC9WaiYfze3VjRcB)v$-`SrMgO(gf+ z%e}VY{4or23+E9T3Df1oO{-Kl;}IrPS2HaPf7g#H{C%w3<~wXP?b#$rJ^!*DIYR+2 z2A)s}qdj3XTPA2YBXYONvZLMN!w54#|IGX*BP&eE%IYR_oj+%+5L(uno%dv!nV5kJ zD-+eP=fr^A1zO+$Or9#JvAJc~o_UnV@8z30o=dfM(p=I3t)!OcX@a?%VFLjl0x z5P(wNt1Y(`j*M|Yf(@sZIP|q*mIS0dw29>JOUFQL6pv_kVxcZSV zB2R8Lb%0I{57uF}KH zm&8)bFcdwQAK-BOkxAS)Y1HCB5S7c_M9m{3JmTnmo;`gWUK?mmh<~$PVYvw(SvrbOZrWlwBZ*=>A+eYXy zc{~Q@!ahhDUW3`LTZF!sM-39*S;3dHkM8 zhmbct1iSMNL2odZ42c=CIv-ed=3iwWU5`@T8Az*Rj>d?VXFjtt@()?B;bG)~3~QzL zOyF6^%B>}|XgAv)_WJXrk1woRNVClDk2d4CnE8c~{#Hs_Ii$wTt^O{^>JRRC7Y z4-Hw;EdL-cI6bxl*25<(_!ah}x&_7@wwjc2>*v#^j))g8mAf%-L)O!Bl`mllak42V ztWy5;$1}Nf+=sG1p7gk}^Vq)~Yd7Yo{lQ@eRT20_tm6^~tXko|c<3X@u8fq3A$TS= zgA4%}B7gGz34xAg{|O_>&vU9gZVahsZg(Hf@51KEfLI>tav;ie5t5F9-+%;{Ujt(9 zqsB5c3#?f+!+ZIevtyzN3E~G#uF@u)Ska1Hm^(E~kIK{&0m5C|w|vc9iqJ!qbJ}=d zIl^*Wa+S|#c?6!YA*6D3O*8(XZFtW%U~C03e(lk;E^awABu437Q*=NKfwB9U7_mJo z%6+gh8MD#rk5TL7BG}g$5~Xb%pNvS5a;NLDpVwf!_%kCTZj>!&t3A(ZNeKjA%A~Cp z?&Q(_d=DUjHlZ0bd6jSF&jhXicoZ!0M7%%LW68F6b?|MgcROuojnHC>`yK#QbAR5( zuz8Y$?0ZEa=Wv6z_dA*GLzOSr;{=<`7h~y0W8knw!vcdR7eD>q1%eRQ!SObZikBgYP4B{BB|d;V7@~>FOdw9 zKM{9DR2;!(<{!|N3DuC;l+MgczLZV8WhrSnQRVs)i36dSw3o!OVJZ@zPLI_U>DB@v zxE_Iof66In5~pv(tfHhT4N|V;*(de1=RL;%qTHuz@&dci#fw0v&5Dg7K6oCI0Eq1t zbb_3I_9lNorB!9Ce52gb?%Ma0Z3~;wJ5^ zVESg|9hP%7c*S5_>AZd{7P>H_>NaAm$s;$t&oZb2avW}>Y4sPfH%$I*_qv6hZ%6_k!xsw^?k-^Cwlq`YE3^WKo6FTzcT$j&Wa zK5jWuyurl7R{kK-L=w)rOm_!+xp9#3#3^=Ew8GblaOg?3I7$DT?oB1wbI{-)<~z$% z>Ac3fn&2YRv~5c+>f~%id!C(}Mx6UNSkdiNMFmO+u%phLK$%+Y!b8jld=$3^{m$T0 zMZL*5TttU*e*zz4~Ii?~5NalD?-?k}LLTdk6E%pW9^I zku9muNNmj0(3~9D9PDc&S62B9KZ zqYM^%{8h|!h*PhA-hE(}`{XUFI@v_%+RY4OVwRN3%pXmM?PnWOmw2hE?+O2sFvZfO zpq7(rH#5>-4d{awWL>KVjQ(D2OQ1*OAaAjkM5fnP7H#>{HB2`QHX~5 zvg}wsf*#60Q+#hb{~?H;HZ9gjgM@G)A~s@|jzDwNzg}9_e|bYWI@6`b*yKOZ3|d6? zOKDVPWCxhgFGG-o50a}bUjJ4q>t>VkfyD;x$YnpUw*TONRewt_3)VnUWKy^T6_6Sb zP=!wLnuL*^8M|DIZ;!3yje06Ql|ERTmO`?zdtRbqP^`bs@Gj_k>0kB~`NoFN2b@0Yn2i}S_8 zBm;cHdUMZBG2M9ZPiK%oA9gCpL*9hfi0fUwRrYuDu(&aeD$W#~aYQRcLB5m~)aA=% H%|iYkBIc_t literal 30817 zcmX_H1yEaCw7mp(YjFu)ibJvD?xhqj?i7l_|2nV{O5B|X5eI0FhDhr~GW3?N9d4}4U{Oj$_>$O*%V4j@p zHojta=3i?!#BYcP_ijfNL$J)~C30dSnR1aio64IRz=TKF1Kc`VFh%LWPcji%-|y85d@;~;`IDV{;|R2!sr9wC zLt3Ldw*;3l!+8NZggaD0vf!e8#31915416of_4~-thrEro|K(zD$VX;eIi3_n8i6C zLT%0dY>VG3>Vy2N6TJ|;Cjoq2?iC!y_5u0G^Ou80Zf=~y{bhJjgN`bGgoEsab0;S! zv7LiphZveN+5vZe{6ws1)P%UlzK7YFo#kVFRYHzG?J$3peW0WiH5TY>fkU74iRD#KUjMBD5Z)y*wme z5HOmd6Dn99n{w`MBjuiO^k!z>$9zMeqik@#3MA*|<+i@IQCK7IBPel3%`%L|+dI%3 ze<`*pD94%g7v0;E#gh$Bd}wMtBVocHT;2_@5mVp;5NcuQggrkp$jSZcTr=k!E_4bE zv4?AW8a#3PimFH(n)77!buhwK^OT57_hMX6x7n(@uNh5VDF^o?s!n`?(TJ7@^p{{g z0SF*j0Ks=N3@0et;zPgr5xvbnk$lVBNSMQ&sFPtIAvGGR{>fPRQN@)a!9=O&48* zeSbcL=A?0dY*dIGZtW6C#t%W8_FTD9QiAekD{M)}*d)RD1{IHOK!xo|^`ne4Sz5O? zK6a3vf$~!bwQe=EU@K4q@B9m(#>w}8wcRJ6d-hP9I@0wV-M92Q5;f3VpP`VPLLrZg z@$Y=r>eF5q{AO_b8D2=A9-0NbEvXxT)6=Aj;0AchV(J@Ir3zECW;00H>t?Ze+k!>| z8P30~4a8yrYPt?J9+`+4Ce4i-OS4`h)wEDM#??KuM z#&BK{&_e9`#yXm;9eJlxu;~qF`VhZneMie2ohKWHO#aF$Dg}UOU z)w4QWi?8(+ONHCDrFBVTno%hHCDEVjwIv@Icmbx2{&aS69XtRF+*Vb+!$~;M^&H%{ z%)B%?AtDNO&4kGT?d)b16X2c=`%eh-ja7=`4R-XuGjn5SAb*utwId#fL6{soYWc!S z0#DJu;kew4!ejo~H9b>AUrMK5VUJSwEpc2a+2#^;rYqXOBDd%dbp)gsnZ<6@W$yJlUej$5}fRNRRbI}HpRoeGU z#b5UO-qM3fI3zt#><>Rr1INbd?7u_@Ko~|YipN{`f-`!6x4DsvM(p39Bt~6pLW~8k z!bV$wPD(d}Q}=cAT#x=%+KZIq-Uv`{%Q+9)1}8mKg{Fc{c`J!F4^GuQTi~iuZbg}I zXTfEsCyWma=202m814h%Lm0^D?eu-k%{TMoGP(L@MJ02{KErA`dki=X#gT1;TH^S?HlC#f_tgiWTX0??oE}H543^=@96RxP zri*}>*uqIv0R;aW7JCtTf7mP2+%SV|41-Fx=&W8jI7VObBLz1wf!bD#FWRY2+u5}pM}#jSmD@w2+vLoc|6 z#>eJ)r7w*sR4W83Zr8hlw&0_^^Bi0=9h9y@wi|}|69&si_4NShM5_z%z~}eGX#m-0 z=j*bRXbNx)NVmyaqIH5$qo^9iiPT%C&N~BvHOlGddHSscyX`wMh4}Wj8YHqjOxMqB zsEWZ(y-Ay4xq<%>8YZI8=lrXx24=yJIe33WFaJ&X&m6uq; z{uqP1v$K-E6Dj+p4R3hI3%Ge0&s$t+^i#z$@A-tx?~0wm7_x3z3KU@U{Bs{$67kRIs1QT7;C+^5txZ=H1St^Bp!QQ`p0)qxc7 zDCeL7gib@aTQ%Z&=a%O}w2@LwdG8%^9p}4eR(z;iTQ7JxF9a-naq0QIBxU7@Pl{tS zA0O;phsXG!-YGSC)b9t zQ9?@Yp(ckC#5R=PwEa<4UgXP3V&&qr%VCnoC!7Zzj9supK)Zb}dx=U81Mcack4|yrz}DBrF&@)91V-28+M=Cdq%MV(#ua5!8Sshzp>3 zn*ponSuld^-jd#%K%K7(HezK`GFt=$xLNSHmc6`|iAdNUaG%Q#N6Qfh`owq3f?$f4rr$xAWY-lMqueVY|)nmB+ zT*$U=-9W^tgtwE4t3q*Is`crh5ScGC!>1ntt8&u7Z}Bp+dgOVOQTl<+oMU`9Iyw=s z3y9goLno3o8ydFqp$-&b^*g5$93Dj3b-9>EOHOg^dBT3HD>}0%)LJNHaDI@IuQ*8W zwG>yB2ramLSwu~J0pD{R^Io~$)vZ7NaCjKrw+2@V&T80nrN)GPI*aGBt;E}u+gSWt zH~)yF2>U}JJM(4Y-SwA(5PV?gsiBjnz;VeR*6p84mv28*UbG;ijC+yP@KCp^(9Cy8 zRqyzlmb8Rv&5g;Z3yy--KHdA201|YpEYA4x4F{&m-#_U{=n*#Gg)OY9?{@|vB&e#R z--1fqYPR1j%aYX9kv?GiNVs$(@$58I+C$6;m$@AUBlx_D6OW_5Y$n9Vuhv?hu3T^P zu@gL1)6a_=UKOV!X1_rDpGReb@KMVMlas|jD`a#J0?v3Bdeu`E8D)iU3@7v z*NW}VXZ_Y!_4N=7CP~kca4}`eH4#7X=nTfJaMTqGoF%B@yD;y{n%4DjroWTFpG^B1 z3^SfTk^dsem#~3bM#ib;ijJVA;(dk0Uzsf?&r@vyxS4j+PVB0X1n~v+&1C!B-4ZS7 zpPWX1Gc1`QT-VU_Ui^WCpmDS_k^i4a-T9;1N7-}~Cp04ZkEfu?6TtXxu5?ZsgjbK<9IG|acN-Fgbrys)No*m} zSGlLnR=jz<4VsU{z(4j0gI0%eoka_GJq1l{@+&d&Ph?#Y5b(PzMsgc&p{zO0^)B&| zUDIZT#m?<5rB!#@gr(5F%Kzy8jx_QUsTqQ}dOj?nF!0-C?TnYKz@Y`{&5j6MJOQ;}h?jg-C6 zNKp}CZPwG@Kd{sz6TiJ&q6@2T4)bxe|NVr!3Q+EN%qnEkt$bF7s)0TixpQ56-crmT zxjaa>;K;+SP)JIkizM+JdaIl==OCELXqaU%l3rGt_cQ1mV_MvCZulsIVWxKPI*egC z1JTAKsh>LrzZw_sRH)~2MV#zfAs_@xE{7I?*aQ+y0ZQW$wgY}H504jQrZolc)(jJW zKBh>eqLEp0HU;edCD|IHwFK8xK%r>DT3`9ag5kfiK9WwwES%G@S z=?#1BNl)oVr&J-9_qwS8cLfm4n9Y>A~LtReFmJIBI_GCDIXB-lA$zzo zv0i-eRs-w?dfdHQ&i2;mb`!OZi*QS_(S*D6QLf?qz$~Mfdr1kQC(6ZSC9r{4)$B%h zClM>9cTMvxJqsBpXLu{bGV=e}zCu>`@|m4JpQtJ?$X zD1xRsLo;*l4@-o$K?`euBeJ2gIbx*#?I#jUr#^cGcYQ=)XphXo;$5?EOfP_EDV-(~ zn{j}_1vIzqQn%kd~U8ve_`)xqQal!fL$v zNZ_E9S|>9D?{T%eu{{Db4aVBEk*}{9iL+QrJXA9Q=7^V{A6-<-+9?uMS2)Y-i*210 zh6R&Fo0m8lRtf0M)hRx+7a_62p$?~BBHNt-i=RqZ@PBl3v^1%h`hgTvsS>LDP6D_8 z-TC&wzt7+T4`aJA1`O6i-E}PH|2XZkuzvi)HMTLx3gD6M;hmP)p8JChUWCg%`_o;T zml0N5-7Q3iT$+;#x`nYsPXR%~<>0G8{YB3}yH25`y`qdK-$cxllv) zZ;koIZgh*v_hgTuPkR`-e1409wp_vFW@|JFZb_BeY7E7pj41b|Hx9X}e00XjGv(hW z(u6mBxZ}do#5O=uYiIqsUza#bF-dvZ(yaq%5A-(a$|xT6g#$%7r+X+Typd(EQca|` z&r~4z@m5C{P1=hZ(lOEd%Q^PX{lm?HH3=(OKpUm;Dsoqg=caj1e{;!N7V3SdVJ+Bzhhs zluy6oiO|_o!ZLvujs|XkdII&it)AWl)M{{{sAHGc2cs28XnZ&gDNT&L&hxypo4RbE zM(1SPGjzH5SGY%T+id%KNDNfz4thp!h~_6vb*+iV(n0Zf9r!QRh$}bOK0y@%Px~W{8EyX)&d7qowS&H_baVW*Z!5fC7!iH zh{2`|XK%CpV&iCSaq%I-}|4gzVmdqt=7G&Y(XN;OYc{!PQD|1Xzy;FZ9 znty;_`dRZkPF~8S##KreeQL}k^?j9XNXI@yDpqHFzBiONR>FDt&jds}Y1^wSE|2a_l-+>QDIz2Eh{Q7xhxLs%3> zeK|Sa4VCo4GC`c5&uliC+C+dq8J0KA;g%aZ&kFj`07?bZOy!uQO*k&pwf~1T1e;L{ zp^$|cY7gQKw6in1<7*6sjV?EA5|0Aeu03)Kyd)A!+{J7;7mUft4fbxqI-8K}K{<24 zi7(<5=nBMKBck@fq`nH)X(G7t@12V3B{&j6g&QkNXh`%{_0l|RZYV!ZzA*_w1@gqU z-KIBr@qaW;$_p3U4eeB>8&>| zJ24hEogVwK{9bg$T(%Bn#aRdKhf`*hTqoQ?x_--a*L7XHau-qSJx$?XdlR{(p1eaa zBSB1ko?7rzPjYEW4I(omVckJ>D>Dyu%UYSu71-{KES2PeWZtE01MSuJdsq(|keR9B zyNucF8DbLJ1e0_4cu_IaIFXSAY)CUSBP`xjhUnW~z`v1pA?Z26Abub>mbyjc&62Y`<-q+alHm?M$6Z6fG(GPh@ z|4dTNWwr2AQv;q1Zv3(?*4m^`V+gh&CE%Tm*t?|m<=#b9-_;ox{x(Q351gTIuoSO* zKY$^_=SiI6q+%plUF8azd1UY*M7%FI-MxcnqbvhU)eF_M#jspy52lgh8Tdq|>kbl` z`0^n8NCXG%v0XGLmN^DR{urqDVL1p$Sfyp-Q45u`&dr@;4ZjJvh!ZG;GXq=X1u%K(2t7KfPve6F=#wi^YaC-kQSfsP)Om7DYS z8~92qEm-!Zt`O3fzQTM6V0uDh-xKHF{-^Z-pHFSiQ}KA;Do{eI+HRNGm)&Cis=YP< zsRk32@Y(MZLJ5<+jziYB9>qE4=dYI$KA}(Q!h3s%AYsVD>GD;43~65t%H;oem^$u$ z=E~6Y{1|Ye00ksNS_q?#zwG(j_w&u`#JNkbI<1Y!zp4#vcnruPkUW$)bEo3@#3*dXc zjRsS3Rkt!s33WC&6`u9TUamaU`=!51z}w~hT1REIDz6L9r0i>_hX-fQAml-*dMVjSNohxe3uzXdv+DH?p3Wk4S4; zQ%F?F7%9EEPCfyT(7X)8x#f)(SKQ-%RZ~7TGVB>oQq34C*Um4!glBS3O;Ggcvo301 z-iBD!{~>IbwMHw#mn;8N#_Dc3dmKD-JYa(Q zke1j*F59dYG48#ssTWg`@3yo&{CM2Iz1ti6*z;(B#d34Q zr!WXhT=!dt zDX5K&&d73W=WkIX0VqAgn7zb8O7ke2G|{@UJ<_U>w;X7FDTEpt7kdhL>I%*RT1qG? ziP#wa^pcR<&5rNPzw~7=><{6dkU9z%b4kL>~V#?7mnGXWf#Wc(RQ(<+>>C2(R$3@p6YbBs>*GOW%iQ} zb<*jVQeMFj#Z6D>IK!MDJsb!R4nUi{yBK7EOg~B2nv9xZJCV=DhjV0vVf8I2El-aa zzdN{Q2ESoa*1r|;mpYqr@8CC}s@ltAYl?pOyT2D}_N?Uo9)&;KaX!xE=sNkX!v zv3Ni|UBS29gmBN*2lGUz6uT2Gs6w5+M};-PY7wdBb~>r2{4kR+G6Qs;91iapaW#6i zBQvVLK{~GgZ<^gu+#h3>!}Jg@fNz#2IS?%-obFf{1=Pso=YHo3=NhQC|Gi^H=A6y1 z5W5Mni#fOkl=SOt4U2Ve)F=Fu-t_NZ%JEI^fXCH|PvLM^qKO~cS?*0dPIQU24%H_l z5k&pP5aR1$cX6{@VmH)veB{nf9gn?}JYj#^eGojz#(69`(c=3h!&~V_mn;x4eD-h&zA0Z|BD`@Bq2hd-IA>S$Hx9BaM}8|PNQsU}{(}g0F(S*QCjJVBTQ|!3 zitrO9KGnPoLJgc*A>Dh;`uDBX&VLKZ36bL$F!|dj*Nz$~zsS%2r+LZP2zkAi_~=GW zb`jQEihDm@hbhc+?!i5-mT!fOf)G=eFNa0kO&%lW?6eQPT(!Lc^OJRyc(wp;Q-1tl z^ci7V7oElAYl-9o$e==`UMV z*%{EuhPPOBXZ5E1>qSK-U}swTqr9Wc`WbcQY2)^%l)Cx8ppDtzwu69EQn^hMf{m8U z;gEhyi+V)+Fc<>jr&T3bq5PR>x?Ac1ubS6E>K#6Ug>nn&4oeO_=p}@KemRZ0B@E3P z1G6KAL=UYNvzyfBiW&!)9Ja8Ga@YKSYv<8#*h#=)7FCA$_d5+cVwgpr37l|o@B|_U zHn>Zbc_-Dwz~ktPOxCMl`RPQanySyN>cKuMrIjm5<=N?h)NT8RGGN;RNG` zJ`t!EyQMw`4KiVBsCt3q$-^s}VV^{Ct3{jldNZ>JrB=u9qn)kpcGLf?XNKdK!aM#! z*<8!5JC-z7c%QJ^qMWRp^>Xg8+YXxLixV`3;@)fv&pVD0-3Pt~N~KM%86CrV`=_z0 z%1H*xsLZKB=rP-@q8cvt!>?GpG;1^99_eR6ye<@rV-?wXlT&9O@amAHng1pjz0K)r zXE@{MgG&@*`w8BL6zc1}m9y*{Hp%3Aj7`Nd5rOFqRh+`h4TK>%I%4JLr#gA=K3Lo5 z%eQh86nh;<(5~{9wVN|(&!3J?R5DET6WbP!H+JRaIEyN0X1kmo3F&mq&%gQ= zvVD|$S7UkDY}BKw!!@;O>Ad6XD)~?%i1Jh!umDQj`67(J9V(q&`1sYv7je^2=yw5`1jg$Wtwfj@C)v$=OLK>=h4@WXhX| zR1d2sE(4-ryk!ou!FN{%M-v1htds3i_Tzt~l3qHm->>oUwHhssig3uObMhTT_Nj|G z+mE%SNBLZI7mpG$L{)7Hd4CMy_6x?jp5zN~_~8^HfA%gO53R4)Gh~FPetW(n;xU$* zBy};zrVY&PFvD-y+KMVk{(o8k)dmm1m+IEIMy{<^smfs_L2gtqDQS}Rk5|4_Om1D7 z9kia6QH@y&CE_0uPLDSDG*O=%sd~?(&-YTs*V^m7adxdd<`u2X!qDo}1bCaT-s1W)T=>(Bgk*yC5Z1VT{paBaP4) zaZz;rOJN?nFL2=jDA`__jJ)IrK)n;>Z*VrDl6F0CcKkAko7|RDoRP4CYUiUmjulRZ z)u7HS5W6!u$E*jPT%&CE0mC*pBF}0cg`Qd30pBP^O2laV+36F3Mn%{Qkp&aH)4MV&k@o|pT`TdWCf0_oal!In+ z;6QazVG$AL?@;@IFvy!!YSWTp=7rmU*aWw^jPXxFR9x5Mb4%q@9DeylmJfBV{()!c z5$>&%0P|a??L5}C4Ts@7$Fk)-C`X3J1N9fmeYWGZpKnRDZuvN9Z#2&XTHIh)|^S+Uac=ksZc}cqhwmU z#B%(iE0pYN*$YEK<&FakTtt(IZi5E+Cb`7EME3r1AV9`)60B=o>oPnb=-d*Rck4}K z#FY7NLU2;=B44BM<`Cgr$a~9A>|rR+%5Y`;yQpz}g}pAUFM-i7CJl*N)=POf?JM_p zR%%bC25G8E`^`nDf_i~ho12ovaiXZYD<|4CaTzX`*&{(Z}6-!nQT5Ai>S zO*Sj`qSb}xYhv+o%zI#6Tiu00=Kh^vyQCujj*LUvU+G5Z;$~(NK_ba;HpuL`r>w}5 zV`OE0bO>B}va{WJbo1j6dM#HY;_!bBDb>p<@P$1DdN?jByYd+&=u#l47rvB&A-HUt zc5enaR48=+MOXS^jM!VH5WuOuMsd+5lSZ}nm zCTjt*s?yqGkFk#gsk4Mf3;&$RI6&8bz}>!jVJN~9=QER9RF7(1aN1^~X^=sXJvp}g ztnn?a(v9?N7lSP&P^d-mt`vSY)r3b?g&hVM7t_mR4wDJdLy)7NuzR-Jr+X$w^wO3F zQ=90-yQ$xU`RZ+PV4exr{|Qy;nAszbVkS>;nYJZqPwb^yPP!ZY3JJ9%A1&~Dj--Pu zx3F8CoBp5bgijM!KkLDrRFth`VlXmoI|1y!-r#ar13tesh)!u`eom{VsC-xrb-gHn zzcn%1ox(f(vTiH|(v4tObiyFPeue7uG1~NpqqIg_vWD_0!n+Ia{`q={8{=jAiDo!= ztpu~r?|gs6F(c}qQCn=7fh+1fsW)UGswU{j&9wPsKI|Lp$W@|R^=@>@Khw=FU(~Mx zToxK?b-JRuo=Kng^p0-m#mGKv{`iEXZV7t%Px(1b-1a2>k2>?lcD!|EzyfGM0VKbE zfY#GBlkVB8fQTt{1(I-C_w}r9&sV76x9t1wGXaXRaL7a#+2_~?M88T0Hqp7o_Y{Qe zf^_T_i_?rCftMqdj$T(5Qw zMSvD+XohSf41jO(-Ki|zRKVLY6^N9tCPJKz(kvi?LY%%J_V?Mhcs%t+J3)(UZJ`$FPb|Qu#8s}8yW&9)^mKnOk=Y)Y*2B5#cO4!MM)u>Rl%2(f)10C96%oX$!3P5!TNAX7@sD77R z7W{kcI7>qC1(c{EhXOU$u5?-R7-FsWJBz2&0wSY&cWe6^k)iZRz|?hW$8fvna~_&; zbS7Njkwf!-2lyJj$qbBqzSAMjg-O%-C2Cd|y(icpiLs_;uOOL`ag>R+9P1@@ZNA5J z9nXu{GxxmvpI&9;b=!ZFDRi?7TKGn9*Br{etosJVZpwZugAH@(mGwE5FtB~~p_qq) zK1nG2<)Z1V%5b2gi~Lzy$QjLF=aY|WnKgkxn(0zzqIfS%ap^6qH8kGZH%V*z|CCV! zm-`ezIP_%ck0z7elBapQ?h@OZU^xp`k<#Ie)CuM~qj)jn)yjjkDB_mu#*;t4r|h2P zeHuyQ94a__>!5(^<)JZM&!di8AMMNcfkq^4JT6+nGZmldKEnB!q5vWWEKL<|`!~?A zFCXGcmPnIVOZsJc*&DWZ{jLK47rDJEjgMkwuF?)Pkbpd(=8vkj-a&~`hlLdKHF$w8 z)V?*`4Ke23p;4B9WKFvj;>WLng^HZTji#ldc$5Dh$5yBHp}9QnC@*^lJ{-r!9HLU!1! z*#D^P3H3F*tCNf#=FD0%0CQ!iM~cRlk;QQahS|{j0lE3h>B@12O<8*C=kDkL0(V%{ zYFGo!Of>_~6BfIxe+epdmSAB4xMd);bH2+TB=mtyoC=UEfP>+WLPQOT?w2L)Jz7<- zwX>q$Mv$>3+^Ys_(h7Dz?q}?*ol2ox1t@ud#AjAl+6YNY2h92BJtnIey4CHau2Gvd zQ=jGZCU-F=-$6JdP6V*3<$WBWB~RVw{H+@uHKy@Ru7cyr<4p%;3p~-`9g*z|#&)y9 ziN-`PV`Slg=Yc0#|9b=#_f4spVJJaaZ)@#iFL*4}pZPaJ>@hFnLH(Q`?>joKwX`B! zOpZ4o)58xAjw&>qZ=|2zCO7q8foyF2{E;La5W{oTys)xVUF5FYavW@R7|i#jJV!m$ zu3c5=@+S4ATY#p15uVtBD5o5bv42-(obB1jrWXvu^^GvE#KZ`*U5vk#oh_qGMqk7mKFc1zBj3Y; zf`MTyE*mQ~PNYL#b~!SnfSK8L@@0SjQ$33+b_3KpKZLOzrtkI`_5b|tjAwD#z11i| zA``Yx3B<47I>u?L>+2-{C9=XFe=ITNcd9s^yHU8)EvVZg060y|s`N>95{@z~^^$d45QNH`R39Dz?|O;5M1-$8-WHU?35SipZkz4axhA==ZHF`;LWkf3 zet3?-=u~`~Sc8z(5)k1Vbi;c!4dg(lwZ!aZ`5KEilsLjg=Vn=j^6UUWzpO_~gZLBu z$BQ)E-ur>&O~t}(-65lcT2GO^?-=4jQ!AA7`$w0NKoa^Xq60i;AjZ0hIL;^fgzyM> z&cD3kZ*mseKk#_a9g?scgor8gI=4SdTeTq^uOYM6fKVG1!|EMvv7i7cfibi*_ozjS z#!|w-U?rDWAv%;Tq=E3ejN6#AqdS9g{v>rDT^K}x&Gj`^T<73y6bl_X7%*VO3-kD? zL!pR{gU1{CpSXn|-Tx(eA2vq|>^ZYseAgUOq~TMdf+PD$D9rJ6VHQ3w=}uT9#<_d1`@_I>z0H(H|{pk1sh| zlaoYd2O^+W^-U1Q&z=v!*MTe#;1S9nI~x-(0uO#2oFXHnygAb_`WoQtmush(e{c|p24G5VR` z-AW{NEF9{7*r6uDLvz8ee`MbA`3eIDzP?iv_xX(pz$bYCZGi<0Hz%lC+B{YgItLNn z_#A}3H{!huXUp|-?MR?4b8ON#gC5(>QgL2|X@#Un(M4UU7|EgP@G^HkChmUw;6-07 z*^cM$#Qvj^8Ehy6l`JI6_ITK5CqY99k)h_x5Vp!;ToNJv#U>#4=Vgu`07J_XcCXxI zMy`(X4Hwb~krShko7P`D;992EQ&0~bPVfhaiZv|Rtel+yq^TN{+N}I=ll|hM&$NIw zL~YPLf-N*qw{U{KLqpowuC`ocTW@I2s#d2<^g9bBfjwFiR_=Hg{Cq5j%CqbCD_U{4 z2y;=^o89!6AGrI`cgIiRUpLeI6w!>=f%tzm9EFTM=$V&^VVqxVRv&ofI4uRXpq>Tn ztZz@p)i;Mf)n9COkUni6=|YWh7+6X4y`EIC4gE1ss&(zg%Y=c4wVb4B~`hvAQs z72V&j$fS_a@BHRSetSMWF4GM+RnitfKQ&FRT;Kp)c0)^uLRNmi3H*c5EZeQ8(8`8f zF*_`$OByZKs(ybnDIa1AVP2bNIF4was(Z_EuIaJc1q$}|_8s~^kjON@4dF$6N;G6k zfl7tbi?iR3Tpnp51(2tndJ2NbLh+|mx35am63?2xs@=_hyAO|=UhaeT;+}6$E;~Xb zs8K;-8xnpuIue5-iXlpgy%ek`ZJi7rMdzS{QW)&f28HHf+>=C^6vh`q3N?9@Cn7fW z(xJw#6nOI+L;w{mUKjuA!kLfNi;|;0hmY;lD8~|z zzpz-oPWewatGo;&WH3-7Sz79IC9!GW8U~#5#+c9P>w5U;wOF(6y~On#Rmx)-Dgxjf zqkEF^nsy#)h#HKP%s<%fvkB1)0W>~r;KgW2okQ24oc!c;)nMbPJMaf)l4Lz0eCzDM zKBs6@_i|)(v9afFJ&6;aT~x_sDgqn##sNQ(1 zWPuCHSpElqiV)*z$W&P>S_Y1uGwugAauoHlB{D(L#k%#k4{wSM3>` zkn$zrQT1Jd1~B;-jxKngoci-1f_@7B3H|gkiqKQmyGr4$4$^L#oG}^KEv>RTa8raJ zF0|6wx|sa6D@~NHLB&a)d?MFQ?-N42py;*9pqP@9lI-u92VNh>m*U%S9}Kv9_}_d` z6o<{rOCeky<#UesLN>$ELk0Ost%gi3u`I63Yo}Ew$cj; zoG_~xuvTUM`elR~uqNz@K_o;z#u5!HO?g^}xT9qjUWZSkvSUzEUpN60qW1J2jGHge z5l7J0(^~QqK_m|%hi7R+CCrTNj)NAX-Dn3IZaU6?aU=yeV_~6r1hnJ1>x#%R3ky|r zi=zR*04o>+4g};krRoVgT1osAtKj8y6Ez3$)gXng>(h}3Rs-s~BSf#VgnyX?b7YF5 z?Ui#YtPt;2_R#eB1CbhZiHx$9-p-RTEhhaV(DX*8Xe3k*rs<`;=3gNn=f8gs#86ix za8A#3xJAes%o8@3I5Ll0H_K0AJ@ZR*7Mj-AM_#3SaJq8#4D|HZPpgj?O&QWzxbn(p zv!wGKDGkjP71ob`%&gx;hC;jjz^s2W@hy>6>{-1VR=0ayN!^{X;KAUNQ5px z7{v+2yJUTvFv7%AA&wOO)SAET;GnB0BMX%qO%?Ik^@H?w2bKYYmDsl$fRu>*y^?f6 zqfWF#)L!aDy6qEYsxPT2XJHMu`7FM!UAp||(+9`}yz<(3EK#ak9@nGf-{WN@(_CP_ z>J*h9ak5~*1ESYQ+EImQJQH+70`eX!t;tYw-kyV;p)bE>hXjOMmiQ3D_k5-&>?r&z zdOoK|0rqTP6B$0r2N5fxj%8ho z;d~{Lc=qoix}Wkr&Cv8p8#P&BiF^b#H8OG)cl{=;j^16nd7|C05=^Ug38(kgP4K{} z#0x#OAeWoU6LQK80(kE+lqf1~|8#Rmr+$w4%RMPKgr$GAUf!l=WMtG#;)TtcUe&ll zx90bzhz;Q?tWN)3<^sEJY{H5GcgPZ*v2KexaO)~B1-mk=-_l%-^z(-yB5yX!_$cdj zK0Wty;r!;=QA*NwmXv9uf(LYTG2d zm%{*Za&vPTaAZoT^LvYa%v7qFzeL?jjCnlp+1S`@WFt7J!VYyol;PP>soiyUk2hOP zolcFK|B{jc$bFfvpC9cvW$5Zf!U*c6?5?ONDcRpOMnEnp7bb=-eP7r;lo1=tOKa3| z;>aUA{nt#Ve(8k0+3D=1o7+jwz`(#fFTA8Rl2){G?udbFwW1Q^?I?qXX|{-zREW+H zv_@EiW|^y=a1Wd;TMy*!Mq4fF=T_|iFnOrmXAQP1pDK79nfw*Y@z+*2Cob}wh6XNG zgdnaWkkN)HrJv{{!NSkSm;D7|&sTOiHogpK<@u1{&D7q!kyJQdk%yGp;GBYy& znFISKVejCqcn&##xI8f&-1qN)Nz%U7Bvuvf|5*5AWvwEGPm%xkWnZnhK>6&(xsHei zZuG#u4=Q*fuLc8CHFZ`-eq-}8oJ*w%nzN{~Wn;@E;clk*SH5ST3Db7VpI9&hiECIn6Qa2M4 zQYm%nm$NGsCr0BW%9R;aYGw+QZazlPY8U+gSw%xunKRwT&F3pMG2XfNN@%?XP+DRu zVp>`k!kq@N@8!{;py1(>eUiU?)=D=xrCj;P-!4#8G%fX6%7j{v>*4VpC9iqywzPh= z$o0r2^Ok#Eu2JdmMQi7h@3Cj=QB_IDFgo$W$U_Aa$yENPCT0F+G0xBg*C!m$S5%Qf zD>a=}D)Ke{rhyLmb@2e6VWZR1@CB&bm<{57Qqtv#xt+M-C5;ixw!`n3-0%NNY*#Iv zF+9&nL|Xl1O=i03y%Sp$NNjTHcltYd`~A-9ww~uTavxRKGw8Ts+|ALJuwy9o2Vux0 zNnASodTKX}TghkFoZ#@{OH?oWV;MghM}`5BI-2m4c^mC8n;Z)UQRgt)WF14SQ$oQt ze34DOAf#xBZx|~6(K#g`eVrH>7?}85H=9yh`G|enqQqQ|W8aI%6OpveQQNV9Q)Rqz z-5UBV-FfAyq`}EJb|$ps$3MW(Q4GyAm=I<#a1{eq95THl6kK!|57k@!Ir$4L+Mg2f zoEC}AiNj%OtyE^gGPc3K_e`vtB2;U=QdbdfG@kwZbZQ+hyRyYb%HK8l zUZQ~do6453``x7{O_134(yV24+rP?R&7?|~ek^XA)1Cd05>9sKjYp$qrUZ_YOnCp2 zvu}c&aa;JuqGYgSp>Y4URVEtuqdkYM1>HGdZFcSA;(AX|yyNuevIY;UCj)886dHyW zzrhpbQGGmhzOF1hvc0^Qi@op0b*y83U1tjM_C$9LPek8;FE&7;WHAg*I$!6yz%8oA z@yV8DZ0NT!v&tX?`L4OgYRBHuXrdP6L0p;e3ZG`EFc)Y5yAF+ySHEvX{GD;w?fx;> zb;0lkUuBqGW8#5*eQS7S1QD+FH%N*Fjm7^$EiG+8%j_BbU!t_~iLHzMbr;T78e6_h zP%WN`J`2M#(Be>6S)aQ_3b9gH&Ny6aDlI-xHF!-|@<5tqnqZr$%G*#Ep6g!U%LO0M zu8QQBFH*hmGci(?KYKr9@(LsJC^$!lHeOnFmT>O$edR=T?H`<3lVTZ_+h%dX;4`Borbn6>L;2~_Wi!5>x4@2m z_b_uh;6K-X&DH;G5zZ$<-yd@B>x_Kh9H#fEXYFCyH8TZjW2HQoP=2=7Z#n5RVO*;@ zy57RoLI1|rk+z(u`a05KrPi`zNz! zpK#Qw@t;A?f4}Zy<9*vlYj@W89OI5`y?;H0CBmIgL1J}qRnYJ63btA64NX%v_*(|j z5D{`m1ZM>yUnYkiNp}{H!j#`4mM8>gyNb$xbSP8SM!f!VT7d>-sCE0vPgB3!0P&iR zmFrLa{)=z;_sONN#L9TY_{0mWtgN7Uco_Bki6N8{*?d-;ZHbvm#7H)@W63N;I>6)?uCOXOyB3 z`m32zO)?;c`aYZ(Oug+PE#Z`8iR9uE>)7E4w)o&AF3hepy zTD~(Z9@D?gzI%qdpg$a&`s?cR9*F^|Qikvbm_>MW za&S=AFO{#}C+IAL;{K+0V0pd461ci}=Hg~(vHC&4C9ha!X-f)o1@{-)$0kMn*vxYC zTYY^?>IB0hq=;VZP1Wx`Neu6|!cppL|1A|(N+ge&7=#L4Ff*Hk6NxdE&!piQ$bLR} zL7R#1P+_^m(XWITmyj3+iawS`R>Q?G`7_xqeWNASC_X%uqP(f@YeW>(O}E-Ufrf_m zD(4pGO_y!M*xAe)xMqguvwR4^X+;tA*MQkGR-%#X!EvcrJ8EY?Drl4DiqW|4?)`R< zs;Fws&FKJ3o?a{yl%dglf<2jf%2%b|-$qJel|tt{>#&A=S+E|bc@UDFUNwbV-MFH&Ua!9X$Jdf3MfGzt7Hn`nuk6?t7*8 z=T7vIKH$C}ITTeceM>klXEwd>Ht#UM)^x)Eg35Ipo#~g{c^Sgi*Y^EpmWhamnb-1AFz04g z(cnX`DuIlz&lgHN9E}?fyNQzqjS|kfWK)`uur8ydTs8rz13w31l#<_v!kcI2p>8w3 z)Y=3x$D}&Xc;k9i$oy!yKFicbV`UJAjT_ZqeFeel$>P1A|`xHMMTNIrM5nHs;3i4jc5Co1ZO0nfcVsyKS4-HG^I z*0;^crfy8Sk+Bb)YyZ6uM$bN{+&?a`p0w5o4ywn6%9&Z8PI7g*~n|Y(|&8WE;;AjV<@f^i|c3VDuzda(J@-$ zyt{Mtpe>x)j>o^{u=E}ygLySNqxQqzWx`9kY-bG<^+J>%r9^PDmkuvxqV{4_gnNPa z=-H>w78l}(l`Z&fpRGY^628Etb1aFId$$cc)3&dxh3{$GzwQ4EFc9%Vam|oTKWbG0 zH(4S9y#%Rsh_90MxGKs!FopeTntp1RsnG5MkZ?3I#VqCxyEd+#i}pNjnzE180I{n} zsj8->7S0%&Q*iLn-9yl*<%b&HqE!=(8te-+p0VcB50w~vsl&&XoAhKv_iA1HChvFa zYL~9)hFTA*LxY(mk}N|Zt{$l!WnWVpk~m_Wlc4T}DZX~*=5hRcZ!_gDy>Q%sI)1z% zFO!pf>Q4H5e^nVD{xU=#Ue^i?xsfa6A2&3b3L<{Pdtf^|yPu%znWB+QBm$ePdBQo9 zDWSN`L?aOj;XQD*LEgU8f!o`SnnjH-`(l;!xIK?IM}u|F9JIHOXmNy8w&az$mN^&7 zAcDE5Czav=@cxu+!Ds%xSWkfm!*7Y^D*gf(9@?c-a{{-LDNxReF4V;owc^WwR&;HE zvwPWWeW5RH0wZHn^fIT-^*A>D-%L|Rzs0b9N$sn-;;N&)ze8OdIsAE@pW6fHAfT7p zVECit$U_mNwM;)yQ=Vs-Wi5SNu34Y=x0&V=to%hYj-TeLczVDN)F3{KrW)vWJ)NZi z&lvjHEz}n9j|F%9RqXnEz1N}kk?Hu_bKefgkcSzf6g?sgpRkG#)*ZKMp8y1yt`(`M z-ke`r7%O|YAZcZhF+zjOB*%E}iW&m&E4BXTJmKX|{sF8Cg7J?cY5+$@#h@R!1Ugn0xX%-E0MT{yLZ~7Dw?^CgDTZ`~CX4Go zX#x7%Hk&kBLF>SOmKQg)Lyo*T(moo61apxmt$&83q9#&XF4s)?9meBQM-b-^GNe;l z22=kDPduxJZh3$E9j{J^aZo?kls!D=O?Oi>|D798nMgVRR8$}AR0EqWW|+Ax00}KW z-q;A(gfs&=ev!uDd>F&II%WObPoI(e?w>*R(l#=`e`_o%cG+)A&afQT56QT7gc^Odg40aZFB4=8V<>t)`?t zPgB<966g(F;S*WP=J5STb?-6n6~Z_aGG-Ib2PksKQ`_3B?YlvrFlrDLQOw~l?~yEl zq;g51A0(RQFz%TcFcU)8$(Mqs7>asEKUxf1xo<2xWnh&D`}~o0H$7@t zw;uhjMtP#5G4I9e#b*?F{L`t89_hY7}^QW*~CoFsX+< zO}gB`MO}ET2}>4J$N#U&=9nPq+2Z^80eX2m#gR55iMZ? znjh00q<-7EGT1AHR)>|9(uO$oU2^?9f51oiVTMrEgZe%-dOHDIt|le2WLtz zt&-g7;3T|c0EhVku6xzING`f`vgERmuR!t#W-*Hba52wUOb>ZHhO`foderlpe8LW# z>2s$vJmdu2=|&^0lL(I>!_1vTo;2P!~8dz*_Z9dn<1&M+z(O==~zo*n3VzS5XTyl7F_CbZ`9a=hZs2 zCS9us`YeX1@!Nxuoq5xg?GD2{mRFK2-lSEN*F7Gy% zlf6vnHaRIMC|EFp{jnglr^jVsMRBy{pgc5^!lNxpf}V_ci9L9?!SL=rn&C6J?)3J+ z>EYjaMfS7C0VJ||ylcMSq~v2F;G^^iw>jF{?7p9#jX>sE%vl~jSAs-Ryr_8S ztFX1b^0h0jSq)bLdWpb=*1nE{`0BXBuhghS|17B+w?Oy3ssS)uwe``BJeA@zf>pMC z#e$Oh`uaB0_#{@8ExHRrK#)#22*EA|U|XmP`jJ@HhELt98W>I^_A!p{*lB1@b{M{N z*Fp%GCrzBN(m1>Zcb7qd04KQ8@CA?apX2HsFBLU))&dk567uq0mC-;en*A%rP`YyV zd8}DZ?X)S8BNAF_0u)U={-G=LIGj8i-qza6_$L`sbyUu@C@9+{;)<9XUVtyL9qkS* zCXV8tbuvCVy!v^%Tf`w^K4U1qvJ@{9yE(rmR;Iw10jAP|>0&zu{}vQaD&l*i zqlIg+hd3-JzYJ`)$@-irsC^`goxGe?d7Jp$#YfQN|AZ7+*urAl^;(IIblY|tSKzRZECJ|}GMfSF zMn_pVj}nc~h}s%(9*w=mQv6&t`+}?QZ^}+zepQ~h$R-#4>GnwA$7gj}$3?TZ2I{<9 zkhH44l@H_Q74H|eGgV`l64vBsU|;4eb)b`ez1`~UT$@O01fCy2dsjE*IM>PVGhyPe zHRz@dY!Y-Yav1*arOwS z=O190CTZ;y8=%y2xp4uNV{}`L{hTwXSbe;@ScFAMuV@7X&wC9f9NuuNr2EqdJ5rjY z8q{l)wZD_$g041s_uI7uZUga4K}JqG$p%hx0>e9l0CkeZI-ZUyPU9PL?527etx9T3 z!=ifNoV{W*$EDmiCTR=)W|pJYJclyR)fW5FU))Gbj?ip35{}(8T_Mw>L=z`DC$MLb z;h>=rWv(-(`P8AG5%`E2mBucKC)!1cHI2A9zXqfGK6tKthLUuHx7KW0r1R)VKapBI zUAb7`Pll2FGNV?(t)a$Y6#qbBt!v=l#=8-w@T70QVZCmly>F|YuGvs7vc|H4FepDz zZJg<*K%T0)e{R#R&CC>R@47@9Z97ZlRqKPV@Cf#7uZZFn8|-JQDzYD`T(cDPev%IJ zQeES2*Q{T)I}K#q<1C!;%zWipnSyKG;1o~OgIDwsQ-g)ShyM#CZv`QG!&r!B`BQd` za$6N&h^T$DSD=*A(xUOgo9hu(W3Vpu9eaNzVSaXjf6ux-%uR}pW~dBREf_bf z7uKb@800smp-cOBqHrbTJ zboo}$*6hB3g(>2E)M+O=1)9ECVeLki;@+m^5PZ8_ujY*_Na%(C z^nq>poQ7Jh*$NMA;Zfr3EmGAH9j#o|Pa6UvE3)gSAk&L*q)gR4_QYy4fzL)Zty-oHO*4Z?;NPX5dF+tfVMhAGK*mT**#z4^9p4Hzpujd3qOkJ8(qA!STuWjegLFUSW+y(E!?k*5QA(5Zpp%!d|$K#sgFZ1^*4wg>O5) zzCyxa48{SH?!r9vc{^CfjF-_zpcg8Cf7$8O%EuVxpazTX#y8S^FCk^Br{-L{0dYGM z!WsSb?+9gy{@OKSrt*?|!7G5pkPlO>2|pPCG5kR!;<(6{6*p*#?Ox3AmS#4ZOeVO? zVGiOD(AhXF=F$Iks28^zn*>?iaFuQOm#g{pyI-}%jbUnuxLwBvSLeE$D1ZoEM|MBnb$X5U zhy6pY>8XE(lj|jz^)}_M{fwGlZ-}fPk*xVX9QO2%|5U^x9FPM~e3}C~B`D}Y8cyG8 zm3;ld(ZJy;_TlE;r3CL8ji1nvpq!h`Gpsa3d7Z|$UYhc=t_2R}Oz9`rSzX$F{Meun zrU?AH*Jt=#bwV$mzcWPeJGri(ref_UlAac4R*?`3t~#>^ZlwIqbrOKG5 z%uSrq0OaTqHjwBn@~ZIK+1iStaJ=~2>O5acN0+J(2edAFgCylrm|lOFA;L1h8l>Dt zVEHd+PivpN?Tv_+rk9osmS?(iaU-IKf`2@DB{n8{Y4P}o{;E6{e|BxQzALqek15eE z;~Dg64HTzlrQ5Kt-;+8CAKF~q)V!`k|fWV;#r|4 zo%|y>=b|!-knVI&Ww^Ep!5rhYuicsjn7w zy_Kc)l|o2OU6JoR_7s~7y7Y5|R2+H-gW_>ST7ZxHkmdXV?ji5?W=V%>tGl7rCCly? z;m`SI(aqF)&hKLSr`%oWiT106G^|EjZ3gOec` z)07_jTx!C8@sr!Xc(ty5yHTm2i!#489|?YeUW02ne`bxUL|qm4Bm}UxYoxNW^Y?H$ z&Egv;lP+6atjL0$Gz!d#CI$)S^#8a}jM26GIko*J2{*7%NRK|$PA(hx^tQ0=KzRP= z$JB^kX~ijT5CN8nO7ARciqStb6e)|&@APc{f~!5D!|j?=-#FH!MeJ^}P~=;33eSG; zl%C}#rK_Z};L3~*LP!3^Cu3K(c}S0|x3q+B+{u>{HCSWkOnc@Ak=pOw*-cxy%-D?a zDuPr>4-{ZEhfO-Eul3F2ddw9>zJXpg0k{txi)$=b`4#@Pp>nTOl|OxKW^h6$Qbj)| zAf~#j?5IYN);>3~=z{iji+y`I12?{Mo^GjbLiW>E&UDn2l$+RDeYeAj`+i5Cy*$Xd z(ik?r8Dt;7if7O$#e$Nr7{3v;pGNeOMZ-dstguz4f*~&vn-#Y<1Ua}v|J8~Kn!Qc8 z^ZyE{<@WW3@f`~8@NmKY1ew-SJ88?0tG!9(eVc(RO;1YA5GUMJob`XTvGPay_0eZg z;~0Uwy05C7yp|`3QrgHn1Fi<6XJ%Lb|0ClePK#|H%JPCdEkA8X23Pw+iT5|;L@qj_ z<|jb^_tY#wKX)P>E63pR`5P_JABv~yVP=vh>cMw1!0(*G_+J}foftF4ut14=U|6@N zI675hjhuOT|0&+r$IO#%@6eMl$J%?N&=c!_n0t0jh>ofu+IWe^ViU%olBtNJF>Gp> z{(Ey%k}PhfE(oQg;Kvk^2PrKjCsu@K&i*U^zovK)%k{~5c`-$x8$ekxjk<#2 zi<_I9@hgb;RdU-q{$It@KZo1-Akam-PZ2>B^>6?Ge*={9#-xirQlb-Nv;h%CjTinv zKOWOlbDK?#sGBRP6mR!LMbQU0kj|X){}8k+8su z!r+NMky~Z+o-Z`#6V+^k3VCF~*f~wECudX;e|rTu0n(s5@p)RuQr_w5X=3bSUNw9? z)CVQWXv^kMk}vIvF8JR2F_BMCGiw_Tt~ykm9xo^snk3l#@?0*b8YR(3ZYT^ zDPq?9xSGF%+ga^j#yWg83`1TQ1MmJxU6wy`68O`(Yj)V{Y?l2yf z)=!m!cCx!W;^xKNI~W4KaZ6^Zp3<0HISPvxVQj{9Pfkwq5PRU)*t^_W7Z7dn{L0e+ z9a(JNFbb&2ZP^WaZ%z!!`;vw7Z{B7Mg*iC2wzY{D1ymqVc);tGbraQ3uIDn7k$U=J z?>zX$XMYZphPLmorQBgW8>H|mZD2q872V$3zeIO+Q@?W z3ops`Kh5~7UQ_~6#Ne@ls3;am;6|n1$d9o>U4H^lT`-`$R&BU4c_OZ9kPbWIl`eHd zix(G-Wjp>ogDIi(SV?ffBSt=C4qOGnA5=Bss%YHpwAk865H;Ia2{K?q z?ec{2@xJFGKf0c4>6WA(H0m5VT?^md1@wDZh@QoDUQKCS2lS^qa*)#-4@p7AFSZeV zlw9|Jl!bP*^;I-lC%1(bQJ3Yz4$5^aANvq&^4(*?>d#@zS4`T_f`b^w-k{>?Ye2Ey zpPWEFo-~8V<%P(`B=q3RQcq99;Q-Y4NWq%$-#q{L(Z~m)Z3~FCs8^RaUU?rcep=bS z`iOiF(>ib8KR%I?pwa|^8fe#Ti{_VOncUOpozZFjH6eFF^qMNtE{3j|S;oU00q^Oe zXQxF(3}rqoji;pO@u>SC*74UO!?nMBV~+BRh@+5I1koNZ6gW~WZRSUoyxOLxYkfux z^MqB4iq7&W<=A#VKLNjOge-9N*Q*jyoSx%Qemt&6*-4C3r)-QZ2ZuJ{E0R4X(V}xL z&0mtIpiaT_x8O>`WUn<#B0n#E8_-Yq;=8(=w@bhg*_sZ7(2m=CS@PQ5!Bc`XDMT=D zBK^PMo^cthK!`R&;H_6)KY?z&mR1khpS^X<2l^{{{xh7nnm>MP_oShdW=ZCbqw>4{ z73P|q>nU3t+^tqW#{>5emYbXS@BZFMCQ;x+c@j5{yH8unOAtaWFt2*l87_98XfzCl z5_?3mJsI+af%xFjRUVtH0fpmdYIk%8D^nrB9V~ORWX)GaZziAc{|TJ=`5ddSWUAWG z*9Kx8lYG{laWh!jxUu0}PW+n7R%VM3)0hf16mQD?Cfb-vUETwNTtFd02w@kQ%cs7? zfa9ew!y2Q4QRLb$f_Hay))vTu(gw*o!ZH1nb=&Q=mP_t7uHA^qFkP%%V$RKI1ezm- zk&emLj@(z%S8eyCs+SN(m*xC&NCGmG-FubDL;_x+EybU$E{e?FojY27LyRoim4A&r z5@5-3lVBs`g`EuNEsODZOG^>p#g~b;ss%swL$hawenR(Ve==`|Q>!m@FqEk3g zw0jv985I>}vS4!9{e%XYNWQ(JhB2d>2M4Twq(Uk?Ks z2XSuMyE|ivi334vTp0m|{m*uCwfY&9*_(8H9}=`WIz_XUUm3x7p7a11m}g}_qV|sC z4uAMfJWZ5sv{kLlpp=BY8?k5$=SK^zM4{n0e1VFJ-m8G-D5Y!l+r^K5JtMYci$5oq zj$0?x7``Bgp2MO>PM|d}|2wL%xUB20In#s7{k7dwUy~ucnqi`}G(??c>$%M9_Yqx<%f~ta%qD;@x9rUMG6fEmf?sz-`^AZ8~Y5&NEOvcXeMAPl>?#aDf+yy zG9fh&+QE)17U!(lyZ9q1lfFRmH=y_bzR+6N+P)jfHeLwI+*dnZP*Z%1V7IqoJ;k&EHxT3R@g#XRadV_G;I&rlc3;RiL5>Ep{!5LOuauv&)BAw%5QR#)m}l9J zI93ROEeV-V+ZGF7@ERlY8Z8+HjeIQ;ka=<6FE3N$N$Kv|Gx{t9umgj&)vY}MB1kn^ z&`m-53EKF}4qF(AyEF6OFBYo~g*^MXyiD#|qBIwgkSNan`$hl-zZ(zQ(_dJYQFrJE zBysd&>%v6%=xpb%cG-S^N_oZdd_L+N_wxBQIy#xPE!QoIgv(dgRF9eccd$0@L*PXI z@?92dKl{t8q*jzLnZ!S>r#dpG#ieD=uQ`QM%p($r{L`tm6u7;=4F)R9*98fiw3x z)itW1ycvY5?>^K0t8ITpU4yYUPiT)Lc}`}ca0OVT0#&RnNnqc%T|1_E>UbWSIVAf= zF8<&rMYcN$lN;;nO44gC@uthlJ{TvEESqg{+mR$UEUYd6@kEwu-PbM=_YC0^^$lhS zg+R#PIue^d0cq-ybr`mwh^jB}7y|5^r%QTK1M#3cQS3MJziz15HM$j1V>A03g1ThJT38fxC~)GDKg z&;tnpJG(e;GQ5Y!$L)Sn&W}eVcO7_w0y`ZPTTg`of1{~r7L>D5Ie|NkY_DS58(Gs@ z-ao`tWpmqilCs{a%oda-G@d7P{D*q9fA4G zcQvDWX4B(dzp$KA$VAL*pVH;Re41Y4U`p6I_7^NLoI;%CmLo1#(h@T*M9&WYaezCl zMGZ6>3m|4KIOIkBh|~gwLX{lKf6W{SVFVG9?vXZeK1wI__-99Z<}X_U&q@THxQX1p zMXy$J=&4wJ zuKPOiGE|kt!-H(!RmS(bNE;?1CDn`X23z0saE(&*}G&v2W9(;@`MvX zr|`_5t=d($Je0v5QmrtyLPo7#o1e^QQ8iN7#2)D3r!vaxJi1RI!P#`w+R{9PT-drC z>ye+2iJ(0At%mc>0>$I3JlQ`)6?#xGH}l0!Mfp?0>}E}MCg&ASR8#%(s~Ze+drZ}8 z*f3fGXrFW^IMrti^~cy_@pWrR0`xl78QP3}PANpwUQp%da!~@E>-Qz4DKB3i{Yqpa zbN=q>9bBAi*?oR~?rK(xIH}ZvqzjZ7Humvn@iBCJ5pOtY#4hDr{mgP4_KHHRiT{mep9ZlWF@jTNjKlsXzwWA{qmnzV#X*NJAgXW)ZR$J*Pw&DDd&hB z@Id*w+FyXL#I+vbrOAtZ?~Q*hD2=}t{$R1Sf;4Y<+5ZeiLP+lHkai;J5N$ku!l+? zv92!a(U#g4UjE6+R%d%ujmR|?@ax;NsBQI{-Tq}}H#HN+GIoX-MHe7Aa`f}EUnyOv zFnP(kOX7$%LX4w7U~9S#hDcC17&Y`1DqSSb|k0v-nC886a$dV0{k zCY{llV z1D?D^LK{J(hvlZ{R|vd~02oo&orF0*pAUG`I#bk|_vItaTFN8=(Bk^_DbWp8 zO+vYv8{_4CNu!>!pv#-a`gUvw`;G{+P`dK2E7Le}=VMe%22(+&e~`_N-3446F{8nu zZ3<&%Ab6V|Azf#usok+6456twBn>8M&h_H&xhf=)F^f;w5ZDWiSK<&xpX-(Ti_AYa zib}Ne@O=PZ+P#MDE8GO=bcqZ!fPigiwh8?qjitsJADPXPP_z1R5pU+5mVCS2`ni|0 zOMUYPh?oXW;!$h45wOHQk5k_g!s}qLZ07@Y*~pE4U0Y-NE?bq(!F=V~d9Yj?*^c^JV zp{Gab*E|I?#qzeJN&G8h2Q(fgfsef%_1bR5dq2`V*5u^9vdlRg480gnd!*tf2P0i) zU+Q=-wUaYS;kFB2?-%Swu$7pFK56`XCFwlj;ORJjA$;YFVN*1CVt}8%?Gj;w^|DgB-<9`^#Yh`IE_ICu6_#@(;o#;9);o9^Oj7aI>T?V&;6J zIij#GN#f-U7njVq==g1SS#Ss9-JE0RRvSZ3-PTsP1N91&fKnK%qFQEczh9a@je#sb zkoy^|Ju!RWMlH;Oi29?aUCZVRTYa|>K%6*53c!8%?k&^{P#O~31szynQ19iyqq$&RiiJ-9f)FZdLzzAuZ>pZpT zP$V{4y>hM#xF#fc26ba<3NEdz7;OUp59xeB1aj8D?hxR%P1Hq$vMm!no?FU;QHA{V z>4W%TqiFN|?^g3Lrksn>90fA`x@Limt*hjF!YsL~G9CW=_ls^Q3%CM)t6zSgFmcUbv6UfF3a-n}0JUk88b_VcUB9fBVl{K% zIPfM1-gbMIRirF`v(x}XpXV>ZxqK26==R2*mU49G3vXMQ_%G&G9GN=InUdiM>wcMd zCE>gH&I6o%y%qZPj#lP<*oWF%icn=r?l!YeL2KDI`M^g7jG#2)t2~I96X1$cj@FAH zH1iGzkr}tU(hjoA(>0kxU0f`EeJRim{gRyl%SgXPnXlYc){SNzfbsk%aD>~J<+@7$ z1By!`md+rhAICWKLnnzH4HXsD;Z^LJe(5viqD^^7_K@`B_Ewi)5eyZ5;;Hzk^==@A zp560lgwKEXgyeuF!hBu~Qj05Q$Ht`1JJD5m?qx)&*>JK`_dxlQ5&#x#}fg z@|njE_wZ?X#;F>LGg&@|6S*(i)rCpfcX8F;7IE4qI4ieNJQ6ih&$XLPL_DloE5nM=qUr{ino~ z>{M0*Zfw5md00=ClLifNUj7V&gb<&{?WU-u-^AB|j)Qe3+vCvaG1saU@W?DcN=$W7 z8(+{3>$2CC22xNd!8CrxP(#l>_?I5LgXkz7|A{qsLEo+q(YMo}zm@xjTNRloUXrnP zrCP1^VQ{&M;$4x4z~DV;%z6YFb|tf3-wiKko5v^`Z7r)t8jK2}XNpb&0V%!sxVuT>ZZX&yuR%IY zc>AlfKX6n~+Zg>c3y{RVh<28$p(tT?g)?-)t}xbThoo(d?^I=YlB94~tIy4A@Ugl( zF;X=>8w*AL6YY;1MA9VZAdl5-p{I;1&{sWPWmwY_K_ zOC<8G6^Ef=&W8w^Uw2UWNAUN?9JI#~S7XUI)3U^t0!=ouaJP?URj|ydGmb}YV95Hu zUr0EEx<1~6(_$Al#zQc=5&4I#@831{t{%Sfv*fD%9M_$qC_mKctrIc09z<;KPaSTE zWmZo#4xD4-+kK@t_Cf~~+X+aCLR?D;;TY0E8|EY@o%7v0Xj<*z}c6;`zf6J zDM}iC`XLJ3m$!}T^J-m~*Z*9(0wdbcgpE9-h~3D(N9ML-V((qDMQWckl59lw1bXTB zJ%oa~7&pIz-s>Xd^}SY)r*fSKkmz?pgDHc-f;YUhx`+>{%`tZ^XJ^#9^N%!UoAgdhM9T3a`l=VxW|=Vr*0%wjlXoZZb#3Mdj0Wu zi9FLP&U{KF^rI$ed{tQIOsER_JAOXqZwwrKs+Sme&jOgJIy0=mLR1b~JX+Nsi+YMX zO||YT=&GaIz`U@1IN#APG4uyLg%v?8-rCkf1@t+sG(L%-FV)ZJDK%8LL5&PArW`KM zufoH{k^b}C{7M~e60_jZg`xPPzUFDQ`HX>lhJH}mC|;{;MhFb=LPsWe;FHS6s+UGs z_V28}p5lN^EVU?hPt5;*;SZCTI2vs!JL<)%9}T<~nyNjyzxVm9eO9;rhWsgJITWZ5 zPA)AN@uOwZq~=55Z_5Aix=KuQ8Y{IdXqF;!?(J z00S#k>lP5#^|9^riFT(KM}@nU#Cmt0Nu(lNk!2yvSg?aZdg<9HGY56?e+pTxOM!Hmj(fv(sUn4HKg7IjW| zQQ~9*z=?=*cYdUZm7@QN0L{YGCBh{qG&*MSg?pO#^tV?|RyGEk)!x%=iXi=W8!DmS0+UJ<%k5U@rVZV=pNlCvafPJ@ zn4;@&x%I`NMhk_#7A>9uuRxoG`3!6=_df%DPl66A8$P}e?L(mY2xI|@5!yu_;g;g( z=P0kALf>EcgFMu`fM{~5&|i4z?O(>Dz%(kkgax@zCDG0`1FQUea(qMoWulZGHexBF zhJAj&AYJsI;t4=&7Txvd=GpZV9W=N!B}=1-zT!XmoP=1s5%!MlH&agz?$J4JjS22^ zCU*Sc1bghc8@M=&U%)P}I@G}Frl7XY-ETcT6y5U$7*M_O7vvD&2^zKtg(%8fZfeSwBnv5@iUF znR{fts0V)=IX3N}f~XlH_!~r8+hR-#q0awN#eN_Y&?!G%H=cIDvd=9^l4M}EGW%?5 zg5f}lWF|Y{AbbzKlv2})S1c;_&DhKui6HpJ?xpUF_oEFbZ1WfD0gYe2?nyEkwKD1; zN)W#Q2S?CYU1sRe<_1Y?2EcNzD}guU&u3X96=U!x$NdVO^!*2eIqLQj2zA?*0ufre z)KA{-+-WFvcMK-gi!>&Rd^t_Fh7%=yrudOp8*4>GipG$BL3ITA1d?XWklrS52kEGL z*3QFm Date: Mon, 10 Mar 2025 10:40:56 +0100 Subject: [PATCH 10/21] update documentation --- doc/about/installation.rst | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/doc/about/installation.rst b/doc/about/installation.rst index b864b1e..db2fef1 100644 --- a/doc/about/installation.rst +++ b/doc/about/installation.rst @@ -7,7 +7,7 @@ Installation Guide Installing Python ---------------------------- -simbench is tested with Python 3.5, 3.6 and 3.7. We recommend the Anaconda Distribution, which provides a Python distribution that already includes a lot of modules for scientific computing that are needed. Of course it is also possible to use simbench with other distributions besides Anaconda. Anyway, it is important that the following package is included: +simbench is tested with multiple up-to-date Python versions. We recommend the Miniconda Distribution, which provides a Python distribution that already includes a lot of modules for scientific computing that are needed. Of course it is also possible to use simbench with other distributions besides Anaconda. Anyway, it is important that the following package is included: - pandapower @@ -20,23 +20,15 @@ The easiest way to install simbench is through pip: 1. Open a command prompt (e.g. start–>cmd on windows systems) -2. If you already work with the pandapower development version from GitHub, but did not yet register it to pip: - - a. Navigate your command prompt into your pandapower folder (with the command cd ). - - b. Register pandapower to pip, to not install pandapower a second time, via typing: - - :code:`pip install -e .` - -3. Install simbench by running: +2. Install simbench by running: :code:`pip install simbench` -Installing simbench without pip +Installing simbench without internet connection -------------------------------------------------------- -If you don't have internet access on your system or don't want to use pip for some other reason, simbench can also be installed without using pip: +If you don't have internet access on your system and already downloaded the repository (step 1), simbench can also be installed without from local files: 1. Download and unzip the current simbench distribution from PyPi under "Download files". @@ -46,7 +38,9 @@ If you don't have internet access on your system or don't want to use pip for so 3. Install simbench by running : - :code:`python setup.py install` + :code:`pip install -e .` + + This registers your local pandapower installation with pip, the option -e ensures the edits in the files have a direct impact on the pandapower installation. Development Version @@ -66,7 +60,7 @@ To install the latest version of simbench from github, simply follow these steps :code:`pip install -e .` - This registers your local simbench installation with pip. + This registers your local pandapower installation with pip, the option -e ensures the edits in the files have a direct impact on the pandapower installation. Test your installation From fb954b70e3154bdab249e5af941b05b5c674cd85 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 11 Mar 2025 18:53:24 +0100 Subject: [PATCH 11/21] Update pyproject.toml for pandapower >= 3.0 --- pyproject.toml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d415be9..7c2ca69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ maintainers = [ description = "Electrical Power System Benchmark Models." readme = "README.rst" license = { file = "LICENSE" } -requires-python = ">=3.8" +requires-python = ">=3.9" classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Console", @@ -27,14 +27,13 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", # Add the specific Python versions supported here, e.g.: - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12" ] dependencies = [ - "pandapower>=2.14.6" + "pandapower>=3.0.0" ] keywords = [ "benchmark grid", "power system", "network", "grid planning", "grid operation", "grid generation methodology", "comparability", "reproducibility", "electricity", "energy", "engineering", "simulation", "simbench", "time series", "future scenarios" @@ -72,4 +71,4 @@ find = {} addopts = ["--strict-markers"] markers = [ "slow: marks tests as slow (deselect with '-m \"not slow\"'), e.g. in run_fast_tests" -] \ No newline at end of file +] From 01da21c444b90a5250e1fb8cfe73013e45ce8769 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Wed, 12 Mar 2025 08:20:26 +0100 Subject: [PATCH 12/21] drop py3.8 support --- .github/workflows/github_test_action.yml | 2 +- .github/workflows/test_release.yml | 6 +++--- CHANGELOG.rst | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/github_test_action.yml b/.github/workflows/github_test_action.yml index f3062d5..8ebdbd5 100644 --- a/.github/workflows/github_test_action.yml +++ b/.github/workflows/github_test_action.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] + python-version: ['3.9', '3.10', '3.11', '3.12'] # Reminder: when removing support of an old python version here, then don't forget to remove # it also in pyproject.toml 'requires-python' steps: diff --git a/.github/workflows/test_release.yml b/.github/workflows/test_release.yml index fd1b0ea..94afa22 100644 --- a/.github/workflows/test_release.yml +++ b/.github/workflows/test_release.yml @@ -17,7 +17,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] + python-version: ['3.9', '3.10', '3.11', '3.12'] os: [ ubuntu-latest, windows-latest ] steps: @@ -40,14 +40,14 @@ jobs: run: | if ( '${{ matrix.python-version }}' -eq '3.9' ) { python -m pip install pypower } if ( '${{ matrix.python-version }}' -ne '3.9' ) { python -m pip install numba } - if ( '${{ matrix.python-version }}' -eq '3.8' -or '${{ matrix.python-version }}' -eq '3.10' ) { python -m pip install lightsim2grid } + if ( '${{ matrix.python-version }}' -eq '3.10' ) { python -m pip install lightsim2grid } - name: Install specific dependencies (Ubuntu) if: matrix.os == 'ubuntu-latest' run: | if ${{ matrix.python-version == '3.9' }}; then python -m pip install pypower; fi if ${{ matrix.python-version != '3.9' }}; then python -m pip install numba; fi - if ${{ matrix.python-version == '3.8' || matrix.python-version == '3.10' }}; then python -m pip install lightsim2grid; fi + if ${{ matrix.python-version == '3.10' }}; then python -m pip install lightsim2grid; fi - name: List all installed packages run: | diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e66f059..4302122 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,7 @@ Change Log [1.6.0] - 2024-xx-xx ---------------------- - [CHANGED] support pandapower geojson, released with pandapower version 3.0.0 +- [CHANGED] drop python 3.8 support [1.5.3] - 2024-04-23 ---------------------- From 611948089c3f9a9383c356ce9e3aa0a63be0436a Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 8 Apr 2025 17:02:57 +0200 Subject: [PATCH 13/21] support pandapower parameters step_dependency_table and tap_dependency_table, released with pandapower version 3.0.0 --- CHANGELOG.rst | 1 + simbench/converter/csv_pp_converter.py | 19 ++++++++++++++----- simbench/converter/pp_net_manipulation.py | 7 +++++++ .../test/converter/test_csv_pp_converter.py | 2 +- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4302122..bf8ceb3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,7 @@ Change Log [1.6.0] - 2024-xx-xx ---------------------- - [CHANGED] support pandapower geojson, released with pandapower version 3.0.0 +- [ADDED] support pandapower parameters step_dependency_table and tap_dependency_table, released with pandapower version 3.0.0 - [CHANGED] drop python 3.8 support [1.5.3] - 2024-04-23 diff --git a/simbench/converter/csv_pp_converter.py b/simbench/converter/csv_pp_converter.py index 6f250e1..ea1cd9e 100644 --- a/simbench/converter/csv_pp_converter.py +++ b/simbench/converter/csv_pp_converter.py @@ -3,7 +3,10 @@ # contributors (see AUTHORS file for details). All rights reserved. # This is the csv_pp_converter for the simbench project. -# pandapower 2.0.1 <-> simbench format (reasled status from 25.04.2019) + +# OPTIONAL IMPROVEMENTS for compatibility with future pandapower changes: constructing the +# dataframes net[element_table] by using the create_buses(), create_lines(), ... functions +# which where fast enough or not available at the time SimBench was developed. import os import pandas as pd @@ -28,7 +31,7 @@ from simbench.converter.pp_net_manipulation import _extend_pandapower_net_columns, \ _add_dspf_calc_type_and_phys_type_columns, _add_vm_va_setpoints_to_buses, \ _prepare_res_bus_table, replace_branch_switches, create_branch_switches, _add_coordID, \ - _set_vm_setpoint_to_trafos + _set_vm_setpoint_to_trafos, _set_dependency_table_parameters from simbench.converter.csv_data_manipulation import * from simbench.converter.csv_data_manipulation import _extend_coordinates_to_node_shape, \ _sort_switch_nodes_and_prepare_element_and_et, \ @@ -127,6 +130,7 @@ def csv_data2pp(csv_data): create_branch_switches(net) net.bus.loc[net.bus.type == "multi_auxiliary", "type"] = "auxiliary" _set_vm_setpoint_to_trafos(net, csv_data) + _set_dependency_table_parameters(net) _csv_types_to_pp2(net) ensure_bus_index_columns_as_int(net) @@ -222,15 +226,20 @@ def pp2csv_data(net1, export_pp_std_types=False, drop_inactive_elements=True, csv_data = _init_csv_tables(['elements', 'profiles', 'types', 'res_elements']) aux_nodes_are_reserved = reserved_aux_node_names is not None + if ("step_dependency_table" in net1.trafo.columns and net1.trafo.step_dependency_table.any()) \ + or \ + ("step_dependency_table" in net1.shunt.columns and net1.shunt.step_dependency_table.any()): + logger.warning("'step_dependency_table' is not supported in SimBench's csv data format.") + # --- net data preparation for converting _extend_pandapower_net_columns(net) if drop_inactive_elements: # attention: trafo3ws are not considered in current version of drop_inactive_elements() pp.drop_inactive_elements(net, respect_switches=False) - check_results = pp.deviation_from_std_type(net) - if check_results: + dev_from_std = pp.deviation_from_std_type(net) + if dev_from_std: logger.warning("There are deviations from standard types in elements: " + - str(["%s" % elm for elm in check_results.keys()]) + ". Only the standard " + + str(["%s" % elm for elm in dev_from_std.keys()]) + ". Only the standard " + "type values are converted to csv.") convert_parallel_branches(net) merge_busbar_coordinates(net, True) diff --git a/simbench/converter/pp_net_manipulation.py b/simbench/converter/pp_net_manipulation.py index 4c96d9c..8fdaf74 100644 --- a/simbench/converter/pp_net_manipulation.py +++ b/simbench/converter/pp_net_manipulation.py @@ -408,6 +408,13 @@ def _set_vm_setpoint_to_trafos(net, csv_data): idx_node].values +def _set_dependency_table_parameters(net): + for et in ["trafo", "trafo3w", "shunt"]: + param = "step_dependency_table" if et == "shunt" else "tap_dependency_table" + if param in net[et].columns: + net[et][param] = False + net[et][param] = net[et][param].astype(bool) + def _prepare_res_bus_table(net): """ Adds columns to be converted to csv_data. """ if net.res_bus.shape[0]: diff --git a/simbench/test/converter/test_csv_pp_converter.py b/simbench/test/converter/test_csv_pp_converter.py index 974d1af..84b9ac8 100644 --- a/simbench/test/converter/test_csv_pp_converter.py +++ b/simbench/test/converter/test_csv_pp_converter.py @@ -256,7 +256,7 @@ def test_example_simple(): logger.error("dtype adjustment of %s failed." % key) # drop result table rows if pp_is_27lower and "res_" in key: - if not key == "res_bus": + if key != "res_bus": net[key] = net[key].iloc[0:0] else: net[key].loc[:, ["p_mw", "q_mvar"]] = np.nan From 18544e6458760072bec89355830b50f11a3ef541 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 8 Apr 2025 17:11:48 +0200 Subject: [PATCH 14/21] Fixes #56 --- simbench/networks/profiles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simbench/networks/profiles.py b/simbench/networks/profiles.py index 61b2239..82a1e63 100644 --- a/simbench/networks/profiles.py +++ b/simbench/networks/profiles.py @@ -233,7 +233,7 @@ def get_absolute_profiles_from_relative_profiles( missing = list(applied_profiles[~applied_profiles.isin(relative_profiles.columns)]) if len(missing): raise ValueError("These profiles are set to be applied but are missing in the profiles " - "data: " + str(missings)) + "data: " + str(missing)) isna = applied_profiles.isnull() is_not_na_pos = np.arange(len(isna), dtype=int)[~isna.values] relative_profiles_vals[:, is_not_na_pos] = \ From 7db3e49eabe1d10544408f1973e07f4016ff61e5 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 8 Apr 2025 17:12:16 +0200 Subject: [PATCH 15/21] Change Log of #56 Fix --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bf8ceb3..c28aa6a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,7 @@ Change Log - [CHANGED] support pandapower geojson, released with pandapower version 3.0.0 - [ADDED] support pandapower parameters step_dependency_table and tap_dependency_table, released with pandapower version 3.0.0 - [CHANGED] drop python 3.8 support +- [FIXED] fix ValueError raise according to GitHub issue #56 [1.5.3] - 2024-04-23 ---------------------- From a3706f0690dccdbc0abc0d6d05c573d5b41ee7e1 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 8 Apr 2025 17:54:22 +0200 Subject: [PATCH 16/21] [CHANGED] rename parameter csv2pp parameter `no_generic_coord` by `fill_bus_geo_by_generic_data` --- CHANGELOG.rst | 1 + simbench/converter/csv_pp_converter.py | 27 ++++++++++++------- simbench/converter/pp_net_manipulation.py | 6 ++--- .../simbench_grids_basics_and_usage.ipynb | 13 +++------ 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c28aa6a..52ed1bd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,7 @@ Change Log - [ADDED] support pandapower parameters step_dependency_table and tap_dependency_table, released with pandapower version 3.0.0 - [CHANGED] drop python 3.8 support - [FIXED] fix ValueError raise according to GitHub issue #56 +- [CHANGED] rename parameter csv2pp parameter `no_generic_coord` by `fill_bus_geo_by_generic_data` [1.5.3] - 2024-04-23 ---------------------- diff --git a/simbench/converter/csv_pp_converter.py b/simbench/converter/csv_pp_converter.py index ea1cd9e..89c7f7c 100644 --- a/simbench/converter/csv_pp_converter.py +++ b/simbench/converter/csv_pp_converter.py @@ -45,7 +45,7 @@ __author__ = 'smeinecke' -def csv2pp(path, sep=';', add_folder_name=None, nrows=None, no_generic_coord=False): +def csv2pp(path, sep=';', add_folder_name=None, nrows=None, fill_bus_geo_by_generic_data=True): """ Conversion function from simbench csv format to pandapower. @@ -61,8 +61,9 @@ def csv2pp(path, sep=';', add_folder_name=None, nrows=None, no_generic_coord=Fal **nrows** (int, None) - number of rows to be read for profiles. If None, all rows will be read. - **no_generic_coord** (bool, False) - if True, no generic coordinates are created in case of - missing geodata. + **fill_bus_geo_by_generic_data** (bool, False) - if False, no generic coordinates are + created in case of missing geo data. If True, generic coordinates are create when at least + one bus misses geo data. OUTPUT: **net** (pandapowerNet) - the created pandapower net from csv files data @@ -82,17 +83,12 @@ def csv2pp(path, sep=';', add_folder_name=None, nrows=None, no_generic_coord=Fal csv_data = read_csv_data(path, sep, nrows=nrows) # run net creation - net = csv_data2pp(csv_data) - - # ensure geodata - if not no_generic_coord and any(pd.isnull(net.bus_geodata.x) | pd.isnull(net.bus_geodata.y)): - del net.bus_geodata - create_generic_coordinates(net) + net = csv_data2pp(csv_data, fill_bus_geo_by_generic_data=fill_bus_geo_by_generic_data) return net -def csv_data2pp(csv_data): +def csv_data2pp(csv_data, fill_bus_geo_by_generic_data=False): """ Internal functionality of csv2pp, but with a given dict of csv_data as input instead of csv files. """ # --- initializations @@ -134,6 +130,17 @@ def csv_data2pp(csv_data): _csv_types_to_pp2(net) ensure_bus_index_columns_as_int(net) + # --- ensure geodata + if not fill_bus_geo_by_generic_data: + if n_missing_geo_data := sum(pd.isnull(net.bus.geo) | (net.bus.geo == "")): + if n_missing_geo_data != len(net.bus): + logger.info(f"Due to {fill_bus_geo_by_generic_data=}, new generic geo data are " + f"created and overwrite existing bus geo data (" + f"{len(net.bus)-n_missing_geo_data} buses had geo data, " + f"{n_missing_geo_data} buses missed geo data).") + net.bus["geo"] = None + create_generic_coordinates(net) + return net diff --git a/simbench/converter/pp_net_manipulation.py b/simbench/converter/pp_net_manipulation.py index 8fdaf74..3489f57 100644 --- a/simbench/converter/pp_net_manipulation.py +++ b/simbench/converter/pp_net_manipulation.py @@ -186,10 +186,10 @@ def convert_geojson_to_bus_geodata_xy(net): def notnone(val): return isinstance(val, str) and bool(len(val)) net.bus_geodata = pd.DataFrame(np.nan, index=net.bus.index, columns=["x", "y"]) - # x = idxs = net.bus.index[net.bus.geo.apply(notnone)] - net.bus_geodata.loc[idxs, ["x", "y"]] = np.r_[[pd.read_json(StringIO(net.bus.geo.at[ - i])).coordinates.values for i in idxs]] + if len(idxs): + net.bus_geodata.loc[idxs, ["x", "y"]] = np.r_[[pd.read_json(StringIO(net.bus.geo.at[ + i])).coordinates.values for i in idxs]] def merge_busbar_coordinates(net, on_bus_geodata): diff --git a/tutorials/simbench_grids_basics_and_usage.ipynb b/tutorials/simbench_grids_basics_and_usage.ipynb index 517c7c6..a5efcc2 100644 --- a/tutorials/simbench_grids_basics_and_usage.ipynb +++ b/tutorials/simbench_grids_basics_and_usage.ipynb @@ -255,7 +255,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -273,14 +273,14 @@ "# let's run a simple power flow calculation while assuming an outage of the first line in feeder 1\n", "outage_line = 1\n", "outage_line_switches = net.switch.index[(net.switch.element == outage_line) & (net.switch.et == \"l\")]\n", - "net.switch.closed.loc[outage_line_switches] = False\n", + "net.switch.loc[outage_line_switches, \"closed\"] = False\n", "\n", "# resupply feeder 1 via feeder 5\n", "feeder1_buses = net.bus.index[net.bus.subnet.str.contains(\"Feeder1\")]\n", "feeder5_buses = net.bus.index[net.bus.subnet.str.contains(\"Feeder5\")]\n", "loop_line_1_5 = net.line.index[net.line.from_bus.isin(feeder1_buses) & net.line.to_bus.isin(feeder5_buses)]\n", "loop_switches_1_5 = net.switch.index[(net.switch.element == loop_line_1_5[0]) & (net.switch.et == \"l\")]\n", - "net.switch.closed.loc[loop_switches_1_5] = True\n", + "net.switch.loc[loop_switches_1_5, \"closed\"] = True\n", "\n", "# run a simple power flow\n", "pp.runpp(net)\n", @@ -988,7 +988,7 @@ "metadata": { "anaconda-cloud": {}, "kernelspec": { - "display_name": "Python 3.10.11 ('base')", + "display_name": "base", "language": "python", "name": "python3" }, @@ -1003,11 +1003,6 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.11" - }, - "vscode": { - "interpreter": { - "hash": "19d1d53a962d236aa061289c2ac16dc8e6d9648c89fe79f459ae9a3493bc67b4" - } } }, "nbformat": 4, From cf8b4fe6b0a4b12e0a76515069f20fbfd48c3651 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 8 Apr 2025 17:59:09 +0200 Subject: [PATCH 17/21] revise docs_check test action --- .github/workflows/github_test_action.yml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/workflows/github_test_action.yml b/.github/workflows/github_test_action.yml index 8ebdbd5..8e8cfe6 100644 --- a/.github/workflows/github_test_action.yml +++ b/.github/workflows/github_test_action.yml @@ -113,20 +113,14 @@ jobs: PYTHONPATH=$PYTHONPATH:$GITHUB_WORKSPACE python -m pytest -W error --nbmake -n=auto --nbmake-timeout=900 "./tutorials" docs_check: + needs: build + name: Sphinx docs check runs-on: ubuntu-latest - strategy: - matrix: - python-version: [ '3.9' ] steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - name: Check docs for Python ${{ matrix.python-version }} - uses: e2nIEE/sphinx-action@master + - name: Check sphinx build + uses: ammaraskar/sphinx-action@7.4.7 with: - pre-build-command: "python -m pip install --upgrade pip; - python -m pip install .[docs];" + pre-build-command: "python -m pip install uv && uv pip install .[docs] --system --link-mode=copy" build-command: "sphinx-build -b html . _build -W" docs-folder: "doc/" From 71328ff527f95e0d9ff9017fef44f6bb3337b501 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 8 Apr 2025 18:04:46 +0200 Subject: [PATCH 18/21] tiny fix --- simbench/test/converter/test_csv_pp_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simbench/test/converter/test_csv_pp_converter.py b/simbench/test/converter/test_csv_pp_converter.py index 84b9ac8..29a2f11 100644 --- a/simbench/test/converter/test_csv_pp_converter.py +++ b/simbench/test/converter/test_csv_pp_converter.py @@ -155,7 +155,7 @@ def test_convert_parallel_branches(): def test_test_network(): - net = csv2pp(test_network_path, no_generic_coord=True) + net = csv2pp(test_network_path, fill_bus_geo_by_generic_data=False) # test min/max ratio for elm in pp.pp_elements(bus=False, branch_elements=False, other_elements=False): From 16345f875c93f73a0995f3464920b798121c40e1 Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 8 Apr 2025 18:13:02 +0200 Subject: [PATCH 19/21] revise upload_release.yml --- .github/workflows/upload_release.yml | 33 +++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/.github/workflows/upload_release.yml b/.github/workflows/upload_release.yml index ecf0592..7606059 100644 --- a/.github/workflows/upload_release.yml +++ b/.github/workflows/upload_release.yml @@ -6,9 +6,16 @@ name: upload # Controls when the action will run. on: # Allows you to run this workflow manually from the Actions tab - push: - branches: - - master + workflow_dispatch: + inputs: + upload_server: + description: 'upload server' + required: true + default: 'testpypi' + type: choice + options: + - 'testpypi' + - 'pypi' # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -19,10 +26,12 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v4 + # Sets up python3 - uses: actions/setup-python@v5 with: python-version: '3.10' + # Installs and upgrades pip, installs other dependencies and installs the package from setup.py - name: Install dependencies run: | @@ -30,6 +39,19 @@ jobs: python3 -m pip install --upgrade pip # Install twine python3 -m pip install build setuptools wheel twine + + # Upload to TestPyPI + - name: Build and Upload to TestPyPI + if: ${{ inputs.upload_server == 'testpypi' }} + run: | + python3 -m build + python3 -m twine check dist/* --strict + python3 -m twine upload dist/* + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.TESTPYPI }} + TWINE_REPOSITORY: testpypi + # Upload to PyPI - name: Build and Upload to PyPI run: | @@ -40,10 +62,15 @@ jobs: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI }} TWINE_REPOSITORY: pypi + + # Wait some time - name: Sleep for 300s to make release available + if: ${{ inputs.upload_server == 'pypi' }} uses: juliangruber/sleep-action@v2 with: time: 300s + + # Run an installation for testing - name: Install simbench from PyPI run: | python3 -m pip install simbench From c37bd88682b42321f1bd00fd5ffbfec34cce02ae Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Tue, 8 Apr 2025 18:16:59 +0200 Subject: [PATCH 20/21] start release v1.6.0 --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 52ed1bd..acd89b5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Change Log ============= -[1.6.0] - 2024-xx-xx +[1.6.0] - 2024-04-09 ---------------------- - [CHANGED] support pandapower geojson, released with pandapower version 3.0.0 - [ADDED] support pandapower parameters step_dependency_table and tap_dependency_table, released with pandapower version 3.0.0 From fac7d6a78234296ba911c499e4df2f69d71ccbfc Mon Sep 17 00:00:00 2001 From: Steffen Meinecke Date: Wed, 9 Apr 2025 08:58:37 +0200 Subject: [PATCH 21/21] update net output in tutorial --- .../simbench_grids_basics_and_usage.ipynb | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/tutorials/simbench_grids_basics_and_usage.ipynb b/tutorials/simbench_grids_basics_and_usage.ipynb index a5efcc2..2745c95 100644 --- a/tutorials/simbench_grids_basics_and_usage.ipynb +++ b/tutorials/simbench_grids_basics_and_usage.ipynb @@ -23,7 +23,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -120,7 +120,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -138,7 +138,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -157,7 +157,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -179,27 +179,26 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "This pandapower network includes the following parameter tables:\n", - " - bus (97 element)\n", - " - load (96 element)\n", - " - sgen (102 element)\n", - " - switch (204 element)\n", - " - ext_grid (1 elements)\n", - " - line (99 element)\n", - " - trafo (2 element)\n", - " - measurement (37 element)\n", - " - bus_geodata (97 element)\n", - " - substation (1 elements)\n", - " - loadcases (6 element)" + " - bus (97 elements)\n", + " - load (96 elements)\n", + " - sgen (102 elements)\n", + " - switch (204 elements)\n", + " - ext_grid (1 element)\n", + " - line (99 elements)\n", + " - trafo (2 elements)\n", + " - measurement (37 elements)\n", + " - substation (1 element)\n", + " - loadcases (6 elements)" ] }, - "execution_count": 46, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" }