#!/usr/bin/env python
"""
Creates a frame with a toolbar and graph for plotting
"""
import os
import pdb
import sys

import getopt
import optparse
import wx

from optparse import OptionParser

# Used to guarantee to use at least Wx2.8
# import wxversion
# wxversion.ensureMinimal('2.8')

import matplotlib

# 
#matplotlib.use('WXAgg')

from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg

from matplotlib.backends.backend_wx import _load_bitmap
from matplotlib.figure import Figure
from numpy.random import rand


#----------------------------------------------------------------------

class MyNavigationToolbar(NavigationToolbar2WxAgg):
    """
    Extend the default wx toolbar with your own event handlers
    """
    ON_CUSTOM = wx.NewId()
    def __init__(self, canvas, cankill):
        NavigationToolbar2WxAgg.__init__(self, canvas)

        # for simplicity I'm going to reuse a bitmap from wx, you'll
        # probably want to add your own.
        self.AddSimpleTool(self.ON_CUSTOM, _load_bitmap('stock_left.xpm'),
                           'Click me', 'Activate custom contol')
        wx.EVT_TOOL(self, self.ON_CUSTOM, self._on_custom)

#----------------------------------------------------------------------

    def _on_custom(self, evt):
        # add some text to the axes in a random location in axes (0,1)
        # coords) with a random color

        # get the axes
        ax = self.canvas.figure.axes[0]

        # generate a random location can color
        x,y = tuple(rand(2))
        rgb = tuple(rand(3))

        # add the text and draw
        ax.text(x, y, 'You clicked me',
                transform=ax.transAxes,
                color=rgb)
        self.canvas.draw()
        evt.Skip()

#*********************** Start G3Plot **********************************
class G3Plot(wx.Frame):

    """

    G3Plot creates a frame with a toolbar that holds a G-3 graph (2D y vs.
    x plot).  The graph allows multiple plots from multicolumn data 'x, y1,
    y2, ...'  given at successive x-values, given in one or more files.
    Wildcard file names are accepted.

    """
    def __init__(self, files, verbose=False,
                 title='(x,y) data', formt='k',
                 xlabel='X', ylabel='Y',
                 ymin=-0.1, ymax=0.05,
                 xmin=0.0, xmax=1.0,
                 pos=(50, 60), size=(640, 500)):
        
        wx.Frame.__init__(self, None, -1, "G3 Plot", pos, size)

        self.SetBackgroundColour(wx.NamedColor("WHITE"))

        self.panel = None
        self.dpi = None
        self.fig = None
        self.canvas = None
        self.axes = None
        self.toolbar = None

        # Just in case we need to have these values stored
        self.verbose = verbose
        self.title = title
        self.formt = formt
        self.xlabel = xlabel
        self.ylabel = ylabel
        self.ymin = ymin
        self.ymax = ymax
        self.xmin = xmin
        self.xmax = xmax

        if self.verbose:
           print "xmin, xmax, ymin, ymax: ", self.xmin, self.xmax, self.ymin, self.ymax

        self.subplot = []
        # Give the figure size in inches, and rez
        self.figure = Figure(figsize=(6.4,4.8), dpi=100)
        # Wait to create the subplot when AddSubplot() is called
#        self.axes = self.figure.add_subplot(1,1,1)
#        self.axes.set_title(self.title)
#        self.axes.set_xlabel(self.xlabel)
#        self.axes.set_ylabel(self.ylabel)

        self.PlotFiles(files) # create axes and plot all the data
        self.canvas = FigureCanvas(self, -1, self.figure)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND)
        # Capture the paint message
        wx.EVT_PAINT(self, self.OnPaint)

        self.toolbar = MyNavigationToolbar(self.canvas, True)
        self.toolbar.Realize()
        if wx.Platform == '__WXMAC__':
            # Mac platform (OSX 10.3, MacPython) does not seem to cope with
            # having a toolbar in a sizer. This work-around gets the buttons
            # back, but at the expense of having the toolbar at the top
            self.SetToolBar(self.toolbar)
        else:
            # On Windows platform, default window size is incorrect, so set
            # toolbar width to figure width.
            tw, th = self.toolbar.GetSizeTuple()
            fw, fh = self.canvas.GetSizeTuple()
            # By adding toolbar in sizer, we are able to put it at the bottom
            # of the frame - so appearance is closer to GTK version.
            # As noted above, doesn't work for Mac.
            self.toolbar.SetSize(wx.Size(fw, th))
            self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)

        # update the axes menu on the toolbar
        self.toolbar.update()
        self.SetSizer(self.sizer)
        self.Fit()

#----------------------------------------------------------------------

    def PlotFiles(self, file_list):
        """
        Loops through all files and makes a call to _PlotFile to plot
        each data set to the canvas.
        """
        self.plot_data = []

        if self.verbose:

            print "Processing %d files." % len(file_list)
            
        for f in file_list:

            this_file = os.path.abspath(f)

            if os.path.isfile(this_file):

                try:
                    
                    self._PlotFile(this_file)

                except Exception, e:

                    sys.exit("Error plotting files: %s" % e)
                
            else:

                print "File Error: '%s' is not found." % this_file
                
#----------------------------------------------------------------------

    def _PlotFile(self, f):
        """
        Parses the data in file f and plots all data columns

        """
        
        # Will end up being a list of lists. First item
        # of the list will be the time step, all following
        # items will be output data at each time step.
        plot_data = None
        
        if self.verbose:

            print "Plotting file: %s" % f
  

        this_file = os.path.abspath(f)

        if os.path.isfile(this_file):

            num_items = None
            
            fdata = open(this_file, 'r')

            for line in fdata.readlines():
                
                data = line.split()

                if plot_data is None:
                    
                    num_items = len(data)

                    plot_data = [[] for i in range(num_items)]

                for indx, d in enumerate(data):

                    if indx < num_items:
                        
                        try:
                        
                            plot_data[indx].append(d)

                        except IndexError, e:

                            print "Error processing data line for index %d" % indx

            # Now we plot all of the data we collected.
            t = plot_data[0]

            for indx, x in enumerate(plot_data[1:]):

                if self.verbose:

                    num_plots = len(plot_data[1:])
                        
                    print "\tPlotting data set %d of %d" % (indx+1, num_plots)
                self._AddSubplot(t, x)

        else:

            print "File Error: '%s' is not found." % this_file

#----------------------------------------------------------------------

    def _AddSubplot(self, t, x):
        """
        Create a subplot if one doesn't exist, and plot the (t, x) data.
        For historical reasons the x-axis variable is called 't' and the
        y-axis variable 'x'.  This should be changed!

        The add_subplot method of a Figure creates an Axes instance
        (111) == (1,1,1) --> row 1, col 1, Figure 1
       
        """
        
        if self.axes is None:
            self.axes = self.figure.add_subplot(1,1,1)
            # This is where Axes attributes are set
            self.axes.set_title(self.title)
            self.axes.set_xlabel(self.xlabel)
            self.axes.set_ylabel(self.ylabel)

        if self.xmin is None or self.xmax is None:
            self.axes.set_autoscalex_on(True)
        else:
            self.axes.set_autoscalex_on(False)
            self.axes.axis(xmin=self.xmin,xmax=self.xmax)

        if self.ymin is None or self.ymax is None:
            self.axes.set_autoscaley_on(True)
        else:
            self.axes.set_autoscaley_on(False)
            self.axes.axis(ymin=self.ymin,ymax=self.ymax)

        # With the new, or an exising Axes instance, plot the data          
        if self.formt is None:
            self.axes.plot(t, x)
        else:
            self.axes.plot(t, x, self.formt)

#----------------------------------------------------------------------


    def OnPaint(self, event):
        self.canvas.draw()
        event.Skip()

#-------------------- End of class G3Plot -----------------------------------

#----------- plotApp is the main wx.App to parse command line and plot -------

class plotApp(wx.App):
    def OnInit(self):
        version = 'gipyplot Ver. 2.0'
        filenames = []
        print_version = False
        verbose = False
        formt = None
        xlabel = 'X'
        ylabel = 'Y'
        title="GENESIS 3 Plot"

        cwd=os.getcwd()
        #os.chdir(cwd)

        description = """

gipyplot creates a frame with a toolbar that holds a G-3 graph (a 2D y vs x
plot).  The graph allows multiple plots from multicolumn data 'x, y1, y2,
...'  given at successive x-values, given in one or more files.  Wildcard
file names are accepted.

        """
        usage = "%s [OPTIONS] <files>"
        parser = OptionParser(usage=usage, version=version, description=description)
        parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
            default = False, help="show verbose output")
    
        parser.add_option("-V", "--show-version", action="store_true", dest="version_flag",
            default = False, help="print the program version")

        parser.add_option("-t", "--title", dest="title", type="string",
            default=title,  help="Title for the graph")

        parser.add_option("-f", "--format", dest="formt", type="string",
                      help="The plot format and color. e.g 'k' \
                      default: None cycles color for multiple plots")

        parser.add_option("-x", "--xlabel", dest="xlabel", type="string",
            default=xlabel, help="The label for the X axis")

        parser.add_option("-y", "--ylabel", dest="ylabel", type="string",
            default=ylabel, help="The label for the Y axis")

        rangegroup = optparse.OptionGroup(parser, "Axis Range Options: \n "
            ' Autoscaling is used unless both min and max values are given')

        rangegroup.add_option("--xmin", dest="xmin", type="float",
            default=None, help="Minimum value for the X axis")
        rangegroup.add_option("--xmax", dest="xmax", type="float",
            default=None, help="Maximum value for the X axis")
        rangegroup.add_option("--ymin", dest="ymin", type="float",
            default=None, help="Minimum value for the Y axis")
        rangegroup.add_option("--ymax", dest="ymax", type="float",
            default=None, help="Maximum value for the Y axis")
        parser.add_option_group(rangegroup)
        (options, args) = parser.parse_args()

        if options.version_flag is True:
            parser.print_version()
            return True

#        if len(args) < 1:
        
#             parser.error("Need at least one data file to read in")

        # collect options
        verbose = options.verbose
        if len(args) > 0:
            for a in args:
                if os.path.isfile( a ):
                    filenames.append(a)
                else:
                    parser.error("File '%s' doesn't exist" % a)

            formt = options.formt
            xlabel = options.xlabel
            ylabel = options.ylabel
            title = options.title

        # Now make the plot
        frame = G3Plot(files=filenames,
            verbose=verbose,
            xlabel=xlabel,
            ylabel=ylabel,
            title=title,
            formt=formt,
            xmin=options.xmin,
            xmax=options.xmax,
            ymin=options.ymin,
            ymax=options.ymax)

        frame.Show()
	self.SetTopWindow(frame)
	return True

#----------------------------------------------------------------------
            
if __name__ == '__main__':
    app = plotApp(0)
    app.MainLoop()
