Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
cd83dfe
include DataType in CategoricalEltypes (#876)
tiemvanderdeure Mar 8, 2025
685efd7
Breaking: `DimVector` of `NamedTuple` is a `NamedTuple` `DimTable` (#…
rafaqz Mar 8, 2025
49746ef
Breaking: add `combine` method for `groupby` output, fixing `similar`…
rafaqz Mar 8, 2025
4b8bd51
Breaking: `preservedims` in tables (#917)
rafaqz Mar 26, 2025
5a96fb3
Merge branch 'main' into breaking
asinghvi17 May 4, 2025
db6311c
Remove deprecations (#1009)
felixcremer May 9, 2025
a1ee568
Merge branch 'main' into breaking
rafaqz Jun 28, 2025
8d19346
typo
rafaqz Jun 28, 2025
b0f5df1
add missing reference docs
rafaqz Jun 28, 2025
eb31c61
fix DimSlices doc
rafaqz Jun 28, 2025
886a2b2
Breaking: skipmissing on a dimstack (#1041)
tiemvanderdeure Jul 13, 2025
cc4928e
Breaking: Materialize `DimArray` or `DimStack` From a Table (#739)
JoshuaBillson Aug 10, 2025
605ac84
Merge branch 'main' into breaking
rafaqz Aug 14, 2025
541ff30
start a CHANGELOG
Aug 15, 2025
288bf74
bump minor version to 0.30.0
Aug 15, 2025
648635c
document Changelog.jl usage
Aug 15, 2025
8069385
use rebuild for similar of dimarray with new axes (#1082)
tiemvanderdeure Aug 17, 2025
5669858
Breaking: standardise interface methods and remove `index` (#1083)
rafaqz Aug 21, 2025
a8d08ac
move abstract constructors to DimArray constructors (#1087)
rafaqz Aug 21, 2025
4af492e
Forward name keyword in groupby (#1084)
felixcremer Aug 21, 2025
1a6e7ed
Remove rtol from At selector (#1062)
felixcremer Aug 22, 2025
194f320
Merge branch 'main' into breaking
rafaqz Sep 15, 2025
8892390
fix selector tests
rafaqz Sep 15, 2025
9156dd3
fix At in dimindices
rafaqz Sep 15, 2025
fd8f0ef
Breaking: remove methods that are hardly uesd and cause many invalida…
tiemvanderdeure Oct 15, 2025
2e5a812
Merge branch 'main' into breaking
tiemvanderdeure Oct 15, 2025
fe0bda9
Implement `Base.instantiate` - take 2 (#1118)
tiemvanderdeure Oct 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/src/api/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ prune
DimIndices
DimSelectors
DimPoints
DimSlices
```

## Tables.jl/TableTraits.jl interface
Expand All @@ -70,6 +71,7 @@ For transforming DimensionalData objects:

```@docs
groupby
combine
DimensionalData.DimGroupByArray
Bins
ranges
Expand Down Expand Up @@ -138,6 +140,7 @@ DimensionalData.NoName
DimensionalData.DimArrayInterface
DimensionalData.DimStackInterface
DimensionalData.rebuild_from_arrays
DimensionalData.rebuildsliced
DimensionalData.show_main
DimensionalData.show_after
DimensionalData.refdims_title
Expand Down
6 changes: 3 additions & 3 deletions src/DimensionalData.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ export AbstractDimTable, DimTable

export AbstractDimTree, DimTree, prune

export DimIndices, DimSelectors, DimPoints, #= deprecated =# DimKeys

export DimIndices, DimSelectors, DimPoints
# getter methods
export dims, refdims, metadata, name, lookup, bounds, val, layers

Expand All @@ -83,7 +82,7 @@ export dimnum, hasdim, hasselection, otherdims
export set, rebuild, reorder, modify, broadcast_dims, broadcast_dims!,
mergedims, unmergedims, maplayers

export groupby, seasons, months, hours, intervals, ranges
export groupby, combine, seasons, months, hours, intervals, ranges


export @d
Expand Down Expand Up @@ -116,6 +115,7 @@ include("tables.jl")
include("plotrecipes.jl")
include("utils.jl")
include("set.jl")
include("opaque.jl")
include("groupby.jl")
include("precompile.jl")
include("interface_tests.jl")
Expand Down
1 change: 1 addition & 0 deletions src/Dimensions/dimension.jl
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@
Base.eachindex(d::Dimension) = eachindex(val(d))
Base.length(d::Dimension) = length(val(d))
Base.ndims(d::Dimension) = 0
Base.parentindices(d::Dimension{<:AbstractArray}) = parentindices(parent(d))

Check warning on line 276 in src/Dimensions/dimension.jl

View check run for this annotation

Codecov / codecov/patch

src/Dimensions/dimension.jl#L276

Added line #L276 was not covered by tests
Base.ndims(d::Dimension{<:AbstractArray}) = ndims(val(d))
Base.iterate(d::Dimension{<:AbstractArray}, args...) = iterate(lookup(d), args...)
Base.first(d::Dimension) = val(d)
Expand Down
6 changes: 2 additions & 4 deletions src/Lookups/Lookups.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,15 @@ export Unaligned, Transformed, ArrayLookup
# Deprecated
export LookupArray

const StandardIndices = Union{AbstractArray{<:Integer},Colon,Integer,CartesianIndex,CartesianIndices}

# As much as possible keyword rebuild is automatic
rebuild(x; kw...) = ConstructionBase.setproperties(x, (; kw...))

include("metadata.jl")
include("lookup_traits.jl")
include("metadata.jl")
include("lookup_arrays.jl")
include("beginend.jl")
include("predicates.jl")
include("selector.jl")
include("beginend.jl")
include("indexing.jl")
include("methods.jl")
include("utils.jl")
Expand Down
2 changes: 2 additions & 0 deletions src/Lookups/beginend.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ Base.to_indices(A, inds, (r, args...)::Tuple{<:Union{Begin,End,<:LazyMath},Varar
_to_index(inds, a::Int) = a
_to_index(inds, ::Begin) = first(inds)
_to_index(inds, ::End) = last(inds)
_to_index(inds, ::Type{Begin}) = first(inds)
_to_index(inds, ::Type{End}) = last(inds)
_to_index(inds, l::LazyMath{End}) = l.f(last(inds))
_to_index(inds, l::LazyMath{Begin}) = l.f(first(inds))

Expand Down
13 changes: 7 additions & 6 deletions src/Lookups/lookup_arrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
Base.last(l::Lookup) = last(parent(l))
Base.firstindex(l::Lookup) = firstindex(parent(l))
Base.lastindex(l::Lookup) = lastindex(parent(l))
Base.parentindices(l::Lookup) = parentindices(parent(l))

Check warning on line 35 in src/Lookups/lookup_arrays.jl

View check run for this annotation

Codecov / codecov/patch

src/Lookups/lookup_arrays.jl#L35

Added line #L35 was not covered by tests
function Base.:(==)(l1::Lookup, l2::Lookup)
basetypeof(l1) == basetypeof(l2) && parent(l1) == parent(l2)
end
Expand Down Expand Up @@ -159,11 +160,10 @@
rebuild(l::NoLookup; data=parent(l), kw...) = NoLookup(data)

# Used in @d broadcasts
struct Length1NoLookup <: AbstractNoLookup end
Length1NoLookup(::AbstractVector) = Length1NoLookup()

rebuild(l::Length1NoLookup; kw...) = Length1NoLookup()
Base.parent(::Length1NoLookup) = Base.OneTo(1)
struct Length1NoLookup{A<:AbstractUnitRange} <: AbstractNoLookup
data::A
end
Length1NoLookup() = Length1NoLookup(Base.OneTo(1))

"""
AbstractSampled <: Aligned
Expand Down Expand Up @@ -468,7 +468,7 @@
order(lookup::AbstractCategorical) = lookup.order
metadata(lookup::AbstractCategorical) = lookup.metadata

const CategoricalEltypes = Union{AbstractChar,Symbol,AbstractString}
const CategoricalEltypes = Union{AbstractChar,Symbol,AbstractString,DataType}

function Adapt.adapt_structure(to, l::AbstractCategorical)
rebuild(l; data=Adapt.adapt(to, parent(l)), metadata=NoMetadata())
Expand Down Expand Up @@ -866,6 +866,7 @@
# Fallback NoLookup if not identical type
promote_first(l1::Lookup) = l1
promote_first(l1::L, ls::L...) where L<:Lookup = rebuild(l1; metadata=NoMetadata)
promote_first(l1::L, ls::L...) where L<:AbstractNoLookup = l1
function promote_first(l1::Lookup, ls1::Lookup...)
ls = _remove(Length1NoLookup, l1, ls1...)
if length(ls) != length(ls1) + 1
Expand Down
9 changes: 9 additions & 0 deletions src/Lookups/selector.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
const StandardIndices = Union{
AbstractArray{<:Integer},
Colon,
Integer,
CartesianIndex,
CartesianIndices,
BeginEndRange,
}

struct SelectorError{L,S} <: Exception
lookup::L
selector::S
Expand Down
2 changes: 0 additions & 2 deletions src/Lookups/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ end
_order(A) = first(A) <= last(A) ? ForwardOrdered() : ReverseOrdered()
_order(A::AbstractArray{<:IntervalSets.Interval}) = first(A).left <= last(A).left ? ForwardOrdered() : ReverseOrdered()

@deprecate maybeshiftlocus maybeshiftlocus
@deprecate shiftlocus shiftlocus

# Remove objects of type T from a
Base.@assume_effects :foldable _remove(::Type{T}, x, xs...) where T = (x, _remove(T, xs...)...)
Expand Down
72 changes: 55 additions & 17 deletions src/array/array.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const IDim = Dimension{<:StandardIndices}
const MaybeDimTuple = Tuple{Vararg{Dimension}}

"""
AbstractBasicDimArray <: AbstractArray
Expand All @@ -8,7 +9,7 @@

Only keyword `rebuild` is guaranteed to work with `AbstractBasicDimArray`.
"""
abstract type AbstractBasicDimArray{T,N,D<:Tuple{Vararg{Dimension}}} <: AbstractArray{T,N} end
abstract type AbstractBasicDimArray{T,N,D<:MaybeDimTuple} <: AbstractArray{T,N} end

const AbstractBasicDimVector = AbstractBasicDimArray{T,1} where T
const AbstractBasicDimMatrix = AbstractBasicDimArray{T,2} where T
Expand Down Expand Up @@ -94,10 +95,27 @@

layerdims(A::AbstractDimArray) = basedims(A)

@inline rebuildsliced(A::AbstractBasicDimArray, args...) = rebuildsliced(getindex, A, args...)
@inline function rebuildsliced(f::Function, A::AbstractBasicDimArray, data::AbstractArray, I::Tuple, name=name(A))
"""
rebuildsliced(f::Function, A::AbstractBasicDimArray, I)

Rebuild `AbstractDimArray` where `f` is `getindex` , `view` or `dotview`.

This does not need to be defined for `AbstractDimArray`, as `f`
is simply called on the parent array, dims and refdims are sliced with `slicedims`,
and `rebuild` is called.

However for custom `AbstractBasicDimArray`, `rebuildsliced` methods are needed
to define slicing behavior, as there not be a parent array.
"""
@propagate_inbounds rebuildsliced(A::AbstractBasicDimArray, args...) = rebuildsliced(getindex, A, args...)

Check warning on line 110 in src/array/array.jl

View check run for this annotation

Codecov / codecov/patch

src/array/array.jl#L110

Added line #L110 was not covered by tests
@propagate_inbounds function rebuildsliced(f::Function, A::AbstractDimArray, I::Tuple, name=name(A))
I1 = to_indices(A, I)
data = f(parent(A), I1...)
return rebuildsliced(f, A, data, I1, name)
end
@propagate_inbounds function rebuildsliced(f::Function, A::AbstractDimArray, data::AbstractArray, I::Tuple, name=name(A))
I1 = to_indices(A, I)
rebuild(A, data, slicedims(f, A, I1)..., name)
return rebuild(A, data, slicedims(f, A, I1)..., name)
end

# Array interface methods ######################################################
Expand All @@ -107,6 +125,7 @@
Base.iterate(A::AbstractDimArray, args...) = iterate(parent(A), args...)
Base.IndexStyle(A::AbstractDimArray) = Base.IndexStyle(parent(A))
Base.parent(A::AbstractDimArray) = data(A)
Base.parentindices(A::AbstractDimArray) = parentindices(parent(A))

Check warning on line 128 in src/array/array.jl

View check run for this annotation

Codecov / codecov/patch

src/array/array.jl#L128

Added line #L128 was not covered by tests
Base.vec(A::AbstractDimArray) = vec(parent(A))
# Only compare data and dim - metadata and refdims can be different
Base.:(==)(A1::AbstractDimArray, A2::AbstractDimArray) =
Expand Down Expand Up @@ -170,14 +189,6 @@
# An alternative would be to fill missing dims with `Anon`, and keep existing
# dims but strip the Lookup? It just seems a little complicated when the methods
# below using DimTuple work better anyway.
Base.similar(A::AbstractDimArray, i::Integer, I::Vararg{Integer}; kw...) =
similar(A, eltype(A), (i, I...); kw...)
Base.similar(A::AbstractDimArray, I::Tuple{Int,Vararg{Int}}; kw...) =
similar(A, eltype(A), I; kw...)
Base.similar(A::AbstractDimArray, ::Type{T}, i::Integer, I::Vararg{Integer}; kw...) where T =
similar(A, T, (i, I...); kw...)
Base.similar(A::AbstractDimArray, ::Type{T}, I::Tuple{Int,Vararg{Int}}; kw...) where T =
similar(parent(A), T, I)

const MaybeDimUnitRange = Union{Integer,Base.OneTo,Dimensions.DimUnitRange}
# when all axes are DimUnitRanges we can return an `AbstractDimArray`
Expand Down Expand Up @@ -256,14 +267,27 @@
end

# With Dimensions we can return an `AbstractDimArray`
Base.similar(A::AbstractBasicDimArray, D::DimTuple; kw...) = Base.similar(A, eltype(A), D; kw...)
Base.similar(A::AbstractBasicDimArray, D::Dimension...; kw...) = Base.similar(A, eltype(A), D; kw...)
Base.similar(A::AbstractBasicDimArray, ::Type{T}, D::Dimension...; kw...) where T =
Base.similar(A, T, D; kw...)
Base.similar(A::AbstractBasicDimArray, d1::Dimension, D::Dimension...; kw...) =
Base.similar(A, eltype(A), (d1, D...); kw...)
Base.similar(A::AbstractBasicDimArray, ::Type{T}, d1::Dimension, D::Dimension...; kw...) where T =
Base.similar(A, T, (d1, D...); kw...)
Base.similar(A::AbstractBasicDimArray, D::DimTuple; kw...) =
Base.similar(A, eltype(A), D; kw...)
function Base.similar(A::AbstractBasicDimArray, ::Type{T}, D::DimTuple; kw...) where T
data = _arraytype(T)(undef, _dimlength(D))
dimconstructor(D)(data, D; kw...)
end
function Base.similar(A::AbstractBasicDimArray, ::Type{T}, D::Tuple{};

Check warning on line 280 in src/array/array.jl

View check run for this annotation

Codecov / codecov/patch

src/array/array.jl#L280

Added line #L280 was not covered by tests
refdims=(), name=_noname(A), metadata=NoMetadata(), kw...
) where T
data = _arraytype(T)(undef, _dimlength(D))
dimconstructor(D)(data, (); refdims, name, metadata, kw...)

Check warning on line 284 in src/array/array.jl

View check run for this annotation

Codecov / codecov/patch

src/array/array.jl#L283-L284

Added lines #L283 - L284 were not covered by tests
end

function Base.similar(A::AbstractDimArray, ::Type{T}, D::DimTuple;
refdims=(), name=_noname(A), metadata=NoMetadata(), kw...
) where T
data = similar(parent(A), T, _dimlength(D))
data = _arraytype(T)(undef, _dimlength(D))
dims = _maybestripval(D)
return rebuild(A; data, dims, refdims, metadata, name, kw...)
end
Expand All @@ -274,6 +298,20 @@
rebuild(A; data, dims=(), refdims, metadata, name, kw...)
end

Base.similar(A::AbstractBasicDimArray, shape::Int...; kw...) =
similar(A, eltype(A), shape; kw...)
Base.similar(A::AbstractBasicDimArray, shape::Tuple{Vararg{Int}}; kw...) =
similar(A, eltype(A), shape; kw...)
Base.similar(A::AbstractBasicDimArray, ::Type{T}, shape::Int...; kw...) where T =
similar(A, T, shape; kw...)
Base.similar(A::AbstractBasicDimArray, ::Type{T}, shape::Tuple{Vararg{Int}}; kw...) where T =
_arraytype(T)(undef, shape)
Base.similar(A::AbstractDimArray, ::Type{T}, shape::Tuple{Vararg{Int}}; kw...) where T =
similar(parent(A), T, shape)

_arraytype(::Type{T}) where T = Array{T}
_arraytype(::Type{Bool}) = BitArray

# Keep the same type in `similar`
_noname(A::AbstractBasicDimArray) = _noname(name(A))
_noname(s::String) = ""
Expand Down
40 changes: 36 additions & 4 deletions src/array/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
# It preserves the dimension names.
# `S` should be the `BroadcastStyle` of the wrapped type.
# Copied from NamedDims.jl (thanks @oxinabox).
struct DimensionalStyle{S <: BroadcastStyle} <: AbstractArrayStyle{Any} end
struct BasicDimensionalStyle{N} <: AbstractArrayStyle{Any} end

struct DimensionalStyle{S<:BroadcastStyle} <: AbstractArrayStyle{Any} end
DimensionalStyle(::S) where {S} = DimensionalStyle{S}()
DimensionalStyle(::S, ::Val{N}) where {S,N} = DimensionalStyle(S(Val(N)))
DimensionalStyle(::Val{N}) where N = DimensionalStyle{DefaultArrayStyle{N}}()
Expand All @@ -53,6 +55,8 @@
inner_style = typeof(BroadcastStyle(A))
return DimensionalStyle{inner_style}()
end
BroadcastStyle(::Type{<:AbstractBasicDimArray{T,N}}) where {T,N} =
BasicDimensionalStyle{N}()

BroadcastStyle(::DimensionalStyle, ::Base.Broadcast.Unknown) = Unknown()
BroadcastStyle(::Base.Broadcast.Unknown, ::DimensionalStyle) = Unknown()
Expand All @@ -79,12 +83,31 @@
dims = format(Dimensions.promotedims(bdims...; skip_length_one=true), data)
return rebuild(A; data, dims, refdims=refdims(A), name=Symbol(""))
end
function Broadcast.copy(bc::Broadcasted{BasicDimensionalStyle{N}}) where N
A = _firstdimarray(bc)
data = collect(bc)
A isa Nothing && return data # No AbstractDimArray

bdims = _broadcasted_dims(bc)
_comparedims_broadcast(A, bdims...)

data isa AbstractArray || return data # result is a scalar

# Return an AbstractDimArray
dims = format(Dimensions.promotedims(bdims...; skip_length_one=true), data)
return dimconstructor(dims)(data, dims; refdims=refdims(A), name=Symbol(""))
end

function Base.copyto!(dest::AbstractArray, bc::Broadcasted{DimensionalStyle{S}}) where S
fda = _firstdimarray(bc)
isnothing(fda) || _comparedims_broadcast(fda, _broadcasted_dims(bc)...)
copyto!(dest, _unwrap_broadcasted(bc))
end
function Base.copyto!(dest::AbstractArray, bc::Broadcasted{BasicDimensionalStyle{N}}) where N
fda = _firstdimarray(bc)
isnothing(fda) || _comparedims_broadcast(fda, _broadcasted_dims(bc)...)
copyto!(dest, bc)

Check warning on line 109 in src/array/broadcast.jl

View check run for this annotation

Codecov / codecov/patch

src/array/broadcast.jl#L106-L109

Added lines #L106 - L109 were not covered by tests
end

@inline function Base.Broadcast.materialize!(dest::AbstractDimArray, bc::Base.Broadcast.Broadcasted{<:Any})
# Need to check whether the dims are compatible in dest,
Expand All @@ -97,7 +120,15 @@

function Base.similar(bc::Broadcast.Broadcasted{DimensionalStyle{S}}, ::Type{T}) where {S,T}
A = _firstdimarray(bc)
rebuildsliced(A, similar(_unwrap_broadcasted(bc), T, axes(bc)...), axes(bc), Symbol(""))
data = similar(_unwrap_broadcasted(bc), T, size(bc))
dims, refdims = slicedims(A, axes(bc))
return rebuild(A; data, dims, refdims, name=Symbol(""))
end
function Base.similar(bc::Broadcast.Broadcasted{BasicDimensionalStyle{N}}, ::Type{T}) where {N,T}
A = _firstdimarray(bc)
data = similar(A, T, size(bc))
dims, refdims = slicedims(A, axes(bc))
return dimconstructor(dims)(data, dims; refdims, name=Symbol(""))

Check warning on line 131 in src/array/broadcast.jl

View check run for this annotation

Codecov / codecov/patch

src/array/broadcast.jl#L127-L131

Added lines #L127 - L131 were not covered by tests
end


Expand Down Expand Up @@ -386,9 +417,10 @@

# Get the first dimensional array in the broadcast
_firstdimarray(x::Broadcasted) = _firstdimarray(x.args)
_firstdimarray(x::Tuple{<:AbstractDimArray,Vararg}) = x[1]
_firstdimarray(x::Tuple{<:AbstractBasicDimArray,Vararg}) = x[1]
_firstdimarray(x::AbstractBasicDimArray) = x

Check warning on line 421 in src/array/broadcast.jl

View check run for this annotation

Codecov / codecov/patch

src/array/broadcast.jl#L421

Added line #L421 was not covered by tests
_firstdimarray(ext::Base.Broadcast.Extruded) = _firstdimarray(ext.x)
function _firstdimarray(x::Tuple{<:Broadcasted,Vararg})
function _firstdimarray(x::Tuple{<:Union{Broadcasted,Base.Broadcast.Extruded},Vararg})
found = _firstdimarray(x[1])
if found isa Nothing
_firstdimarray(tail(x))
Expand Down
Loading
Loading