Skip to content

Commit

Permalink
Merge pull request #113 from rafaqz/anon
Browse files Browse the repository at this point in the history
Anon
  • Loading branch information
rafaqz authored Apr 3, 2020
2 parents fb7a9bd + f94f92f commit cfb0826
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 29 deletions.
2 changes: 1 addition & 1 deletion docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Categorical
Unaligned
Transformed
NoIndex
AutoIndex
Auto
```

Order of arrays and indices:
Expand Down
2 changes: 1 addition & 1 deletion src/DimensionalData.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export Sampling, Points, Intervals

export Span, Regular, Irregular, AutoSpan

export IndexMode, AutoIndex, UnknownIndex, NoIndex
export IndexMode, Auto, UnknownIndex, NoIndex

export Aligned, AbstractSampled, Sampled,
AbstractCategorical, Categorical
Expand Down
98 changes: 85 additions & 13 deletions src/dimension.jl
Original file line number Diff line number Diff line change
@@ -1,23 +1,56 @@
"""
Dimensions tag the dimensions of an AbstractArray, or other dimensional data.
Dimension is the abstract supertype of all dimension types.
It can also contain spatial coordinates and their metadata. For simplicity,
the same types are used both for storing dimension information and for indexing.
Example concrete implementations are `X`, `Y`, `Z`,
`Ti` (Time), and the arbirary `Dim{:custom}` dimension.
`Dimension`s label the axes of an `AbstractDimesnionalArray`,
or other dimensional data. They may also provide an alternate index
to lookup for each array axis.
Example:
```julia
using Dates
x = X(2:2:10)
y = Y(['a', 'b', 'c'])
ti = Ti(DateTime(2021, 1):Month(1):DateTime(2021, 12))
```
```julia
A = DimensionalArray(rand(3, 5, 12), (y, x, ti));
```
For simplicity, the same `Dimension` types are also used as wrappers
in `getindex`, like:
```julia
x = A[X(2), Y(3)]
```
Dimension can also wrap [`Selectors`](@ref).
```julia
x = A[X(Between(3, 4)), Y(At('b'))]
```
`Dimension` objects may have [`mode`](@ref) and [`metadata`](@ref) fields
to track additional information about the data and the index, and their relationship.
"""
abstract type Dimension{T,IM,M} end

"""
Abstract supertype for independent dimensions. Will plot on the X axis.
Abstract supertype for independent dimensions. Thise will plot on the X axis.
"""
abstract type IndependentDim{T,IM,M} <: Dimension{T,IM,M} end

"""
Abstract supertype for Dependent dimensions. Will plot on the Y axis.
Abstract supertype for Dependent dimensions. These will plot on the Y axis.
"""
abstract type DependentDim{T,IM,M} <: Dimension{T,IM,M} end

"""
Abstract parent type for all X dimensions.
Abstract parent type for all X dimensions.
"""
abstract type XDim{T,IM,M} <: IndependentDim{T,IM,M} end

Expand All @@ -33,7 +66,11 @@ abstract type ZDim{T,IM,M} <: Dimension{T,IM,M} end

"""
Abstract parent type for all time dimensions.
"""
For an index with `Interval` sampling the locus will automatically be
set to `Start()`, as a date/time index generally defines the start of a
month, second etc, not the central point as is more common with spatial data.
`"""
abstract type TimeDim{T,IM,M} <: IndependentDim{T,IM,M} end

ConstructionBase.constructorof(d::Type{<:Dimension}) = basetypeof(d)
Expand Down Expand Up @@ -130,10 +167,17 @@ Dimensions with user-set type paremeters
abstract type ParametricDimension{X,T,IM,M} <: Dimension{T,IM,M} end

"""
Dim{X}(val, mode, metadata)
Dim{X}(val=:; [mode=Auto()], [metadata=nothing])
A generic dimension. For use when custom dims are required when loading
data from a file. The sintax is ugly and verbose to use for indexing,
ie `Dim{:lat}(1:9)` rather than `Lat(1:9)`. This is the main reason
they are not the only type of dimension availabile.
```julia
dim = Dim{:custom}(['a', 'b', 'c'])
```
"""
struct Dim{X,T,IM<:IndexMode,M} <: ParametricDimension{X,T,IM,M}
val::T
Expand All @@ -143,13 +187,15 @@ struct Dim{X,T,IM<:IndexMode,M} <: ParametricDimension{X,T,IM,M}
new{X,typeof(val),typeof(mode),typeof(metadata)}(val, mode, metadata)
end

Dim{X}(val=:; mode=AutoIndex(), metadata=nothing) where X =
Dim{X}(val=:; mode=Auto(), metadata=nothing) where X =
Dim{X}(val, mode, metadata)
name(::Type{<:Dim{X}}) where X = "Dim $X"
shortname(::Type{<:Dim{X}}) where X = "$X"
basetypeof(::Type{<:Dim{X}}) where {X} = Dim{X}

"""
AnonDim()
Anonymous dimension. Used when extra dimensions are created,
such as during transpose of a vector.
"""
Expand Down Expand Up @@ -190,27 +236,53 @@ dimmacro(typ, supertype, name=string(typ), shortname=string(typ)) =
mode::IM
metadata::M
end
$typ(val=:; mode=AutoIndex(), metadata=nothing) =
$typ(val=:; mode=Auto(), metadata=nothing) =
$typ(val, mode, metadata)
DimensionalData.name(::Type{<:$typ}) = $name
DimensionalData.shortname(::Type{<:$typ}) = $shortname
end)

# Define some common dimensions.
@dim X XDim
@doc "X dimension. `X <: XDim <: IndependentDim`" X
@doc """
X [`Dimension`](@ref). `X <: XDim <: IndependentDim`
## Example:
```julia
x = X(2:2:10)
```
""" X

@dim Y YDim
@doc "Y dimension. `Y <: YDim <: DependentDim`" Y
@doc """
Y [`Dimension`](@ref). `Y <: YDim <: DependentDim`
## Example:
```julia
y = Y(['a', 'b', 'c'])
```
""" Y

@dim Z ZDim
@doc "Z dimension. `Z <: ZDim <: Dimension`" Z
@doc """
Z [`Dimension`](@ref). `Z <: ZDim <: Dimension`
## Example:
```julia
z = Z(10:10:100)
```
""" Z

@dim Ti TimeDim "Time"
@doc """
Time dimension. `Ti <: TimeDim <: IndependentDim`
Time [`Dimension`](@ref). `Ti <: TimeDim <: IndependentDim`
`Time` is already used by Dates, so we use `Ti` to avoid clashing.
## Example:
```julia
ti = Ti(DateTime(2021, 1):Month(1):DateTime(2021, 12))
```
""" Ti

# Time dimensions need to default to the Start() locus, as that is
Expand Down
10 changes: 5 additions & 5 deletions src/mode.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,12 @@ order(mode::NoIndex) = Ordered(Forward(), Forward(), Forward())
Automatic [`IndexMode`](@ref). Will be converted automatically to another
`IndexMode` when possible.
"""
struct AutoIndex{O<:Order} <: IndexMode
struct Auto{O<:Order} <: IndexMode
order::O
end
AutoIndex() = AutoIndex(AutoOrder())
Auto() = Auto(AutoOrder())

order(mode::AutoIndex) = mode.order
order(mode::Auto) = mode.order

"""
Supertype for [`IndexMode`](@ref) where the index is aligned with the array axes.
Expand Down Expand Up @@ -388,9 +388,9 @@ identify(IM::Type{<:IndexMode}, dimtype::Type, index) =
identify(IM(), dimtype, index)
identify(mode::IndexMode, dimtype::Type, index) = mode

identify(mode::AutoIndex, dimtype::Type, index::AbstractArray) =
identify(mode::Auto, dimtype::Type, index::AbstractArray) =
identify(Sampled(), dimtype, index)
identify(mode::AutoIndex, dimtype::Type,
identify(mode::Auto, dimtype::Type,
index::AbstractArray{<:Union{AbstractChar,Symbol,AbstractString}}) =
Categorical()
identify(mode::AbstractCategorical, dimtype::Type, index) = mode
Expand Down
2 changes: 1 addition & 1 deletion test/dimension.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ using DimensionalData: Forward, slicedims
@test label(TestDim) == "Test dimension"
@test shortname(TestDim) == "TestDim"
@test val(TestDim(:test)) == :test
@test metadata(TestDim(1, AutoIndex(), "metadata")) == "metadata"
@test metadata(TestDim(1, Auto(), "metadata")) == "metadata"
@test units(TestDim) == nothing
@test label(TestDim) == "Test dimension"
@test eltype(TestDim(1)) <: Int
Expand Down
16 changes: 8 additions & 8 deletions test/mode.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ using DimensionalData: Forward, Reverse,
@test identify(Sampled(sampling=Intervals()), Ti, 1:2:3) ==
Sampled(Ordered(), Regular(2), Intervals(Start()))

@test identify(AutoIndex(), X, 1:2:10) ==
@test identify(Auto(), X, 1:2:10) ==
Sampled(Ordered(), Regular(2), Points())
@test identify(AutoIndex(), X, [1, 2, 3, 4, 5]) ==
@test identify(Auto(), X, [1, 2, 3, 4, 5]) ==
Sampled(Ordered(), Irregular(), Points())

@test identify(Sampled(), X, 1:2:10) ==
Expand All @@ -27,14 +27,14 @@ using DimensionalData: Forward, Reverse,
@test identify(Sampled(order=Ordered(Reverse(), Forward(), Forward())), X, 10:-2:1) ==
Sampled(Ordered(Reverse(), Forward(), Forward()), Regular(-2), Points())

@test identify(AutoIndex(), X, [:a, :b]) == Categorical()
@test identify(AutoIndex(), X, ["a", "b"]) == Categorical()
@test identify(AutoIndex(), X, ['a', 'b']) == Categorical()
@test identify(AutoIndex(), X, [1, 2, 3, 4]) ==
@test identify(Auto(), X, [:a, :b]) == Categorical()
@test identify(Auto(), X, ["a", "b"]) == Categorical()
@test identify(Auto(), X, ['a', 'b']) == Categorical()
@test identify(Auto(), X, [1, 2, 3, 4]) ==
Sampled(span=Irregular())
@test_broken identify(AutoIndex(AutoOrder()), X, [4, 3, 2, 1]) ==
@test_broken identify(Auto(AutoOrder()), X, [4, 3, 2, 1]) ==
Sampled(Ordered(Reverse(), Forward(), Forward()), NoLocus())
@test_broken identify(AutoIndex(AutoOrder()), X, [1, 3, 2, 9]) ==
@test_broken identify(Auto(AutoOrder()), X, [1, 3, 2, 9]) ==
Sampled(Unordered(Forward(), NoLocus()))

end
Expand Down

0 comments on commit cfb0826

Please sign in to comment.