Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions content/mooreslaw-tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,20 +289,23 @@ The style sheet replicates
```{code-cell}
transistor_count_predicted = np.exp(B) * np.exp(A * year)
transistor_Moores_law = Moores_law(year)

plt.style.use("fivethirtyeight")
plt.semilogy(year, transistor_count, "s", label="MOS transistor count")
plt.semilogy(year, transistor_count_predicted, label="linear regression")

fig, ax = plt.subplots()
ax.semilogy(year, transistor_count, "s", label="MOS transistor count")
ax.semilogy(year, transistor_count_predicted, label="linear regression")


plt.plot(year, transistor_Moores_law, label="Moore's Law")
plt.title(
ax.plot(year, transistor_Moores_law, label="Moore's Law")
ax.set_title(
"MOS transistor count per microprocessor\n"
+ "every two years \n"
+ "Transistor count was x{:.2f} higher".format(np.exp(A * 2))
)
plt.xlabel("year introduced")
plt.legend(loc="center left", bbox_to_anchor=(1, 0.5))
plt.ylabel("# of transistors\nper microprocessor")
ax.set_xlabel("year introduced")
ax.set_ylabel("# of transistors\nper microprocessor")
ax.legend(loc="center left", bbox_to_anchor=(1, 0.5))
```

_A scatter plot of MOS transistor count per microprocessor every two years with a red line for the ordinary least squares prediction and an orange line for Moore's law._
Expand Down Expand Up @@ -346,19 +349,20 @@ y = np.linspace(2016.5, 2017.5)
your_model2017 = np.exp(B) * np.exp(A * y)
Moore_Model2017 = Moores_law(y)

plt.plot(
fig, ax = plt.subplots()
ax.plot(
2017 * np.ones(np.sum(year == 2017)),
transistor_count2017,
"ro",
label="2017",
alpha=0.2,
)
plt.plot(2017, transistor_count2017.mean(), "g+", markersize=20, mew=6)
ax.plot(2017, transistor_count2017.mean(), "g+", markersize=20, mew=6)

plt.plot(y, your_model2017, label="Your prediction")
plt.plot(y, Moore_Model2017, label="Moores law")
plt.ylabel("# of transistors\nper microprocessor")
plt.legend()
ax.plot(y, your_model2017, label="Your prediction")
ax.plot(y, Moore_Model2017, label="Moores law")
ax.set_ylabel("# of transistors\nper microprocessor")
ax.legend()
```

The result is that your model is close to the mean, but Gordon
Expand Down
7 changes: 3 additions & 4 deletions content/tutorial-deep-learning-on-mnist.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ import matplotlib.pyplot as plt
# Take the 60,000th image (indexed at 59,999) from the training set,
# reshape from (784, ) to (28, 28) to have a valid shape for displaying purposes.
mnist_image = x_train[59999, :].reshape(28, 28)

fig, ax = plt.subplots()
# Set the color mapping to grayscale to have a black background.
plt.imshow(mnist_image, cmap="gray")
# Display the image.
plt.show()
ax.imshow(mnist_image, cmap="gray")
```

```{code-cell}
Expand Down Expand Up @@ -586,7 +586,6 @@ for ax, metrics, title in zip(
ax.set_title(title)
ax.set_xlabel("Epochs")
ax.legend()
plt.show()
```

_The training and testing error is shown above in the left and right
Expand Down
44 changes: 26 additions & 18 deletions content/tutorial-ma.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,11 @@ First of all, we can plot the whole set of data we have and see what it looks li
import matplotlib.pyplot as plt

selected_dates = [0, 3, 11, 13]
plt.plot(dates, nbcases.T, "--")
plt.xticks(selected_dates, dates[selected_dates])
plt.title("COVID-19 cumulative cases from Jan 21 to Feb 3 2020")

fig, ax = plt.subplots()
ax.plot(dates, nbcases.T, "--")
ax.set_xticks(selected_dates, dates[selected_dates])
ax.set_title("COVID-19 cumulative cases from Jan 21 to Feb 3 2020")
```

The graph has a strange shape from January 24th to February 1st. It would be interesting to know where this data comes from. If we look at the `locations` array we extracted from the `.csv` file, we can see that we have two columns, where the first would contain regions and the second would contain the name of the country. However, only the first few rows contain data for the the first column (province names in China). Following that, we only have country names. So it would make sense to group all the data from China into a single row. For this, we'll select from the `nbcases` array only the rows for which the second entry of the `locations` array corresponds to China. Next, we'll use the [numpy.sum](https://numpy.org/devdocs/reference/generated/numpy.sum.html#numpy.sum) function to sum all the selected rows (`axis=0`). Note also that row 35 corresponds to the total counts for the whole country for each date. Since we want to calculate the sum ourselves from the provinces data, we have to remove that row first from both `locations` and `nbcases`:
Expand Down Expand Up @@ -183,9 +185,10 @@ Let's try and see what the data looks like excluding the first row (data from th
closely:

```{code-cell}
plt.plot(dates, nbcases_ma[1:].T, "--")
plt.xticks(selected_dates, dates[selected_dates])
plt.title("COVID-19 cumulative cases from Jan 21 to Feb 3 2020")
fig, ax = plt.subplots()
ax.plot(dates, nbcases_ma[1:].T, "--")
ax.set_xticks(selected_dates, dates[selected_dates])
ax.set_title("COVID-19 cumulative cases from Jan 21 to Feb 3 2020")
```

Now that our data has been masked, let's try summing up all the cases in China:
Expand Down Expand Up @@ -232,9 +235,10 @@ china_total
We can replace the data with this information and plot a new graph, focusing on Mainland China:

```{code-cell}
plt.plot(dates, china_total.T, "--")
plt.xticks(selected_dates, dates[selected_dates])
plt.title("COVID-19 cumulative cases from Jan 21 to Feb 3 2020 - Mainland China")
fig, ax = plt.subplots()
ax.plot(dates, china_total.T, "--")
ax.set_xticks(selected_dates, dates[selected_dates])
ax.set_title("COVID-19 cumulative cases from Jan 21 to Feb 3 2020 - Mainland China")
```

It's clear that masked arrays are the right solution here. We cannot represent the missing data without mischaracterizing the evolution of the curve.
Expand Down Expand Up @@ -271,21 +275,25 @@ package to create a cubic polynomial model that fits the data as best as possibl
```{code-cell}
t = np.arange(len(china_total))
model = np.polynomial.Polynomial.fit(t[~china_total.mask], valid, deg=3)
plt.plot(t, china_total)
plt.plot(t, model(t), "--")

fig, ax = plt.subplots()
ax.plot(t, china_total)
ax.plot(t, model(t), "--")
```

This plot is not so readable since the lines seem to be over each other, so let's summarize in a more elaborate plot. We'll plot the real data when
available, and show the cubic fit for unavailable data, using this fit to compute an estimate to the observed number of cases on January 28th 2020, 7 days after the beginning of the records:

```{code-cell}
plt.plot(t, china_total)
plt.plot(t[china_total.mask], model(t)[china_total.mask], "--", color="orange")
plt.plot(7, model(7), "r*")
plt.xticks([0, 7, 13], dates[[0, 7, 13]])
plt.yticks([0, model(7), 10000, 17500])
plt.legend(["Mainland China", "Cubic estimate", "7 days after start"])
plt.title(
fig, ax = plt.subplots()
ax.plot(t, china_total)
ax.plot(t[china_total.mask], model(t)[china_total.mask], "--", color="orange")
ax.plot(7, model(7), "r*")

ax.set_xticks([0, 7, 13], dates[[0, 7, 13]])
ax.set_yticks([0, model(7), 10000, 17500])
ax.legend(["Mainland China", "Cubic estimate", "7 days after start"])
ax.set_title(
"COVID-19 cumulative cases from Jan 21 to Feb 3 2020 - Mainland China\n"
"Cubic estimate for 7 days after start"
)
Expand Down
6 changes: 2 additions & 4 deletions content/tutorial-plotting-fractals.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,7 @@ mesh = x + (1j * y)

output = divergence_rate(mesh)

fig = plt.figure(figsize=(5, 5))
ax = plt.axes()
fig, ax = plt.subplots(figsize=(5, 5))

ax.set_title('$f(z) = z^2 -1$')
ax.set_xlabel('Real axis')
Expand Down Expand Up @@ -273,8 +272,7 @@ We will also write a function that we will use to create our fractal plots:
```{code-cell} ipython3
def plot_fractal(fractal, title='Fractal', figsize=(6, 6), cmap='rainbow', extent=[-2, 2, -2, 2]):

plt.figure(figsize=figsize)
ax = plt.axes()
fig, ax = plt.subplots(figsize=figsize)

ax.set_title(f'${title}$')
ax.set_xlabel('Real axis')
Expand Down
8 changes: 2 additions & 6 deletions content/tutorial-static_equilibrium.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ d3.quiver(x, y, z, u, v, w, color="r", label="forceA")
u, v, w = forceB
d3.quiver(x, y, z, u, v, w, color="b", label="forceB")

plt.legend()
plt.show()
d3.legend()
```

There are two forces emanating from a single point. In order to simplify this problem, you can add them together to find the sum of forces. Note that both `forceA` and `forceB` are three-dimensional vectors, represented by NumPy as arrays with three components. Because NumPy is meant to simplify and optimize operations between vectors, you can easily compute the sum of these two vectors as follows:
Expand Down Expand Up @@ -129,8 +128,7 @@ d3.quiver(x, y, z, u, v, w, color="b", label="forceB")
u, v, w = forceC
d3.quiver(x, y, z, u, v, w, color="g", label="forceC")

plt.legend()
plt.show()
d3.legend()
```

However, the goal is equilibrium.
Expand Down Expand Up @@ -172,8 +170,6 @@ x, y, z = np.array([0, 0, 0])

u, v, w = forceA + forceB + R # add them all together for sum of forces
d3.quiver(x, y, z, u, v, w)

plt.show()
```

The empty graph signifies that there are no outlying forces. This denotes a system in equilibrium.
Expand Down
25 changes: 13 additions & 12 deletions content/tutorial-svd.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ import matplotlib.pyplot as plt
```

```{code-cell}
plt.imshow(img)
plt.show()
fig, ax = plt.subplots()
ax.imshow(img)
```

### Shape, axis and array properties
Expand Down Expand Up @@ -196,8 +196,8 @@ To see if this makes sense in our image, we should use a colormap from `matplotl
In our case, we are approximating the grayscale portion of the image, so we will use the colormap `gray`:

```{code-cell}
plt.imshow(img_gray, cmap="gray")
plt.show()
fig, ax = plt.subplots()
ax.imshow(img_gray, cmap="gray")
```

Now, applying the [linalg.svd](https://numpy.org/devdocs/reference/generated/numpy.linalg.svd.html#numpy.linalg.svd) function to this matrix, we obtain the following decomposition:
Expand Down Expand Up @@ -259,8 +259,8 @@ np.allclose(img_gray, U @ Sigma @ Vt)
To see if an approximation is reasonable, we can check the values in `s`:

```{code-cell}
plt.plot(s)
plt.show()
fig, ax = plt.subplots()
ax.plot(s)
```

In the graph, we can see that although we have 768 singular values in `s`, most of those (after the 150th entry or so) are pretty small. So it might make sense to use only the information related to the first (say, 50) *singular values* to build a more economical approximation to our image.
Expand All @@ -282,8 +282,8 @@ approx = U @ Sigma[:, :k] @ Vt[:k, :]
Note that we had to use only the first `k` rows of `Vt`, since all other rows would be multiplied by the zeros corresponding to the singular values we eliminated from this approximation.

```{code-cell}
plt.imshow(approx, cmap="gray")
plt.show()
fig, ax = plt.subplots()
ax.imshow(approx, cmap="gray")
```

Now, you can go ahead and repeat this experiment with other values of `k`, and each of your experiments should give you a slightly better (or worse) image depending on the value you choose.
Expand Down Expand Up @@ -362,8 +362,9 @@ Since `imshow` expects values in the range, we can use `clip` to excise the floa

```{code-cell}
reconstructed = np.clip(reconstructed, 0, 1)
plt.imshow(np.transpose(reconstructed, (1, 2, 0)))
plt.show()

fig, ax = plt.subplots()
ax.imshow(np.transpose(reconstructed, (1, 2, 0)))
```

```{note}
Expand Down Expand Up @@ -391,8 +392,8 @@ approx_img.shape
which is not the right shape for showing the image. Finally, reordering the axes back to our original shape of `(768, 1024, 3)`, we can see our approximation:

```{code-cell}
plt.imshow(np.transpose(np.clip(approx_img, 0, 1), (1, 2, 0)))
plt.show()
fig, ax = plt.subplots()
ax.imshow(np.transpose(np.clip(approx_img, 0, 1), (1, 2, 0)))
```

Even though the image is not as sharp, using a small number of `k` singular values (compared to the original set of 768 values), we can recover many of the distinguishing features from this image.
Expand Down
29 changes: 12 additions & 17 deletions content/tutorial-x-ray-image-processing.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ print(xray_image.dtype)
```{code-cell}
import matplotlib.pyplot as plt

plt.imshow(xray_image, cmap="gray")
plt.axis("off")
plt.show()
fig, ax = plt.subplots()
ax.imshow(xray_image, cmap="gray")
ax.set_axis_off()
```

## Combine images into a multidimensional array to demonstrate progression
Expand Down Expand Up @@ -240,7 +240,6 @@ axes[1].set_title("Laplacian-Gaussian (edges)")
axes[1].imshow(xray_image_laplace_gaussian, cmap="gray")
for i in axes:
i.axis("off")
plt.show()
```

### The Gaussian gradient magnitude method
Expand Down Expand Up @@ -273,7 +272,6 @@ axes[1].set_title("Gaussian gradient (edges)")
axes[1].imshow(x_ray_image_gaussian_gradient, cmap="gray")
for i in axes:
i.axis("off")
plt.show()
```

### The Sobel-Feldman operator (the Sobel filter)
Expand Down Expand Up @@ -338,7 +336,6 @@ axes[2].set_title("Sobel (edges) - CMRmap")
axes[2].imshow(xray_image_sobel, cmap="CMRmap")
for i in axes:
i.axis("off")
plt.show()
```

### The Canny filter
Expand Down Expand Up @@ -399,7 +396,6 @@ axes[3].set_title("Canny (edges) - terrain")
axes[3].imshow(xray_image_canny, cmap="terrain")
for i in axes:
i.axis("off")
plt.show()
```

## Apply masks to X-rays with `np.where()`
Expand Down Expand Up @@ -438,9 +434,9 @@ pixel_intensity_distribution = ndimage.histogram(
xray_image, min=np.min(xray_image), max=np.max(xray_image), bins=256
)

plt.plot(pixel_intensity_distribution)
plt.title("Pixel intensity distribution")
plt.show()
fig, ax = plt.subplots()
ax.plot(pixel_intensity_distribution)
ax.set_title("Pixel intensity distribution")
```

As the pixel intensity distribution suggests, there are many low (between around
Expand All @@ -455,19 +451,19 @@ a certain threshold:
# Return the original image if true, `0` otherwise
xray_image_mask_noisy = np.where(xray_image > 150, xray_image, 0)

plt.imshow(xray_image_mask_noisy, cmap="gray")
plt.axis("off")
plt.show()
fig, ax = plt.subplots()
ax.imshow(xray_image_mask_noisy, cmap="gray")
ax.set_axis_off()
```

```{code-cell}
# The threshold is "greater than 150"
# Return `1` if true, `0` otherwise
xray_image_mask_less_noisy = np.where(xray_image > 150, 1, 0)

plt.imshow(xray_image_mask_less_noisy, cmap="gray")
plt.axis("off")
plt.show()
fig, ax = plt.subplots()
ax.imshow(xray_image_mask_less_noisy, cmap="gray")
ax.set_axis_off()
```

## Compare the results
Expand Down Expand Up @@ -500,7 +496,6 @@ axes[8].set_title("Mask (> 150, less noisy)")
axes[8].imshow(xray_image_mask_less_noisy, cmap="gray")
for i in axes:
i.axis("off")
plt.show()
```

## Next steps
Expand Down