<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Introduction to numpy, sympy and matplotlib
Kevin J. Walchko
created 5 July 2017
Matplotlib, NumPy and pysym are open-source add-on modules to Python that provide common mathematical and numerical routines in pre-compiled, fast functions. These are growing into highly mature packages that provide functionality that meets, or perhaps exceeds, that associated with common commercial software like MatLab. There is little that Matlab can do that python, numpy and other modules can't do too.
Matplotlib is a plotting library modeled after Matlab's plotting commands. We will use matplotlib to produce some graphs, but really use it heavily when we get to image processing. Again, we will delay the image specific functions until we get to that point. Here we are just going to learn the basics.
Objectives
Understand how to do very basic linear algebra in python
Understand how to do symbolic manipulation in python
Understand how to use matplotlib
How to insert LaTeX math symbols into plots
Understand how to plot engineering data in a Jupyter notebook
References
numpy tutorial
numpy for matlab users
sympy
sympy tutorials
matplotlib examples
matplotlib summary
matplotlib gallery of plots
LaTEX math symbols
Setup
Step1:  How Does the Jupyter Notebook Work?
Well, I probably should have covered this last lesson, but there already was a lot of material in that lesson. This one is shorter. When you run the command jupyter notebook from a bash terminal, it lauches a webserver and a web browser that shows the contents of the current directory. When you click on a jupyter file, lsn4.ipynb, the webserver reads the file and launches a kernel to run the notebook. Kernels are processes that run interactive code in a particular programming language and return output to the user. 
Jupyter supports many different languages, we are only using python. However, there are a bunch of kernels for other languages you can use if you want, like
Step2:  Now, generally we don't think about data types with python, but for math (and later working with images in OpenCV) we will. Note
Step3:  Remeber for later
Step4:  Documentation
If you don't understand what a function does, Google it or (like all python libraries) use the built in help system
Step5:  Matplotlib
This will allow us to plot sensor data, robot arm positions, a path through a map, images, etc. We will cover a few commands here, but revisit this later when we are doing image processing. The key commands are
<ASSISTANT_TASK:>
Python Code:
%matplotlib inline
from __future__ import division
from __future__ import print_function
import numpy as np  # common to rename numpy to np ... because programmers are lazy :)
from matplotlib import pyplot as plt
Explanation: Introduction to numpy, sympy and matplotlib
Kevin J. Walchko
created 5 July 2017
Matplotlib, NumPy and pysym are open-source add-on modules to Python that provide common mathematical and numerical routines in pre-compiled, fast functions. These are growing into highly mature packages that provide functionality that meets, or perhaps exceeds, that associated with common commercial software like MatLab. There is little that Matlab can do that python, numpy and other modules can't do too.
Matplotlib is a plotting library modeled after Matlab's plotting commands. We will use matplotlib to produce some graphs, but really use it heavily when we get to image processing. Again, we will delay the image specific functions until we get to that point. Here we are just going to learn the basics.
Objectives
Understand how to do very basic linear algebra in python
Understand how to do symbolic manipulation in python
Understand how to use matplotlib
How to insert LaTeX math symbols into plots
Understand how to plot engineering data in a Jupyter notebook
References
numpy tutorial
numpy for matlab users
sympy
sympy tutorials
matplotlib examples
matplotlib summary
matplotlib gallery of plots
LaTEX math symbols
Setup
End of explanation
# lets create an array
a = np.array([1,2,3])  # you could call this a 3 dimensional vector if you want
print(a)
# let's create a matrix with rows: [1,2,3], [4,5,6], and [6,7,8]
m = np.array([
    [1,2,3],
    [4,5,6],
    [6,7,8]
])
print('m =', m)
print('size', m.size)
print('shape', m.shape)
print('type', m.dtype)
Explanation: How Does the Jupyter Notebook Work?
Well, I probably should have covered this last lesson, but there already was a lot of material in that lesson. This one is shorter. When you run the command jupyter notebook from a bash terminal, it lauches a webserver and a web browser that shows the contents of the current directory. When you click on a jupyter file, lsn4.ipynb, the webserver reads the file and launches a kernel to run the notebook. Kernels are processes that run interactive code in a particular programming language and return output to the user. 
Jupyter supports many different languages, we are only using python. However, there are a bunch of kernels for other languages you can use if you want, like: Go, Ruby, Julia, R, etc.
How To Shut Things Down
Since you are launching both a web server and browser, you need to close the browser and shutdown the server. The server can be shutdown in one of two ways.
In the bash window, press contro-C
Or, just close the bash window
Either of these will work.
Numpy
First let's do some simple matrix/vector operations, since we will need this for our serial manipulator work. We will also use numpy later for OpenCV imagery work, but we will push that off to later when we need it. There are some specific things we need  to understand when working with images that would be best covered right before we need it.
End of explanation
# there are functions for special matrices
# zeros matrix
z = np.zeros((3,3))
print(z)
# Identity matrix
o = np.eye(3)
print(o)
# numpy even works in multiple dimension beyond standard MxN matrices we will do for this class.
# numpy actually lets you do n dimensional tensor math, and if you are Einstein, that is awesome!
np.zeros((3,4,5)) # go on and add some more dimentions like: (3,3,3,3)
# let's multiply them together
# NOTE: you can NOT do v = M * a
a = np.array([1,2,3])
v = m.dot(a)
print('m * a = m.dot(a) =', v)
# let's remember what v and m are
print('v = ', v, '\n')
print('m = ', m, '\n')
# let's access the number of each ... all zero based arrays
print('first v:', v[0])   # this is a vector (or array) so only 1 number given to get the value
print('first m:', m[0,0]) # this is a matrix, so you need 2 numbers to get the value 
# now let's do the last number
print('last v:', v[2])
print('last m:', m[2,2])
# remember: m[row, column]
print('\nm[0,1]', m[0,1])
print('m[2]', m[2], ' this gives me the entire row')
# let's get their dimensions
print('\nlen(a):', len(v))
print('v.shape:', v.shape)
print('m.shape:', m.shape)
Explanation: Now, generally we don't think about data types with python, but for math (and later working with images in OpenCV) we will. Note: you will probably have to prefix these with a namespace like np: np.uint8. This assumes you did the import numpy as np. 
| Data type | Description |
|---|:---|
| bool_ | Boolean (True or False) stored as a byte
| int_  | Default integer type (same as C long; normally either int64 or int32)
| intc  | Identical to C int (normally int32 or int64)
| intp  | Integer used for indexing (same as C ssize_t; normally either int32 or int64)
| int8  | Byte (-128 to 127)
| int16 | Integer (-32768 to 32767)
| int32 | Integer (-2147483648 to 2147483647)
| int64 | Integer (-9223372036854775808 to 9223372036854775807)
| uint8 | Unsigned integer (0 to 255)
| uint16 | Unsigned integer (0 to 65535)
| uint32 | Unsigned integer (0 to 4294967295)
| uint64 | Unsigned integer (0 to 18446744073709551615)
| float_ | Shorthand for float64.
| float16 | Half precision float: sign bit, 5 bits exponent, 10 bits mantissa
| float32 | Single precision float: sign bit, 8 bits exponent, 23 bits mantissa
| float64 | Double precision float: sign bit, 11 bits exponent, 52 bits mantissa
| complex_ | Shorthand for complex128.
| complex64 | Complex number, represented by two 32-bit floats (real and imaginary components)
| complex128 | Complex number, represented by two 64-bit floats (real and imaginary components)
Honestely, I generally only use np.float for math or np.unit8 for OpenCV. However, if you are calculating 3-phase power from ENGR 311, you might need np.complex, but I am not an AC power guy.
End of explanation
n = np.array([
    [1,0,0],
    [0,2,0],
    [0,0,3]
])
# inverse
nn = np.linalg.inv(n)
print('nn:\n', nn)
# calculate the determinate
nn = np.linalg.det(n)
print('det(n) =',nn)
# calculate the norm
nn = np.linalg.norm(n)
print('norm(n) =', nn)
# too much typing ... let's shorten it
# just becareful not to alias another python function ... python for example
# already has a built in abs (absolute) function, but so numpy
from numpy.linalg import inv, det, norm
# inverse
nn = inv(n)
print('nn', nn)
# calculate the determinate
nn = det(n)
print('det(n)', nn)
# calculate the norm
nn = norm(n)
print('norm(n)', nn)
# let's iterate over a matrix and print each value out
# remember, m.shape returns (rows, cols) tuple
m = np.array([
    [1,2,3],
    [4,5,6],
    [6,7,8]
])
# remember, shape gives rows, cols
mm, nn = m.shape
for i in range(mm):
    for j in range(nn):
        print('m[{}, {}] = {}'.format(i,j,m[i,j]))
print('') # add a blank line between the 2 prints
print(m)
# we can do it another way
# also, enumerate is a nice way to get a counter
for i, r in enumerate(m):
    for j, c in enumerate(r):
        print('m[{}, {}] = {}'.format(i,j,c))
Explanation: Remeber for later: OpenCV uses numpy to represent images. We access things by Matrix[row, col]. During image processing we have the same matrix interface, but we access a pixel by Image[height, width]. Here, height and row are the same while column and width are the same. This is backwards from how we usually think about images or screen resolutions, width x height like: 640 x 480.
End of explanation
from sympy import symbols, sin, cos, pi, simplify
# create some symbols and a symbolic equation
a, b = symbols('a b')
eqn = sin(a)*sin(a)+cos(a)**2+sin(b)/cos(b) + a
print(eqn)
# simplify the equations
# sin^2 + cos^2 = 1
# sin/cos = tan
e = simplify(eqn)
print(e)
# e is a numpy object, uncomment and see all of the amazing function (methods in CompSci lingo) that are associated with it
dir(e)
# substitute in some numbers for a and b
ee=e.subs([(b, 2.0), (a, 3.0)])
print(ee)
# this should give us the same answer
import math
3.0+math.tan(2.0)+1.0
Explanation: Documentation
If you don't understand what a function does, Google it or (like all python libraries) use the built in help system: help(numpy.inv). 
You can also find out what is availble in a  package by: dir(numpy). This would list everything in numpy. Or if you wanted to know what was in the linear algebra sub-package: dir(numpy.linalg).
Sympy
You can use sympy to manipulate equations symbolically. This will be useful later when we do forward/inverse kinematics.
get library and functions you need: from sympy import symbols, simplify
you may also need other things like trig functions: from sympy import sin, cos, pi
define your symbols()
build your equations
then run simplify()
finally substitute in values for variables if needed
End of explanation
# Prepare the data
x = np.linspace(0, 100, 10)  # linspace(start, stop, number_of_points)
y = np.linspace(0, 10, 10)
# Plot the data
plt.plot(x, y, label='linear')
# make it look nice
plt.grid(True)
plt.legend()
plt.title('title')
plt.ylabel('y $\Omega$')  # you can also include latex math symbols
plt.xlabel('x');  # note, if you don't put the ';' at the end, it prints 
                  # the object address. Not an issue, but it annoys me
from math import cos
# Prepare the data
x = np.linspace(0, 5, 100)  # linspace(start, stop, how_many_inbetween)
y1 = x                      # simple stupid y = x linear line
y2 = [n*cos(n) for n in y1] # remember this fancy way to use a for loop and create an array?
# similar to matlab
plt.plot(x,y1, 'r-', x,y2, 'b^')  # if you only put 1 array, plot assumes it is the y-axis
# make it look nice
plt.grid(True)
plt.title('title')
plt.ylabel('y1 and y2')
plt.xlabel('x');
# let's put more than one plot together ... every use subplot in Matlab?
plt.subplot(1,2,1)
plt.plot(x, label='linear')
plt.title('no grid')
plt.subplot(1,2,2)
plt.plot(x, label='linear')
plt.title('grid');
plt.grid(True)
Explanation: Matplotlib
This will allow us to plot sensor data, robot arm positions, a path through a map, images, etc. We will cover a few commands here, but revisit this later when we are doing image processing. The key commands are:
plt.plot()
plt.subplot()
plt.legend()
plt.title()
plt.ylabel() and plt.xlabel()
plt.grit()
plt.text()
There really isn't anything hard here, just examples of the plotting commands we will use the most. See the Matplotlib gallery for more examples of what is possible.
End of explanation
<END_TASK>