Skip to content

Commit 05e0185

Browse files
committed
update docs and add error
1 parent 19080c1 commit 05e0185

File tree

3 files changed

+20
-6
lines changed

3 files changed

+20
-6
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,13 @@ m[0, 0] # "index" the model at [y, x]
7474
m[:, 0]
7575
m(0.3, 1.0) # directly query value at (x, y)
7676
m([1.2, 0.4])
77+
```
78+
79+
**Important:**:
7780

81+
It is important to recognize the difference in the order of the dimensions between indexing and calling. Indexing is reverse of the cartesian order, which is the natural way of indexing a multi-dimensional array. If you try calling a model as a function with an index, an error will be thrown.
82+
83+
```julia
7884
# scalar multiplication or division will create a ScaledPSFModel
7985
20 * m # or `m * 20`
8086
m / 20

src/PSFModels.jl

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,15 @@ julia> m = PSFModels.Gaussian(5); # fwhm of 5 pixels, centered at (0, 0)
2323
2424
julia> m[0, 0] # [y, x] for indexing
2525
1.0
26+
27+
julia> m(0, 0) # (x, y) for evaluating
28+
1.0
2629
```
2730
31+
!!! note "axis order"
32+
33+
It's important to note the difference in the axis ordering between the index-style calls and the function-style calls. The index-style calls are reverse cartesian order (e.g., `(z, y, x)`), while function calls are the typical cartesian order `(x, y, z)`. Regardless, the constructors are always in cartesian order (`(x, y, z)`).
34+
2835
To control the amplitude, the best method is using scalar multiplication or division. These operations create another lazy object ([`ScaledPSFModel`](@ref)) that scales the original model without having to broadcast and potentially allocate.
2936
3037
```jldoctest model
@@ -55,7 +62,7 @@ if we want to collect the model into a dense matrix, regardless of the indexing
5562
julia> stamp = collect(m);
5663
```
5764
58-
these axes are merely a convenience for bounding the model, since they accept any real number as input.
65+
these axes are merely a convenience for bounding the model, since they accept any real number as input.
5966
6067
```jldoctest model
6168
julia> m[100, 10000] # index-like inputs [y, x]
@@ -153,11 +160,11 @@ Base.checkbounds(::Type{Bool}, ::PSFModel, idx::CartesianIndex) = true
153160
# in general, parse to static vector
154161
(model::PSFModel)(point...) = model(SVector(point))
155162
(model::PSFModel)(point::Tuple) = model(SVector(point))
156-
# make sure to reverse indices
157-
(model::PSFModel)(idx::CartesianIndex) = model(SVector(reverse(idx.I)))
163+
# disallow index to avoid confusion
164+
(model::PSFModel)(::CartesianIndex) = error("PSF models should be indexed using `getindex`, (equivalently `[]`)")
158165

159166
# getindex just calls model with reversed indices
160-
Base.getindex(model::PSFModel, idx::Vararg{Int,2}) = model(reverse(idx))
167+
Base.getindex(model::PSFModel, idx::Vararg{<:Number,2}) = model(reverse(idx))
161168

162169
# broadcasting hack to slurp other axes (doesn't work for numbers)
163170
Broadcast.combine_axes(kern::PSFModel, other) = axes(other)

test/runtests.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ function test_model_interface(K)
1111
@test m.pos SA[0, 0]
1212
@test eltype(m) == Float64
1313

14-
@test m[0, 0] m(0, 0) m(SA[0, 0]) m(CartesianIndex(0, 0)) 1
14+
@test m[0, 0] m(0, 0) m(SA[0, 0]) 1
15+
@test_throws ErrorException m(CartesianIndex(0, 0))
1516
@test m[-100, -10] m(-10, -100)
16-
@test_throws ArgumentError m[1.0, 1.0]
17+
@test m(1.0, 1.0) m[1.0, 1.0]
1718
@test maximum(m) 1
1819
@test 0 minimum(m) 1
1920

0 commit comments

Comments
 (0)