Repository: Qiskit/qiskit

Issue:
Auto scale pulse drawings for given channels
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues to confirm this idea does not exist. -->

### What is the expected enhancement?
There's a lot of unused space with default Schedule drawing.

<img width="914" alt="Screen Shot 2019-09-19 at 10 33 44 AM" src="https://user-images.githubusercontent.com/10730254/65253650-fcbbef00-dac8-11e9-8020-480b7dae24ae.png">

Changing the `scaling` option helps, but this still isn't great. We should try to automatically adjust the plotting range, or the scale, or at least not show negative values by default (it looks like the space for neg values leaves a large gap between channels, and I haven't seen it used)

<img width="914" alt="Screen Shot 2019-09-19 at 10 28 24 AM" src="https://user-images.githubusercontent.com/10730254/65253795-41e02100-dac9-11e9-9f74-7e915d9c29ab.png">




Discussion:
Hi @lcapelluto, i'm working on this.
I think the problem come from the method `_count_valid_waveforms()`  of `qiskit.visualization.pulse_visualization` module, and when the scaling=1(by default in the draw method) the maximum amplitude `v_max=0.5*scaling` is low.
![image](https://user-images.githubusercontent.com/49644465/65698381-b47a6f00-e07c-11e9-9edb-389f5490aa8c.png)

However we can specify `scaling=None`  like this to have a better visualization:
![image](https://user-images.githubusercontent.com/49644465/65698982-ac6eff00-e07d-11e9-9f91-c9309f518280.png) 

So my recommendation is to change the  default value from 1 to `None` but also adjust the scaling for this last.


Thank you! That is definitely already an improvement. Would it be possible to also check if the pulse envelope has negative values, and if not, set the range for the drawn channel to go from 0 up? For many cases, including our examples, this would remove a lot of unused space. (Note that we can't assume the envelope won't have negative values)
I tried two values of `v_max` for `scaling=None`:

### 1- `v_max = 0.5 / (v_max)`

![image](https://user-images.githubusercontent.com/49644465/65701676-02de3c80-e082-11e9-914a-34ae63062671.png)

And for a DriveChannel with negative values

![image](https://user-images.githubusercontent.com/49644465/65701899-69635a80-e082-11e9-8601-60c4e4e57f1a.png)


### 2-`v_max=1/v_max`
![image](https://user-images.githubusercontent.com/49644465/65702820-f1962f80-e083-11e9-943a-317dbe0dcf9e.png)

With negative value:

![image](https://user-images.githubusercontent.com/49644465/65703323-dd066700-e084-11e9-9aab-9bd7ac3d489e.png)

As you said, if i don't have negative values, could i use the case 2, otherwise the case 1?



I think the `scaling=None` solution you found handles the scaling issue well. I was hoping we could make the best use of the space by also changing the y-axis range that is displayed for each channel. If there are no negative values, I was hoping we could get an output something like this:

<img width="955" alt="Screen Shot 2019-09-26 at 12 12 05 PM" src="https://user-images.githubusercontent.com/10730254/65705816-26d85880-e057-11e9-820b-c17112d15911.png">

Do you think that would be possible?

Resolving patch:
diff --git a/qiskit/pulse/schedule.py b/qiskit/pulse/schedule.py
--- a/qiskit/pulse/schedule.py
+++ b/qiskit/pulse/schedule.py
@@ -315,7 +315,7 @@ def only_channel_one(time_and_inst_tuple) -> bool:
 
     def draw(self, dt: float = 1, style: Optional['SchedStyle'] = None,
              filename: Optional[str] = None, interp_method: Optional[Callable] = None,
-             scaling: float = 1, channels_to_plot: Optional[List[Channel]] = None,
+             scaling: float = None, channels_to_plot: Optional[List[Channel]] = None,
              plot_all: bool = False, plot_range: Optional[Tuple[float]] = None,
              interactive: bool = False, table: bool = True, label: bool = False,
              framechange: bool = True):
diff --git a/qiskit/visualization/pulse/matplotlib.py b/qiskit/visualization/pulse/matplotlib.py
--- a/qiskit/visualization/pulse/matplotlib.py
+++ b/qiskit/visualization/pulse/matplotlib.py
@@ -366,7 +366,7 @@ def _count_valid_waveforms(self, channels, scaling=1, channels_to_plot=None,
         if scaling:
             v_max = 0.5 * scaling
         else:
-            v_max = 0.5 / (1.2 * v_max)
+            v_max = 0.5 / (v_max)
 
         return n_valid_waveform, v_max
 
@@ -504,6 +504,8 @@ def _draw_channels(self, ax, output_channels, interp_method, t0, tf, dt, v_max,
                     # instead, it just returns vector of zero.
                     re, im = np.zeros_like(time), np.zeros_like(time)
                 color = self._get_channel_color(channel)
+                # Minimum amplitude scaled
+                amp_min = v_max * abs(min(0, np.nanmin(re), np.nanmin(im)))
                 # scaling and offset
                 re = v_max * re + y0
                 im = v_max * im + y0
@@ -531,16 +533,21 @@ def _draw_channels(self, ax, output_channels, interp_method, t0, tf, dt, v_max,
 
             else:
                 continue
+
             # plot label
             ax.text(x=0, y=y0, s=channel.name,
                     fontsize=self.style.axis_font_size,
                     ha='right', va='center')
 
-            y0 -= 1
+            # change the y0 offset for removing spacing when a channel has negative values
+            if self.style.remove_spacing:
+                y0 -= 0.5 + amp_min
+            else:
+                y0 -= 1
         return y0
 
     def draw(self, schedule, dt, interp_method, plot_range,
-             scaling=1, channels_to_plot=None, plot_all=True,
+             scaling=None, channels_to_plot=None, plot_all=True,
              table=True, label=False, framechange=True):
         """Draw figure.
 
diff --git a/qiskit/visualization/pulse/qcstyle.py b/qiskit/visualization/pulse/qcstyle.py
--- a/qiskit/visualization/pulse/qcstyle.py
+++ b/qiskit/visualization/pulse/qcstyle.py
@@ -21,7 +21,7 @@ def __init__(self, figsize=(10, 12), fig_unit_h_table=0.4,
                  label_font_size=10, icon_font_size=18, label_ch_linestyle='--',
                  label_ch_color=None, label_ch_alpha=0.3, d_ch_color=None, u_ch_color=None,
                  m_ch_color=None, s_ch_color=None, s_ch_linestyle='-', table_color=None,
-                 bg_color=None, num_points=1000, dpi=150):
+                 bg_color=None, num_points=1000, dpi=150, remove_spacing=True):
         """Set style sheet for OpenPulse schedule drawer.
 
         Args:
@@ -45,6 +45,7 @@ def __init__(self, figsize=(10, 12), fig_unit_h_table=0.4,
             bg_color(str): color for figure background
             num_points (int): number of points for interpolation
             dpi (int): dpi to save image
+            remove_spacing(bool): Remove redundant spacing when the waveform has no negative values
         """
         self.figsize = figsize
         self.fig_unit_h_table = fig_unit_h_table
@@ -67,6 +68,7 @@ def __init__(self, figsize=(10, 12), fig_unit_h_table=0.4,
         self.bg_color = bg_color or '#f2f3f4'
         self.num_points = num_points
         self.dpi = dpi
+        self.remove_spacing = remove_spacing
 
 
 class PulseStyle:


Test patch:
diff --git a/test/python/visualization/references/instruction_matplotlib_ref.png b/test/python/visualization/references/instruction_matplotlib_ref.png
Binary files a/test/python/visualization/references/instruction_matplotlib_ref.png and b/test/python/visualization/references/instruction_matplotlib_ref.png differ
diff --git a/test/python/visualization/references/pulse_matplotlib_ref.png b/test/python/visualization/references/pulse_matplotlib_ref.png
Binary files a/test/python/visualization/references/pulse_matplotlib_ref.png and b/test/python/visualization/references/pulse_matplotlib_ref.png differ
diff --git a/test/python/visualization/references/schedule_matplotlib_ref.png b/test/python/visualization/references/schedule_matplotlib_ref.png
Binary files a/test/python/visualization/references/schedule_matplotlib_ref.png and b/test/python/visualization/references/schedule_matplotlib_ref.png differ