#!/usr/bin/env python3
#
# tutor.c
# Tony Richardson
#
# This program is intended to be used as a template for creating simple
# two-dimensional plotting programs which use the PLplot plotting
# library.  The program was written with an emphasis on trying to clearly
# illustrate how to use the PLplot library functions.
#
# This program reads data for M lines with N points each from an input
# data file and plots them on the same graph using different symbols.  It
# draws axes with labels and places a title at the top of the figure.  A
# legend is drawn to the right of the figure.  The input data file must
# have the following format:
#
#    x[1]     x[2]        x[3]        .     .     .     x[N]
#    y1[1]    y1[2]       y1[3]       .     .     .     y1[N]
#    y2[1]    y2[2]       y2[3]       .     .     .     y2[N]
#     .          .           .        .     .     .        .
#     .          .           .        .     .     .        .
#     .          .           .        .     .     .        .
#    yM[1]     yM[2]      yM[3]       .     .     .     yM[N]
#
# For example:
#
#       0       1       2       3       4
#       1.2     1.5     1.6     1.9     2.0
#       1.1     1.3     1.8     2.1     2.3
#       1.3     1.6     1.8     2.0     2.2
#
# (The first line contains the x-coordinates.  The succeeding M lines
# contain the y-coordinates of each of the M lines.)

import pl
import string
import sys

# You can select a different set of symbols to use when plotting the
# lines by changing the value of OFFSET.

OFFSET = 2

def main():

        # Here are the character strings that appear in the plot legend.

        legend = ["Aardvarks", "Gnus", "Llamas"]

        # ==============  Read in data from input file. =============

        # Parse and process command line arguments

        pl.ParseOpts(sys.argv, pl.PARSE_FULL)

        # First prompt the user for the input data file name

        filename = raw_input("Enter input data file name.\n")

        # and open the file.

        try:
                datafile = open(filename, "r")
        except:
                error("Error opening input file.")

        # Read in all the data.

        try:
                lines = datafile.readlines()
                datafile.close()

                x = []
                data = string.split(lines[0])
                for num in data:
                        x.append(string.atof(num))

                y = []
                del lines[0]
                for line in lines:
                        yy = []
                        data = string.split(line)
                        for num in data:
                                yy.append(string.atof(num))
                        y.append(yy)
        except:
                error("Error while reading data file.")

        # ==============  Graph the data. =============

        # Set graph to portrait orientation. (Default is landscape.)
        # (Portrait is usually desired for inclusion in TeX documents.)

        pl.sori(-1)

        # Initialize plplot

        pl.init()

        # We must call pladv() to advance to the first (and only) subpage.
        # You might want to use plenv() instead of the pladv(), plvpor(),
        # plwind() sequence.

        pl.adv(0)

        # Set up the viewport.  This is the window into which the data is
        # plotted.  The size of the window can be set with a call to
        # plvpor(), which sets the size in terms of normalized subpage
        # coordinates.  I want to plot the lines on the upper half of the
        # page and I want to leave room to the right of the figure for
        # labelling the lines. We must also leave room for the title and
        # labels with plvpor().  Normally a call to plvsta() can be used
        # instead.

        pl.vpor(0.15, 0.70, 0.5, 0.9)

        # We now need to define the size of the window in user coordinates.
        # To do this, we first need to determine the range of the data
        # values.

        xmin, xmax = min(x), max(x)
        ymin = ymax = y[0][0]
        for yy in y:
                yymin, yymax = min(yy), max(yy)
                if yymin < ymin:
                        ymin = yymin
                if yymax > ymax:
                        ymax = yymax

        # Now set the size of the window. Leave a small border around the
        # data.

        xdiff = (xmax - xmin) / 20.
        ydiff = (ymax - ymin) / 20.
        pl.wind(xmin - xdiff, xmax + xdiff, ymin - ydiff, ymax + ydiff)

        # Call plbox() to draw the axes (see the PLPLOT manual for
        # information about the option strings.)

        pl.box("bcnst", 0.0, 0, "bcnstv", 0.0, 0)

        # Label the axes and title the graph.  The string "#gm" plots the
        # Greek letter mu, all the Greek letters are available, see the
        # PLplot manual.

        pl.lab("Time (weeks)", "Height (#gmparsecs)", "Specimen Growth Rate")

        # Plot the data.  plpoin() draws a symbol at each point.  plline()
        # connects all the points.

        i = 0
        for yy in y:
                pl.poin(x, yy, i + OFFSET)
                pl.line(x, yy)
                i = i + 1

        # Draw legend to the right of the chart.  Things get a little messy
        # here.  You may want to remove this section if you don't want a
        # legend drawn.  First find length of longest string.

        leglen = 0
        for leg in legend:
                j = len(leg)
                if j > leglen:
                        leglen = j

        # Now build the string.  The string consists of an element from the
        # legend string array, padded with spaces, followed by one of the
        # symbols used in plpoin above.

        M = len(y)
        i = 0
        for leg in legend:
                if i >= M:
                        break

                text = leg
                j = len(text)
                # pad string with spaces
                if j < leglen:
                        k = leglen - j
                        text = text + ' ' * k

                # pad an extra space

                text = text + ' '

                # insert the ASCII value of the symbol plotted with plpoin()

                text = text + chr(i + OFFSET)

                # plot the string

                pl.mtex("rv", 1., 1. - float(i + 1) / (M + 1), 0., text)
                i = i + 1

        # Don't forget to call PLEND to finish off!

        pl.end()

def error(str):

        sys.stderr.write(str)
        sys.stderr.write('\n')
        sys.exit(1)

main()
