def test_post_solve_watershed_stable(client, watershed_requests, watershed_responses, watershed_test_case): size, pct_tmnt, dirty_nodes = watershed_test_case watershed_request = watershed_requests[size, pct_tmnt] post_response = watershed_responses[size, pct_tmnt] results = post_response.json()["data"]["results"] reqd_min_attrs = attrs_to_resubmit(results) previous_results = { "previous_results": [{k: dct[k] for k in dct.keys() if k in reqd_min_attrs + ["node_id"]} for dct in results] } g = graph_factory(watershed_request["graph"]) subg = nx.DiGraph(g.subgraph(get_subset(g, nodes=dirty_nodes)).edges) subgraph = {"graph": nxGraph_to_dict(subg)} new_request = deepcopy(watershed_request) new_request.update(subgraph) new_request.update(previous_results) payload = json.dumps(new_request) route = config.API_LATEST + "/watershed/solve" response = client.post(route, data=payload) subgraph_results = response.json()["data"]["results"] check_subgraph_response_equal(subgraph_results, results)
def test_watershed_solve_sequence(contexts, watershed_requests, n_nodes, pct_tmnt): watershed_request = deepcopy(watershed_requests[n_nodes, pct_tmnt]) context = contexts["default"] g = graph_factory(watershed_request["graph"]) initial_results = land_surface_loading(watershed_request, False, context=context)["summary"] db = pandas.DataFrame(initial_results).set_index("node_id") _node_list = solution_sequence( watershed_request["graph"], 16)["solution_sequence"]["parallel"][0]["series"] node_list = [[n["id"] for n in nl["nodes"]] for nl in _node_list] presults = [] # no initial results, obvs for branch_nodes in node_list: # this subgraph is empty, has no data. subg = nx.DiGraph(g.subgraph(branch_nodes).edges) subgraph = {"graph": nxGraph_to_dict(subg)} reqd_min_attrs = attrs_to_resubmit(presults) previous_results = { "previous_results": [{ k: dct[k] for k in dct.keys() if k in reqd_min_attrs + ["node_id"] } for dct in presults if dct["node_id"] in subg.nodes()] } subg_request = deepcopy(watershed_request) subg_request.update(subgraph) subg_request.update(previous_results) subgraph_response_dict = solve_watershed( subg_request, False, context=context, ) subgraph_results = subgraph_response_dict["results"] presults.extend(subgraph_results) db = db.combine_first( pandas.DataFrame(subgraph_results).set_index("node_id")) response_dict = solve_watershed( watershed=watershed_request, treatment_pre_validated=False, context=context, ) results = response_dict["results"] + response_dict["leaf_results"] check_db = pandas.DataFrame(results).set_index("node_id").sort_index(0) check_results_dataframes(db.sort_index(0), check_db)
def test_solve_watershed_stable_with_subsets(contexts, watershed_graph, initial_node_data): g, data = watershed_graph, deepcopy(initial_node_data) context = contexts["default"] nx.set_node_attributes(g, data) solve_watershed_loading(g, context) # from the previous solution, we only need the keys which contain the accumulated keys. # keys = ["_direct", "_upstream", "_cumul", "_inflow", "_discharged"] reqd_min_attrs = attrs_to_resubmit( [data for n, data in g.nodes(data=True)]) prev_solve_data = { n: {k: dct[k] for k in dct.keys() if k in reqd_min_attrs} for n, dct in g.nodes(data=True) } # check single dirty nodes for dirty_node in g.nodes(): dirty_nodes = [dirty_node] subg = nx.DiGraph(g.subgraph(get_subset(g, nodes=dirty_nodes)).edges) # always send the info that was sent the first time nx.set_node_attributes( subg, {k: v for k, v in data.items() if k in subg.nodes()}) nx.set_node_attributes( subg, {k: v for k, v in prev_solve_data.items() if k not in dirty_nodes}) solve_watershed_loading(subg, context) check_graph_data_equal(g, subg) # check multiple dirty nodes numpy.random.seed(42) for dirty_nodes in [ numpy.random.choice(g.nodes(), size=size, replace=False) for size in [2, 4, 6, 8, 10] ]: subg = nx.DiGraph(g.subgraph(get_subset(g, nodes=dirty_nodes)).edges) # always send the info that was sent the first time nx.set_node_attributes( subg, {k: v for k, v in data.items() if k in subg.nodes()}) nx.set_node_attributes( subg, {k: v for k, v in prev_solve_data.items() if k not in dirty_nodes}) solve_watershed_loading(subg, context) check_graph_data_equal(g, subg)
def solve_watershed( watershed: Dict[str, Any], treatment_pre_validated: bool, context: Dict[str, Any], ) -> Dict[str, Any]: """Main program function. This function builds the network and solves for water quality at each node in the input graph. Parameters ---------- watershed : dict watersheds have 5 data entities: 1. graph : defines the connectivity of each component part of the watershed. These components can be any of: land surface, treatment facility, treatment site, other/nothing/null. See `src.network. 2. land_surfaces : which load the graph with """ response = {} build_nomo.cache_clear() g, msgs = initialize_graph( watershed, treatment_pre_validated, context, ) response["errors"] = [e for e in msgs if "error" in e.lower()] response["warnings"] = [w for w in msgs if "warning" in w.lower()] try: # pragma: no branch solve_watershed_loading(g, context=context) all_results = [dct for n, dct in g.nodes(data=True)] results = [dct for dct in all_results if not dct["_is_leaf"]] leafs = [dct for dct in all_results if dct["_is_leaf"]] previous_results_keys = attrs_to_resubmit(all_results) response["results"] = results response["leaf_results"] = leafs response["previous_results_keys"] = previous_results_keys except Exception as e: # pragma: no cover response["errors"].append(str(e)) return response
def test_stable_watershed_stable_subgraph_solutions(contexts, watershed_requests, watershed_test_case): n_nodes, pct_tmnt, dirty_nodes = watershed_test_case watershed_request = deepcopy(watershed_requests[(n_nodes, pct_tmnt)]) context = contexts["default"] response_dict = solve_watershed( watershed=watershed_request, treatment_pre_validated=False, context=context, ) results = response_dict["results"] reqd_min_attrs = attrs_to_resubmit(results) previous_results = { "previous_results": [{k: dct[k] for k in dct.keys() if k in reqd_min_attrs + ["node_id"]} for dct in results] } g = graph_factory(watershed_request["graph"]) # this subgraph is empty, has no data. subg = nx.DiGraph(g.subgraph(get_subset(g, nodes=dirty_nodes)).edges) subgraph = {"graph": nxGraph_to_dict(subg)} new_request = deepcopy(watershed_request) new_request.update(subgraph) new_request.update(previous_results) subgraph_response_dict = solve_watershed( watershed=new_request, treatment_pre_validated=False, context=context, ) subgraph_results = subgraph_response_dict["results"] check_subgraph_response_equal(subgraph_results, results)