# -*- coding: utf-8 -*-
"""
Created on Fri Sep 25 14:09:12 2020

@author: jbobowsk
"""

# This tutorial will demonstrate how to create basic plots of data and
# functions.

# I will first import the module numpy and 'matplotlib' which we will use
# for ploting.  Matplotlib provides a MATLAB-like interface.  Many of the 
# options used for plotting in MATLAB are the same in Matplotlib.
import numpy as np
import matplotlib.pyplot as plt

# Here is a sample data set.
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
y = [1.02, 4.3, 8.6, 16, 22, 34, 45, 60.2, 80.1, 96, 125, 144]

# Here's the simplest possible plot of y vs x.
plt.plot(x, y)

# Of course, there are lots of options that can be used to better format
# the plot.  Before we get to those options, let's clarify an important
# point.  If we were to execute another plot command, it would add to
# the plot that was we created just a moment ago.  To tell Python that we
# want a new plot to be started, we must first use the command
# 'plt.figure()'
plt.figure()

# Now let's do some formating.  I will not attempt to show you all of the
# possible plot options -- you can check the online Python and matplotlib 
# documentation yourself.  I'll just show you some of the basics.

# You can make line plots or scatter plots.  One way to make a scatter plot
# is to specify the mark type after the x, y input.
plt.plot(x, y, 's')

# scatter plot point types:
# o - circle
# + - plus sign
# * - star
# . - point
# x - cross
# s - square
# d - diamond
# ^ - up-pointing triangle
# v - down-pointing triangle
# > - right-pointing triangle
# < - left-pointing triangle
# p - pentagram
# h - hexagram

# We can combine scatter plots and line plots be specifying both a mark style 
# and a line type.
# line plot line types
# -     solid line (default)
# --    dashed line
# :     dotted line
# -.    dash-dot line
plt.figure()
plt.plot(x, y, 's:')

# Of course, you can change the colours too.
# point/line colours
# y - yellow
# m - magenta
# c - cyan
# r - red
# g - green
# b - blue
# w - white
# k - black
plt.figure()
plt.plot(x, y, 'gs:')

# If you wanted to have your line and point to be different colours (for some
# reason), one way to it is by putting multiple plots into the same plt.plot()
# command.
plt.figure()
plt.plot(x, y, 'gs', x, y, 'c-.')

# We can use the 'linewidth' option to adjust the thickness of the line
# used to draw the point and we can use 'markersize' to adjust the overall
# size of the point.  I'll also include a 'fillstyle' option to make the point 
# hollow inside.
plt.figure()
plt.plot(x, y, 'ks', linewidth = 2.5, markersize = 12, fillstyle = 'none')

# The other fillstyle options available are:
# 'none'
# 'top'
# 'bottom'
# 'right'
# 'left'
# 'full'

# Here's another example of multiple plots in a single plot command.  
# Notice that I converted the y list to an array in the last two plots to 
# facilitate mathematical operations on the y-data.  Evidentally, it's possible
# to mix lists and arrays when plotting.

# I've also included x- and y-axis labels, a title, and a legend.  I don't know
# why, but for some reason, the way to control the legend font is not the same
# as it is for the axes labels and title. 
plt.figure()
plt.plot(x, y, 'ks', x, np.array(y)**1.1 + 20, 'r--', x, np.array(y)**1.2 + 40, 'g*')
plt.xlabel('x-axis label', fontsize = 18, fontname = 'Times', color = 'r')
plt.ylabel('y-axis label', fontsize = 18, fontname = 'Palatino', fontweight = 'bold')
plt.title('Title of the plot', fontsize = 22, fontname = 'Arial', style = 'italic')
plt.legend(('First', 'Second', 'Third'), shadow = 'true', loc = 'upper left',\
           fontsize = 16, prop={'family': 'Consolas', 'size': 16})

# We can format the tick labels too!
plt.figure()
plt.plot(x, y, 'ks', x, np.array(y)**1.1 + 20, 'r--', x, np.array(y)**1.2 + 40, 'g*')
plt.xlabel('x-axis label', fontsize = 18, fontname = 'Times', color = 'r')
plt.ylabel('y-axis label', fontsize = 18, fontname = 'Palatino', fontweight = 'bold')
plt.title('Title of the plot', fontsize = 22, fontname = 'Arial', style = 'italic')
plt.legend(('First', 'Second', 'Third'), shadow = 'true', loc = 'upper left',\
           fontsize = 16, prop={'family': 'Consolas', 'size': 16})
plt.xticks(fontsize = 26, fontname = 'Helvetica')
plt.yticks(fontsize = 16, fontname = 'Times', color = 'b')

# Finally, you can also set the ranges of the x- and y-axes.
# Use plt.axis((xmin, xmax, ymin, ymax)) to do this.
plt.figure()
plt.plot(x, y, 'ks', x, np.array(y)**1.1 + 20, 'r--', x, np.array(y)**1.2 + 40, 'g*')
plt.xlabel('x-axis label', fontsize = 18, fontname = 'Times', color = 'r')
plt.ylabel('y-axis label', fontsize = 18, fontname = 'Palatino', fontweight = 'bold')
plt.title('Title of the plot', fontsize = 22, fontname = 'Arial', style = 'italic')
plt.legend(('First', 'Second', 'Third'), shadow = 'true', loc = 'upper left',\
           fontsize = 16, prop={'family': 'Consolas', 'size': 16})
plt.xticks(fontsize = 26, fontname = 'Helvetica')
plt.yticks(fontsize = 16, fontname = 'Times', color = 'b')
plt.axis((0, 15, 0, 500))


# So far, everything has been done for a simple x vs y plot of data.
# In physics will often want to add error bars to our plots.  Below are
# some error bar values and a plot with error bars.  Instead of 'plot', we
# use 'errorbar'.  I also threw in another option to colour the inside of
# the marker pink.  Notice that, for some reason, we have to add the 'fmt' 
# (format) syntax when using errorbar().
dy = [.3, .3, .5, 2, 2, 2, 4, 4, 6, 10, 20, 20];
plt.figure()
plt.errorbar(x, y, yerr = dy, fmt = 'ko', markerfacecolor = 'pink',\
             fillstyle = 'top', capsize = 5, markersize= 8)
plt.xlabel('x-axis label', fontsize = 14, fontname = 'Times')
plt.ylabel('y-axis label', fontsize = 14, fontname = 'Times')
plt.axis((0, 13, 0, 170))

# I can't resist showing one more option.  Suppose you wanted to add text
# to you plot, maybe somewhere where there's a lot of white space.  You can
# use text(x-coordinate, y-coordinate, 'text') to do just that.
plt.figure()
plt.errorbar(x, y, yerr = dy, fmt = 'ko', markerfacecolor = 'pink',\
             fillstyle = 'top', capsize = 5, markersize= 8)
plt.xlabel('x-axis label', fontsize = 14, fontname = 'Times')
plt.ylabel('y-axis label', fontsize = 14, fontname = 'Times')
plt.axis((0, 13, 0, 170))
plt.text(2, 125, 'some text', fontsize = 18,fontname = 'Times')

# What if the text you wanted to add is some complicated symbollic
# expression?  Those of you that a familiar with entering in equations in
# LaTeX will love this.  Python has a LaTeX interpreter.  See the last line
# in the block of code below to see how to use it.  Note that you can use
# the LaTaX interpreter in axis labels and plot titles too.  The 'r' for the $..$
# is necessary.
plt.figure()
plt.errorbar(x, y, yerr = dy, fmt = 'ko', markerfacecolor = 'pink',\
             fillstyle = 'top', capsize = 5, markersize= 8)
plt.xlabel('x-axis label', fontsize = 14, fontname = 'Times')
plt.ylabel('y-axis label', fontsize = 14, fontname = 'Times')
plt.axis((0, 13, 0, 170))
plt.text(2, 125, r'$p_n(\mathbf{k})=\frac{e^{-n\hbar\omega(k)/k_\mathrm{B}T}}{Z(\mathbf{k})}$',\
         fontsize = 18)

# One thing that matplotlib does very nicely is export figures to a variety
# of file formats.  Here, for example, are png and jpg exports. 
plt.savefig('test_plot.png', format='png')
plt.savefig('test_plot.jpg', format='jpg')

# I generaly don't recommend using png or jpg for figure files.  THey look 
# after zooming in just a little bit.  It is far better to use vector graphics.
# I always cringe when I see posters around the campus with low-resolution
# figures that have been blown up and look blurry as hell.  I use Inkscape 
# to create figures with vector graphics.  Below is a svg, pdf, and eps export
# of the last plot created.  The eps files are espcially useful for including
# in LaTeX documents.
plt.savefig('test_plot.svg', format='svg')
plt.savefig('test_plot.pdf', format='pdf')
plt.savefig('test_plot.eps', format='eps')

# Note that the image files displayed in the html output of this script
# are png files.  They will note look good if you zoom in.  I have included
# copies of the svg, pdf, and eps files generated on the Python tutorial
#website.  You can compare the quality of these images with the corresponding 
# png and jpg files (also posted on the website).