Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking: split set into unsafe_set and set #926

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
10 changes: 7 additions & 3 deletions src/DimensionalData.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ include("Dimensions/Dimensions.jl")

using .Dimensions
using .Dimensions.Lookups

using .Dimensions: StandardIndices, DimOrDimType, DimTuple, DimTupleOrEmpty, DimType, AllDims
import .Lookups: metadata, set, _set, rebuild, basetypeof,
import .Dimensions: dims, refdims, name, lookup, kw2dims, hasdim, label, checkaxes, _astuple

import .Lookups: Safety, Safe, Unsafe, SelectorOrInterval, Begin, End
import .Lookups: metadata, reorder, set, _set, rebuild, basetypeof,
order, span, sampling, locus, val, index, bounds, intervalbounds,
hasselection, units, SelectorOrInterval, Begin, End
import .Dimensions: dims, refdims, name, lookup, kw2dims, hasdim, label, _astuple
hasselection, units

using OrderedCollections: OrderedDict

Expand All @@ -51,6 +54,7 @@ export Lookups, Dimensions
# Deprecated
const LookupArrays = Lookups
const LookupArray = Lookup

export LookupArrays, LookupArray

# Dimension
Expand Down
3 changes: 2 additions & 1 deletion src/Dimensions/Dimensions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ using .Lookups
const LU = Lookups
const LookupArrays = Lookups

import .Lookups: rebuild, order, span, sampling, locus, val, index, set, _set,
import .Lookups: rebuild, order, span, sampling, locus, val, index, reorder, set, _set,
metadata, bounds, intervalbounds, units, basetypeof, unwrap, selectindices, hasselection,
shiftlocus, maybeshiftlocus, ordered_first, ordered_last, ordered_firstindex, ordered_lastindex,
promote_first, _remove
using .Lookups: StandardIndices, SelTuple, CategoricalEltypes,
LookupTrait, AllMetadata, LookupSetters, AbstractBeginEndRange,
SelectorOrInterval, Interval
import .Lookups: Safety, Safe, Unsafe

using Base: tail, OneTo, @propagate_inbounds

Expand Down
14 changes: 6 additions & 8 deletions src/Dimensions/dimunitrange.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ struct DimUnitRange{T,R<:AbstractUnitRange{T},D<:Dimension} <: AbstractUnitRange
range::R
dim::D
end

DimUnitRange{T}(r::DimUnitRange{T}) where {T<:Integer} = r
function DimUnitRange{T}(r::DimUnitRange) where {T<:Integer}
return DimUnitRange(AbstractUnitRange{T}(parent(r)), dims(r))
end
DimUnitRange{T}(r::DimUnitRange) where {T<:Integer} =
DimUnitRange(AbstractUnitRange{T}(parent(r)), dims(r))

@inline dims(r::DimUnitRange) = r.dim
@inline dims(rs::Tuple{DimUnitRange,Vararg{DimUnitRange}}) = map(dims, rs)

@inline Base.parent(r::DimUnitRange) = r.range
Base.parent(r::DimUnitRange) = r.range

function Base.reduced_index(dur::DimUnitRange)
r = Base.reduced_index(parent(dur))
Expand All @@ -21,9 +22,6 @@ function Base.reduced_index(dur::DimUnitRange)
return DimUnitRange(r, d1)
end

@inline dims(r::DimUnitRange) = r.dim
@inline dims(rs::Tuple{DimUnitRange,Vararg{DimUnitRange}}) = map(dims, rs)

# this is necessary to ensure that keyword syntax for DimArray works correctly
Base.Slice(r::DimUnitRange) = Base.Slice(parent(r))

Expand Down
15 changes: 9 additions & 6 deletions src/Dimensions/format.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ _format(::Type{D}, axis::AbstractRange) where D<:Dimension = D(NoLookup(axes(axi
_format(dim::Dimension{Colon}, axis::AbstractRange) = rebuild(dim, NoLookup(axes(axis, 1)))
function _format(dim::Dimension, axis::AbstractRange)
newlookup = format(val(dim), basetypeof(dim), axes(axis, 1))
checkaxis(newlookup, axis)
return rebuild(dim, newlookup)
newdim = rebuild(dim, newlookup)
checkaxis(newdim, axis)
return newdim
end

format(val::AbstractArray, D::Type, axis::AbstractRange) = format(AutoLookup(), D, val, axis)
Expand Down Expand Up @@ -155,18 +156,20 @@ _format(locus::Locus, D::Type, values) = locus

_order(values) = first(values) <= last(values) ? ForwardOrdered() : ReverseOrdered()

checkaxis(lookup::Transformed, axis) = nothing
checkaxis(lookup, axis) = first(axes(lookup)) == axis || _checkaxiserror(lookup, axis)
checkaxis(lookup::Union{Dimension,Lookup}, axis::AbstractUnitRange) =
first(axes(lookup)) == axis || _checkaxiserror(lookup, axis)

checkaxes(lookups::Tuple, axes::Tuple) = all(map(checkaxis, lookups, axes))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be the checkaxis function? From what I understand they are doing conceptually the same on different input. I find it quite confusing to have two different functions with such a similar name.


@noinline _explicitpoints_error() =
throw(ArgumentError("Cannot use Explicit span with Points sampling"))
@noinline _steperror(values, span) =
throw(ArgumentError("lookup step $(step(span)) does not match lookup step $(step(values))"))
@noinline _arraynosteperror() =
throw(ArgumentError("`Regular` must specify `step` size with values other than `AbstractRange`"))
@noinline _checkaxiserror(lookup, axis) =
@noinline _checkaxiserror(dimorlookup::Union{Dimension,Lookup}, axis) =
throw(DimensionMismatch(
"axes of $(basetypeof(lookup)) of $(first(axes(lookup))) do not match array axis of $axis"
"axes of $(basetypeof(dimorlookup)) of $(first(axes(dimorlookup))) do not match array axis of $axis"
))
@noinline _valformaterror(v, D::Type) =
throw(ArgumentError(
Expand Down
84 changes: 49 additions & 35 deletions src/Dimensions/set.jl
Original file line number Diff line number Diff line change
@@ -1,52 +1,66 @@
const DimSetters = Union{LookupSetters,Type,UnionAll,Dimension,Symbol}

set(dim::Dimension, ::Type{T}) where T = set(dim, T())
set(dims::DimTuple, ::Type{T}) where T = set(dims, T())
set(dim::Dimension, x::DimSetters) = _set(dim, x)
set(dims_::DimTuple, args::Union{Dimension,DimTuple,Pair}...; kw...) =

_set(dims_, args...; kw...)
set(dims::DimTuple, l::Lookup) = set(dims, map(d -> basedims(d) => l, dims)...)
set(dims::DimTuple, l::LookupTrait) = set(dims, map(d -> basedims(d) => l, dims)...)
# Convert args/kw to dims and set
_set(dims_::DimTuple, args::Dimension...; kw...) = _set(dims_, (args..., kw2dims(kw)...))
const DimSetters = Union{Lookup,LookupSetters,Tuple,Dimension,Symbol}

set(dim::Dimension, x::DimSetters) = _set(Safe(), dim, x)
set(dims::DimTuple, x::DimSetters) = _set(Safe(), dims, x)
set(dims::DimTuple, p::Pair) = _set(Safe(), dims, p)
set(dims::DimTuple, a1::Union{Dimension,Pair}, a2::Union{Dimension,Pair}, args::Union{Dimension,Pair}...) =
_set(Safe(), dims, a1, a2, args...)

unsafe_set(dim::Dimension, x::DimSetters) = _set(Unsafe(), dim, x)
unsafe_set(dims::DimTuple, x::DimSetters) = _set(Unsafe(), dims, x)
unsafe_set(dims::DimTuple, p::Pair) = _set(Unsafe(), dims, p)
unsafe_set(dims::DimTuple, a1::Union{Dimension,Pair}, a2::Union{Dimension,Pair}, args::Union{Dimension,Pair}...) =
_set(Unsafe(), dims, a1, a2, args...)

_set(s::Safety, dims::DimTuple, l::LookupSetters) =
_set(s, dims, map(d -> basedims(d) => l, dims)...)

# Convert pairs to wrapped dims and set
_set(dims_::DimTuple, p::Pair, ps::Vararg{Pair}) = _set(dims_, (p, ps...))
_set(dims_::DimTuple, ps::Tuple{Vararg{Pair}}) = _set(dims_, pairs2dims(ps...))
_set(dims_::DimTuple, ::Tuple{}) = dims_
_set(s::Safety, dims::DimTuple, p::Pair, ps::Pair...) =
_set(s, dims, (p, ps...))
_set(s::Safety, dims::DimTuple, ps::Tuple{Vararg{Pair}}) =
_set(s, dims, pairs2dims(ps...))
_set(s::Safety, dims::DimTuple, ::Tuple{}) = dims
_set(s::Safety, dims::DimTuple, newdims::Dimension...) =
_set(s, dims, newdims)
# Set dims with (possibly unsorted) wrapper vals
_set(dims::DimTuple, wrappers::DimTuple) = begin
_set(s::Safety, dims::DimTuple, wrappers::DimTuple) = begin
# Check the dimension types match
map(wrappers) do w
hasdim(dims, w) || _wrongdimserr(dims, w)
end
# Missing dims return `nothing` from sortdims
newdims = map(_set, dims, sortdims(wrappers, dims))
newdims = map(dims, sortdims(wrappers, dims)) do d, w
_set(s, d, w)
end
# Swaps existing dims with non-nothing new dims
swapdims(dims, newdims)
end

# Set things wrapped in dims
_set(dim::Dimension, wrapper::Dimension{<:DimSetters}) =
_set(_set(dim, basetypeof(wrapper)), val(wrapper))
_set(s::Safety, dim::Dimension, wrapper::Dimension{<:DimSetters}) = begin
rewrapped = _set(s, dim, basetypeof(wrapper))
x = _set(s, rewrapped, val(wrapper))
x
end
# Set the dim, checking the lookup
_set(dim::Dimension, newdim::Dimension) = _set(newdim, _set(val(dim), val(newdim)))
# Construct types
_set(dim::Dimension, ::Type{T}) where T = _set(dim, T())
_set(dim::Dimension, key::Symbol) = _set(dim, name2dim(key))
_set(dim::Dimension, dt::DimType) = basetypeof(dt)(val(dim))
_set(dim::Dimension, x) = rebuild(dim; val=_set(val(dim), x))
# Set the lookup
# Otherwise pass this on to set fields on the lookup
_set(dim::Dimension, x::LookupTrait) = rebuild(dim, _set(lookup(dim), x))
_set(s::Safety, dim::Dimension, newdim::Dimension) =
_set(s, newdim, _set(s, val(dim), val(newdim)))
_set(s::Safety, dim::Dimension, newdim::Dimension{<:Type}) =
_set(s, dim, val(newdim)())
_set(s::Safety, dim::Dimension, key::Symbol) = _set(s, dim, name2dim(key))
_set(s::Safety, dim::Dimension, x) = rebuild(dim, _set(s, val(dim), x))
_set(s::Safety, dim::Dimension, ::Type{T}) where T = _set(s, dim, T())

# Metadata
_set(dim::Dimension, newmetadata::AllMetadata) = rebuild(dim, _set(lookup(dim), newmetadata))
_set(s::Safety, dim::Dimension, newmetadata::AllMetadata) =
rebuild(dim, _set(s, lookup(dim), newmetadata))

_set(x::Dimension, ::Nothing) = x
_set(::Nothing, x::Dimension) = x
_set(::Nothing, ::Nothing) = nothing
_set(x, ::Nothing) = x
_set(::Nothing, x) = x
_set(::Safety, x::Dimension, ::Nothing) = x
_set(::Safety, ::Nothing, x::Dimension) = x
_set(::Safety, ::Nothing, ::Nothing) = nothing
_set(::Safety, x, ::Nothing) = x
_set(::Safety, ::Nothing, x) = x

@noinline _wrongdimserr(dims, w) = throw(ArgumentError("dim $(basetypeof(w))) not in $(map(basetypeof, dims))"))
@noinline _wrongdimserr(dims, w) =
throw(ArgumentError("dim $(basetypeof(w))) not in $(map(basetypeof, dims))"))
2 changes: 2 additions & 0 deletions src/Dimensions/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ for f in (:shiftlocus, :maybeshiftlocus)
end
end
end

reorder(dim::Dimension, o::Order) = rebuild(reorder(lookup(dim), o))
Loading
Loading