Skip to content

Commit

Permalink
Update docstrings
Browse files Browse the repository at this point in the history
  • Loading branch information
Miguel Bazdresch committed Apr 18, 2023
1 parent e160047 commit 630f6e6
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 104 deletions.
37 changes: 37 additions & 0 deletions src/SinusoidalRegressions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,43 @@ include("lsqfit.jl")
include("liang.jl")
include("plotrecipes.jl")

"""
sinfit(problem::Problem, algorithm::Algorithm)
Calculate a sinosoidal regression on `problem` using `algorithm`.
Currently supported problem types are:
* `Sin3Problem` -- three-parameter sinusoidal regression
* `Sin4Problem` -- four-parameter sinusoidal regression
* `MixedLinSin4Problem` -- four-parameter mixed linear and sinusoidal regression
* `MixedLinSin5Problem` -- five-parameter mixed linear and sinusoidal regression
Currently supported algorithms are:
* `IEEE1057`
* `IntegralEquations`
* `LevMar`
* `Liang`
Example
=======
```
julia> using SinusoidalRegressions
julia> t = range(0, 1, length = 100) # time instants
julia> s = sin.(2*pi*15*t .+ pi/4) .+ 0.1*randn(100) # noisy samples
julia> p = Sin3Problem(t, s, 15) # define regression problem
julia> sinfit(p, IEEE1057()) # calculate fit with IEEE 1057
Sinusoidal parameters SinusoidP{Float64}:
Frequency (Hz) : 15.0
DC : -0.01067218324878172
Sine amplitude (Q) : 0.7299806464221965
Cosine amplitude (I): 0.6822068658523716
```
See the documentation for more details.
"""
sinfit(p::Problem, a::Algorithm) = sinfit(p, a)

function sinfit(p::Sin3Problem, ::IEEE1057)
ieee1057(p)
end
Expand Down
24 changes: 0 additions & 24 deletions src/ieee1057.jl
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@

"""
ieee1057(X, Y, f::Real) :: SinusoidP
Calculate a three-parameter sinusoidal fit of the independent variables `X` and dependent
variables `Y`, using the algorithm described by the IEEE 1057 Standard. Argument `f`
is the exact frequency of the sinusoid, in hertz.
The data is fit to the model ``f(x; DC, Q, I) = DC + Q\\sin(2πfx) + I\\cos(2πfx)``.
See also [`SinusoidP`](@ref).
"""
function ieee1057(p::Sin3Problem)
(; X, Y, f) = p
if length(X) != length(Y)
Expand All @@ -21,19 +10,6 @@ function ieee1057(p::Sin3Problem)
return _ieee1057_3P(X, Y, f)
end

"""
ieee1057(X, Y ; f = nothing, iterations = 6) :: SinusoidP
Calculate a four-parameter sinusoidal fit of the independent variables `X` and
dependent variables `Y`, using the algorithm described by the IEEE 1057
Standard.
Argument `f` is an estimate of the frequency, in hertz. If not provided, then
it is calculated using the integral equations method (see [`sinfit_j`](@ref)).
Argument `iterations` specifies how many iterations to run. The default value is 6,
which is the value recommended by the standard.
"""
function ieee1057(p::Sin4Problem, a::IEEE1057)
(; X, Y, f) = p
if length(X) != length(Y)
Expand Down
11 changes: 0 additions & 11 deletions src/jacquelin_mlsr.jl
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
"""
mixlinsinfit_j(X, Y) :: MixedLinearSinusoidP

Perform a mixed linear-sinusoidal fit of the independent variables `X` and dependent
variables `Y`, using the method of integral equations.
The data is fit to the model ``s(x; f, DC, Q, I, m) = DC + mx + Q\\sin(2πfx) + I\\sin(2πfx)``.
No initial guess as to the values of the parameters `f`, `DC`, `Q`, `I`, or `m` is required.
The values in `X` must be sorted in ascending order.
See also [`sinfit_j`](@ref)
"""
function jacquelin(prob::MixedLinSin5Problem)
(; X, Y) = prob
# verify elements of X are ordered
Expand Down
13 changes: 0 additions & 13 deletions src/jacquelin_sr.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,4 @@
"""
jacquelin(X, Y) :: SinusoidP

Perform a four-parameter sinusoidal fit of the independent variables `X` and
dependent variables `Y`, using the method of integral equations described in J.
Jacquelin, "Régressions et équations intégrales", 2014 (available at
https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales)
The data is fit to the model ``s(x; f, DC, Q, I) = DC + Q\\sin(2πfx) +
I\\cos(2πfx)``. No initial guess as to the values of the parameters `f`, `DC`,
`Q`, or `I` is required. The values in `X` must be sorted in ascending order.
See also [`SinusoidP`](@ref).
"""
function jacquelin(p::Sin4Problem)
(; X, Y) = p
n = length(X)
Expand Down
56 changes: 0 additions & 56 deletions src/lsqfit.jl
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
"""
sinfit(X, Y, f ; kwargs...)

Perform a three-parameter least-squares sinusoidal fit of the independent variables
`X` and dependent variables `Y`, assuming a known frequency `f`, using the non-linear
optimization solver from `LsqFit.jl`.
The data is fit to the model ``s(x; DC, Q, I) = DC + Q\\sin(2πfx) + I\\cos(2πfx)``. The
values in `X` must be sorted in ascending order.
The Levenberg-Marquardt algorithm used by `LsqFit.jl` requires an initial guess
of all three parameters, `DC`, `Q` and `I`. If no initial guess is provided, then one is
calculated using the linear regression algorithm from IEEE 1057 (see [`ieee1057`](@ref)).
All keyword arguments provided are directly passed to `LsqFit.curve_fit`.
See also [`SinusoidP`](@ref), [`ieee1057`](@ref),
[`curve_fit`](https://github.com/JuliaNLSolvers/LsqFit.jl).
"""
function levmar(prob::Sin3Problem, a::LevMar ; kwargs...)
(; X, Y, f, DC, Q, I, lb, ub) = prob
# Check if all parameters are given initial estimates
Expand Down Expand Up @@ -50,26 +32,6 @@ function levmar(prob::Sin3Problem, a::LevMar ; kwargs...)
return SinusoidP(f, coef(fit)...)
end

"""
sinfit(X, Y, guess::SinusoidP = sinfit_j(X, Y) ; kwargs...)
Perform a four-parameter least-squares sinusoidal fit of the independent variables
`X` and dependent variables `Y`, using the non-linear optimization solver from
`LsqFit.jl`.
The data is fit to the model ``s(x; f, DC, Q, I) = DC + Q\\sin(2πfx) + I\\cos(2πfx)``. The
values in `X` must be sorted in ascending order.
The Levenberg-Marquardt algorithm used by `LsqFit.jl` requires an initial guess
of all four model parameters. If no initial guess is provided, then one is calculated
using [`sinfit_j`](@ref).
All keyword arguments provided are directly passed to `LsqFit.curve_fit`.
See also [`SinusoidP`](@ref), [`sinfit_j`](@ref),
[LsqFit.jl](https://github.com/JuliaNLSolvers/LsqFit.jl),
[`curve_fit`](https://github.com/JuliaNLSolvers/LsqFit.jl)
"""
function levmar(prob::Sin4Problem, a::LevMar ; kwargs...)
(; X, Y, f, DC, Q, I, lb, ub) = prob
# Check if all parameters are given initial estimates
Expand Down Expand Up @@ -104,24 +66,6 @@ function levmar(prob::Sin4Problem, a::LevMar ; kwargs...)
return SinusoidP(coef(fit)...)
end

"""
mixlinsinfit(X, Y, guess::MixedLinearSinusoidP = mixlinsinfit_j(X, Y) ; kwargs...)
Perform a least-squares mixed linear-sinusoid fit of the independent variables `X` and dependent
variables `Y`, using the non-linear optimization solver from `LsqFit.jl`.
The data is fit to the model ``s(x, f, DC, Q, I, m) = DC + Q\\sin(2πfx) + I\\cos(2πfx) + mx``. The
values in `X` must be sorted in axcending order.
The Levenberg-Marquardt algorithm used by `LsqFit.jl` requires an initial guess
of the parameters, `DC`, `Q` `I`, and `m`. If no initial guess is provided, then one is
calculated then one is calculated using [`mixlinsinfit_j`](@ref).
All keyword arguments provided are directly passed to `LsqFit.curve_fit`.
See also [`MixedLinearSinusoidP`](@ref), [`mixlinsinfit_j`](@ref),
[`curve_fit`](https://github.com/JuliaNLSolvers/LsqFit.jl).
"""
function levmar(prob::MixedLinSin4Problem, a::LevMar ; kwargs...)
(; X, Y, f, DC, Q, I, m, lb, ub) = prob
# Check if all parameters are given initial estimates
Expand Down
97 changes: 97 additions & 0 deletions src/typedefs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,55 @@

abstract type Algorithm end

"""
IEEE1057([iterations = 6]) <: Algorithm
Define an instance of the IEEE 1057 sinusoidal fitting algorithm.
Optional argument `iterations` specifies how many iterations to run before the algorithm
stops. The default value is 6, which is the value recommended by the standard. This value
is only used when calculating a 4-parameter fit.
"""
Base.@kwdef struct IEEE1057 <: Algorithm
iterations::Int = 6
end

"""
IntegralEquations() <: Algorithm
Define an instance of the integral-equations sinusoidal fitting algorithm described by
J. Jacquelin in "Régressions et équations intégrales", 2014 (available at
https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales).
This algorithm does not accept any configuration parameters.
"""
struct IntegralEquations <: Algorithm end

"""
LevMar([use_ga = false]) <: Algorithm
Define an instance of the Levenberg-Marquardt sinusoidal fitting algorithm.
If the optional argument `use_ga` is set to `true`, the algorithm will use geodesic
acceleration to potentially improve its performance and accuracy. See
[`curve_fit`](https://github.com/JuliaNLSolvers/LsqFit.jl) for more details.
"""
Base.@kwdef struct LevMar <: Algorithm
use_ga :: Bool = false
end

"""
Liang([threshold = 0.15, iterations = 100, q = 1e-5]) <: Algorithm
Define an instance of the sinusoidal fitting algorithm described in Liang et al,
"Fitting Algorithm of Sine Wave with Partial Period Waveforms and Non-Uniform Sampling
Based on Least-Square Method." Journal of Physics: Conference Series 1149.1
(2018)ProQuest. Web. 17 Apr. 2023.
This algorithm is designed for scenarios where only a fraction of a period of the sinusoid
has been sampled. Its optional parameters `threshold` and `q` are described in the paper.
Additionally, a maximum number of iterations may be specified in `iterations`.
"""
Base.@kwdef struct Liang <: Algorithm
threshold :: Float64 = 0.15
iterations :: Int = 100
Expand All @@ -27,6 +66,21 @@ end

abstract type Problem end

"""
Sin3Problem(X, Y, f , [DC, Q, I, lb, ub]) <: Problem
Define a three-parameter sinusoidal regression problem.
The data is fit to the model ``f(x; DC, Q, I) = DC + Q\\sin(2πfx) + I\\cos(2πfx)``. The sampling
instants are given by `X`, and the samples by `Y`. The frequency `f` (in Hz) is assumed to
be known exactly.
When using a fitting algorithm that accepts initial parameter estimates, these may be given
by the optional keyword arguments `DC`, `Q` and `I` (default `missing`). Lower and upper bounds
may be specified in `lb` and `ub`, which must be vectors of length 3.
See also: [`Sin4Problem`](@ref)
"""
Base.@kwdef struct Sin3Problem{T1, T2, T3} <: Problem where
{T1 <: AbstractVector, T2 <: AbstractVector, T3 <: Real}
X :: T1 # sampling times
Expand All @@ -41,6 +95,20 @@ end

Sin3Problem(X, Y, f ; kwargs...) = Sin3Problem(; X, Y, f, kwargs...)

"""
Sin4Problem(X, Y ; [f, DC, Q, I, lb, ub]) <: Problem
Define a four-parameter sinusoidal regression problem.
The data is fit to the model ``f(x; f, DC, Q, I) = DC + Q\\sin(2πfx) + I\\cos(2πfx)``.
The sampling instants are given by `X`, and the samples by `Y`.
When using a fitting algorithm that accepts initial parameter estimates, these may be given
by the optional keyword arguments `f`, `DC`, `Q` and `I` (default `missing`). Lower and upper
bounds may be specified in `lb` and `ub`, which must be vectors of length 4.
See also: [`Sin3Problem`](@ref)
"""
Base.@kwdef struct Sin4Problem{T1, T2} <: Problem where
{T1 <: AbstractVector, T2 <: AbstractVector}
X :: T1 # sampling times
Expand All @@ -55,6 +123,21 @@ end

Sin4Problem(X, Y ; kwargs...) = Sin4Problem(; X, Y, kwargs...)

"""
MixedLinSin4Problem(X, Y, f ; [DC, Q, I, m, lb, ub])
Define a four-parameter mixed linear-sinusoidal regression problem.
The data is fit to the model ``f(x; DC, Q, I, m) = DC + Q\\sin(2πfx) + I\\cos(2πfx) + mx``.
The sampling instants are given by `X`, and the samples by `Y`. The frequency `f` (in Hz) is
assumed to be known exactly.
When using a fitting algorithm that accepts initial parameter estimates, these may be given
by the optional keyword arguments `DC`, `Q` `I` and `m` (default `missing`). Lower and upper
bounds may be specified in `lb` and `ub`, which must be vectors of length 4.
See also: [`MixedLinSin5Problem`](@ref)
"""
Base.@kwdef struct MixedLinSin4Problem{T1, T2, T3} <: Problem where
{T1 <: AbstractVector, T2 <: AbstractVector, T3 <: Real}
X :: T1
Expand All @@ -70,6 +153,20 @@ end

MixedLinSin4Problem(X, Y, f ; kwargs...) = MixedLinSin4Problem(; X, Y, f, kwargs...)

"""
MixedLinSin5Problem(X, Y ; [f, DC, Q, I, m, lb, ub])
Define a five-parameter mixed linear-sinusoidal regression problem.
The data is fit to the model ``f(x ; f, DC, Q, I, m) = DC + Q\\sin(2πfx) + I\\cos(2πfx) + mx``.
The sampling instants are given by `X`, and the samples by `Y`.
When using a fitting algorithm that accepts initial parameter estimates, these may be given
by the optional keyword arguments `f`, `DC`, `Q` `I` and `m` (default `missing`). Lower and upper
bounds may be specified in `lb` and `ub`, which must be vectors of length 5.
See also: [`MixedLinSin4Problem`](@ref)
"""
Base.@kwdef struct MixedLinSin5Problem{T1, T2} <: Problem where
{T1 <: AbstractVector, T2 <: AbstractVector, T3 <: Real}
X :: T1
Expand Down

0 comments on commit 630f6e6

Please sign in to comment.