Repository: Qiskit/qiskit

Issue:
Gates are not left justified in mpl circuit drawer
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

- **Qiskit Terra version**: master
- **Python version**:
- **Operating system**:

### What is the current behavior?
There is always a space on the line between the qubit label and the first gate:
![circ_color](https://user-images.githubusercontent.com/1249193/61219110-7dcdc300-a6e1-11e9-9653-5b6851a34f93.png)

To reduce the width of the figure as much as possible, the gates should be drawn as far left as possible.



### Steps to reproduce the problem



### What is the expected behavior?



### Suggested solutions





Discussion:
@nonhermitian, is PR #3168 a fix for this issue?
Hi,

I was trying to look into this issue. The draw function has a parameter, justify. However if I use Justify='left' or justify='right' I do not see any change. Please help me to understand.
<img width="347" alt="image" src="https://user-images.githubusercontent.com/29120460/83592175-60168000-a577-11ea-8606-ef2d6d190606.png">

I know this is an old issue, but I believe the reason for the extra room is for displaying bars for the folded (wrapped) rows. As in,
![image](https://user-images.githubusercontent.com/16268251/85865709-26eabd80-b77b-11ea-9ccf-ceab5728102b.png)
If the gates were moved to the left on the first row, either there wouldn't be enough room for the bars or the columns would not line up between the rows.
@1ucian0 @nonhermitian Is this still open?  If yes, can I have a go at this?
I think @enavarro51 has some ideas about how to handle this.

Do you have bandwidth to work on this @enavarro51 or @abhobe can jump in?
@1ucian0 The issue here has to do with what to do when the circuit folds as in my comment above. The solution I had suggested earlier (4 below) turned out to be more complicated than I thought.  I see 4 options.
1 - Do nothing. It's only really noticeable on small circuits, but it is noticeable.
2 - Just move the first row gates to the left. The first row will be out of alignment with the folded rows below it, as will the index numbers if used.
3 - Remove the inner vertical bars at the beginning and end of the rows that fold, and leave the outer one. Don't know why there are two bars at each end except it looks like a musical clef. If we do this, it's easy to move all the gates left and just leave enough space between the single bar and a gate. This could reduce empty wire space at both ends.
4 - Only move the gates left if the circuit doesn't fold. Since folds are usually 20 or more indexes wide, the space at the left is much less noticeable for these large circuits. Problem with this is that as the code is currently structured, when you go to draw the first gate, you don't know if the circuit is going to fold or not, so a solution would require a significant restructuring of the code. (Which might be more efficient.)
My preference is for 3 and I'm happy to have @abhobe work on it, and I'd be available to answer questions.
Thanks!
Option 3 sounds good!
![image](https://user-images.githubusercontent.com/29938963/93009838-67680500-f53a-11ea-9b3f-fc10bf120295.png)
@nonhermitian Is this what is wanted?
Yes, that looks nice. 
Ok, Here is what I did, changed line ``687`` from 
``self._line([self.x_offset + 0.2, y], [self._cond['xmax'], y],
                       zorder=PORDER_REGLINE)``
to
``self._line([self.x_offset + 1, y], [self._cond['xmax'], y],
                       zorder=PORDER_REGLINE)``
This will solve the case only for one set of rows for the circuit. More sets will break the folds in the next lines.
I would also like to note that the gates are perfectly aligned when looking  by the column. However, In the first row you will see there is an excess of white space since I removed the initial space wire.

![2788](https://user-images.githubusercontent.com/29938963/93011266-afdaef00-f549-11ea-98fb-f03f17f8a3b5.png)

I like @enavarro51 's [idea](https://github.com/Qiskit/qiskit-terra/compare/master...enavarro51:fixissue2788branch?diff=unified) of removing one of those lines in the folds to increase circuit  space. However, this did not solve the extra gate space in the beginning. So I thought of combining these ideas but the folds broke again.

@enavarro51 's Idea
![image](https://user-images.githubusercontent.com/29938963/93011408-ecf3b100-f54a-11ea-921d-b18cf16f5a58.png)

The combination
![merge](https://user-images.githubusercontent.com/29938963/93011397-c59ce400-f54a-11ea-9ba1-8c9339d7725f.png)


(Sorry for the random x gates)
@abhobe Are you on Slack? I think we can pick this discussion up over there. I have some ideas how to fix this.
@enavarro51 Yes I am in slack. My slack handle also @abhobe
@enavarro51 and I had a discussion on slack on what the final result should be. So here is what we plan to make it look like.
![Download](https://user-images.githubusercontent.com/29938963/93031178-a602cb80-f5dd-11ea-8b85-cae0df2e9192.png)

- on the first set of qubits I removed the initial gate wire

We just need to find a way to seperate the first set of qubits from the next sets.

Note: The code for this has not been made yet. This was formatted on GIMP.

@nonhermitian @1ucian0 
Looks good! 
@1ucian0 @nonhermitian I am pretty new to the qiskit source, could you point me to some functions which manage the length of the circuit wire length?
@enavarro51 can help. He knows the drawer very well. 

Resolving patch:
diff --git a/qiskit/visualization/matplotlib.py b/qiskit/visualization/matplotlib.py
--- a/qiskit/visualization/matplotlib.py
+++ b/qiskit/visualization/matplotlib.py
@@ -73,10 +73,10 @@ def plot_coord(self, index, gate_width, x_offset):
         if self.__fold > 0:
             if h_pos + (gate_width - 1) > self.__fold:
                 index += self.__fold - (h_pos - 1)
-            x_pos = index % self.__fold + 1 + 0.5 * (gate_width - 1)
+            x_pos = index % self.__fold + 0.5 * gate_width + 0.04
             y_pos = self.__yind - (index // self.__fold) * (self.__reg_num + 1)
         else:
-            x_pos = index + 1 + 0.5 * (gate_width - 1)
+            x_pos = index + 0.5 * gate_width + 0.04
             y_pos = self.__yind
 
         # could have been updated, so need to store
@@ -464,7 +464,7 @@ def _measure(self, qxy, cxy, cid, fc=None, ec=None, gt=None, sc=None):
         self._line(qxy, [cx, cy + 0.35 * WID], lc=self._style.cc, ls=self._style.cline)
         arrowhead = patches.Polygon(((cx - 0.20 * WID, cy + 0.35 * WID),
                                      (cx + 0.20 * WID, cy + 0.35 * WID),
-                                     (cx, cy)), fc=self._style.cc, ec=None)
+                                     (cx, cy + 0.04)), fc=self._style.cc, ec=None)
         self.ax.add_artist(arrowhead)
         # target
         if self.cregbundle:
@@ -556,16 +556,6 @@ def _barrier(self, config):
                                     linewidth=self._lwidth15, zorder=PORDER_GRAY)
             self.ax.add_patch(box)
 
-    def _linefeed_mark(self, xy):
-        xpos, ypos = xy
-
-        self.ax.plot([xpos - .1, xpos - .1],
-                     [ypos, ypos - self._cond['n_lines'] + 1],
-                     color=self._style.lc, linewidth=self._lwidth15, zorder=PORDER_LINE)
-        self.ax.plot([xpos + .1, xpos + .1],
-                     [ypos, ypos - self._cond['n_lines'] + 1],
-                     color=self._style.lc, linewidth=self._lwidth15, zorder=PORDER_LINE)
-
     def draw(self, filename=None, verbose=False):
         self._draw_regs()
         self._draw_ops(verbose)
@@ -684,7 +674,7 @@ def _draw_regs_sub(self, n_fold, feedline_l=False, feedline_r=False):
             self.ax.text(self.x_offset - 0.2, y, label, ha='right', va='center',
                          fontsize=1.25 * self._style.fs, color=self._style.tc,
                          clip_on=True, zorder=PORDER_TEXT)
-            self._line([self.x_offset + 0.2, y], [self._cond['xmax'], y],
+            self._line([self.x_offset, y], [self._cond['xmax'], y],
                        zorder=PORDER_REGLINE)
 
         # classical register
@@ -699,28 +689,34 @@ def _draw_regs_sub(self, n_fold, feedline_l=False, feedline_r=False):
         for y, this_creg in this_creg_dict.items():
             # cregbundle
             if this_creg['val'] > 1:
-                self.ax.plot([self.x_offset + 0.64, self.x_offset + 0.74], [y - .1, y + .1],
+                self.ax.plot([self.x_offset + 0.2, self.x_offset + 0.3], [y - 0.1, y + 0.1],
                              color=self._style.cc, zorder=PORDER_LINE)
-                self.ax.text(self.x_offset + 0.54, y + .1, str(this_creg['val']), ha='left',
+                self.ax.text(self.x_offset + 0.1, y + 0.1, str(this_creg['val']), ha='left',
                              va='bottom', fontsize=0.8 * self._style.fs,
                              color=self._style.tc, clip_on=True, zorder=PORDER_TEXT)
             self.ax.text(self.x_offset - 0.2, y, this_creg['label'], ha='right', va='center',
                          fontsize=1.25 * self._style.fs, color=self._style.tc,
                          clip_on=True, zorder=PORDER_TEXT)
-            self._line([self.x_offset + 0.2, y], [self._cond['xmax'], y], lc=self._style.cc,
+            self._line([self.x_offset, y], [self._cond['xmax'], y], lc=self._style.cc,
                        ls=self._style.cline, zorder=PORDER_REGLINE)
 
-        # lf line
-        if feedline_r:
-            self._linefeed_mark((self.fold + self.x_offset + 1 - 0.1,
-                                 - n_fold * (self._cond['n_lines'] + 1)))
-        if feedline_l:
-            self._linefeed_mark((self.x_offset + 0.3,
-                                 - n_fold * (self._cond['n_lines'] + 1)))
+        # lf vertical line at either end
+        if feedline_l or feedline_r:
+            xpos_l = self.x_offset - 0.01
+            xpos_r = self.fold + self.x_offset + 0.1
+            ypos1 = -n_fold * (self._cond['n_lines'] + 1)
+            ypos2 = -(n_fold + 1) * (self._cond['n_lines']) - n_fold + 1
+            if feedline_l:
+                self.ax.plot([xpos_l, xpos_l], [ypos1, ypos2],
+                             color=self._style.lc, linewidth=self._lwidth15, zorder=PORDER_LINE)
+            if feedline_r:
+                self.ax.plot([xpos_r, xpos_r], [ypos1, ypos2],
+                             color=self._style.lc, linewidth=self._lwidth15, zorder=PORDER_LINE)
 
     def _draw_ops(self, verbose=False):
-        _standard_gates = ['x', 'y', 'z', 'id', 'h', 'r', 's', 'sdg', 't', 'tdg', 'rx', 'ry', 'rz',
-                           'rxx', 'ryy', 'rzx', 'u1', 'u2', 'u3', 'swap', 'reset', 'sx', 'sxdg']
+        _standard_1q_gates = ['x', 'y', 'z', 'id', 'h', 'r', 's', 'sdg', 't', 'tdg', 'rx', 'ry',
+                              'rz', 'rxx', 'ryy', 'rzx', 'u1', 'u2', 'u3', 'swap', 'reset', 'sx',
+                              'sxdg', 'p']
         _barrier_gates = ['barrier', 'snapshot', 'load', 'save', 'noise']
         _barriers = {'coord': [], 'group': []}
 
@@ -753,7 +749,7 @@ def _draw_ops(self, verbose=False):
 
                 # if a standard_gate, no params, and no labels, layer_width is 1
                 if (not hasattr(op.op, 'params') and
-                        ((op.name in _standard_gates or base_name in _standard_gates)
+                        ((op.name in _standard_1q_gates or base_name in _standard_1q_gates)
                          and gate_text in (op.name, base_name) and ctrl_text is None)):
                     continue
 
@@ -782,7 +778,7 @@ def _draw_ops(self, verbose=False):
                 else:
                     gate_width = self._get_text_width(gate_text, fontsize=self._style.fs) + 0.10
                     # add .21 for the qubit numbers on the left of the multibit gates
-                    if (op.name not in _standard_gates and base_name not in _standard_gates):
+                    if (op.name not in _standard_1q_gates and base_name not in _standard_1q_gates):
                         gate_width += 0.21
 
                 box_width = max((gate_width, ctrl_width, param_width, WID))
@@ -996,10 +992,10 @@ def _draw_ops(self, verbose=False):
 
         # window size
         if max_anc > self.fold > 0:
-            self._cond['xmax'] = self.fold + 1 + self.x_offset
+            self._cond['xmax'] = self.fold + 1 + self.x_offset - 0.9
             self._cond['ymax'] = (n_fold + 1) * (self._cond['n_lines'] + 1) - 1
         else:
-            self._cond['xmax'] = max_anc + 1 + self.x_offset
+            self._cond['xmax'] = max_anc + 1 + self.x_offset - 0.9
             self._cond['ymax'] = self._cond['n_lines']
 
         # add horizontal lines
@@ -1012,10 +1008,10 @@ def _draw_ops(self, verbose=False):
         if self._style.index:
             for ii in range(max_anc):
                 if self.fold > 0:
-                    x_coord = ii % self.fold + self._reg_long_text - 0.2
+                    x_coord = ii % self.fold + self._reg_long_text - 0.67
                     y_coord = - (ii // self.fold) * (self._cond['n_lines'] + 1) + 0.7
                 else:
-                    x_coord = ii + self._reg_long_text - 0.2
+                    x_coord = ii + self._reg_long_text - 0.67
                     y_coord = 0.7
                 self.ax.text(x_coord, y_coord, str(ii + 1), ha='center',
                              va='center', fontsize=self._style.sfs,


Test patch:
diff --git a/test/ipynb/mpl/references/big_gates.png b/test/ipynb/mpl/references/big_gates.png
Binary files a/test/ipynb/mpl/references/big_gates.png and b/test/ipynb/mpl/references/big_gates.png differ
diff --git a/test/ipynb/mpl/references/cnot.png b/test/ipynb/mpl/references/cnot.png
Binary files a/test/ipynb/mpl/references/cnot.png and b/test/ipynb/mpl/references/cnot.png differ
diff --git a/test/ipynb/mpl/references/conditional.png b/test/ipynb/mpl/references/conditional.png
Binary files a/test/ipynb/mpl/references/conditional.png and b/test/ipynb/mpl/references/conditional.png differ
diff --git a/test/ipynb/mpl/references/creg_initial_false.png b/test/ipynb/mpl/references/creg_initial_false.png
Binary files a/test/ipynb/mpl/references/creg_initial_false.png and b/test/ipynb/mpl/references/creg_initial_false.png differ
diff --git a/test/ipynb/mpl/references/creg_initial_true.png b/test/ipynb/mpl/references/creg_initial_true.png
Binary files a/test/ipynb/mpl/references/creg_initial_true.png and b/test/ipynb/mpl/references/creg_initial_true.png differ
diff --git a/test/ipynb/mpl/references/cswap_rzz.png b/test/ipynb/mpl/references/cswap_rzz.png
Binary files a/test/ipynb/mpl/references/cswap_rzz.png and b/test/ipynb/mpl/references/cswap_rzz.png differ
diff --git a/test/ipynb/mpl/references/ctrl_labels.png b/test/ipynb/mpl/references/ctrl_labels.png
Binary files a/test/ipynb/mpl/references/ctrl_labels.png and b/test/ipynb/mpl/references/ctrl_labels.png differ
diff --git a/test/ipynb/mpl/references/fold_4.png b/test/ipynb/mpl/references/fold_4.png
Binary files a/test/ipynb/mpl/references/fold_4.png and b/test/ipynb/mpl/references/fold_4.png differ
diff --git a/test/ipynb/mpl/references/fold_minus1.png b/test/ipynb/mpl/references/fold_minus1.png
Binary files a/test/ipynb/mpl/references/fold_minus1.png and b/test/ipynb/mpl/references/fold_minus1.png differ
diff --git a/test/ipynb/mpl/references/ghz_to_gate.png b/test/ipynb/mpl/references/ghz_to_gate.png
Binary files a/test/ipynb/mpl/references/ghz_to_gate.png and b/test/ipynb/mpl/references/ghz_to_gate.png differ
diff --git a/test/ipynb/mpl/references/global_phase.png b/test/ipynb/mpl/references/global_phase.png
Binary files a/test/ipynb/mpl/references/global_phase.png and b/test/ipynb/mpl/references/global_phase.png differ
diff --git a/test/ipynb/mpl/references/init_reset.png b/test/ipynb/mpl/references/init_reset.png
Binary files a/test/ipynb/mpl/references/init_reset.png and b/test/ipynb/mpl/references/init_reset.png differ
diff --git a/test/ipynb/mpl/references/long_name.png b/test/ipynb/mpl/references/long_name.png
Binary files a/test/ipynb/mpl/references/long_name.png and b/test/ipynb/mpl/references/long_name.png differ
diff --git a/test/ipynb/mpl/references/no_barriers.png b/test/ipynb/mpl/references/no_barriers.png
Binary files a/test/ipynb/mpl/references/no_barriers.png and b/test/ipynb/mpl/references/no_barriers.png differ
diff --git a/test/ipynb/mpl/references/partial_layout.png b/test/ipynb/mpl/references/partial_layout.png
Binary files a/test/ipynb/mpl/references/partial_layout.png and b/test/ipynb/mpl/references/partial_layout.png differ
diff --git a/test/ipynb/mpl/references/pauli_clifford.png b/test/ipynb/mpl/references/pauli_clifford.png
Binary files a/test/ipynb/mpl/references/pauli_clifford.png and b/test/ipynb/mpl/references/pauli_clifford.png differ
diff --git a/test/ipynb/mpl/references/pi_in_param_expr.png b/test/ipynb/mpl/references/pi_in_param_expr.png
Binary files a/test/ipynb/mpl/references/pi_in_param_expr.png and b/test/ipynb/mpl/references/pi_in_param_expr.png differ
diff --git a/test/ipynb/mpl/references/plot_barriers_false.png b/test/ipynb/mpl/references/plot_barriers_false.png
Binary files a/test/ipynb/mpl/references/plot_barriers_false.png and b/test/ipynb/mpl/references/plot_barriers_false.png differ
diff --git a/test/ipynb/mpl/references/plot_barriers_true.png b/test/ipynb/mpl/references/plot_barriers_true.png
Binary files a/test/ipynb/mpl/references/plot_barriers_true.png and b/test/ipynb/mpl/references/plot_barriers_true.png differ
diff --git a/test/ipynb/mpl/references/plot_partial_barrier.png b/test/ipynb/mpl/references/plot_partial_barrier.png
Binary files a/test/ipynb/mpl/references/plot_partial_barrier.png and b/test/ipynb/mpl/references/plot_partial_barrier.png differ
diff --git a/test/ipynb/mpl/references/r_gates.png b/test/ipynb/mpl/references/r_gates.png
Binary files a/test/ipynb/mpl/references/r_gates.png and b/test/ipynb/mpl/references/r_gates.png differ
diff --git a/test/ipynb/mpl/references/scale_default.png b/test/ipynb/mpl/references/scale_default.png
Binary files a/test/ipynb/mpl/references/scale_default.png and b/test/ipynb/mpl/references/scale_default.png differ
diff --git a/test/ipynb/mpl/references/scale_double.png b/test/ipynb/mpl/references/scale_double.png
Binary files a/test/ipynb/mpl/references/scale_double.png and b/test/ipynb/mpl/references/scale_double.png differ
diff --git a/test/ipynb/mpl/references/scale_half.png b/test/ipynb/mpl/references/scale_half.png
Binary files a/test/ipynb/mpl/references/scale_half.png and b/test/ipynb/mpl/references/scale_half.png differ
diff --git a/test/ipynb/mpl/references/u_gates.png b/test/ipynb/mpl/references/u_gates.png
Binary files a/test/ipynb/mpl/references/u_gates.png and b/test/ipynb/mpl/references/u_gates.png differ