Repository: Qiskit/qiskit

Issue:
pi_check does not seems to be running over the values in bind_parameters 
After #2808, the visualizations represent fractions of `pi` very nicely. 
 
```python
my_u2_circuit = QuantumCircuit(1, name='my_u2')
phi = Parameter('phi')
lam = Parameter('lambda')
my_u2_circuit.u3(3.141592653589793, phi, lam, 0)
print(my_u2_circuit)
```
```
        ┌───────────────────┐
q_0: |0>┤ U3(pi,phi,lambda) ├
        └───────────────────┘
```

However, there are some corner cases missing. Like this one:
```python
my_u2 = my_u2_circuit.to_gate()
qr = QuantumRegister(1, name='qr')
circuit = QuantumCircuit(qr, name='circuit')
circuit.append(my_u2, [qr[0]])
circuit = circuit.bind_parameters({phi: 3.141592653589793, lam: 3.141592653589793})
print(circuit)
```
```
         ┌──────────────────────────────────────────┐
qr_0: |0>┤ My_u2(3.14159265358979,3.14159265358979) ├
         └──────────────────────────────────────────┘
```
## What is expected?
The last example should look like this:
```
         ┌──────────────┐
qr_0: |0>┤ My_u2(pi,pi) ├
         └──────────────┘
```


Discussion:

Resolving patch:
diff --git a/qiskit/visualization/tools/pi_check.py b/qiskit/visualization/tools/pi_check.py
--- a/qiskit/visualization/tools/pi_check.py
+++ b/qiskit/visualization/tools/pi_check.py
@@ -45,7 +45,10 @@ def pi_check(inpt, eps=1e-6, output='text', ndigits=5):
         QiskitError: if output is not a valid option.
     """
     if isinstance(inpt, ParameterExpression):
-        return str(inpt)
+        try:
+            return pi_check(float(inpt), eps=eps, output=output, ndigits=ndigits)
+        except ValueError:
+            return str(inpt)
     elif isinstance(inpt, str):
         return inpt
 
@@ -61,8 +64,8 @@ def normalize(single_inpt):
             pi = '$\\pi$'
         else:
             raise QiskitError('pi_check parameter output should be text, latex, or mpl')
-        if abs(val) >= 1:
-            if abs(val % 1) < eps:
+        if abs(val) >= 1 - eps:
+            if abs(abs(val) - abs(round(val))) < eps:
                 val = int(round(val))
                 if val == 1:
                     str_out = '{}'.format(pi)


Test patch:
diff --git a/test/python/visualization/test_circuit_text_drawer.py b/test/python/visualization/test_circuit_text_drawer.py
--- a/test/python/visualization/test_circuit_text_drawer.py
+++ b/test/python/visualization/test_circuit_text_drawer.py
@@ -987,6 +987,25 @@ def test_text_parameters_mix(self):
 
         self.assertEqual(str(_text_circuit_drawer(circuit)), expected)
 
+    def test_text_bound_parameters(self):
+        """Bound parameters
+        See: https://github.com/Qiskit/qiskit-terra/pull/3876 """
+        expected = '\n'.join(["         ┌──────────────┐",
+                              "qr_0: |0>┤ My_u2(pi,pi) ├",
+                              "         └──────────────┘"])
+
+        my_u2_circuit = QuantumCircuit(1, name='my_u2')
+        phi = Parameter('phi')
+        lam = Parameter('lambda')
+        my_u2_circuit.u3(3.141592653589793, phi, lam, 0)
+        my_u2 = my_u2_circuit.to_gate()
+        qr = QuantumRegister(1, name='qr')
+        circuit = QuantumCircuit(qr, name='circuit')
+        circuit.append(my_u2, [qr[0]])
+        circuit = circuit.bind_parameters({phi: 3.141592653589793, lam: 3.141592653589793})
+
+        self.assertEqual(str(_text_circuit_drawer(circuit)), expected)
+
 
 class TestTextDrawerVerticalCompressionLow(QiskitTestCase):
     """Test vertical_compression='low' """
diff --git a/test/python/visualization/test_tools.py b/test/python/visualization/test_tools.py
new file mode 100644
--- /dev/null
+++ b/test/python/visualization/test_tools.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+
+# This code is part of Qiskit.
+#
+# (C) Copyright IBM 2017, 2020.
+#
+# This code is licensed under the Apache License, Version 2.0. You may
+# obtain a copy of this license in the LICENSE.txt file in the root directory
+# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
+#
+# Any modifications or derivative works of this code must retain this
+# copyright notice, and modified files need to carry a notice indicating
+# that they have been altered from the originals.
+
+"""A test for visualizing tools"""
+import unittest
+
+from test import combine
+from ddt import ddt
+from qiskit.test import QiskitTestCase
+from qiskit.visualization.tools.pi_check import pi_check
+
+
+@ddt
+class TestPiCheck(QiskitTestCase):
+    """ qiskit/visualization/tools/pi_check.py """
+
+    @combine(case=[(3.14, '3.14'),
+                   (3.141592653589793, 'pi'),
+                   (6.283185307179586, '2pi'),
+                   (2.99, '2.99'),
+                   (2.999999999999999, '3'),
+                   (0.99, '0.99'),
+                   (0.999999999999999, '1')])
+    def test_default(self, case):
+        """Default pi_check({case[0]})='{case[1]}'"""
+        input_number = case[0]
+        expected_string = case[1]
+        result = pi_check(input_number)
+        self.assertEqual(result, expected_string)
+
+
+if __name__ == '__main__':
+    unittest.main(verbosity=2)