Skip to content

Commit 77e7d14

Browse files
committed
docs(border-arrays): document filtering helper functions
Adds documentation for `kern_padding`, `outer_axes`, and `padtoaxes` functions, which are helper functions for sampling extended arrays for filtering purposes. Also fixes the missing cross-refs and fixes the `rand` doctest.
1 parent 0cb98a3 commit 77e7d14

5 files changed

Lines changed: 84 additions & 26 deletions

File tree

docs/src/pages/arrays/border-arrays.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,31 @@ end
8080
f
8181
```
8282

83-
If the border type does not support the extent of the padding that is given in the constructor, the [`TransferFunctions.InvalidBorderExtent`](@ref) is thrown.
83+
If the border type does not support the extent of the padding that is given in the constructor, the
84+
[`TransferFunctions.InvalidBorderExtent`](@ref) is thrown.
8485

8586
```@docs
8687
TransferFunctions.InvalidBorderExtent
8788
```
89+
90+
# Functions
91+
Border arrays are useful for extending the domain of an array for [filtering](@ref filtering-manual).
92+
93+
This motivates some helper functions for sampling an extended array at given indices.
94+
95+
To determine the padding necessary for a given kernel in filtering, you can use `kern_padding`
96+
97+
```@docs
98+
TransferFunctions.kern_padding
99+
```
100+
101+
For determining the indices that are necessary in the parent to facilitate a filtering, you can use `outer_axes`
102+
```@docs
103+
TransferFunctions.outer_axes
104+
```
105+
106+
For extending the domain of an array to some given indices with a border strategy, you can use `padtoaxes`. This may
107+
also be useful if you do not want to have all the indices of the parent in the output of a filtering.
108+
```@docs
109+
padtoaxes
110+
```

docs/src/pages/devdocs/array-types.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,9 @@ CollapsedDocStrings = true
55

66
# Filtering Arrays and Circulant Tensors
77

8-
- [`TransferFunctions.kern_padding`](@ref) is used to determine the padding necessary to perform the full domain
8+
- [`TransferFunctions.kern_padding`](@ref) is useful for determining the padding necessary to perform the full domain
99
filtering of an array.
1010

11-
```@docs
12-
TransferFunctions.kern_padding
13-
```
14-
1511
- [`TransferFunctions.ind2sub`](@ref) is used in the [`FilteringMatrix`](@ref) to determine the "`kernel`" and
1612
"`parent`" indices from the index to the `FilteringMatrix`.
1713

docs/src/pages/filtering/array-discrete-filtering.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ using OffsetArrays: no_offset_view
1010
A = testimage("mandril_color")
1111
```
1212

13-
# Filtering
13+
# [Filtering](@id filtering-manual)
1414

1515
`TransferFucntions` provides some functions for discrete filtering. Both convolution and correlation have a dedicated
1616
function. This function accepts an image `A`, kernel `K` and an optional [border](@ref "Border Types") and an output

src/types/border-arrays.jl

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ end
274274
border_array(A, border, padding)
275275
Construct a [`BorderArray`](@ref) of `A` with the border `border` and padding `padding`.
276276
277-
See also [`padtoaxes`](@ref TransferFunctions.padtoaxes)
277+
See also [`padtoaxes`](@ref)
278278
```jldoctest
279279
julia> border_array(reshape(1:9, (3,3)), :circular, 2)
280280
7×7 border_array(reshape(::UnitRange{Int64}, 3, 3), :Circular) with eltype Int64 with indices -1:5×-1:5:
@@ -298,30 +298,59 @@ For any indices where the `target` is contained in the parent `A`, a view is tak
298298
299299
See also [`border_array`](@ref).
300300
```jldoctest
301-
julia> TF.padtoaxes(OAs.OffsetArray(rand(100,100), -30:69, -20:79), :fill, (-35:-25, -30:-15))
302-
11×16 border_array(view(OffsetArray(::Matrix{Float64}, -30:69, -20:79), Base.IdentityUnitRange(-30:-25), Base.IdentityUnitRange(-20:-15)), fill(0.0)) with eltype Float64 with indices -35:-25×-30:-15:
303-
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 … 0.0 0.0 0.0 0.0
304-
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
305-
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
306-
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
307-
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
308-
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 … 0.452376 0.20255 0.921373 0.654289
309-
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.727716 0.355869 0.156582 0.437704
310-
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.52427 0.591113 0.223759 0.943134
311-
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.709755 0.46971 0.550499 0.150776
312-
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.575396 0.854017 0.170872 0.825171
313-
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 … 0.962307 0.898315 0.922924 0.925127
301+
julia> padtoaxes(OAs.OffsetArray(reshape(1:100^2, 100, 100), -30:69, -20:79), :fill, (-35:-25, -30:-15))
302+
11×16 border_array(view(OffsetArray(reshape(::UnitRange{Int64}, 100, 100), -30:69, -20:79), Base.IdentityUnitRange(-30:-25), Base.IdentityUnitRange(-20:-15)), fill(0)) with eltype Int64 with indices -35:-25×-30:-15:
303+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
304+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
305+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
306+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
307+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
308+
0 0 0 0 0 0 0 0 0 0 1 101 201 301 401 501
309+
0 0 0 0 0 0 0 0 0 0 2 102 202 302 402 502
310+
0 0 0 0 0 0 0 0 0 0 3 103 203 303 403 503
311+
0 0 0 0 0 0 0 0 0 0 4 104 204 304 404 504
312+
0 0 0 0 0 0 0 0 0 0 5 105 205 305 405 505
313+
0 0 0 0 0 0 0 0 0 0 6 106 206 306 406 506
314314
```
315+
316+
!!! warning "`:circular` border"
317+
By default, this constructs a border array from the view into the parent array. If you use some border strategy that
318+
uses indices and/or values of the other edge, you may want to have the border array constructed from the full array
319+
instead and take the view into it. This can be done by setting the `outerpadding` keyword argument to `true`.
320+
321+
322+
```jldoctest
323+
julia> padtoaxes(reshape(1:121, 11, 11), :circular, (-1:2, -1:2))
324+
4×4 border_array(view(reshape(::UnitRange{Int64}, 11, 11), Base.IdentityUnitRange(1:2), Base.IdentityUnitRange(1:2)), :Circular) with eltype Int64 with indices -1:2×-1:2:
325+
1 12 1 12
326+
2 13 2 13
327+
1 12 1 12
328+
2 13 2 13
329+
330+
julia> padtoaxes(reshape(1:121, 11, 11), :circular, (-1:2, -1:2); outerpadding=true)
331+
4×4 view(border_array(reshape(::UnitRange{Int64}, 11, 11), :Circular), Base.IdentityUnitRange(-1:2), Base.IdentityUnitRange(-1:2)) with eltype Int64 with indices -1:2×-1:2:
332+
109 120 10 21
333+
110 121 11 22
334+
100 111 1 12
335+
101 112 2 13
336+
```
337+
338+
!!! tip "Border extent"
339+
`outerpadding` may also lead to a greater extent of the border supplied since for example the `:circular` border is
340+
only defined when the wrapped index is in the range of the parent view which is smaller that the parent array.
315341
"""
316-
function padtoaxes(parent, border, target)
342+
function padtoaxes(parent, border, target; outerpadding=false)
317343
padding = map(target, axes(parent)) do t, ax
318344
(abs(max(0, first(ax)- first(t))), abs(max(0, last(t) - last(ax))))
319345
end
320-
viewaxes = map(target, axes(parent)) do t, ax
321-
(max(first(ax), first(t))):(min(last(ax), last(t)))
346+
if !outerpadding
347+
viewaxes = map(target, axes(parent)) do t, ax
348+
(max(first(ax), first(t))):(min(last(ax), last(t)))
349+
end
350+
return border_array(offset_view(parent, viewaxes...), border, padding)
351+
else
352+
return offset_view(border_array(parent, border, padding), target...)
322353
end
323-
A = offset_view(parent, viewaxes...)
324-
return border_array(A, border, padding)
325354
end
326355

327356
function Base.showarg(io::IO, A::BorderArray, toplevel)

src/utils.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,13 @@ julia> TF.OriginAt(3, 3)(reshape(1:16, (4,4)))
284284
kern_padding(kern)
285285
Determine the padding necessary to keep the input array fully contained in the interior of the output when filtered with
286286
`kern`.
287+
288+
```jldoctest
289+
julia> K = OAs.OffsetArray(ones(11,8) ./ (11*8), -5:5, -3:4);
290+
291+
julia> TF.kern_padding(K)
292+
((5, 5), (3, 4))
293+
```
287294
"""
288295
function kern_padding(K::Indices)
289296
if !all(I -> 0 I, K)
@@ -298,6 +305,8 @@ kern_padding(K::AbstractArray) = kern_padding(axes(K))
298305
inner_axes(A, K)
299306
Determine the inner axes of the array with edges `edges` or when filtered with kernel `K`.
300307
308+
See also [`outer_axes`](@ref).
309+
301310
```jldoctest
302311
julia> TF.inner_axes(ones(100,100), ((2,4), (1,10)))
303312
(3:96, 2:90)
@@ -319,6 +328,7 @@ For instance this is useful when one wants to select the indices necessary to ta
319328
the filtered array with some kernel `K` at indices of `A` without the need for calculating for all of the indices of the
320329
initial array.
321330
331+
See also [`inner_axes`](@ref).
322332
```jldoctest
323333
julia> TF.outer_axes(ones(100,100), ((2,4), (1,10)))
324334
(-1:104, 0:110)

0 commit comments

Comments
 (0)