# ========================================================================================================
# This file is part of Reflex
# Copyright (C) 2010 European Southern Observatory
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

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')
except ImportError:
  donothing=1


class giSpectrumDisplay(Plot):

    """This class allows to plot a spectrum.
    The basic usage is as follows:
    specdsp = giSpectrumDisplay()
    specdsp.display(subplot, title, tooltip, wave, flux)
    where wave is the array with the wavelengths and flux contains the fluxes.
    Do not reuse an object of this class for different plots."""

    def __init__(self):
        self.x_label = None
        self.wave_lim = None
        self.flux_lim = None

    def setLabels(self, x_label, y_label):
        """This method sets the labels to use for the X and Y axes. It should be
         called before the display method()"""
        self.x_label = x_label
        self.y_label = y_label

    def display(self, subplot, title, tooltip, wave,
                flux, errorflux=None, autolimits=False, color='blue'):
        """This method is the main one, as it actually specifies what to plot.
        The subplot argument contains a subplot created with
        matplotlib.figure.add_subplot() method
        The tooltip will appear when hovering the mouse over the plot.
        wave is the array with the wavelengths and flux contains the fluxes. They
        must have the same length. If errorflux is provided, then the error bars
        will be plotted accordingly.
        If autolimits is set to True, then an algorithm that can choose the best
        axes limits is applied. Otherwise, the axes will span to cover the minimum
        and maximum of the wave and fluxes array values or the last applied
        limits, if any.
        """
        flux_1sigma_below = None
        flux_1sigma_above = None
        xlabelText = None
        ylabelText = None
        errorFill = None
        if self.x_label is not None:
            xlabelText=subplot.set_xlabel(self.x_label, style='italic')
            ylabelText=subplot.set_ylabel(self.y_label, style='italic')
        if errorflux is not None:
            if not errorflux == [] :
                flux_1sigma_below = flux - errorflux
                flux_1sigma_above = flux + errorflux
            else :
                flux_1sigma_below = []
                flux_1sigma_above = []
            errorFill = subplot.fill_between(wave, flux_1sigma_below, flux_1sigma_above,
                                 facecolor='b', alpha=0.30)
        if self.flux_lim is None or autolimits == True:
            self.__setFluxAutoLimits(
                wave, flux, flux_1sigma_below, flux_1sigma_above)

        line, = subplot.plot(wave, flux, color=color)
        if self.wave_lim is None:
            self.__setWaveAutoLimits(wave)
        subplot.set_xlim(self.wave_lim)
        subplot.set_ylim(self.flux_lim)
        #self.finalSetup(subplot, title, tooltip)
        #from esoreflex-2.9.0/esoreflex/python/pipeline_display.py
        subplot.grid(True)
        titleText = subplot.set_title(title, fontsize=12, fontweight='semibold')
        subplot.tooltip = tooltip

        return line, errorFill, titleText, xlabelText, ylabelText

    def overplot(self, subplot, wave, flux, errorflux=None, color='green'):
        """This method allows to over plot a second spectrum, but with
        all the subplot setup already created by a previous display call.
        The subplot argument contains a subplot created with
        matplotlib.figure.add_subplot() method
        """
        errorFill = None
        if errorflux is not None:
            if not errorflux == [] :
                flux_1sigma_below = flux - errorflux
                flux_1sigma_above = flux + errorflux
            else :
                flux_1sigma_below = []
                flux_1sigma_above = []
            errorFill = subplot.fill_between(wave, flux_1sigma_below, flux_1sigma_above,
                                 facecolor=color, alpha=0.30)

        line, = subplot.plot(wave, flux, color=color)
        return line, errorFill

    def setWaveLimits(self, wave_limits):
        """This method sets the limits in X axes
        """
        self.wave_lim = wave_limits

    def __setWaveAutoLimits(self, wave):
        """This method will set automatically the limits for X axis
        """
        self.wave_lim = wave[0], wave[len(wave)-1]

    def __setFluxAutoLimits(self, wave, flux,
                            flux_1sigma_below=None, flux_1sigma_above=None):
        """This method performs an optimal scaling of the axes. It is only used
        internally"""
        nwave = len(flux)
        minlimwave = int(nwave*0.25)
        maxlimwave = int(nwave*0.75)
        flux_plotmin = 0
        if flux_1sigma_above is None:
            flux_plotmax = 1.2 * numpy.nanmax(
                flux[minlimwave:maxlimwave])
        else:
            flux_plotmax = 1.2 * numpy.nanmax(
                flux_1sigma_above[minlimwave:maxlimwave])
        self.flux_lim = flux_plotmin, flux_plotmax
