#!/usr/bin/env python3

'''
Created on 12 Apr 2014

@author: tessonec
'''

import spg.plot as spgp
import spg.base as spgb 
import spg.utils as spgu


import pandas as pd
import numpy as np
import math as m



import os.path
import re

import ipywidgets as ipyw
import itertools

import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.lines as mpll

from IPython.display import display



from spg import CONFIG_DIR

# from spg.utils import newline_msg, evaluate_string, load_configuration

from spg.plot import DataFrameIterator

class BaseDataLoader:

    def describe_variables(self):
        for v in self.variables:
            red_d = self.data[ v ].unique()
            print("%-16s: %4s values || %s -- %s"%(v, len(red_d), min(red_d), max(red_d) ))


    def describe_configuration(self):
        print("variables      : %s"%( ", ".join(self.variables ) ))
        print("  + separated  : %s"%(self.separated_vars))
        print("  + coalesced  : %s"%(self.coalesced_vars))
        print("  + independent: %s"%(self.independent_var))
        print("output columns : %s "%( ", ".join(self.output_columns) ))




    def setup_output_columns(self, oc):
        self.output_columns = oc
        self.data = self.full_dataframe[self.variables + self.output_columns]

    #
    # def setup_coalesced_vars(self, cv):
    #     all_vars = self.separated_vars + self.coalesced_vars
    #     for v in cv:
    #         if v in all_vars or v == self.independent_var:
    #             all_vars.remove(v)
    #     self.coalesced_vars = cv
    #     self.separated_vars = all_vars
    #
    #
    # def setup_separated_vars(self, sv):
    #     all_vars = self.separated_vars + self.coalesced_vars
    #     for v in sv:
    #         if v in all_vars or v == self.independent_var:
    #             all_vars.remove(v)
    #     self.coalesced_vars = all_vars
    #     self.separated_vars = sv
    #
    # def setup_independent_var(self, v):
    #     if v in self.coalesced_vars:
    #         self.coalesced_vars.remove(v)
    #         self.independent_var = v
    #     if v in self.separated_vars:
    #         self.separated_vars.remove(v)
    #         self.independent_var = v


    # def cycle_all(self, f_local):
    #
    #     ret = []
    #     for outer_df in DataFrameIterator( self.data, self.separated_vars ):
    #         for inner_df in DataFrameIterator( outer_df, self.coalesced_vars ):
    #
    #             r_loc = f_local(outer_df, inner_df )
    #             ret.append(r_loc)
    #     return ret

    def get_separated_values(self):

        ret = []
        for outer_df in DataFrameIterator(self.data, self.separated_vars):
            ret.append( [ outer_df[v].unique()[0] for v in self.separated_vars ] )
        return ret

    def get_coalesced_values(self):

        ret = []
        for inner_df in DataFrameIterator(self.data, self.coalesced_vars):
            ret.append( [ inner_df[v].unique()[0] for v in self.coalesced_vars ] )

        return ret


    #
    # def outer_inner(self, outer_df, inner_df):
    #     ouv = [ outer_df[v].unique()[0] for v in self.separated_vars ]
    #     iuv = [ inner_df[v].unique()[0] for v in self.coalesced_vars ]
    #
    #     return ouv, iuv


class CSVDataLoader(BaseDataLoader):
    def __init__(self, ds_filename, output_columns=[], settings={}):
        self.full_dataframe = pd.read_csv(ds_filename)

        self.output_columns = output_columns

        self.constants = {}
        self.variables = []
        for vn in list(self.full_dataframe.keys()):
            if vn in self.output_columns:
                continue
            all_values = self.full_dataframe[vn].unique()
            if len(all_values) > 1:
                self.variables.append(vn)
            else:
                self.constants[vn] = self.full_dataframe[vn].unique()[0]

        self.independent_var = self.variables[-1]

        try:
            self.coalesced_vars = [self.variables[-2]]
        except:
            self.coalesced_vars = []
        try:
            self.separated_vars = self.variables[:-2]
        except:
            self.separated_vars = []

        self.data = self.full_dataframe[self.variables + self.output_columns]

        self.settings = settings


        print("[__init__] constants: %s"% list(self.constants.keys()))
        print("[__init__] independent variables: %s"% self.variables)
        print("[__init__] output columns: %s"% self.output_columns)


    def configure_vars(self, separated_vars, coalesced_vars, independent_var=None, recalculate_output_columns=True):
        all_vars = separated_vars + coalesced_vars
        if independent_var is not None:
            all_vars.append(independent_var)

        # No unknown columns are present
        assert len(set(all_vars) - set(self.data)) == 0
        # All sets are disjoint
        assert independent_var not in separated_vars
        assert independent_var not in coalesced_vars
        assert len(set(separated_vars).intersection(coalesced_vars)) == 0

        self.separated_vars = separated_vars
        self.coalesced_vars = coalesced_vars
        self.independent_var = independent_var

        self.variables = all_vars

#        print self.variables
        if recalculate_output_columns:
            self.output_columns = [kn for kn in list(self.data.keys()) if kn not in self.variables]



class SPGDataLoader(BaseDataLoader):
    """
     A class that constructs the plots.
     It exposes
     self.parameter_file: spg file name
     self.base_name:
     self.datafile_name:

     self.simulation: the MultIterator that describes the simulation

     self.full_dataframe : ALl the data in the table
     self.variables
     self.constants
    """

    def __init__(self, exec_name, simulation_filename):

        self.simulation = spgb.MultIteratorParser(open(simulation_filename))
        self.simulation.command = exec_name

        self.simulation_filename = simulation_filename

        self.base_name, foo = os.path.splitext(self.simulation_filename)
#        self.datafile_name = "%s_%s.csv"%(self.base_name, table_name)
        self.datafile_name = "%s.csv"%(self.base_name)

        self.full_dataframe = pd.read_csv(self.datafile_name)

        settings_output = spgu.read_output_configuration( self.simulation.command )
        self.output_columns = [_ for _ in settings_output.keys()]

        self.constants = {}
        self.variables = []
        for vn in list(self.full_dataframe.keys()):
            if vn in self.output_columns:
                continue
            all_values = self.full_dataframe[vn].unique()
            if len(all_values) > 1:
                self.variables.append(vn)
            else:
                self.constants[vn] = self.full_dataframe[vn].unique()[0]

#        print spgu.load_configuration( "%s.input" % self.simulation.command.split(".")[0])


        try:
            self.settings = spgu.read_input_configuration(self.simulation.command)
        except:
            self.settings = spgu.SPGSettings()
            spgu.newline_msg( "INF", "no 'input' file found: %s"%self.simulation.command)
        self.settings.update(settings_output)
        try:
            self.coalesced_vars = [self.variables[-2]]
        except:
            self.coalesced_vars = []

        try:
            self.separated_vars = self.variables[:-2]
        except:
            self.separated_vars = []

        self.independent_var = self.variables[-1]

        x_axis_iter = self.simulation.data[ self.simulation.position_of(self.independent_var)]
        if self.independent_var not in self.settings:
            self.settings[ self.independent_var ] = spgu.SPGSettings()
        if x_axis_iter.type == "*":
            self.settings[self.independent_var]['scale'] = 'log'
            self.settings[self.independent_var]['lim'] =  (x_axis_iter.xmin, x_axis_iter.xmax)



        self.data = self.full_dataframe[self.variables + self.output_columns]

        print("[__init__] constants: %s"% list(self.constants.keys()))
        print("[__init__] independent variables:", self.separated_vars, self.coalesced_vars, self.independent_var)
        print("[__init__] output columns: %s"% self.output_columns)


    def configure_vars(self, separated_vars, coalesced_vars, independent_var = None):

        all_vars = separated_vars + coalesced_vars
        if independent_var is not None:
            all_vars.append( independent_var )

        # No unknown columns are present
        try:
            assert len(set(all_vars) - set(self.data.keys() )) == 0
        except:
            print("[configure_vars] ", set(all_vars) - set(self.data.keys() ), "not recognised as column name")
            return
        # All sets are disjoint
        try:
            assert independent_var not in separated_vars
        except:
            print("[configure_vars] ", independent_var, "is  in separated_vars")
            return

        try:
            assert independent_var not in coalesced_vars
        except:
            print("[configure_vars] ", independent_var, "is alse in coalesced_vars")
            return

        assert len(set(separated_vars).intersection(coalesced_vars)) == 0
        # No output column is used
        assert len(set(all_vars).intersection(self.output_columns)) == 0

        self.separated_vars = separated_vars
        self.coalesced_vars = coalesced_vars
        self.independent_var = independent_var

        self.variables = all_vars

#        self.output_columns = [kn for kn in self.data.keys() if kn not in self.variables]

        #self.__initialise_independent_elements()


#########################################################################################
#########################################################################################
class SPGInteractivePlotter:

        colors = ['black', 'blue', 'green', 'red', 'yellow', 'brown', 'grey', 'violet']
        markers = mpll.Line2D.filled_markers

        def __init__(self, splotter, xscale = 'linear', yscale = 'linear'):
            # self.splotter = splotter

            self.full_data = splotter.data

            self.separated_vars = splotter.separated_vars
            self.separated_values = splotter.get_separated_values()
            self.separated_selection = self.separated_values[0]

            self.coalesced_vars = splotter.coalesced_vars
            self.coalesced_values = splotter.get_coalesced_values()


            self.output_columns = splotter.output_columns
            self.dependent_var = self.output_columns[0]

            self.independent_var = splotter.independent_var
            self.figure, self.axis = plt.subplots(1, 1, figsize=(12, 6))

            self.settings = splotter.settings

            if len(self.separated_vars) == 0:
                vec_labels = ["all values"]
            else:
                vec_labels = [(", ".join(map(str, ou)), ou) for ou in self.separated_values]
#            print vec_labels
            self.dd_filter = ipyw.Dropdown(
                options=vec_labels)  # ,
            # description = "%s :"%(self.separated_vars) )
            self.dd_output = ipyw.Dropdown(
                options=self.output_columns)  # ,

            self.select_xscale = ipyw.Checkbox(
                value= xscale == "log",
                description='x log scale',
                icon='check'
            )

            self.select_yscale = ipyw.Checkbox(
                value= yscale == "log",
                description='y log scale',
                icon='check'
            )

            # description = "Output columns: ")

            self.xscale = xscale
            self.yscale = yscale

            self.dd_filter.observe(self.on_dd_filter_value_change, names='value')
            self.dd_output.observe(self.on_dd_output_value_change, names='value')

            self.select_yscale.observe(self.on_select_scale, names=['value', 'owner'])
            self.select_xscale.observe(self.on_select_scale, names=['value', 'owner'])

            self.__separated_value_change()
            display(
                ipyw.HBox([
                    ipyw.HBox([ipyw.Label("%s: " % (self.separated_vars)), self.dd_filter]),
                    ipyw.HBox([ipyw.Label("Output columns: "), self.dd_output])
                ]),
                ipyw.HBox([self.select_xscale, self.select_yscale])
            )
            self.draw()

        def __separated_value_change(self):
            query_str = " & ".join(["(%s==%s)" % i for i in zip(self.separated_vars, self.separated_values)])
            #print query_str
            if len(query_str) > 0:
                self.data = self.full_data.query(query_str)
            else:
                self.data = self.full_data

        def on_select_scale(self, change):

            mpl.rcParams['text.usetex'] = 'false'
            #     if not change.has_key('new'): return
            if change['owner'] == self.select_xscale:
                self.xscale = "log" if change['new'] else "linear"
                #print xscale
                self.axis.set_xscale(self.xscale)
            if change['owner'] == self.select_yscale:
                self.yscale = "log" if change['new'] else "linear"
                self.axis.set_yscale(self.yscale)
            self.__recalculate_lims()
            self.axis.figure.canvas.draw()

        def on_dd_filter_value_change(self, change):
            self.separated_values = change['new']
            self.__separated_value_change()
            self.redraw()

        def on_dd_output_value_change(self, change):
            self.dependent_var = change['new']

            self.redraw()

        def redraw(self):


            mpl.rcParams['text.usetex'] = 'false'
            color_it = itertools.cycle(self.colors)
            marker_it = itertools.cycle(self.markers)

            for ix, iv in enumerate(self.coalesced_values):
                query_inn_str = " & ".join(["(%s==%s)" % i for i in zip(self.coalesced_vars, iv)])
                if len(query_inn_str) > 0:
                    local_df = self.data.query(query_inn_str)
                else:
                    local_df = self.data

                self.axis.lines[ix].set_data(local_df[self.independent_var], local_df[self.dependent_var])

            self.axis.set_xlabel(self.independent_var)
            self.axis.set_ylabel(self.dependent_var)
            self.__recalculate_lims()


            self.axis.figure.canvas.draw()

        def draw(self):

            mpl.rcParams['text.usetex'] = 'false'
            color_it = itertools.cycle(self.colors)
            marker_it = itertools.cycle(self.markers)
            for iv in self.coalesced_values:
                query_inn_str = " & ".join(["(%s==%s)" % i for i in zip(self.coalesced_vars, iv)])

                if len(query_inn_str) > 0:
                    local_df = self.data.query(query_inn_str)
                else:
                    local_df = self.data
#                print query_inn_str
                self.axis.plot(local_df[self.independent_var], local_df[self.dependent_var],
                               linestyle='', marker=next(marker_it), color=next(color_it),
                               label=query_inn_str)

#            self.axis.set_ylim(min(self.data[self.dependent_var]), max(self.data[self.dependent_var]))
#            self.axis.set_xlim(min(self.data[self.independent_var]), max(self.data[self.independent_var]))
            self.axis.set_xlabel(self.independent_var)
            self.axis.set_ylabel(self.dependent_var)

            box = self.axis.get_position()
            self.axis.set_position([box.x0, box.y0, box.width * 0.8, box.height])
            self.axis.legend(loc='upper right' ) #, bbox_to_anchor=(1, 0.5))

            self.__recalculate_lims()

            self.axis.figure.canvas.draw()

        def savefig(self, filename, draw_legend = True):
            mpl_rcParams = mpl.rcParams.copy()

            spgp.init_mpl()
            mpl.rcParams['text.usetex'] = 'True'

            fig_out, axis_out = plt.subplots(1, 1, figsize=(8, 4))

            color_it = itertools.cycle(self.colors)
            marker_it = itertools.cycle(self.markers)
            for iv in self.coalesced_values:
                query_inn_str = " & ".join(["(%s==%s)" % i for i in zip(self.coalesced_vars, iv)])
                if len(query_inn_str) > 0:
                    local_df = self.data.query(query_inn_str)
                else:
                    local_df = self.data
                label_str = ", ".join(["%s=%s" % i for i in zip(self.coalesced_vars, iv)])
                axis_out.plot(local_df[self.independent_var], local_df[self.dependent_var],
                               linestyle='', marker=next(marker_it), color=next(color_it),
                               label=label_str.replace("_", " "))
           #     print label_str

            self.__recalculate_lims(axis_out)
            axis_out.tick_params()

            if "label" in self.settings[self.independent_var]:
                xlabel = self.settings[self.independent_var]["label"]
            else:
                xlabel = self.independent_var.replace("_"," ")

            if "label" in self.settings[self.dependent_var]:
                ylabel = self.settings[self.dependent_var]["label"]
            else:
                ylabel = self.dependent_var.replace("_"," ")

            # print xlabel, ylabel

            axis_out.set_xlabel(xlabel)
            axis_out.set_ylabel(ylabel)


            axis_out.set_xscale(self.xscale)
            axis_out.set_yscale(self.yscale)

        ###    axis_out.set_title(
        ###        ", ".join([" %s=%s".replace("_", " ") % i for i in zip(self.separated_vars, self.separated_values)]),
        ###        axis_font)
            title = ", ".join([" %s=%s" % i for i in zip(self.separated_vars, self.separated_values)])
            title = title.replace("_", " ")

            axis_out.set_title(title)

            box = axis_out.get_position()
            axis_out.set_position([box.x0, box.y0, box.width * 0.8, box.height])
            if draw_legend:
                axis_out.legend(loc='center left', bbox_to_anchor=(1, 0.5))

            axis_out.figure.canvas.draw()
            fig_out.savefig(filename, bbox_inches='tight',
                            transparent=True,
                            pad_inches=0)

            mpl.rcParams = mpl_rcParams

        def __recalculate_lims(self, axis_out = None):
            ydata = self.data[self.dependent_var]
            xdata = self.data[self.independent_var]
            if self.select_yscale.value:  # it is not log
                ydata = ydata[ydata > 1e-9]

#            print ydata

            ymin, ymax = 0.9*np.min(ydata), 1.1*np.max(ydata)
            if self.select_xscale.value:  # it is not log
                xdata = xdata[xdata > 1e-9]
            xmin, xmax = 0.9*np.min(xdata), 1.1*np.max(xdata)

            self.axis.set_xscale(self.xscale)
            self.axis.set_yscale(self.yscale)

            if axis_out:
                axis_out.set_ylim(ymin, ymax)
                axis_out.set_xlim(xmin, xmax)

            else:

                self.axis.set_ylim(ymin, ymax)
                self.axis.set_xlim(xmin, xmax)


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



class SPGInteractiveScalingPlotter:
    colors = ['black', 'blue', 'green', 'red', 'yellow', 'brown', 'grey', 'violet']
    markers = mpll.Line2D.filled_markers

    def __init__(self, splotter):
        self.full_data = splotter.data

        self.separated_values = splotter.get_separated_values()
        self.separated_vars = splotter.separated_vars
        self.separated_selection = self.separated_values[0]

        self.coalesced_values = splotter.get_coalesced_values()
        self.coalesced_vars = splotter.coalesced_vars

        self.output_columns = splotter.output_columns
        self.dependent_var = self.output_columns[0]

        self.independent_var = splotter.independent_var

        self.constants = splotter.constants
        self.variables = [ i for i in list(self.full_data.keys()) if i not in self.constants ]

        self.settings = splotter.settings

        if len(self.separated_vars) == 0:
            vec_labels = ["all values"]
        else:
            vec_labels = [(", ".join(map(str, ou)), ou) for ou in self.separated_values]

        self.dd_filter = ipyw.Dropdown(
            options=vec_labels)

        self.select_xscale = ipyw.Checkbox(
            value=False,
            description='x log scale',
            icon='check'
        )

        self.select_yscale = ipyw.Checkbox(
            value=False,
            description='y log scale',
            icon='check'
        )

        # description = "Output columns: ")

        self.dd_filter.observe(self.on_dd_filter_value_change, names='value')

        self.select_yscale.observe(self.on_select_scale, names=['value', 'owner'])
        self.select_xscale.observe(self.on_select_scale, names=['value', 'owner'])

        self.__separated_value_change()
        self.__scaling_parameters = {}
        self.scaling_values = {}
        self.__scaling_widgets = {}
        self.xscale = "linear"
        self.yscale = "linear"

    def interact(self):

        vec_row2 = []
        for sp in sorted(self.__scaling_parameters.keys()):
            (value, value_min, value_max, step) = self.__scaling_parameters[sp]
            vec_row2.append(ipyw.Label("%s: " % (sp)))
            new_slider = ipyw.FloatSlider(value=value, min=value_min, max=value_max, step=step)

            vec_row2.append(new_slider)
            self.__scaling_widgets[new_slider] = sp
            new_slider.observe(self.on_slider_change, names=['value'])

        display(
            ipyw.VBox([
                ipyw.HBox([ipyw.Label("%s: " % (self.separated_vars)), self.dd_filter, self.select_xscale,
                           self.select_yscale]),
                ipyw.HBox(vec_row2)
            ])
        )

        self.figure, self.axis = plt.subplots(1, 1, figsize=(8, 4))

        self.transform_data()
        self.draw()

    def __separated_value_change(self):

        query_str = " & ".join(["(%s==%s)" % i for i in zip(self.separated_vars, self.separated_values)])
        if len(query_str) > 0:
            self.data = self.full_data.query(query_str)
        else:
            self.data = self.full_data.copy()


        self.data = self.data[ sorted( set(self.variables + self.output_columns) )]



    def on_slider_change(self, change):
        par_name = self.__scaling_widgets[change['owner']]
        self.scaling_values[par_name] = change['new']
        self.transform_data()

        # print self.scaling_values, self.evaluate_string(self.x_transform), self.evaluate_string(self.y_transform)
        self.redraw()

    def on_select_scale(self, change):

        if change['owner'] == self.select_xscale:
            self.xscale = "log" if change['new'] else "linear"

            self.axis.set_xscale(self.xscale)
        if change['owner'] == self.select_yscale:
            self.yscale = "log" if change['new'] else "linear"
            self.axis.set_yscale(self.yscale)

        self.axis.figure.canvas.draw()

    def on_dd_filter_value_change(self, change):

        self.separated_values = change['new']
        self.__separated_value_change()
        self.redraw()

    def evaluate_string(self, to_evaluate):
        res = to_evaluate
        for i_var in self.constants:
            res = re.sub(r'\{%s\}' % i_var, str(self.constants[i_var]), res)

        for i_var in self.scaling_values:
            res = re.sub(r'\{%s\}' % i_var, str(self.scaling_values[i_var]), res)

        for i_var in self.variables:
            res = re.sub(r'\{%s\}' % i_var, "self.data['%s']" % i_var, res)



        return eval(res)

    def setup_transforms(self, xt, yt):
        rx = re.compile(r'\{([a-zA-Z0-9_]\w*)\}')
        vars_in_x_expr = rx.findall(xt)
        vars_in_y_expr = rx.findall(yt)
        possible_keys = list(self.constants.keys()) + self.variables + self.output_columns + list(self.__scaling_parameters.keys())
#        print possible_keys

        assert len(set(vars_in_x_expr) - set(possible_keys)) == 0
        assert len(set(vars_in_y_expr) - set(possible_keys)) == 0

        self.x_transform = xt
        self.y_transform = yt

    def add_scaling_parameter(self, parameter_name, value, value_min=0., value_max=None, step=0.01):
        if value_max is None:
            value_max = 2. * value

        self.__scaling_parameters[parameter_name] = (value, value_min, value_max, step)
        self.scaling_values[parameter_name] = value

    def transform_data(self):
        self.data_transformed = self.data.copy()
#        print self.x_transform, self.y_transform

        self.data_transformed['transformed_x'] = self.evaluate_string(self.x_transform)
        self.data_transformed['transformed_y'] = self.evaluate_string(self.y_transform)

    def redraw(self):
        color_it = itertools.cycle(self.colors)
        marker_it = itertools.cycle(self.markers)

        for ix, iv in enumerate(self.coalesced_values):
            query_inn_str = " & ".join(["(%s==%s)" % i for i in zip(self.coalesced_vars, iv)])
            if len(query_inn_str) > 0:
                local_df = self.data_transformed.query(query_inn_str)
            else:
                local_df = self.data_transformed

            self.axis.lines[ix].set_data(local_df['transformed_x'], local_df['transformed_y'])

        self.__recalculate_lims()

        self.axis.figure.canvas.draw()

    def draw(self):

        color_it = itertools.cycle(self.colors)
        marker_it = itertools.cycle(self.markers)
        for iv in self.coalesced_values:
            query_inn_str = " & ".join(["(%s==%s)" % i for i in zip(self.coalesced_vars, iv)])
            if len(query_inn_str) > 0:
                local_df = self.data_transformed.query(query_inn_str)
            else:
                local_df = self.data_transformed
            self.axis.plot(local_df['transformed_x'], local_df['transformed_y'],
                           linestyle='', marker=next(marker_it), color=next(color_it),
                           label=query_inn_str)

        self.__recalculate_lims()
        self.axis.set_xlabel('transformed_x')
        self.axis.set_ylabel('transformed_y')

        box = self.axis.get_position()
        self.axis.set_position([box.x0, box.y0, box.width * 0.8, box.height])
        self.axis.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        self.axis.figure.canvas.draw()


    def savefig(self, filename, xlabel, ylabel, draw_legend = True):

#        spgp.init_mpl()

        fig_out, axis_out = plt.subplots(1, 1, figsize=(12, 6))

        color_it = itertools.cycle(self.colors)
        marker_it = itertools.cycle(self.markers)
        for iv in self.coalesced_values:
            query_inn_str = " & ".join(["(%s==%s)" % i for i in zip(self.coalesced_vars, iv)])
            if len(query_inn_str) > 0:
                local_df = self.data_transformed.query(query_inn_str)
            else:
                local_df = self.data_transformed

            label_str = ", ".join(["%s=%s" % i for i in zip(self.coalesced_vars, iv)])
            axis_out.plot(local_df['transformed_x'], local_df['transformed_y'],
                           linestyle='', marker=next(marker_it), color=next(color_it),
                           label=label_str.replace("_"," "))

        self.__recalculate_lims(axis_out)
#        axis_out.tick_params(labelsize=axis_font["size"] - 6)

        axis_out.set_xlabel(xlabel)
        axis_out.set_ylabel(ylabel)

        axis_out.set_xscale(self.xscale)
        axis_out.set_yscale(self.yscale)
        title = ", ".join([" %s=%s" % i for i in zip(self.separated_vars, self.separated_values)])
        title = title.replace("_", " ")

        axis_out.set_title(title)

        box = axis_out.get_position()
        axis_out.set_position([box.x0, box.y0, box.width * 0.8, box.height])
        if draw_legend:
            axis_out.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        axis_out.figure.canvas.draw()
        fig_out.savefig( filename,  bbox_inches='tight',
               transparent=True,
               pad_inches=0 )


    def __recalculate_lims(self, axis_out = None):
        ydata = self.data_transformed['transformed_y']
        xdata = self.data_transformed['transformed_x']
        if self.select_yscale.value:  # it is not log
            ydata = ydata[ydata > 0]
        ymin, ymax = 0.9 * min(ydata), 1.1 * max(ydata)
        if self.select_xscale.value:  # it is not log
            xdata = xdata[xdata > 0]
        xmin, xmax = 0.9 * min(xdata), 1.1 * max(xdata)

        if axis_out:
            axis_out.set_ylim(ymin, ymax)
            axis_out.set_xlim(xmin, xmax)

        else:

            self.axis.set_ylim(ymin, ymax)
            self.axis.set_xlim(xmin, xmax)

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











#########################################################################################
#########################################################################################
#########################################################################################
#########################################################################################
#########################################################################################
#########################################################################################
# def parse_command_line():
#      from optparse import OptionParser
#
#      parser = OptionParser()
#
#      parser.add_option("--coalesced", type="string", action='store', dest="coalesced",
# 		        default = [],
#                         help = "comma separated list of coalesced variables")
#
#      parser.add_option("--separated", type="string", action='store', dest="separated",
# 		        default = [],
#                         help = "comma separated list of separated variables")
#
#      parser.add_option("--output", type="string", action='store', dest="output",
#                        default=[],
#                        help="output structure")
#
#      parser.add_option("--join", action='store_true', dest="join",
#                        default=[],
#                        help="join all y columns")
#
#      opts, args = parser.parse_args()
#      if len( opts.coalesced ) >0:
#          opts.coalesced = opts.coalesced.split(",")
#      if len( opts.separated ) >0:
#          opts.separated = opts.separated.split(",")
#      if len( opts.output ) >0:
#          opts.output = opts.output.split(",")
#      return  opts, args


#
#
#
# if __name__ == "__main__":
#     opts, args = parse_command_line()
#
#     for iarg in args:
#
#         plotter = SPGDataLoader(iarg)
#         if len(opts.coalesced) > 0:
#             plotter.setup_coalesced_vars( opts.coalesced )
#         if len(opts.separated) > 0:
#             plotter.setup_separated_vars( opts.separated )
#         if len(opts.output) > 0:
#             plotter.setup_output_columns( opts.output )
#
#         if not opts.join:
#             plotter.plot_all(spgp.SPGBasePlotter)
#         else:
#             plotter.plot_all_join_outputs(spgp.SPGBasePlotter)
