diff --git a/Project.toml b/Project.toml index 24b19a7..aed7387 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,8 @@ name = "MetidaNCA" uuid = "097c2839-c7bc-4c4b-a5f2-b4167c1b4e7c" authors = ["PharmCat "] -version = "0.5.13" +version = "0.5.14" + [deps] diff --git a/change.log b/change.log index 33dbf86..e9bbcad 100644 --- a/change.log +++ b/change.log @@ -1,3 +1,6 @@ +0.5.14 +- pd tau + 0.5.13 - breaking changes in plotting output diff --git a/docs/src/examples.md b/docs/src/examples.md index c76472b..1efcffe 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -175,6 +175,22 @@ MetidaNCA.nca!(pd[1]) p = MetidaNCA.pkplot(pd[1], drawth = true, drawbl = true) png(p, "plot6.png") + +# Plot DoseTime (can be used for PK plots) + +dt = DoseTime(dose = 200, time = 1.5) +setdosetime!(pd, dt) + +p = MetidaNCA.pkplot(pd[1], drawdt = true) + + +png(p, "plot7.png") ``` +##### Plot 6 + ![](plot6.png) + +##### Plot 7 + +![](plot7.png) diff --git a/src/MetidaNCA.jl b/src/MetidaNCA.jl index f46db2a..a489a28 100644 --- a/src/MetidaNCA.jl +++ b/src/MetidaNCA.jl @@ -5,6 +5,8 @@ module MetidaNCA using RecipesBase +import RecipesBase: plot!, plot + import Base: length, length, push!, resize! import MetidaBase import MetidaBase: Tables, StatsBase, PrecompileTools, @@ -35,6 +37,7 @@ PKSubject, UPKSubject, PDSubject, NCAResult function __init__() @require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" begin savefig = Plots.savefig + current = Plots.current end end diff --git a/src/import.jl b/src/import.jl index dc7af1c..03684eb 100644 --- a/src/import.jl +++ b/src/import.jl @@ -327,12 +327,14 @@ Keywords: * `warn` - warning supress if `false`. """ -function pdimport(data, time, obs, sort; bl = 0, th = 0, limitrule::Union{Nothing, LimitRule} = nothing, warn = true) +function pdimport(data, time, obs, sort; bl = 0, th = 0, dosetime::Union{Nothing, DoseTime} = nothing, limitrule::Union{Nothing, LimitRule} = nothing, warn = true) if isa(sort, String) sort = [Symbol(sort)] end if isa(sort, Symbol) sort = [sort] end Tables.istable(data) || error("Data not a table!") + + cols = Tables.columns(data) cdata = Tuple(Tables.getcolumn(cols, y) for y in sort) d = Dict{Tuple{eltype.(cdata)...}, Vector{Int}}() @@ -341,6 +343,8 @@ function pdimport(data, time, obs, sort; bl = 0, th = 0, limitrule::Union{Nothin timec = Tables.getcolumn(data, time) obsc = Tables.getcolumn(data, obs) + if isnothing(dosetime) dosetime = DoseTime(NaN, zero(eltype(timec)), NaN) end + any(isnanormissing, timec) && error("Some time values is NaN or Missing!") sdata = Vector{PDSubject}(undef, length(d)) @@ -372,7 +376,7 @@ function pdimport(data, time, obs, sort; bl = 0, th = 0, limitrule::Union{Nothin timevals_spv = view(timevals, sp) obsvals_spv = view(obsvals, sp) timevals_sp, obsvals_sp = checkvalues(timevals_spv, obsvals_spv, warn = warn) - sdata[i] = PDSubject(timevals_sp, obsvals_sp, bl, th, Dict(sort .=> k)) + sdata[i] = PDSubject(timevals_sp, obsvals_sp, bl, th, dosetime, Dict(sort .=> k)) i += one(Int) end ds = DataSet(identity.(sdata)) diff --git a/src/nca.jl b/src/nca.jl index 6db3652..bceabb1 100644 --- a/src/nca.jl +++ b/src/nca.jl @@ -833,10 +833,10 @@ function nca!(data::PKSubject{T, O}; adm = :ev, calcm = :lint, intpm = nothing, return ncares end -function maxconc(subj::T) where T <: PKSubject +function maxconc(subj::T) where T <: AbstractSubject maximum(subj.obs) end -function minconc(subj::T, pos = false) where T <: PKSubject +function minconc(subj::T, pos = false) where T <: AbstractSubject if pos return minimum(Iterators.filter(x-> x > zero(x), subj.obs)) else @@ -1100,7 +1100,14 @@ function nca!(data::PDSubject{T,O}; calcm = :lint, intpm = nothing, verbose = 0, ################################################################################ result[:Obsnum] = obsnum = length(obs_cp) + result[:BL] = data.bl + + result[:TH] = data.th + + result[:Rmax], result[:Tmax], tmaxn = ctmax(time_cp, obs_cp, length(obs_cp)) + + # ALL NAN AND MISSING VALUES LINEAR INTERPOLATED step_2_interpolate!(time_cp, obs_cp, einds, 1, :lint) @@ -1138,6 +1145,78 @@ function nca!(data::PDSubject{T,O}; calcm = :lint, intpm = nothing, verbose = 0, result[:TIMEBTW] = result[:TBBL] - result[:TBTH] end + + # Tau parameters + if data.dosetime.tau > zero(data.dosetime.tau) + taufirstp = findfirst(x -> x >= data.dosetime.time, time_cp) + taulastp = findlast(x -> x <= data.dosetime.time + data.dosetime.tau, time_cp) + taupn = taulastp - taufirstp + + aucpartabl_tau = Array{ptype, 1}(undef, taupn) + aucpartbbl_tau = Array{ptype, 1}(undef, taupn) + aucpartath_tau = Array{ptype, 1}(undef, taupn) + aucpartbth_tau = Array{ptype, 1}(undef, taupn) + tpartabl_tau = Array{ptype, 1}(undef, taupn) + tpartbbl_tau = Array{ptype, 1}(undef, taupn) + tpartath_tau = Array{ptype, 1}(undef, taupn) + tpartbth_tau = Array{ptype, 1}(undef, taupn) + aucpartbtw_tau = Array{ptype, 1}(undef, taupn) + + for i = taufirstp:taulastp-1 + j = i - taufirstp + 1 + aucpartabl_tau[j], aucpartbbl_tau[j], tpartabl_tau[j], tpartbbl_tau[j], aucpartath_tau[j], aucpartbth_tau[j], tpartath_tau[j], tpartbth_tau[j], aucpartbtw_tau[j] = auctblth(obs_cp[i], obs_cp[i + 1], time_cp[i], time_cp[i + 1], data.bl, data.th, calcm) + end + # before first responce point + if data.dosetime.time < time_cp[taufirstp] + if taufirstp > 1 + # Interpolate responce between observations + intpmr = interpolate(time_cp[taufirstp-1], time_cp[taufirstp], data.dosetime.time, obs_cp[taufirstp-1], obs_cp[taufirstp], calcm, true) + aucpartabl_, aucpartbbl_, tpartabl_, tpartbbl_, aucpartath_, aucpartbth_, tpartath_, tpartbth_, aucpartbtw_ = auctblth(intpmr, obs_cp[taufirstp], data.dosetime.time, time_cp[taufirstp], data.bl, data.th, calcm) + else # else set first point to zero + aucpartabl_, aucpartbbl_, tpartabl_, tpartbbl_, aucpartath_, aucpartbth_, tpartath_, tpartbth_, aucpartbtw_ = auctblth(0, obs_cp[taufirstp], data.dosetime.time, time_cp[taufirstp], data.bl, data.th, calcm) + end + pushfirst!(aucpartabl_tau, aucpartabl_) + pushfirst!(aucpartbbl_tau, aucpartbbl_) + pushfirst!(aucpartath_tau, aucpartath_) + pushfirst!(aucpartbth_tau, aucpartbth_) + pushfirst!(tpartabl_tau, tpartabl_) + pushfirst!(tpartbbl_tau, tpartbbl_) + pushfirst!(tpartath_tau, tpartath_) + pushfirst!(tpartbth_tau, tpartbth_) + pushfirst!(aucpartbtw_tau, aucpartbtw_) + end + # after last responce point + if data.dosetime.time + data.dosetime.tau > time_cp[taulastp] + if taulastp < length(time_cp) + # Interpolate responce between observations + intpmr = interpolate(time_cp[taulastp], time_cp[taulastp+1], data.dosetime.time + data.dosetime.tau, obs_cp[taulastp], obs_cp[taulastp+1], calcm, true) + + aucpartabl_, aucpartbbl_, tpartabl_, tpartbbl_, aucpartath_, aucpartbth_, tpartath_, tpartbth_, aucpartbtw_ = auctblth(obs_cp[taulastp], intpmr, time_cp[taulastp], data.dosetime.time + data.dosetime.tau, data.bl, data.th, calcm) + else # else set first point to zero + aucpartabl_, aucpartbbl_, tpartabl_, tpartbbl_, aucpartath_, aucpartbth_, tpartath_, tpartbth_, aucpartbtw_ = auctblth(obs_cp[taulastp], 0, time_cp[taulastp], data.dosetime.time + data.dosetime.tau, data.bl, data.th, calcm) + end + push!(aucpartabl_tau, aucpartabl_) + push!(aucpartbbl_tau, aucpartbbl_) + push!(aucpartath_tau, aucpartath_) + push!(aucpartbth_tau, aucpartbth_) + push!(tpartabl_tau, tpartabl_) + push!(tpartbbl_tau, tpartbbl_) + push!(tpartath_tau, tpartath_) + push!(tpartbth_tau, tpartbth_) + push!(aucpartbtw_tau, aucpartbtw_) + end + + result[:AUCABLtau] = sum(aucpartabl_tau) + result[:AUCBBLtau] = sum(aucpartbbl_tau) + result[:AUCATHtau] = sum(aucpartath_tau) + result[:AUCBTHtau] = sum(aucpartbth_tau) + result[:TABLtau] = sum(tpartabl_tau) + result[:TBBLtau] = sum(tpartbbl_tau) + result[:TATHtau] = sum(tpartath_tau) + result[:TBTHtau] = sum(tpartbth_tau) + result[:AUCBTWtau] = sum(aucpartbtw_tau) + end + # Verbose output if verbose > 0 hnames = [:Time, :Observation, :AUCABL, :AUCBBL, :AUCATH, :AUCBTH] diff --git a/src/plots.jl b/src/plots.jl index 125b609..b80ffc2 100644 --- a/src/plots.jl +++ b/src/plots.jl @@ -45,7 +45,7 @@ end @userplot PKPlot @userplot PKElimpPlot @userplot PKElimpDrop -@userplot PdHLine +#@userplot PdHLine function luceil(x) fl = Int(floor(log10(x))) @@ -119,12 +119,13 @@ end (x, y) end +#= @recipe function f(subj::PdHLine) x, y = subj.args seriestype --> :straightline (x, [y, y]) end - +=# # Text label from ID function plotlabel(d, ld = nothing) title = "" @@ -157,6 +158,7 @@ Plot for subject * `plotstyle` - predefined plot style from PKPLOTSTYLE; * `drawbl` (`false`) - draw baseline, only for PDSubject; * `drawth` (`false`) - draw threshold, only for PDSubject; +* `drawdt` (`false`) - draw drawdose time; """ function pkplot(subj::AbstractSubject; ls = false, elim = false, xticksn = :auto, yticksn = :auto, kwargs...) @@ -170,6 +172,9 @@ function pkplot(subj::AbstractSubject; ls = false, elim = false, xticksn = :auto else kwargs[:linestyle], kwargs[:linecolor], kwargs[:markershape], kwargs[:markercolor] = kwargs[:plotstyle] end + if !(:drawdt in k) + kwargs[:drawdt] = false + end if !(:drawbl in k) kwargs[:drawbl] = false end @@ -256,12 +261,15 @@ function pkplot(subj::AbstractSubject; ls = false, elim = false, xticksn = :auto end if isa(subj, PDSubject) if kwargs[:drawth] == true - pdhline!(p, [minimum(subj.time), maximum(subj.time)], getth(subj), lc = :blue, label = "TH") + plot!(p, [minimum(subj.time), maximum(subj.time)], [getth(subj), getth(subj)], lc = kwargs[:linecolor], ls = :dashdot, label = "TH") end if kwargs[:drawbl] == true - pdhline!(p, [minimum(subj.time), maximum(subj.time)], getbl(subj), lc = :red, label = "BL") + plot!(p, [minimum(subj.time), maximum(subj.time)], [getbl(subj), getbl(subj)], lc = kwargs[:linecolor], ls = :dash, label = "BL") end end + if kwargs[:drawdt] == true && !isnan(subj.dosetime.time) + plot!(p, [subj.dosetime.time, subj.dosetime.time], [minimum(subj.obs), maximum(subj.obs)], label = "DoseTime", ls = :dot, lc = kwargs[:linecolor]) + end return p end @@ -276,6 +284,9 @@ function pkplot!(subj; ls = false, elim = false, xticksn = :auto, yticksn = :aut kwargs[:linestyle], kwargs[:linecolor], kwargs[:markershape], kwargs[:markercolor] = kwargs[:plotstyle] end + if !(:drawdt in k) + kwargs[:drawdt] = false + end if !(:legend in k) kwargs[:legend] = true end @@ -325,6 +336,18 @@ function pkplot!(subj; ls = false, elim = false, xticksn = :auto, yticksn = :aut end p = pkplot!(time, obs; lcd = yticksn, tcd = xticksn, kwargs...) + + if isa(subj, PDSubject) + if kwargs[:drawth] == true + plot!(p, [minimum(subj.time), maximum(subj.time)], [getth(subj), getth(subj)], lc = kwargs[:linecolor], ls = :dashdot, label = "TH") + end + if kwargs[:drawbl] == true + plot!(p, [minimum(subj.time), maximum(subj.time)], [getbl(subj), getbl(subj)], lc = kwargs[:linecolor], ls = :dash, label = "BL") + end + end + if kwargs[:drawdt] == true && !isnan(subj.dosetime.time) + plot!(p, [subj.dosetime.time, subj.dosetime.time], [minimum(subj.obs), maximum(subj.obs)], label = "DoseTime", ls = :dot, lc = kwargs[:linecolor]) + end return p end diff --git a/src/setdosetime.jl b/src/setdosetime.jl index 1c7f7b7..cf173ee 100644 --- a/src/setdosetime.jl +++ b/src/setdosetime.jl @@ -1,20 +1,20 @@ #Subject """ - setdosetime!(data::T, dosetime::DoseTime) where T <: PKSubject + setdosetime!(data::T, dosetime::DoseTime) where T <: AbstractSubject Set dose time `dosetime` for subject `data`. """ -function setdosetime!(data::PKSubject, dosetime::DoseTime) +function setdosetime!(data::AbstractSubject, dosetime::DoseTime) data.dosetime = dosetime data end #DS ind Int """ - setdosetime!(data::DataSet{T}, dosetime::DoseTime, ind::Int) where T <: PKSubject + setdosetime!(data::DataSet{T}, dosetime::DoseTime, ind::Int) where T <: AbstractSubject * `ind` - index in DataSet. """ -function setdosetime!(data::DataSet{<:PKSubject}, dosetime::DoseTime, ind::Int) +function setdosetime!(data::DataSet{<:AbstractSubject}, dosetime::DoseTime, ind::Int) setdosetime!(data[ind], dosetime) data end @@ -24,7 +24,7 @@ end * `inds` - indexes in DataSet. """ -function setdosetime!(data::DataSet{<:PKSubject}, dosetime::DoseTime, inds::Union{Vector{Int}, UnitRange{Int}, Tuple{Vararg{Int}}}) +function setdosetime!(data::DataSet{<:AbstractSubject}, dosetime::DoseTime, inds::Union{Vector{Int}, UnitRange{Int}, Tuple{Vararg{Int}}}) for i in inds setdosetime!(data[i], dosetime) end @@ -32,11 +32,11 @@ function setdosetime!(data::DataSet{<:PKSubject}, dosetime::DoseTime, inds::Unio end #DS all """ - setdosetime!(data::DataSet{T}, dosetime::DoseTime) where T <: PKSubject + setdosetime!(data::DataSet{T}, dosetime::DoseTime) where T <: AbstractSubject For all subjects in DataSet. """ -function setdosetime!(data::DataSet{<:PKSubject}, dosetime::DoseTime) +function setdosetime!(data::DataSet{<:AbstractSubject}, dosetime::DoseTime) for i = 1:length(data) setdosetime!(data[i], dosetime) end @@ -44,11 +44,11 @@ function setdosetime!(data::DataSet{<:PKSubject}, dosetime::DoseTime) end #DS Dict """ - setdosetime!(data::DataSet{T}, dosetime::DoseTime, sort::Dict) where T <: PKSubject + setdosetime!(data::DataSet{T}, dosetime::DoseTime, sort::Dict) where T <: AbstractSubject Set dose time `dosetime` for subjects if `sort` ⊆ subject's `id`. """ -function setdosetime!(data::DataSet{<:PKSubject}, dosetime::DoseTime, sort::Dict) +function setdosetime!(data::DataSet{<:AbstractSubject}, dosetime::DoseTime, sort::Dict) for i = 1:length(data) if sort ⊆ data[i].id setdosetime!(data[i], dosetime) end end @@ -60,7 +60,7 @@ end Return dosetime. """ -function getdosetime(data::PKSubject) +function getdosetime(data::AbstractSubject) data.dosetime end diff --git a/src/show.jl b/src/show.jl index 76e1149..c014070 100644 --- a/src/show.jl +++ b/src/show.jl @@ -59,13 +59,13 @@ function Base.show(io::IO, obj::PDSubject) PrettyTables.pretty_table(io, metida_table(obj.time, obj.obs; names = (:Time, :Observation)); tf = PrettyTables.tf_compact) end -function subject_type_str(subj::Type{<:PKSubject}) +function subject_type_str(subj::Type{PKS}) where PKS <: PKSubject "Pharmacokinetics subject" end -function subject_type_str(subj::Type{<:UPKSubject}) +function subject_type_str(subj::Type{UPKS}) where UPKS <: UPKSubject "Pharmacokinetics subject (urine)" end -function subject_type_str(subj::Type{<:PDSubject}) +function subject_type_str(subj::Type{PDS}) where PDS <: PDSubject "Pharmacodynamics subject" end function Base.show(io::IO, obj::DataSet{ST}) where ST <: AbstractSubject diff --git a/src/types.jl b/src/types.jl index ae9d11b..431d364 100644 --- a/src/types.jl +++ b/src/types.jl @@ -106,7 +106,7 @@ end # PK subject """ - PKSubject(time::Vector{T}, conc::Vector{O}, kelauto::Bool, kelrange::ElimRange, dosetime::DoseTime, keldata::KelData, sort::Dict{Symbol, V} = Dict{Symbol, Any}()) where T <: Number where O <: Union{Number, Missing} where V + PKSubject(time::Vector{T}, conc::Vector{O}, kelauto::Bool, kelrange::ElimRange, dosetime::DoseTime, keldata::KelData, id::Dict{Symbol, V} = Dict{Symbol, Any}()) where T <: Number where O <: Union{Number, Missing} where V Pharmacokinetic subject. @@ -129,11 +129,11 @@ mutable struct PKSubject{T <: Number, O <: Union{Number, Missing}, V <: Any} <: dosetime::DoseTime keldata::KelData id::Dict{Symbol, V} - function PKSubject(time::Vector{T}, conc::Vector{O}, kelauto::Bool, kelrange::ElimRange, dosetime::DoseTime, keldata::KelData, sort::Dict{Symbol, V} = Dict{Symbol, Any}()) where T <: Number where O <: Union{Number, Missing} where V - new{T, O, V}(time, conc, kelauto, kelrange, dosetime, keldata, sort)::PKSubject + function PKSubject(time::Vector{T}, conc::Vector{O}, kelauto::Bool, kelrange::ElimRange, dosetime::DoseTime, keldata::KelData, id::Dict{Symbol, V} = Dict{Symbol, Any}()) where T <: Number where O <: Union{Number, Missing} where V + new{T, O, V}(time, conc, kelauto, kelrange, dosetime, keldata, id)::PKSubject end - function PKSubject(time::Vector{T}, conc::Vector{O}, kelauto::Bool, kelrange::ElimRange, dosetime::DoseTime, sort::Dict{Symbol, V}) where T where O where V - PKSubject(time, conc, kelauto, kelrange, dosetime, KelData(T[], T[], Float64[], Float64[], Float64[], Float64[], Int[]), sort) + function PKSubject(time::Vector{T}, conc::Vector{O}, kelauto::Bool, kelrange::ElimRange, dosetime::DoseTime, id::Dict{Symbol, V}) where T where O where V + PKSubject(time, conc, kelauto, kelrange, dosetime, KelData(T[], T[], Float64[], Float64[], Float64[], Float64[], Int[]), id) end #= function PKSubject(time::Vector, conc::Vector, sort::Dict) @@ -240,12 +240,13 @@ mutable struct PDSubject{T <: Number, O <: Union{Number, Missing}, V <: Any} <: obs::Vector{O} bl::Float64 th::Float64 + dosetime::DoseTime id::Dict{Symbol, V} - function PDSubject(time::Vector{T}, conc::Vector{O}, bl, th, sort::Dict{Symbol, V} = Dict{Symbol, Any}()) where T <: Number where O <: Union{Number, Missing} where V - new{T, O, V}(time, conc, bl, th, sort)::PDSubject + function PDSubject(time::Vector{T}, conc::Vector{O}, bl, th, dosetime::DoseTime, id::Dict{Symbol, V} = Dict{Symbol, Any}()) where T <: Number where O <: Union{Number, Missing} where V + new{T, O, V}(time, conc, bl, th, dosetime, id)::PDSubject end - function PDSubject(time::Vector, conc::Vector, bl, th, sort::Dict{Symbol, V}) where V - PDSubject(time, conc, bl, th, sort) + function PDSubject(time::Vector, conc::Vector, bl, th, id::Dict{Symbol, V}) where V + PDSubject(time, conc, bl, th, DoseTime(), id) end end diff --git a/test/pdtest.jl b/test/pdtest.jl index f7428cb..6ce282f 100644 --- a/test/pdtest.jl +++ b/test/pdtest.jl @@ -6,6 +6,9 @@ @test_nowarn MetidaNCA.pkplot(pd) @test_nowarn MetidaNCA.pkplot(pd[1], drawth = true, drawbl = true) + p = plot() + @test_nowarn MetidaNCA.pkplot!(pd[1], drawth = true, drawbl = true) + pd_res = MetidaNCA.nca!(pd[1]) pd_rds = MetidaNCA.nca!(pd) @@ -76,3 +79,69 @@ # pd_rds = MetidaNCA.nca!(pd; calcm = :luld) end + + +@testset " #7 Pharmacodynamics data; Linear-trapezoidal rule; Tau " begin + + io = IOBuffer(); + + pd = MetidaNCA.pdimport(pddata, :time, :obs, :subj; bl = 1.5, th = 5.0) + + dt = MetidaNCA.DoseTime(dose = 100, time = 0.0, tau = 9.0) + MetidaNCA.setdosetime!(pd, dt) + pd_rds = MetidaNCA.nca!(pd) + + @test pd_rds[1,:AUCATH] ≈ pd_rds[1,:AUCATHtau] atol=1E-6 + @test pd_rds[1,:AUCBTH] ≈ pd_rds[1,:AUCBTHtau] atol=1E-6 + @test pd_rds[1,:AUCABL] ≈ pd_rds[1,:AUCABLtau] atol=1E-6 + @test pd_rds[1,:AUCBBL] ≈ pd_rds[1,:AUCBBLtau] atol=1E-6 + @test pd_rds[1,:AUCBTW] ≈ pd_rds[1,:AUCBTWtau] atol=1E-6 + @test pd_rds[1,:TATH] ≈ pd_rds[1,:TATHtau] atol=1E-6 + @test pd_rds[1,:TBTH] ≈ pd_rds[1,:TBTHtau] atol=1E-6 + @test pd_rds[1,:TABL] ≈ pd_rds[1,:TABLtau] atol=1E-6 + @test pd_rds[1,:TBBL] ≈ pd_rds[1,:TBBLtau] atol=1E-6 + + + dt = MetidaNCA.DoseTime(dose = 100, time = 1.0, tau = 7.0) + MetidaNCA.setdosetime!(pd, dt) + pd_rds = MetidaNCA.nca!(pd) + @test pd_rds[1,:AUCATH] ≈ pd_rds[1,:AUCATHtau] atol=1E-6 + @test pd_rds[1,:AUCBTH] - 8.5 ≈ pd_rds[1,:AUCBTHtau] atol=1E-6 + @test pd_rds[1,:AUCABL] ≈ pd_rds[1,:AUCABLtau] atol=1E-6 + @test pd_rds[1,:AUCBBL] - 1.5 ≈ pd_rds[1,:AUCBBLtau] atol=1E-6 + @test pd_rds[1,:AUCBTW] ≈ pd_rds[1,:AUCBTWtau] atol=1E-6 + @test pd_rds[1,:TATH] ≈ pd_rds[1,:TATHtau] atol=1E-6 + @test pd_rds[1,:TBTH] - 2 ≈ pd_rds[1,:TBTHtau] atol=1E-6 + @test pd_rds[1,:TABL] ≈ pd_rds[1,:TABLtau] atol=1E-6 + @test pd_rds[1,:TBBL] - 2 ≈ pd_rds[1,:TBBLtau] atol=1E-6 + + + dt = MetidaNCA.DoseTime(dose = 100, time = 0.5, tau = 8.0) + MetidaNCA.setdosetime!(pd, dt) + pd_rds = MetidaNCA.nca!(pd) + @test pd_rds[1,:AUCATH] ≈ pd_rds[1,:AUCATHtau] atol=1E-6 + @test pd_rds[1,:AUCBTH] - 4.375 ≈ pd_rds[1,:AUCBTHtau] atol=1E-6 + @test pd_rds[1,:AUCABL] ≈ pd_rds[1,:AUCABLtau] atol=1E-6 + @test pd_rds[1,:AUCBBL] - 0.875 ≈ pd_rds[1,:AUCBBLtau] atol=1E-6 + @test pd_rds[1,:AUCBTW] ≈ pd_rds[1,:AUCBTWtau] atol=1E-6 + @test pd_rds[1,:TATH] ≈ pd_rds[1,:TATHtau] atol=1E-6 + @test pd_rds[1,:TBTH] - 1 ≈ pd_rds[1,:TBTHtau] atol=1E-6 + @test pd_rds[1,:TABL] ≈ pd_rds[1,:TABLtau] atol=1E-6 + @test pd_rds[1,:TBBL] - 1 ≈ pd_rds[1,:TBBLtau] atol=1E-6 + + pddata2 = deepcopy(pddata) + deleteat!(pddata2, 1) + pd2 = MetidaNCA.pdimport(pddata2, :time, :obs, :subj; bl = 1.5, th = 5.0, dosetime = MetidaNCA.DoseTime(dose = 100, time = 0.0, tau = 9.0)) + pd_rds2 = MetidaNCA.nca!(pd2) + + @test pd_rds2[1,:AUCATH] ≈ pd_rds2[1,:AUCATHtau] atol=1E-6 + @test pd_rds2[1,:AUCBTH] + 4.5 ≈ pd_rds2[1,:AUCBTHtau] atol=1E-6 + @test pd_rds2[1,:AUCABL] ≈ pd_rds2[1,:AUCABLtau] atol=1E-6 + @test pd_rds2[1,:AUCBBL] + 1 ≈ pd_rds2[1,:AUCBBLtau] atol=1E-6 + @test pd_rds2[1,:AUCBTW] ≈ pd_rds2[1,:AUCBTWtau] atol=1E-6 + @test pd_rds2[1,:TATH] ≈ pd_rds2[1,:TATHtau] atol=1E-6 + @test pd_rds2[1,:TBTH] + 1 ≈ pd_rds2[1,:TBTHtau] atol=1E-6 + @test pd_rds2[1,:TABL] ≈ pd_rds2[1,:TABLtau] atol=1E-6 + @test pd_rds2[1,:TBBL] + 1 ≈ pd_rds2[1,:TBBLtau] atol=1E-6 + +end diff --git a/test/tests.jl b/test/tests.jl index 21726d4..23cc2a6 100644 --- a/test/tests.jl +++ b/test/tests.jl @@ -75,6 +75,9 @@ include("refdicts.jl") # If typesort defined and NoPageSort() return one plot pl = @test_nowarn MetidaNCA.pkplot(ds; typesort = :Subject, pagesort = MetidaNCA.NoPageSort(), sort = Dict(:Formulation => "R")) @test isa(pl, Plots.Plot) == true + #@test_throws "There is no pkplot! methods for DataSet, use pkplot or pkplot! for each subject separately." MetidaNCA.pkplot!(ds; typesort = :Subject, pagesort = MetidaNCA.NoPageSort(), sort = Dict(:Formulation => "R")) + + pl = @test_nowarn MetidaNCA.pkplot(ds; typesort = :Formulation, pagesort = MetidaNCA.NoPageSort(), legend = true) @test isa(pl, Plots.Plot) == true @@ -107,12 +110,26 @@ include("refdicts.jl") @test isa(pl, Plots.Plot) == true # Return plot for PKSubject + + @test_nowarn MetidaNCA.pkplot(ds[1].time, ds[1].obs) + @test_nowarn MetidaNCA.pkplot!(ds[1].time, ds[1].obs) + p = plot() + @test_nowarn MetidaNCA.pkplot!(p, ds[1].time, ds[1].obs) + p = plot() + @test_nowarn MetidaNCA.pkplot!(ds[1]) + #p = plot() + #@test_nowarn MetidaNCA.pkplot!(ds[1]) + @test_nowarn pl = MetidaNCA.pkplot(ds[1]; ylims = (0, 250), yscale = :log10, legend = false) @test_nowarn pl = MetidaNCA.pkplot(ds[1]; elim = true, ls = false) @test_nowarn MetidaNCA.plotstyle(40) pl = MetidaNCA.pkplot(ds[3]) pl = MetidaNCA.pkplot!(ds[2]; yscale = :log10) + p = plot() + MetidaNCA.pkplot!(ds[1]; ylims = (0, 250), yscale = :log10, legend = false) + #MetidaNCA.pkplot!(p, ds[1]; ylims = (0, 250), yscale = :log10, legend = false) + kr = MetidaNCA.ElimRange(kelstart = 4, kelend = 12, kelexcl = Int[5,6]) MetidaNCA.setkelrange!(ds, kr, [1,2,3]) dsnca = MetidaNCA.nca!(ds) @@ -184,6 +201,12 @@ include("refdicts.jl") dsncafromds = MetidaNCA.pkimport(missingpk, :Time, :Concentration, :Subject; limitrule = MetidaNCA.LimitRule(;lloq = 0, btmax = 0, atmax = NaN, nan = NaN, rm = true)) + + # PD import + pd = MetidaNCA.pdimport(pddata, :time, :obs; bl = 3.0, th = 1.5, id = Dict(:subj => 1)) + # draw PD + pl = @test_nowarn MetidaNCA.pkplot(pd; legend = true, drawbl = true, drawth = true, drawdt = true) + # Multiple time @test_logs (:warn,"Not all time values is unique ([96.0, 4.0, 2.5]), last observation used! ((1,))") (:warn,"Some concentration values maybe not a number, try to fix.") ds = MetidaNCA.pkimport(multtimepk, :Time, :Concentration, :Subject)