Geometries

A common way of analyzing HCI data is to look at specific spatial extents, such as annuli. These geometries can be thought of as spatially filtering the input data.

For example, to create a geometry that is a concentric circle with radius r, we could filter a single frame like this

frame = ones(101, 101)
idxs = CartesianIndices(frame)
radius = 10
center = (51, 51)
# only include indices that are within circle
idxs_inside_circle = filter(idxs) do idx
    translated = idx.I .- center
    dist = sqrt(sum(abs2, translated))
    return dist ≤ radius
end

using these filtered indices we can mask the data with something like

masked = zero(frame)
masked[idxs_inside_circle] = frames[idxs_inside_circle]

more useful, though, is filtering the data. If we think of the frame as a sample of pixels unrolled into a vector, we can filter that vector and only use the pixels that are within the mask.

filtered = frame[idxs_inside_circle]

This is very convenient for statistical algorithms wince we are filtering the data instead of just masking it, which greatly reduces the number of pixels. For example, the circle defined above only uses 4% of the data, so why waste time processing the rest?

Index

API/Reference

HCIToolbox.AnnulusViewType
AnnulusView(cube::AbstractArray{T,3};
            inner=0, outer=first(size(parent))/2 + 0.5,
            fill=0)

Cut out an annulus with inner radius inner and outer radius outer. Values that fall outside of this region will be replaced with fill. This does not copy any data, it is merely a view into the data.

source
(::AnnulusView)(asview=false)

Return the pixels that fall within the annulus as a matrix. This matrix is equivalent to unrolling each frame and then spatially filtering the pixels outside the annulus. If asview is true, the returned values will be a view of the parent array instead of a copy.

Examples

julia> ann = AnnulusView(ones(101, 101, 10); inner=5, outer=20);

julia> X = ann();

julia> size(X)
(1188, 10)
source
HCIToolbox.MultiAnnulusViewType
MultiAnnulusView(cube::AbstractArray{T,3} width, radii; fill=0)

Create multiple annuli at each radius in radii with width width. Values that fall outside of these regions will be replaced with fill. This does not copy any data, it is merely a view into the data.

source
MultiAnnulusView(cube::AbstractArray{T,3}, width;
                 inner=0, outer=first(size(parent))/2 + 0.5,
                 fill=0)

Create multiple annuli between inner and outer with width spacing. Values that fall outside of these regions will be replaced with fill. This does not copy any data, it is merely a view into the data.

source
(::MultiAnnulusView)(idx, asview=false)

Return the idxth annulus as a matrix. This is equivalent to unrolling the frame and filtering out pixels outside of the idxth annulus. If asview is true, the returned values will be a view of the parent array instead of a copy.

Examples

julia> ann = MultiAnnulusView(ones(101, 101, 10), 5; inner=5, outer=30);

julia> X = ann(1);

julia> size(X)
(248, 10)

julia> X2 = ann(2);

julia> size(X2)
(404, 10)

See also

eachannulus

source
HCIToolbox.eachannulusFunction
eachannulus(::MultiAnnulusView, asview=false)

Create a generator for each annulus in the view. If asview is true, the annuli will be returned as a view into the parent array instead of a copy.

Examples

julia> ann = MultiAnnulusView(ones(101, 101, 10), 5; inner=5, outer=30);

julia> [size(X) for X in eachannulus(ann)]
5-element Vector{Tuple{Int64, Int64}}:
 (248, 10)
 (404, 10)
 (560, 10)
 (716, 10)
 (880, 10)
source
HCIToolbox.inverseFunction
inverse(::AnnulusView, mat::AbstractMatrix)

Generate a cube similar to the view with the pixels from mat. mat should have the same size as the matrix output from AnnulusView

Examples

julia> ann = AnnulusView(ones(101, 101, 10); inner=5, outer=20);

julia> X = ann();

julia> out = inverse(ann, -X);

julia> out ≈ -ann
true
source
inverse(::MultiAnnulusView, idx, mat)
inverse(::MultiAnnulusView, mats...)

Generate a cube similar to the view using the given pixel matrices. The pixels from mat will be put into the location of the idxth annulus. mat should have the same size as the output matrices generated by MultiAnnulusView. If multiple matrices are supplied, it is assumed each one corresponds to each annulus in the view.

Examples

Expand a single annulus-

julia> ann = MultiAnnulusView(ones(101, 101, 10), 5; inner=5, outer=30);

julia> X = ann(1);

julia> out = inverse(ann, 1, -X);

julia> sum(out) == -sum(X)
true

expand many annuli-

julia> Xs = [-X for X in eachannulus(ann)];

julia> out = inverse(ann, Xs);

julia> out ≈ -ann
true
source
HCIToolbox.inverse!Function
inverse!(::AnnulusView, out, mat)

In-place version of inverse that fills out in-place.

source
inverse!(::MultiAnnulusView, out, idx, mat)
inverse!(::MultiAnnulusView, out, mats...)

In-place version of inverse that fills out with annuli defined by the geometry of the view.

source
Base.copyto!Function
copyto!(::AnnulusView, mat::AbstractMatrix)

Copy the pixels from mat into the pixels in the annulus. mat should have the same size as the matrix output from AnnulusView

Examples

julia> ann = AnnulusView(ones(101, 101, 10); inner=5, outer=20);

julia> X = ann();

julia> new_ann = copyto!(ann, -X);

julia> new_ann() ≈ -X
true
source
copyto!(::MultiAnnulusView, idx, mat)
copyto!(::MultiAnnulusView, mats...)

Copy the pixels from mat into the pixels in the idxth annulus. mat should have the same size as the matrices generated by MultiAnnulusView. If multiple matrices are supplied, it is assumed each one corresponds to each annulus in the view.

Examples

Update a single annulus-

julia> ann = MultiAnnulusView(ones(101, 101, 10), 5; inner=5, outer=30);

julia> X = ann(1);

julia> new_ann = copyto!(ann, 1, -X);

julia> new_ann(1) ≈ -X
true

update each annulus-

julia> ann = MultiAnnulusView(ones(101, 101, 10), 5; inner=5, outer=30);

julia> Xs = [-X for X in eachannulus(ann)];

julia> new_ann = copyto!(copy(ann), Xs);

julia> new_ann ≈ -ann
true
source