|
109 | 109 | ds = DD.dims(A, _astuple(dims))
|
110 | 110 | # Run one slice with dimensions to get the transformed dim
|
111 | 111 | d_inds = map(d -> rebuild(d, 1), otherdims(A, ds))
|
112 |
| - example_dims = length(d_inds) > 0 ? DD.dims(f(view(A, d_inds...))) : () |
| 112 | + example_dims = DD.dims(f(view(A, d_inds...))) |
113 | 113 | replacement_dims = if isnothing(example_dims) || length(example_dims) != length(ds)
|
114 | 114 | map(d -> rebuild(d, NoLookup()), ds)
|
115 | 115 | else
|
@@ -547,6 +547,100 @@ $message on dimension $D.
|
547 | 547 | To fix for `AbstractDimArray`, pass new lookup values as `cat(As...; dims=$D(newlookupvals))` keyword or `dims=$D()` for empty `NoLookup`.
|
548 | 548 | """
|
549 | 549 |
|
| 550 | +function Base._typed_stack(::Colon, ::Type{T}, ::Type{S}, A, Aax=_iterator_axes(A)) where {T,S<:AbstractDimArray} |
| 551 | + origdims = map(dims, A) |
| 552 | + _A = parent.(A) |
| 553 | + t = eltype(_A) |
| 554 | + _A = Base._typed_stack(:, T, t, A) |
| 555 | + |
| 556 | + if !comparedims(Bool, origdims...; |
| 557 | + order=true, val=true, warn=" Can't `stack` AbstractDimArray, applying to `parent` object." |
| 558 | + ) |
| 559 | + return _A |
| 560 | + else |
| 561 | + DimArray(_A, (first(origdims)..., AnonDim())) |
| 562 | + end |
| 563 | +end |
| 564 | + |
| 565 | +function Base._dim_stack(newdim::Integer, ::Type{T}, ::Type{S}, A) where {T,S<:AbstractDimArray} |
| 566 | + origdims = dims.(A) |
| 567 | + _A = parent.(A) |
| 568 | + t = eltype(_A) |
| 569 | + _A = Base._dim_stack(newdim, T, t, A) |
| 570 | + |
| 571 | + if !comparedims(Bool, origdims...; |
| 572 | + order=true, val=true, warn=" Can't `stack` AbstractDimArray, applying to `parent` object." |
| 573 | + ) |
| 574 | + return _A |
| 575 | + end |
| 576 | + |
| 577 | + newdims = first(origdims) |
| 578 | + newdims = ntuple(length(newdims) + 1) do d |
| 579 | + if d == newdim |
| 580 | + AnonDim() |
| 581 | + else # Return the old dimension, shifted across once if it comes after the new dim |
| 582 | + newdims[d-(d>newdim)] |
| 583 | + end |
| 584 | + end |
| 585 | + DimArray(_A, newdims) |
| 586 | +end |
| 587 | + |
| 588 | +""" |
| 589 | + Base.stack(A::AbstractVector{<:AbstractDimArray}; dims=Pair(ndims(A[1])+1, AnonDim())) |
| 590 | +
|
| 591 | +Stack arrays along a new axis while preserving the dimensional information of other axes. |
| 592 | +
|
| 593 | +The optional keyword argument `dims` has the following behavior: |
| 594 | +- `dims isa Integer`: The dimension of the new axis is an `AnonDim` at position `dims` |
| 595 | +- `dims isa Dimension`: The new axis is at `ndims(A[1])+1` and has a dimension of `dims`. |
| 596 | +- `dims isa Pair{Integer, Dimension}`: The new axis is at `first(dims)` and has a dimension |
| 597 | + of `last(dims)`. |
| 598 | +
|
| 599 | +If `dims` contains a `Dimension`, that `Dimension` must have the same length as A. |
| 600 | +
|
| 601 | +# Examples |
| 602 | +```julia-repl |
| 603 | +julia> da = DimArray([1 2 3; 4 5 6], (X(10:10:20), Y(300:-100:100))); |
| 604 | +julia> db = DimArray([6 5 4; 3 2 1], (X(10:10:20), Y(300:-100:100))); |
| 605 | +
|
| 606 | +# Stack along a new dimension `Z` |
| 607 | +julia> dc = stack([da, db], dims=3=>Z(1:2)) |
| 608 | +╭─────────────────────────╮ |
| 609 | +│ 2×3×2 DimArray{Int64,3} │ |
| 610 | +├─────────────────────────┴──────────────────────────────── dims ┐ |
| 611 | + ↓ X Sampled{Int64} 10:10:20 ForwardOrdered Regular Points, |
| 612 | + → Y Sampled{Int64} 300:-100:100 ReverseOrdered Regular Points, |
| 613 | + ↗ Z 1:2 |
| 614 | +└────────────────────────────────────────────────────────────────┘ |
| 615 | +
|
| 616 | +julia> dims(dc, 3) == Z(1:2) |
| 617 | +true |
| 618 | +julia> parent(dc) == stack(map(parent, [da, db]), dims=3) |
| 619 | +true |
| 620 | +``` |
| 621 | +""" |
| 622 | +function Base.stack(A::AbstractVector{<:AbstractDimArray}; dims=Pair(ndims(A[1])+1, AnonDim())) |
| 623 | + if dims isa Integer |
| 624 | + dims = dims => AnonDim() |
| 625 | + elseif dims isa Dimension |
| 626 | + dims = ndims(A[1])+1 => dims |
| 627 | + end |
| 628 | + |
| 629 | + B = Base._stack(first(dims), A) |
| 630 | + |
| 631 | + if B isa AbstractDimArray |
| 632 | + newdims = ntuple(ndims(B)) do d |
| 633 | + if d == first(dims) # Use the new provided dimension |
| 634 | + last(dims) |
| 635 | + else |
| 636 | + DimensionalData.dims(B, d) |
| 637 | + end |
| 638 | + end |
| 639 | + B = rebuild(B; dims=format(newdims, B)) |
| 640 | + end |
| 641 | + return B |
| 642 | +end |
| 643 | + |
550 | 644 | function Base.inv(A::AbstractDimArray{T,2}) where T
|
551 | 645 | newdata = inv(parent(A))
|
552 | 646 | newdims = reverse(dims(A))
|
|
0 commit comments