Skip to content

Commit

Permalink
Switch plotting backend from PythonCall to CairoMakie (#673)
Browse files Browse the repository at this point in the history
* Switch plotting backend from PythonCall to CairoMakie

* fix test and broken documents

* fix a marker issue

* fix test
  • Loading branch information
GiggleLiu authored Aug 5, 2024
1 parent 78a960f commit d86cccc
Show file tree
Hide file tree
Showing 27 changed files with 345 additions and 395 deletions.
1 change: 0 additions & 1 deletion .ci/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ version = "0.1.0"

[deps]
Comonicon = "863f3e99-da2a-4334-8734-de3dacbe5542"
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"
CoverageTools = "c36e975a-824b-4404-a568-ef97ca766997"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589"
Expand Down
2 changes: 0 additions & 2 deletions .ci/src/example.jl
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,13 @@ in parallel.
example_dir = root_dir("examples")
script = """
using Pkg
using CondaPkg
using Literate
for name in readdir(\"$example_dir\")
project_dir = joinpath(\"$example_dir\", name)
isdir(project_dir) || continue
Pkg.activate(project_dir)
Pkg.instantiate()
CondaPkg.resolve()
@info "building" project_dir
Literate.$target(
Expand Down
2 changes: 0 additions & 2 deletions CondaPkg.toml

This file was deleted.

3 changes: 1 addition & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ BloqadeLattices = "bd27d05e-4ce1-5e79-84dd-c5d7d508bbe4"
BloqadeMIS = "bd27d05e-4ce1-5e74-84dd-c5d7d508bbe2"
BloqadeODE = "bd27d05e-4ce1-5e79-84dd-c5d7d508bbe5"
BloqadeWaveforms = "bd27d05e-4ce1-5e79-84dd-c5d7d508bbe7"
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7"
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
Yao = "5872b779-8223-5990-8dd0-5abbb0748c8c"
YaoSubspaceArrayReg = "bd27d05e-4ce1-5e79-84dd-c5d7d508ade2"
Expand All @@ -29,7 +29,6 @@ ColorSchemes = "3"
Colors = "0.12"
ForwardDiff = "0.10"
Measurements = "2"
PythonCall = "0.8,0.9"
Reexport = "1"
Yao = "0.9"
YaoSubspaceArrayReg = "0.2"
Expand Down
1 change: 0 additions & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
Yao = "5872b779-8223-5990-8dd0-5abbb0748c8c"
YaoAPI = "0843a435-28de-4971-9e8b-a9641b2983a8"
Expand Down
4 changes: 0 additions & 4 deletions docs/src/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ Built on top of Ubuntu Server 20.04 LTS, this image includes
- [Yao.jl](https://yaoquantum.org/)
- [Revise.jl](https://github.com/timholy/Revise.jl)
- [BenchmarkTools.jl](https://juliaci.github.io/BenchmarkTools.jl/stable/)
- [PythonCall.jl](https://cjdoris.github.io/PythonCall.jl/stable/)
- Conda package manager, provided by [Miniconda](https://docs.conda.io/en/latest/miniconda.html)

#### Bloqade CUDA AMI

Expand Down Expand Up @@ -227,8 +225,6 @@ Built on top of Ubuntu Server 20.04 LTS, this image includes
- [Yao.jl](https://yaoquantum.org/)
- [Revise.jl](https://github.com/timholy/Revise.jl)
- [BenchmarkTools.jl](https://juliaci.github.io/BenchmarkTools.jl/stable/)
- [PythonCall.jl](https://cjdoris.github.io/PythonCall.jl/stable/)
- Conda package manager, provided by [Mamba](https://mamba.readthedocs.io/en/latest/index.html)
- Jupyter Lab interface with dedicated Julia and Python kernels
- Integrated Terminal for interactive command-line sessions

Expand Down
27 changes: 17 additions & 10 deletions docs/src/waveform.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@ which is a created by providing a callable object and a real number `duration`:
Bloqade gives users the flexibility to specify general waveforms by inputting functions. The following code constructs a sinusoidal waveform with a time duration of 2 μs:

```@example waveform
using Bloqade
using PythonCall
plt = pyimport("matplotlib.pyplot")
using Bloqade, Bloqade.CairoMakie
waveform = Waveform(t->2.2*2π*sin(2π*t), duration = 2);
Bloqade.plot(waveform)
```
In our documentation, we use the
python package [`matplotlib`](https://matplotlib.org) for plotting.
In our documentation, we use the [`CairoMakie`](https://docs.makie.org/) for plotting.

Bloqade supports built-in waveforms for convenience (see References below).
For example, the codes below create different waveform shapes with a single line:
Expand Down Expand Up @@ -63,7 +60,9 @@ wf1 = piecewise_linear(;clocks, values=values1);
values2 = 2π*rand(length(clocks)-1)
wf2 = piecewise_constant(;clocks, values=values2);
fig, (ax1, ax2) = plt.subplots(figsize=(12, 4), ncols=2)
fig = Figure(size=(960, 400))
ax1 = Axis(fig[1, 1])
ax2 = Axis(fig[1, 2])
Bloqade.plot!(ax1, wf1)
Bloqade.plot!(ax2, wf2)
fig
Expand Down Expand Up @@ -104,7 +103,9 @@ waveform:
wf = piecewise_linear(clocks=[0.0, 2.0, 3.0, 4.0], values=2π*[0.0, 3.0, 1.1, 2.2]);
swf = smooth(wf;kernel_radius=0.1);
fig, (ax1, ax2) = plt.subplots(figsize=(12, 4), ncols=2)
fig = Figure(size=(960, 400))
ax1 = Axis(fig[1, 1])
ax2 = Axis(fig[1, 2])
Bloqade.plot!(ax1, wf)
Bloqade.plot!(ax2, swf)
fig
Expand All @@ -120,7 +121,9 @@ wf2 = sinusoidal(duration = 2.2, amplitude = 2.2*2π);
wf3 = wf1 + wf2;
wf4 = wf1 - wf2;
fig, (ax1, ax2) = plt.subplots(figsize=(12, 4), ncols=2)
fig = Figure(size=(960, 400))
ax1 = Axis(fig[1, 1])
ax2 = Axis(fig[1, 2])
Bloqade.plot!(ax1, wf3)
Bloqade.plot!(ax2, wf4)
fig
Expand All @@ -133,7 +136,9 @@ To increase the strength of a waveform by some factors, we can directly use `*`:
wf = linear_ramp(;duration=2.2, start_value=0.0, stop_value=1.0*2π);
wf_t = 3 * wf;
fig, (ax1, ax2) = plt.subplots(figsize=(12, 4), ncols=2)
fig = Figure(size=(960, 400))
ax1 = Axis(fig[1, 1])
ax2 = Axis(fig[1, 2])
Bloqade.plot!(ax1, wf)
Bloqade.plot!(ax2, wf_t)
fig
Expand All @@ -144,7 +149,9 @@ Such operations can also be broadcasted by using `.*`:
```@example waveform
wf2, wf3 = [2.0, 3.0] .* wf1;
fig, (ax1, ax2) = plt.subplots(figsize=(12, 4), ncols=2)
fig = Figure(size=(960, 400))
ax1 = Axis(fig[1, 1])
ax2 = Axis(fig[1, 2])
Bloqade.plot!(ax1, wf2)
Bloqade.plot!(ax2, wf3)
fig
Expand Down
1 change: 0 additions & 1 deletion examples/1.blockade/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ BloqadeMIS = "bd27d05e-4ce1-5e74-84dd-c5d7d508bbe2"
BloqadeODE = "bd27d05e-4ce1-5e79-84dd-c5d7d508bbe5"
BloqadeWaveforms = "bd27d05e-4ce1-5e79-84dd-c5d7d508bbe7"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
Yao = "5872b779-8223-5990-8dd0-5abbb0748c8c"
YaoArrayRegister = "e600142f-9330-5003-8abb-0ebd767abc51"
Expand Down
43 changes: 23 additions & 20 deletions examples/1.blockade/main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -345,26 +345,29 @@ for _ in TimeChoiceIterator(integrator2, 0.0:dt:Tmax)
end

# Plot the data:
using PythonCall # Use matplotlib to generate plots
matplotlib = pyimport("matplotlib")
plt = pyimport("matplotlib.pyplot")

ax = plt.subplot(1, 1, 1)
plt.plot(times, real(densities), "k", label = "Full space")
plt.plot(times, real(densities2), "r--", label = "Subspace")
ax.axis([0, Tmax, 0, 0.45])
plt.xlabel("Time (us)")
plt.ylabel("Rydberg density")
plt.tight_layout()
plt.legend()

inset_axes = pyimport("mpl_toolkits.axes_grid1.inset_locator")
ax2 = inset_axes.inset_axes(ax, width = "20%", height = "30%", loc = "lower right", borderpad = 1)
plt.plot(times, real(densities - densities2))
plt.axis([0, 0.5, -0.001, 0.003])
plt.ylabel("Difference", fontsize = 12)
plt.yticks(LinRange(-0.001, 0.003, 5), fontsize = 12);
plt.xticks([0, 0.2, 0.4, 0.6], fontsize = 12);
using Bloqade.CairoMakie # Use CairoMakie to generate plots

fig = Figure()
ax = Axis(fig[1, 1], xlabel = "Time (us)", ylabel = "Rydberg density", limits=(0.0, Tmax, 0.0, 0.45))
lines!(ax, times, real(densities), label = "Full space", color=:black)
lines!(ax, times, real(densities2), label = "Subspace", color=:red, linestyle=:dash)
axislegend(ax, position = :rt)
fig

# The inset axis
ax2 = Axis(fig[1, 1],
width=Relative(0.2),
height=Relative(0.3),
halign=0.9,
valign=0.1,
limits=(0.0, 0.5, -0.001, 0.003),
ylabel="Difference",
yticks=LinRange(-0.001, 0.003, 5),
xticks=[0, 0.2, 0.4, 0.6],
backgroundcolor=:lightgray)

lines!(ax2, times, real(densities - densities2), color = :black)
fig;

# ![RydbergBlockadeSubspace](../../../assets/RydbergBlockadeSubspace.png)

Expand Down
1 change: 0 additions & 1 deletion examples/2.adiabatic/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ BloqadeMIS = "bd27d05e-4ce1-5e74-84dd-c5d7d508bbe2"
BloqadeODE = "bd27d05e-4ce1-5e79-84dd-c5d7d508bbe5"
BloqadeWaveforms = "bd27d05e-4ce1-5e79-84dd-c5d7d508bbe7"
KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77"
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
YaoSubspaceArrayReg = "bd27d05e-4ce1-5e79-84dd-c5d7d508ade2"

[extras]
Expand Down
81 changes: 30 additions & 51 deletions examples/2.adiabatic/main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@
# Let's start by importing the required libraries:

using Bloqade
using PythonCall
using Bloqade.CairoMakie
using KrylovKit
using SparseArrays

plt = pyimport("matplotlib.pyplot");

# # Ground State Properties

# We start by probing the ground state properties of the Rydberg Hamiltonian in a 1D system.
Expand Down Expand Up @@ -59,21 +57,15 @@ end

# To compare, we first plot the density profile when ``\Delta= -2π \times 10`` MHz:

fig, ax = plt.subplots(figsize = (10, 4))
ax.bar(1:nsites, density_g[1, :])
ax.set_xticks(1:nsites)
ax.set_xlabel("Sites")
ax.set_ylabel("Rydberg density")
ax.set_title("Density Profile: 1D Chain, Δ = -2π * 10 MHz")
fig = Figure(size=(800, 320))
ax = Axis(fig[1, 1], xlabel = "Sites", ylabel = "Rydberg density", title = "Density Profile: 1D Chain, Δ = -2π * 10 MHz", xticks = 1:nsites)
barplot!(ax, 1:nsites, density_g[1, :])
fig

# We can see that the Rydberg densities in this case are close to 0 for all sites. In contrast, for ``\Delta= 2π \times 10`` MHz, the density shows a clear ``Z_2`` ordered profile:
fig, ax = plt.subplots(figsize = (10, 4))
ax.bar(1:nsites, density_g[30, :])
ax.set_xticks(1:nsites)
ax.set_xlabel("Sites")
ax.set_ylabel("Rydberg density")
ax.set_title("Density Profile: 1D Chain, Δ = 2π * 10 MHz")
fig = Figure(size=(800, 320))
ax = Axis(fig[1, 1], xlabel = "Sites", ylabel = "Rydberg density", title = "Density Profile: 1D Chain, Δ = 2π * 10 MHz", xticks = 1:nsites)
barplot!(ax, 1:nsites, density_g[30, :])
fig

# More generally, we can plot an order parameter as a function of ``\Delta`` to clearly see the onset of phase transition.
Expand All @@ -83,13 +75,10 @@ order_para = map(1:Δ_step) do ii
return sum(density_g[ii, 1:2:nsites]) - sum(density_g[ii, 2:2:nsites]) # density on odd sites - density on even sites
end

fig, ax = plt.subplots(figsize = (10, 4))
ax.plot/ 2π, order_para)
ax.set_xlabel("Δ/2π (MHz) ")
ax.set_ylabel("Order parameter")
fig = Figure(size=(800, 320))
ax = Axis(fig[1, 1], xlabel = "Δ/2π (MHz)", ylabel = "Order parameter")
lines!(ax, Δ / (2π), order_para)
fig

# From the density profile of ground states and the change in the order parameter, we can observe a phase transition with changing ``\Delta``.
# Below, we show that by slowly changing the parameters of the Hamiltonian, we can follow the trajectory of the ground states and adiabatically evolve the atoms from the ground state to the ``Z_2``
# ordered state.

Expand All @@ -106,13 +95,12 @@ U2 = 2π * 10;
Δ = piecewise_linear(clocks = [0.0, 0.6, 2.1, total_time], values = [U1, U1, U2, U2]);

# We plot the two waveforms:
fig, (ax1, ax2) = plt.subplots(ncols = 2, figsize = (12, 4))
Bloqade.plot!(ax1, Ω)
ax1.set_ylabel("Ω/2π (MHz)")
Bloqade.plot!(ax2, Δ)
ax2.set_ylabel("Δ/2π (MHz)")
fig = Figure(size=(960, 320))
ax1 = Axis(fig[1, 1], ylabel = "Ω/2π (MHz)")
ax2 = Axis(fig[1, 2], ylabel = "Δ/2π (MHz)")
Bloqade.plot!(ax1, Ω / (2π))
Bloqade.plot!(ax2, Δ / (2π))
fig

# We generate the positions for a 1D atomic chain again:

nsites = 9
Expand All @@ -136,19 +124,13 @@ densities = []
for _ in TimeChoiceIterator(integrator, 0.0:1e-3:total_time)
push!(densities, rydberg_density(reg))
end
D = hcat(densities...);

# and finally plot the time-dependent dynamics of Rydberg density for each site:
fig, ax = plt.subplots(figsize = (10, 4))
shw = ax.imshow(real(D), interpolation = "nearest", aspect = "auto", extent = [0, total_time, 0.5, nsites + 0.5])
ax.set_xlabel("time (μs)")
ax.set_ylabel("site")
ax.set_xticks(0:0.2:total_time)
ax.set_yticks(1:nsites)
bar = fig.colorbar(shw)
fig
D = hcat(densities...)';

# We can clearly see that a ``Z_2`` ordered state has been generated by the specified adiabatic pulse sequence.
fig = Figure(size=(800, 320))
ax = Axis(fig[1, 1], xlabel = "time (μs)", ylabel = "site", xticks=0:0.2:total_time, yticks=(0.5:1:nsites, string.(1:nsites)))
shw = heatmap!(ax, LinRange(0.0, total_time, size(D, 1)), LinRange(0.5, nsites - 0.5, size(D, 2)), real(D))
Colorbar(fig[1, 2], shw, label = "Rydberg density")
fig
# We can also confirm it by plotting the bitstring distribution at the final time step:

bitstring_hist(reg; nlargest = 20)
Expand Down Expand Up @@ -194,11 +176,11 @@ total_time = 2.9
U = 2π * 15.0
Δ = piecewise_linear(clocks = [0.0, 0.3, 2.6, total_time], values = [-U, -U, U, U]);

fig, (ax1, ax2) = plt.subplots(ncols = 2, figsize = (10, 4))
fig = Figure(size=(800, 320))
ax1 = Axis(fig[1, 1], ylabel = "Ω/2π (MHz)")
ax2 = Axis(fig[1, 2], ylabel = "Δ/2π (MHz)")
Bloqade.plot!(ax1, Ω)
ax1.set_ylabel("Ω/2π (MHz)")
Bloqade.plot!(ax2, Δ)
ax2.set_ylabel("Δ/2π (MHz)")
fig

# Then, we use the waveforms and atom positions to create a Hamiltonian and define a time evolution problem:
Expand All @@ -213,13 +195,10 @@ densities = [];
for _ in TimeChoiceIterator(integrator, 0.0:1e-3:total_time)
push!(densities, rydberg_density(reg))
end
D = hcat(densities...)

fig, ax = plt.subplots(figsize = (10, 4))
shw = ax.imshow(real(D), interpolation = "nearest", aspect = "auto", extent = [0, total_time, 0.5, nsites + 0.5])
ax.set_xlabel("time (μs)")
ax.set_ylabel("site")
ax.set_xticks(0:0.2:total_time)
ax.set_yticks(1:nsites)
bar = fig.colorbar(shw)
D = hcat(densities...)'

fig = Figure(size=(800, 320))
ax = Axis(fig[1, 1], xlabel = "time (μs)", ylabel = "site", xticks=0:0.2:total_time, yticks=(0.5:1:nsites, string.(1:nsites)))
shw = heatmap!(ax, LinRange(0.0, total_time, size(D, 1)), LinRange(0.5, nsites - 0.5, size(D, 2)), real(D))
Colorbar(fig[1, 2], shw, label = "Rydberg density")
fig
3 changes: 1 addition & 2 deletions examples/3.quantum-scar/Project.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
Bloqade = "bd27d05e-4ce1-5e79-84dd-c5d7d508bbe1"
BloqadeExpr = "bd27d05e-4ce1-5e79-84dd-c5d7d508abe2"
BloqadeKrylov = "bd27d05e-4cd1-5e79-84dd-c5d7d508ade2"
BloqadeLattices = "bd27d05e-4ce1-5e79-84dd-c5d7d508bbe4"
BloqadeMIS = "bd27d05e-4ce1-5e74-84dd-c5d7d508bbe2"
BloqadeODE = "bd27d05e-4ce1-5e79-84dd-c5d7d508bbe5"
BloqadeWaveforms = "bd27d05e-4ce1-5e79-84dd-c5d7d508bbe7"
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
Yao = "5872b779-8223-5990-8dd0-5abbb0748c8c"
YaoArrayRegister = "e600142f-9330-5003-8abb-0ebd767abc51"
Expand Down
Loading

0 comments on commit d86cccc

Please sign in to comment.