Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use democards for examples #48

Merged
merged 5 commits into from
May 8, 2024
Merged
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
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DemoCards = "311a05b2-6137-4a5a-b473-18580a3d38b5"
PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee"
Batsrus = "e74ebddf-6ac1-4047-a0e5-c32c99e57753"

Expand Down
7 changes: 7 additions & 0 deletions docs/examples/basics/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"theme": "nocoverlist",
"order": [
"demo_animate_1d.md",
"demo_animate_2d.md"
]
}
106 changes: 106 additions & 0 deletions docs/examples/basics/demo_animate_1d.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# ---
# title: Line Animation
# id: demo_line_animation
# date: 2024-05-08
# author: "[Hongyang Zhou](https://github.com/henry2004y)"
# julia: 1.10.3
# description: 1D line animation using pyplot
# ---

This example shows how to create 1D space line animation from series of SWMF outputs.

* Vertical line moving at the solar wind speed for reference.
* Twin axes sharing the same x-axis for showing two quantities in one frame.
* Time-dependent title.

```julia
using Batsrus, PyPlot, Printf

"""
animate1d(files::Vector{String}, vars::Vector{String}; kwargs...)

Saving series of plots of `vars` from SWMF output `files`.

# Keywords
- `filedir::String="./"`: input SWMF file directory.
- `outdir::String="out/"`: output directory.
- `output_interval::Int=1`: Timestep interval for output files.
- `vmin=-1`: plot value lower bound.
- `vmax=1`: plot value upper bound.
- `refloc=1e5`: reference vertical line initial location.
"""
function animate1d(files::Vector{String}, vars::Vector{String};
filedir::String="./", outdir::String="out/", output_interval::Int=1,
vmin=-1, vmax=1, refloc=1e5)
nfile = length(files)
x = let
bd = load(joinpath(filedir, files[1]))
bd.x[:,1,1]
end

fig = plt.figure(figsize=(12,5), constrained_layout=true)
ax = plt.axes(xlim=extrema(x), ylim=(vmin, vmax))

line, = ax.plot([], [], lw=1)
# Move reference line forward in the canvas
vl = ax.axvline(0, ls="-", color="tab:brown", lw=1, zorder=10)

color = "tab:blue"
ax.set_xlabel("x [km]"; fontsize=14)
ax.set_ylabel(var*" [nT]"; fontsize=14, color)
ax.tick_params(axis="y", labelcolor=color)

ax2 = ax.twinx()
ax2.set_ylim(-600, 0)

color = "tab:red"
ax2.set_ylabel("Ux [km/s]"; fontsize=14, color)

line2, = ax2.plot([], []; color, alpha=0.7)
ax2.tick_params(axis="y", labelcolor=color)


for (i, file) in enumerate(files)
@info "$i in $nfile"
outname = outdir*lpad(i, 4, '0')*".png"
isfile(outname) && continue

bd = load(joinpath(filedir, file))

d = bd[vars[1]][:,1]
title_str = @sprintf "t = %4.1f s" bd.head.time
line.set_data(x, d)
d2 = bd[vars[2]][:,1]
line2.set_data(x, d2)

ax.set_title(title_str)

refloc -= output_interval * VSW
if refloc <= 0
refloc += 1e5
end
vl.set_xdata([refloc, refloc])

savefig(outname, bbox_inches="tight", dpi=200)
end

close()
end

####################
# Constants
const VSW = 500.0 # Solar wind speed, [km/s]

# Data directory
filedir = "./"
# Plot variables
vars = ["By", "uxs1"]

# Find simulation data
files = let
pick_file = file -> startswith(file, "z") && endswith(file, ".out")
filter(pick_file, readdir(filedir))
end

animate1d(files, vars)
```
151 changes: 151 additions & 0 deletions docs/examples/basics/demo_animate_2d.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# ---
# title: Contour Animation
# id: demo_contour_animation
# date: 2024-05-08
# author: "[Hongyang Zhou](https://github.com/henry2004y)"
# julia: 1.10.3
# description: 2D contour animation using pyplot
# ---

This example shows how to create 2D colored contour animation from series of SWMF outputs.

* Time-dependent title.
* Tweakable colorbar.
* Plotting streamline on top of colored contours is a bit hacky because there is currently no intrinsic methods for removing the streamlines. Our solution here is to dispatch a streamline into lines and arrows and then remove them separately.

```julia
using Batsrus, PyPlot, Printf

"""
animate2d(files::Vector{String}, var::String; kwargs...)

Saving series of plots of `var` from SWMF output `files`.

# Keywords
- `filedir::String="./"`: input SWMF file directory.
- `outdir::String="out/"`: output directory.
- `vmin=-4`: plot value lower bound.
- `vmax=4`: plot value upper bound.
- `cmap=matplotlib.cm.RdBu_r`: chosen colormap from Matplotlib.
"""
function animate2d(files::Vector{String}, var; filedir="./", outdir="out/", vmin=-4, vmax=4,
cmap = matplotlib.cm.RdBu_r)
nfile = length(files)
x, y = let bd = load(filedir*files[1])
range(bd.x[1,1,1], bd.x[end,1,1], length=size(bd.x,1)),
range(bd.x[1,1,2], bd.x[1,end,2], length=size(bd.x,2))
end
# colormap norm
norm = matplotlib.colors.Normalize(vmin, vmax)

fig = plt.figure(figsize=(8, 3), constrained_layout=true)
ax = plt.axes()

c = let
fakedata = zeros(Float32, length(x), length(y))
ax.pcolormesh(x, y, fakedata'; norm, cmap)
end
ax.set_xlabel("x [km]", fontsize=14)
ax.set_ylabel("y [km]", fontsize=14)
cb = colorbar(c; ax, orientation="horizontal", location="top", aspect=50)
cb.ax.set_ylabel("Bz [nT]", fontsize=14)

for (i, file) in enumerate(files)
@info "$i in $nfile"
bd = load(joinpath(filedir, file))
c.set_array(bd[var]')

title_str = @sprintf "t = %4.1f s" bd.head.time
ax.set_title(title_str)

savefig(outdir*lpad(i, 4, '0')*".png", bbox_inches="tight", dpi=200)
end

close()
end

"""
animate2d_with_streamline(files::Vector{String}, var::String, streamvars; kwargs...)

Saving series of plots of `var`, together with streamplots of `streamvars`, from SWMF output
`files`.

# Keywords
- `filedir::String="./"`: input SWMF file directory.
- `outdir::String="out/"`: output directory.
- `vmin=-4`: plot value lower bound.
- `vmax=4`: plot value upper bound.
- `cmap=matplotlib.cm.RdBu_r`: chosen colormap from Matplotlib.
"""
function animate2d_with_streamline(files::Vector{String}, var, streamvars="Bx;By";
filedir="./", outdir="out/", vmin=-4, vmax=4, cmap=matplotlib.cm.RdBu_r)
nfile = length(files)
x, y = let bd = load(filedir*files[1])
range(bd.x[1,1,1], bd.x[end,1,1], length=size(bd.x,1)),
range(bd.x[1,1,2], bd.x[1,end,2], length=size(bd.x,2))
end
# colormap norm
norm = matplotlib.colors.Normalize(vmin, vmax)

fig = plt.figure(figsize=(8, 3), constrained_layout=true)
ax = plt.axes()

@info "1 in $nfile"
c = ax.pcolormesh(x, y, bd[var]'; norm, cmap)

ax.set_xlabel("x [km]", fontsize=14)
ax.set_ylabel("y [km]", fontsize=14)
cb = colorbar(c; ax, orientation="horizontal", location="top", aspect=50)
cb.ax.set_ylabel("Bz [nT]", fontsize=14)
title_str = @sprintf "t = %4.1f s" bd.head.time
ax.set_title(title_str)

st = streamplot(bd, streamvars, ax; color="gray", density=2)

save_and_clean!(1, outdir, st, ax)

for i in 2:nfile
@info "$i out of $nfile"
bd = load(joinpath(filedir, files[i]))
c.set_array(bd["Bz"]')

st = streamplot(bd, streamvars, ax; color="gray", density=2)
ax.set_xlim(x[1], x[end])
ax.set_ylim(y[1], y[end])

title_str = @sprintf "t = %4.1f s" bd.head.time
ax.set_title(title_str)

save_and_clean!(i, outdir, st, ax)
end

close()
end

function save_and_clean!(i::Int, outdir::String, st, ax)
savefig(outdir*lpad(i, 4, '0')*".png", bbox_inches="tight", dpi=200)
# Clean up streamlines
st.lines.remove()
for art in ax.get_children()
if !pybuiltin(:isinstance)(art, matplotlib.patches.FancyArrowPatch)
continue
end
art.remove()
end
end

####################
# Data directory
filedir = "./"
# Plot variables
var = "By"

# Find simulation data
files = let
pick_file = file -> startswith(file, "z") && endswith(file, ".out")
filter(pick_file, readdir(filedir))
end

animate2d(files, var)
#animate2d_with_streamline(files, var, "Bx;By")
```
9 changes: 9 additions & 0 deletions docs/examples/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"theme": "nocoverlist",
"order": [
"basics"
],
"properties": {
"notebook": "false"
}
}
9 changes: 9 additions & 0 deletions docs/examples/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# [Examples](@id examples)

This section contains thorough examples of using Batsrus.jl.

---

{{{democards}}}

---
9 changes: 9 additions & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
using Batsrus, Documenter, PyPlot
using Batsrus.UnitfulBatsrus
using DemoCards

branch = "master"
# generate demo files
demos, postprocess_cb, demo_assets = makedemos("examples"; branch)
# if there are generated css assets, pass it to Documenter.HTML
assets = String[]
isnothing(demo_assets) || (push!(assets, demo_assets))

makedocs(;
modules=[Batsrus],
Expand All @@ -13,6 +21,7 @@ makedocs(;
pages=[
"Home" => "index.md",
"Manual" => "man/manual.md",
"Examples" => demos,
"Internal" => "man/internal.md",
"Log" => "man/log.md",
],
Expand Down