API reference
time axes
ImageAxes.timeaxis — Functiontimeaxis(A)Return the time axis, if present, of the array A, and nothing otherwise.
ImageAxes.istimeaxis — Functionistimeaxis(ax)Test whether the axis ax corresponds to time.
ImageAxes.timedim — Functiontimedim(img) -> d::IntReturn the dimension of the array used for encoding time, or 0 if not using an axis for this purpose.
Note: if you want to recover information about the time axis, it is generally better to use timeaxis.
ImageAxes.HasTimeAxis — TypeHasTimeAxis{AA}A trait for testing whether type AA has a time axis. Time axes must be declared before use.
Examples
using ImageAxes, SimpleTraits
# Declare that all axes named `:time` are time axes
@traitimpl TimeAxis{Axis{:time}}
# Define functions that dispatch on AxisArrays that may or may not have time axes
@traitfn got_time{AA<:AxisArray; HasTimeAxis{AA}}(img::AA) = "yep, I've got time"
@traitfn got_time{AA<:AxisArray; !HasTimeAxis{AA}}(img::AA) = "no, I'm too busy"
julia> A = AxisArray(1:5, Axis{:time}(1:5));
julia> got_time(A)
"yep, I've got time"
julia> A = AxisArray(1:5, Axis{:x}(1:5));
julia> got_time(A)
"no, I'm too busy"ImageAxes.TimeAxis — TypeTimeAxis{Ax}A trait (from SimpleTraits) indicating whether axis Ax corresponds to time. This decision is based on the symbol-name given to Ax. For example, the following declares that all Axis{:time} objects correspond to time:
@traitimpl TimeAxis{Axis{:time}}This definition has already been made in ImageAxes, but you can add new names as well.
Streaming container
ImageAxes.StreamingContainer — TypeA = StreamingContainer{T}(f!, parent, streamingaxes::Axis...)An array-like object possessing one or more axes for which changing "slices" may be expensive or subject to restrictions. A canonical example would be an AVI stream, where addressing pixels within the same frame is fast but jumping between frames might be slow.
Here's a simple example of dividing by the mean of each slice of an image before returning values.
A = AxisArrays.AxisArray(reshape(1:36, 3, 3, 4))
function f!(buffer, slice)
meanslice = mean(slice)
buffer .= slice./meanslice
end
B = StreamingContainer{Float64}(f!, A, AxisArrays.axes(A)[3])
julia> A[:,:,1]
3×3 AxisArray{Int64,2,Array{Int64,2},Tuple{Axis{:row,Base.OneTo{Int64}},Axis{:col,Base.OneTo{Int64}}}}:
1 4 7
2 5 8
3 6 9
julia> B[:,:,1]
3×3 Array{Float64,2}:
0.2 0.8 1.4
0.4 1.0 1.6
0.6 1.2 1.8The user-provided f! function should take arguments:
f!(buffer, slice)Where buffer will be an empty array that can hold a slice of your series, and slice will hold the current input slice.
It's worth noting that StreamingContainer is not a subtype of AbstractArray, but that much of the array interface (eltype, ndims, axes, size, getindex, and IndexStyle) is supported. A StreamingContainer A can be built from an AxisArray, but it may also be constructed from other "parent" objects, even non-arrays, as long as they support the same functions. In either case, the parent should also support the standard AxisArray functions axes, axisnames, axisvalues, and axisdim; this support will be extended to the StreamingContainer.
Additionally, a StreamingContainer A supports
getindex!(dest, A, axt::Axis{:time}, ...)to obtain slices along the streamed axes (here it is assumed that :time is a streamed axis of A). You can implement this directly (dispatching on the parameters of A), or (if the parent is an AbstractArray) rely on the fallback
A.getindex!(dest, view(parent, axs...))where A.getindex! = f! as passed as an argument at construction. dest should have dimensionality ndims(parent)-length(streamingaxes).
Optionally, define StreamIndexStyle(typeof(parent),typeof(f!)).
ImageAxes.StreamIndexStyle — Typestyle = StreamIndexStyle(A)A trait that indicates the degree of support for indexing the streaming axes of A. Choices are IndexAny() and IndexIncremental() (for arrays that only permit advancing the time axis, e.g., a video stream from a webcam). The default value is IndexAny().
This should be specialized for the type rather than the instance. For a StreamingContainer S, you can define this trait via
StreamIndexStyle(::Type{P}, ::typeof(f!)) = IndexIncremental()where P = typeof(parent(S)).
ImageAxes.IndexAny — TypeIndexAny()Indicates that an axis supports full random-access indexing.
ImageAxes.IndexIncremental — TypeIndexIncremental()Indicates that an axis supports only incremental indexing, i.e., from i to i+1. This is commonly used for the temporal axis with media streams.