try:
  import numpy
  from pipeline_display import *
  from pipeline_product import *
  from reflex_plot_widgets import *
  from numpy.polynomial import Polynomial
  numpy.seterr(invalid='ignore')
  import giraf_der_snr
except ImportError:
  donothing=1


## Potentially interesting code here...
## http://python4esac.github.io/plotting/specnorm.html

## These are the GIRAFFE routines, hacked from the FORS ones,
## see below for the remaining FORS ones as examples...
class PlotableFlat(object) :
  def __init__(self, fits_flat):
    self.flat      = PipelineProduct(fits_flat)
    self.flatdisp  = ImageDisplay()
    self.loadFromFits()

  def loadFromFits(self) :
    #Reading the flat image
    self.flat.readImage()

  def plot(self, subplot, title, tooltip):
    self.flatdisp.setLabels('X [pix]', 'Y [pix]')
    self.flatdisp.display(subplot, title, tooltip, self.flat.image)

################################################################################

class PlotableFlatWithLOCcentroid(object) :
  def __init__(self, fits_flat, fits_ff_loccentroid):
    self.Xsectplot = -1
    self.flat      = PipelineProduct(fits_flat)
    self.ff_loccentroid = None
    if fits_ff_loccentroid is not None:
      self.ff_loccentroid = PipelineProduct(fits_ff_loccentroid)
    self.flatdisp  = ImageDisplay()
    self.Xsectplot = SpectrumDisplay()
    self.loadFromFits()
    
    self.NAXIS1=self.flat.all_hdu[0].header['NAXIS1']
    self.NAXIS2=self.flat.all_hdu[0].header['NAXIS2']
    # Params are available via the interactive_app.getCurrentParameterValue()
    # but I can't figure out how to access them from here... so I need to
    # make my own param dictionary...
    i=0
    pFound=True
    self.params = {}
    self.params[self.flat.all_hdu[0].header['HIERARCH ESO PRO REC1 PARAM%d NAME' %(i+1)]] = self.flat.all_hdu[0].header['HIERARCH ESO PRO REC1 PARAM%d VALUE' %(i+1)]
    while pFound :
        try :
            self.params[self.flat.all_hdu[0].header['HIERARCH ESO PRO REC1 PARAM%d NAME' %(i+1)]] = self.flat.all_hdu[0].header['HIERARCH ESO PRO REC1 PARAM%d VALUE' %(i+1)]
            i+=1
        except :
            pFound=False
    self.sloc_start=int(self.params['sloc-start'])
    self.setXsectRow(self.sloc_start)

  def loadFromFits(self) :
    #Reading the flat image
    self.flat.readImage()
    if self.ff_loccentroid is not None:
      self.ff_loccentroid.readImage()
      self.fibres = self.ff_loccentroid.image.shape[1]

      #Creating the points to plot based on the polynomail traces
      self.ypos_fibres = range(self.ff_loccentroid.image.shape[0])
      self.xpos_fibres = []
      for fibre in numpy.arange(self.fibres) :
        self.xpos_fibres.append(self.ff_loccentroid.all_hdu[0].data[:,fibre]+1.)


  def plot(self, subplot, title, tooltip):
    subplot.cla()
    self.flatdisp.setLabels('X [pix]', 'Y [pix]')
    self.flatdisp.display(subplot, title, tooltip, self.flat.image)
    lss=self.sloc_start
    if lss == -1 :
        lss=int(self.NAXIS2/2)
    if self.ff_loccentroid is not None:
      subplot.autoscale(enable=False)
      ## EVEN number subslits...
      for fibre in numpy.arange(self.fibres)[numpy.where(self.ff_loccentroid.all_hdu[1].data['SSN']%2 == 0)] :
        subplot.plot(self.xpos_fibres[fibre], self.ypos_fibres,
                     linestyle='solid',color='red')
      ## ODD number subslits...
      for fibre in numpy.arange(self.fibres)[numpy.where(self.ff_loccentroid.all_hdu[1].data['SSN']%2 == 1)] :
        subplot.plot(self.xpos_fibres[fibre], self.ypos_fibres,
                     linestyle='solid',color='yellow')
      ## Label the subslits...
      for SS in numpy.unique(self.ff_loccentroid.all_hdu[1].data['SSN']):
          subplot.annotate(str(SS), xy=(numpy.mean(numpy.array(self.xpos_fibres)[numpy.where(self.ff_loccentroid.all_hdu[1].data['SSN'] == SS)][:,lss]),self.NAXIS2),
              xycoords='data', horizontalalignment='center', verticalalignment='top')
      ## Label the fibres...
      j=0
      for i in numpy.unique(self.ff_loccentroid.all_hdu[1].data['FPS']):
        subplot.annotate(str(i), xy=(numpy.array(self.xpos_fibres)[j,lss],lss),
              xycoords='data', horizontalalignment='center', verticalalignment='bottom', rotation=90.)
        j+=1
    ## A horizontal line at the sloc-start value...
    subplot.plot([0,self.NAXIS1], [lss,lss],
                 linestyle='solid', color='black', linewidth=2)

  def setXsectRow(self, row):
      self.XsectRow=row
      if row == -1 :
          self.XsectRow=int(self.NAXIS2/2)

  def plotXsection(self, subplot, title, tooltip):
    subplot.cla()
    self.Xsectplot.setLabels('X [pix]', 'Y [ADU]')
    self.Xsectplot.display(subplot, title, tooltip, numpy.arange(self.NAXIS1)+1, self.flat.image[self.XsectRow,:])
    SSylab=subplot.get_ylim()[1]*0.99
    lss=self.sloc_start
    if lss == -1 :
        lss=int(self.NAXIS2/2)
    if self.ff_loccentroid is not None:
      subplot.autoscale(enable=False)
      ## EVEN number subslits...
      for fibre in numpy.arange(self.fibres)[numpy.where(self.ff_loccentroid.all_hdu[1].data['SSN']%2 == 0)] :
        subplot.axvline(self.xpos_fibres[fibre][self.XsectRow],
                     linestyle='solid',color='red')
      ## ODD number subslits...
      for fibre in numpy.arange(self.fibres)[numpy.where(self.ff_loccentroid.all_hdu[1].data['SSN']%2 == 1)] :
        subplot.axvline(self.xpos_fibres[fibre][self.XsectRow],
                     linestyle='solid',color='yellow')
      ## Label the subslits...
      for SS in numpy.unique(self.ff_loccentroid.all_hdu[1].data['SSN']):
          subplot.annotate(str(SS), xy=(numpy.mean(numpy.array(self.xpos_fibres)[numpy.where(self.ff_loccentroid.all_hdu[1].data['SSN'] == SS)][:,self.XsectRow]),SSylab),
              xycoords='data', horizontalalignment='center', verticalalignment='top')
      ## Label the fibres...
      j=0
      for i in numpy.unique(self.ff_loccentroid.all_hdu[1].data['FPS']):
        subplot.annotate(str(i), xy=(numpy.array(self.xpos_fibres)[j,self.XsectRow],0),
              xycoords='data', horizontalalignment='center', verticalalignment='bottom', rotation=90.)
        j+=1

################################################################################

class PlotableFlatWithPSFcentroid(object) :
  def __init__(self, fits_flat, fits_ff_psfcentroid):
    self.flat      = PipelineProduct(fits_flat)
    self.ff_psfcentroid = None
    if fits_ff_psfcentroid is not None:
      self.ff_psfcentroid = PipelineProduct(fits_ff_psfcentroid)
    self.flatdisp  = ImageDisplay()
    self.Xsectplot = SpectrumDisplay()
    self.loadFromFits()

    self.NAXIS1=self.flat.all_hdu[0].header['NAXIS1']
    self.NAXIS2=self.flat.all_hdu[0].header['NAXIS2']
    # Params are available via the interactive_app.getCurrentParameterValue()
    # but I can't figure out how to access them from here... so I need to
    # make my own param dictionary...
    i=0
    pFound=True
    self.params = {}
    self.params[self.flat.all_hdu[0].header['HIERARCH ESO PRO REC1 PARAM%d NAME' %(i+1)]] = self.flat.all_hdu[0].header['HIERARCH ESO PRO REC1 PARAM%d VALUE' %(i+1)]
    while pFound :
        try :
            self.params[self.flat.all_hdu[0].header['HIERARCH ESO PRO REC1 PARAM%d NAME' %(i+1)]] = self.flat.all_hdu[0].header['HIERARCH ESO PRO REC1 PARAM%d VALUE' %(i+1)]
            i+=1
        except :
            pFound=False
    self.sloc_start=int(self.params['sloc-start'])
    self.setXsectRow(self.sloc_start)

  def loadFromFits(self) :
    #Reading the flat image
    self.flat.readImage()
    if self.ff_psfcentroid is not None:
      self.ff_psfcentroid.readImage()
      self.fibres = self.ff_psfcentroid.image.shape[1]

      #Creating the points to plot based on the polynomail traces
      self.ypos_fibres = range(self.ff_psfcentroid.image.shape[0])
      self.xpos_fibres = []
      for fibre in range(self.fibres) :
        self.xpos_fibres.append(self.ff_psfcentroid.all_hdu[0].data[:,fibre]+1.)


  def plot(self, subplot, title, tooltip):
    subplot.cla()
    self.flatdisp.setLabels('X [pix]', 'Y [pix]')
    self.flatdisp.display(subplot, title, tooltip, self.flat.image)
    lss=self.sloc_start
    if lss == -1 :
        lss=int(self.NAXIS2/2)
    if self.ff_psfcentroid is not None:
      subplot.autoscale(enable=False)
      ## EVEN number subslits...
      for fibre in numpy.arange(self.fibres)[numpy.where(self.ff_psfcentroid.all_hdu[1].data['SSN']%2 == 0)] :
        subplot.plot(self.xpos_fibres[fibre], self.ypos_fibres,
                     linestyle='solid',color='blue')
      ## ODD number subslits...
      for fibre in numpy.arange(self.fibres)[numpy.where(self.ff_psfcentroid.all_hdu[1].data['SSN']%2 == 1)] :
        subplot.plot(self.xpos_fibres[fibre], self.ypos_fibres,
                     linestyle='solid',color='green')
      ## Label the subslits...
      for SS in numpy.unique(self.ff_psfcentroid.all_hdu[1].data['SSN']):
          subplot.annotate(str(SS), xy=(numpy.mean(numpy.array(self.xpos_fibres)[numpy.where(self.ff_psfcentroid.all_hdu[1].data['SSN'] == SS)][:,lss]),self.NAXIS2),
              xycoords='data', horizontalalignment='center', verticalalignment='top')
      ## Label the fibres...
      j=0
      for i in numpy.unique(self.ff_psfcentroid.all_hdu[1].data['FPS']):
        subplot.annotate(str(i), xy=(numpy.array(self.xpos_fibres)[j,lss],lss),
              xycoords='data', horizontalalignment='center', verticalalignment='bottom', rotation=90.)
        j+=1
    ## A horizontal line at the sloc-start value...
    subplot.plot([0,self.NAXIS1], [lss,lss],
                 linestyle='solid', color='black', linewidth=2)

  def setXsectRow(self, row):
      self.XsectRow=row
      if row == -1 :
          self.XsectRow=int(self.NAXIS2/2)

  def plotXsection(self, subplot, title, tooltip):
    subplot.cla()
    self.Xsectplot.setLabels('X [pix]', 'Y [ADU]')
    self.Xsectplot.display(subplot, title, tooltip, numpy.arange(self.NAXIS1)+1, self.flat.image[self.XsectRow,:])
    SSylab=subplot.get_ylim()[1]*0.99
    lss=self.sloc_start
    if lss == -1 :
        lss=int(self.NAXIS2/2)
    if self.ff_psfcentroid is not None:
      subplot.autoscale(enable=False)
      ## EVEN number subslits...
      for fibre in numpy.arange(self.fibres)[numpy.where(self.ff_psfcentroid.all_hdu[1].data['SSN']%2 == 0)] :
        subplot.axvline(self.xpos_fibres[fibre][self.XsectRow],
                     linestyle='solid',color='blue')
      ## ODD number subslits...
      for fibre in numpy.arange(self.fibres)[numpy.where(self.ff_psfcentroid.all_hdu[1].data['SSN']%2 == 1)] :
        subplot.axvline(self.xpos_fibres[fibre][self.XsectRow],
                     linestyle='solid',color='green')
      ## Label the subslits...
      for SS in numpy.unique(self.ff_psfcentroid.all_hdu[1].data['SSN']):
          subplot.annotate(str(SS), xy=(numpy.mean(numpy.array(self.xpos_fibres)[numpy.where(self.ff_psfcentroid.all_hdu[1].data['SSN'] == SS)][:,self.XsectRow]),SSylab),
              xycoords='data', horizontalalignment='center', verticalalignment='top')
      ## Label the fibres...
      j=0
      for i in numpy.unique(self.ff_psfcentroid.all_hdu[1].data['FPS']):
        subplot.annotate(str(i), xy=(numpy.array(self.xpos_fibres)[j,self.XsectRow],0),
              xycoords='data', horizontalalignment='center', verticalalignment='bottom', rotation=90.)
        j+=1


################################################################################

class PlotableARC_RBNSPECTRA(object) :
  def __init__(self, fits_arc_rbnspectra):
    self.rbnspectra      = PipelineProduct(fits_arc_rbnspectra)
    self.rbnspectradisp  = ImageDisplay()
    self.loadFromFits()

  def loadFromFits(self) :
    #Reading the flat image
    self.rbnspectra.readImage()

  def plot(self, subplot, title, tooltip):
    self.rbnspectradisp.setLabels('Fibre', 'Y [pix]')
    self.rbnspectradisp.display(subplot, title, tooltip, self.rbnspectra.image)



################################################################################

class PlotableSCI_RBNSPECTRA(object) :
  def __init__(self, fits_sci_rbnspectra):
    self.rbnspectra      = PipelineProduct(fits_sci_rbnspectra)
    self.rbnspectradisp  = ImageDisplay()
    self.loadFromFits()

  def loadFromFits(self) :
    #Reading the flat image
    self.rbnspectra.readImage()

  def plot(self, subplot, title, tooltip):
    self.rbnspectradisp.setLabels('Fibre', 'Y [pix]')
    self.rbnspectradisp.display(subplot, title, tooltip, self.rbnspectra.image)

  def getObjectInPosition(self, xpos) :
    return int(xpos)

################################################################################

class PlotableExtractedScience :
    def __init__(self, fits_extractedscience, fib_id=-1):
        self.fib_id = fib_id
        self.extractedscience  = PipelineProduct(fits_extractedscience)
        self.spectrumdisplay   = SpectrumDisplay()
        self.loadFromFits()

    def loadFromFits(self) :
        #Reading the flat image
        self.extractedscience.readImage()
        self.nobj   = self.extractedscience.image.shape[1]
        self.crpix  = self.extractedscience.readKeyword('CRPIX2', 0)
        self.crval  = self.extractedscience.readKeyword('CRVAL2', 0)
        self.cdelt  = self.extractedscience.readKeyword('CDELT2', 0)
        self.bunit  = self.extractedscience.readKeyword('BUNIT', 0)
        self.nwave  = self.extractedscience.image.shape[0]
        self.isARG  = self.extractedscience.readKeyword('HIERARCH ESO INS MODE', 0) == 'ARG'
        self.wave   = numpy.arange(1, self.nwave+1, 1)
        self.wave   = (self.wave - self.crpix) * self.cdelt + self.crval
        self.selectHighestSNR()
        self.setFluxSelected()

    def selectBrightest(self):
        if self.nobj == 1:
            self.fib_id = 1
        median = 0
        for obj in range(self.nobj) :
            new_median = numpy.median(self.extractedscience.image[:,obj])
            if new_median > median :
                median = new_median
                self.fib_id = obj + 1

    def selectHighestSNR(self):
        self.SNRarr=numpy.zeros(self.nobj)
        if self.nobj == 1:
            self.fib_id = 1
        for obj in range(self.nobj) :
            self.SNRarr[obj] = giraf_der_snr.DER_SNR(self.extractedscience.image[:,obj])
        if(self.fib_id == -1) : # Select Highest SNR
            self.fib_id = numpy.argsort(self.SNRarr)[-1]+1

    def setFluxSelected(self) :
        self.flux = self.extractedscience.image[:,self.fib_id-1]
        self.OBJECT = self.extractedscience.all_hdu[1].data['OBJECT'][self.fib_id-1]
        self.FPS = self.extractedscience.all_hdu[1].data['FPS'][self.fib_id-1]
        self.SSN = self.extractedscience.all_hdu[1].data['SSN'][self.fib_id-1]
        if self.isARG and not self.extractedscience.all_hdu[1].data['TYPE'][self.fib_id-1] == 'S' :
            self.OBJECT = self.extractedscience.all_hdu[0].header['HIERARCH ESO OBS TARG NAME']
        self.OBJECT_SNR = self.SNRarr[self.fib_id-1]

    def selectObject(self, fib_id):
        self.fib_id = fib_id
        self.setFluxSelected()

    def plot(self, subplot, title, tooltip):
        subplot.cla()
        wlUnit=""
        try :
            wlUnit=" ["+self.extractedscience.all_hdu[0].header['CUNIT2']+"]"
        except :
            pass
        ltitle='Rebinned spectrum of %s, S/N = %5.2f [FPS/SSN=%d/%d, col=%d]' %(self.OBJECT, self.OBJECT_SNR, self.FPS, self.SSN, self.fib_id)
        self.spectrumdisplay.setLabels('Wavelength'+wlUnit, 'Total Flux ['+self.bunit+']')
        self.spectrumdisplay.display(subplot, ltitle, tooltip, self.wave, self.flux,
                                     autolimits = True)

