Skip to content

Commit b6214f5

Browse files
committed
Move tutorials and how-tos to literate folder
1 parent 7fec43c commit b6214f5

File tree

13 files changed

+213
-0
lines changed

13 files changed

+213
-0
lines changed

docs/src/literate/howots/custom.jl

Whitespace-only changes.

docs/src/literate/howots/gpu.jl

Whitespace-only changes.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# # Block Diagonal Operator
2+
include("../../util.jl") #hide
3+
# This operator represents a block-diagonal matrix out of given operators.
4+
# One can also provide a single-operator and a number of blocks. In that case the given operator is repeated for each block.
5+
# In the case of stateful operators, one can supply a method for copying the operators.
6+
blocks = N
7+
ops = [WeightingOp(fill(i % 2, N)) for i = 1:N]
8+
dop = DiagOp(ops)
9+
typeof(dop)
10+
11+
# We can retrieve the operators:
12+
dop.ops
13+
14+
# And visualize the result:
15+
fig = Figure()
16+
plot_image(fig[1,1], image, title = "Image")
17+
plot_image(fig[1,2], reshape(dop * vec(image), N, N), title = "Block Weighted")
18+
resize_to_layout!(fig)
19+
fig

docs/src/literate/tutorials/fft.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# # Fourier Operator
2+
include("../../util.jl") #hide
3+
# The Fourier operator and its related operators for the discrete cosine and sine transform are available
4+
# whenever FFTW.jl is loaded together with LinearOperatorCollection:
5+
using LinearOperatorCollection, FFTW
6+
fop = FFTOp(Complex{eltype(image)}, shape = (N, N))
7+
cop = DCTOp(eltype(image), shape = (N, N))
8+
sop = DSTOp(eltype(image), shape = (N, N))
9+
image_frequencies = reshape(fop * vec(image), N, N)
10+
image_cosine = reshape(cop * vec(image), N, N)
11+
image_sine = reshape(sop * vec(image), N, N)
12+
13+
fig = Figure()
14+
plot_image(fig[1,1], image, title = "Image")
15+
plot_image(fig[1,2], abs.(weighted_frequencies) .+ eps(), title = "Frequency Domain", colorscale = log10)
16+
plot_image(fig[1,3], image_cosine, title = "Cosine")
17+
plot_image(fig[1,4], image_sine, title = "Sine")
18+
resize_to_layout!(fig)
19+
fig
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# # Gradient Operator
2+
include("../../util.jl") #hide
3+
# This operator computes a direction gradient along one or more dimensions of an array:
4+
gop = GradientOp(eltype(image); shape = (N, N), dims = 1)
5+
gradients = reshape(gop * vec(image), :, N)
6+
fig = Figure()
7+
plot_image(fig[1,1], image, title = "Image")
8+
plot_image(fig[1,2], gradients[:, :], title = "Gradient", colormap = :vik)
9+
resize_to_layout!(fig)
10+
fig

docs/src/literate/tutorials/nfft.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include("../../util.jl") #hide

docs/src/literate/tutorials/normal.jl

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# # Normal operator
2+
include("../../util.jl") #hide
3+
4+
# This operator implements a lazy normal operator implementing:
5+
# ```math
6+
# \begin{equation}
7+
# (\mathbf{A})^*\mathbf{A}
8+
# \end{equation}
9+
# ```
10+
# for some operator $\mathbf{A}$:
11+
fop = op = FFTOp(ComplexF32, shape = (N, N))
12+
nop = NormalOp(eltype(fop), parent = fop)
13+
isapprox(nop * vec(image), vec(image))
14+
15+
# And we can again access our original operator:
16+
typeof(nop.parent)
17+
18+
# LinearOperatorCollection also provides an opinionated `normalOperator` function which tries to optimize the resulting normal operator.
19+
# As an example consider the normal operator of a weighted fourier operator:
20+
weights = collect(range(0, 1, length = N*N))
21+
wop = WeightingOp(weights)
22+
pop = ProdOp(wop, fop)
23+
nop = normalOperator(pop)
24+
typeof(nop.parent) == typeof(pop)
25+
# Note that the parent was changed. This is because the normal operator was optimized by initially computing the weights:
26+
# ```math
27+
# \begin{equation}
28+
# \tilde{\mathbf{W}} = \mathbf{W}^*\mathbf{W}
29+
# \end{equation}
30+
# ```
31+
# and then applying the following each iteration:
32+
# ```math
33+
# \begin{equation}
34+
# \mathbf{A}^*\tilde{\mathbf{W}}\mathbf{A}
35+
# \end{equation}
36+
# ```
37+
38+
# Other operators can define different optimization strategies for the `normalOperator` method.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# # Getting Started
2+
# To begin, we first need to load LinearOperatorCollection:
3+
using LinearOperatorCollection
4+
5+
# If we require an operator which is implemented via a package extensions, we also need to include
6+
# the package that implements the functionality of the operator:
7+
using FFTW
8+
9+
# As an introduction, we will construct a two dimensional FFT operator and apply it to an image.
10+
# To construct an operator we can either call its constructor directly:
11+
N = 256
12+
op = FFTOp(ComplexF32, shape = (N, N))
13+
typeof(op)
14+
15+
# Or we can use the factory method:
16+
op = createLinearOperator(FFTOp{ComplexF64}, shape = (N, N))
17+
18+
# We will use a Shepp-logan phantom as an example image:
19+
using ImagePhantoms, ImageGeoms
20+
image = shepp_logan(N, SheppLoganToft())
21+
size(image)
22+
23+
# Since our operators are only defined for matrix-vector products, we can't directly apply them to the two-dimensional image.
24+
# We first have to reshape the image to a vector:
25+
y = op * vec(image);
26+
27+
# Afterwards we can reshape the result and visualize it with CairoMakie:
28+
image_freq = reshape(y, N, N)
29+
using CairoMakie
30+
function plot_image(figPos, img; title = "", width = 150, height = 150, colorscale = identity)
31+
ax = CairoMakie.Axis(figPos[1, 1]; yreversed=true, title, width, height)
32+
hidedecorations!(ax)
33+
hm = heatmap!(ax, img, colorscale = colorscale)
34+
Colorbar(figPos[1, 2], hm)
35+
end
36+
fig = Figure()
37+
plot_image(fig[1,1], image, title = "Image")
38+
plot_image(fig[1,2], abs.(image_freq), title = "Frequency Domain", colorscale = log10)
39+
resize_to_layout!(fig)
40+
fig
41+
42+
# To perform the inverse Fourier transform we can simply use the adjoint of our operator:
43+
image_inverse = reshape(adjoint(op) * y, N, N)
44+
plot_image(fig[1,3], real.(image_inverse), title = "Image after Inverse")
45+
resize_to_layout!(fig)
46+
fig
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# # Product Operator
2+
include("../../util.jl") #hide
3+
# This operator describes the product or composition between two operators:
4+
weights = collect(range(0, 1, length = N*N))
5+
wop = WeightingOp(weights)
6+
fop = FFTOp(ComplexF64, shape = (N, N))
7+
# A feature of LinearOperators.jl is that operator can be cheaply transposed, conjugated and multiplied and only in the case of a matrix-vector product the combined operation is evaluated.
8+
tmp_op = wop * fop
9+
tmp_freqs = tmp_op * vec(image)
10+
11+
12+
# Similar to the WeightingOp, the main difference with the product operator provided by LinearOperatorCollection is the dedicated type, which allows for code specialisation.
13+
pop = ProdOp(wop, fop)
14+
# and the ability to retrieve the components:
15+
typoef(pop.A)
16+
# and
17+
typeof(pop.B)
18+
19+
# Otherwise they compute the same thing:
20+
pop * vec(image) == tmp_op * vec(image)
21+
22+
# Note that a product operator is not thread-safe.
23+
24+
# We can again visualize our result:
25+
weighted_frequencies = reshape(pop * vec(image), N, N)
26+
image_inverse = reshape(adjoint(pop) * y, N, N)
27+
fig = Figure()
28+
plot_image(fig[1,1], image, title = "Image")
29+
plot_image(fig[1,2], abs.(weighted_frequencies) .+ eps(), title = "Frequency Domain", colorscale = log10)
30+
plot_image(fig[1,3], real.(image_inverse), title = "Image after Inverse")
31+
resize_to_layout!(fig)
32+
fig

docs/src/literate/tutorials/radon.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# # Radon Operator
2+
include("../../util.jl") #hide
3+
# The Radon operator is available when loading RadonKA.jl and LinearOperatorCollection:
4+
using LinearOperatorCollection, RadonKA
5+
angles = collect(range(0, π, N))
6+
rop = RadonOp(eltype(image); angles, shape = size(image));
7+
sinogram = reshape(rop * vec(image), :, N)
8+
fig = Figure()
9+
plot_image(fig[1,1], image, title = "Image")
10+
plot_image(fig[1,2], sinogram, title = "Sinogram")
11+
plot_image(fig[1,3], reshape(adjoint(rop) * vec(sinogram), N, N), title = "Backprojection")
12+
resize_to_layout!(fig)
13+
fig

0 commit comments

Comments
 (0)