text: #!/usr/bin/env python
  
  import numpy as np
  import matplotlib.pyplot as plt
  from matplotlib.ticker import AutoMinorLocator
  import os
  from math import ceil 
  
  
  def _ax_plot(ax, x, y, secs=10, lwidth=0.5, amplitude_ecg = 1.8, time_ticks =0.2):
      ax.set_xticks(np.arange(0,11,time_ticks))    
      ax.set_yticks(np.arange(-ceil(amplitude_ecg),ceil(amplitude_ecg),1.0))
  
      #ax.set_yticklabels([])
      #ax.set_xticklabels([])
  
      ax.minorticks_on()
      
      ax.xaxis.set_minor_locator(AutoMinorLocator(5))
  
      ax.set_ylim(-amplitude_ecg, amplitude_ecg)
      ax.set_xlim(0, secs)
  
      ax.grid(which='major', linestyle='-', linewidth='0.5', color='red')
      ax.grid(which='minor', linestyle='-', linewidth='0.5', color=(1, 0.7, 0.7))
  
      ax.plot(x,y, linewidth=lwidth)
  
  
  lead_index = ['I', 'II', 'III', 'aVR', 'aVL', 'aVF', 'V1', 'V2', 'V3', 'V4', 'V5', 'V6']
  def plot_12(
          ecg, 
          sample_rate = 500, 
          title       = 'ECG 12', 
          lead_index  = lead_index, 
          lead_order  = None,
          columns     = 2
          ):
      """Plot multi lead ECG chart.
      # Arguments
          ecg        : m x n ECG signal data, which m is number of leads and n is length of signal.
          sample_rate: Sample rate of the signal.
          title      : Title which will be shown on top off chart
          lead_index : Lead name array in the same order of ecg, will be shown on 
              left of signal plot, defaults to ['I', 'II', 'III', 'aVR', 'aVL', 'aVF', 'V1', 'V2', 'V3', 'V4', 'V5', 'V6']
          lead_order : Lead display order 
          columns    : display columns, defaults to 2
      """
      if not lead_order:
          lead_order = list(range(0,len(ecg)))
  
      leads = len(lead_order)
      seconds = len(ecg[0])/sample_rate
  
      plt.rcParams.update({'font.size': 8})
      fig, ax = plt.subplots(
          ceil(len(lead_order)/columns),columns,
          sharex=True, 
          sharey=True,
          figsize=(0.7*seconds*columns, 1.1*leads/columns)
          )
      fig.subplots_adjust(
          hspace = 0, 
          wspace = 0.04,
          left   = 0.04,  # the left side of the subplots of the figure
          right  = 0.98,  # the right side of the subplots of the figure
          bottom = 0.06,  # the bottom of the subplots of the figure
          top    = 0.95
          )
      fig.suptitle(title)
  
      step = 1.0/sample_rate
  
      for i in range(0, len(lead_order)):
          if(columns == 1):
              t_ax = ax[i]
          else:
              t_ax = ax[i//columns,i%columns]
          t_lead = lead_order[i]
          t_ax.set_ylabel(lead_index[t_lead])
          t_ax.tick_params(axis='x',rotation=90)
         
          _ax_plot(t_ax, np.arange(0, len(ecg[t_lead])*step, step), ecg[t_lead], seconds)
  
  def plot(
          ecg, 
          sample_rate    = 500, 
          title          = 'ECG 12', 
          lead_index     = lead_index, 
          lead_order     = None,
          rhythm_lead    = 'II',
          style          = None,
          columns        = 2,
          row_height     = 6,
          show_lead_name = True,
          show_grid      = True,
          show_separate_line  = False,
          ):
      """Plot multi lead ECG chart.
      # Arguments
          ecg        : m x n ECG signal data, which m is number of leads and n is length of signal.
          sample_rate: Sample rate of the signal.
          title      : Title which will be shown on top off chart
          lead_index : Lead name array in the same order of ecg, will be shown on 
              left of signal plot, defaults to ['I', 'II', 'III', 'aVR', 'aVL', 'aVF', 'V1', 'V2', 'V3', 'V4', 'V5', 'V6']
          lead_order : Lead display order 
          columns    : display columns, defaults to 2
          style      : display style, defaults to None, can be 'bw' which means black white
          row_height :   how many grid should a lead signal have,
          show_lead_name : show lead name
          show_grid      : show grid
          show_separate_line  : show separate line
      """
  
      if not lead_order:
          lead_order = list(range(0,len(ecg)))
      secs  = len(ecg[0])/sample_rate
      leads = len(lead_order)
      rows  = int(ceil(leads/columns)) + 1 # extra row for the rhythm strip
      # display_factor = 2.5
      display_factor = 1
      line_width = 0.5
      fig, ax = plt.subplots(figsize=(secs/4*columns * display_factor, rows * row_height / 5 * display_factor))
      display_factor = display_factor ** 0.5
      fig.subplots_adjust(
          hspace = 0, 
          wspace = 0,
          left   = 0,  # the left side of the subplots of the figure
          right  = 1,  # the right side of the subplots of the figure
          bottom = 0,  # the bottom of the subplots of the figure
          top    = 1
          )
  
      fig.suptitle(title)
  
      x_min = 0
      x_max = columns*secs/4
      y_min = row_height/4 - (rows/2)*row_height
      y_max = row_height/4
  
      if (style == 'bw'):
          color_major = (0.4,0.4,0.4)
          color_minor = (0.75, 0.75, 0.75)
          color_line  = (0,0,0)
      else:
          color_major = (1,0,0)
          color_minor = (1, 0.7, 0.7)
          color_line  = (0,0,0.7)
  
      if(show_grid):
          ax.set_xticks(np.arange(x_min,x_max,0.2))    
          ax.set_yticks(np.arange(y_min,y_max,0.5))
  
          ax.minorticks_on()
          
          ax.xaxis.set_minor_locator(AutoMinorLocator(5))
  
          ax.grid(which='major', linestyle='-', linewidth=0.5 * display_factor, color=color_major)
          ax.grid(which='minor', linestyle='-', linewidth=0.5 * display_factor, color=color_minor)
  
      ax.set_ylim(y_min,y_max)
      ax.set_xlim(x_min,x_max)
  
  
      for c in range(0, columns): #plot 12 leads
          for i in range(0, rows-1):
              if (c * (rows-1) + i < leads):
                  y_offset = -(row_height/2) * ceil(i%(rows-1))
                  # if (y_offset < -5):
                  #     y_offset = y_offset + 0.25
  
                  x_offset = 0
                  if(c > 0):
                      x_offset = secs/4 * c
                      if(show_separate_line):
                          ax.plot([x_offset, x_offset], [ecg[t_lead][0] + y_offset - 0.3, ecg[t_lead][0] + y_offset + 0.3], linewidth=line_width * display_factor, color=color_line)
  
           
                  t_lead = lead_order[c * (rows-1) + i]
           
                  step = 1.0/sample_rate
                  if(show_lead_name):
                      ax.text(x_offset + 0.07, y_offset - 0.5, lead_index[t_lead], fontsize=9 * display_factor)
                  ax.plot(
                      np.arange(0, len(ecg[t_lead])*step/4, step) + x_offset, 
                      ecg[t_lead][len(ecg[t_lead])*3/4:] + y_offset,
                      linewidth=line_width * display_factor, 
                      color=color_line
                      )
  
      y_offset = -(row_height/2) * (rows-1)
      x_offset = 0
      t_lead = lead_index.index(rhythm_lead)
  
      if(show_lead_name):
          ax.text(x_offset + 0.07, y_offset - 0.5, rhythm_lead, fontsize=11 * display_factor)
      ax.plot(
          np.arange(0, len(ecg[t_lead])*step, step) + x_offset, 
          ecg[t_lead] + y_offset,
          linewidth=line_width * display_factor, 
          color=color_line
          )
  
          
  
  def plot_1(ecg, sample_rate=500, title = 'ECG', fig_width = 15, fig_height = 2, line_w = 0.5, ecg_amp = 1.8, timetick = 0.2):
      """Plot multi lead ECG chart.
      # Arguments
          ecg        : m x n ECG signal data, which m is number of leads and n is length of signal.
          sample_rate: Sample rate of the signal.
          title      : Title which will be shown on top off chart
          fig_width  : The width of the plot
          fig_height : The height of the plot
      """
      plt.figure(figsize=(fig_width,fig_height))
      plt.suptitle(title)
      plt.subplots_adjust(
          hspace = 0, 
          wspace = 0.04,
          left   = 0.04,  # the left side of the subplots of the figure
          right  = 0.98,  # the right side of the subplots of the figure
          bottom = 0.2,   # the bottom of the subplots of the figure
          top    = 0.88
          )
      seconds = len(ecg)/sample_rate
  
      ax = plt.subplot(1, 1, 1)
      #plt.rcParams['lines.linewidth'] = 5
      step = 1.0/sample_rate
      _ax_plot(ax,np.arange(0,len(ecg)*step,step),ecg, seconds, line_w, ecg_amp,timetick)
      
  DEFAULT_PATH = './'
  show_counter = 1
  def show_svg(tmp_path = DEFAULT_PATH):
      """Plot multi lead ECG chart.
      # Arguments
          tmp_path: path for temporary saving the result svg file
      """ 
      global show_counter
      file_name = tmp_path + "show_tmp_file_{}.svg".format(show_counter)
      plt.savefig(file_name)
      os.system("open {}".format(file_name))
      show_counter += 1
      plt.close()
  
  def show():
      plt.show()
  
  
  def save_as_png(file_name, path = DEFAULT_PATH, dpi = 100, layout='tight'):
      """Plot multi lead ECG chart.
      # Arguments
          file_name: file_name
          path     : path to save image, defaults to current folder
          dpi      : set dots per inch (dpi) for the saved image
          layout   : Set equal to "tight" to include ax labels on saved image
      """
      plt.ioff()
      plt.savefig(path + file_name + '.png', dpi = dpi, bbox_inches=layout)
      plt.close()
  
  def save_as_svg(file_name, path = DEFAULT_PATH):
      """Plot multi lead ECG chart.
      # Arguments
          file_name: file_name
          path     : path to save image, defaults to current folder
      """
      plt.ioff()
      plt.savefig(path + file_name + '.svg')
      plt.close()
  
  def save_as_jpg(file_name, path = DEFAULT_PATH):
      """Plot multi lead ECG chart.
      # Arguments
          file_name: file_name
          path     : path to save image, defaults to current folder
      """
      plt.ioff()
      plt.savefig(path + file_name + '.jpg')
      plt.close()
  