/
scaling.jl
102 lines (81 loc) · 3.11 KB
/
scaling.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
using PaddedViews
"""
scale(cube::AbstractArray{T,3}, scales)
Linearly stretch each frame in `cube` by the corresponding scale in `scales`. Uses bilinear interpolaiton internally. The output size can be specified or else we will choose the smallest size that contains the largest stretch.
"""
function scale(cube::AbstractArray{T,3}, scales) where T
out = similar(cube)
Threads.@threads for i in axes(cube, 3)
frame = @view cube[:, :, i]
out[:, :, i] .= scale(frame, scales[i])
end
return out
end
"""
scale(frame::AbstractMatrix, scale)
Linearly stretch `frame` with the ratio `scale`. Uses bilinear interpolation internally.
"""
scale(frame::AbstractMatrix, scale) = cropview(imresize(frame; ratio=scale), size(frame); force=true, verbose=false)
"""
invscale(cube::AbstractArray{T,3}, scales)
Linearly contract each frame in `cube` by the corresponding scale in `scales`. Uses bilinear interpolaiton internally.
"""
function invscale(cube::AbstractArray{T,3}, scales) where T
out = similar(cube)
Threads.@threads for i in axes(cube, 3)
out[:, :, i] .= invscale(cube[:, :, i], scales[i])
end
return out
end
"""
invscale(frame::AbstractMatrix, scale)
Linearly contract `frame` with the ratio `scale`. Uses bilinear interpolation internally.
"""
function invscale(frame::AbstractMatrix{T}, scale) where T
out = imresize(frame; ratio=inv(scale))
size(out) == size(frame) && return out
offset = div.(size(frame) .- size(out), 2) .+ 1
return PaddedView(zero(T), out, size(frame), offset)
end
"""
scale_and_stack(spcube::AbstractArray{T,4}, scales)
Given a 4-D spectral ADI (SDI) tensor this function scales each temporal slice according to `scales` and then concatenates into a cube with `nλ * nf` frames.
"""
function scale_and_stack(spcube::AbstractArray{T,4}, scales) where T
nx, ny, nλ, nf = size(spcube)
out = similar(spcube, nx, ny, nλ * nf)
Threads.@threads for n in axes(spcube, 4)
slice = (n - 1) * nλ + firstindex(spcube, 4):n * nλ
frame = @view spcube[:, :, :, n]
out[:, :, slice] .= scale(frame, scales)
end
return out
end
"""
invscale_and_collapse(stack_cube::AbstractArray{T,3}, scales; kwargs...)
Given an SDI tensor that has been stacked into a cube, invscales each spectral slice and combines with [`collapse`](@ref). The output will be cropped to `size`.
"""
function invscale_and_collapse(stack_cube::AbstractArray{T,3}, scales; kwargs...) where T
nλ = length(scales)
n = Base.size(stack_cube, 3) ÷ nλ
out = similar(stack_cube, size(stack_cube)[1:2]..., n)
Threads.@threads for n in axes(out, 3)
slice = (n - 1) * nλ + firstindex(out, 3):n * nλ
cube = @view stack_cube[:, :, slice]
out[:, :, n] .= collapse(invscale(cube, scales); kwargs...)
end
return out
end
"""
scale_list(wavelengths)
Returns a list of scaling factors for aligning SDI tensors from a list of wavelengths.
# Examples
```jldoctest
julia> scale_list([0.5, 2, 4])
3-element Vector{Float64}:
8.0
2.0
1.0
```
"""
scale_list(wavelengths) = maximum(wavelengths) ./ wavelengths