Справка
#
OffsetArrays.OffsetArray
— Type
OffsetArray(A, indices...)
Возвращает AbstractArray
, который использует тип и размер элемента совместно с первым аргументом, но применяет предоставленные индексы (indices
) для вывода его осей. Если все индексы являются AbstractUnitRange
, они напрямую используются в качестве осевого интервала в каждом измерении. Другие допустимые типы см. в примерах ниже.
В качестве альтернативы можно указать координаты одного угла массива, и тогда оси будут вычисляться автоматически из размера A
. Этот конструктор позволяет выполнять смещение к произвольному начальному индексу вдоль каждой оси, например к нулевой схеме индексирования, используемой в массивах в таких языках, как C и Python. См. OffsetArrays.Origin
и примеры ниже.
Пример: смещения
Существует два типа indices
: целые числа и диапазоноподобные типы.
Целые числа распознаются как смещения, где 0
означает, что смещения не применяются:
julia> A = OffsetArray(reshape(1:6, 2, 3), -1, -2)
2×3 OffsetArray(reshape(::UnitRange{Int64}, 2, 3), 0:1, -1:1) with eltype Int64 with indices 0:1×-1:1:
1 3 5
2 4 6
julia> A[0, 1]
5
Примеры диапазоноподобных типов: UnitRange
(например, -1:2
), CartesianIndices
и Colon()
(или сокращенно :
). UnitRange
указывает на интервал оси вдоль одного конкретного измерения, CartesianIndices
указывает на интервалы вдоль нескольких измерений, а Colon
является заполнителем, указывающим, что OffsetArray
использует свою ось совместно с родительским объектом вдоль этого измерения.
julia> OffsetArray(reshape(1:6, 2, 3), 0:1, -1:1)
2×3 OffsetArray(reshape(::UnitRange{Int64}, 2, 3), 0:1, -1:1) with eltype Int64 with indices 0:1×-1:1:
1 3 5
2 4 6
julia> OffsetArray(reshape(1:6, 2, 3), :, -1:1) # : как заполнитель, указывающий, что смещение не должно применяться к первому измерению.
2×3 OffsetArray(reshape(::UnitRange{Int64}, 2, 3), 1:2, -1:1) with eltype Int64 with indices 1:2×-1:1:
1 3 5
2 4 6
Используйте CartesianIndices
, чтобы указать координаты двух диагонально противоположных углов:
julia> OffsetArray(reshape(1:6, 2, 3), CartesianIndex(0, -1):CartesianIndex(1, 1))
2×3 OffsetArray(reshape(::UnitRange{Int64}, 2, 3), 0:1, -1:1) with eltype Int64 with indices 0:1×-1:1:
1 3 5
2 4 6
Целые числа и диапазоноподобные типы нельзя объединять в одном вызове:
julia> OffsetArray(reshape(1:6, 2, 3), 0, -1:1)
ERROR: [...]
Пример: начало
OffsetArrays.Origin
можно использовать для указания начала OffsetArray. Термин «начало» здесь означает угол с наименьшими значениями координат, например левый край для AbstractVector
, левый нижний угол для AbstractMatrix
и так далее. Координаты начала задают начальный индекс массива вдоль каждого измерения.
julia> a = [1 2; 3 4];
julia> OffsetArray(a, OffsetArrays.Origin(0, 1))
2×2 OffsetArray(::Matrix{Int64}, 0:1, 1:2) with eltype Int64 with indices 0:1×1:2:
1 2
3 4
julia> OffsetArray(a, OffsetArrays.Origin(0)) # задает нулевое начало по каждому измерению
2×2 OffsetArray(::Matrix{Int64}, 0:1, 0:1) with eltype Int64 with indices 0:1×0:1:
1 2
3 4
#
OffsetArrays.OffsetVector
— Type
OffsetVector(v, index)
Псевдоним типа и вспомогательный конструктор для одномерных OffsetArray
.
#
OffsetArrays.OffsetMatrix
— Type
OffsetMatrix(A, index1, index2)
Псевдоним типа и вспомогательный конструктор для двумерных OffsetArray
.
#
OffsetArrays.Origin
— Type
Origin(indices...)
Origin(origin::Tuple)
Origin(origin::CartesianIndex)
Вспомогательный тип для построения OffsetArray с заданным началом. Не экспортируется.
origin
массива определяется как кортеж первого индекса вдоль каждой оси, то есть first.(axes(A))
.
Пример
julia> a = [1 2; 3 4];
julia> using OffsetArrays: Origin
julia> OffsetArray(a, Origin(0, 1))
2×2 OffsetArray(::Matrix{Int64}, 0:1, 1:2) with eltype Int64 with indices 0:1×1:2:
1 2
3 4
julia> OffsetArray(a, Origin(0)) # краткое обозначение для `Origin(0, 0)`
2×2 OffsetArray(::Matrix{Int64}, 0:1, 0:1) with eltype Int64 with indices 0:1×0:1:
1 2
3 4
Объект Origin
является вызываемым, и он может сместить начало массива в указанную точку.
julia> b = Origin(0)(a) # смещение начала массива в точку (0,0)
2×2 OffsetArray(::Matrix{Int64}, 0:1, 0:1) with eltype Int64 with indices 0:1×0:1:
1 2
3 4
Тип Origin
, вызванный с AbstractArray
в качестве аргумента, возвратит экземпляр, соответствующий началу массива.
julia> origin_b = Origin(b) # получение начала массива в виде экземпляра Origin
Origin(0, 0)
julia> origin_b(ones(2,2)) # смещение начала другого массива к началу массива b, в данном случае в точку (0,0)
2×2 OffsetArray(::Matrix{Float64}, 0:1, 0:1) with eltype Float64 with indices 0:1×0:1:
1.0 1.0
1.0 1.0
Можно транслировать экземпляр |
julia> using OffsetArrays: Origin
julia> a = [1 2; 3 4]; # начало в точке (1,1)
julia> b = Origin(2,3)(a); # начало в точке (2,3)
julia> c = Origin(4)(a); # начало в точке (4,4)
julia> ao, bo, co = Origin(0).((a, b, c)); # смещение всех начал в точку (0,0)
julia> first.(axes(ao)) == first.(axes(bo)) == first.(axes(co)) == (0,0)
true
julia> ao, bo, co = Origin(b).((a, b, c)); # смещение всех начал в начало массива b
julia> first.(axes(ao)) == first.(axes(bo)) == first.(axes(co)) == (2,3)
true
julia> ao, bo, co = OffsetArray.((a, b, c), Origin(b)); # другой способ выполнения того же самого
julia> first.(axes(ao)) == first.(axes(bo)) == first.(axes(co)) == (2,3)
true
#
OffsetArrays.IdOffsetRange
— Type
ro = IdOffsetRange(r::AbstractUnitRange, offset=0)
Строит «диапазон смещения тождественности». Численно collect(ro) == collect(r) .+ offset
, с дополнительным свойством, так что axes(ro, 1) = axes(r, 1) .+ offset
. Когда r
начинается с 1, тогда ro[i] == i
и даже ro[ro] == ro
, т. е. это «тождество», которое является началом «Id» в IdOffsetRange
.
Примеры
Самый распространенный случай — это смещение диапазона, который начинается с 1 (либо 1:n
, либо Base.OneTo(n)
):
julia> using OffsetArrays: IdOffsetRange
julia> ro = IdOffsetRange(1:3, -2)
IdOffsetRange(values=-1:1, indices=-1:1)
julia> axes(ro, 1)
IdOffsetRange(values=-1:1, indices=-1:1)
julia> ro[-1]
-1
julia> ro[3]
ERROR: BoundsError: attempt to access 3-element OffsetArrays.IdOffsetRange{Int64, UnitRange{Int64}} with indices -1:1 at index [3]
Если диапазон не начинается с 1, значения могут отличаться от индексов:
julia> ro = IdOffsetRange(11:13, -2)
IdOffsetRange(values=9:11, indices=-1:1)
julia> axes(ro, 1) # 11:13 индексируется по 1:3, и это смещение также применяется к осям
IdOffsetRange(values=-1:1, indices=-1:1)
julia> ro[-1]
9
julia> ro[3]
ERROR: BoundsError: attempt to access 3-element OffsetArrays.IdOffsetRange{Int64, UnitRange{Int64}} with indices -1:1 at index [3]
Расширенная справка
Построение/принуждение сохраняет (смещенные) значения входного диапазона, но может изменять индексы, если этого требуют указанные типы. Пример:
r = OffsetArrays.IdOffsetRange{Int,UnitRange{Int}}(3:4)
имеет r[1] == 3
и r[2] == 4
, в то время как
r = OffsetArrays.IdOffsetRange{Int,Base.OneTo{Int}}(3:4)
имеет r[3] == 3
и r[4] == 4
, а r[1]
вызовет ошибку BoundsError
. В этом последнем случае потребовалось смещение осей, поскольку диапазоны Base.OneTo
должны начинаться со значения 1.
В будущем преобразование будет сохранять как значения, так и |
индексы, выдавая ошибку, если это невозможно. Например:
r = convert(OffsetArrays.IdOffsetRange{Int,UnitRange{Int}}, 3:4) имеет `r[1] == 3` и `r[2] == 4` и удовлетворяет `r == 3:4`, тогда как ```julia julia> convert(OffsetArrays.IdOffsetRange{Int,Base.OneTo{Int}}, 3:4) # future behavior, not present behavior ERROR: ArgumentError: first element must be 1, got 3
ERROR: ArgumentError: first element must be 1, got 3
``` где возникнет ошибка, поскольку результат не может иметь те же оси, что и входные данные. Важным следствием является то, что `typeof(r1)(r2)` и `oftype(r1, r2)` будут вести себя по-разному:
первый принуждает r2
быть типом r1
, а второй преобразует. Разработчикам рекомендуется «обезопасить» свой код на будущее, выбрав поведение, подходящее для каждого случая использования.
#
OffsetArrays.no_offset_view
— Function
no_offset_view(A)
Возвращает AbstractArray
, имеющий общую структуру и базовые данные с аргументом, но использующий индексирование на основе 1. Может просто возвращать аргумент, если это применимо. Не экспортируется.
В реализации по умолчанию применяется OffsetArrays
, но другие типы должны использовать что-то более конкретное, чтобы устранить уровень косвенности, когда это применимо.
julia> A = [1 3 5; 2 4 6];
julia> O = OffsetArray(A, 0:1, -1:1)
2×3 OffsetArray(::Matrix{Int64}, 0:1, -1:1) with eltype Int64 with indices 0:1×-1:1:
1 3 5
2 4 6
julia> OffsetArrays.no_offset_view(O)[1,1] = -9
-9
julia> A
2×3 Matrix{Int64}:
-9 3 5
2 4 6
#
OffsetArrays.AxisConversionStyle
— Type
OffsetArrays.AxisConversionStyle(typeof(indices))
AxisConversionStyle
определяет, следует ли преобразовывать indices
в один AbstractUnitRange{Int}
или в Tuple{Vararg{AbstractUnitRange{Int}}}
при разложении пользовательских типов на индексы. Этот метод вызывается после to_indices(A::Array, axes(A), indices)
, чтобы предоставить дополнительную информацию в случае, если to_indices
не возвращает Tuple
из AbstractUnitRange{Int}
.
Пользовательские типы индексов должны расширять AxisConversionStyle
и возвращать либо OffsetArray.SingleRange()
, который используется по умолчанию, либо OffsetArray.TupleOfRanges()
. В первом случае тип T
должен определять Base.convert(::Type{AbstractUnitRange{Int}}, ::T)
, а во втором — Base.convert(::Type{Tuple{Vararg{AbstractUnitRange{Int}}}}, ::T)
.
Примером последнего является CartesianIndices
, который преобразуется в кортеж (Tuple
) из AbstractUnitRange{Int}
при разложении на индексы.
Пример
julia> struct NTupleOfUnitRanges{N}
x ::NTuple{N, UnitRange{Int}}
end
julia> Base.to_indices(A, inds, t::Tuple{NTupleOfUnitRanges{N}}) where {N} = t;
julia> OffsetArrays.AxisConversionStyle(::Type{NTupleOfUnitRanges{N}}) where {N} = OffsetArrays.TupleOfRanges();
julia> Base.convert(::Type{Tuple{Vararg{AbstractUnitRange{Int}}}}, t::NTupleOfUnitRanges) = t.x;
julia> a = zeros(3, 3);
julia> inds = NTupleOfUnitRanges((3:5, 2:4));
julia> oa = OffsetArray(a, inds);
julia> axes(oa, 1) == 3:5
true
julia> axes(oa, 2) == 2:4
true
#
OffsetArrays.center
— Function
center(A, [r::RoundingMode=RoundDown])::Dims
Возвращает координату центра заданного массива A
. Если значение является size(A, k)
четным числом, то будет применена процедура округления с режимом r
.
Совместимость: OffsetArrays 1.9
Для этого метода требуется версия OffsetArrays не ниже 1.9. |
Примеры
julia> A = reshape(collect(1:9), 3, 3)
3×3 Matrix{Int64}:
1 4 7
2 5 8
3 6 9
julia> c = OffsetArrays.center(A)
(2, 2)
julia> A[c...]
5
julia> Ao = OffsetArray(A, -2, -2); # оси (-1:1, -1:1)
julia> c = OffsetArrays.center(Ao)
(0, 0)
julia> Ao[c...]
5
Чтобы сместить центральную координату заданного массива в точку (0, 0, ...)
, можно использовать centered
.
#
OffsetArrays.centered
— Function
centered(A, cp=center(A)) -> Ao
Смещает центральную координату/точку cp
массива A
в точку (0, 0, ..., 0)
. Внутренне это эквивалентно OffsetArray(A, .-cp)
.
Совместимость: OffsetArrays 1.9
Для этого метода требуется версия OffsetArrays не ниже 1.9. |
Примеры
julia> A = reshape(collect(1:9), 3, 3)
3×3 Matrix{Int64}:
1 4 7
2 5 8
3 6 9
julia> Ao = OffsetArrays.centered(A); # оси (-1:1, -1:1)
julia> Ao[0, 0]
5
julia> Ao = OffsetArray(A, OffsetArrays.Origin(0)); # оси (0:2, 0:2)
julia> Aoo = OffsetArrays.centered(Ao); # оси (-1:1, -1:1)
julia> Aoo[0, 0]
5
Пользователи могут передавать cp
, чтобы изменить интерпретацию «центральной точки», но значение выходного массива также должно быть переосмыслено. Например, если cp = map(last, axes(A))
, то эта функция смещает уже не центральную точку, а правую нижнюю точку в точку (0, 0, ..., 0)
. Обычно cp
используется для изменения поведения округления, когда массив имеет четное значение размера в некотором измерении:
julia> A = reshape(collect(1:4), 2, 2) # В идеале центр должен быть в точке (1.5, 1.5), но OffsetArrays поддерживают только целочисленные смещения.
2×2 Matrix{Int64}:
1 3
2 4
julia> OffsetArrays.centered(A, OffsetArrays.center(A, RoundUp)) # задание (2, 2) в качестве центральной точки
2×2 OffsetArray(::Matrix{Int64}, -1:0, -1:0) with eltype Int64 with indices -1:0×-1:0:
1 3
2 4
julia> OffsetArrays.centered(A, OffsetArrays.center(A, RoundDown)) # задание (1, 1) в качестве центральной точки
2×2 OffsetArray(::Matrix{Int64}, 0:1, 0:1) with eltype Int64 with indices 0:1×0:1:
1 3
2 4
См. также описание center
.