#!/usr/bin/python
# graphpaper - log-log graph paper

## Copyright 2005,2006 Grant Ingram, this program is distributed under the
## terms of the GNU General Public License
## Author e-mail: g.l.ingram@durham.ac.uk

##     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.

from optparse import OptionParser
import sys
import biggles
import math, Numeric
biggles.configure( 'printer', 'paper', 'a4' )

version_no = 1.1

def process_args(opt_list):
  
    usage = "usage: %prog [options] arg"
    parser = OptionParser(usage,version="%prog "+str(version_no))
    
    parser.add_option("-o", "--output", type="string", dest="filename",
                      default="graphpaper",
                      help="sets output filename root")
    parser.add_option("-l", "--labels",
                      action="store_false", dest="labels",default="True",
                      help="remove label from graph")
    parser.add_option("-x", "--xcycles", type="float", dest="xcycles",
                      default="1",
                      help="Number of x cycles to draw (max six)")
    parser.add_option("-y", "--ycycles", type="float", dest="ycycles",
                      default="1",
                      help="Number of y cycles to draw (max six)")
    parser.add_option("-a", "--xlinear",
                      action="store_true", dest="xlinear",
                      help="make x-axis linear" )
    parser.add_option("-b", "--ylinear",
                      action="store_true", dest="ylinear",
                      help="make y-axis linear" )
    parser.add_option("-v", "--verbose",
                      action="store_true", dest="verbose",
                      help="outputs lots of info")
    parser.add_option("-q", "--quiet",
                      action="store_false", dest="verbose",
                      help="operates silently (default)")
    parser.add_option("-c", "--license",
                      action="store_true", dest="license",
                      help="prints out copyright information")    
    (options, args) = parser.parse_args(opt_list)

    if options.verbose:
        print "graphpaper"+str(version_no)+"""
        Copyright (C) 2005,2006 Grant Ingram.  This program comes with
        ABSOLUTELY NO WARRANTY; for details use option --license.
        This is free software, and you are welcome to redistribute it
        under certain conditions.
        """
        print "Output file: %s.eps" % options.filename
        if options.labels: print "Labels to be printed"
        print "%d x cycles" % options.xcycles
        print "%d y cycles" % options.ycycles
     
    if options.license:
      print "graphpaper"+str(version_no)
      print """
      Copyright (C) 2005,2006 Grant Ingram

      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, 51 Franklin Street, Fifth Floor,Boston, MA
      02110-1301, USA.

      """
    return options

def drawlines(options,g):
    
    # Grey bits
    if options.xlinear:
        drawlinearlines(options,g,'x','grey')
    else:
        drawloglines(options,g,'x','grey')

    if options.ylinear:
        drawlinearlines(options,g,'y','grey')
    else:
        drawloglines(options,g,'y','grey')

    # Black bits
    if options.xlinear:
        drawlinearlines(options,g,'x','black')
    else:
        drawloglines(options,g,'x','black')

    if options.ylinear:
        drawlinearlines(options,g,'y','black')
    else:
        drawloglines(options,g,'y','black')

def drawlinearlines(options,g,axis,line_colour):

    l1 = range(0,600,1)
    for i in l1:
        if (axis == 'y' and line_colour == 'grey'):
            g.add ( biggles.LineY( i, color='grey'))
        if (axis == 'x' and line_colour == 'grey'):
            g.add ( biggles.LineX( i, color='grey'))

    l2 = range(0,600,10)
    for i in l2:
        if (axis == 'y' and line_colour == 'black'):
            g.add ( biggles.LineY( i, color='black'))
        if (axis == 'x' and line_colour == 'black'):
            g.add ( biggles.LineX( i, color='black'))

    
def drawloglines(options,g,axis,line_colour):
    lower = range(10,50,1)
    upper = range(50,100,2)
    l1 = lower + upper
    l1.append(100)

    # Just draw six cycles in Biggles and use the range to cap the
    # output later, ugl1....
    # Print grey lines before black to make sure the lines don't cross
    for i in range(len(l1)):
        if (l1[i] % 10 != 0):
            for k in  (1,10,100,1000,10000,100000):
                if (axis == 'y' and line_colour == 'grey'):
                    g.add ( biggles.LineY( (l1[i]*k), color='grey'))
                if (axis == 'x' and line_colour == 'grey'):
                    g.add ( biggles.LineX( (l1[i]*k), color='grey'))

    for i in range(len(l1)):
        if (l1[i] % 10 == 0):
            for k in (1,10,100,1000,10000,100000):
                if (axis == 'y' and line_colour == 'black'):
                    g.add ( biggles.LineY( (l1[i]*k), color='black'))
                if (axis == 'x' and line_colour == 'black'):
                    g.add ( biggles.LineX( (l1[i]*k), color='black'))
    

def drawlabels(options,g):
    # Labels from 1 to 9 so the students can add their own scales
    labels_string = ('1','2','3','4','5','6','7','8','9')
    xticklabels = []; yticklabels = [];

    if options.xlinear:
        g.x1.draw_ticklabels =  0
    elif options.labels:
        for i in range(int(options.xcycles)):
            xticklabels = xticklabels + range(10**(i+1),10**(i+2),10**(i+1))

            g.x1.ticks = xticklabels
            g.x1.ticklabels = labels_string*int(options.xcycles)
            g.x1.tickdir = 1
            g.x1.ticklabels_style["size"] = 1
            g.x1.draw_ticklabels =  1

    if options.ylinear:
        g.y1.draw_ticklabels =  0
    elif options.labels:
        for i in range(int(options.ycycles)):
            yticklabels = yticklabels + range(10**(i+1),10**(i+2),10**(i+1))
            
            g.y1.ticks = yticklabels
            g.y1.ticklabels = labels_string*int(options.ycycles)
            g.y1.tickdir = 1
            g.y1.ticklabels_style["size"] = 1
            g.y1.draw_ticklabels =  1
    
    g.frame.draw_ticks = 1
    g.frame.draw_subticks = 1
    g.frame.draw_grid = 0


    # Just in case you want to later....
    # g.y1.ticklabels_style["color"] = "red"
    # g.y1.ticklabels_style["textangle"] = -90


def plot_graph(options):
        
    g = biggles.FramedPlot()
    drawlines(options,g)
    drawlabels(options,g)
                
    # Graph settings
    if options.xlinear == True:
        g.xlog =  0
        g.xrange = (0,10*(options.xcycles*10))
    else:
        g.xlog =  1
        g.xrange = (10,10**(options.xcycles+1))
        
    if options.ylinear == True:
        g.ylog =  0
        g.yrange = (0,10*(options.ycycles*10))
    else:
        g.ylog =  1
        g.yrange = (10,10**(options.ycycles+1))
        
    g.aspect_ratio = options.ycycles / options.xcycles
    
    g.write_eps ("%s.eps" % options.filename )
    g.show()

def main():
    options = process_args(sys.argv[1:])
    plot_graph(options)
    
if __name__ == "__main__":
    main()
