Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Introduce `Lanczos` solver for `spectrum`. ([#476])
- Add Bloch-Redfield master equation solver. ([#473])
- Implement Bloch Sphere rendering. ([#472])
- Implement Bloch Sphere rendering and align style with qutip. ([#472], [#480])

## [v0.31.1]
Release date: 2025-05-16
Expand Down Expand Up @@ -235,3 +235,4 @@ Release date: 2024-11-13
[#472]: https://github.com/qutip/QuantumToolbox.jl/issues/472
[#473]: https://github.com/qutip/QuantumToolbox.jl/issues/473
[#476]: https://github.com/qutip/QuantumToolbox.jl/issues/476
[#480]: https://github.com/qutip/QuantumToolbox.jl/issues/480
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
IncompleteLU = "40713840-3770-5561-ab4c-a76e7d0d7895"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
OrdinaryDiffEqCore = "bbf590c4-e513-4bbe-9b18-05decba2e5d8"
Expand Down Expand Up @@ -51,6 +52,7 @@ GPUArrays = "10, 11"
Graphs = "1.7"
IncompleteLU = "0.2"
KernelAbstractions = "0.9.2"
LaTeXStrings = "1.2"
LinearAlgebra = "1"
LinearSolve = "2, 3"
Makie = "0.20, 0.21, 0.22"
Expand Down
6 changes: 3 additions & 3 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ end
DocMeta.setdocmeta!(QuantumToolbox, :DocTestSetup, doctest_setup; recursive = true)

# some options for `makedocs`
const DRAFT = false # set `true` to disable cell evaluation
const DOCTEST = true # set `false` to skip doc tests
const DRAFT = get(ENV, "DRAFT", false) == true # set `true` to disable cell evaluation
const DOCTEST = get(ENV, "DOCTEST", true) == false # set `false` to skip doc tests

# generate bibliography
bib = CitationBibliography(
Expand Down Expand Up @@ -51,7 +51,6 @@ const PAGES = [
],
"Manipulating States and Operators" => "users_guide/states_and_operators.md",
"Tensor Products and Partial Traces" => "users_guide/tensor.md",
"Plotting on the Bloch Sphere" => "users_guide/plotting_the_bloch_sphere.md",
"Time Evolution and Dynamics" => [
"Introduction" => "users_guide/time_evolution/intro.md",
"Time Evolution Solutions" => "users_guide/time_evolution/solution.md",
Expand All @@ -65,6 +64,7 @@ const PAGES = [
"Hierarchical Equations of Motion" => "users_guide/HEOM.md",
"Solving for Steady-State Solutions" => "users_guide/steadystate.md",
"Two-time correlation functions" => "users_guide/two_time_corr_func.md",
"Plotting on the Bloch Sphere" => "users_guide/plotting_the_bloch_sphere.md",
"QuantumToolbox Settings" => "users_guide/settings.md",
"Extensions" => [
"Extension for CUDA.jl" => "users_guide/extensions/cuda.md",
Expand Down
11 changes: 8 additions & 3 deletions docs/src/resources/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,13 +319,18 @@ meshgrid
```@docs
plot_wigner
plot_fock_distribution
plot_bloch
```

### [Bloch Sphere](@id doc-API:Bloch-Sphere)

```@docs
Bloch
plot_bloch
render
add_points!
add_vectors!
add_line!
add_arc!
clear!
add_states!
```
clear!
```
149 changes: 96 additions & 53 deletions docs/src/users_guide/plotting_the_bloch_sphere.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,61 +7,65 @@ using CairoMakie
CairoMakie.enable_only_mime!(MIME"image/svg+xml"())
```

## [Introduction](@id doc:Bloch_sphere_rendering)
## Introduction

When studying the dynamics of a two-level system, it's often convenient to visualize the state of the system by plotting the state vector or density matrix on the Bloch sphere.

In [QuantumToolbox.jl](https://qutip.org/QuantumToolbox.jl/), this can be done using the [`Bloch`](@ref) or [`plot_bloch`](@ref) methods that provide same syntax as [QuTiP](https://qutip.readthedocs.io/en/stable/guide/guide-bloch.html).
In [`QuantumToolbox`](https://qutip.org/QuantumToolbox.jl/), this can be done using the [`Bloch`](@ref) or [`plot_bloch`](@ref) methods that provide same syntax as [QuTiP](https://qutip.readthedocs.io/en/stable/guide/guide-bloch.html).

## Create a Bloch Sphere

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

```@example Bloch_sphere_rendering
b = Bloch();
b = Bloch()
```

which will load an instance of [`Bloch`](@ref). Before getting into the details of these objects, we can simply plot the blank [`Bloch`](@ref) sphere associated with these instances via:

```@example Bloch_sphere_rendering
fig, _ = render(b);
fig, _ = render(b)
fig
```

## Add a Single Data Point
See the [API documentation for Bloch sphere](@ref doc-API:Bloch-Sphere) for a full list of other available functions.

## Add a single data point

As an example, we can add a single data point via [`add_points!`](@ref):

```@example Bloch_sphere_rendering
pnt = [1 / sqrt(3), 1 / sqrt(3), 1 / sqrt(3)];
add_points!(b, pnt);
fig, _ = render(b);
pnt = [1 / sqrt(3), 1 / sqrt(3), 1 / sqrt(3)]
add_points!(b, pnt)
fig, _ = render(b)
fig
```

## Add a Single Vector
## Add a single vector

and then a single vector via [`add_vectors!`](@ref):
Add a single vector via [`add_vectors!`](@ref):

```@example Bloch_sphere_rendering
vec = [0, 1, 0];
vec = [0, 1, 0]
add_vectors!(b, vec)
fig, _ = render(b)
fig
```

and then add another vector corresponding to the ``|0\rangle`` state:
## Add a single quantum state

Add another vector corresponding to the ``|0\rangle`` state:

```@example Bloch_sphere_rendering
x = basis(2, 0)
add_states!(b, [x])
z0 = basis(2, 0)
add_states!(b, z0)
fig, _ = render(b)
fig
```

## Add Multiple Vectors
## Add multiple data

We can also plot multiple points, vectors, and states at the same time by passing arrays instead of individual elements via [`add_vectors!](@ref). Before giving an example, we can use [`clear!`](@ref) to remove the current data from our [`Bloch`](@ref) sphere instead of creating a new instance:
We can also plot multiple points, vectors, and states at the same time by passing arrays instead of individual elements via [`add_points!`](@ref), [`add_vectors!`](@ref), and [`add_states!`](@ref), respectively. Before giving an example, we can use [`clear!`](@ref) to remove the current data from our [`Bloch`](@ref) sphere instead of creating a new instance:

```@example Bloch_sphere_rendering
clear!(b)
Expand All @@ -73,14 +77,16 @@ Now on the same [`Bloch`](@ref) sphere, we can plot the three states via [`add_s

```@example Bloch_sphere_rendering
x = basis(2, 0) + basis(2, 1)
y = basis(2, 0) - im * basis(2, 1)
y = basis(2, 0) + im * basis(2, 1)
z = basis(2, 0)
b = Bloch()
add_states!(b, [x, y, z])
fig, _ = render(b)
fig
```

!!! note "State normalization"
The function [`add_states!`](@ref) will automatically normalize the given quantum state(s), while [`add_vectors!`](@ref) does not normalize the given vectors.

A similar method works for adding vectors:

```@example Bloch_sphere_rendering
Expand All @@ -91,70 +97,107 @@ fig, _ = render(b)
fig
```

# Add Arc, Line, and Vector
# Add lines and arcs

You can also add lines and arcs via [`add_line!`](@ref) and [`add_arc!`](@ref) respectively:

```@example Bloch_sphere_rendering
clear!(b)
vec = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
add_vectors!(b, vec);
add_line!(b, [1,0,0], [0,1,0])
add_arc!(b, [1, 0, 0], [0, 1, 0], [0, 0, 1])
add_line!(b, x, y)
add_arc!(b, y, z)
fig, _ = render(b)
fig
```

## Add Multiple Points
## Add multiple points

Adding multiple points to the [`Bloch`](@ref) sphere works slightly differently than adding multiple states or vectors. For example, lets add a set of `20` points around the equator (after calling [`clear!`](@ref)):

```@example Bloch_sphere_rendering
th = range(0, 2π; length=20);
clear!(b)
xp = cos.(th);
yp = sin.(th);
zp = zeros(20);
pnts = [xp, yp, zp];
add_points!(b, pnts);
fig, ax = render(b);

th = LinRange(0, 2π, 20)
xp = cos.(th)
yp = sin.(th)
zp = zeros(20)
pnts = [xp, yp, zp]
add_points!(b, pnts)
fig, ax = render(b)
fig
```

Notice that, in contrast to states or vectors, each point remains the same color as the initial point. This is because adding multiple data points using [`add_points!`](@ref) is interpreted, by default, to correspond to a single data point (single qubit state) plotted at different times. This is very useful when visualizing the dynamics of a qubit. If we want to plot additional qubit states we can call additional [`add_points!`](@ref):

## Add Another Set of Points
Notice that, in contrast to states or vectors, each point remains the same color as the initial point. This is because adding multiple data points using [`add_points!`](@ref) is interpreted, by default, to correspond to a single data point (single qubit state) plotted at different times. This is very useful when visualizing the dynamics of a qubit. If we want to plot additional qubit states we can call additional [`add_points!`](@ref) function:

```@example Bloch_sphere_rendering
xz = zeros(20);
yz = sin.(th);
zz = cos.(th);
pnts = [xz, yz, zz];
add_points!(b, pnts);
fig, ax = render(b);
xz = zeros(20)
yz = sin.(th)
zz = cos.(th)
add_points!(b, [xz, yz, zz])
fig, ax = render(b)
fig
```

The color and shape of the data points is varied automatically by [`Bloch`](@ref). Notice how the color and point markers change for each set of data.
The color and shape of the data points is varied automatically by [`Bloch`](@ref). Notice how the color and point markers change for each set of data. Again, we have had to call [`add_points!`](@ref) twice because adding more than one set of multiple data points is not supported by the [`add_points!`](@ref) function.

What if we want to vary the color of our points. We can tell [`Bloch`](@ref) to vary the color of each point according to the colors listed in the `point_color` attribute.
What if we want to vary the color of our points. We can tell [`Bloch`](@ref) to vary the color of each point according to the colors listed in the `point_color` field (see [Configuring the Bloch sphere](@ref doc:Configuring-the-Bloch-sphere) below). Again, after [`clear!`](@ref):

```@example Bloch_sphere_rendering
clear!(b)
xp = cos.(th);
yp = sin.(th);
zp = zeros(20);
pnts = [xp, yp, zp];
add_points!(b, pnts, meth=:m);
fig, ax = render(b);

xp = cos.(th)
yp = sin.(th)
zp = zeros(20)
pnts = [xp, yp, zp]
add_points!(b, pnts, meth=:m) # add `meth=:m` to signify 'multi' colored points
fig, ax = render(b)
fig
```

Now, the data points cycle through a variety of predefined colors. Now lets add another set of points, but this time we want the set to be a single color, representing say a qubit going from the ``|0\rangle`` state to the ``|1\rangle`` state in the `y-z` plane:

```@example Bloch_sphere_rendering
pnts = [xz, yz, zz] ;
add_points!(b, pnts);
fig, ax = render(b);
pnts = [xz, yz, zz]
add_points!(b, pnts) # no `meth=:m`
fig, ax = render(b)
fig
```

## [Configuring the Bloch sphere](@id doc:Configuring-the-Bloch-sphere)

At the end of the last section we saw that the colors and marker shapes of the data plotted on the Bloch sphere are automatically varied according to the number of points and vectors added. But what if you want a different choice of color, or you want your sphere to be purple with different axes labels? Well then you are in luck as the Bloch class has many attributes which one can control. Assuming `b = Bloch()`:

| **Field** | **Description** | **Default setting** |
|:----------|:----------------|:--------------------|
| `b.points` | Points to plot on the Bloch sphere (3D coordinates) | `Vector{Matrix{Float64}}()` (empty) |
| `b.vectors` | Vectors to plot on the Bloch sphere | `Vector{Vector{Float64}}()` (empty) |
| `b.lines` | Lines to draw on the sphere (points, style, properties) | `Vector{Tuple{Vector{Vector{Float64}},String}}()` (empty) |
| `b.arcs` | Arcs to draw on the sphere | `Vector{Vector{Vector{Float64}}}()` (empty) |
| `b.font_color` | Color of axis labels and text | `"black"` |
| `b.font_size` | Font size for labels | `15` |
| `b.frame_alpha` | Transparency of the frame background | `0.1` |
| `b.frame_color` | Background color of the frame | `"gray"` |
| `b.frame_limit` | Axis limits for the 3D frame (symmetric around origin) | `1.2` |
| `b.point_default_color` | Default color cycle for points | `["blue", "red", "green", "#CC6600"]` |
| `b.point_color` | List of colors for Bloch point markers to cycle through | `Union{Nothing,String}[]` |
| `b.point_marker` | List of point marker shapes to cycle through | `[:circle, :rect, :diamond, :utriangle]` |
| `b.point_size` | List of point marker sizes (not all markers look the same size when plotted) | `[5.5, 6.2, 6.5, 7.5]` |
| `b.point_style` | List of marker styles | `Symbol[]` |
| `b.point_alpha` | List of marker transparencies | `Float64[]` |
| `b.sphere_color` | Color of Bloch sphere surface | `0.2` |
| `b.sphere_alpha` | Transparency of sphere surface | `"#FFDDDD"` |
| `b.vector_color` | Colors for vectors | `["green", "#CC6600", "blue", "red"]` |
| `b.vector_width` | Width of vectors | `0.025` |
| `b.vector_arrowsize` | Arrow size parameters as (head length, head width, stem width) | `[0.07, 0.08, 0.08]` |
| `b.view` | Azimuthal and elevation viewing angles in degrees | `[30, 30]` |
| `b.xlabel` | Labels for x-axis | `[L"x", ""]` (``+x`` and ``-x``) |
| `b.xlpos` | Positions of x-axis labels | `[1.0, -1.0]` |
| `b.ylabel` | Labels for y-axis | `[L"y", ""]` (``+y`` and ``-y``) |
| `b.ylpos` | Positions of y-axis labels | `[1.0, -1.0]` |
| `b.zlabel` | Labels for z-axis | `[L"\|0\rangle", L"\|1\rangle]"` (``+z`` and ``-z``) |
| `b.zlpos` | Positions of z-axis labels | `[1.0, -1.0]` |

These properties can also be accessed via the `print` command:

```@example Bloch_sphere_rendering
b = Bloch()
print(b)
```
Loading
Loading