Repository: Qiskit/qiskit

Issue:
add visualization of open controlled gates [latex drawer]
@ewinston says in https://github.com/Qiskit/qiskit-terra/issues/3864:
> In PR #3739, open controlled gates were implemented. With that PR a new keyword argument was added to specify the control state,
> 
> `XGate().control(3, ctrl_state=6)`
> 
> This creates a 4 qubit gate where the first three qubits are controls and the fourth qubit is the target where the x-gate may be applied. A `ctrl_state` may alternatively be expressed as an integer string,
> 
> `XGate().control(3, ctrl_state='110')`
> 
> where it is more apparent which qubits are open and closed. In this case when q[0] is open and q[1] and q[2] are closed the x-gate will be applied to q[4].

As a reference https://github.com/Qiskit/qiskit-terra/pull/3867 implements open controlled gates for the text visualizer like this:
```python
qr = QuantumRegister(4, 'q')
circuit = QuantumCircuit(qr)
circuit.append(U2Gate(pi, -5 * pi / 8).control(3, ctrl_state='100'),
               [qr[0], qr[3], qr[2], qr[1]])
circuit.draw('text')
```
```
                         
q_0: |0>────────o────────
        ┌───────┴───────┐
q_1: |0>┤ U2(pi,-5pi/8) ├
        └───────┬───────┘
q_2: |0>────────■────────
                │        
q_3: |0>────────o────────
```
The current output for `circuit.draw('latex')` is:
![image](https://user-images.githubusercontent.com/766693/76469532-d36b8400-63c4-11ea-8530-c53750daacc0.png)



Discussion:
Hi @ewinston, just checking how this is going. I want to try out this, but wanted to check with you before proceeding! 
I think you can jump in directly, @Hrishik-Shrestha ! Let me know if you have any question.
Hi @Hrishik-Shrestha . Any update on the issue?

Resolving patch:
diff --git a/qiskit/visualization/latex.py b/qiskit/visualization/latex.py
--- a/qiskit/visualization/latex.py
+++ b/qiskit/visualization/latex.py
@@ -390,6 +390,7 @@ def _build_latex_array(self, aliases=None):
                         pos_array.append(self.img_regs[qarglist[ctrl]])
                     pos_qargs = pos_array[num_ctrl_qubits:]
                     ctrl_pos = pos_array[:num_ctrl_qubits]
+                    ctrl_state = "{0:b}".format(op.op.ctrl_state).rjust(num_ctrl_qubits, '0')[::-1]
                     if op.condition:
                         mask = self._get_mask(op.condition[0])
                         cl_reg = self.clbit_list[self._ffs(mask)]
@@ -409,9 +410,24 @@ def _build_latex_array(self, aliases=None):
                                     "\\controlo \\cw \\cwx[-" + str(gap) + "]"
                                 gap = 1
                     if num_qargs == 1:
-                        for index, pos in enumerate(ctrl_pos):
-                            self._latex[pos][column] = "\\ctrl{" + str(
-                                pos_array[index + 1] - pos_array[index]) + "}"
+                        for index, ctrl_item in enumerate(zip(ctrl_pos, ctrl_state)):
+                            pos = ctrl_item[0]
+                            cond = ctrl_item[1]
+                            nxt = pos_array[index]
+                            if pos_array[index] > pos_array[-1]:
+                                nxt -= 1
+                                while nxt not in pos_array:
+                                    nxt -= 1
+                            else:
+                                nxt += 1
+                                while nxt not in pos_array:
+                                    nxt += 1
+                            if cond == '0':
+                                self._latex[pos][column] = "\\ctrlo{" + str(
+                                    nxt - pos_array[index]) + "}"
+                            elif cond == '1':
+                                self._latex[pos][column] = "\\ctrl{" + str(
+                                    nxt - pos_array[index]) + "}"
                         if name == 'Z':
                             self._latex[pos_array[-1]][column] = "\\control\\qw"
                         else:
@@ -429,7 +445,9 @@ def _build_latex_array(self, aliases=None):
                             name = generate_latex_label(
                                 op.name).replace(" ", "\\,")
                         else:
-                            for index, pos in enumerate(ctrl_pos):
+                            for index, ctrl_item in enumerate(zip(ctrl_pos, ctrl_state)):
+                                pos = ctrl_item[0]
+                                cond = ctrl_item[1]
                                 if index + 1 >= num_ctrl_qubits:
                                     if pos_array[index] > pos_stop:
                                         upper = pos_stop
@@ -438,8 +456,12 @@ def _build_latex_array(self, aliases=None):
                                 else:
                                     upper = pos_array[index + 1]
 
-                                self._latex[pos][column] = "\\ctrl{" + str(
-                                    upper - pos_array[index]) + "}"
+                                if cond == '0':
+                                    self._latex[pos][column] = "\\ctrlo{" + str(
+                                        upper - pos_array[index]) + "}"
+                                elif cond == '1':
+                                    self._latex[pos][column] = "\\ctrl{" + str(
+                                        upper - pos_array[index]) + "}"
 
                         self._latex[pos_start][column] = ("\\multigate{%s}{%s}" %
                                                           (num_qargs - 1, name))
@@ -566,6 +588,8 @@ def _build_latex_array(self, aliases=None):
                                 self._latex[pos_1][column] = ("\\gate{%s}" % nm)
 
                     elif len(qarglist) == 2:
+                        if op.name not in ['swap', 'rzz']:
+                            cond = str(op.op.ctrl_state)
                         pos_1 = self.img_regs[qarglist[0]]
                         pos_2 = self.img_regs[qarglist[1]]
 
@@ -587,33 +611,57 @@ def _build_latex_array(self, aliases=None):
                                     gap = 1
 
                             if nm == "cx":
-                                self._latex[pos_1][column] = \
-                                    "\\ctrl{" + str(pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\targ"
                             elif nm == "cz":
-                                self._latex[pos_1][column] = \
-                                    "\\ctrl{" + str(pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\control\\qw"
                             elif nm == "cy":
-                                self._latex[pos_1][column] = \
-                                    "\\ctrl{" + str(pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\gate{Y}"
                             elif nm == "ch":
-                                self._latex[pos_1][column] = \
-                                    "\\ctrl{" + str(pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\gate{H}"
                             elif nm == "swap":
                                 self._latex[pos_1][column] = "\\qswap"
                                 self._latex[pos_2][column] = \
                                     "\\qswap \\qwx[" + str(pos_1 - pos_2) + "]"
                             elif nm == "crz":
-                                self._latex[pos_1][column] = \
-                                    "\\ctrl{" + str(pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = \
                                     "\\gate{R_z(%s)}" % (self.parse_params(op.op.params[0]))
                             elif nm == "cu1":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\control \\qw"
                                 self._latex[min(pos_1, pos_2)][column + 1] = \
                                     "\\dstick{%s}\\qw" % (self.parse_params(op.op.params[0]))
@@ -622,8 +670,12 @@ def _build_latex_array(self, aliases=None):
                                 # and we have just written to the next column
                                 num_cols_used = 2
                             elif nm == "cu3":
-                                self._latex[pos_1][column] = \
-                                    "\\ctrl{" + str(pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = \
                                     "\\gate{U_3(%s,%s,%s)}" % \
                                     (self.parse_params(op.op.params[0]),
@@ -645,41 +697,69 @@ def _build_latex_array(self, aliases=None):
                             temp.sort(key=int)
 
                             if nm == "cx":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\targ"
                             elif nm == "cz":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\control\\qw"
                             elif nm == "cy":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\gate{Y}"
                             elif nm == "ch":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\gate{H}"
                             elif nm == "swap":
                                 self._latex[pos_1][column] = "\\qswap"
                                 self._latex[pos_2][column] = \
                                     "\\qswap \\qwx[" + str(pos_1 - pos_2) + "]"
                             elif nm == "crz":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = \
                                     "\\gate{R_z(%s)}" % (self.parse_params(op.op.params[0]))
                             elif nm == "cu1":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\control \\qw"
                                 self._latex[min(pos_1, pos_2)][column + 1] = \
                                     "\\dstick{%s}\\qw" % (self.parse_params(op.op.params[0]))
                                 self._latex[max(pos_1, pos_2)][column + 1] = "\\qw"
                                 num_cols_used = 2
                             elif nm == "cu3":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
+                                if cond == '0':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrlo{" + str(pos_2 - pos_1) + "}"
+                                elif cond == '1':
+                                    self._latex[pos_1][column] = \
+                                        "\\ctrl{" + str(pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = \
                                     ("\\gate{U_3(%s,%s,%s)}" %
                                      (self.parse_params(op.op.params[0]),
@@ -713,6 +793,10 @@ def _build_latex_array(self, aliases=None):
                                                                      nm)
 
                     elif len(qarglist) == 3:
+                        if op.name in ['ccx', 'cswap']:
+                            ctrl_state = "{0:b}".format(op.op.ctrl_state).rjust(2, '0')[::-1]
+                            cond_1 = ctrl_state[0]
+                            cond_2 = ctrl_state[1]
                         pos_1 = self.img_regs[qarglist[0]]
                         pos_2 = self.img_regs[qarglist[1]]
                         pos_3 = self.img_regs[qarglist[2]]
@@ -735,29 +819,53 @@ def _build_latex_array(self, aliases=None):
                                     gap = 1
 
                             if nm == "ccx":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
-                                self._latex[pos_2][column] = "\\ctrl{" + str(
-                                    pos_3 - pos_2) + "}"
+                                if cond_1 == '0':
+                                    self._latex[pos_1][column] = "\\ctrlo{" + str(
+                                        pos_2 - pos_1) + "}"
+                                elif cond_1 == '1':
+                                    self._latex[pos_1][column] = "\\ctrl{" + str(
+                                        pos_2 - pos_1) + "}"
+                                if cond_2 == '0':
+                                    self._latex[pos_2][column] = "\\ctrlo{" + str(
+                                        pos_3 - pos_2) + "}"
+                                elif cond_2 == '1':
+                                    self._latex[pos_2][column] = "\\ctrl{" + str(
+                                        pos_3 - pos_2) + "}"
                                 self._latex[pos_3][column] = "\\targ"
 
                             if nm == "cswap":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
+                                if cond_1 == '0':
+                                    self._latex[pos_1][column] = "\\ctrlo{" + str(
+                                        pos_2 - pos_1) + "}"
+                                elif cond_1 == '1':
+                                    self._latex[pos_1][column] = "\\ctrl{" + str(
+                                        pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\qswap"
                                 self._latex[pos_3][column] = \
                                     "\\qswap \\qwx[" + str(pos_2 - pos_3) + "]"
                         else:
                             if nm == "ccx":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
-                                self._latex[pos_2][column] = "\\ctrl{" + str(
-                                    pos_3 - pos_2) + "}"
+                                if cond_1 == '0':
+                                    self._latex[pos_1][column] = "\\ctrlo{" + str(
+                                        pos_2 - pos_1) + "}"
+                                elif cond_1 == '1':
+                                    self._latex[pos_1][column] = "\\ctrl{" + str(
+                                        pos_2 - pos_1) + "}"
+                                if cond_2 == '0':
+                                    self._latex[pos_2][column] = "\\ctrlo{" + str(
+                                        pos_3 - pos_2) + "}"
+                                elif cond_2 == '1':
+                                    self._latex[pos_2][column] = "\\ctrl{" + str(
+                                        pos_3 - pos_2) + "}"
                                 self._latex[pos_3][column] = "\\targ"
 
                             elif nm == "cswap":
-                                self._latex[pos_1][column] = "\\ctrl{" + str(
-                                    pos_2 - pos_1) + "}"
+                                if cond_1 == '0':
+                                    self._latex[pos_1][column] = "\\ctrlo{" + str(
+                                        pos_2 - pos_1) + "}"
+                                elif cond_1 == '1':
+                                    self._latex[pos_1][column] = "\\ctrl{" + str(
+                                        pos_2 - pos_1) + "}"
                                 self._latex[pos_2][column] = "\\qswap"
                                 self._latex[pos_3][column] = \
                                     "\\qswap \\qwx[" + str(pos_2 - pos_3) + "]"


Test patch: