def test_dag_custom_operations(): """Tests if custom dantro data operations can be registered via the extensions made to PlotManager. NOTE This test has to be the FIRST here, because side effects of other tests can lead to some pre-conditions of this test not being valid. """ print("Available operations:", ", ".join(available_operations())) assert "my_custom_dummy_operation" not in available_operations() # Now, set up the model and its PlotManager model = ModelTest('dummy') mv, dm = model.create_run_load() mv.pm.raise_exc = True plot_cfgs = load_yml(DAG_PLOTS) # Should still not be available assert "my_custom_dummy_operation" not in available_operations() # Now, do some unrelated plot operation, i.e. not requiring model-specific # plot functions, but only utopya plot functions. # This should still lead to the _invoke_creator method being called, which # takes care of invoking register_operation mv.pm.plot("test", out_dir=mv.dirs['eval'], **plot_cfgs['uni_ts']) assert "my_custom_dummy_operation" in available_operations()
def test_Parameter_validation(): """Tests validation of the Parameter class.""" def get_match(element) -> Tuple[Any, str]: """If the given element is a sequence, assume the second value is an error match string """ if isinstance(element, (tuple, list)): return element[0], element[1] return element, None cfg = load_yml(PM_CFG_PATH) for case_name, case_cfg in chain(cfg["to_assert"].items(), cfg["shorthands"].items()): print(f"Testing case '{case_name}' ...") param = case_cfg["construct_param"] if "expected_default" in case_cfg: assert param.default == case_cfg["expected_default"] for val in case_cfg["validate_true"]: assert param.validate(val) for val in case_cfg["validate_false"]: val, match = get_match(val) assert not param.validate(val, raise_exc=False) with pytest.raises(utopya.parameter.ValidationError, match=match): assert param.validate(val)
def test_parameter_extraction(): """Tests extraction and dumping of Parameter objects from and to a configuration """ cfg = load_yml(PM_CFG_PATH)["to_extract"] model_cfg, params_to_validate = _extract(cfg, model_name='model') assert model_cfg, {} == _extract(model_cfg, model_name='model') assert len(params_to_validate) == 10 # NOTE When adjusting this, add the # explicit case below! # Check explicitly assert (params_to_validate[('model', 'param1', 'subparam1')] == Parameter(default=0.3, limits=[0, 2], dtype=float)) assert (params_to_validate[('model', 'param1', 'subparam3')] == Parameter(default=-3, limits=[None, 0], dtype=int, limits_mode='()')) assert (params_to_validate[('model', 'param1', 'subparam4')] == Parameter(default=42.2, limits=[0, None], limits_mode='(]')) assert (params_to_validate[( 'model', 'param2', )] == Parameter.from_shorthand(0.5, mode='is-probability')) assert (params_to_validate[('model', 'param3', 'subparam2y')] == Parameter.from_shorthand( True, mode='is-bool')) assert (params_to_validate[('model', 'param3', 'subparam2n')] == Parameter.from_shorthand( False, mode='is-bool')) assert (params_to_validate[('model', 'param3', 'subparam3')] == Parameter( default="baz", dtype=str, is_any_of=['foo', 'bar', 'baz', 'bam'])) assert (params_to_validate[('model', 'param4')] == Parameter.from_shorthand( 2, mode='is-int')) assert (params_to_validate[('model', 'param5')] == Parameter(default=0.4)) assert (params_to_validate[('model', 'param6')] == Parameter(default=None, dtype=str))
def test_yaml_roundtrip(): """Tests loading and writing from and to yaml files.""" def make_roundtrip(obj: Any) -> Any: s = io.StringIO("") yaml.dump(obj, stream=s) s = s.getvalue() return yaml.load(s) cfg = load_yml(PM_CFG_PATH)["to_extract"] model_cfg, params_to_validate = _extract(cfg, model_name='model') for param_key, param in params_to_validate.items(): assert make_roundtrip(param) == param # Check magic methods once more assert param == param assert param != 'foo' assert str(param)
def test_dag_plotting(): """Makes sure that DAG plotting works as expected""" # Now, set up the model model = ModelTest('dummy') mv, dm = model.create_run_load() mv.pm.raise_exc = True print(dm.tree) # Load some configuration arguments shared_kwargs = dict(out_dir=mv.dirs['eval']) plot_cfgs = load_yml(DAG_PLOTS) # Can do a simple DAG-based universe and multiverse plot for cfg_name, plot_cfg in plot_cfgs.items(): if cfg_name.startswith('.'): continue # The actual plotting print("Plotting '{}' ...".format(cfg_name)) mv.pm.plot(cfg_name, **shared_kwargs, **plot_cfg) print("Successfully plotted '{}'!\n\n".format(cfg_name))
def sc_run_kws(): return load_yml(STOP_CONDS_PATH)['run_kwargs']
def cfg() -> dict: return load_yml(TEST_CFG_PATH)
def test_graph_plot_class(): """Tests the plot_funcs._graph module. Mainly tests basic functionality, class attribute management and configuration parsing. Plotting of more complex graph data (using features like property-mapping) is tested in test_plotting.test_graph_plots. """ graph = nx.complete_graph(3, create_using=nx.Graph) digraph = nx.complete_graph(3, create_using=nx.DiGraph) # Initialize GraphPlot with defaults gp = GraphPlot(graph) # Check that all nodes and edges are selected for drawing assert gp._nodes_to_draw == [0, 1, 2] assert len(gp._edges_to_draw) == 3 assert gp._nodes_to_shrink == [] # Check properties assert isinstance(gp.g, nx.Graph) assert gp.g is not gp._g # Draw nodes, edges, and default labels gp.draw(node_labels=dict(enabled=True), edge_labels=dict(enabled=True)) # Draw again, re-creating the colormanagers gp.draw(nodes=dict(vmin=0.), edges=dict(edge_vmin=0.)) assert isinstance(gp._mpl_nodes, mpl.collections.PathCollection) assert isinstance(gp._mpl_edges, mpl.collections.LineCollection) assert isinstance(gp._mpl_node_labels, dict) assert isinstance(gp._mpl_edge_labels, dict) assert gp._mpl_node_cbar is None assert gp._mpl_edge_cbar is None # Check that the label drawing kwargs are not set permanently assert gp._node_label_kwargs == {} assert gp._edge_label_kwargs == {} # Add colorbars gp.add_colorbars() # Doing this twice should be ok and should remove the first colorbars gp.add_colorbars() assert isinstance(gp._mpl_node_cbar, mpl.colorbar.Colorbar) assert isinstance(gp._mpl_edge_cbar, mpl.colorbar.Colorbar) # Clear plot gp.clear_plot() # Doing this twice should be ok gp.clear_plot() # Done with testing the drawing on this figure. plt.close(gp.fig) # Test the subgraph selection # Select two nodes to draw, remove 1 node and 2 edges from the graph gp = GraphPlot(graph, select=dict(nodelist=[0, 1])) assert gp._g.number_of_nodes() == 2 assert gp._g.number_of_edges() == 1 assert gp._nodes_to_draw == [0, 1] assert len(gp._edges_to_draw) == 1 assert gp._nodes_to_shrink == [] # Select two nodes to draw, but don't remove anything from the graph gp = GraphPlot(graph, select=dict(nodelist=[0, 1], drop=False)) assert gp._g.number_of_nodes() == 3 assert gp._g.number_of_edges() == 3 assert gp._nodes_to_draw == [0, 1] assert len(gp._edges_to_draw) == 1 assert gp._nodes_to_shrink == [] # With open_edges, the non-selected node is still drawn but shrinked gp = GraphPlot(graph, select=dict(nodelist=[0, 1], open_edges=True)) assert gp._g.number_of_nodes() == 3 assert gp._g.number_of_edges() == 3 assert gp._nodes_to_draw == [0, 1, 2] assert len(gp._edges_to_draw) == 3 assert gp._nodes_to_shrink == [2] # Now go through configurations and test initialization and drawing configs = load_yml(GRAPH_PLOT_CLS) for name, cfg in configs.items(): fig = plt.figure() # Try using a graphviz node layout, which requires pydot if name == "graphviz": try: import pydot except ImportError: with pytest.raises(ImportError, match="No module named 'pydot'"): gp = GraphPlot(digraph, fig=fig, **cfg) continue # Configurations for which an Error is raised if "_raises" in cfg: exc_type = getattr(builtins, cfg.pop("_raises")) match = cfg.pop("_match") with pytest.raises(exc_type, match=match): gp = GraphPlot(digraph, fig=fig, **cfg) gp.draw() gp.clear_plot() # Configurations that lead to a warning elif "_warns" in cfg: warn_type = getattr(builtins, cfg.pop("_warns")) match = cfg.pop("_match") with pytest.warns(warn_type, match=match): gp = GraphPlot(digraph, fig=fig, **cfg) gp.draw() gp.clear_plot() # These should work fine else: gp = GraphPlot(digraph, fig=fig, **cfg) gp.draw() gp.clear_plot() plt.close(fig)