Skip to content

Commit

Permalink
add test for curvefit
Browse files Browse the repository at this point in the history
  • Loading branch information
kongdd committed Jan 23, 2024
1 parent 73c35cb commit 377f5e2
Show file tree
Hide file tree
Showing 18 changed files with 99 additions and 59 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ temp/
examples/
*.R
*.jld
*.jld2
# *.jld2

Manifest.toml

## Figures
*.pdf
7 changes: 6 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
nlminb_jll = "c04a2911-6870-53d6-aa47-4d7d5aff1028"

[compat]
Parameters = "0.12"
StaticArrays = "1.9"
nlminb_jll = "0.1.1"
julia = "1.9"

[extras]
JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]
test = ["Test", "JLD2", "UnPack"]
17 changes: 17 additions & 0 deletions data/data-CA_NS6.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using JLD2
using RData
using UnPack

l = load("data/phenofit-CA_NS6.rda")
@unpack INPUT, brks2 = l

dt = brks2["dt"]
nptperyear = INPUT["nptperyear"] |> Int
y = INPUT["y"]
t = INPUT["t"]
w = INPUT["w"]

ylu = INPUT["ylu"]
ylu = [ylu[1], ylu[2]]

jldsave("data/phenofit-CA_NS6.jld2", true; y, t, w, ylu, nptperyear, dt)
Binary file added data/phenofit-CA_NS6.jld2
Binary file not shown.
Binary file added data/phenofit-CA_NS6.rda
Binary file not shown.
19 changes: 19 additions & 0 deletions src/CurveFit/Constant.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
DATE_ORIGIN = Date("2000-01-01")

FUNCS_FITDL = Dict(
"AG" => FitDL_AG,
"Zhang" => FitDL_Zhang,
"Beck" => FitDL_Beck,
"Elmore" => FitDL_Elmore,
"Gu" => FitDL_Gu,
"Klos" => FitDL_Klos
)

FUNCS_doubleLog = Dict(
"AG" => doubleLog_AG,
"Zhang" => doubleLog_Zhang,
"Beck" => doubleLog_Beck,
"Elmore" => doubleLog_Elmore,
"Gu" => doubleLog_Gu,
"Klos" => doubleLog_Klos
)
34 changes: 10 additions & 24 deletions src/CurveFit/CurveFit.jl
Original file line number Diff line number Diff line change
@@ -1,33 +1,18 @@
include("_get_ylu.jl")
include("init_param.jl")
include("doubleLogistics.jl")

include("get_ylu.jl")
include("get_extent.jl")
include("FitDL.jl")
include("Constant.jl")


DATE_ORIGIN = Date("2000-01-01")
"""
# Arguments
- `y::AbstractVector{T}`: input time series
FUNCS_FITDL = Dict(
"AG" => FitDL_AG,
"Zhang" => FitDL_Zhang,
"Beck" => FitDL_Beck,
"Elmore" => FitDL_Elmore,
"Gu" => FitDL_Gu,
"Klos" => FitDL_Klos
)

FUNCS_doubleLog = Dict(
"AG" => doubleLog_AG,
"Zhang" => doubleLog_Zhang,
"Beck" => doubleLog_Beck,
"Elmore" => doubleLog_Elmore,
"Gu" => doubleLog_Gu,
"Klos" => doubleLog_Klos
)


function curvefits(y::AbstractArray{T,1}, t, w::AbstractArray{T,1},
"""
function curvefits(y::AbstractVector{T}, t, w::AbstractVector{T},
ylu::Vector{Float64}, nptperyear::Integer,
dt;
methods=["AG", "Zhang", "Beck", "Elmore"]) where {T<:Real}
Expand All @@ -45,7 +30,7 @@ function curvefits(y::AbstractArray{T,1}, t, w::AbstractArray{T,1},

begs = getDateId(dt[:, :beg], t)
# peaks = getDateId(dt[:, :peak], t)
ends = getDateId(dt[:, :end], t, "after")
ends = getDateId(dt[:, :_end], t, "after")
ns = length(begs) # number of seasons

opts = []
Expand All @@ -54,7 +39,7 @@ function curvefits(y::AbstractArray{T,1}, t, w::AbstractArray{T,1},
I_end = ends[i]
I = I_beg:I_end
I_extend = get_extentI(w0, I_beg, I_end, nptperyear)
ylu_period = get_ylu(input.y, years, w0, width_ylu, I; wmin=0.2) # ylu_period
ylu_period = _get_ylu(input.y, years, w0, width_ylu, I; wmin=0.2) # ylu_period
merge_ylu!(ylu, ylu_period)
# println(ylu_period)

Expand All @@ -69,6 +54,7 @@ function curvefits(y::AbstractArray{T,1}, t, w::AbstractArray{T,1},
## solve double logistics
inputI = input_struct(yi, ti, wi)
opt = Dict{String,Any}()

for meth = methods
temp = FUNCS_FITDL[meth](inputI) # par, obj, method
# opt["ypred"] = getfield(curvefit, Symbol("doubleLog_$meth"))(opt["par"], tout)
Expand Down
4 changes: 2 additions & 2 deletions src/CurveFit/FitDL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ end
function FitDL_template(input::input_struct, method=nothing; options...)
par0, lims = init_param(input)

func_init = getfield(curvefit, Symbol("init_$method"))
func! = getfield(curvefit, Symbol("doubleLog_$(method)!"))
func_init = getfield(VegCurveFit, Symbol("init_$method"))
func! = getfield(VegCurveFit, Symbol("doubleLog_$(method)!"))

prior, lower, upper = func_init(par0, lims)
# opt (Dict): par, obj
Expand Down
8 changes: 2 additions & 6 deletions src/CurveFit/get_ylu.jl → src/CurveFit/_get_ylu.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
get_range(y::AbstractArray{T,1}) where {T<:Real} = [minimum(y), maximum(y)]

get_ylu(y) = get_range(y)

function get_ylu(y, years, w0, width::Integer, I; wmin=0.2)
function _get_ylu(y, years, w0, width::Integer, I; wmin=0.2)
n = length(w0)
I_beg = first(I)
I_end = last(I)
Expand Down Expand Up @@ -43,4 +39,4 @@ function merge_ylu!(ylu, ylu_new)
end


export get_range, get_ylu
# export get_range, get_ylu
20 changes: 11 additions & 9 deletions src/DataTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,23 @@ end


# input of check_input object
mutable struct input_struct
y::AbstractArray{<:Real,1}
# TODO: 尚有提升空间
mutable struct input_struct{T<:Real}
y::AbstractVector{T}
# t::AbstractArray{<:Dates.Date, 1}
t::AbstractArray{<:Union{Dates.Date,<:Real},1}
w::AbstractArray{<:Real,1}
w::AbstractVector{T}
end

function input_struct(y::AbstractArray{T,1}, t::AbstractArray{T,1}) where {T<:Real}
input_struct(y, t, ones(y))
function input_struct(y::AbstractVector{T}, t::AbstractVector{T}) where {T<:Real}
input_struct{T}(y, t, ones(T, y))
end

mutable struct inputI_struct
y::AbstractArray{<:Real,1}
t::AbstractArray{<:Real,1}
w::AbstractArray{<:Real,1}

mutable struct inputI_struct{T}
y::AbstractVector{T}
t::AbstractVector{<:Real}
w::AbstractVector{T}
ind::UnitRange{Int64}
# tout::AbstractArray{<:Real, 1}
end
Expand Down
2 changes: 1 addition & 1 deletion src/VegCurveFit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ using Statistics

include("DataTypes.jl")
include("tools.jl")
include("get_ylu.jl")

include("Optim/Optim.jl")
include("weights/wFUN.jl")

include("get_ylu.jl")

include("CurveFit/CurveFit.jl")

Expand Down
13 changes: 8 additions & 5 deletions src/get_ylu.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import Statistics: quantile


get_range(y::AbstractVector{T}) where {T<:Real} = [minimum(y), maximum(y)]

get_ylu(y) = get_range(y)


"""
get_ylu(y::AbstractVector{<:Real}, w::AbstractVector{<:Real};
wmin=0.2, wmid=0.5, wmax=1.0,
ratio = 0.4,
alpha=0.02, alpha_high=nothing)
"""
function get_ylu(y::AbstractVector{<:Real}, w::AbstractVector{<:Real};
wmin=0.2, wmid=0.5, wmax=1.0,
ratio = 0.4,
wmin=0.2, wmid=0.5, wmax=1.0,
ratio=0.4,
alpha=0.02, alpha_high=nothing)

alpha_high = null_default(alpha_high, alpha)
Expand All @@ -27,7 +30,7 @@ function get_ylu(y::AbstractVector{<:Real}, w::AbstractVector{<:Real};
w_critical = wmid
end
y_good = @view y[w.>=w_critical]

# alpha/2, alpha_high set to 0.05 for remote sensing (20200322)
ymin = max(quantile(y_good, alpha / 2), 0) # TODO: fix CN-Din
ymax = quantile(y_good, 1 - alpha_high / 2)
Expand Down
2 changes: 1 addition & 1 deletion src/smooth_SG/SG_weighted.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ wSG(y::AbstractVector{FT}; kw...) where {FT<:Real} = wSG(y, ones(FT, size(y)); k


# weighted Savitzky Golay filter
function wSG_low(y::AbstractArray{T,1}, w::AbstractArray{T2,1}; halfwin=1, d=2) where {
function wSG_low(y::AbstractVector{T}, w::AbstractArray{T2,1}; halfwin=1, d=2) where {
T<:Real,T2<:Real}
# constrain the w_min, unless it will lead to matrix division erorr
# w = deepcopy(w)
Expand Down
9 changes: 4 additions & 5 deletions src/tools.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
# println("optimized improved:", mean(b_old.times)/mean(b_new.times), " times")
# end

first(x::AbstractArray{T,1}) where {T<:Real} = x[1]
last(x::AbstractArray{T,1}) where {T<:Real} = x[end]
# first(x::AbstractVector) = x[1]
# last(x::AbstractVector) = x[end]

day2num(x::AbstractArray{Dates.Day,1}) = map(x -> x.value, x)

function aggregate(x::AbstractArray{T,1}, by::AbstractArray{T2,1}, FUN::Function=mean) where {
function aggregate(x::AbstractVector{T}, by::AbstractArray{T2,1}, FUN::Function=mean) where {
T<:Real,T2<:Real}

grps = unique(by)
Expand All @@ -30,5 +30,4 @@ function pmap(vec::Vector{Dict}, prop)
map(x -> x[prop], vec)
end

export first, last, day2num, aggregate,
pmap2
export day2num, aggregate, pmap2
4 changes: 2 additions & 2 deletions src/weights/wBisquare.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Statistics

# Genius function
function wBisquare(y::AbstractArray{T,1}, yfit::AbstractArray{T,1}, w::AbstractArray{T2,1},
function wBisquare(y::AbstractVector{T}, yfit::AbstractVector{T}, w::AbstractArray{T2,1},
nptperyear::Int;
options...) where {T<:AbstractFloat,T2<:AbstractFloat}

Expand Down Expand Up @@ -32,7 +32,7 @@ end
# Examples
"""
function wBisquare(y::AbstractArray{T,1}, yfit::AbstractArray{T,1}, w::AbstractArray{T2,1};
function wBisquare(y::AbstractVector{T}, yfit::AbstractVector{T}, w::AbstractArray{T2,1};
# QC_flag;
# iter::Integer = 2,
# to_upper = true,
Expand Down
4 changes: 2 additions & 2 deletions src/weights/wTSM.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Weight updating method in TIMESAT
# Author
Translated from TIMESAT to Julia by Dongdong Kong (20200808)
"""
function wTSM!(y::AbstractArray{T,1}, yfit::AbstractArray{T,1}, w::AbstractArray{T,1};
function wTSM!(y::AbstractVector{T}, yfit::AbstractVector{T}, w::AbstractVector{T};
iter::Integer=2, nptperyear::Integer=46, wfact::Float64=0.5) where {T<:AbstractFloat}

n = length(y)
Expand Down Expand Up @@ -48,7 +48,7 @@ function wTSM!(y::AbstractArray{T,1}, yfit::AbstractArray{T,1}, w::AbstractArray
end
end

# function wTSM(y::AbstractArray{T,1}, yfit::AbstractArray{T,1}, w::AbstractArray{T,1}; options...) where {T <: AbstractFloat}
# function wTSM(y::AbstractVector{T}, yfit::AbstractVector{T}, w::AbstractVector{T}; options...) where {T <: AbstractFloat}
# w = copy(w)
# wTSM!(y, yfit, w; options...)
# end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Test
using VegCurveFit

include("test-curvefit.jl")
include("test-lambda_init.jl")
include("test-smooth_SG.jl")
include("test-smooth_whit.jl")
Expand Down
9 changes: 9 additions & 0 deletions test/test-curvefit.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Test
using JLD2, UnPack
@unpack y, w, t, ylu, dt, nptperyear = load("data/phenofit-CA_NS6.jld2")

@testset "curvefits" begin
@test_nowarn begin
@time r = curvefits(y, t, w, ylu, nptperyear, dt)
end
end

0 comments on commit 377f5e2

Please sign in to comment.