-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More statistics functions #115
Changes from 36 commits
3ec58b3
c8810d0
948dbb0
59bf810
5ef705d
13c1229
395a2a7
cea4a67
92e6dd8
577d714
202a00a
d764aa3
35aef02
e50c732
f699edf
2cde7cb
1732406
4c5437e
d78efe5
72f090c
ffebd5c
ace7626
6eb07f0
19f6d41
7ed5fca
1330b9d
c947685
5c1ea66
70d2e16
d9c1010
4ef1141
8c8f742
d26aa68
ddf9e37
546962a
8ce0161
e4c1ba2
572e780
3672faf
aad6ce8
9762587
ae64861
499f70a
eb2385c
e43eb45
59119b8
2baafb1
f6a67e5
41cd416
c1b5d8b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ import Random: AbstractRNG, randn, MersenneTwister | |
import FFTW | ||
import Luna | ||
import Luna.Utils: saveFFTwisdom, loadFFTwisdom | ||
import Roots: fzero | ||
import Dierckx | ||
|
||
"Calculate derivative of function f(x) at value x using finite differences" | ||
|
@@ -64,18 +65,123 @@ function rms_width(x::Vector, y; dim = 1) | |
end | ||
|
||
""" | ||
Trapezoidal integration for multi-dimensional arrays, in-place or with output array. | ||
In all of these functions, x can be an array (the x axis) or a number (the x axis spacing) | ||
fwhm(x, y; method=:linear, baseline=false, minmax=:min) | ||
|
||
In-place integration for multi-dimensional arrays | ||
Calculate the full width at half maximum (FWHM) of `y` on the axis `x` | ||
|
||
`method` can be `:spline` or `:nearest`. `:spline` uses a [`CSpline`](@ref), whereas | ||
`:nearest` finds the closest values either side of the crossing point and interpolates linearly. | ||
|
||
If `baseline` is true, the width is not taken at | ||
half the global maximum, but at half of the span of `y`. | ||
|
||
`minmax` determines whether the FWHM is taken at the narrowest (`:min`) or the widest (`:max`) | ||
point of y. | ||
""" | ||
function fwhm(x, y; method=:linear, baseline=false, minmax=:min) | ||
minmax in (:min, :max) || error("minmax has to be :min or :max") | ||
if baseline | ||
val = minimum(y) + 0.5*(maximum(y) - minimum(y)) | ||
else | ||
val = 0.5*maximum(y) | ||
end | ||
if !(method in (:spline, :linear, :nearest)) | ||
error("Unknown FWHM method $method") | ||
end | ||
maxidx = argmax(y) | ||
xmax = x[maxidx] | ||
left, right = try | ||
if minmax == :min | ||
lefti = findlast((x .< xmax) .& (y .< val)) | ||
righti = findfirst((x .> xmax) .& (y .< val)) | ||
(method == :nearest) && return abs(x[lefti] - x[righti]) | ||
left = linterpx(x[lefti], x[lefti+1], y[lefti], y[lefti+1], val) | ||
right = linterpx(x[righti-1], x[righti], y[righti-1], y[righti], val) | ||
else | ||
lefti = findfirst((x .< xmax) .& (y .> val)) | ||
righti = findlast((x .> xmax) .& (y .> val)) | ||
(method == :nearest) && return abs(x[lefti] - x[righti]) | ||
left = linterpx(x[lefti-1], x[lefti], y[lefti-1], y[lefti], val) | ||
right = linterpx(x[righti], x[righti+1], y[righti], y[righti+1], val) | ||
end | ||
(method == :linear) && return abs(right - left) | ||
left, right | ||
catch | ||
return NaN | ||
end | ||
#spline method | ||
minmax == :max && error("Spline method only supports min FWHM") | ||
try | ||
spl = CSpline(x, y) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know the linear method is preferred, but it'd be interesting to use the new BSpline here and the roots function just to see hoe well it does. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes I'll replace the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm sure this is completely negligible in the bigger picture |
||
lb = xmax - 2*(xmax-left) | ||
ub = xmax + 2*(right-xmax) | ||
f(x) = spl(x) - val | ||
lfine = fzero(f, lb, xmax) | ||
rfine = fzero(f, xmax, ub) | ||
return abs(rfine - lfine) | ||
catch | ||
return NaN | ||
end | ||
end | ||
|
||
""" | ||
linterpx(x1, x2, y1, y2, val) | ||
|
||
Given two points on a straight line, `(x1, y1)` and `(x2, y2)`, calculate the value of `x` | ||
at which this straight line intercepts with `val`. | ||
|
||
# Examples | ||
```jldoctest | ||
julia> x1 = 0; x2 = 1; y1 = 0; y2 = 2; # y = 2x | ||
julia> linterpx(x1, x2, y1, y2, 0.5) | ||
0.25 | ||
``` | ||
""" | ||
function linterpx(x1, x2, y1, y2, val) | ||
slope = (y2-y1)/(x2-x1) | ||
icpt = y1 - slope*x1 | ||
(val-icpt)/slope | ||
end | ||
|
||
""" | ||
hwhwm(f, x0=0; direction=:fwd) | ||
|
||
Find the value `x` where the function `f(x)` drops to half of its maximum, which is located | ||
at `x0`. For `direction==:fwd`, search in the region `x > x0`, for :bwd, search in `x < x0`. | ||
""" | ||
function hwhm(f, x0=0; direction=:fwd) | ||
m = f(x0) | ||
fhalf(x) = f(x) - 0.5*m | ||
if direction == :fwd | ||
xhw = fzero(fhalf, x0, Inf) | ||
elseif direction == :bwd | ||
xhw = fzero(fhalf, -Inf, x0) | ||
end | ||
return abs(xhw - x0) | ||
end | ||
|
||
""" | ||
cumtrapz!([out, ] y, x; dim=1) | ||
|
||
Trapezoidal integration for multi-dimensional arrays or vectors, in-place or with output array. | ||
|
||
If `out` is omitted, `y` is integrated in place. Otherwise the result is placed into `out`. | ||
|
||
`x` can be an array (the x axis) or a number (the x axis spacing). | ||
""" | ||
function cumtrapz! end | ||
|
||
function cumtrapz!(y, x; dim=1) | ||
idxlo = CartesianIndices(size(y)[1:dim-1]) | ||
idxhi = CartesianIndices(size(y)[dim+1:end]) | ||
_cumtrapz!(y, x, idxlo, idxhi) | ||
end | ||
|
||
"Inner function for multi-dimensional arrays - uses 1-D routine internally" | ||
""" | ||
_cumtrapz!([out, ] y, x, idxlo, idxhi) | ||
|
||
Inner function for multi-dimensional `cumtrapz!` - uses 1-D routine internally | ||
""" | ||
function _cumtrapz!(y, x, idxlo, idxhi) | ||
for lo in idxlo | ||
for hi in idxhi | ||
|
@@ -84,7 +190,6 @@ function _cumtrapz!(y, x, idxlo, idxhi) | |
end | ||
end | ||
|
||
"In-place integration for 1-D arrays" | ||
function cumtrapz!(y::T, x) where T <: Union{SubArray, Vector} | ||
tmp = y[1] | ||
y[1] = 0 | ||
|
@@ -95,14 +200,12 @@ function cumtrapz!(y::T, x) where T <: Union{SubArray, Vector} | |
end | ||
end | ||
|
||
"Integration into output array for multi-dimensional arrays" | ||
function cumtrapz!(out, y, x; dim=1) | ||
idxlo = CartesianIndices(size(y)[1:dim-1]) | ||
idxhi = CartesianIndices(size(y)[dim+1:end]) | ||
_cumtrapz!(out, y, x, idxlo, idxhi) | ||
end | ||
|
||
"Inner function for multi-dimensional arrays - uses 1-D routine internally" | ||
function _cumtrapz!(out, y, x, idxlo, idxhi) | ||
for lo in idxlo | ||
for hi in idxhi | ||
|
@@ -111,24 +214,30 @@ function _cumtrapz!(out, y, x, idxlo, idxhi) | |
end | ||
end | ||
|
||
"Integration into output array for 1-D array" | ||
function cumtrapz!(out, y::Union{SubArray, Vector}, x) | ||
out[1] = 0 | ||
for i in 2:length(y) | ||
out[i] = out[i-1]+ 1//2*(y[i-1] + y[i])*_dx(x, i) | ||
end | ||
end | ||
|
||
"x axis spacing if x is given as an array" | ||
function _dx(x, i) | ||
x[i] - x[i-1] | ||
end | ||
""" | ||
_dx(x, i) | ||
|
||
"x axis spacing if x is given as a number (i.e. dx)" | ||
function _dx(x::Number, i) | ||
x | ||
end | ||
Calculate the axis spacing at index `i` given an axis `x`. If `x` is a number, interpret this | ||
as `δx` directly | ||
""" | ||
_dx(x, i) = x[i] - x[i-1] | ||
_dx(δx::Number, i) = δx | ||
|
||
|
||
""" | ||
cumtrapz(y, x; dim=1) | ||
|
||
Calculate the cumulative trapezoidal integral of `y`. | ||
|
||
`x` can be an array (the x axis) or a number (the x axis spacing). | ||
""" | ||
function cumtrapz(y, x; dim=1) | ||
out = similar(y) | ||
cumtrapz!(out, y, x; dim=dim) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the idea here? is this for the stats or just on the side?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mostly wondering about how to save the list of modes and similar fundamental parameters, so related to the stats. one way is to make the representation of the
transform
properly human-readable and just save that, and this is an attempt at that