Skip to content
Snippets Groups Projects
Commit a7b27f98 authored by gsingh58's avatar gsingh58
Browse files

lec16 minor fix

parent 4bb6dd7e
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id:471a762b tags:
# Visualization 1
- Advanced visualization, example: https://trailsofwind.figures.cc/
- Custom visualization steps:
- draw "patches" (shapes) on the screen (what):
- lines
- polygons
- circle
- text
- location of the "patches" on the screen (where):
- X & Y co-ordinate
- "Coordinate Reference System (CRS)":
- takes some X & Y and maps it on to actual space on screen
- several CRS
%% Cell type:code id:5df39a4b-d55b-4ba0-ab78-bd06fac8047e tags:
``` python
# import statements
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import math
```
%% Cell type:markdown id:7fcd95b4 tags:
### Review: drawing a figure
- `fig, ax = plt.subplots(figsize=(<width>, <height>))`
### Drawing a circle
- Type `plt.` and then tab to see a list of `patches`.
- `plt.Circle((<X>, <Y>), <RADIUS>)`
- To see the cicle, we need to invoke either:
- `ax.add_patch(<circle object>)`
- `ax.add_artist(<circle object>)`
- this invocation needs to be in the same cell as the one that draws the figure
- Is there a difference between `ax.add_patch` and `ax.add_artist`?
- `ax.autoscale_view()`: automatically chose limits for the axes; typically works better with `ax.add_patch(...)`
%% Cell type:code id:152cd4b0-7334-491f-841d-c0bfe3fce3c9 tags:
``` python
fig, ax = plt.subplots(figsize=(6, 4))
# Let's draw a circle at (0.5, 0.5) of radius 0.3
c = plt.Circle((0.5, 0.5), 0.3)
# Add the circle to the AxesSubplot
ax.add_artist(c)
# ax.autoscale_view()
```
%% Output
<matplotlib.patches.Circle at 0x7f3598817c40>
%% Cell type:code id:e6b1fa0f tags:
``` python
fig, ax = plt.subplots(figsize=(6, 4))
# Let's draw a circle at (0.5, 0.5) of radius 0.3
c = plt.Circle((0.5, 0.5), 0.3)
# Add the circle to the AxesSubplot
ax.add_patch(c)
ax.autoscale_view()
```
%% Output
%% Cell type:markdown id:9918baa3 tags:
Type and MRO of circle object.
%% Cell type:code id:8a714acd-e33d-4fa0-9fdd-de8438e94418 tags:
``` python
type(c)
```
%% Output
matplotlib.patches.Circle
%% Cell type:code id:392e6b98 tags:
``` python
type(c).__mro__
```
%% Output
(matplotlib.patches.Circle,
matplotlib.patches.Ellipse,
matplotlib.patches.Patch,
matplotlib.artist.Artist,
object)
%% Cell type:markdown id:418cedd8 tags:
### Making the circle circular
1. Have same figure width and height
2. Aspect ratio
3. Transformers: let's us pick a Coordinate Reference System (CRS)
%% Cell type:code id:c6446c47 tags:
``` python
# Option 1: Have same figure width and height
fig, ax = plt.subplots(figsize=(4, 4))
c = plt.Circle((0.5, 0.5), 0.3)
ax.add_patch(c)
ax.autoscale_view()
```
%% Output
%% Cell type:markdown id:4bd1648d-55ce-4156-b94e-6b9a10db4da7 tags:
### Aspect Ratio
- `ax.set_aspect(<Y DIM>)`: how much space y axes takes with respect to x axes space
%% Cell type:code id:06b32774-26a2-4627-b363-f79eb2838d07 tags:
``` python
fig, ax = plt.subplots(figsize=(6, 4))
c = plt.Circle((0.5, 0.5), 0.3)
ax.add_artist(c)
# Set aspect for y-axis to 1
ax.set_aspect(1)
```
%% Output
%% Cell type:markdown id:1699cae2 tags:
What if we want x and y axes to have the same aspect ratio? That is we care more about the figure being square than about the circle being circular.
%% Cell type:code id:7fa11875-34ba-4550-8e8b-9a9f92e58a9a tags:
``` python
fig, ax = plt.subplots(figsize=(6,4))
# Set x axis limit to (0, 3)
ax.set_xlim(0, 3)
c = plt.Circle((0.5, 0.5), 0.3)
ax.add_artist(c)
# Set aspect for y-axis to 3
ax.set_aspect(3)
```
%% Output
%% Cell type:markdown id:c2429f83-1603-4aaf-b767-a60969fc20d7 tags:
### Transformers: let us pick a Coordinate Reference System (CRS)
- Documentation: https://matplotlib.org/stable/tutorials/advanced/transforms_tutorial.html
- `ax.transData`: default
- `ax.transAxes` and `fig.transFigure`:
- (0, 0) is bottom left
- (1, 1) is top right
- these are true immaterial of the axes limits
- `None` or `IdentityTransform()`: disabling CRS
%% Cell type:markdown id:aae7da52 tags:
### Review:
- `fig, ax = plt.subplots(figsize=(<width>, <height>), ncols=<N>, nrows=<N>)`:
- ncols: split into vertical sub plots
- nrows: split into horizontal sub plots
- `ax.set_xlim(<lower limit>, <upper limit>)`: set x-axis limits
- `ax.set_ylim(<lower limit>, <upper limit>)`: set y-axis limits
### `ax.transData`
- `transform` parameter in "patch" creation function let's us specify the CRS
- `color` parameter controls the color of the "patch"
- `edgecolor` parameter controls outer border color of the "patch"
- `linewidth` parameter controls the size of the border of the "patch"
- `facecolor` parameter controls the filled in color of the "patch"
%% Cell type:code id:5adb1223-0fc4-422c-95ef-1446ad811940 tags:
``` python
# Create a plot with two vertical subplots
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(6, 4))
# Set right subplot x-axis limit from 0 to 3
ax2.set_xlim(0, 3)
# Left subplot: plot Circle at (0.5, 0.5) with radius 0.2
# Specify CRS as ax1.transData (tranform parameter)
c = plt.Circle((0.5, 0.5), 0.2, transform=ax1.transData)
ax1.add_artist(c)
# Right subplot: plot Circle at (0.5, 0.5) with radius 0.2
# default: transform=ax2.transData
c = plt.Circle((0.5, 0.5), 0.2)
ax2.add_artist(c)
# Observe that we get a different circle
# Transform based on ax1, but crop based on ax2
# Left subplot: plot Circle at (1, 1) with radius 0.3 and crop using ax1
# Left subplot: plot Circle at (1, 1) with radius 0.3 and crop using ax2
c = plt.Circle((1, 1), 0.3, transform=ax1.transData) # where to position the shape
ax1.add_artist(c) # how to crop the shape
# Right subplot: plot Circle at (1, 1) with radius 0.3 and crop using ax2
c = plt.Circle((1, 1), 0.3, transform=ax1.transData, color="lightblue") # where to position the shape
ax2.add_artist(c) # how to crop the shape
```
%% Output
<matplotlib.patches.Circle at 0x7f359624d820>
%% Cell type:markdown id:7ffc89cd tags:
### `ax.transAxes` and `fig.transFigure`
- (0, 0) is bottom left
- (1, 1) is top right
- these are true immaterial of the axes limits
%% Cell type:code id:38aa99c6-039a-468e-9cb1-b1a3d9b36a80 tags:
``` python
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(6, 4))
ax2.set_xlim(0, 3)
# Left subplot
c = plt.Circle((0.5, 0.5), 0.2, transform=ax1.transAxes)
ax1.add_artist(c)
# Right subplot
c = plt.Circle((0.5, 0.5), 0.2, transform=ax2.transAxes)
ax2.add_artist(c)
# whole figure
# edgecolor="red", facecolor="none", linewidth=3
c = plt.Circle((0.5, 0.5), 0.2, transform=fig.transFigure, edgecolor="red", facecolor="none", linewidth=3)
fig.add_artist(c)
```
%% Output
<matplotlib.patches.Circle at 0x7f35961849a0>
%% Cell type:markdown id:bfa71840 tags:
### No CRS (raw pixel coordinates)
- `fig.dpi`: dots (aka pixesl) per inch
- increasing dpi makes the figure have higher resolution (helpful when you want to print a large size)
- Review:
- `plt.tight_layout()`: avoid unncessary cropping of the figure --- always needed for No CRS cases
- `fig.savefig(<relative path.png>)`: to save a local copy of the image
- Jupyter command to avoid cropping:
- `%config InlineBackend.print_figure_kwargs={'bbox_inches': None}`
- bbox_inches stands for bounding box
%% Cell type:code id:4c571b0f tags:
``` python
# Jupyter commands begin with %
%config InlineBackend.print_figure_kwargs={'bbox_inches': None}
```
%% Cell type:code id:e09ef243-ba52-4b70-a980-6ff4735f0fc2 tags:
``` python
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(6, 4))
ax2.set_xlim(0, 3)
# What is the dpi?
print(fig.dpi) # dots (aka pixel) per inch
# Calculate total width and height of the figure using dpi and dimensions
width = 6 * fig.dpi
height = 4 * fig.dpi
# Calculate (x, y) in the middle of the plot
x = width / 2
y = height / 2
print(x, y)
# Make sure to invoke plt.tight_layout()
# matplotlib does the cropping better than Jupyter
#plt.tight_layout()
# Draw a circle at (x, y) with radius 30
# Make sure to set transform=None
c = plt.Circle((x, y), 30, transform=None)
fig.add_artist(c)
# Save the figure to temp.png
fig.savefig("temp.png")
```
%% Output
100.0
300.0 200.0
%% Cell type:markdown id:78040b6e-0446-4aab-8e0b-feb4f2646142 tags:
### Mix and match
- `ax.transData.transform((x, y))`: converts axes / data coords into raw coordinates
- How to draw an arrow:
`matplotlib.patches.FancyArrowPatch((<x1>, <y1>), (<x2>, (<y2>)), transform=None, arrowstyle=<STYLE>)`
`matplotlib.patches.FancyArrowPatch((<x1>, <y1>), (<x2>, <y2>)), transform=None, arrowstyle=<STYLE>)`
- arrowstyle="simple,head_width=10,head_length=10"
%% Cell type:code id:9ef4efdf-ce83-4096-a411-fa4ae968514e tags:
``` python
# GOAL: draw a visual circle at axes / data coords 0.5, 0.5
# with raw co-ordinate radius 30 on right subplot
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(6, 4))
ax2.set_xlim(0, 3)
# crop now (after .transform, we don't want to move anything!)
plt.tight_layout()
x, y = ax2.transData.transform((0.5, 0.5))
print(x, y)
# Draw a circle at (x, y) with radius 30 and set transform to None
c = plt.Circle((x, y), 30, transform=None)
ax2.add_artist(c)
# GOAL: arrow from 0.2, 0.2 (left) to 2, 0.5 (right)
# Use axes / data coords from one subplot to another subplot
x1, y1 = ax1.transData.transform((0.2, 0.2))
x2, y2 = ax2.transData.transform((2, 0.5))
# arrowstyle="simple,head_width=10,head_length=10"
arrow = matplotlib.patches.FancyArrowPatch((x1, y1), (x2, y2), transform=None, color="k",
arrowstyle="simple,head_width=10,head_length=10")
fig.add_artist(arrow)
```
%% Output
382.2164351851851 209.11111111111111
<matplotlib.patches.FancyArrowPatch at 0x7f359602afa0>
%% Cell type:markdown id:8878fb2b-b39c-4c32-b54d-0e9fc909c400 tags:
### Custom Scatter Plots with Angles
%% Cell type:code id:263cc5c9-2751-4dbb-be8a-9dc5fc0b5217 tags:
``` python
df = pd.DataFrame([
{"x":2, "y":5, "a": 90},
{"x":3, "y":1, "a": 0},
{"x":6, "y":6, "a": 45},
{"x":8, "y":1, "a": 180}
])
df
```
%% Output
x y a
0 2 5 90
1 3 1 0
2 6 6 45
3 8 1 180
%% Cell type:code id:24c2de6e-86e7-48fc-9f89-48d8cff68736 tags:
``` python
fig, ax = plt.subplots(figsize=(3,2))
ax.set_xlim(0, 10)
ax.set_ylim(-1, 10)
for row in df.itertuples():
print(row.x, row.y, row.a)
# v1: draw a circle of radius 10 for each scatter point
# x, y = ax.transData.transform((row.x, row.y))
# c = plt.Circle((x,y), radius=10, transform=None)
# ax.add_artist(c)
# v2: draw an arrow for each scatter point (correct angle)
x, y = ax.transData.transform((row.x, row.y))
# Calculate angle: math.radians(row.a)
a = math.radians(row.a)
# Calculate end axes / data coords using math.cos and math.sin
x_diff = math.cos(a) * 25
y_diff = math.sin(a) * 25
c = matplotlib.patches.FancyArrowPatch((x,y), (x+x_diff, y+y_diff),transform=None, color="k",
arrowstyle="simple,head_width=10,head_length=10")
ax.add_artist(c)
```
%% Output
2 5 90
3 1 0
6 6 45
8 1 180
%% Cell type:markdown id:9730e3e9-ed3c-49d8-aaf0-e0c29290fb90 tags:
### Plot annotations
- Target plot:
<img src = "Target_plot.png">
%% Cell type:markdown id:19eb08f2-3949-465c-9629-fe9c33d9aa8d tags:
- `ax.text(<x>, <y>, <text>, ha=<someval>, va=<someval>)`
- `ha`: horizontalalignment
- `va`: verticalalignment
- enables us to modify "anchor" of the text
### More patches
- `plt.Line2D((<x1>, <x2>), (<y1>, <y2>)))`
- `matplotlib.patches.FancyArrowPatch((<x1>, <y1>), (<x2>, (<y2>))`
- `plt.Rectangle((<x>,<y>), <width>, <height>)`
%% Cell type:code id:3fe00736-a62f-41ce-ae99-a6e95a36f9f8 tags:
``` python
plt.rcParams["font.size"] = 16
df = pd.DataFrame({"A": [1,2,8,9], "B": [5,7,12,15]}, index=[10,20,30,40])
ax = df.plot.line(figsize=(4,3), legend=False)
ax.set_xlabel("Day")
ax.set_ylabel("Amount")
plt.tight_layout()
# Enables us to control borders (aka spines)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
# 1. Replace legened with line labels
for col in df.columns:
ax.text(df.index[-1], df[col].iat[-1], col, ha="left", va="center")
# 2. Draw a vertical line at x=20
p = plt.Line2D((20, 20), ax.get_ylim(), color="r", linestyle="--")
ax.add_artist(p)
# 3. Highlight a region from x=25 to x=35
p = plt.Rectangle((25, 0), 10, ax.get_ylim()[1], color="k", zorder=50, alpha=0.2, linewidth=0)
ax.add_artist(p)
df
```
%% Output
A B
10 1 5
20 2 7
30 8 12
40 9 15
......
%% Cell type:markdown id:084b5333 tags:
# Visualization 1
- Advanced visualization, example: https://trailsofwind.figures.cc/
- Custom visualization steps:
- draw "patches" (shapes) on the screen (what):
- lines
- polygons
- circle
- text
- location of the "patches" on the screen (where):
- X & Y co-ordinate
- "Coordinate Reference System (CRS)":
- takes some X & Y and maps it on to actual space on screen
- several CRS
%% Cell type:code id:5df39a4b-d55b-4ba0-ab78-bd06fac8047e tags:
``` python
# import statements
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import math
```
%% Cell type:markdown id:af357b87 tags:
### Review: drawing a figure
- `fig, ax = plt.subplots(figsize=(<width>, <height>))`
### Drawing a circle
- Type `plt.` and then tab to see a list of `patches`.
- `plt.Circle((<X>, <Y>), <RADIUS>)`
- To see the cicle, we need to invoke either:
- `ax.add_patch(<circle object>)`
- `ax.add_artist(<circle object>)`
- this invocation needs to be in the same cell as the one that draws the figure
- Is there a difference between `ax.add_patch` and `ax.add_artist`?
- `ax.autoscale_view()`: automatically chose limits for the axes; typically works better with `ax.add_patch(...)`
%% Cell type:code id:152cd4b0-7334-491f-841d-c0bfe3fce3c9 tags:
``` python
fig, ax = plt.subplots(figsize=(6, 4))
# Let's draw a circle at (0.5, 0.5) of radius 0.3
# Add the circle to the AxesSubplot
```
%% Cell type:code id:5064c802 tags:
``` python
```
%% Cell type:markdown id:5b760ce1 tags:
Type and MRO of circle object.
%% Cell type:code id:8a714acd-e33d-4fa0-9fdd-de8438e94418 tags:
``` python
type(c)
```
%% Cell type:code id:2617ab22 tags:
``` python
type(c)
```
%% Cell type:markdown id:085918f5 tags:
### Making the circle circular
1. Have same figure width and height
2. Aspect ratio
3. Transformers: let's us pick a Coordinate Reference System (CRS)
%% Cell type:code id:1bf67506 tags:
``` python
# Option 1: Have same figure width and height
fig, ax = plt.subplots(figsize=(6, 4))
c = plt.Circle((0.5, 0.5), 0.3)
ax.add_patch(c)
ax.autoscale_view()
```
%% Cell type:markdown id:4bd1648d-55ce-4156-b94e-6b9a10db4da7 tags:
### Aspect Ratio
- `ax.set_aspect(<Y DIM>)`: how much space y axes takes with respect to x axes space
%% Cell type:code id:06b32774-26a2-4627-b363-f79eb2838d07 tags:
``` python
fig, ax = plt.subplots(figsize=(6, 4))
c = plt.Circle((0.5, 0.5), 0.3)
ax.add_artist(c)
# Set aspect for y-axis to 1
```
%% Cell type:markdown id:65f0928e tags:
What if we want x and y axes to have the same aspect ratio? That is we care more about the figure being square than about the circle being circular.
%% Cell type:code id:7fa11875-34ba-4550-8e8b-9a9f92e58a9a tags:
``` python
fig, ax = plt.subplots(figsize=(6,4))
# Set x axis limit to (0, 3)
c = plt.Circle((0.5, 0.5), 0.3)
ax.add_artist(c)
# Set aspect for y-axis to 3
```
%% Cell type:markdown id:c2429f83-1603-4aaf-b767-a60969fc20d7 tags:
### Transformers: let us pick a Coordinate Reference System (CRS)
- Documentation: https://matplotlib.org/stable/tutorials/advanced/transforms_tutorial.html
- `ax.transData`: default
- `ax.transAxes` and `fig.transFigure`:
- (0, 0) is bottom left
- (1, 1) is top right
- these are true immaterial of the axes limits
- `None` or `IdentityTransform()`: disabling CRS
%% Cell type:markdown id:84c0e7b7 tags:
### Review:
- `fig, ax = plt.subplots(figsize=(<width>, <height>), ncols=<N>, nrows=<N>)`:
- ncols: split into vertical sub plots
- nrows: split into horizontal sub plots
- `ax.set_xlim(<lower limit>, <upper limit>)`: set x-axis limits
- `ax.set_ylim(<lower limit>, <upper limit>)`: set y-axis limits
### `ax.transData`
- `transform` parameter in "patch" creation function let's us specify the CRS
- `color` parameter controls the color of the "patch"
- `edgecolor` parameter controls outer border color of the "patch"
- `linewidth` parameter controls the size of the border of the "patch"
- `facecolor` parameter controls the filled in color of the "patch"
%% Cell type:code id:5adb1223-0fc4-422c-95ef-1446ad811940 tags:
``` python
# Create a plot with two vertical subplots
# Set right subplot x-axis limit from 0 to 3
# Left subplot: plot Circle at (0.5, 0.5) with radius 0.2
# Specify CRS as ax1.transData (tranform parameter)
# Right subplot: plot Circle at (0.5, 0.5) with radius 0.2
# default: transform=ax2.transData
# Observe that we get a different circle
# Transform based on ax1, but crop based on ax2
# Left subplot: plot Circle at (1, 1) with radius 0.3 and crop using ax1
# Left subplot: plot Circle at (1, 1) with radius 0.3 and crop using ax2
# where to position the shape
# how to crop the shape
# Right subplot: plot Circle at (1, 1) with radius 0.3 and crop using ax2
# where to position the shape
# how to crop the shape
```
%% Cell type:markdown id:0167a871 tags:
### `ax.transAxes` and `fig.transFigure`
- (0, 0) is bottom left
- (1, 1) is top right
- these are true immaterial of the axes limits
%% Cell type:code id:38aa99c6-039a-468e-9cb1-b1a3d9b36a80 tags:
``` python
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(6, 4))
ax2.set_xlim(0, 3)
# Left subplot
c = plt.Circle((0.5, 0.5), 0.2, transform=???)
???.add_artist(c)
# Right subplot
c = plt.Circle((0.5, 0.5), 0.2, transform=???)
???.add_artist(c)
# whole figure
# edgecolor="red", facecolor="none", linewidth=3
```
%% Cell type:markdown id:bc52379c tags:
### No CRS (raw pixel coordinates)
- `fig.dpi`: dots (aka pixesl) per inch
- increasing dpi makes the figure have higher resolution (helpful when you want to print a large size)
- Review:
- `plt.tight_layout()`: avoid unncessary cropping of the figure --- always needed for No CRS cases
- `fig.savefig(<relative path.png>)`: to save a local copy of the image
- Jupyter command to avoid cropping:
- `%config InlineBackend.print_figure_kwargs={'bbox_inches': None}`
- bbox_inches stands for bounding box
%% Cell type:code id:222eb737 tags:
``` python
# Jupyter commands begin with %
```
%% Cell type:code id:e09ef243-ba52-4b70-a980-6ff4735f0fc2 tags:
``` python
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(6, 4))
ax2.set_xlim(0, 3)
# What is the dpi?
# dots (aka pixel) per inch
# Calculate total width and height of the figure using dpi and dimensions
width = ???
height = ???
# Calculate (x, y) in the middle of the plot
x = ???
y = >>>
print(x, y)
# Make sure to invoke plt.tight_layout()
# matplotlib does the cropping better than Jupyter
# Draw a circle at (x, y) with radius 30
# Make sure to set transform=None
# Save the figure to temp.png
```
%% Cell type:markdown id:744d76e5 tags:
### Mix and match
- `ax.transData.transform((x, y))`: converts axes / data coords into raw coordinates
- How to draw an arrow:
`matplotlib.patches.FancyArrowPatch((<x1>, <y1>), (<x2>, (<y2>)), transform=None, arrowstyle=<STYLE>)`
`matplotlib.patches.FancyArrowPatch((<x1>, <y1>), (<x2>, <y2>)), transform=None, arrowstyle=<STYLE>)`
- arrowstyle="simple,head_width=10,head_length=10"
%% Cell type:code id:db8a296e-6eae-4e57-a94e-b7901c476ae2 tags:
``` python
# GOAL: draw a visual circle at axes / data coords 0.5, 0.5
# with raw co-ordinate radius 30 on right subplot
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(6, 4))
ax2.set_xlim(0, 3)
# crop now (after .transform, we don't want to move anything!)
# plt.tight_layout()
# Transform (0.5, 0.5) to transData CRS
print(x, y)
# Draw a circle at (x, y) with radius 30 and set transform to None
# GOAL: arrow from 0.2, 0.2 (left) to 2, 0.5 (right)
# Use axes / data coords from one subplot to another subplot
# arrowstyle="simple,head_width=10,head_length=10"
arrow = matplotlib.patches.FancyArrowPatch((x1, y1), (x2, y2), transform=None)
fig.add_artist(arrow)
```
%% Cell type:markdown id:d2272a0b-f8f1-4bdd-87d5-971aee1ce160 tags:
### Custom Scatter Plots with Angles
%% Cell type:code id:468492f8-0e1e-4a37-b16c-d08e818a1b63 tags:
``` python
df = pd.DataFrame([
{"x":2, "y":5, "a": 90},
{"x":3, "y":1, "a": 0},
{"x":6, "y":6, "a": 45},
{"x":8, "y":1, "a": 180}
])
df
```
%% Cell type:code id:4963466b-acab-468e-bdde-97f9908933a8 tags:
``` python
fig, ax = plt.subplots(figsize=(3, 2))
ax.set_xlim(0, 10)
ax.set_ylim(0, 10)
for row in df.itertuples():
print(row.x, row.y, row.a)
# v1: draw a circle for each scatter point
# x, y = ax.transData.transform((row.x, row.y))
# c = plt.Circle((x,y), radius=10, transform=None)
# ax.add_artist(c)
# v2: draw an arrow for each scatter point (correct angle)
#x, y = ax.transData.transform((row.x, row.y))
# Calculate angle: math.radians(row.a)
#a = ???
# Calculate end axes / data coords:
# using math.cos(a) * 25 and math.sin(a) * 25
#x_diff = ???
#y_diff = ???
c = matplotlib.patches.FancyArrowPatch((x,y), (x+x_diff, y+y_diff),transform=None, color="k",
arrowstyle="simple,head_width=10,head_length=10")
ax.add_artist(c)
```
%% Cell type:markdown id:1ddfa239-804f-4c86-b8e9-6f94e7709ab6 tags:
### Plot annotations
- Target plot:
<img src = "Target_plot.png">
%% Cell type:markdown id:dff3b3a7-171f-4dab-9bb4-9c5fc76ca0db tags:
- `ax.text(<x>, <y>, <text>, ha=<someval>, va=<someval>)`
- `ha`: horizontalalignment
- `va`: verticalalignment
- enables us to modify "anchor" of the text
### More patches
- `plt.Line2D((<x1>, <x2>), (<y1>, <y2>)))`
- `matplotlib.patches.FancyArrowPatch((<x1>, <y1>), (<x2>, (<y2>))`
- `plt.Rectangle((<x>,<y>), <width>, <height>)`
%% Cell type:code id:648f8e12-d357-43ec-b7de-1f8a14b7264b tags:
``` python
plt.rcParams["font.size"] = 16
df = pd.DataFrame({"A": [1,2,8,9], "B": [5,7,12,15]}, index=[10,20,30,40])
ax = df.plot.line(figsize=(4,3))
ax.set_xlabel("Day")
ax.set_ylabel("Amount")
plt.tight_layout()
# Enables us to control borders (aka spines)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
# 1. Replace legened with line labels
# 2. Draw a vertical line at x=20
# color="r", linestyle="--"
# 3. Highlight a region from x=25 to x=35
# color="k", zorder=50, alpha=0.2, linewidth=0
df
```
......
%% Cell type:markdown id:084b5333 tags:
# Visualization 1
- Advanced visualization, example: https://trailsofwind.figures.cc/
- Custom visualization steps:
- draw "patches" (shapes) on the screen (what):
- lines
- polygons
- circle
- text
- location of the "patches" on the screen (where):
- X & Y co-ordinate
- "Coordinate Reference System (CRS)":
- takes some X & Y and maps it on to actual space on screen
- several CRS
%% Cell type:code id:5df39a4b-d55b-4ba0-ab78-bd06fac8047e tags:
``` python
# import statements
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import math
```
%% Cell type:markdown id:af357b87 tags:
### Review: drawing a figure
- `fig, ax = plt.subplots(figsize=(<width>, <height>))`
### Drawing a circle
- Type `plt.` and then tab to see a list of `patches`.
- `plt.Circle((<X>, <Y>), <RADIUS>)`
- To see the cicle, we need to invoke either:
- `ax.add_patch(<circle object>)`
- `ax.add_artist(<circle object>)`
- this invocation needs to be in the same cell as the one that draws the figure
- Is there a difference between `ax.add_patch` and `ax.add_artist`?
- `ax.autoscale_view()`: automatically chose limits for the axes; typically works better with `ax.add_patch(...)`
%% Cell type:code id:152cd4b0-7334-491f-841d-c0bfe3fce3c9 tags:
``` python
fig, ax = plt.subplots(figsize=(6, 4))
# Let's draw a circle at (0.5, 0.5) of radius 0.3
# Add the circle to the AxesSubplot
```
%% Cell type:code id:5064c802 tags:
``` python
```
%% Cell type:markdown id:5b760ce1 tags:
Type and MRO of circle object.
%% Cell type:code id:8a714acd-e33d-4fa0-9fdd-de8438e94418 tags:
``` python
type(c)
```
%% Cell type:code id:2617ab22 tags:
``` python
type(c)
```
%% Cell type:markdown id:085918f5 tags:
### Making the circle circular
1. Have same figure width and height
2. Aspect ratio
3. Transformers: let's us pick a Coordinate Reference System (CRS)
%% Cell type:code id:1bf67506 tags:
``` python
# Option 1: Have same figure width and height
fig, ax = plt.subplots(figsize=(6, 4))
c = plt.Circle((0.5, 0.5), 0.3)
ax.add_patch(c)
ax.autoscale_view()
```
%% Cell type:markdown id:4bd1648d-55ce-4156-b94e-6b9a10db4da7 tags:
### Aspect Ratio
- `ax.set_aspect(<Y DIM>)`: how much space y axes takes with respect to x axes space
%% Cell type:code id:06b32774-26a2-4627-b363-f79eb2838d07 tags:
``` python
fig, ax = plt.subplots(figsize=(6, 4))
c = plt.Circle((0.5, 0.5), 0.3)
ax.add_artist(c)
# Set aspect for y-axis to 1
```
%% Cell type:markdown id:65f0928e tags:
What if we want x and y axes to have the same aspect ratio? That is we care more about the figure being square than about the circle being circular.
%% Cell type:code id:7fa11875-34ba-4550-8e8b-9a9f92e58a9a tags:
``` python
fig, ax = plt.subplots(figsize=(6,4))
# Set x axis limit to (0, 3)
c = plt.Circle((0.5, 0.5), 0.3)
ax.add_artist(c)
# Set aspect for y-axis to 3
```
%% Cell type:markdown id:c2429f83-1603-4aaf-b767-a60969fc20d7 tags:
### Transformers: let us pick a Coordinate Reference System (CRS)
- Documentation: https://matplotlib.org/stable/tutorials/advanced/transforms_tutorial.html
- `ax.transData`: default
- `ax.transAxes` and `fig.transFigure`:
- (0, 0) is bottom left
- (1, 1) is top right
- these are true immaterial of the axes limits
- `None` or `IdentityTransform()`: disabling CRS
%% Cell type:markdown id:84c0e7b7 tags:
### Review:
- `fig, ax = plt.subplots(figsize=(<width>, <height>), ncols=<N>, nrows=<N>)`:
- ncols: split into vertical sub plots
- nrows: split into horizontal sub plots
- `ax.set_xlim(<lower limit>, <upper limit>)`: set x-axis limits
- `ax.set_ylim(<lower limit>, <upper limit>)`: set y-axis limits
### `ax.transData`
- `transform` parameter in "patch" creation function let's us specify the CRS
- `color` parameter controls the color of the "patch"
- `edgecolor` parameter controls outer border color of the "patch"
- `linewidth` parameter controls the size of the border of the "patch"
- `facecolor` parameter controls the filled in color of the "patch"
%% Cell type:code id:5adb1223-0fc4-422c-95ef-1446ad811940 tags:
``` python
# Create a plot with two vertical subplots
# Set right subplot x-axis limit from 0 to 3
# Left subplot: plot Circle at (0.5, 0.5) with radius 0.2
# Specify CRS as ax1.transData (tranform parameter)
# Right subplot: plot Circle at (0.5, 0.5) with radius 0.2
# default: transform=ax2.transData
# Observe that we get a different circle
# Transform based on ax1, but crop based on ax2
# Left subplot: plot Circle at (1, 1) with radius 0.3 and crop using ax1
# Left subplot: plot Circle at (1, 1) with radius 0.3 and crop using ax2
# where to position the shape
# how to crop the shape
# Right subplot: plot Circle at (1, 1) with radius 0.3 and crop using ax2
# where to position the shape
# how to crop the shape
```
%% Cell type:markdown id:0167a871 tags:
### `ax.transAxes` and `fig.transFigure`
- (0, 0) is bottom left
- (1, 1) is top right
- these are true immaterial of the axes limits
%% Cell type:code id:38aa99c6-039a-468e-9cb1-b1a3d9b36a80 tags:
``` python
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(6, 4))
ax2.set_xlim(0, 3)
# Left subplot
c = plt.Circle((0.5, 0.5), 0.2, transform=???)
???.add_artist(c)
# Right subplot
c = plt.Circle((0.5, 0.5), 0.2, transform=???)
???.add_artist(c)
# whole figure
# edgecolor="red", facecolor="none", linewidth=3
```
%% Cell type:markdown id:bc52379c tags:
### No CRS (raw pixel coordinates)
- `fig.dpi`: dots (aka pixesl) per inch
- increasing dpi makes the figure have higher resolution (helpful when you want to print a large size)
- Review:
- `plt.tight_layout()`: avoid unncessary cropping of the figure --- always needed for No CRS cases
- `fig.savefig(<relative path.png>)`: to save a local copy of the image
- Jupyter command to avoid cropping:
- `%config InlineBackend.print_figure_kwargs={'bbox_inches': None}`
- bbox_inches stands for bounding box
%% Cell type:code id:222eb737 tags:
``` python
# Jupyter commands begin with %
```
%% Cell type:code id:e09ef243-ba52-4b70-a980-6ff4735f0fc2 tags:
``` python
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(6, 4))
ax2.set_xlim(0, 3)
# What is the dpi?
# dots (aka pixel) per inch
# Calculate total width and height of the figure using dpi and dimensions
width = ???
height = ???
# Calculate (x, y) in the middle of the plot
x = ???
y = >>>
print(x, y)
# Make sure to invoke plt.tight_layout()
# matplotlib does the cropping better than Jupyter
# Draw a circle at (x, y) with radius 30
# Make sure to set transform=None
# Save the figure to temp.png
```
%% Cell type:markdown id:744d76e5 tags:
### Mix and match
- `ax.transData.transform((x, y))`: converts axes / data coords into raw coordinates
- How to draw an arrow:
`matplotlib.patches.FancyArrowPatch((<x1>, <y1>), (<x2>, (<y2>)), transform=None, arrowstyle=<STYLE>)`
`matplotlib.patches.FancyArrowPatch((<x1>, <y1>), (<x2>, <y2>)), transform=None, arrowstyle=<STYLE>)`
- arrowstyle="simple,head_width=10,head_length=10"
%% Cell type:code id:db8a296e-6eae-4e57-a94e-b7901c476ae2 tags:
``` python
# GOAL: draw a visual circle at axes / data coords 0.5, 0.5
# with raw co-ordinate radius 30 on right subplot
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(6, 4))
ax2.set_xlim(0, 3)
# crop now (after .transform, we don't want to move anything!)
# plt.tight_layout()
# Transform (0.5, 0.5) to transData CRS
print(x, y)
# Draw a circle at (x, y) with radius 30 and set transform to None
# GOAL: arrow from 0.2, 0.2 (left) to 2, 0.5 (right)
# Use axes / data coords from one subplot to another subplot
# arrowstyle="simple,head_width=10,head_length=10"
arrow = matplotlib.patches.FancyArrowPatch((x1, y1), (x2, y2), transform=None)
fig.add_artist(arrow)
```
%% Cell type:markdown id:d2272a0b-f8f1-4bdd-87d5-971aee1ce160 tags:
### Custom Scatter Plots with Angles
%% Cell type:code id:468492f8-0e1e-4a37-b16c-d08e818a1b63 tags:
``` python
df = pd.DataFrame([
{"x":2, "y":5, "a": 90},
{"x":3, "y":1, "a": 0},
{"x":6, "y":6, "a": 45},
{"x":8, "y":1, "a": 180}
])
df
```
%% Cell type:code id:4963466b-acab-468e-bdde-97f9908933a8 tags:
``` python
fig, ax = plt.subplots(figsize=(3, 2))
ax.set_xlim(0, 10)
ax.set_ylim(0, 10)
for row in df.itertuples():
print(row.x, row.y, row.a)
# v1: draw a circle for each scatter point
# x, y = ax.transData.transform((row.x, row.y))
# c = plt.Circle((x,y), radius=10, transform=None)
# ax.add_artist(c)
# v2: draw an arrow for each scatter point (correct angle)
#x, y = ax.transData.transform((row.x, row.y))
# Calculate angle: math.radians(row.a)
#a = ???
# Calculate end axes / data coords:
# using math.cos(a) * 25 and math.sin(a) * 25
#x_diff = ???
#y_diff = ???
c = matplotlib.patches.FancyArrowPatch((x,y), (x+x_diff, y+y_diff),transform=None, color="k",
arrowstyle="simple,head_width=10,head_length=10")
ax.add_artist(c)
```
%% Cell type:markdown id:1ddfa239-804f-4c86-b8e9-6f94e7709ab6 tags:
### Plot annotations
- Target plot:
<img src = "Target_plot.png">
%% Cell type:markdown id:dff3b3a7-171f-4dab-9bb4-9c5fc76ca0db tags:
- `ax.text(<x>, <y>, <text>, ha=<someval>, va=<someval>)`
- `ha`: horizontalalignment
- `va`: verticalalignment
- enables us to modify "anchor" of the text
### More patches
- `plt.Line2D((<x1>, <x2>), (<y1>, <y2>)))`
- `matplotlib.patches.FancyArrowPatch((<x1>, <y1>), (<x2>, (<y2>))`
- `plt.Rectangle((<x>,<y>), <width>, <height>)`
%% Cell type:code id:648f8e12-d357-43ec-b7de-1f8a14b7264b tags:
``` python
plt.rcParams["font.size"] = 16
df = pd.DataFrame({"A": [1,2,8,9], "B": [5,7,12,15]}, index=[10,20,30,40])
ax = df.plot.line(figsize=(4,3))
ax.set_xlabel("Day")
ax.set_ylabel("Amount")
plt.tight_layout()
# Enables us to control borders (aka spines)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
# 1. Replace legened with line labels
# 2. Draw a vertical line at x=20
# color="r", linestyle="--"
# 3. Highlight a region from x=25 to x=35
# color="k", zorder=50, alpha=0.2, linewidth=0
df
```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment