Tutorial 01 - Introduction to Python and Jupyter

Basic concepts and features of Python, numeric and math-related functions and data types, Jupyter environment, numpy, scipy, matplotlib modules.

Jupyter

From the official website jupyter.org:

The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and narrative text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, data visualization, machine learning, and much more.

Keyboard shortcuts of the most frequent commands:

  • create cell above / below selected: A / B

  • delete selected cell: D + D

  • change cell to markdown: M

  • change cell to code: Y

  • execute cell: Ctrl + Enter (or Shift + Enter)

  • show keyboard shortcuts: H

Python

  • high-level, object-oriented, general purpose programming language

  • open source (free to use and distribute, including for commercial purposes)

  • interpreted (no need to compile the code)

  • simple-to-learn syntax and excellent readability

  • large community

  • numerous libraries for scientific computing

Variable assignment and basic operations

assign number \( 4 \) to variable \( x \) and print the value of \( x \):

x = 4
print(x) 

print the type of variable \( x \) using the type function:

type(x)

single-line comments:

# this is a single-line comment

multi-line comments:

"""
this is 
a multi-line
comment
"""

assign number \( 2 \) to variable \( a \), assign number \( 4 \) to variable \( b \), and print sum, difference, product, and quotient of both variables:

a = 2
b = 4 
print(a + b, a - b, a * b, a / b)

assign number \( 2 \) to variable \( c \) and print square-root of \( c \) and \( c \) to the power of \( 2 \) using the ** operator:

c = 2 
print(c**0.5, c**2) 

create a list \( l \) of \( 1 \), \( 2.0 \), \( 3 \), and \( c \) (lists can contain any type of variable) and print the content of \( l \):

l = [1, 2.0, 3, "c"]
print(l) 

Conditions

check if \( x \) is equal to \( 4 \), check if \( x \) is not equal to \( 3 \) using the operators == and !=:

print(x == 4, x != 3)

check if \( x \) is greater than \( 1 \) and less than \( 3 \), check if \( x \) is equal to \( 3 \) or \( 4 \) using the operators and and or:

print(x > 1 and x < 3, x == 3 or x == 4)

if the value of variable \( x \) is less than or equal to \( 3 \), print “x <= 3”, if the value of variable \( x \) is greater than \( 3 \) and less than \( 5 \), print “3 < x < 5”, else print “x >= 5” using the if, elif, and else statements (note that in Python the code blocks must be indented - both tabs and spaces are supported):

if x <= 3:
    print("x <= 3") 
elif x > 3 and x < 5: 
    print("3 < x < 5")
else: 
    print("x >= 5")

use the in operator to check if the list \( l \) contains character \( c \):

print("c" in l)

use the in and not operators to check if the number 4 is not in the list \( l \):

print(4 not in l)

Loops

print the sequence of numbers from 0 to 2 using the range function and for loop (note that the range function is zero based):

for i in range(3):
    print(i)

print the sequence of numbers from \( 3 \) to \( 5 \):

for i in range(3, 6):
    print(i)

iterate over a sequence given by list:

for x in [1,5,4]:
    print(x)

while loops repeat as long as a certain boolean condition is met (note that the else clause can be used in loops):

k = 10
while k > 5:
    print("k =", k)
    k = k - 1 # or k -= 1
else:
    print("k <= 5")

Functions

define a function that takes two numbers and returns their product using the def keyword:

def multiply(x, y):
    return x*y

print(multiply(2, 3))

generate an exception using the raise statement (exceptions are used to abort functions when some error condition occurs):

raise Exception("description of the error")

use the try and except statements to catch the error thrown by multiply function when multiplying two strings:

try:
    multiply("a", "b")
except Exception as e:
    print("Caught an exception: " + str(e))

redefine the multiply function using the lambda keyword:

z = lambda x, y: x*y

z(2, 3)

Further reading: https://docs.python.org/3/

Numpy

import the numpy module and bind the import to the local variable np (to avoid name collisions and shorten module name):

import numpy as np

print \( \sqrt{4} \), \( \left|-1 \right| \), \( \exp{(1)} \), \( \ln{(e)} \), \( \sin{(\pi)}\), and \( \cos{(\pi)} \) using the functions from numpy module:

print(np.sqrt(4), np.abs(-1), np.exp(1), np.log(np.e), np.sin(np.pi), np.cos(np.pi))

create a vector \( v \) of numbers from \( 1 \) to \( 9 \) using the array function:

v = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(v)

create a \( 3 \times 3 \) matrix \( \mathbb{M} \) of numbers from \( 1 \) to \( 9 \) using the array function:

M = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(M)

print the dimensions of the vector \( v \) and matrix \( \mathbb{M} \) using the shape function:

print(np.shape(v), np.shape(M))

print number of elements of the vector \( v \) and matrix \( \mathbb{M} \) using the size function:

print(np.size(v), np.size(M))

print the scalar product \( v \cdot v \) using the dot function (compare with the element-wise multiplication using the operator *):

print(np.dot(v, v)) # alternatively v @ v
print(v * v)

print the matrix product \( \mathbb{M} \cdot \mathbb{M} \) using the dot function (compare with the element-wise multiplication using the operator *):

print(np.dot(M, M))  # alternatively M @ M
print(M * M)

print the first, last, and the sixth element of vector \( v \):

print(v[0], v[-1], v[5])

print the first five, last four, and each second element of vector \( v \) using the numpy array indexing:

print(v[:5], v[5:], v[::2])

print the \( \mathbb{M}_{0, 0} \) element, the first row, and the second column of matrix \( \mathbb{M} \):

print(M[0, 0], M[0, :], M[:, 1])

create evenly spaced vector \( x \) of size \( 5 \) from \( -2 \) to \( 2 \) using the linspace function

x = np.linspace(-2, 2, 5)
print(x)

create evenly spaced vector \( x \) of size \( 5 \) from \( -2 \) to \( 2 \) using the linspace function and print the step size:

x, h = np.linspace(-2, 2, 5, retstep=True)
print(h)

create evenly spaced vector \( x \) from \( -2 \) to \( 2 \) with a step of size \( 1 \) using the arange function:

x = np.arange(-2, 2, 1.0)
print(x)

create a matrix from the vector \( x \) using the meshgrid function:

xx, yy = np.meshgrid(x, x)
print(xx[1,0], yy[1, 0])

create a vector of zeros of size \( 3 \) using the zeros function:

z = np.zeros(3)
print(z)

create a \( 3 \times 3\) matrix of zeros using the zeros function:

Z = np.zeros((3, 3))
print(Z)

create a \( 3 \times 3 \) matrix with ones on the diagonal and zeros elsewhere using the eye function:

D = np.eye(3)
print(D)

create a \( 3 \times 3 \) matrix filled with ones using the ones function:

O = np.ones((3, 3))
print(O)

create a \( 3 \times 3 \) matrix filled with random floating point numbers between \( 0 \) and \( 1 \) using the rand function:

R = np.random.rand(3, 3)
print(R)

create a \( 3 \times 3 \) matrix with the vector \( (1, 2, 3) \) on the diagonal using the diag function:

print(np.diag([1,2,3], 0))

extract the main diagonal, and the diagonals above and below the main diagonal from matrix \( \mathbb{M} \) using the diag function:

print(np.diag(M, 0), np.diag(M, 1), np.diag(M, -1))

set all elements of matrix \( \mathbb{M} \) below and above diagonal to zero using the triu and tril functions:

print(np.triu(M))
print(np.tril(M))

print minimum and maximum elements, index of minimum and maximum elements, and the sum of vector \( v \) using the min, max, argmin, argmax, and sum functions:

print(np.min(v), np.max(v), np.argmin(v), np.argmax(v), np.sum(v))

print even numbers of vector \( v \) and their indices using the where, argwhere, and mod functions:

even = np.where(np.mod(v, 2) == 0)
print(v[even])

indices = np.argwhere(np.mod(v, 2) == 0)
print(v[indices])

assign vector \( v \) to vector \( v_2 \) using the = operator (note that if you modify one in place, you’ll see the change through the other one too):

v2 = v
v2[0] = -1
print(v)
print(v2)

copy the vector \( v \) to vector \( v_3 \) using the copy function:

v3 = np.copy(v)
v3[0] = -2
print(v)
print(v3)

create vector \( v_4 \) by appending \( 0 \) to the end of vector \( v \) using the append function:

v4 = np.append(v, 0)
print(v4)

create vector \( v_5 \) by inserting \( -5 \) as a sixth element to vector \( v \) using the insert function:

v5 = np.insert(v, 5, -5)
print(v5)

create vector \( v_6 \) by concatenating vectors \( v_4 \) and \( v_5 \) using the concatenate function:

v6 = np.concatenate((v4, v5))
print(v6)

create polynomial \( p = x^3 + 2x^2 + 3x + 2 \) using the poly1d function:

p = np.poly1d([1, 2, 3, 2])
print(p)

Further reading: https://numpy.org/doc/stable/reference/

Scipy

import scientific constants from the scipy module and print \( \pi \), golden_ratio, and speed of light in vacuum:

from scipy.constants import pi, golden_ratio, c
print(pi, golden_ratio, c)

import various submodules from scipy that will be useful throughout the course:

import scipy.linalg # linear algebra
import scipy.interpolate # interpolation and curve fitting
import scipy.optimize # minima, maxima, root finding
import scipy.integrate # numerical integration and solving of ODEs

Further reading: https://docs.scipy.org/doc/scipy/reference/

Matplotlib

import pyplot submodule from matplotlib and bind the import to the local variable plt:

import matplotlib.pyplot as plt

Use the command below to show the plots inside the Jupyter notebook (starting with IPython 5.0 and matplotlib 2.0 you can avoid the use of IPython’s specific commands):

%matplotlib inline

plot \( \sin{(x)} \) and \( \cos{(x)} \) functions for \( x \in [0, 10] \) using the plot function:

x = np.linspace(0, 10, 100)

fig, ax = plt.subplots()
ax.plot(x, np.sin(x))
ax.plot(x, np.cos(x))
plt.show()

change the linestyles, axes labels, and add legend to the plot above:

fig, ax = plt.subplots()
ax.plot(x, np.sin(x), linestyle="--", color="red", label="y = sin(x)", linewidth=2)
ax.plot(x, np.cos(x), linestyle="-", color="blue", label="z = cos(x)", linewidth=1)
ax.set_xlabel("x")
ax.set_ylabel("y (x)")
ax.legend()
plt.show()

plot the functions \( y(x) = x \) and \( y(x) = x^2 \) for \( x \in [0, 10] \) and show the plots next to each other:

fig, ax = plt.subplots(nrows=1, ncols=2)

ax[0].plot(x, x, color="green")
ax[0].set_xlabel("x")
ax[0].set_ylabel("y")

ax[1].plot(x, x**2, color="blue")
ax[1].set_xlabel("x")
ax[1].set_ylabel("y")
    
fig.tight_layout()
plt.show()

change the size of the figure using the figsize parameter:

fig, ax = plt.subplots(figsize=(8,3))

ax.plot(x, x, color="red")
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_title("title");
plt.show()

save the figure above as “figure.png”:

fig.savefig("figure.png", dpi=100)

create a 2D plot of Gaussian function, \( f(x, y) = \exp{(-x^2 - y^2)} \), for \( x, y \in [-2, 2] \) using the pcolormesh function:

x = np.linspace(-2, 2, 100)
y = np.linspace(-2, 2, 100)
xx, yy = np.meshgrid(x, y)
function = np.exp(-xx**2 - yy**2)

fig, ax = plt.subplots()
img = ax.pcolormesh(x, y, function, cmap="jet", shading="gouraud")
ax.set_title("2D plot of Gaussian function")
ax.set_xlabel("x")
ax.set_ylabel("y")

cbar = plt.colorbar(img)
cbar.set_label(label=r"$ exp(-x^2 - y^2) $", fontsize=12)

plt.show()

create a contour plot of function \( f(x, y) = x^2 - 2 \sin(x + y) \) using the contour function and draw a mark at the coordinates \( (0, \ \pi \, / \, 2) \) using the scatter function:

function_2 = xx**2 - 2.0 * np.sin(xx + yy) 

fig, ax = plt.subplots(figsize=(4, 4))
contours = ax.contour(x, y, function_2, linestyles="--", colors="blue")
ax.scatter(0, np.pi / 2, marker="+", s=200, color="red")
ax.clabel(contours)
ax.set_title("contour plot")
ax.set_xlabel("x")
ax.set_ylabel("y")
plt.show()

Further reading: https://matplotlib.org/