Jupyter notebooks are made up of *cells*. Each cell is an *execution scope*, which means that it will be executed as a single block of instructions. Cells know about variables defined in previous cells (above them) but not any cells below them.

There are a few different types of cells:

- Markdown - used for text editing.
- Code - used for python code. When you execute a cell, it will be rendered (Markdown) or run through Python (Code). In fact, this cell was a Markdown cell and is then rendered using Markdown formatting.

- In
*edit mode*, keyboard commands will edit the contents of a cell.- A cell in edit mode has a green border.
- To switch to command mode, hit
.`Esc`

- In
*command mode*, keyboard commands will invoke shortcuts to take actions on a notebook.- A cell in command mode has a blue border.
- To switch to edit mode, hit
`Enter`

When in command mode, you can get a quick list of shortcut commands by typing ** h** or going to

`Help->Keyboard Shortcuts`

.When in command mode:

converts the cell to Markdown.`M`

converts the cell to Code.`Y`

- ⇪↩︎ (shift-enter) will evaluate the current cell and advance to the next cell.
- ⌃↩︎ (control-enter) will evaluate the current cell and keep focus there.

In a notebook, you can execute cells in any order, but typically you should execute them top-to-bottom. One of the nice things about cells is you can make many quick changes and re-evaluate a cell without needing to re-evaluate the entire notebook.

When in command mode, use the up/down arrows to move to cells above/below.

You will definitely want to learn a bit about Markdown. Fortunately, there is a link under `Help ➟ Markdown`

that will point you to some helpful resources.

Among some of the things you can do:

- Create
**sections**(`#`

),**subsections**(`##`

),**subsubsections**(`###`

) Create

**quote**blocks for text using a >My famous quote

**Display code**(that won't be executed) enclosed in a single tick ` for in-line code fragments or in a section of triple ticks ``` for separate displayed fragments:`def display_hello(): print('hello there!')`

- Insert
**LaTeX equations**by enclosing them in \$ for inline equations: $\alpha=\frac{\beta}{\gamma}$ and \$\$ for displayed equations: $$\vec{q}=-\lambda\nabla T$$

Note that not all LaTeX functionality is supported, however. More on LaTeX below.

- Insert
**images**:

For example, to insert`![Image](path-or-url)`

`picture.png`

from the`img`

directory adjacent to your notebook:`![Image](img/picture.png)`

- Insert
**hyperlinks**:`[displayed link text](http://www.my_url.com)`

Tables are formed using | to separate columns and `---`

to indicate header rows. For example,

```
Fruit | Vegetable
------- | ---------
Banana | Pea
Kiwi | Carrot
```

displays:

Fruit | Vegetable |
---|---|

Banana | Pea |

Kiwi | Carrot |

You can also alter the cell alignment in a table:

Right-aligned | Centered | Left-aligned |
---|---|---|

Use a trailing `:` for right-aligned. |
Use leading and trailing `:` for centered |
Use leading `:` for left-aligned |

Republican | Sane | Democrat |

If you want to display data from Python in tabular format, you may want to use the pandas library.

You can link to any section heading as follows:

` [link text to display](#heading-text)`

For example, here is a link to the executing cells section above.

The heading text is case sensitive, and spaces should be replaced with dashes.

In addition to Markdown, you can use any HTML commands in a notebook (at least in markdown mode).

LaTeX is a powerful typesetting language in its own right, but a subset of LaTeX is supported in Jupyter.
If you are learning LaTeX, here is a cheat sheet that you may find useful.
Built-in to Jupyter notebooks you will find support for inline equations by encapsulating them in single `$`

and for displayed equations by encapsulating them in double `$$`

LaTeX | Displayed |
---|---|

`\int_{\alpha}^{\beta} f(x) dx` |
$\int_{\alpha}^{\beta} f(x) dx$ |

`\frac{a}{b}` |
$\frac{a}{b}$ |

`\left( \frac{\partial f}{\partial x} \right)` |
$\left( \frac{\partial f}{\partial x}\right)$ |

`\vec{x}` |
$\vec{x}$ |

`\overline{abc}` |
$\overline{abc}$ |

`\int_a^b \underbrace{ \frac{1-x}{e^x}}_\mathrm{integrand} dx` |
$\int_a^b \underbrace{ \frac{1-x}{\exp(x^2)}}_\mathrm{integrand} dx$ |

`\mathsf{abcde}` |
$\mathsf{abcde}$ |

`\mathrm{abcde}` |
$\mathrm{abcde}$ |

`\boldsymbol{\alpha}` |
$\boldsymbol{\alpha}$ |

LaTeX macros can be used to create shortcuts to simplify frequently used, complex expressions. Put them at the top of your notebook in a markdown cell and they will be available in any later markdown cell. Here are some examples: $\def\del#1#2{\frac{\partial#1}{\partial#2}}$ $\def\d#1#2{\frac{\mathrm{d}#1}{\mathrm{d}#2}}$ $\newcommand{\Ls}{\mathcal{L}_\sigma}$ $\def\D#1#2{\frac{\mathrm{D}#1}{\mathrm{D}#2}}$

Macro definition | Example Usage | Example Output |
---|---|---|

`$\def\del#1#2{\frac{\partial#1}{\partial#2}}$` |
`$\del{f}{x}$` |
$\del{f}{x}$ |

`$\def\d#1#2{\frac{\mathrm{d}#1}{\mathrm{d}#2}}$` |
`$\d{f}{x}$` |
$\d{f}{x}$ |

`$\def\D#1#2{\frac{\mathrm{D}#1}{\mathrm{D}#2}}$` |
`$\D{f}{x}$` |
$\D{f}{x}$ |

`$\newcommand{\Ls}{\mathcal{L}_\sigma}$` |
`$\Ls$` |
$\Ls$ |

If you install the nbextensions package then you get support for a few additional LaTeX features, including:

- The
`equation`

environment for numbered equations:

To disable numbering, put`\begin{equation} a = b + c \label{eq:my special equation} \end{equation}`

`\nonumber`

after the equation. That is basically equivalent to putting the equation within double`$$`

:`$$ a = b + c $$`

- The
`align`

environment for aligned (and numbered) equations:

This produces equations aligned at the`\begin{align} a &\rightarrow b + c \\ c + d &\rightarrow e \\ \end{align}`

`&`

symbol. These equations are also numbered and can be labeled. - To cross-reference an equation, use the
`\ref{}`

command and supply the label you created:`\ref{eq:my special equation}`

There are a few techniques to use in debugging a notebook:

- Add
`print()`

statements in to see what your code is doing. - Use the
`%who`

or`whos`

cell magics. This will tell you what variables are currently defined. - Activate the
**variable inspector**plugin from the nbextensions package. This will give you a floating window containing a list of variables currently defined. It is very handy! - Sometimes it is helpful to restart the kernel (press the ⟳ button). This will clear all variables defined in the notebook and give you a clean slate.
- Add the
`%%debug`

cell magic to the beginning of a code cell. This will produce a terminal prompt at the bottom of the cell that allows you to enter python commands (like`print`

, etc.) without needing to rerun the whole cell.

One of the great things about Jupyter is the ability to intersperse documentation (Markdown) with code that runs interactively and generates results.

We'll next consider a few useful things that you will need to know to get started in Python

In python, a function is defined using the `def`

keyword. For example, we could create a function `add`

In [1]:

```
def add( x1, x2 ):
return x1+x2;
```

To use this, we can call our `add`

function:

In [2]:

```
add( 5, 6 )
```

Out[2]:

11

In [3]:

```
x = 3.14; y = 10;
z = add( x, y );
print(z)
```

13.14

Python has a vast number of libraries to simplify many tasks. Among those that you will probably use regularly:

- matplotlib provides very powerful (but sometimes challenging to use) plotting capabilities. A quick way to get started on a plot is to look at the matplotlib gallery to obtain code to generate a plot like the one you want to create.
- NumPy provides really powerful array handling capabilities like those in Matlab to allow you to create and manipulate arrays of data. It also has some algorithms that operate on the data. If you are a matlab user, here is a great guide showing you the equivalent numpy/python commands
- SciPy has a large number of algorithms such as interpolation, quadrature, optimization, ODE solvers, linear algebra tools, etc. There is some duplication between NumPy and SciPy.
- pandas provides a lot of data analysis tools.
- SymPy provides support for symbolic mathematics within Python.

The first step in using a library is to tell Python that you want it. This is done using the `import`

command:

In [4]:

```
# import the numpy library and alias it to np. numpy provides linspace like matlab.
# It also provides constants like pi and functions like sin, cos, etc.
import numpy as np
x = np.linspace( 0, 2*np.pi ) # create an array spaced from 0 to 2*pi.
y = np.sin(x)
z = y**2
```

Python has vast plotting capabilities that can be a bit overwhelming. Frequently, we simply want to plot basic 1D functions, which is accomplished through matplotlib's pyplot package:

In [5]:

```
# note that this cell uses results defined in the cell above (x and z)
import matplotlib.pyplot as plt
plt.plot( x, np.sin(x), 'k', label='SIN' ) # label is what the legend will show.
plt.plot( x, np.cos(x), 'r', label='COS' )
plt.plot( x, np.tan(x), 'g' ) # no label = no legend entry
plt.plot( x, z, label="sin^2" )
plt.title('sin, cos and tan') # title for the plot
plt.xlabel('x') # x-axis label
plt.ylabel('f(x)') # y-axis label
plt.legend() # show the legend
plt.grid() # show the grid on the plot
plt.ylim(-1,1) # set the y-axis range
plt.show() # render the plot
```

<Figure size 640x480 with 1 Axes>

You can get help on a Python command by typing it in a command cell and following it by `?`

then evaluating the cell:

In [6]:

```
import numpy as np
np.linspace?
```

Widgets are a set of simple tools that enable powerful interactivity in a notebook.

There are a few building blocks necessary:

- Create the widget(s). There are numerous widgets available including sliders, text boxes, drop-downs, radio buttons, etc.
- Create a function to call when the widget is modified.
- Use the
`interact`

function

In [7]:

```
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams
from ipywidgets import interact
import ipywidgets as widgets
# Create the function that we will call. It can take multiple arguments if necessary.
def plot_it(f,w):
t = np.linspace(0,2,500)
if w=='sin':
plt.plot( t, np.sin(np.pi*f*t) )
elif w=='cos':
plt.plot( t, np.cos(np.pi*f*t) )
elif w=='tan':
plt.plot( t, np.tan(np.pi*f*t) )
plt.ylim([-4,4])
plt.xlabel('t',fontsize=16)
plt.grid()
plt.show()
# create our widgets.
fwidget = widgets.IntSlider(min=0,
max=8,
value=1,
description='Frequency:')
which = widgets.Dropdown(options=['sin','cos','tan'],
value='sin',
description='Function:')
# hook up the widget with the function
interact( plot_it, f=fwidget, w=which )
```

Out[7]:

<function __main__.plot_it(f, w)>

There are many other things that you can do with widgets. See the documentation for more information.

In [8]:

```
%lsmagic
```

Out[8]:

Available line magics: %alias %alias_magic %autocall %automagic %autosave %bookmark %cat %cd %clear %colors %config %connect_info %cp %debug %dhist %dirs %doctest_mode %ed %edit %env %gui %hist %history %killbgscripts %ldir %less %lf %lk %ll %load %load_ext %loadpy %logoff %logon %logstart %logstate %logstop %ls %lsmagic %lx %macro %magic %man %matplotlib %mkdir %more %mv %notebook %page %pastebin %pdb %pdef %pdoc %pfile %pinfo %pinfo2 %popd %pprint %precision %profile %prun %psearch %psource %pushd %pwd %pycat %pylab %qtconsole %quickref %recall %rehashx %reload_ext %rep %rerun %reset %reset_selective %rm %rmdir %run %save %sc %set_env %store %sx %system %tb %time %timeit %unalias %unload_ext %who %who_ls %whos %xdel %xmode Available cell magics: %%! %%HTML %%SVG %%bash %%capture %%debug %%file %%html %%javascript %%js %%latex %%markdown %%perl %%prun %%pypy %%python %%python2 %%python3 %%ruby %%script %%sh %%svg %%sx %%system %%time %%timeit %%writefile Automagic is ON, % prefix IS NOT needed for line magics.

A line magic has a single `%`

prefix and applies to the given line of code only.
A cell magic has a double `%%`

prefix and applies to the whole cell below where it is found.

The `timeit`

magic is very useful when you want to time a section of code. For example:

In [9]:

```
import numpy as np
A = np.random.rand(50,50) # a large matrix
%timeit np.linalg.det(A) # calculate the determinant
```

28.8 µs ± 2.07 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

`timeit`

runs the cell/line several times to get a decent average time, and also reports the variability in the runtime.

The `who`

and `whos`

magics provide information about the variables defined in the notebook similar to their Matlab counterparts:

In [10]:

```
%whos
```