JuliaImages / Images.jl

An image library for Julia
http://juliaimages.org/
Other
533 stars 141 forks source link

RFC: Towards consistent style, part 2: a documentation guide #790

Open johnnychen94 opened 5 years ago

johnnychen94 commented 5 years ago

This is the continuation of https://github.com/JuliaImages/Images.jl/issues/767 on documentation style

!!! Warning ⚠️

This is not a guideline yet, at present it's just some material to inspire thoughts.

Why we need an extra documentation guide for Images.jl?

Many image processing algorithms are too complicated that well-explained documentations is absolutely necessary. The old way of documentation in other languages is to write step-by-step tutorials. For julia, Documenter.jl provides an alternative -- we can make everything documented in docstring, then the (step-by-step) tutorial of the function can be generated.

However, julia guide on documentation isn't prepared for this kind of docstring work -- most docstring in julia are quite small.

What part would this guide contain?

  1. what are contained in a complete docstring?
  2. best practice to write each part of docstring.

Based on julia documentation, a complete docstring contains:

  1. [Required] signature of a function
  2. [Required] a single one-line sentence
  3. [Recomended] detailed description
  4. [Optional] argument list when really necessary
  5. [Recomended] code examples
  6. [Recomended] reference list
  7. [Recomended] hints to related functions

detailed explaination

docstring with math

if you need to write math in your docstring, it's very likely that you need to write a huge mount of math, it's recommended to use

@doc raw"""
``\LaTeX``
"""
imhist # single backslash `\`

instead of

"""
``\\LaTeX``
"""
imhist # double backslash `\\`

The former helps you debug your latex codes with your local latex compiler

One exception: if you just need some symbols, using Unicode (e.g., α) is sufficient. -- REPL support unicode, but doesn't support latex.

argument list

do I need an argument list?

You only need an detailed argument list when there is arguments that control the behavior and result of the function, otherwise, good design on names and method signature is enough.

argument list style

julia documentation uses the following style

# Arguments
- `n::Integer`: the number of elements to compute.
- `dim::Integer=1`: the dimensions along which to perform the computation.

we take another way,

# Arguments
Various options for the parameters of this function are described in more detail
below.

## Choices for `n::Interger`
the number of elements to compute.

## Choices for `dim::Integer=1`
the dimensions along which to perform the computation.

This is because most arguments are too complicated to be explained using one-line sentence.

img arugment(s)

Most image processing functions have img argument(s):

code examples

the challenge with good-quality code example is:

(TODO: Literate provides a way to write such kind of demos/tutorials, but I'm not sure if this works well with docstring examples.)

reference list

The following serves as a recommendation

# References
1. apa style reference
    > description of reference1
2. apa style reference
    > description of reference2

APA style is not compulsory, the point is: you can't just simply provide an url link.

For example,

"""
...
# References
1. Rudin, L. I., Osher, S., and Fatemi, E. (1992). Nonlinear total variation based noise removal algorithms. Physica D: nonlinear phenomena, 60(1-4), 259-268.
    > The classic paper that uses variational model to do image denoising.
    >
    > detailed description
2. Goldstein, T., & Osher, S. (2009). The split Bregman method for L1-regularized problems. SIAM journal on imaging sciences, 2(2), 323-343.
    > use Split Bregman method to solve ROF model
    > 
    > https://epubs.siam.org/doi/abs/10.1137/080725891
"""
denoise(algo::ROF, img)

hints to related functions

syntax of @ref

The following ways are recommended:

johnnychen94 commented 5 years ago

RFC: Detailed description

In https://github.com/JuliaImages/Images.jl/issues/772 and https://github.com/zygmuntszpak/ImageBinarization.jl/issues/23, we reach a consensus that a julia way of implementing image processing algorithm is to take advantage of multiple dispatch

abstract type BinarizationAlgorithm end
struct Otsu <: BinarizationAlgorithm end
struct Yen <: BinarizationAlgorithm end

function binarize(algo::Otsu, img)
# implementation
end

function binarize(algo::Yen, img)
# implementation
end

However, we will meet problem when writing docstring to each binarize methods. Users will get pages of docstring with a single ?binarize

Why this is terrible?

The reason for this behavior is

When retrieving documentation for a generic function, the metadata for each method is concatenated with the catdoc function, which can of course be overridden for custom types.

One way to solve this problem is to

In general, only the most generic method should be documented, or even the function itself (i.e. the object created without any methods by function bar end). Specific methods should only be documented if their behaviour differs from the more generic ones. In any case, they should not repeat the information provided elsewhere.

For example:

"""
    Otsu()

one-line description

# Algorithm details
...

# Argument list
...

# Examples
...

# References
...

See also: [`binarize`](@ref ), [`BinarizationAlgorithm`](@ref)
"""
struct Otsu <: BinarizationAlgorithm end

"""
    binarize(algo::Otsu, img)

one-line description

Check [`ImageBinarization.Otsu`](@ref ImageBinarization.Otsu) for more details
"""
function binarize(algo::Otsu, img)
# implementation
end

# In ImageBinarization.jl
"""
    binarize(algo::BinarizationAlgorithm, img)

one-line description

detailed explaination

# Example
...

See also: [`BinarizationAlgorithm`](@ref)
"""
binarize

By doing this, we can get a more concise result with ?binarize

result of `?binarize(Otsu(), img)` ```julia binarize(algorithm::Otsu, img::AbstractArray{T,2}) where T <: Colorant Binarizes the image using Otsu histogram thresholding method. Under the assumption that the image histogram is bimodal the binarization threshold is set so that the resultant between-class variance is maximal. Check Otsu for more details ```
result of `?binarize` ```julia binarize(algorithm::Otsu, img::AbstractArray{T,2}) where T <: Colorant Binarizes the image using Otsu histogram thresholding method. Under the assumption that the image histogram is bimodal the binarization threshold is set so that the resultant between-class variance is maximal. Check Otsu for more details ──────────────────────────────────────────────────────────────────────────────────────────────── binarize(algorithm::BinarizationAlgorithm, img::AbstractArray{T,2}) where T <: Colorant Returns the binarized image as an Array{Gray{Bool},2} Example ≡≡≡≡≡≡≡≡≡ Binarizes the "cameraman" image in the TestImages package using Otsu method. All other algorithms are used in a similar way. using TestImages, ImageBinarization img = testimage("cameraman") binarize_method = Otsu() img_binary = binarize(binarize_method, img) See also: BinarizationAlgorithm ```