diff --git a/CHANGELOG.md b/CHANGELOG.md index a0f40251f..e45c11665 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Empty outputs layer removed from flow's partial order. - Flow well-formedness check does not trigger false negative for flows on open graphs without outputs. +- #554, #560: Pauli-measurement entry is removed from the legend when visualizing an open graph without Pauli measurements. + ### Changed - #452: Use `uv` for dependency management diff --git a/graphix/visualization.py b/graphix/visualization.py index 1212e6023..3709678dd 100644 --- a/graphix/visualization.py +++ b/graphix/visualization.py @@ -587,16 +587,20 @@ def _draw_legend(self) -> None: marker=DEFAULT_NODE_MARKER, ) if self.options.pauli_measurements: - plt.scatter( - [], - [], - edgecolor=DEFAULT_NODE_EC, - facecolor=PAULI_NODE_FC, - s=150, - zorder=2, - label="Pauli-measured nodes", - marker=DEFAULT_NODE_MARKER, + has_pauli_measurements = any( + isinstance(measurement, PauliMeasurement) for measurement in self.og.measurements.values() ) + if has_pauli_measurements: + plt.scatter( + [], + [], + edgecolor=DEFAULT_NODE_EC, + facecolor=PAULI_NODE_FC, + s=150, + zorder=2, + label="Pauli-measured nodes", + marker=DEFAULT_NODE_MARKER, + ) plt.plot([], [], "--", c=EDGE_C, label="Graph edge") assert self._source is not None @@ -612,7 +616,25 @@ def _draw_legend(self) -> None: case _: assert_never(self._source) - plt.legend(loc="center left", fontsize=10, bbox_to_anchor=(1, 0.5)) + # Set scatterpoints=1 to prevent node icons from appearing + # three times in the legend with the Agg backend used by + # pytest-mpl. + legend = plt.legend(loc="center left", fontsize=10, bbox_to_anchor=(1, 0.5), scatterpoints=1) + + # Resize the figure to accommodate the legend. + fig = plt.gcf() + fig.canvas.draw() # Force layout + + bbox = legend.get_window_extent() + + # Width of the legend in inches + padding = 0.5 + legend_width = bbox.width / fig.dpi + padding + legend_height = bbox.height / fig.dpi + padding + + width, height = fig.get_size_inches() + fig.set_size_inches(width + legend_width, max(height, legend_height), forward=True) + fig.subplots_adjust(right=width / (width + legend_width)) @singledispatch diff --git a/tests/baseline/test_causal_flow_draw.png b/tests/baseline/test_causal_flow_draw.png index 9c474e962..6f60dcbb8 100644 Binary files a/tests/baseline/test_causal_flow_draw.png and b/tests/baseline/test_causal_flow_draw.png differ diff --git a/tests/baseline/test_draw_graph_reference_False.png b/tests/baseline/test_draw_graph_reference_False.png index 55b09a743..15b7b7eb9 100644 Binary files a/tests/baseline/test_draw_graph_reference_False.png and b/tests/baseline/test_draw_graph_reference_False.png differ diff --git a/tests/baseline/test_draw_graph_reference_True.png b/tests/baseline/test_draw_graph_reference_True.png index 64972df49..c374d91b6 100644 Binary files a/tests/baseline/test_draw_graph_reference_True.png and b/tests/baseline/test_draw_graph_reference_True.png differ diff --git a/tests/baseline/test_gflow_draw.png b/tests/baseline/test_gflow_draw.png index 6288c67ea..0b0d46110 100644 Binary files a/tests/baseline/test_gflow_draw.png and b/tests/baseline/test_gflow_draw.png differ diff --git a/tests/baseline/test_legend_pauli_measurements_False.png b/tests/baseline/test_legend_pauli_measurements_False.png new file mode 100644 index 000000000..8f2f73a58 Binary files /dev/null and b/tests/baseline/test_legend_pauli_measurements_False.png differ diff --git a/tests/baseline/test_legend_pauli_measurements_True.png b/tests/baseline/test_legend_pauli_measurements_True.png new file mode 100644 index 000000000..84035cc6b Binary files /dev/null and b/tests/baseline/test_legend_pauli_measurements_True.png differ diff --git a/tests/baseline/test_og_draw.png b/tests/baseline/test_og_draw.png index 1f14d4b1e..661a1ca53 100644 Binary files a/tests/baseline/test_og_draw.png and b/tests/baseline/test_og_draw.png differ diff --git a/tests/baseline/test_pauli_flow_draw.png b/tests/baseline/test_pauli_flow_draw.png index 642ace731..3276e002e 100644 Binary files a/tests/baseline/test_pauli_flow_draw.png and b/tests/baseline/test_pauli_flow_draw.png differ diff --git a/tests/baseline/test_xzcorr_draw.png b/tests/baseline/test_xzcorr_draw.png index a365384f7..7460bcd30 100644 Binary files a/tests/baseline/test_xzcorr_draw.png and b/tests/baseline/test_xzcorr_draw.png differ diff --git a/tests/test_visualization.py b/tests/test_visualization.py index 598082bc8..c8936530d 100644 --- a/tests/test_visualization.py +++ b/tests/test_visualization.py @@ -265,3 +265,17 @@ def test_draw_graph_reference(flow_and_not_pauli_presimulate: bool) -> Figure: flow_from_pattern=flow_and_not_pauli_presimulate, node_distance=(1, 1), measurement_labels=True, legend=False ) return plt.gcf() + + +@pytest.mark.usefixtures("mock_plot") +@pytest.mark.parametrize("infer_pauli_measurements", [False, True]) +@pytest.mark.mpl_image_compare +def test_legend_pauli_measurements(infer_pauli_measurements: bool) -> Figure: + # See https://github.com/TeamGraphix/graphix/issues/554 + circuit = Circuit(1) + circuit.h(0) + pattern = circuit.transpile().pattern + if infer_pauli_measurements: + pattern = pattern.infer_pauli_measurements() + pattern.draw() + return plt.gcf()