Skip to content

Commit d6797e7

Browse files
committed
Simplify README
Now that we have doctests, it is even more important that we reduce the duplication here to ensure that the real documentation is the one canonical source.
1 parent 9994724 commit d6797e7

File tree

1 file changed

+13
-221
lines changed

1 file changed

+13
-221
lines changed

README.md

+13-221
Original file line numberDiff line numberDiff line change
@@ -1,234 +1,26 @@
11
# AxisArrays
22

3-
[![Build Status](https://travis-ci.org/JuliaArrays/AxisArrays.jl.svg?branch=master)](https://travis-ci.org/JuliaArrays/AxisArrays.jl) [![Coverage Status](https://coveralls.io/repos/github/JuliaArrays/AxisArrays.jl/badge.svg?branch=master)](https://coveralls.io/github/JuliaArrays/AxisArrays.jl?branch=master)
3+
[![0.6 Pkg Status](http://pkg.julialang.org/badges/AxisArrays_0.6.svg)](http://pkg.julialang.org/?pkg=AxisArrays)
4+
5+
[![Build Status](https://travis-ci.org/JuliaArrays/AxisArrays.jl.svg?branch=master)](https://travis-ci.org/JuliaArrays/AxisArrays.jl)
6+
[![Coverage Status](https://coveralls.io/repos/github/JuliaArrays/AxisArrays.jl/badge.svg?branch=master)](https://coveralls.io/github/JuliaArrays/AxisArrays.jl?branch=master)
7+
[![Stable Documentation][docs-stable-img]][docs-stable-url]
8+
[![Latest Documentation][docs-latest-img]][docs-latest-url]
49

510
This package for the Julia language provides an array type (the `AxisArray`) that knows about its dimension names and axis values.
611
This allows for indexing with the axis name without incurring any runtime overhead.
712
AxisArrays can also be indexed by the values of their axes, allowing column names or interval selections.
813
This permits one to implement algorithms that are oblivious to the storage order of the underlying arrays.
9-
In contrast to similar approaches in [Images.jl](https://github.com/timholy/Images.jl) and [NamedArrays.jl](https://github.com/davidavdav/NamedArrays), this allows for type-stable selection of dimensions and compile-time axis lookup. It is also better suited for regularly sampled axes, like samples over time.
14+
In contrast to similar approaches in [NamedArrays.jl](https://github.com/davidavdav/NamedArrays) and old versions of [Images.jl](https://github.com/timholy/Images.jl), this allows for type-stable selection of dimensions and compile-time axis lookup. It is also better suited for regularly sampled axes, like samples over time.
1015

1116
Collaboration is welcome! This is still a work-in-progress. See [the roadmap](https://github.com/JuliaArrays/AxisArrays.jl/issues/7) for the project's current direction.
1217

13-
## Example of currently-implemented behavior:
14-
15-
```julia
16-
julia> Pkg.add("AxisArrays")
17-
julia> using AxisArrays, Unitful
18-
julia> import Unitful: s, ms, µs
19-
20-
julia> rng = MersenneTwister(123) # Seed a random number generator for repeatable examples
21-
julia> fs = 40000 # Generate a 40kHz noisy signal, with spike-like stuff added for testing
22-
julia> y = randn(rng, 60*fs+1)*3
23-
julia> for spk = (sin.(0.8:0.2:8.6) .* [0:0.01:.1; .15:.1:.95; 1:-.05:.05] .* 50,
24-
sin.(0.8:0.4:8.6) .* [0:0.02:.1; .15:.1:1; 1:-.2:.1] .* 50)
25-
i = rand(rng, round(Int,.001fs):1fs)
26-
while i+length(spk)-1 < length(y)
27-
y[i:i+length(spk)-1] += spk
28-
i += rand(rng, round(Int,.001fs):1fs)
29-
end
30-
end
31-
32-
julia> A = AxisArray([y 2y], Axis{:time}(0s:1s/fs:60s), Axis{:chan}([:c1, :c2]))
33-
2-dimensional AxisArray{Float64,2,...} with axes:
34-
:time, 0.0 s:2.5e-5 s:60.0 s
35-
:chan, Symbol[:c1, :c2]
36-
And data, a 2400001×2 Array{Float64,2}:
37-
3.5708 7.14161
38-
6.14454 12.2891
39-
3.42795 6.85591
40-
1.37825 2.75649
41-
-1.19004 -2.38007
42-
-1.99414 -3.98828
43-
2.9429 5.88581
44-
-0.226449 -0.452898
45-
0.821446 1.64289
46-
-0.582687 -1.16537
47-
48-
-3.50593 -7.01187
49-
2.26783 4.53565
50-
-0.16902 -0.33804
51-
-3.84852 -7.69703
52-
0.226457 0.452914
53-
0.560809 1.12162
54-
4.67663 9.35326
55-
-2.41005 -4.8201
56-
-3.71612 -7.43224
57-
```
58-
59-
AxisArrays behave like regular arrays, but they additionally use the axis
60-
information to enable all sorts of fancy behaviors. For example, we can specify
61-
indices in *any* order, just so long as we annotate them with the axis name:
62-
63-
```julia
64-
julia> A[Axis{:time}(4)]
65-
1-dimensional AxisArray{Float64,1,...} with axes:
66-
:chan, Symbol[:c1, :c2]
67-
And data, a 2-element Array{Float64,1}:
68-
1.37825
69-
2.75649
70-
71-
julia> A[Axis{:chan}(:c2), Axis{:time}(1:5)]
72-
1-dimensional AxisArray{Float64,1,...} with axes:
73-
:time, 0.0 s:2.5e-5 s:0.0001 s
74-
And data, a 5-element Array{Float64,1}:
75-
7.14161
76-
12.2891
77-
6.85591
78-
2.75649
79-
-2.38007
80-
```
81-
82-
We can also index by the *values* of each axis using an `Interval` type that
83-
selects all values between two endpoints `a .. b` or the axis values directly.
84-
Notice that the returned AxisArray still has axis information itself... and it
85-
still has the correct time information for those datapoints!
86-
87-
```julia
88-
julia> A[40µs .. 220µs, :c1]
89-
1-dimensional AxisArray{Float64,1,...} with axes:
90-
:time, 5.0e-5 s:2.5e-5 s:0.0002 s
91-
And data, a 7-element Array{Float64,1}:
92-
3.42795
93-
1.37825
94-
-1.19004
95-
-1.99414
96-
2.9429
97-
-0.226449
98-
0.821446
99-
100-
julia> axes(ans, 1)
101-
AxisArrays.Axis{:time,StepRangeLen{Quantity{Float64, Dimensions:{𝐓}, Units:{s}},Base.TwicePrecision{Quantity{Float64, Dimensions:{𝐓}, Units:{s}}},Base.TwicePrecision{Quantity{Float64, Dimensions:{𝐓}, Units:{s}}}}}(5.0e-5 s:2.5e-5 s:0.0002 s)
102-
```
103-
104-
You can also index by a single value on an axis using `atvalue`. This will drop
105-
a dimension. Indexing with an `Interval` type retains dimensions, even
106-
when the ends of the interval are equal:
107-
108-
```julia
109-
julia> A[atvalue(2.5e-5s), :c1]
110-
6.14453912336772
111-
112-
julia> A[2.5e-5s..2.5e-5s, :c1]
113-
1-dimensional AxisArray{Float64,1,...} with axes:
114-
:time, 2.5e-5 s:2.5e-5 s:2.5e-5 s
115-
And data, a 1-element Array{Float64,1}:
116-
6.14454
117-
```
118-
119-
You can even index by multiple values by broadcasting `atvalue` over an array:
120-
121-
```julia
122-
julia> A[atvalue.([2.5e-5s, 75.0µs])]
123-
2-dimensional AxisArray{Float64,2,...} with axes:
124-
:time, Quantity{Float64, Dimensions:{𝐓}, Units:{s}}[2.5e-5 s, 7.5e-5 s]
125-
:chan, Symbol[:c1, :c2]
126-
And data, a 2×2 Array{Float64,2}:
127-
6.14454 12.2891
128-
1.37825 2.75649
129-
```
130-
131-
Sometimes, though, what we're really interested in is a window of time about a
132-
specific index. One of the operations above (looking for values in the window from 40µs
133-
to 220µs) might be more clearly expressed as a symmetrical window about a
134-
specific index where we know something interesting happened. To represent this,
135-
we use the `atindex` function:
136-
137-
```julia
138-
julia> A[atindex(-90µs .. 90µs, 5), :c2]
139-
1-dimensional AxisArray{Float64,1,...} with axes:
140-
:time_sub, -7.5e-5 s:2.5e-5 s:7.500000000000002e-5 s
141-
And data, a 7-element Array{Float64,1}:
142-
6.85591
143-
2.75649
144-
-2.38007
145-
-3.98828
146-
5.88581
147-
-0.452898
148-
1.64289
149-
```
150-
151-
Note that the returned AxisArray has its time axis shifted to represent the
152-
interval about the given index! This simple concept can be extended to some
153-
very powerful behaviors. For example, let's threshold our data and find windows
154-
about those threshold crossings.
155-
156-
```julia
157-
julia> idxs = find(diff(A[:,:c1] .< -15) .> 0);
158-
159-
julia> spks = A[atindex(-200µs .. 800µs, idxs), :c1]
160-
2-dimensional AxisArray{Float64,2,...} with axes:
161-
:time_sub, -0.0002 s:2.5e-5 s:0.0008 s
162-
:time_rep, Quantity{Float64, Dimensions:{𝐓}, Units:{s}}[0.162 s, 0.20045 s, 0.28495 s, 0.530325 s, 0.821725 s, 1.0453 s, 1.11967 s, 1.1523 s, 1.22085 s, 1.6253 s 57.0094 s, 57.5818 s, 57.8716 s, 57.8806 s, 58.4353 s, 58.7041 s, 59.1015 s, 59.1783 s, 59.425 s, 59.5657 s]
163-
And data, a 41×247 Array{Float64,2}:
164-
0.672063 7.25649 0.633375 1.54583 5.81194 -4.706
165-
-1.65182 2.57487 0.477408 3.09505 3.52478 4.13037
166-
4.46035 2.11313 4.78372 1.23385 7.2525 3.57485
167-
5.25651 -2.19785 3.05933 0.965021 6.78414 5.94854
168-
7.8537 0.345008 0.960533 0.812989 0.336715 0.303909
169-
0.466816 0.643649 -3.67087 3.92978 -3.1242 0.789722
170-
-6.0445 -13.2441 -4.60716 0.265144 -4.50987 -8.84897
171-
-9.21703 -13.2254 -14.4409 -8.6664 -13.3457 -11.6213
172-
-16.1809 -22.7037 -25.023 -15.9376 -28.0817 -16.996
173-
-23.2671 -31.2021 -25.3787 -24.4914 -32.2599 -26.1118
174-
175-
-0.301629 0.0683982 -4.36574 1.92362 -5.12333 -3.4431
176-
4.7182 1.18615 4.40717 -4.51757 -8.64314 0.0800021
177-
-2.43775 -0.151882 -1.40817 -3.38555 -2.23418 0.728549
178-
3.2482 -0.60967 0.471288 2.53395 0.468817 -3.65905
179-
-4.26967 2.24747 -3.13758 1.74967 4.5052 -0.145357
180-
-0.752487 1.69446 -1.20491 1.71429 1.81936 0.290158
181-
4.64348 -3.94187 -1.59213 7.15428 -0.539748 4.82309
182-
1.09652 -2.66999 0.521931 -3.80528 1.70421 3.40583
183-
-0.94341 2.60785 -3.34291 1.10584 4.31118 3.6404
184-
```
185-
186-
By indexing with a repeated interval, we have *added* a dimension to the
187-
output! The returned AxisArray's columns specify each repetition of the
188-
interval, and each datapoint in the column represents a timepoint within that
189-
interval, adjusted by the time of the theshold crossing. The best part here
190-
is that the returned matrix knows precisely where its data came from, and has
191-
labeled its dimensions appropriately. Not only is there the proper time
192-
base for each waveform, but we also have recorded the event times as the axis
193-
across the columns.
194-
195-
## Indexing
196-
197-
### Indexing axes
198-
199-
Two main types of Axes supported by default include:
200-
201-
* Categorical axis -- These are vectors of labels, normally symbols or
202-
strings. Elements or slices can be selected by elements or vectors
203-
of elements.
204-
205-
* Dimensional axis -- These are sorted vectors or iterators that can
206-
be selected by `Intervals`. These are commonly used for sequences of
207-
times or date-times. For regular sample rates, ranges can be used.
208-
209-
Here is an example with a Dimensional axis representing a time
210-
sequence along rows and a Categorical axis of symbols for column
211-
headers.
212-
213-
```julia
214-
B = AxisArray(reshape(1:15, 5, 3), .1:.1:0.5, [:a, :b, :c])
215-
B[Axis{:row}(Interval(.2,.4))] # restrict the AxisArray along the time axis
216-
B[Interval(0.,.3), [:a, :c]] # select an interval and two of the columns
217-
```
18+
**Installation**: at the Julia REPL, `Pkg.add("AxisArrays")`
21819

219-
User-defined axis types can be added along with custom indexing
220-
behaviors.
20+
**Documentation**: [![Stable Documentation][docs-stable-img]][docs-stable-url] [![Latest Documentation][docs-latest-img]][docs-latest-url]
22121

222-
### Example: compute the intensity-weighted mean along the z axis
223-
```julia
224-
B = AxisArray(randn(100,100,100), :x, :y, :z)
225-
Itotal = sumz = 0.0
226-
for iter in eachindex(B) # traverses in storage order for cache efficiency
227-
I = B[iter] # intensity in a single voxel
228-
Itotal += I
229-
sumz += I * iter[axisdim(B, Axis{:z})] # axisdim "looks up" the z dimension
230-
end
231-
meanz = sumz/Itotal
232-
```
22+
[docs-latest-img]: https://img.shields.io/badge/docs-latest-blue.svg
23+
[docs-latest-url]: http://juliaarrays.github.io/AxisArrays.jl/latest/
23324

234-
The intention is that all of these operations are just as efficient as they would be if you used traditional position-based indexing with all the inherent assumptions about the storage order of `B`.
25+
[docs-stable-img]: https://img.shields.io/badge/docs-stable-blue.svg
26+
[docs-stable-url]: http://juliaarrays.github.io/AxisArrays.jl/stable/

0 commit comments

Comments
 (0)