Skip to content

Commit d6fda72

Browse files
committed
fix Bloch docstrings and improve visualization of the sphere
1 parent 22efb11 commit d6fda72

File tree

4 files changed

+104
-130
lines changed

4 files changed

+104
-130
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
- Introduce `Lanczos` solver for `spectrum`. ([#476])
1111
- Add Bloch-Redfield master equation solver. ([#473])
12-
- Implement Bloch Sphere rendering and align style with qutip. ([#472], [#480], [#485])
12+
- Implement Bloch Sphere rendering and align style with qutip. ([#472], [#480], [#485], [#487])
1313
- Add `Base.copy` method for `AbstractQuantumObject`. ([#486])
1414

1515
## [v0.31.1]
@@ -239,3 +239,4 @@ Release date: 2024-11-13
239239
[#480]: https://github.com/qutip/QuantumToolbox.jl/issues/480
240240
[#485]: https://github.com/qutip/QuantumToolbox.jl/issues/485
241241
[#486]: https://github.com/qutip/QuantumToolbox.jl/issues/486
242+
[#487]: https://github.com/qutip/QuantumToolbox.jl/issues/487

docs/src/users_guide/plotting_the_bloch_sphere.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ In [`QuantumToolbox`](https://qutip.org/QuantumToolbox.jl/), this can be done us
1717

1818
In [`QuantumToolbox`](https://qutip.org/QuantumToolbox.jl/), creating a [`Bloch`](@ref) sphere is accomplished by calling either:
1919

20+
!!! note "Import plotting libraries"
21+
Remember to import plotting libraries first. Here, we demonstrate the functionalities with [`CairoMakie.jl`](https://docs.makie.org/stable/explanations/backends/cairomakie.html).
22+
2023
```@example Bloch_sphere_rendering
2124
b = Bloch()
2225
```
@@ -172,7 +175,7 @@ At the end of the last section we saw that the colors and marker shapes of the d
172175
| `b.lines` | Lines to draw on the sphere (points, style, properties) | `Vector{Tuple{Vector{Vector{Float64}},String}}()` (empty) |
173176
| `b.arcs` | Arcs to draw on the sphere | `Vector{Vector{Vector{Float64}}}()` (empty) |
174177
| `b.font_color` | Color of axis labels and text | `"black"` |
175-
| `b.font_size` | Font size for labels | `15` |
178+
| `b.font_size` | Font size for labels | `20` |
176179
| `b.frame_alpha` | Transparency of the frame background | `0.1` |
177180
| `b.frame_color` | Background color of the frame | `"gray"` |
178181
| `b.frame_limit` | Axis limits for the 3D frame (symmetric around origin) | `1.2` |

ext/QuantumToolboxMakieExt.jl

Lines changed: 95 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ import Makie:
3434
update_cam!,
3535
cam3d!
3636

37-
import Makie.GeometryBasics: Tessellation
38-
3937
@doc raw"""
4038
plot_wigner(
4139
library::Val{:Makie},
@@ -339,10 +337,7 @@ Render the Bloch sphere visualization from the given [`Bloch`](@ref) object `b`.
339337
# Arguments
340338
341339
- `b::Bloch`: The Bloch sphere object containing states, vectors, and settings to visualize.
342-
- `location`: Specifies where to display or save the rendered figure.
343-
- If `nothing` (default), the figure is displayed interactively.
344-
- If a file path (String), the figure is saved to the specified location.
345-
- Other values depend on backend support.
340+
- `location::Union{GridPosition,Nothing}`: The location of the plot in the layout. If `nothing`, the plot is created in a new figure. Default is `nothing`.
346341
347342
# Returns
348343
@@ -351,13 +346,14 @@ Render the Bloch sphere visualization from the given [`Bloch`](@ref) object `b`.
351346
function QuantumToolbox.render(b::Bloch; location = nothing)
352347
fig, lscene = _setup_bloch_plot!(b, location)
353348
_draw_bloch_sphere!(b, lscene)
354-
_draw_reference_circles!(b, lscene)
355-
_draw_axes!(b, lscene)
349+
_add_labels!(b, lscene)
350+
351+
# plot data fields in Bloch
356352
_plot_points!(b, lscene)
357353
_plot_lines!(b, lscene)
358354
_plot_arcs!(b, lscene)
359355
_plot_vectors!(b, lscene)
360-
_add_labels!(b, lscene)
356+
361357
return fig, lscene
362358
end
363359

@@ -383,15 +379,15 @@ function _setup_bloch_plot!(b::Bloch, location)
383379
cam3d!(lscene.scene, center = false)
384380
cam = cameracontrols(lscene)
385381
cam.fov[] = 12 # Set field of view to 12 degrees
386-
dist = 12 # Set distance from the camera to the Bloch sphere
382+
dist = 12 # Set distance from the camera to the Bloch sphere
387383
update_cam!(lscene.scene, cam, deg2rad(b.view[1]), deg2rad(b.view[2]), dist)
388384
return fig, lscene
389385
end
390386

391387
raw"""
392-
_draw_bloch_sphere!(b, lscene)
388+
_draw_bloch_sphere!(b::Bloch, lscene)
393389
394-
Draw the translucent sphere representing the Bloch sphere surface.
390+
Draw the translucent sphere, axes, and reference circles representing the Bloch sphere surface.
395391
"""
396392
function _draw_bloch_sphere!(b::Bloch, lscene)
397393
radius = 1.0f0
@@ -405,69 +401,114 @@ function _draw_bloch_sphere!(b::Bloch, lscene)
405401
transparency = true,
406402
rasterize = 3,
407403
)
408-
θ_vals = range(0, π, 5)[1:(end-1)]
404+
405+
# X, Y, and Z axes
406+
axes = [
407+
[Point3f(1.0, 0, 0), Point3f(-1.0, 0, 0)], # X-axis
408+
[Point3f(0, 1.0, 0), Point3f(0, -1.0, 0)], # Y-axis
409+
[Point3f(0, 0, 1.0), Point3f(0, 0, -1.0)], # Z-axis
410+
]
411+
for points in axes
412+
lines!(lscene, points; color = b.frame_color)
413+
end
414+
415+
# highlight circles for XY and XZ planes
416+
φ = range(0, 2π, length = 100)
417+
lines!(lscene, [Point3f(cos(φi), sin(φi), 0) for φi in φ]; color = b.frame_color, linewidth = 1.0) # XY
418+
lines!(lscene, [Point3f(cos(φi), 0, sin(φi)) for φi in φ]; color = b.frame_color, linewidth = 1.0) # XZ
419+
420+
# other curves of longitude (with polar angle φ and azimuthal angle θ)
409421
φ_curve = range(0, 2π, 600)
422+
θ_vals = [1, 2, 3] * π / 4
410423
for θi in θ_vals
411424
x_line = radius * sin.(φ_curve) .* cos(θi)
412425
y_line = radius * sin.(φ_curve) .* sin(θi)
413426
z_line = radius * cos.(φ_curve)
414427
lines!(lscene, x_line, y_line, z_line; color = b.frame_color, alpha = b.frame_alpha)
415428
end
416-
φ_vals = range(0, π, 6)
429+
430+
# other curves of latitude (with polar angle φ and azimuthal angle θ)
431+
φ_vals = [1, 3] * π / 4 # missing `2` because XY plane has already be handled above
417432
θ_curve = range(0, 2π, 600)
418433
for ϕ in φ_vals
419434
x_ring = radius * sin(ϕ) .* cos.(θ_curve)
420435
y_ring = radius * sin(ϕ) .* sin.(θ_curve)
421436
z_ring = fill(radius * cos(ϕ), length(θ_curve))
422437
lines!(lscene, x_ring, y_ring, z_ring; color = b.frame_color, alpha = b.frame_alpha)
423438
end
439+
return nothing
424440
end
425441

426442
raw"""
427-
_draw_reference_circles!(b::Bloch, lscene)
443+
_add_labels!(b::Bloch, lscene)
428444
429-
Draw the three great circles `(XY, XZ planes)` on the Bloch sphere.
445+
Add axis labels and state labels to the Bloch sphere.
430446
431447
# Arguments
432-
- `b::Bloch`: Bloch sphere object containing frame color
433-
- `lscene`: Makie LScene object for drawing
448+
- `lscene`: LScene object for text placement
434449
435-
Adds faint circular guidelines representing the three principal planes.
450+
Positions standard labels `(x, y, |0⟩, |1⟩)` at appropriate locations.
436451
"""
437-
function _draw_reference_circles!(b::Bloch, lscene)
438-
wire_color = b.frame_color
439-
φ = range(0, 2π, length = 100)
440-
# XY, XZ circles
441-
circles = [
442-
[Point3f(cos(φi), sin(φi), 0) for φi in φ], # XY
443-
[Point3f(cos(φi), 0, sin(φi)) for φi in φ], # XZ
444-
]
445-
for circle in circles
446-
lines!(lscene, circle; color = wire_color, linewidth = 1.0)
447-
end
448-
end
449-
450-
raw"""
451-
_draw_axes!(b::Bloch, lscene)
452-
453-
Draw the three principal axes `(x, y, z)` of the Bloch sphere.
452+
function _add_labels!(b::Bloch, lscene)
453+
length(b.xlabel) == 2 || throw(ArgumentError("The length of `Bloch.xlabel` must be 2."))
454+
length(b.ylabel) == 2 || throw(ArgumentError("The length of `Bloch.ylabel` must be 2."))
455+
length(b.zlabel) == 2 || throw(ArgumentError("The length of `Bloch.zlabel` must be 2."))
456+
length(b.xlpos) == 2 || throw(ArgumentError("The length of `Bloch.xlpos` must be 2."))
457+
length(b.ylpos) == 2 || throw(ArgumentError("The length of `Bloch.ylpos` must be 2."))
458+
length(b.zlpos) == 2 || throw(ArgumentError("The length of `Bloch.zlpos` must be 2."))
454459

455-
# Arguments
456-
- `b::Bloch`: Bloch sphere object containing axis color
457-
- `lscene`: Makie LScene object for drawing
460+
label_color = parse(RGBf, b.font_color)
461+
label_size = b.font_size
458462

459-
Creates visible axis lines extending slightly beyond the unit sphere.
460-
"""
461-
function _draw_axes!(b::Bloch, lscene)
462-
axis_color = b.frame_color
463-
axes = [
464-
[Point3f(1.0, 0, 0), Point3f(-1.0, 0, 0)], # X-axis
465-
[Point3f(0, 1.0, 0), Point3f(0, -1.0, 0)], # Y-axis
466-
[Point3f(0, 0, 1.0), Point3f(0, 0, -1.0)], # Z-axis
467-
]
468-
for points in axes
469-
lines!(lscene, points; color = axis_color)
470-
end
463+
(b.xlabel[1] == "") || text!(
464+
lscene,
465+
b.xlabel[1],
466+
position = Point3f(b.xlpos[1], 0, 0),
467+
color = label_color,
468+
fontsize = label_size,
469+
align = (:center, :center),
470+
)
471+
(b.xlabel[2] == "") || text!(
472+
lscene,
473+
b.xlabel[2],
474+
position = Point3f(b.xlpos[2], 0, 0),
475+
color = label_color,
476+
fontsize = label_size,
477+
align = (:center, :center),
478+
)
479+
(b.ylabel[1] == "") || text!(
480+
lscene,
481+
b.ylabel[1],
482+
position = Point3f(0, b.ylpos[1], 0),
483+
color = label_color,
484+
fontsize = label_size,
485+
align = (:center, :center),
486+
)
487+
(b.ylabel[2] == "") || text!(
488+
lscene,
489+
b.ylabel[2],
490+
position = Point3f(0, b.ylpos[2], 0),
491+
color = label_color,
492+
fontsize = label_size,
493+
align = (:center, :center),
494+
)
495+
(b.zlabel[1] == "") || text!(
496+
lscene,
497+
b.zlabel[1],
498+
position = Point3f(0, 0, b.zlpos[1]),
499+
color = label_color,
500+
fontsize = label_size,
501+
align = (:center, :center),
502+
)
503+
(b.zlabel[2] == "") || text!(
504+
lscene,
505+
b.zlabel[2],
506+
position = Point3f(0, 0, b.zlpos[2]),
507+
color = label_color,
508+
fontsize = label_size,
509+
align = (:center, :center),
510+
)
511+
return nothing
471512
end
472513

473514
raw"""
@@ -540,6 +581,7 @@ function _plot_points!(b::Bloch, lscene)
540581
lines!(lscene, xs, ys, zs; color = c, linewidth = 2.0, transparency = alpha < 1.0, alpha = alpha)
541582
end
542583
end
584+
return nothing
543585
end
544586

545587
raw"""
@@ -571,6 +613,7 @@ function _plot_lines!(b::Bloch, lscene)
571613
end
572614
lines!(lscene, x, y, z; color = color, linewidth = 1.0, linestyle = linestyle)
573615
end
616+
return nothing
574617
end
575618

576619
raw"""
@@ -599,6 +642,7 @@ function _plot_arcs!(b::Bloch, lscene)
599642
arc_points = [Point3f((v1 * cos(t) + cross(n, v1) * sin(t))) for t in t_range]
600643
lines!(lscene, arc_points; color = RGBAf(0.8, 0.4, 0.1, 0.9), linewidth = 2.0, linestyle = :solid)
601644
end
645+
return nothing
602646
end
603647

604648
raw"""
@@ -633,77 +677,6 @@ function _plot_vectors!(b::Bloch, lscene)
633677
rasterize = 3,
634678
)
635679
end
636-
end
637-
638-
raw"""
639-
_add_labels!(lscene)
640-
641-
Add axis labels and state labels to the Bloch sphere.
642-
643-
# Arguments
644-
- `lscene`: LScene object for text placement
645-
646-
Positions standard labels `(x, y, |0⟩, |1⟩)` at appropriate locations.
647-
"""
648-
function _add_labels!(b::Bloch, lscene)
649-
length(b.xlabel) == 2 || throw(ArgumentError("The length of `Bloch.xlabel` must be 2."))
650-
length(b.ylabel) == 2 || throw(ArgumentError("The length of `Bloch.ylabel` must be 2."))
651-
length(b.zlabel) == 2 || throw(ArgumentError("The length of `Bloch.zlabel` must be 2."))
652-
length(b.xlpos) == 2 || throw(ArgumentError("The length of `Bloch.xlpos` must be 2."))
653-
length(b.ylpos) == 2 || throw(ArgumentError("The length of `Bloch.ylpos` must be 2."))
654-
length(b.zlpos) == 2 || throw(ArgumentError("The length of `Bloch.zlpos` must be 2."))
655-
656-
label_color = parse(RGBf, b.font_color)
657-
label_size = b.font_size
658-
659-
(b.xlabel[1] == "") || text!(
660-
lscene,
661-
b.xlabel[1],
662-
position = Point3f(b.xlpos[1], 0, 0),
663-
color = label_color,
664-
fontsize = label_size,
665-
align = (:center, :center),
666-
)
667-
(b.xlabel[2] == "") || text!(
668-
lscene,
669-
b.xlabel[2],
670-
position = Point3f(b.xlpos[2], 0, 0),
671-
color = label_color,
672-
fontsize = label_size,
673-
align = (:center, :center),
674-
)
675-
(b.ylabel[1] == "") || text!(
676-
lscene,
677-
b.ylabel[1],
678-
position = Point3f(0, b.ylpos[1], 0),
679-
color = label_color,
680-
fontsize = label_size,
681-
align = (:center, :center),
682-
)
683-
(b.ylabel[2] == "") || text!(
684-
lscene,
685-
b.ylabel[2],
686-
position = Point3f(0, b.ylpos[2], 0),
687-
color = label_color,
688-
fontsize = label_size,
689-
align = (:center, :center),
690-
)
691-
(b.zlabel[1] == "") || text!(
692-
lscene,
693-
b.zlabel[1],
694-
position = Point3f(0, 0, b.zlpos[1]),
695-
color = label_color,
696-
fontsize = label_size,
697-
align = (:center, :center),
698-
)
699-
(b.zlabel[2] == "") || text!(
700-
lscene,
701-
b.zlabel[2],
702-
position = Point3f(0, 0, b.zlpos[2]),
703-
color = label_color,
704-
fontsize = label_size,
705-
align = (:center, :center),
706-
)
707680
return nothing
708681
end
709682

src/visualization.jl

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ A structure representing a Bloch sphere visualization for quantum states.
8080
## Style properties
8181
8282
- `font_color::String`: Color of axis labels and text
83-
- `font_size::Int`: Font size for labels. Default: `15`
83+
- `font_size::Int`: Font size for labels. Default: `20`
8484
- `frame_alpha::Float64`: Transparency of the wireframe
8585
- `frame_color::String`: Color of the wireframe
8686
@@ -122,7 +122,7 @@ A structure representing a Bloch sphere visualization for quantum states.
122122
lines::Vector{Tuple{Vector{Vector{Float64}},String}} = Vector{Tuple{Vector{Vector{Float64}},String}}()
123123
arcs::Vector{Vector{Vector{Float64}}} = Vector{Vector{Vector{Float64}}}()
124124
font_color::String = "black"
125-
font_size::Int = 15
125+
font_size::Int = 20
126126
frame_alpha::Float64 = 0.1
127127
frame_color::String = "gray"
128128
point_default_color::Vector{String} = ["blue", "red", "green", "#CC6600"]
@@ -515,10 +515,7 @@ Render the Bloch sphere visualization from the given [`Bloch`](@ref) object `b`.
515515
# Arguments
516516
517517
- `b::Bloch`: The Bloch sphere object containing states, vectors, and settings to visualize.
518-
- `location`: Specifies where to display or save the rendered figure.
519-
- If `nothing` (default), the figure is displayed interactively.
520-
- If a file path (String), the figure is saved to the specified location.
521-
- Other values depend on backend support.
518+
- `location::Union{GridPosition,Nothing}`: The location of the plot in the layout. If `nothing`, the plot is created in a new figure. Default is `nothing`.
522519
523520
# Returns
524521

0 commit comments

Comments
 (0)