Skip to content

Commit ea72f37

Browse files
authored
Add initial documenter docs (#16)
* Prepare documentation structure * Add weighting operator docs * Add prodop documentation * Add block diagonal documentation * Add normal operator docu * Fix deploy url * Add gradient operator docs * Add fft op * Fix tmp array type for DCT and DST operator * Move tutorials and how-tos to literate folder * Finish initial docs
1 parent 01852f9 commit ea72f37

File tree

25 files changed

+435
-34
lines changed

25 files changed

+435
-34
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
/Manifest.toml
1+
Manifest.toml
2+
docs/build/
3+
docs/site/
4+
docs/src/generated/

docs/Project.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[deps]
2+
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
3+
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
4+
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
5+
ImageGeoms = "9ee76f2b-840d-4475-b6d6-e485c9297852"
6+
ImagePhantoms = "71a99df6-f52c-4da1-bd2a-69d6f37f3252"
7+
LinearOperatorCollection = "a4a2c56f-fead-462a-a3ab-85921a5f2575"
8+
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
9+
NFFT = "efe261a4-0d2b-5849-be55-fc731d526b0d"
10+
RadonKA = "86de8297-835b-47df-b249-c04e8db91db5"
11+
Wavelets = "29a6e085-ba6d-5f35-a997-948ac2efa89a"

docs/make.jl

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using Documenter, Literate # Documentation
2+
using RadonKA, Wavelets, NFFT, FFTW # Extensions
3+
using CairoMakie, ImageGeoms, ImagePhantoms # Documentation Example Packages
4+
5+
# Generate examples
6+
OUTPUT_BASE = joinpath(@__DIR__(), "src", "generated")
7+
INPUT_BASE = joinpath(@__DIR__(), "src", "literate")
8+
for (root, dirs, files) in walkdir(INPUT_BASE)
9+
for dir in dirs
10+
OUTPUT = joinpath(OUTPUT_BASE, dir)
11+
INPUT = joinpath(INPUT_BASE, dir)
12+
for file in filter(f -> endswith(f, ".jl"), readdir(INPUT))
13+
Literate.markdown(joinpath(INPUT, file), OUTPUT)
14+
end
15+
end
16+
end
17+
18+
modules = [LinearOperatorCollection,
19+
isdefined(Base, :get_extension) ? Base.get_extension(LinearOperatorCollection, :LinearOperatorFFTWExt) : LinearOperatorCollection.LinearOperatorFFTWExt,
20+
isdefined(Base, :get_extension) ? Base.get_extension(LinearOperatorCollection, :LinearOperatorNFFTExt) : LinearOperatorCollection.LinearOperatorNFFTExt,
21+
isdefined(Base, :get_extension) ? Base.get_extension(LinearOperatorCollection, :LinearOperatorRadonKAExt) : LinearOperatorCollection.LinearOperatorRadonKAExt,
22+
isdefined(Base, :get_extension) ? Base.get_extension(LinearOperatorCollection, :LinearOperatorWaveletExt) : LinearOperatorCollection.LinearOperatorWaveletExt]
23+
24+
makedocs(
25+
format = Documenter.HTML(prettyurls=get(ENV, "CI", "false") == "true",
26+
canonical="https://github.com/JuliaImageRecon/LinearOperatorCollection.jl",
27+
assets=String[],
28+
collapselevel=1,
29+
),
30+
modules = modules,
31+
sitename = "LinearOperatorCollection",
32+
authors = "Tobias Knopp, Niklas Hackelberg and Contributors",
33+
pages = [
34+
"Home" => "index.md",
35+
"Getting Started" => "generated/tutorials/overview.md",
36+
"Tutorials" => Any[
37+
"Weighting Operator" => "generated/tutorials/weighting.md",
38+
"FFT Operator" => "generated/tutorials/fft.md",
39+
"Diagonal Operator" => "generated/tutorials/diagonal.md",
40+
"Gradient Operator" => "generated/tutorials/gradient.md",
41+
#"Sampling Operator" => "generated/tutorials/sampling.md",
42+
#"NFFT Operator" => "generated/tutorials/nfft.md",
43+
"Wavelet Operator" => "generated/tutorials/wavelet.md",
44+
"Radon Operator" => "generated/tutorials/radon.md",
45+
"Product Operator" => "generated/tutorials/product.md",
46+
"Normal Operator" => "generated/tutorials/normal.md",
47+
],
48+
"How to" => Any[
49+
#"Implement Custom Operators" => "generated/howtos/custom.md",
50+
"Enable GPU Acceleration" => "generated/howtos/gpu.md",
51+
],
52+
#"Explanations" => Any[
53+
# "Operator Structure" => "operators.md",
54+
#],
55+
"Reference" => "references.md"
56+
],
57+
warnonly = [:missing_docs]
58+
)
59+
60+
deploydocs(repo = "github.com/JuliaImageRecon/LinearOperatorCollection.jl")

docs/src/index.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# LinearOperatorCollection
2+
3+
*Collection of linear operators for multi-dimensional signal and imaging tasks*
4+
5+
6+
## Introduction
7+
8+
This package contains a collection of linear operators that are particularly useful for multi-dimensional signal and image processing tasks. Linear operators or linear maps behave like matrices in a matrix-vector product, but aren't necessarily matrices themselves. They can utilize more effective algorithms and can defer their computation until they are multiplied with a vector.
9+
10+
All operators provided by this package extend types and methods [LinearOperators.jl](https://github.com/JuliaSmoothOptimizers/LinearOperators.jl). For example this package
11+
provides operators for the FFT (Fast Fourier Transform) and its non-equidistant variant (NFFT), the DCT (Discrete Cosine Transform), and the Wavelet transform. This package, however, does not implement
12+
these transformation itself but uses established libraries for them.
13+
14+
LinearOperatorCollection's main purpose is provide a wrapper around low-level libraries like FFTW.jl and NFFT.jl, which allows using the transformations as linear operators, i.e., implementing `Op * x`, `adjoint(Op) * x` and the `mul!` based in-place variants of the former.
15+
16+
## Installation
17+
18+
Within Julia, use the package manager to install this package:
19+
```julia
20+
using Pkg
21+
Pkg.add("LinearOperatorCollection")
22+
```
23+
This will install `LinearOperatorCollection` and a subset of the available operators.
24+
To keep the load time of this package low, many operators are implemented using package extensions.
25+
For instance, in order to get the `FFTOp`, one needs to install not only `LinearOperatorCollection` but also `FFTW` and load both in a Julia sessiong:
26+
```julia
27+
Pkg.add("FFTW")
28+
using LinearOperatorCollection, FFTW
29+
```
30+
Small operators are implemented in LinearOperatorCollection directly.
31+
32+
33+
## License / Terms of Usage
34+
35+
The source code of this project is licensed under the MIT license. This implies that
36+
you are free to use, share, and adapt it. However, please give appropriate credit
37+
by citing the project.
38+
39+
## Contact
40+
41+
If you have problems using the software, find mistakes, or have general questions please use
42+
the [issue tracker](hthttps://github.com/JuliaImageRecon/LinearOperatorCollection.jl/issues) to contact us.
43+
44+
## Related Packages
45+
46+
There exist many related packages which also implement efficient and/or lazy operators:
47+
48+
* [LinearOperators.jl](https://github.com/JuliaSmoothOptimizers/LinearOperators.jl)
49+
* [LinearMaps.jl](https://github.com/JuliaLinearAlgebra/LinearMaps.jl)
50+
* [LazyArrays.jl](https://github.com/JuliaArrays/LazyArrays.jl)
51+
* [BlockArrays.jl](https://github.com/JuliaArrays/BlockArrays.jl)
52+
* [Kronecker.jl](https://github.com/MichielStock/Kronecker.jl)
53+
54+
Generally, it should be possible to combine operators and arrays from various packages.

docs/src/literate/howtos/custom.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# # Implement Custom Operators
2+
# There are two different ways one can implement a custom LinearOperator. The first one is to directly implement an operator as a LinearOperator from LinearOperators.jl:

docs/src/literate/howtos/gpu.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# # GPU Acceleration
2+
include("../../util.jl") #hide
3+
# GPU kernels generally require all their arguments to exist on the GPU. This is not ncessarily the case for matrix-free operators as provides LinearOperators or LinearOperatorCollection.
4+
# In the case that a matrix free operator is solely a function call and contains no internal array state, the operator is GPU compatible as long as the method has a GPU compatible implementation.
5+
6+
# If the operator has internal fields required for its computation, such as temporary arrays for intermediate values or indices, then it needs to move those to the GPU.
7+
# Furthermore if the operator needs to create a new array in its execution, e.g. it is used in a non-inplace matrix-vector multiplication or it is combined with other operators, then the operator needs to specify
8+
# a storage type. LinearOperatorCollection has several GPU compatible operators, where the storage type is given by setting a `S` parameter:
9+
# ```julia
10+
# using CUDA # or AMDGPU, Metal, ...
11+
# image_gpu = cu(image)
12+
# ```
13+
using LinearOperatorCollection.LinearOperators
14+
image_gpu = image #hide
15+
storage = Complex.(similar(image_gpu, 0))
16+
fop = FFTOp(eltype(image_gpu), shape = (N, N), S = typeof(storage))
17+
LinearOperators.storage_type(fop) == typeof(storage)
18+
19+
# GPU operators can be used just like the other operators. Note however, that a GPU operator does not necessarily work with a CPU vector.
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+
typeof(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.(image_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

0 commit comments

Comments
 (0)