Repository: Qiskit/qiskit

Issue:
plot_error_map fails
### Environment

- **Qiskit Terra version**: 0.20
- **Python version**: 3.10
- **Operating system**: 
```python
backend = provider.backend.ibmq_kolkata
plot_error_map(backend)
```

gives

```
ValueError: shape mismatch: objects cannot be broadcast to a single shape
```

### What is happening?

fails for some reason in the measurement bar plots

### How can we reproduce the issue?

run above

### What should happen?

works

### Any suggestions?

_No response_


Discussion:
Yeah, it looks like a bug I inadvertently added in #7814 (there are also bugs with the V2 path too). I'll prep a fix and tag it for 0.20.1.

Resolving patch:
diff --git a/qiskit/visualization/gate_map.py b/qiskit/visualization/gate_map.py
--- a/qiskit/visualization/gate_map.py
+++ b/qiskit/visualization/gate_map.py
@@ -20,6 +20,7 @@
 
 from qiskit.exceptions import QiskitError
 from qiskit.utils import optionals as _optionals
+from qiskit.providers.exceptions import BackendPropertyError
 from .exceptions import VisualizationError
 from .utils import matplotlib_close_if_inline
 
@@ -910,14 +911,16 @@ def plot_error_map(backend, figsize=(12, 9), show_title=True, qubit_coordinates=
 
     backend_version = _get_backend_interface_version(backend)
     if backend_version <= 1:
+        backend_name = backend.name()
         num_qubits = backend.configuration().n_qubits
         cmap = backend.configuration().coupling_map
-        props = backend.properties().to_dict()
+        props = backend.properties()
+        props_dict = props.to_dict()
         single_gate_errors = [0] * num_qubits
         read_err = [0] * num_qubits
         cx_errors = []
         # sx error rates
-        for gate in props["gates"]:
+        for gate in props_dict["gates"]:
             if gate["gate"] == "sx":
                 _qubit = gate["qubits"][0]
                 for param in gate["parameters"]:
@@ -937,16 +940,18 @@ def plot_error_map(backend, figsize=(12, 9), show_title=True, qubit_coordinates=
                         break
 
             for line in cmap:
-                for item in props["gates"]:
+                for item in props_dict["gates"]:
                     if item["qubits"] == line:
                         cx_errors.append(item["parameters"][0]["value"])
                         break
         for qubit in range(num_qubits):
-            for item in props["qubits"][qubit]:
-                if item["name"] == "readout_error":
-                    read_err.append(item["value"])
+            try:
+                read_err[qubit] = props.readout_error(qubit)
+            except BackendPropertyError:
+                pass
 
     else:
+        backend_name = backend.name
         num_qubits = backend.num_qubits
         cmap = backend.coupling_map
         two_q_error_map = {}
@@ -977,7 +982,7 @@ def plot_error_map(backend, figsize=(12, 9), show_title=True, qubit_coordinates=
                     if not [edge[1], edge[0]] in cmap:
                         directed = True
                         break
-            for line in cmap:
+            for line in cmap.get_edges():
                 err = two_q_error_map.get(tuple(line), 0)
                 cx_errors.append(err)
 
@@ -1095,6 +1100,6 @@ def plot_error_map(backend, figsize=(12, 9), show_title=True, qubit_coordinates=
         spine.set_visible(False)
 
     if show_title:
-        fig.suptitle(f"{backend.name()} Error Map", fontsize=24, y=0.9)
+        fig.suptitle(f"{backend_name} Error Map", fontsize=24, y=0.9)
     matplotlib_close_if_inline(fig)
     return fig


Test patch:
diff --git a/test/python/visualization/references/kolkata_error.png b/test/python/visualization/references/kolkata_error.png
new file mode 100644
Binary files /dev/null and b/test/python/visualization/references/kolkata_error.png differ
diff --git a/test/python/visualization/references/kolkata_v2_error.png b/test/python/visualization/references/kolkata_v2_error.png
new file mode 100644
Binary files /dev/null and b/test/python/visualization/references/kolkata_v2_error.png differ
diff --git a/test/python/visualization/references/washington_error.png b/test/python/visualization/references/washington_error.png
new file mode 100644
Binary files /dev/null and b/test/python/visualization/references/washington_error.png differ
diff --git a/test/python/visualization/references/washington_v2_error.png b/test/python/visualization/references/washington_v2_error.png
new file mode 100644
Binary files /dev/null and b/test/python/visualization/references/washington_v2_error.png differ
diff --git a/test/python/visualization/test_gate_map.py b/test/python/visualization/test_gate_map.py
--- a/test/python/visualization/test_gate_map.py
+++ b/test/python/visualization/test_gate_map.py
@@ -18,7 +18,18 @@
 from PIL import Image
 from ddt import ddt, data
 from qiskit.test.mock import FakeProvider
-from qiskit.visualization.gate_map import plot_gate_map, plot_coupling_map, plot_circuit_layout
+from qiskit.providers.fake_provider import (
+    FakeKolkata,
+    FakeWashington,
+    FakeKolkataV2,
+    FakeWashingtonV2,
+)
+from qiskit.visualization.gate_map import (
+    plot_gate_map,
+    plot_coupling_map,
+    plot_circuit_layout,
+    plot_error_map,
+)
 from qiskit.utils import optionals
 from qiskit import QuantumRegister, QuantumCircuit
 from qiskit.transpiler import Layout
@@ -93,6 +104,54 @@ def test_plot_gate_map_no_backend(self):
             self.assertImagesAreEqual(Image.open(img_buffer), img_ref, 0.2)
         plt.close(fig)
 
+    @unittest.skipIf(not optionals.HAS_MATPLOTLIB, "matplotlib not available.")
+    def test_plot_error_map_backend_v1(self):
+        """Test plotting error map with fake backend v1."""
+        backend = FakeKolkata()
+        img_ref = path_to_diagram_reference("kolkata_error.png")
+        fig = plot_error_map(backend)
+        with BytesIO() as img_buffer:
+            fig.savefig(img_buffer, format="png")
+            img_buffer.seek(0)
+            self.assertImagesAreEqual(Image.open(img_buffer), img_ref, 0.2)
+        plt.close(fig)
+
+    @unittest.skipIf(not optionals.HAS_MATPLOTLIB, "matplotlib not available.")
+    def test_plot_error_map_backend_v2(self):
+        """Test plotting error map with fake backend v2."""
+        backend = FakeKolkataV2()
+        img_ref = path_to_diagram_reference("kolkata_v2_error.png")
+        fig = plot_error_map(backend)
+        with BytesIO() as img_buffer:
+            fig.savefig(img_buffer, format="png")
+            img_buffer.seek(0)
+            self.assertImagesAreEqual(Image.open(img_buffer), img_ref, 0.2)
+        plt.close(fig)
+
+    @unittest.skipIf(not optionals.HAS_MATPLOTLIB, "matplotlib not available.")
+    def test_plot_error_map_over_100_qubit(self):
+        """Test plotting error map with large fake backend."""
+        backend = FakeWashington()
+        img_ref = path_to_diagram_reference("washington_error.png")
+        fig = plot_error_map(backend)
+        with BytesIO() as img_buffer:
+            fig.savefig(img_buffer, format="png")
+            img_buffer.seek(0)
+            self.assertImagesAreEqual(Image.open(img_buffer), img_ref, 0.2)
+        plt.close(fig)
+
+    @unittest.skipIf(not optionals.HAS_MATPLOTLIB, "matplotlib not available.")
+    def test_plot_error_map_over_100_qubit_backend_v2(self):
+        """Test plotting error map with large fake backendv2."""
+        backend = FakeWashingtonV2()
+        img_ref = path_to_diagram_reference("washington_v2_error.png")
+        fig = plot_error_map(backend)
+        with BytesIO() as img_buffer:
+            fig.savefig(img_buffer, format="png")
+            img_buffer.seek(0)
+            self.assertImagesAreEqual(Image.open(img_buffer), img_ref, 0.2)
+        plt.close(fig)
+
 
 if __name__ == "__main__":
     unittest.main(verbosity=2)