# [ANN] FFTIndexing.jl

FFTIndexing.jl is a small package I’ve written that provides a few types that you can use to index an array in a manner that exposes the underlying frequency bins from a Fourier transform.

This package accomplishes similar goals to FFTViews.jl, but does so without constructing any view objects. Instead, it provides types, `FFTIndex` and `FFTIndices`, similar to `CartesianIndex` and `CartesianIndices` in Julia Base, that can be used with any array that defines `getindex` and/or `setindex!`.

## Usage

An index `i::FFTIndex{D}` type indexes an array `A::AbstractArray{T,D}` with the assumption that the array has periodic boundary conditions. Suppose `A` is a `Array{Float32,3}` which resulted from a multidimensional fast Fourier transform: `FFTIndex(0, 0, 0)` corresponds to the zero frequency component, located at `firstindex(A)`, and `FFTIndex(-1, -1, -1)` corresponds to the last index.

The array is assumed to have periodic boundary conditions, and modulo math is used to interpret values in an `FFTIndex` as valid array indices. This allows for the elimination of bounds checks if this is the only type used to index an array. For example, if `size(A) === (3, 3, 7)`:

``````julia> A[3, 3, 7] === A[FFTIndex(2, 2, 6)]
true

julia> A[3, 3, 7] === A[FFTIndex(-1, -1, -1)]
true
``````

This also works for disparate `FFTIndex` dimensionalities, as long as the total dimensions indexed is equal to that of the array:

``````julia> A[3, 3, 7] === A[FFTIndex(2, 2), FFTIndex(6)]
true
``````

The `FFTIndices{D}` type represents all of the valid `FFTIndex{D}` objects for a given array or other object that has a `size`.

## Use case

In my research, I’ve needed to take fast Fourier transforms of datasets (which are `Vector{Float32}`) of disparate length. Using this package, I can combine `FFTIndices` with `stack` to fit all of the data into a contiguous `Matrix{Float32}` rather than a `Vector{Vector{Float32}}`:

``````julia> stack(v -> fft(v)[FFTIndices((256,))] for v in data)
``````

This automatically truncates the high frequency components of longer datasets down to a fixed size so they all fit into the matrix.

5 Likes