@@ -161,33 +161,43 @@ immutable AxisArray{T,N,D,Ax} <: AbstractArray{T,N}
161
161
end
162
162
#
163
163
_defaultdimname (i) = i == 1 ? (:row ) : i == 2 ? (:col ) : i == 3 ? (:page ) : Symbol (:dim_ , i)
164
+
165
+ default_axes (A:: AbstractArray ) = _default_axes (A, indices (A), ())
166
+ _default_axes {T,N} (A:: AbstractArray{T,N} , inds, axs:: NTuple{N} ) = axs
167
+ @inline _default_axes {T,N,M} (A:: AbstractArray{T,N} , inds, axs:: NTuple{M} ) =
168
+ _default_axes (A, inds, (axs... , _nextaxistype (A, axs)(inds[M+ 1 ])))
169
+ # Why doesn't @pure work here?
170
+ @generated function _nextaxistype {T,M} (A:: AbstractArray{T} , axs:: NTuple{M} )
171
+ name = _defaultdimname (M+ 1 )
172
+ :(Axis{$ (Expr (:quote , name))})
173
+ end
174
+
164
175
AxisArray (A:: AbstractArray , axs:: Axis... ) = AxisArray (A, axs)
165
- @generated function AxisArray {T,N,L} (A:: AbstractArray{T,N} , axs:: NTuple{L,Axis} )
166
- ax = Expr (:tuple )
167
- Ax = Tuple{axs. parameters... ,
168
- ntuple (i-> Axis{_defaultdimname (i+ L),UnitRange{Int64}},N- L)... }
169
- if ! all (x-> isa (axisname (x),Symbol), axs. parameters)
170
- return :(throw (ArgumentError (" the Axis names must be Symbols" )))
171
- end
172
- for i= 1 : L
173
- push! (ax. args, :(axs[$ i]))
174
- end
175
- for i= L+ 1 : N
176
- push! (ax. args, :(Axis {_defaultdimname($i)} (indices (A, $ i))))
177
- end
178
- quote
179
- for i = 1 : length (axs)
180
- checkaxis (axs[i]. val)
181
- if _length (axs[i]. val) != _size (A, i)
182
- throw (ArgumentError (" the length of each axis must match the corresponding size of data" ))
183
- end
184
- end
185
- if length (unique (axisnames ($ (ax. args... )))) != N
186
- throw (ArgumentError (" axis names $(axisnames ($ (ax. args... ))) must be unique" ))
187
- end
188
- $ (AxisArray{T,N,A,Ax})(A, $ ax)
176
+ function AxisArray {T,N} (A:: AbstractArray{T,N} , axs:: NTuple{N,Axis} )
177
+ checksizes (axs, _size (A)) || throw (ArgumentError (" the length of each axis must match the corresponding size of data" ))
178
+ checknames (axisnames (axs... )... )
179
+ AxisArray {T,N,typeof(A),typeof(axs)} (A, axs)
180
+ end
181
+ function AxisArray {L} (A:: AbstractArray , axs:: NTuple{L,Axis} )
182
+ newaxs = _default_axes (A, indices (A), axs)
183
+ AxisArray (A, newaxs)
184
+ end
185
+
186
+ @inline checksizes (axs, sz) =
187
+ (length (axs[1 ]) == sz[1 ]) & checksizes (tail (axs), tail (sz))
188
+ checksizes (:: Tuple{} , sz) = true
189
+
190
+ @inline function checknames (name:: Symbol , names... )
191
+ matches = false
192
+ for n in names
193
+ matches |= name == n
189
194
end
195
+ matches && throw (ArgumentError (" axis name :$name is used more than once" ))
196
+ checknames (names... )
190
197
end
198
+ checknames (name, names... ) = throw (ArgumentError (" the Axis names must be Symbols" ))
199
+ checknames () = ()
200
+
191
201
# Simple non-type-stable constructors to specify just the name or axis values
192
202
AxisArray (A:: AbstractArray ) = AxisArray (A, ()) # Disambiguation
193
203
AxisArray (A:: AbstractArray , names:: Symbol... ) = AxisArray (A, map ((name,ind)-> Axis {name} (ind), names, indices (A)))
@@ -365,9 +375,9 @@ axisnames{T,N,D,Ax}(::Type{AxisArray{T,N,D,Ax}}) = _axisnames(Ax)
365
375
axisnames {Ax<:Tuple{Vararg{Axis}}} (:: Type{Ax} ) = _axisnames (Ax)
366
376
@pure _axisnames (Ax) = axisnames (Ax. parameters... )
367
377
axisnames () = ()
368
- axisnames {name } (:: Axis{name} , B:: Axis... ) = tuple (name, axisnames (B... )... )
369
- axisnames {name } (:: Type{Axis{name}} , B:: Type... ) = tuple (name, axisnames (B... )... )
370
- axisnames {name,T} (:: Type{Axis{name,T}} , B:: Type... ) = tuple (name, axisnames (B... )... )
378
+ @inline axisnames {name } (:: Axis{name} , B:: Axis... ) = tuple (name, axisnames (B... )... )
379
+ @inline axisnames {name } (:: Type{Axis{name}} , B:: Type... ) = tuple (name, axisnames (B... )... )
380
+ @inline axisnames {name,T} (:: Type{Axis{name,T}} , B:: Type... ) = tuple (name, axisnames (B... )... )
371
381
372
382
axisname {name,T} (:: Type{Axis{name,T}} ) = name
373
383
axisname {name } (:: Type{Axis{name }} ) = name
@@ -392,6 +402,9 @@ Returns the tuple of axis vectors for an AxisArray. If an specific `Axis` is
392
402
specified, then only that axis vector is returned. Note that when extracting a
393
403
single axis vector, `axes(A, Axis{1})`) is type-stable and will perform better
394
404
than `axes(A)[1]`.
405
+
406
+ For an AbstractArray without `Axis` information, `axes` returns the
407
+ default axes, i.e., those that would be produced by `AxisArray(A)`.
395
408
""" ->
396
409
axes (A:: AxisArray ) = A. axes
397
410
axes (A:: AxisArray , dim:: Int ) = A. axes[dim]
@@ -400,6 +413,8 @@ axes(A::AxisArray, ax::Axis) = axes(A, typeof(ax))
400
413
dim = axisdim (A, T)
401
414
:(A. axes[$ dim])
402
415
end
416
+ axes (A:: AbstractArray ) = default_axes (A)
417
+ axes (A:: AbstractArray , dim:: Int ) = default_axes (A)[dim]
403
418
404
419
# ## Axis traits ###
405
420
abstract AxisTrait
0 commit comments