from __future__ import absolute_import
from __future__ import print_function
try:
  import numpy
  import pipeline_display
  import pipeline_product
  import platform
except ImportError:
  donothing=1


class Plot:

  def finalSetup(self, subplot, title, tooltip):
    subplot.grid(True)
    subplot.set_title(title, fontsize=12)
    subplot.tooltip = tooltip

class UvesBlueSpectrum:
  def __init__(self, fits, fits_err = None):
    self.spectrum     = pipeline_product.PipelineProduct(fits)
    self.spectrum_err = None
    if fits_err != None:
      self.spectrum_err = pipeline_product.PipelineProduct(fits_err)
    self.loadFromFits()
    self.specdisp = pipeline_display.SpectrumDisplay()

  def loadFromFits(self) :
    self.spectrum.readSpectrum()
    if self.spectrum_err != None :
      self.spectrum_err.readSpectrum()
    self.qc_ex_nord   = self.spectrum.readKeyword('ESO QC EX NORD', 0)
    self.qc_ex_ysize  = self.spectrum.readKeyword('ESO QC EX YSIZE', 0)

  def plot(self, subplot, title, tooltip):
    self.specdisp.setLabels(self.spectrum.type1,
                           'Total Flux ['+self.spectrum.bunit+']')
    if self.spectrum_err == None :
      self.specdisp.display(subplot, title, tooltip, 
                           self.spectrum.wave, self.spectrum.flux, 
                           autolimits=True)
    else :
      os = platform.platform().lower()
      mac_os="darwin" in os
      if mac_os :
          nwave = len(self.spectrum.flux)
          step = int (nwave / 1300 +0.5)
          print("nwave=",nwave,"step=",step)
          print("Mac OS: spectrum resampled every",step,"pixels")
          self.specdisp.display(subplot, title, tooltip, 
                                self.spectrum.wave[::step], 
                                self.spectrum.flux[::step], 
                                self.spectrum_err.flux[::step], 
                                autolimits=True)
      else :
          print("Default OS")
          self.specdisp.display(subplot, title, tooltip, 
                                self.spectrum.wave, 
                                self.spectrum.flux, self.spectrum_err.flux, 
                                autolimits=True)

class UvesRedSpectrum:
  def __init__(self, fits_low, fits_high, 
               fits_low_err = None, fits_high_err = None):
    self.spec_low  = pipeline_product.PipelineProduct(fits_low)
    self.spec_high = pipeline_product.PipelineProduct(fits_high)
    self.spec_low_err = None
    if fits_low_err != None and fits_high_err != None :
      self.spec_low_err  = pipeline_product.PipelineProduct(fits_low_err)
      self.spec_high_err = pipeline_product.PipelineProduct(fits_high_err)
    self.loadFromFits()
    self.specdisp = pipeline_display.SpectrumDisplay()

  def loadFromFits(self) :
    self.spec_low.readSpectrum()
    self.spec_high.readSpectrum()
    if self.spec_low_err != None :
      self.spec_low_err.readSpectrum()
      self.spec_high_err.readSpectrum()
    self.qc_ex_nord_low    = self.spec_low.readKeyword('ESO QC EX NORD', 0)
    self.qc_ex_ysize_low   = self.spec_low.readKeyword('ESO QC EX YSIZE', 0)
    self.qc_ex_nord_high   = self.spec_high.readKeyword('ESO QC EX NORD', 0)
    self.qc_ex_ysize_high  = self.spec_high.readKeyword('ESO QC EX YSIZE', 0)

  def plot(self, subplot, title, tooltip):
    self.specdisp.setLabels(self.spec_low.type1,
                           'Total Flux ['+self.spec_low.bunit+']')
    if self.spec_low_err == None :
      self.specdisp.display(subplot, title, tooltip, 
                            self.spec_low.wave, self.spec_low.flux, 
                            autolimits=True)
      (flux_low_plotmin, flux_low_plotmax)   = self.specdisp.flux_lim
      self.specdisp.display(subplot, title, tooltip, 
                            self.spec_high.wave, self.spec_high.flux, 
                            autolimits=True)
      (flux_high_plotmin, flux_high_plotmax) = self.specdisp.flux_lim
    else :
      self.specdisp.display(subplot, title, tooltip, 
                           self.spec_low.wave, 
                           self.spec_low.flux, self.spec_low_err.flux, 
                           autolimits=True)
      (flux_low_plotmin, flux_low_plotmax)   = self.specdisp.flux_lim
      self.specdisp.display(subplot, title, tooltip, 
                           self.spec_high.wave, 
                           self.spec_high.flux, self.spec_high_err.flux, 
                           autolimits=True)
      (flux_high_plotmin, flux_high_plotmax) = self.specdisp.flux_lim
      
    subplot.set_xlim(min(self.spec_low.start_wave, self.spec_high.start_wave),
                     max(self.spec_low.end_wave, self.spec_high.end_wave))
    flux_plotmin           = min(flux_low_plotmin, flux_high_plotmin) 
    flux_plotmin           = min(flux_plotmin, 0) 
    flux_plotmax           = max(flux_low_plotmax, flux_high_plotmax)
    subplot.set_ylim(flux_plotmin,flux_plotmax)

class ScatterPlot(Plot):
  def __init__(self, fits):
    self.loadFromFits(fits)

  def scatterPlot(self, subplot, x, y, x_label, y_label, title, tooltip):
    self.scatterPlotScatter(subplot, x, y)
    self.setLabels(subplot, x_label, y_label)
    self.scatterPlotLimits(subplot, x, y)
    self.finalSetup(subplot, title, tooltip)

  def scatterPlotScatter(self, subplot, x, y):
    subplot.scatter(x, y, s=1.4, color='blue')

  def scatterPlotScatterSmall(self, subplot, x, y, color_pt='blue'):
    subplot.scatter(x, y, s=0.5, color=color_pt)

  def setLabels(self, subplot, x_label, y_label):
    subplot.set_xlabel(x_label)
    subplot.set_ylabel(y_label)

  def scatterPlotLimits(self, subplot, x, y):
    subplot.set_xlim(0., numpy.nanmax(x) + 1.)
    subplot.set_ylim(0., 1.05 * numpy.nanmax(y))



class PlotableResponseTable(ScatterPlot):
  def __init__(self, fits):
    self.table = pipeline_product.PipelineProduct(fits)
    self.loadFromFits(self.table)

  def loadFromFits(self, table) :
    self.wave_smo        = table.all_hdu[1].data.field('wavelength')
    self.resp_smo        = table.all_hdu[1].data.field('response_smo')
    self.resp_smo_err    = table.all_hdu[1].data.field('response_smo_error')
    self.resp_smo_bpm    = table.all_hdu[1].data.field('response_smo_bpm')

    self.wave_raw        = table.all_hdu[2].data.field('wavelength')
    self.resp_raw        = table.all_hdu[2].data.field('response_raw')
    self.resp_raw_err    = table.all_hdu[2].data.field('response_raw_error')
    self.resp_raw_bpm    = table.all_hdu[2].data.field('response_raw_bpm')

    self.wave_fit_pts        = table.all_hdu[3].data.field('wavelength')
    self.resp_fit_pts        = table.all_hdu[3].data.field('response_fit_pts')
    self.resp_fit_pts_err    = table.all_hdu[3].data.field('response_fit_pts_error')
    self.resp_fit_pts_bpm    = table.all_hdu[3].data.field('response_fit_pts_bpm')


  def maxWaveSmo(self):
    return numpy.nanmax(self.wave_smo)
  def minWaveSmo(self):
    return numpy.nanmin(self.wave_smo)

  def maxWaveRaw(self):
    return numpy.nanmax(self.wave_raw)
  def minWaveRaw(self):
    return numpy.nanmin(self.wave_raw)


class PlotableBlueResponseTable(PlotableResponseTable):
  def __init__(self, fits):
    self.table = pipeline_product.PipelineProduct(fits)
    self.loadFromFits(self.table)

  def plotResponseRaw(self, subplot, title, tooltip):
    print("min",self.minWaveRaw())
    self.scatterPlot(subplot, self.wave_raw, self.resp_raw, 'Wavelength', 'Response [erg/e-/cm2]', title, tooltip)
    self.scatterPlotScatterSmall(subplot, self.wave_smo, self.resp_smo,color_pt='green')
    self.scatterPlotScatterSmall(subplot, self.wave_fit_pts, self.resp_fit_pts,color_pt='red')
    subplot.set_xlim(self.minWaveRaw(), self.maxWaveRaw())
    self.finalSetup(subplot, title, tooltip)

class PlotableRedResponseTable(PlotableResponseTable):
  def __init__(self, fits_low, fits_high):
    self.resp_low         = PlotableResponseTable(fits_low)
    self.resp_high        = PlotableResponseTable(fits_high)
    #self.order_high_shift  = self.order_high.order_raw + self.order_low.maxOrder()
    #self.max_total_order   = numpy.nanmax(self.order_high_shift)

  def plotResponseRaw(self, subplot, title, tooltip):
    #self.plotLowHiTextBottom(subplot)
    self.setLabels(subplot, 'Wavelength', 'Response [erg/e-/cm2]')
    self.scatterPlot(subplot, self.resp_low.wave_raw, self.resp_low.resp_raw, 'Wavelength', 'Response [erg/e-/cm2]', title, tooltip)
    self.scatterPlotScatterSmall(subplot, self.resp_low.wave_smo, self.resp_low.resp_smo,color_pt='green')
    self.scatterPlotScatterSmall(subplot, self.resp_low.wave_fit_pts, self.resp_low.resp_fit_pts,color_pt='red')
    #subplot.set_xlim(self.resp_low.minWaveRaw(), self.resp_high.maxWaveRaw())

    
    self.scatterPlot(subplot, self.resp_high.wave_raw, self.resp_high.resp_raw, 'Wavelength', 'Response [erg/e-/cm2]', title, tooltip)
    self.scatterPlotScatterSmall(subplot, self.resp_high.wave_smo, self.resp_high.resp_smo,color_pt='green')
    self.scatterPlotScatterSmall(subplot, self.resp_high.wave_fit_pts, self.resp_high.resp_fit_pts,color_pt='red')
    subplot.set_xlim(self.resp_low.minWaveRaw(), self.resp_high.maxWaveRaw())

    #subplot.set_ylim(0., 1.05 * max(self.order_low.maxSN(), self.order_high.maxSN()))
    #self.plotLowHiSepLine(subplot)
    self.finalSetup(subplot, title, tooltip)

    
class PlotableOrderTable(ScatterPlot):
  def __init__(self, fits):
    self.table = pipeline_product.PipelineProduct(fits)
    self.loadFromFits(self.table)

  def loadFromFits(self, table) :
    self.order_raw      = table.all_hdu[1].data.field('Order')
    self.sn_raw         = table.all_hdu[1].data.field('ObjSnBlzCentre')
    self.fwhm_raw       = table.all_hdu[1].data.field('ObjFwhmAvg')
    self.pos_raw        = table.all_hdu[1].data.field('ObjPosOnSlit')
    self.ripple_raw     = table.all_hdu[1].data.field('Ripple')

  def maxOrder(self):
    return numpy.nanmax(self.order_raw)
  
  def maxSN(self):
    return numpy.nanmax(self.sn_raw)
  
  def minSN(self):
    return numpy.nanmin(self.sn_raw)
  
  def maxFWHM(self):
    return numpy.nanmax(self.fwhm_raw)
  
  def minFWHM(self):
    return numpy.nanmin(self.fwhm_raw)

  def maxRipple(self):
    return numpy.nanmax(self.ripple_raw)
  
  def minRipple(self):
    return numpy.nanmin(self.ripple_raw)
  
  def maxLinepos(self):
    return numpy.nanmax(self.pos_raw)
  
  def minLinepos(self):
    return numpy.nanmin(self.pos_raw)


class PlotableBlueOrderTable(PlotableOrderTable):
  def __init__(self, fits):
    self.table = pipeline_product.PipelineProduct(fits)
    self.loadFromFits(self.table)

  def plotSN(self, subplot, title, tooltip):
    self.scatterPlot(subplot, self.order_raw, self.sn_raw, 'Order', 'S/N', title, tooltip)

  def plotFWHM(self, subplot, title, tooltip):
    self.scatterPlot(subplot, self.order_raw, self.fwhm_raw, 'Order', 'FWHM (pix)', title, tooltip)

  def plotRipple(self, subplot, title, tooltip):
    self.setLabels(subplot, 'Order', 'Ripple')
    self.scatterPlotScatter(subplot, self.order_raw, self.ripple_raw)
    subplot.set_xlim(0., self.maxOrder() + 1.)
    self.finalSetup(subplot, title, tooltip)

  def plotLinepos(self, subplot, title, tooltip):
    self.scatterPlot(subplot, self.order_raw, self.pos_raw, 'Order', 'Slit Position (pix)', title, tooltip)
  
class PlotableRedOrderTable(PlotableOrderTable):
  def __init__(self, fits_low, fits_high):
    self.order_low         = PlotableOrderTable(fits_low)
    self.order_high        = PlotableOrderTable(fits_high)
    self.order_high_shift  = self.order_high.order_raw + self.order_low.maxOrder()
    self.max_total_order   = numpy.nanmax(self.order_high_shift)

  def plotSN(self, subplot, title, tooltip):
    self.plotLowHiTextBottom(subplot)
    self.setLabels(subplot, 'Order', 'S/N')
    self.scatterPlotScatter(subplot, self.order_low.order_raw, self.order_low.sn_raw)
    self.scatterPlotScatter(subplot, self.order_high_shift,    self.order_high.sn_raw)
    subplot.set_xlim(0., self.max_total_order + 1.)
    subplot.set_ylim(0., 1.05 * max(self.order_low.maxSN(), self.order_high.maxSN()))
    self.plotLowHiSepLine(subplot)
    self.finalSetup(subplot, title, tooltip)

  def plotFWHM(self, subplot, title, tooltip):
    self.plotLowHiTextBottom(subplot)
    self.setLabels(subplot, 'Order', 'FWHM (pix)')
    self.scatterPlotScatter(subplot, self.order_low.order_raw, self.order_low.fwhm_raw)
    self.scatterPlotScatter(subplot, self.order_high_shift,    self.order_high.fwhm_raw)
    subplot.set_xlim(0., self.max_total_order + 1.)
    subplot.set_ylim(0., 1.05 * max(self.order_low.maxFWHM(), self.order_high.maxFWHM()))
    self.plotLowHiSepLine(subplot)
    self.finalSetup(subplot, title, tooltip)

  def plotRipple(self, subplot, title, tooltip):
    self.plotLowHiTextBottom(subplot)
    self.setLabels(subplot, 'Order', 'Ripple')
    self.scatterPlotScatter(subplot, self.order_low.order_raw, self.order_low.ripple_raw)
    self.scatterPlotScatter(subplot, self.order_high_shift,    self.order_high.ripple_raw)
    subplot.set_xlim(0., self.max_total_order + 1.)
    self.plotLowHiSepLine(subplot)
    self.finalSetup(subplot, title, tooltip)

  def plotLinepos(self, subplot, title, tooltip):
    self.plotLowHiTextBottom(subplot)
    self.setLabels(subplot, 'Order', 'Slit Position (pix)')
    self.scatterPlotScatter(subplot, self.order_low.order_raw, self.order_low.pos_raw)
    self.scatterPlotScatter(subplot, self.order_high_shift,    self.order_high.pos_raw)
    subplot.set_xlim(0., self.max_total_order + 1.)
    self.plotLowHiSepLine(subplot)
    self.finalSetup(subplot, title, tooltip)

  def plotLowHiSepLine(self, subplot):
    subplot.axvline(linewidth=1.5, color='black', x=self.order_low.maxOrder() + 0.5)

  def plotLowHiTextBottom(self, subplot):
    subplot.text(0.1, 0.1, "RedLo", transform = subplot.transAxes,
                 ha="left",size=13,bbox=dict(boxstyle="round",alpha=0.2))
    subplot.text(0.9, 0.1, "RedHi", transform = subplot.transAxes,
                 ha="right",size=13,bbox=dict(boxstyle="round",alpha=0.2))
    
  def maxSN(self):
    return max(self.order_low.maxSN(), self.order_high.maxSN())
  
  def minSN(self):
    return min(self.order_low.minSN(), self.order_high.minSN())
  
  def maxFWHM(self):
    return max(self.order_low.maxFWHM(), self.order_high.maxFWHM())
  
  def minFWHM(self):
    return min(self.order_low.minFWHM(), self.order_high.minFWHM())

  def maxRipple(self):
    return max(self.order_low.maxRipple(), self.order_high.maxRipple())
  
  def minRipple(self):
    return min(self.order_low.minRipple(), self.order_high.minRipple())
  
  def maxLinepos(self):
    return max(self.order_low.maxLinepos(), self.order_high.maxLinepos())
  
  def minLinepos(self):
    return min(self.order_low.minLinepos(), self.order_high.minLinepos())
  
class PlotableLineGuessTable(ScatterPlot):
  def __init__(self, fits):
    self.table = pipeline_product.PipelineProduct(fits)
    self.loadFromFits(self.table)
  
  def loadFromFits(self, table) :
    self.xdif_raw    = table.all_hdu[1].data.field('XDIF')
    self.ydif_raw    = table.all_hdu[1].data.field('YDIF')
    self.x_raw       = table.all_hdu[1].data.field('X')
    self.ynew_raw    = table.all_hdu[1].data.field('YNEW')
    self.select_raw  = table.all_hdu[1].data.field('SELPLOT')
    self.det_nx      = table.all_hdu[0].header['ESO DET OUT1 NX']
    self.det_ny      = table.all_hdu[0].header['ESO DET OUT1 NY']
    self.xdif_sel    = self.xdif_raw[self.select_raw == 1]
    self.x_sel       = self.x_raw[self.select_raw == 1]
    self.ydif_sel    = self.ydif_raw[self.select_raw == 1]
    self.ynew_sel    = self.ynew_raw[self.select_raw == 1]
    self.min_x       = numpy.nanmin(self.x_raw)
    self.max_x       = numpy.nanmax(self.x_raw)
    self.min_ynew    = numpy.nanmin(self.ynew_raw)
    self.max_ynew    = numpy.nanmax(self.ynew_raw)
    self.median_xdif = numpy.median(self.xdif_sel)
    self.mean_xdif   = numpy.mean(self.xdif_sel)
    self.std_xdif    = numpy.std(self.xdif_sel)
    self.median_ydif = numpy.median(self.ydif_sel)
    self.mean_ydif   = numpy.mean(self.ydif_sel)
    self.std_ydif    = numpy.std(self.ydif_sel)

class PlotableBlueLineGuessTable(PlotableLineGuessTable):

  def plotXDIFvsX(self, subplot, title, tooltip) :
    self.setLabels(subplot, 'X [pix]', 'XDIF [pix]')
    self.scatterPlotScatterSmall(subplot, self.x_sel, self.xdif_sel)
    subplot.set_xlim(self.min_x, self.max_x)
    subplot.axhline(y=self.median_xdif, color='black', lw=1.2)
    subplot.axhline(y=self.median_xdif+self.std_xdif, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_xdif-self.std_xdif, color='black', ls='-.', lw=1.2)
    self.finalSetup(subplot, title, tooltip)

  def plotYDIFvsX(self, subplot, title, tooltip) :
    self.setLabels(subplot, 'X [pix]', 'YDIF [pix]')
    self.scatterPlotScatterSmall(subplot, self.x_sel, self.ydif_sel)
    subplot.set_xlim(self.min_x, self.max_x)
    subplot.axhline(y=self.median_ydif, color='black', lw=1.2)
    subplot.axhline(y=self.median_ydif+self.std_ydif, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_ydif-self.std_ydif, color='black', ls='-.', lw=1.2)
    self.finalSetup(subplot, title, tooltip)

  def plotXDIFvsY(self, subplot, title, tooltip) :
    self.setLabels(subplot,'Y [pix]', 'XDIF [pix]')
    self.scatterPlotScatterSmall(subplot, self.ynew_sel, self.xdif_sel)
    subplot.set_xlim(self.min_ynew, self.max_ynew)
    subplot.axhline(y=self.median_xdif, color='black', lw=1.2)
    subplot.axhline(y=self.median_xdif+self.std_xdif, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_xdif-self.std_xdif, color='black', ls='-.', lw=1.2)
    self.finalSetup(subplot, title, tooltip)

  def plotYDIFvsY(self, subplot, title, tooltip) :
    self.setLabels(subplot,'Y [pix]', 'YDIF [pix]')
    self.scatterPlotScatterSmall(subplot, self.ynew_sel, self.ydif_sel)
    subplot.set_xlim(self.min_ynew, self.max_ynew)
    subplot.axhline(y=self.median_ydif, color='black', lw=1.2)
    subplot.axhline(y=self.median_ydif+self.std_ydif, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_ydif-self.std_ydif, color='black', ls='-.', lw=1.2)
    self.finalSetup(subplot, title, tooltip)

  def plotYDIFvsXDIF(self, subplot, title, tooltip) :
    self.setLabels(subplot,'XDIF [pix]', 'YDIF [pix]')
    self.scatterPlotScatterSmall(subplot, self.xdif_sel, self.ydif_sel)
    subplot.axhline(y=self.median_ydif, color='black', lw=1.2)
    subplot.axvline(x=self.median_xdif, color='black', lw=1.2)
    self.finalSetup(subplot, title, tooltip)

  def plotYvsX(self, subplot, title, tooltip) :
    self.setLabels(subplot,'X [pix]', 'Y [pix]')
    self.scatterPlotScatterSmall(subplot, self.x_raw, self.ynew_raw, 'red')
    self.scatterPlotScatterSmall(subplot, self.x_sel, self.ynew_sel)
    subplot.set_xlim(0., self.det_ny)
    subplot.set_ylim(0., self.det_nx)
    self.finalSetup(subplot, title, tooltip)
 

class PlotableRedLineGuessTable(ScatterPlot):
  def __init__(self, fits_low, fits_high):
    self.tab_low = PlotableLineGuessTable(fits_low)
    self.tab_high = PlotableLineGuessTable(fits_high)
    self.x_sel_shift     = self.tab_high.x_sel + self.tab_low.det_ny
    self.x_raw_shift     = self.tab_high.x_raw + self.tab_low.det_ny
    self.y_sel_shift     = self.tab_high.ynew_sel + self.tab_low.det_nx
    self.y_raw_shift     = self.tab_high.ynew_raw + self.tab_low.det_nx
    self.ynew_sel_shift  = self.tab_high.ynew_sel + self.tab_low.det_nx
    self.median_all_xdif = numpy.median(numpy.concatenate((self.tab_low.xdif_sel, self.tab_high.xdif_sel)))
    self.mean_all_xdif   = numpy.mean(numpy.concatenate((self.tab_low.xdif_sel, self.tab_high.xdif_sel)))
    self.std_all_xdif    = numpy.std(numpy.concatenate((self.tab_low.xdif_sel, self.tab_high.xdif_sel)))
    self.median_all_ydif = numpy.median(numpy.concatenate((self.tab_low.ydif_sel, self.tab_high.ydif_sel)))
    self.mean_all_ydif   = numpy.mean(numpy.concatenate((self.tab_low.ydif_sel, self.tab_high.ydif_sel)))
    self.std_all_ydif    = numpy.std(numpy.concatenate((self.tab_low.ydif_sel, self.tab_high.ydif_sel)))

  def plotGridLowHiTextRight(self, grid):
    grid[1].text(0.9, 0.1, "RedLo", transform = grid[1].transAxes,
                 ha="right",size=13,bbox=dict(boxstyle="round",alpha=0.2))
    grid[0].text(0.9, 0.9, "RedHi", transform = grid[0].transAxes,
                 ha="right",va="top",size=13,bbox=dict(boxstyle="round",alpha=0.2))

  def plotLowHiTextBottom(self, subplot):
    subplot.text(0.1, 0.1, "RedLo", transform = subplot.transAxes,
                 ha="left",size=13,bbox=dict(boxstyle="round",alpha=0.2))
    subplot.text(0.9, 0.1, "RedHi", transform = subplot.transAxes,
                 ha="right",size=13,bbox=dict(boxstyle="round",alpha=0.2))

  def plotLowHiTextRight(self, subplot):
    subplot.text(0.9, 0.1, "RedLo", transform = subplot.transAxes,
                 ha="right",size=13,bbox=dict(boxstyle="round",alpha=0.2))
    subplot.text(0.9, 0.9, "RedHi", transform = subplot.transAxes,
                 ha="right",va="top",size=13,bbox=dict(boxstyle="round",alpha=0.2))

  def plotGridXDIFvsX(self, grid, title, tooltip) :
    self.plotGridLowHiTextRight(grid)
    self.setLabels(grid[0], 'X [pix]', 'XDIF [pix]')
    self.scatterPlotScatterSmall(grid[0], self.tab_high.x_sel, self.tab_high.xdif_sel)
    self.setLabels(grid[1], 'X [pix]', 'XDIF [pix]')
    self.scatterPlotScatterSmall(grid[1], self.tab_low.x_sel, self.tab_low.xdif_sel)
    grid[0].set_xlim(min(self.tab_low.min_x, self.tab_high.min_x), max(self.tab_low.max_x, self.tab_high.max_x))
    grid[1].set_xlim(min(self.tab_low.min_x, self.tab_high.min_x), max(self.tab_low.max_x, self.tab_high.max_x))
#    Should we plot here the median of that chip or the median of all the values?
    grid[0].axhline(y=self.tab_high.median_xdif, color='black', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_xdif, color='black', lw=1.2)
    grid[0].axhline(y=self.tab_high.median_xdif+self.tab_high.std_xdif, color='black', ls='-.', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_xdif+self.tab_low.std_xdif, color='black', ls='-.', lw=1.2)
    grid[0].axhline(y=self.tab_high.median_xdif-self.tab_high.std_xdif, color='black', ls='-.', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_xdif-self.tab_low.std_xdif, color='black', ls='-.', lw=1.2)
    self.finalSetup(grid[0], title, tooltip)
    self.finalSetup(grid[1], "", tooltip)

  def plotXDIFvsX(self, subplot, title, tooltip) :
    self.plotLowHiTextBottom(subplot)
    self.setLabels(subplot, 'X [pix]', 'XDIF [pix]')
    self.scatterPlotScatterSmall(subplot, self.x_sel_shift, self.tab_high.xdif_sel)
    self.scatterPlotScatterSmall(subplot, self.tab_low.x_sel, self.tab_low.xdif_sel)
    subplot.set_xlim(min(self.tab_low.min_x, self.tab_high.min_x + self.tab_low.det_ny), max(self.tab_low.max_x, self.tab_high.max_x + self.tab_low.det_ny))
    subplot.axhline(y=self.median_all_xdif, color='black', lw=1.2)
    subplot.axhline(y=self.median_all_xdif+self.std_all_xdif, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_all_xdif-self.std_all_xdif, color='black', ls='-.', lw=1.2)
    subplot.axvline(linewidth=1.5, color='black', x=self.tab_low.det_ny)
    self.finalSetup(subplot, title, tooltip)

  def plotGridYDIFvsX(self, grid, title, tooltip) :
    self.plotGridLowHiTextRight(grid)
    self.setLabels(grid[0], 'X [pix]', 'YDIF [pix]')
    self.scatterPlotScatterSmall(grid[0], self.tab_high.x_sel, self.tab_high.ydif_sel)
    self.setLabels(grid[1], 'X [pix]', 'YDIF [pix]')
    self.scatterPlotScatterSmall(grid[1], self.tab_low.x_sel, self.tab_low.ydif_sel)
    grid[0].set_xlim(min(self.tab_low.min_x, self.tab_high.min_x), max(self.tab_low.max_x, self.tab_high.max_x))
    grid[1].set_xlim(min(self.tab_low.min_x, self.tab_high.min_x), max(self.tab_low.max_x, self.tab_high.max_x))
#    Should we plot here the median of that chip or the median of all the values?
    grid[0].axhline(y=self.tab_high.median_ydif, color='black', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_ydif, color='black', lw=1.2)
    grid[0].axhline(y=self.tab_high.median_ydif+self.tab_high.std_ydif, color='black', ls='-.', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_ydif+self.tab_low.std_ydif, color='black', ls='-.', lw=1.2)
    grid[0].axhline(y=self.tab_high.median_ydif-self.tab_high.std_ydif, color='black', ls='-.', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_ydif-self.tab_low.std_ydif, color='black', ls='-.', lw=1.2)
    self.finalSetup(grid[0], title, tooltip)
    self.finalSetup(grid[1], "", tooltip)

  def plotYDIFvsX(self, subplot, title, tooltip) :
    self.plotLowHiTextBottom(subplot)
    self.setLabels(subplot, 'X [pix]', 'YDIF [pix]')
    self.scatterPlotScatterSmall(subplot, self.x_sel_shift, self.tab_high.ydif_sel)
    self.scatterPlotScatterSmall(subplot, self.tab_low.x_sel, self.tab_low.ydif_sel)
    subplot.set_xlim(min(self.tab_low.min_x, self.tab_high.min_x + self.tab_low.det_ny), max(self.tab_low.max_x, self.tab_high.max_x + self.tab_low.det_ny))
    subplot.axhline(y=self.median_all_ydif, color='black', lw=1.2)
    subplot.axhline(y=self.median_all_ydif+self.std_all_ydif, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_all_ydif-self.std_all_ydif, color='black', ls='-.', lw=1.2)
    subplot.axvline(linewidth=1.5, color='black', x=self.tab_low.det_ny)
    self.finalSetup(subplot, title, tooltip)

  def plotGridXDIFvsY(self, grid, title, tooltip) :
    self.plotGridLowHiTextRight(grid)
    self.setLabels(grid[0], 'Y [pix]', 'XDIF [pix]')
    self.scatterPlotScatterSmall(grid[0], self.tab_high.ynew_sel, self.tab_high.xdif_sel)
    self.setLabels(grid[1], 'Y [pix]', 'XDIF [pix]')
    self.scatterPlotScatterSmall(grid[1], self.tab_low.ynew_sel, self.tab_low.xdif_sel)
    grid[0].set_xlim(min(self.tab_low.min_ynew, self.tab_high.min_ynew), max(self.tab_low.max_ynew, self.tab_high.max_ynew))
    grid[1].set_xlim(min(self.tab_low.min_ynew, self.tab_high.min_ynew), max(self.tab_low.max_ynew, self.tab_high.max_ynew))
#    Should we plot here the median of that chip or the median of all the values?
    grid[0].axhline(y=self.tab_high.median_xdif, color='black', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_xdif, color='black', lw=1.2)
    grid[0].axhline(y=self.tab_high.median_xdif+self.tab_high.std_xdif, color='black', ls='-.', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_xdif+self.tab_low.std_xdif, color='black', ls='-.', lw=1.2)
    grid[0].axhline(y=self.tab_high.median_xdif-self.tab_high.std_xdif, color='black', ls='-.', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_xdif-self.tab_low.std_xdif, color='black', ls='-.', lw=1.2)
    self.finalSetup(grid[0], title, tooltip)
    self.finalSetup(grid[1], "", tooltip)

  def plotXDIFvsY(self, subplot, title, tooltip) :
    self.plotLowHiTextBottom(subplot)
    self.scatterPlotScatterSmall(subplot, self.ynew_sel_shift, self.tab_high.xdif_sel)
    self.scatterPlotScatterSmall(subplot, self.tab_low.ynew_sel, self.tab_low.xdif_sel)
    self.setLabels(subplot, 'Y [pix]', 'XDIF [pix]')
    subplot.set_xlim(min(self.tab_low.min_ynew, self.tab_high.min_ynew + self.tab_low.det_nx), max(self.tab_low.max_ynew, self.tab_high.max_ynew + self.tab_low.det_nx))
    subplot.axhline(y=self.median_all_xdif, color='black', lw=1.2)
    subplot.axhline(y=self.median_all_xdif+self.std_all_xdif, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_all_xdif-self.std_all_xdif, color='black', ls='-.', lw=1.2)
    subplot.axvline(linewidth=1.5, color='black', x=self.tab_low.det_nx)
    self.finalSetup(subplot, title, tooltip)

  def plotGridYDIFvsY(self, grid, title, tooltip) :
    self.plotGridLowHiTextRight(grid)
    self.setLabels(grid[0], 'Y [pix]', 'YDIF [pix]')
    self.scatterPlotScatterSmall(grid[0], self.tab_high.ynew_sel, self.tab_high.ydif_sel)
    self.setLabels(grid[1], 'Y [pix]', 'YDIF [pix]')
    self.scatterPlotScatterSmall(grid[1], self.tab_low.ynew_sel, self.tab_low.ydif_sel)
    grid[0].set_xlim(min(self.tab_low.min_ynew, self.tab_high.min_ynew), max(self.tab_low.max_ynew, self.tab_high.max_ynew))
    grid[1].set_xlim(min(self.tab_low.min_ynew, self.tab_high.min_ynew), max(self.tab_low.max_ynew, self.tab_high.max_ynew))
#    Should we plot here the median of that chip or the median of all the values?
    grid[0].axhline(y=self.tab_high.median_ydif, color='black', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_ydif, color='black', lw=1.2)
    grid[0].axhline(y=self.tab_high.median_ydif+self.tab_high.std_ydif, color='black', ls='-.', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_ydif+self.tab_low.std_ydif, color='black', ls='-.', lw=1.2)
    grid[0].axhline(y=self.tab_high.median_ydif-self.tab_high.std_ydif, color='black', ls='-.', lw=1.2)
    grid[1].axhline(y=self.tab_low.median_ydif-self.tab_low.std_ydif, color='black', ls='-.', lw=1.2)
    self.finalSetup(grid[0], title, tooltip)
    self.finalSetup(grid[1], "", tooltip)

  def plotYDIFvsY(self, subplot, title, tooltip) :
    self.plotLowHiTextBottom(subplot)
    self.setLabels(subplot, 'Y [pix]', 'YDIF [pix]')
    self.scatterPlotScatterSmall(subplot, self.ynew_sel_shift, self.tab_high.ydif_sel)
    self.scatterPlotScatterSmall(subplot, self.tab_low.ynew_sel, self.tab_low.ydif_sel)
    subplot.set_xlim(min(self.tab_low.min_ynew, self.tab_high.min_ynew + self.tab_low.det_nx), max(self.tab_low.max_ynew, self.tab_high.max_ynew + self.tab_low.det_nx))
    subplot.axhline(y=self.median_all_ydif, color='black', lw=1.2)
    subplot.axhline(y=self.median_all_ydif+self.std_all_ydif, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_all_ydif-self.std_all_ydif, color='black', ls='-.', lw=1.2)
    subplot.axvline(linewidth=1.5, color='black', x=self.tab_low.det_nx)
    self.finalSetup(subplot, title, tooltip)

  def plotYDIFvsXDIF(self, subplot, title, tooltip) :
    self.setLabels(subplot, 'XDIF [pix]', 'YDIF [pix]')
    self.scatterPlotScatterSmall(subplot, self.tab_high.xdif_sel, self.tab_high.ydif_sel)
    self.scatterPlotScatterSmall(subplot, self.tab_low.xdif_sel, self.tab_low.ydif_sel,'red')
    subplot.axhline(y=self.median_all_ydif, color='black', lw=1.2)
    subplot.axvline(x=self.median_all_xdif, color='black', lw=1.2)
    self.finalSetup(subplot, title, tooltip)

  def plotGridYvsX(self, grid, title, tooltip) :
    self.plotGridLowHiTextRight(grid)
    self.setLabels(grid[0], 'X [pix]', 'Y [pix]')
    self.scatterPlotScatterSmall(grid[0], self.tab_high.x_raw, self.tab_high.ynew_raw, color_pt='red')
    self.scatterPlotScatterSmall(grid[0], self.tab_high.x_sel, self.tab_high.ynew_sel, color_pt='blue')
    self.setLabels(grid[1], 'X [pix]', 'Y [pix]')
    self.scatterPlotScatterSmall(grid[1], self.tab_low.x_raw, self.tab_low.ynew_raw, color_pt='red')
    self.scatterPlotScatterSmall(grid[1], self.tab_low.x_sel, self.tab_low.ynew_sel, color_pt='blue')
    grid[0].set_xlim(0, self.tab_high.det_ny)
    grid[0].set_ylim(0, self.tab_high.det_nx)
    grid[1].set_xlim(0, self.tab_low.det_ny)
    grid[1].set_ylim(0, self.tab_low.det_nx)
    self.finalSetup(grid[0], title, tooltip)
    self.finalSetup(grid[1], "", tooltip)

  def plotYvsX(self, subplot, title, tooltip) :
    self.plotLowHiTextRight(subplot)
    self.setLabels(subplot, 'X [pix]', 'Y [pix]')
    self.scatterPlotScatterSmall(subplot, self.tab_high.x_raw, self.y_raw_shift, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.tab_high.x_sel, self.y_sel_shift, color_pt='blue')
    self.scatterPlotScatterSmall(subplot, self.tab_low.x_raw, self.tab_low.ynew_raw, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.tab_low.x_sel, self.tab_low.ynew_sel, color_pt='blue')
    subplot.set_xlim(0, self.tab_low.det_ny)
    subplot.set_ylim(0, self.tab_high.det_nx + self.tab_low.det_nx)
    subplot.axhline(linewidth=1.5, color='black', y=self.tab_low.det_nx)
    self.finalSetup(subplot, title, tooltip)

class PlotableLineTable(ScatterPlot):
  def __init__(self, fits):
    self.table = pipeline_product.PipelineProduct(fits)
    self.loadFromFits(self.table)
  
  def loadFromFits(self, table) :
    n_win                = (table.all_hdu.__len__() - 1 )//3
    id_win               = (n_win+1)//2
    ext_id               = 3 * (id_win -1 ) + 1
    self.x_raw           = table.all_hdu[ext_id].data.field('X')
    self.ynew_raw        = table.all_hdu[ext_id].data.field('Ynew')
    self.residual_raw    = table.all_hdu[ext_id].data.field('Residual')
    self.order_raw       = table.all_hdu[ext_id].data.field('Y')
    self.xwidth_raw      = table.all_hdu[ext_id].data.field('Xwidth')
    self.wavec_raw       = table.all_hdu[ext_id].data.field('WaveC')
    self.select_raw      = table.all_hdu[ext_id].data.field('NLinSol')
    self.det_nx          = table.all_hdu[0].header['ESO DET OUT1 NX']
    self.det_ny          = table.all_hdu[0].header['ESO DET OUT1 NY']
    self.nlintot         = table.all_hdu[0].header['ESO QC NLINTOT']
    self.nlinsel         = table.all_hdu[0].header['ESO QC NLINSEL']
    self.nlinsol         = table.all_hdu[0].header['ESO QC NLINSOL']
    self.fwhm            = self.xwidth_raw * 2.35
    self.fwhm_sel        = self.fwhm[self.select_raw == 1]
    self.fwhm_clean      = self.fwhm_sel[numpy.isfinite(self.fwhm_sel)]
    self.x_sel           = self.x_raw[self.select_raw == 1]
    self.ynew_sel        = self.ynew_raw[self.select_raw == 1]
    self.wavec_sel       = self.wavec_raw[self.select_raw == 1]
    self.residual_sel    = self.residual_raw[self.select_raw == 1]
    self.order_sel       = self.order_raw[self.select_raw == 1]
    self.min_wavec       = numpy.nanmin(self.wavec_raw)
    self.max_wavec       = numpy.nanmax(self.wavec_raw)
    self.mean_residual   = numpy.mean(self.residual_sel)
    self.median_residual = numpy.median(self.residual_sel)
    self.std_residual    = numpy.std(self.residual_sel)
    self.max_order       = numpy.nanmax(self.order_raw)
    self.max_fwhm        = numpy.nanmax(self.fwhm)
    self.mean_fwhm       = numpy.mean(self.fwhm_clean)
    self.median_fwhm     = numpy.median(self.fwhm_clean)
    self.std_fwhm        = numpy.std(self.fwhm_clean)

class PlotableBlueLineTable(PlotableLineTable):
  def plotRESvsWAVE(self, subplot, title, tooltip) :
    self.scatterPlotScatterSmall(subplot, self.wavec_raw, self.residual_raw, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.wavec_sel, self.residual_sel)
    self.setLabels(subplot, 'Wavelength [Ang]', 'Wavelength Residual [Ang]')
    subplot.set_xlim(self.min_wavec, self.max_wavec)
    subplot.axhline(y=self.median_residual, color='black', lw=1.2)
    subplot.axhline(y=self.median_residual+self.std_residual, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_residual-self.std_residual, color='black', ls='-.', lw=1.2)
    self.finalSetup(subplot, title, tooltip)
    
  def plotRESvsORDER(self, subplot, title, tooltip) :
    self.setLabels(subplot, 'Order', 'Wavelength Residual [Ang]')
    self.scatterPlotScatterSmall(subplot, self.order_raw, self.residual_raw, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.order_sel, self.residual_sel)
    subplot.set_xlim(0., self.max_order + 1.)
    subplot.axhline(y=self.median_residual, color='black', lw=1.2)
    subplot.axhline(y=self.median_residual+self.std_residual, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_residual-self.std_residual, color='black', ls='-.', lw=1.2)
    self.finalSetup(subplot, title, tooltip)
    
  def plotFWHMvsWAVE(self, subplot, title, tooltip) :
    self.setLabels(subplot, 'Wavelength [Ang]', 'Line FWHM [pix]')
    self.scatterPlotScatterSmall(subplot, self.wavec_raw, self.fwhm, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.wavec_sel, self.fwhm_sel)
    subplot.set_xlim(self.min_wavec, self.max_wavec)
    subplot.set_ylim(0., self.max_fwhm * 1.05)
    subplot.axhline(y=self.median_fwhm, color='black', lw=1.2)
    subplot.axhline(y=self.median_fwhm+self.std_fwhm, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_fwhm-self.std_fwhm, color='black', ls='-.', lw=1.2)
    self.finalSetup(subplot, title, tooltip)

  def plotYvsX(self, subplot, title, tooltip) :
    self.setLabels(subplot,'X [pix]', 'Y [pix]')
    self.scatterPlotScatterSmall(subplot, self.x_raw, self.ynew_raw, 'red')
    self.scatterPlotScatterSmall(subplot, self.x_sel, self.ynew_sel)
    subplot.set_xlim(0., self.det_ny)
    subplot.set_ylim(0., self.det_nx)
    self.finalSetup(subplot, title, tooltip)

  def plotLinesText(self, subplot) :
     subplot.set_axis_off()
     text1 = 'No. of detected lines = %g'%self.nlintot 
     subplot.text(0.05, 0.80, text1, color='#11557c', fontsize=15, ha='left', va='center', alpha=1.0)
     text2 = 'Initial no. of fitted lines = %g'%self.nlinsel
     subplot.text(0.05, 0.65, text2, color='#11557c', fontsize=15, ha='left', va='center', alpha=1.0)
     text3 = 'Final no. of fitted lines = %g'%self.nlinsol 
     subplot.text(0.05, 0.50, text3, color='#11557c', fontsize=15, ha='left', va='center', alpha=1.0)
     subplot.tooltip='Lines info'

class PlotableRedLineTable(ScatterPlot):
  def __init__(self, fits_low, fits_high):
    self.tab_low              = PlotableLineTable(fits_low)
    self.tab_high             = PlotableLineTable(fits_high)
    self.min_wavec            = min(self.tab_low.min_wavec, self.tab_high.min_wavec)
    self.max_wavec            = max(self.tab_low.max_wavec, self.tab_high.max_wavec)
    self.median_all_residual  = numpy.median(numpy.concatenate((self.tab_low.residual_sel, self.tab_high.residual_sel)))
    self.mean_all_residual    = numpy.mean(numpy.concatenate((self.tab_low.residual_sel, self.tab_high.residual_sel)))
    self.std_all_residual     = numpy.std(numpy.concatenate((self.tab_low.residual_sel, self.tab_high.residual_sel)))
    self.median_all_fwhm      = numpy.median(numpy.concatenate((self.tab_low.fwhm_sel, self.tab_high.fwhm_sel)))
    self.mean_all_fwhm        = numpy.mean(numpy.concatenate((self.tab_low.fwhm_sel, self.tab_high.fwhm_sel)))
    self.std_all_fwhm         = numpy.std(numpy.concatenate((self.tab_low.fwhm_sel, self.tab_high.fwhm_sel)))
    self.order_high_shift     = self.tab_high.order_raw + self.tab_low.max_order
    self.order_high_shift_sel = self.order_high_shift[self.tab_high.select_raw == 1]
    self.max_total_order      = numpy.nanmax(self.order_high_shift)
    self.max_fwhm             = max(self.tab_low.max_fwhm, self.tab_high.max_fwhm)
    self.x_sel_shift          = self.tab_high.x_sel + self.tab_low.det_ny
    self.x_raw_shift          = self.tab_high.x_raw + self.tab_low.det_ny
    self.y_sel_shift          = self.tab_high.ynew_sel + self.tab_low.det_nx
    self.y_raw_shift          = self.tab_high.ynew_raw + self.tab_low.det_nx

  def plotGridLowHiTextRight(self, grid):
    grid[0].text(0.9, 0.9, "RedHi", transform = grid[0].transAxes,
                 ha="right",va="top",size=13,bbox=dict(boxstyle="round",alpha=0.2))
    grid[1].text(0.9, 0.1, "RedLo", transform = grid[1].transAxes,
                 ha="right",size=13,bbox=dict(boxstyle="round",alpha=0.2))

  def plotLowHiTextBottom(self, subplot):
    subplot.text(0.9, 0.1, "RedHi", transform = subplot.transAxes,
                 ha="right", size=13,bbox=dict(boxstyle="round",alpha=0.2))
    subplot.text(0.1, 0.1, "RedLo", transform = subplot.transAxes,
                 ha="left",size=13,bbox=dict(boxstyle="round",alpha=0.2))

  def plotLowHiTextTop(self, subplot):
    subplot.text(0.9, 0.8, "RedHi", transform = subplot.transAxes,
                 ha="right", size=13,bbox=dict(boxstyle="round",alpha=0.2))
    subplot.text(0.1, 0.8, "RedLo", transform = subplot.transAxes,
                 ha="left",size=13,bbox=dict(boxstyle="round",alpha=0.2))

  def plotLowHiTextRight(self, subplot):
    subplot.text(0.9, 0.1, "RedLo", transform = subplot.transAxes,
                 ha="right",size=13,bbox=dict(boxstyle="round",alpha=0.2))
    subplot.text(0.9, 0.9, "RedHi", transform = subplot.transAxes,
                 ha="right",va="top",size=13,bbox=dict(boxstyle="round",alpha=0.2))

  def plotRESvsWAVE(self, subplot, title, tooltip) :
    self.plotLowHiTextTop(subplot)
    self.setLabels(subplot, 'Wavelength [Ang]', 'Wavelength Residual [Ang]')
    self.scatterPlotScatterSmall(subplot, self.tab_low.wavec_raw, self.tab_low.residual_raw, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.tab_low.wavec_sel, self.tab_low.residual_sel)
    self.scatterPlotScatterSmall(subplot, self.tab_high.wavec_raw, self.tab_high.residual_raw, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.tab_high.wavec_sel, self.tab_high.residual_sel)
    subplot.set_xlim(self.min_wavec, self.max_wavec)
    subplot.axhline(y=self.median_all_residual, color='black', lw=1.2)
    subplot.axhline(y=self.median_all_residual+self.std_all_residual, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_all_residual-self.std_all_residual, color='black', ls='-.', lw=1.2)
    subplot.axvline(linewidth=1.5, color='black', x=(self.tab_low.max_wavec + self.tab_high.min_wavec)/2.)
    self.finalSetup(subplot, title, tooltip)

  def plotRESvsORDER(self, subplot, title, tooltip) :
    self.plotLowHiTextTop(subplot)
    self.setLabels(subplot, 'Order', 'Wavelength Residual [Ang]')
    self.scatterPlotScatterSmall(subplot, self.tab_low.order_raw, self.tab_low.residual_raw, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.tab_low.order_sel, self.tab_low.residual_sel)
    self.scatterPlotScatterSmall(subplot, self.order_high_shift, self.tab_high.residual_raw, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.order_high_shift_sel, self.tab_high.residual_sel)
    subplot.set_xlim(0., self.max_total_order + 1.)
    subplot.axhline(y=self.median_all_residual, color='black', lw=1.2)
    subplot.axhline(y=self.median_all_residual+self.std_all_residual, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_all_residual-self.std_all_residual, color='black', ls='-.', lw=1.2)
    subplot.axvline(linewidth=1.5, color='black', x=self.tab_low.max_order + 0.5)
    self.finalSetup(subplot, title, tooltip)

  def plotFWHMvsWAVE(self, subplot, title, tooltip) :
    self.plotLowHiTextTop(subplot)
    self.setLabels(subplot, 'Wavelength [Ang]', 'Line FWHM [pix]')
    self.scatterPlotScatterSmall(subplot, self.tab_low.wavec_raw, self.tab_low.fwhm, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.tab_low.wavec_sel, self.tab_low.fwhm_sel)
    self.scatterPlotScatterSmall(subplot, self.tab_high.wavec_raw, self.tab_high.fwhm, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.tab_high.wavec_sel, self.tab_high.fwhm_sel)
    subplot.set_xlim(self.min_wavec, self.max_wavec)
    subplot.set_ylim(0., self.max_fwhm * 1.05)
    subplot.axhline(y=self.median_all_fwhm, color='black', lw=1.2)
    subplot.axhline(y=self.median_all_fwhm+self.std_all_fwhm, color='black', ls='-.', lw=1.2)
    subplot.axhline(y=self.median_all_fwhm-self.std_all_fwhm, color='black', ls='-.', lw=1.2)
    subplot.axvline(linewidth=1.5, color='black', x=(self.tab_low.max_wavec + self.tab_high.min_wavec)/2.)
    self.finalSetup(subplot, title, tooltip)

  def plotGridYvsX(self, grid, title, tooltip) :
    self.plotLowHiTextRight(grid)
    self.setLabels(grid[0], 'X [pix]', 'Y [pix]')
    self.scatterPlotScatterSmall(grid[0], self.tab_high.x_raw, self.tab_high.ynew_raw, color_pt='red')
    self.scatterPlotScatterSmall(grid[0], self.tab_high.x_sel, self.tab_high.ynew_sel, color_pt='blue')
    self.setLabels(grid[1], 'X [pix]', 'Y [pix]')
    self.scatterPlotScatterSmall(grid[1], self.tab_low.x_raw, self.tab_low.ynew_raw, color_pt='red')
    self.scatterPlotScatterSmall(grid[1], self.tab_low.x_sel, self.tab_low.ynew_sel, color_pt='blue')
    grid[0].set_xlim(0, self.tab_high.det_ny)
    grid[0].set_ylim(0, self.tab_high.det_nx)
    grid[1].set_xlim(0, self.tab_low.det_ny)
    grid[1].set_ylim(0, self.tab_low.det_nx)
    self.finalSetup(grid[0], title, tooltip)
    self.finalSetup(grid[1], "", tooltip)

  def plotYvsX(self, subplot, title, tooltip) :
    self.plotLowHiTextRight(subplot)
    self.setLabels(subplot, 'X [pix]', 'Y [pix]')
    self.scatterPlotScatterSmall(subplot, self.tab_high.x_raw, self.y_raw_shift, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.tab_high.x_sel, self.y_sel_shift, color_pt='blue')
    self.scatterPlotScatterSmall(subplot, self.tab_low.x_raw, self.tab_low.ynew_raw, color_pt='red')
    self.scatterPlotScatterSmall(subplot, self.tab_low.x_sel, self.tab_low.ynew_sel, color_pt='blue')
    subplot.set_xlim(0, self.tab_low.det_ny)
    subplot.set_ylim(0, self.tab_high.det_nx + self.tab_low.det_nx)
    subplot.axhline(linewidth=1.5, color='black', y=self.tab_low.det_nx)
    self.finalSetup(subplot, title, tooltip)

  def plotLinesText(self, subplot) :
     subplot.set_axis_off()
     text1 = 'No. of detected lines = %g'%(self.tab_low.nlintot + self.tab_high.nlintot)  
     subplot.text(0.05, 0.80, text1, color='#11557c', fontsize=15, ha='left', va='center', alpha=1.0)
     text2 = 'Initial no. of fitted lines = %g'%(self.tab_low.nlinsel + self.tab_high.nlinsel)
     subplot.text(0.05, 0.65, text2, color='#11557c', fontsize=15, ha='left', va='center', alpha=1.0)
     text3 = 'Final no. of fitted lines = %g'%(self.tab_low.nlinsol + self.tab_high.nlinsol) 
     subplot.text(0.05, 0.50, text3, color='#11557c', fontsize=15, ha='left', va='center', alpha=1.0)
     subplot.tooltip='Lines info'

