--- file_format: mystnb --- # Division Test Cases To facilitate testing, we have provided a suite of canonical examples that cover the basic, simple scenarios that can occur in segmentation and tracking. Here we describe them and show visualizations of each case. Metrics should test all the basic and division error cases. The examples are generated by functions in the `tests/examples/` directory. ```{code-cell} ipython3 --- tags: [remove-input] --- import sys sys.path.append("../../../tests") import matplotlib.pyplot as plt from matplotlib.patches import Patch import examples.graphs as ex_graphs from traccuracy import TrackingGraph ``` ```{code-cell} ipython3 --- tags: [remove-input] --- def get_loc(graph, node): return graph.graph.nodes[node]["t"], graph.graph.nodes[node]["y"] def plot_graph(ax, graph: TrackingGraph, color="black"): if graph.graph.number_of_nodes() == 0: return [0, 0], [0, 0] ids = list(graph.graph.nodes) x = [graph.graph.nodes[node]["t"] for node in ids] y = [graph.graph.nodes[node]["y"] for node in ids] ax.scatter(x, y, color=color) for _x, _y, _id in zip(x, y, ids): ax.text(_x + 0.05, _y + 0.05, str(_id)) for u, v in graph.graph.edges(): xs = [graph.graph.nodes[u]["t"], graph.graph.nodes[v]["t"]] ys = [graph.graph.nodes[u]["y"], graph.graph.nodes[v]["y"]] ax.plot(xs, ys, color=color) return [max(x), min(x)], [max(y), min(y)] def plot_matching(ax, matched, color="grey"): for u, v in matched.mapping: xs = [ matched.gt_graph.graph.nodes[u]["t"], matched.pred_graph.graph.nodes[v]["t"], ] ys = [ matched.gt_graph.graph.nodes[u]["y"], matched.pred_graph.graph.nodes[v]["y"], ] ax.plot(xs, ys, color=color, linestyle="dashed") def plot_matched(examples, title): gt_color = "black" pred_color = "blue" mapping_color = "grey" fig, ax = plt.subplots(1, len(examples) + 1, figsize=(3 * len(examples) + 1, 2)) for i, matched in enumerate(examples): axis = ax[i] xbounds, ybounds = plot_graph(axis, matched.gt_graph, color=gt_color) bounds = plot_graph(axis, matched.pred_graph, color=pred_color) xbounds.extend(bounds[0]) ybounds.extend(bounds[1]) plot_matching(axis, matched, color=mapping_color) axis.set_ybound(min(ybounds) - 0.5, max(ybounds) + 0.5) axis.set_xbound(min(xbounds) - 0.5, max(xbounds) + 0.5) axis.set_ylabel("Y Value") axis.set_xlabel("Time") handles = [ Patch(color=gt_color), Patch(color=pred_color), Patch(color=mapping_color), ] labels = ["Ground Truth", "Prediction", "Mapping"] ax[-1].legend(handles=handles, labels=labels, loc="center") ax[-1].set_axis_off() plt.tight_layout() fig.suptitle(title, y=1.05) ``` ```{code-cell} ipython3 plot_matched([ex_graphs.empty_pred_div(1), ex_graphs.empty_gt_div(1)], "Empty Divisions") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.good_div(t) for t in [0, 1, 2]], "Correct Divisions") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.fp_div(t) for t in [0, 1]], "False Positive Division") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.one_child(t) for t in [0, 1]], "Only One Child") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.no_children(t) for t in [0, 1]], "No Children") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.wrong_child(t) for t in [0, 1]], "Incorrect Child") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.wrong_children(t) for t in [0, 1]], "Incorrect Children") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.div_daughter_gap(), ex_graphs.div_daughter_dual_gap()], "Skip edge divisions") ``` ## Shifted Division Cases ```{code-cell} ipython3 plot_matched([ex_graphs.div_parent_gap(), ex_graphs.div_parent_daughter_gap(), ex_graphs.div_shifted_one_side_skip()], "Skip edge shifted divisions") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.div_1early_end(), ex_graphs.div_1early_mid()], "1 Frame Early") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.div_2early_end(), ex_graphs.div_2early_mid()], "2 Frames Early") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.div_1late_end(), ex_graphs.div_1late_mid()], "1 Frame Late") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.div_2late_end(), ex_graphs.div_2late_mid()], "2 Frames Late") ``` ```{code-cell} ipython3 plot_matched([ex_graphs.div_shift_min_match()], "Minimal matching for shifted divisions") ``` ```{code-cell} ipython3 plot_matched( [ex_graphs.div_shift_bad_match_pred(), ex_graphs.div_shift_bad_match_daughter()], "Insufficient matching for shifted divisions", ) ```