From 64e1267785dcf730f2652c986377b5fbe49f58ab Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Tue, 22 Aug 2023 21:18:19 +0300 Subject: [PATCH 01/22] plot update (ldict) --- src/plots.jl | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/plots.jl b/src/plots.jl index 67d2f0f..9dd127e 100644 --- a/src/plots.jl +++ b/src/plots.jl @@ -115,12 +115,16 @@ end end # Text label from ID -function plotlabel(d) +function plotlabel(d, ld = nothing) title = "" if isnothing(d) return title end if length(d) > 0 for (k, v) in d - title *= "$(k) = $(v); " + kv = k + if !isnothing(ld) && haskey(ld, kv) + kv = ld[kv] + end + title *= "$(kv) = $(v); " end end return title @@ -309,7 +313,7 @@ function pageplot(data, id, ulist; kwargs...) kwargs = Dict{Symbol, Any}(kwargs) k = keys(kwargs) if !(:title in k) - kwargs[:title] = plotlabel(id) + kwargs[:title] = plotlabel(id, kwargs[:ldict]) end fst = true @@ -338,7 +342,7 @@ function pageplot(data, id, ulist; kwargs...) if num ∈ labvec kwargs[:label] = nothing else - kwargs[:label] = plotlabel(ulist[num]) + kwargs[:label] = plotlabel(ulist[num], kwargs[:ldict]) push!(labvec, num) end else @@ -370,7 +374,8 @@ PK plot for subject set. * `typesort` - sort on page by this id key; * `pagesort` - different pages by this id key; * `filter` - use only subjects if filter ⊆ subject id; -* `uylims` - same ylims for all dataset. +* `uylims` - same ylims for all dataset; +* `ldict` - Dict with labels for replace. Use `pagesort = MetidaNCA.NoPageSort()` to prevent page plotting. """ @@ -379,6 +384,7 @@ function pkplot(data::DataSet{T}; pagesort::Union{Nothing, Symbol, AbstractVector{Symbol}, NoPageSort} = nothing, filter::Union{Nothing, Dict{Symbol}} = nothing, uylims::Bool = false, + ldict = nothing, kwargs...) where T <: AbstractSubject kwargs = Dict{Symbol, Any}(kwargs) @@ -408,17 +414,16 @@ function pkplot(data::DataSet{T}; end for subj in data if printtitle - kwargs[:title] = plotlabel(subj.id) + kwargs[:title] = plotlabel(subj.id, ldict) end if !(:legend in k) kwargs[:legend] = false end - push!(p, pkplot(subj; kwargs...)) + push!(p, pkplot(subj; kwargs...)) end return p end - if !isnothing(typesort) if isa(typesort, Symbol) typesort = [typesort] end typelist = uniqueidlist(data, typesort) @@ -434,13 +439,13 @@ function pkplot(data::DataSet{T}; p = [] pagelist = uniqueidlist(data, pagesort) for id in pagelist - push!(p, pageplot(data, id, typelist; kwargs...)) + push!(p, pageplot(data, id, typelist; ldict, kwargs...)) end return p else if !(:title in k) && !isnothing(filter) kwargs[:title] = plotlabel(filter) end - return pageplot(data, nothing, typelist; kwargs...) + return pageplot(data, nothing, typelist; ldict, kwargs...) end end \ No newline at end of file From 476450a4261a3c192696e0d161c901571280404d Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Tue, 17 Oct 2023 16:11:26 +0300 Subject: [PATCH 02/22] plotting --- Project.toml | 2 +- src/plots.jl | 24 ++++++++++++++++++++++++ test/tests.jl | 3 +++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 1decdfe..5e80938 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MetidaNCA" uuid = "097c2839-c7bc-4c4b-a5f2-b4167c1b4e7c" authors = ["PharmCat "] -version = "0.5.8" +version = "0.5.9" [deps] diff --git a/src/plots.jl b/src/plots.jl index 9dd127e..e80c5b3 100644 --- a/src/plots.jl +++ b/src/plots.jl @@ -204,6 +204,10 @@ function pkplot(subj::AbstractSubject; ls = false, elim = false, xticksn = :auto end if !(:ylims in k) kwargs[:ylims] = (minimum(obs)*0.5, maximum(obs)*2.) + else + if kwargs[:ylims][1] <= 0 + kwargs[:ylims] = (minimum(obs)/b, kwargs[:ylims][2]) + end end end else @@ -288,6 +292,10 @@ function pkplot!(subj; ls = false, elim = false, xticksn = :auto, yticksn = :aut end if !(:ylims in k) kwargs[:ylims] = (minimum(obs)*0.5, maximum(obs)*2.) + else + if kwargs[:ylims][1] <= 0 + kwargs[:ylims] = (minimum(obs)/b, kwargs[:ylims][2]) + end end end else @@ -448,4 +456,20 @@ function pkplot(data::DataSet{T}; end return pageplot(data, nothing, typelist; ldict, kwargs...) end +end + + +""" + pkplot(data::DataSet{T}; kwargs...) where T <: NCAResult +""" +function pkplot(data::DataSet{T}; kwargs...) where T <: NCAResult + ds = map(x-> x.data, data) + pkplot(ds; kwargs...) +end + +""" + pkplot(data::NCAResult; kwargs...) +""" +function pkplot(data::NCAResult; kwargs...) + pkplot(data.data; kwargs...) end \ No newline at end of file diff --git a/test/tests.jl b/test/tests.jl index 44fa67f..de92056 100644 --- a/test/tests.jl +++ b/test/tests.jl @@ -84,6 +84,9 @@ include("refdicts.jl") @test_nowarn MetidaNCA.plotstyle(40) pl = MetidaNCA.pkplot(ds[2]) pl = MetidaNCA.pkplot!(ds[3]; yscale = :log10) + #Plot from NCA result DataSet + @test_nowarn MetidaNCA.pkplot(dsncafromds[1]; ylims = (0, 10), yscale = :log10, legend = false) + @test_nowarn MetidaNCA.pkplot(dsncafromds; typesort = :Subject, pagesort = :Formulation, elim = true, ls = true, title = "Plots") # Unknown typesort @test_nowarn pl = MetidaNCA.pkplot(ds; typesort = :unknown) From 92eec22801d19184d710fe15fbfd2c17c170b8e1 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Sun, 24 Mar 2024 19:07:29 +0300 Subject: [PATCH 03/22] docs pkg --- Project.toml | 2 +- docs/Project.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 5e80938..debeb3e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MetidaNCA" uuid = "097c2839-c7bc-4c4b-a5f2-b4167c1b4e7c" authors = ["PharmCat "] -version = "0.5.9" +version = "0.5.10" [deps] diff --git a/docs/Project.toml b/docs/Project.toml index 8d27f9a..6e76203 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -10,11 +10,11 @@ Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" [compat] -Documenter = "≥0.25" +Documenter = "1" MetidaNCA = "0.5" CSV = "0.8, 0.9, 0.10" DataFrames = "1" PrettyTables = "1, 2" Weave = "0.9, 0.10" Plots = "1" -Latexify = "0.14, 0.15" +Latexify = "0.14, 0.15, 0.16" From 34488ed4317aca03d1a077f522f9bd92dcfc4a05 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:12:23 +0300 Subject: [PATCH 04/22] docs, minor fix --- docs/src/details.md | 10 ++++++++++ src/import.jl | 3 +++ src/nca.jl | 13 ++++++++----- src/plots.jl | 25 ++++++++++++------------- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/docs/src/details.md b/docs/src/details.md index a2ef253..f468f29 100644 --- a/docs/src/details.md +++ b/docs/src/details.md @@ -1,5 +1,15 @@ # Details +## Using LimitRule + +```julia +ll = LimitRule(;lloq = 0.1, btmax = 0.0, atmax = NaN, nan = NaN, rm = true) + +``` + +It means that all values below `lloq` will be replaced by `btmax` before Tmax and replaced by `atmax` after Tmax; `NaN` values will be replaced by `nan`. If `rm` is `true`, all `NaN` values will be deleted. + + ## Calculation steps for PK NCA ### Step 1 diff --git a/src/import.jl b/src/import.jl index 1d116c7..dc7af1c 100644 --- a/src/import.jl +++ b/src/import.jl @@ -103,6 +103,8 @@ keywords: If time column have non-unique values - last pair time-concentration will be used. + +See also: [`ElimRange`](@ref), [`DoseTime`](@ref), [`LimitRule`](@ref). """ function pkimport(data, time, conc, sort; kelauto = true, elimrange = ElimRange(), dosetime = nothing, limitrule::Union{Nothing, LimitRule} = nothing, warn = true, kwargs...) if isa(sort, String) sort = [Symbol(sort)] end @@ -181,6 +183,7 @@ end kwargs...) Import PK data from time vector `time` and concentration vector `conc`. + """ function pkimport(time, conc; kelauto = true, elimrange = ElimRange(), dosetime = nothing, id = Dict{Symbol, Any}(), limitrule::Union{Nothing, LimitRule} = nothing, warn = true, kwargs...) timevals_sp, concvals_sp = checkvalues(time, conc, warn = warn) diff --git a/src/nca.jl b/src/nca.jl index 6d2695c..8136eaf 100644 --- a/src/nca.jl +++ b/src/nca.jl @@ -392,6 +392,8 @@ Import data and perform NCA analysis. Syntax simillar to [`pkimport`](@ref) Applicable `kwargs` see [`nca!`](@ref). + +See also: [`ElimRange`](@ref), [`DoseTime`](@ref), [`LimitRule`](@ref). """ function nca(args...; type::Symbol = :bps, bl = 0, th = 0, kelauto = true, elimrange = ElimRange(), dosetime = DoseTime(), limitrule::Union{Nothing, LimitRule} = nothing, kwargs...) if !(type in (:bps, :ur, :pd)) error("Unknown type") end @@ -411,11 +413,12 @@ end Non-compartmental (NCA) analysis of PK/PD data. """ function nca!(data::DataSet{Subj}; kwargs...) where Subj <: AbstractSubject - result = Vector{NCAResult{Subj}}(undef, length(data)) - for i = 1:length(data) - result[i] = nca!(data[i]; kwargs...) - end - DataSet(result) + #result = Vector{NCAResult{Subj}}(undef, length(data)) + #for i = 1:length(data) + # result[i] = nca!(data[i]; kwargs...) + #end + #DataSet(result) + map(x -> nca!(x; kwargs...), data) end """ diff --git a/src/plots.jl b/src/plots.jl index e80c5b3..57532ca 100644 --- a/src/plots.jl +++ b/src/plots.jl @@ -393,6 +393,7 @@ function pkplot(data::DataSet{T}; filter::Union{Nothing, Dict{Symbol}} = nothing, uylims::Bool = false, ldict = nothing, + savepng = nothing, kwargs...) where T <: AbstractSubject kwargs = Dict{Symbol, Any}(kwargs) @@ -414,6 +415,16 @@ function pkplot(data::DataSet{T}; end if !isnothing(filter) data = subset(data, filter) end + if !isnothing(typesort) + if isa(typesort, Symbol) typesort = [typesort] end + typelist = uniqueidlist(data, typesort) + else + typelist = nothing + if !(:legend in k) + kwargs[:legend] = false + end + end + if isnothing(typesort) && isnothing(pagesort) p = [] printtitle = false @@ -430,19 +441,7 @@ function pkplot(data::DataSet{T}; push!(p, pkplot(subj; kwargs...)) end return p - end - - if !isnothing(typesort) - if isa(typesort, Symbol) typesort = [typesort] end - typelist = uniqueidlist(data, typesort) - else - typelist = nothing - if !(:legend in k) - kwargs[:legend] = false - end - end - - if !isnothing(pagesort) && !isa(pagesort, NoPageSort) + elseif !isnothing(pagesort) && !isa(pagesort, NoPageSort) if isa(pagesort, Symbol) pagesort = [pagesort] end p = [] pagelist = uniqueidlist(data, pagesort) From d550a921cbdbf2a7a178b1fef4f44777128f5cc4 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:02:15 +0300 Subject: [PATCH 05/22] docs --- docs/src/details.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/src/details.md b/docs/src/details.md index f468f29..971ef50 100644 --- a/docs/src/details.md +++ b/docs/src/details.md @@ -9,6 +9,8 @@ ll = LimitRule(;lloq = 0.1, btmax = 0.0, atmax = NaN, nan = NaN, rm = true) It means that all values below `lloq` will be replaced by `btmax` before Tmax and replaced by `atmax` after Tmax; `NaN` values will be replaced by `nan`. If `rm` is `true`, all `NaN` values will be deleted. +See also: [`applylimitrule!`](@ref). + ## Calculation steps for PK NCA From 9b9b3842f37413a07c8447afc3f4b217f9608a87 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:21:17 +0300 Subject: [PATCH 06/22] show ds --- src/show.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/show.jl b/src/show.jl index 5e1e529..041e95f 100644 --- a/src/show.jl +++ b/src/show.jl @@ -71,7 +71,8 @@ end function Base.show(io::IO, obj::DataSet{ST}) where ST <: AbstractSubject println(io, "DataSet: $(subject_type_str(ST))") println(io, "Length: $(length(obj))") - for i = 1:length(obj) + lo = min(length(obj), 20) + for i = 1:lo print(io, "Subject $(i): ") if length(obj[i].id) > 0 for (k, v) in obj[i].id @@ -82,6 +83,9 @@ function Base.show(io::IO, obj::DataSet{ST}) where ST <: AbstractSubject println(io, "-") end end + if lo < length(obj) + printstyled(io, "$(length(obj) - lo) subjects omitted... \n"; color = :blue) + end end function Base.show(io::IO, obj::T) where T <: NCAResult From 3eeb5786b6867a82f4874831bfc483e353c029fe Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:22:44 +0300 Subject: [PATCH 07/22] show res ds --- src/show.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/show.jl b/src/show.jl index 041e95f..76e1149 100644 --- a/src/show.jl +++ b/src/show.jl @@ -96,7 +96,8 @@ end function Base.show(io::IO, obj::DataSet{Res}) where Res <: NCAResult println(io, "DataSet: PK/PD NCA result") println(io, "Length: $(length(obj))") - for i = 1:length(obj) + lo = min(length(obj), 20) + for i = 1:lo print(io, "Subject $(i): ") if length(obj[i].data.id) > 0 for (k, v) in obj[i].data.id @@ -107,4 +108,7 @@ function Base.show(io::IO, obj::DataSet{Res}) where Res <: NCAResult println(io, "-") end end + if lo < length(obj) + printstyled(io, "$(length(obj) - lo) subjects omitted... \n"; color = :blue) + end end From b431c351d5aab087db2e9676f90c9b32d618ccb2 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:46:12 +0300 Subject: [PATCH 08/22] save plots --- src/MetidaNCA.jl | 8 ++++++++ src/plots.jl | 39 +++++++++++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/MetidaNCA.jl b/src/MetidaNCA.jl index ac0be3b..c54cb43 100644 --- a/src/MetidaNCA.jl +++ b/src/MetidaNCA.jl @@ -22,6 +22,8 @@ uniqueidlist, indsdict!, subset +using MetidaBase.Requires + export pkimport, upkimport, pdimport, nca!, nca, DoseTime, ElimRange, LimitRule, NoPageSort, auc_sparse, setdosetime!, setkelauto!, setkelrange!, applylimitrule!, setbl!, setth!, @@ -29,6 +31,12 @@ pkplot, getkeldata, getkelauto, getkelrange, getdosetime, getbl, getth, subset metida_table +function __init__() + @require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" begin + import Plots:savefig + end +end + const LOG2 = log(2) include("types.jl") diff --git a/src/plots.jl b/src/plots.jl index 57532ca..8bd09a8 100644 --- a/src/plots.jl +++ b/src/plots.jl @@ -375,6 +375,9 @@ end pagesort::Union{Nothing, Symbol, AbstractVector{Symbol}, NoPageSort} = nothing, filter::Union{Nothing, Dict{Symbol}} = nothing, uylims::Bool = false, + ldict = nothing, + savepath::Union{Nothing, AbstractString} = nothing, + namepref::Union{Nothing, AbstractString} = nothing, kwargs...) where T <: AbstractSubject PK plot for subject set. @@ -383,7 +386,9 @@ PK plot for subject set. * `pagesort` - different pages by this id key; * `filter` - use only subjects if filter ⊆ subject id; * `uylims` - same ylims for all dataset; -* `ldict` - Dict with labels for replace. +* `ldict` - Dict with labels for replace; +* `savepath` - path for plot saving; +* `namepref` - name prefix for saving files. Use `pagesort = MetidaNCA.NoPageSort()` to prevent page plotting. """ @@ -393,7 +398,8 @@ function pkplot(data::DataSet{T}; filter::Union{Nothing, Dict{Symbol}} = nothing, uylims::Bool = false, ldict = nothing, - savepng = nothing, + savepath::Union{Nothing, AbstractString} = nothing, + namepref::Union{Nothing, AbstractString} = nothing, kwargs...) where T <: AbstractSubject kwargs = Dict{Symbol, Any}(kwargs) @@ -424,9 +430,8 @@ function pkplot(data::DataSet{T}; kwargs[:legend] = false end end - + p = [] if isnothing(typesort) && isnothing(pagesort) - p = [] printtitle = false if !(:title in k) printtitle = true @@ -440,20 +445,38 @@ function pkplot(data::DataSet{T}; end push!(p, pkplot(subj; kwargs...)) end - return p elseif !isnothing(pagesort) && !isa(pagesort, NoPageSort) if isa(pagesort, Symbol) pagesort = [pagesort] end - p = [] pagelist = uniqueidlist(data, pagesort) for id in pagelist push!(p, pageplot(data, id, typelist; ldict, kwargs...)) end - return p else if !(:title in k) && !isnothing(filter) kwargs[:title] = plotlabel(filter) end - return pageplot(data, nothing, typelist; ldict, kwargs...) + push!(p,pageplot(data, nothing, typelist; ldict, kwargs...)) + end + + if !isnothing(savepath) + if @isdefined savefig + if isfile(savepath) + error("File found on this path...") + elseif !isdir(savepath) + mkpath(savepath) + end + if isnothing(namepref) namepref = "plot" end + for i = 1: length(p) + savefig(p[i], joinpath(savepath, namepref*"_$(i).png")) + end + else + @warn "savefig not defined, install Plots.jl for plot writing... plots NOT saved..." + end + end + if length(p) > 1 + return p + else + return p[1] end end From bab326ca70db8cdaea56085e4c144b3531194f62 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:49:07 +0300 Subject: [PATCH 09/22] version bump --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index f19f97b..1793bae 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MetidaNCA" uuid = "097c2839-c7bc-4c4b-a5f2-b4167c1b4e7c" authors = ["PharmCat "] -version = "0.5.10" +version = "0.5.11" From 4b907c5a54725d8a977e6835e7e3566c1c7abf0b Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Tue, 16 Jul 2024 22:38:00 +0300 Subject: [PATCH 10/22] update --- .github/workflows/Documenter.yml | 2 +- .github/workflows/Tier1.yml | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/Documenter.yml b/.github/workflows/Documenter.yml index 316c92a..e02cfcd 100644 --- a/.github/workflows/Documenter.yml +++ b/.github/workflows/Documenter.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Update run: sudo apt-get update - name: Install Pandoc diff --git a/.github/workflows/Tier1.yml b/.github/workflows/Tier1.yml index 34b583b..bc87bc7 100644 --- a/.github/workflows/Tier1.yml +++ b/.github/workflows/Tier1.yml @@ -36,15 +36,26 @@ jobs: arch: - x64 steps: - - uses: actions/checkout@v3 - - uses: julia-actions/setup-julia@v1 + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: julia-actions/cache@v1 + - uses: actions/cache@v4 + env: + cache-name: cache-artifacts + with: + path: ~/.julia/artifacts + key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} + restore-keys: | + ${{ runner.os }}-test-${{ env.cache-name }}- + ${{ runner.os }}-test- + ${{ runner.os }}- - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4 + if: ${{ matrix.os == 'ubuntu-latest' && matrix.version == '1' && matrix.arch == 'x64' }} with: - files: lcov.info + file: lcov.info + token: ${{ secrets.CODECOV_TOKEN }} From d193ccdb1b9a09f0f6b4841cc036e54d4f2dcd84 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Tue, 16 Jul 2024 23:09:47 +0300 Subject: [PATCH 11/22] update --- .github/workflows/Tier1.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Tier1.yml b/.github/workflows/Tier1.yml index bc87bc7..ed70fa4 100644 --- a/.github/workflows/Tier1.yml +++ b/.github/workflows/Tier1.yml @@ -28,7 +28,7 @@ jobs: version: - '1.6' - '1.8' - - '1.9' + - '1' os: - ubuntu-latest - macOS-latest From bc1e5c3eb7dcdf75c5c24147b6626bae24479385 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Tue, 16 Jul 2024 23:19:32 +0300 Subject: [PATCH 12/22] update --- Project.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Project.toml b/Project.toml index 1793bae..eb2fdca 100644 --- a/Project.toml +++ b/Project.toml @@ -9,11 +9,13 @@ version = "0.5.11" MetidaBase = "075456b7-4006-432f-9324-2f8453996c49" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +Requires = "ae029012-a4dd-5104-9daa-d747884805df" [compat] MetidaBase = "0.11.2, 0.11.3, 0.12" RecipesBase = "1" +Requires = "1" julia = "1" [extras] From 7128452ed612445da55592de0ea2780711ebf3a7 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:01:29 +0300 Subject: [PATCH 13/22] docs, plot output --- Project.toml | 2 +- docs/src/api.md | 13 +++++++++++++ docs/src/details.md | 24 ++++++++++++++++++++++++ docs/src/examples.md | 18 +++++++++++++++++- src/nca.jl | 2 +- src/plots.jl | 2 +- src/types.jl | 28 ++++++++++++++++++++++++++++ 7 files changed, 85 insertions(+), 4 deletions(-) diff --git a/Project.toml b/Project.toml index eb2fdca..8824855 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MetidaNCA" uuid = "097c2839-c7bc-4c4b-a5f2-b4167c1b4e7c" authors = ["PharmCat "] -version = "0.5.11" +version = "0.5.12" diff --git a/docs/src/api.md b/docs/src/api.md index 0753958..f461331 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -52,6 +52,19 @@ MetidaNCA.ElimRange MetidaNCA.LimitRule ``` +### MetidaNCA.PKSubject + +```@docs +MetidaNCA.PKSubject +``` + +### MetidaNCA.NCAResult + +```@docs +MetidaNCA.NCAResult +``` + + ## Functions ### applylimitrule! diff --git a/docs/src/details.md b/docs/src/details.md index d44b223..cf2574e 100644 --- a/docs/src/details.md +++ b/docs/src/details.md @@ -12,6 +12,30 @@ It means that all values below `lloq` will be replaced by `btmax` before Tmax an See also: [`applylimitrule!`](@ref). +## Using DoseTime + +```julia + +dt = DoseTime(dose = 200.0, time = 0.0) + +``` + +DoseTime can be appliet to each subject or dataset and can be used with [`pkimport`](@ref). + + +```julia + +ds = pkimport(pkdata2, :Time, :Concentration, [:Subject, :Formulation]; dosetime = dt) + +``` + +DoseTime for staedy-state PK: + +```julia +dt = DoseTime(dose = 100.0, time = 0.25, tau = 9.0) +``` + +See also: [`setdosetime!`](@ref). ## Calculation steps for PK NCA diff --git a/docs/src/examples.md b/docs/src/examples.md index 77a1acd..b4fab8b 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -29,7 +29,7 @@ dsnca = nca!(ds, adm = :ev, calcm = :lint) dsnca[:, :AUClast] ``` -# Partial AUC +## Partial AUC ```@example ncaexample dsnca = nca!(ds, adm = :ev, calcm = :lint, partials = [(1, 7)]) @@ -37,6 +37,22 @@ dsnca = nca!(ds, adm = :ev, calcm = :lint, partials = [(1, 7)]) dsnca[:, :AUC_1_7] ``` +## Result modification or custom parameter function + +```@example ncaexample + +# Define modify! function for new parameter +function newparam(data) + data.result[:AUChalf] = data.result[:AUClast] / 2 +end + +dsncanp = nca!(ds, modify! = newparam) + +dsncanp[1][:AUChalf] +``` + +Function `newparam` applyed to [`NCAResult`](@ref). + ## Print output diff --git a/src/nca.jl b/src/nca.jl index 8136eaf..6db3652 100644 --- a/src/nca.jl +++ b/src/nca.jl @@ -442,7 +442,7 @@ end * `verbose` - print to `io`, 1: partial areas table, 2: 1, and results; * `warn` - show warnings; * `io` - output stream; -* `modify!` - function to modify output paramaters, call `modify!(data, result)` if difined. +* `modify!` - function to modify output paramaters, call `modify!(ncaresult)` if difined. Results: diff --git a/src/plots.jl b/src/plots.jl index 9106efa..a107418 100644 --- a/src/plots.jl +++ b/src/plots.jl @@ -450,7 +450,7 @@ function pkplot(data::DataSet{T}; if isa(pagesort, Symbol) pagesort = [pagesort] end pagelist = uniqueidlist(data, pagesort) for id in pagelist - push!(p, pageplot(data, id, typelist; ldict, kwargs...)) + push!(p, id => pageplot(data, id, typelist; ldict, kwargs...)) end else if !(:title in k) && !isnothing(filter) diff --git a/src/types.jl b/src/types.jl index 2732f33..32c02ea 100644 --- a/src/types.jl +++ b/src/types.jl @@ -105,6 +105,22 @@ struct DoseTime{D <: Number, T <: Number, TAU <: Number} 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 + +Pharmacokinetic subject. + +Fields: + +* time::Vector{T} - time values; +* obs::Vector{O} - observations; +* kelauto::Bool +* kelrange::ElimRange +* dosetime::DoseTime +* keldata::KelData +* id::Dict{Symbol, V} + +""" mutable struct PKSubject{T <: Number, O <: Union{Number, Missing}, V <: Any} <: AbstractSubject time::Vector{T} obs::Vector{O} @@ -136,7 +152,17 @@ function Base.length(obj::T) where T <: AbstractSubject length(obj.time) end +""" + NCAResult(subject::T, options, result::Dict{Symbol, U}) where T <: AbstractSubject where U + +NCA resulst. + +Fields: +* data::T +* options::Dict{Symbol} +* result::Dict{Symbol, U} +""" struct NCAResult{T, U} <: AbstractSubjectResult{T} data::T options::Dict{Symbol} @@ -167,6 +193,8 @@ Rule for PK subject. * STEP 1 (NaN step): replace all `NaN` and `missing` values with nan keyword value (if `nan` not NaN); * STEP 2 (LLOQ step): replace values below `lloq` with `btmax` value if this value befor Tmax or with atmax if this value after Tmax (if `lloq` not NaN); * STEP 3 (remove NaN): `rm` == true, then remove all `NaN` and `missing` values. + +See also: [`applylimitrule!`](@ref) """ struct LimitRule{T<:Real} lloq::T From c37bfbb696ca6b0685ba0a52947060e8a34a859f Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:18:23 +0300 Subject: [PATCH 14/22] fix plots --- src/MetidaNCA.jl | 2 +- src/plots.jl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/MetidaNCA.jl b/src/MetidaNCA.jl index c54cb43..aad1d75 100644 --- a/src/MetidaNCA.jl +++ b/src/MetidaNCA.jl @@ -33,7 +33,7 @@ metida_table function __init__() @require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" begin - import Plots:savefig + savefig = Plots.savefig end end diff --git a/src/plots.jl b/src/plots.jl index a107418..f940e92 100644 --- a/src/plots.jl +++ b/src/plots.jl @@ -456,7 +456,7 @@ function pkplot(data::DataSet{T}; if !(:title in k) && !isnothing(filter) kwargs[:title] = plotlabel(filter) end - push!(p,pageplot(data, nothing, typelist; ldict, kwargs...)) + push!(p, pageplot(data, nothing, typelist; ldict, kwargs...)) end if !isnothing(savepath) @@ -467,8 +467,8 @@ function pkplot(data::DataSet{T}; mkpath(savepath) end if isnothing(namepref) namepref = "plot" end - for i = 1: length(p) - savefig(p[i], joinpath(savepath, namepref*"_$(i).png")) + for i = 1:length(p) + savefig(p[i][2], joinpath(savepath, namepref*"_$(i).png")) end else @warn "savefig not defined, install Plots.jl for plot writing... plots NOT saved..." From c5951ad4560fb4d83dc744c96e208677fcafc4b7 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:50:34 +0300 Subject: [PATCH 15/22] export, fix docs --- docs/src/examples.md | 4 ++-- src/MetidaNCA.jl | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/src/examples.md b/docs/src/examples.md index b4fab8b..c147bdc 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -76,11 +76,11 @@ png(p, "plot2.png") p = pkplot(ds; elim = true, ls = true) -png(p[1], "plot3.png") +png(p[1][2], "plot3.png") p = pkplot(ds; typesort = :Subject, pagesort = :Formulation) -png(p[1], "plot4.png") +png(p[1][2], "plot4.png") ``` #### Plot 1 diff --git a/src/MetidaNCA.jl b/src/MetidaNCA.jl index aad1d75..f46db2a 100644 --- a/src/MetidaNCA.jl +++ b/src/MetidaNCA.jl @@ -28,8 +28,9 @@ export pkimport, upkimport, pdimport, nca!, nca, DoseTime, ElimRange, LimitRule, auc_sparse, setdosetime!, setkelauto!, setkelrange!, applylimitrule!, setbl!, setth!, pkplot, -getkeldata, getkelauto, getkelrange, getdosetime, getbl, getth, subset -metida_table +getkeldata, getkelauto, getkelrange, getdosetime, getbl, getth, subset, +metida_table, +PKSubject, UPKSubject, PDSubject, NCAResult function __init__() @require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" begin From 47a06b14b09010bae435dfceec3891bc4b2dd909 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Wed, 31 Jul 2024 20:20:09 +0300 Subject: [PATCH 16/22] fix plots --- docs/src/examples.md | 4 +++- src/plots.jl | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/src/examples.md b/docs/src/examples.md index c147bdc..cbc5c73 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -76,7 +76,9 @@ png(p, "plot2.png") p = pkplot(ds; elim = true, ls = true) -png(p[1][2], "plot3.png") +png(p[1], "plot3.png") + +# If pagesort used - return pairs with `Page ID` => `Plot` p = pkplot(ds; typesort = :Subject, pagesort = :Formulation) diff --git a/src/plots.jl b/src/plots.jl index f940e92..a262582 100644 --- a/src/plots.jl +++ b/src/plots.jl @@ -391,6 +391,8 @@ PK plot for subject set. * `namepref` - name prefix for saving files. Use `pagesort = MetidaNCA.NoPageSort()` to prevent page plotting. + +If pagesort used - return vector of pairs: `Page ID` => `Plot` """ function pkplot(data::DataSet{T}; typesort::Union{Nothing, Symbol, AbstractVector{Symbol}} = nothing, @@ -468,7 +470,11 @@ function pkplot(data::DataSet{T}; end if isnothing(namepref) namepref = "plot" end for i = 1:length(p) - savefig(p[i][2], joinpath(savepath, namepref*"_$(i).png")) + if isa(p[i], Pair) + savefig(p[i][2], joinpath(savepath, namepref*"_$(i).png")) + else + savefig(p[i], joinpath(savepath, namepref*"_$(i).png")) + end end else @warn "savefig not defined, install Plots.jl for plot writing... plots NOT saved..." From fe6379b54186285f32da62694f87bc626c3be938 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Fri, 27 Sep 2024 16:23:43 +0300 Subject: [PATCH 17/22] breaking changes in plots output --- Project.toml | 2 +- change.log | 3 +++ docs/src/examples.md | 4 ++-- src/plots.jl | 54 ++++++++++++++++++++++++++++++++----------- src/types.jl | 2 +- test/tests.jl | 55 ++++++++++++++++++++++++++++++++++++-------- 6 files changed, 93 insertions(+), 27 deletions(-) diff --git a/Project.toml b/Project.toml index 8824855..7de1e63 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MetidaNCA" uuid = "097c2839-c7bc-4c4b-a5f2-b4167c1b4e7c" authors = ["PharmCat "] -version = "0.5.12" +version = "0.5.13" diff --git a/change.log b/change.log index 3e8ff28..33dbf86 100644 --- a/change.log +++ b/change.log @@ -1,3 +1,6 @@ +0.5.13 +- breaking changes in plotting output + 0.5.8 - plots minor changing diff --git a/docs/src/examples.md b/docs/src/examples.md index cbc5c73..d301755 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -66,11 +66,11 @@ dsnca = nca!(ds[1], adm = :ev, calcm = :lint, verbose = 2); ```@example ncaexample using Plots -p = pkplot(ds; typesort = :Subject, pagesort = nothing, filter = Dict(:Formulation => "R")) +p = pkplot(ds; typesort = :Subject, pagesort = NoPageSort(), filter = Dict(:Formulation => "R")) png(p, "plot1.png") -p = pkplot(ds; typesort = :Formulation, pagesort = nothing, legend = true) +p = pkplot(ds; typesort = :Formulation, pagesort = NoPageSort(), legend = true) png(p, "plot2.png") diff --git a/src/plots.jl b/src/plots.jl index a262582..3208df5 100644 --- a/src/plots.jl +++ b/src/plots.jl @@ -44,6 +44,7 @@ end @userplot PKPlot @userplot PKElimpPlot +@userplot PKElimpDrop @userplot PdHLine function luceil(x) @@ -108,6 +109,16 @@ end (x, y) end +@recipe function f(subj::PKElimpDrop) + x, y = subj.args + seriestype --> :scatter + legend --> false + markersize --> 4 + markercolor --> :red + markershape --> :xcross + (x, y) +end + @recipe function f(subj::PdHLine) x, y = subj.args seriestype --> :straightline @@ -159,9 +170,6 @@ function pkplot(subj::AbstractSubject; ls = false, elim = false, xticksn = :auto else kwargs[:linestyle], kwargs[:linecolor], kwargs[:markershape], kwargs[:markercolor] = kwargs[:plotstyle] end - if !(:title in k) - kwargs[:title] = plotlabel(subj.id) - end if !(:drawbl in k) kwargs[:drawbl] = false end @@ -228,7 +236,7 @@ function pkplot(subj::AbstractSubject; ls = false, elim = false, xticksn = :auto p = pkplot(time, obs; lcd = yticksn, tcd = xticksn, kwargs...) if elim if length(subj.keldata) > 0 - rsq, rsqn = findmax(subj.keldata.ar) + arsq, rsqn = findmax(subj.keldata.ar) lz = subj.keldata.a[rsqn] lzint = subj.keldata.b[rsqn] ts = subj.keldata.s[rsqn] @@ -240,7 +248,10 @@ function pkplot(subj::AbstractSubject; ls = false, elim = false, xticksn = :auto x = collect(ts:(te-ts)/100:te) y = exp.(lzint .+ lz .* x) end - pkelimpplot!(p, x, y) + pkelimpplot!(p, x, y; title = kwargs[:title]*"\n($(round(lzint, sigdigits = 4)) + $(round(lz, sigdigits = 4)) * Time; aR² = $(round(arsq, sigdigits = 4))) ") + if length(subj.kelrange.kelexcl) > 0 + pkelimpdrop!(p, time[subj.kelrange.kelexcl], obs[subj.kelrange.kelexcl]) + end end end if isa(subj, PDSubject) @@ -378,6 +389,7 @@ end ldict = nothing, savepath::Union{Nothing, AbstractString} = nothing, namepref::Union{Nothing, AbstractString} = nothing, + onlyplots = false, kwargs...) where T <: AbstractSubject PK plot for subject set. @@ -389,10 +401,10 @@ PK plot for subject set. * `ldict` - Dict with labels for replace; * `savepath` - path for plot saving; * `namepref` - name prefix for saving files. +* `onlyplots` - if `true` return only vetor of plots; +Use `pagesort = MetidaNCA.NoPageSort()` to prevent page plotting (return single plot). -Use `pagesort = MetidaNCA.NoPageSort()` to prevent page plotting. - -If pagesort used - return vector of pairs: `Page ID` => `Plot` +Return vector of pairs: `Page ID` => `Plot`. """ function pkplot(data::DataSet{T}; typesort::Union{Nothing, Symbol, AbstractVector{Symbol}} = nothing, @@ -402,7 +414,7 @@ function pkplot(data::DataSet{T}; ldict = nothing, savepath::Union{Nothing, AbstractString} = nothing, namepref::Union{Nothing, AbstractString} = nothing, - + onlyplots = false, kwargs...) where T <: AbstractSubject kwargs = Dict{Symbol, Any}(kwargs) @@ -446,7 +458,21 @@ function pkplot(data::DataSet{T}; if !(:legend in k) kwargs[:legend] = false end - push!(p, pkplot(subj; kwargs...)) + push!(p, subj.id => pkplot(subj; kwargs...)) + end + elseif !isnothing(typesort) && isnothing(pagesort) + printtitle = false + if !(:title in k) + printtitle = true + end + for subj in data + if printtitle + kwargs[:title] = plotlabel(subj.id, ldict) + end + if !(:legend in k) + kwargs[:legend] = false + end + push!(p, subj.id => pageplot(data, subj.id, typelist; ldict, kwargs...)) end elseif !isnothing(pagesort) && !isa(pagesort, NoPageSort) if isa(pagesort, Symbol) pagesort = [pagesort] end @@ -480,11 +506,13 @@ function pkplot(data::DataSet{T}; @warn "savefig not defined, install Plots.jl for plot writing... plots NOT saved..." end end - if length(p) > 1 - return p - else + if isa(pagesort, NoPageSort) return p[1] end + + if onlyplots return getindex.(p, 2) end + return p + end diff --git a/src/types.jl b/src/types.jl index 32c02ea..ae9d11b 100644 --- a/src/types.jl +++ b/src/types.jl @@ -52,7 +52,7 @@ Elimination settings for PK subject. * `kelstart` - start point; * `kelend` - end point; -* `kelexcl` - excluded points. +* `kelexcl` - excluded points (not time value). """ mutable struct ElimRange{Symbol} kelstart::Int diff --git a/test/tests.jl b/test/tests.jl index de92056..21726d4 100644 --- a/test/tests.jl +++ b/test/tests.jl @@ -72,18 +72,53 @@ include("refdicts.jl") @test dsnca[:, :AUClast] == dsncafromds[:, :AUClast] # Plotting - @test_nowarn MetidaNCA.pkplot(ds; typesort = :Subject, pagesort = nothing, sort = Dict(:Formulation => "R")) - @test_nowarn MetidaNCA.pkplot(ds; typesort = :Formulation, pagesort = nothing, legend = true) - @test_nowarn pl = MetidaNCA.pkplot(ds; elim = true, ls = true) - @test_nowarn pl = MetidaNCA.pkplot(ds; typesort = :Subject, pagesort = :Formulation, elim = true, ls = true, title = "Plots") - @test_nowarn pl = MetidaNCA.pkplot(ds; typesort = :Formulation, pagesort = :Subject, xticksn = 8, yticksn = 10) - @test_nowarn pl = MetidaNCA.pkplot(ds; pagesort = MetidaNCA.NoPageSort(), xticksn = 8, yticksn = 10) - @test_nowarn pl = MetidaNCA.pkplot(ds; pagesort = [:Subject, :Formulation], legend = false) - @test_nowarn pl = MetidaNCA.pkplot(ds[1]; ylims = (0, 10), yscale = :log10, legend = false) + # 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 + pl = @test_nowarn MetidaNCA.pkplot(ds; typesort = :Formulation, pagesort = MetidaNCA.NoPageSort(), legend = true) + @test isa(pl, Plots.Plot) == true + + pl = @test_nowarn MetidaNCA.pkplot(ds; typesort = :Subject, sort = Dict(:Formulation => "R"), legend = true) + @test length(pl) == 10 + pl = @test_nowarn MetidaNCA.pkplot(ds; typesort = :Formulation, legend = true) + @test length(pl) == 10 + + + # If no typesort and no pagesort returns array of pairs id => plot + pl = @test_nowarn MetidaNCA.pkplot(ds; elim = true, ls = true) + @test length(pl) == 10 + + pl = @test_nowarn MetidaNCA.pkplot(ds; typesort = :Subject, pagesort = :Formulation, elim = true, ls = true, title = "Plots") + @test length(pl) == 2 + + pl = @test_nowarn MetidaNCA.pkplot(ds; typesort = :Formulation, pagesort = :Subject, xticksn = 8, yticksn = 10) + @test length(pl) == 10 + # If MetidaNCA.NoPageSort() return one plot + pl = @test_nowarn MetidaNCA.pkplot(ds; pagesort = MetidaNCA.NoPageSort(), xticksn = 8, yticksn = 10) + @test isa(pl, Plots.Plot) == true + + pl = @test_nowarn MetidaNCA.pkplot(ds; pagesort = [:Subject, :Formulation], legend = false) + @test length(pl) == 10 + + pl = @test_nowarn MetidaNCA.pkplot(ds; typesort = [:Subject, :Formulation], legend = true) + @test length(pl) == 10 + + pl = @test_nowarn MetidaNCA.pkplot(ds; typesort = [:Subject, :Formulation], pagesort = MetidaNCA.NoPageSort(), legend = true) + @test isa(pl, Plots.Plot) == true + + # Return plot for PKSubject + @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[2]) - pl = MetidaNCA.pkplot!(ds[3]; yscale = :log10) + pl = MetidaNCA.pkplot(ds[3]) + pl = MetidaNCA.pkplot!(ds[2]; yscale = :log10) + + kr = MetidaNCA.ElimRange(kelstart = 4, kelend = 12, kelexcl = Int[5,6]) + MetidaNCA.setkelrange!(ds, kr, [1,2,3]) + dsnca = MetidaNCA.nca!(ds) + pl = @test_nowarn MetidaNCA.pkplot(ds[1]; elim = true) + MetidaNCA.setkelauto!(ds, true) + #Plot from NCA result DataSet @test_nowarn MetidaNCA.pkplot(dsncafromds[1]; ylims = (0, 10), yscale = :log10, legend = false) @test_nowarn MetidaNCA.pkplot(dsncafromds; typesort = :Subject, pagesort = :Formulation, elim = true, ls = true, title = "Plots") From 3ac3bd3f50eed6aca281f44abc03416554cf5630 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Fri, 27 Sep 2024 18:34:45 +0300 Subject: [PATCH 18/22] fix docs --- docs/src/examples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/examples.md b/docs/src/examples.md index d301755..c76472b 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -76,7 +76,7 @@ png(p, "plot2.png") p = pkplot(ds; elim = true, ls = true) -png(p[1], "plot3.png") +png(p[1][2], "plot3.png") # If pagesort used - return pairs with `Page ID` => `Plot` From ea99edc1093b47d4d4c2acb48763882b19437b77 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Wed, 30 Oct 2024 04:35:24 +0300 Subject: [PATCH 19/22] pd tau --- Project.toml | 2 +- change.log | 3 ++ src/nca.jl | 72 ++++++++++++++++++++++++++++++++++++++++++++++ src/setdosetime.jl | 20 ++++++------- src/types.jl | 19 ++++++------ test/pdtest.jl | 51 ++++++++++++++++++++++++++++++++ 6 files changed, 147 insertions(+), 20 deletions(-) diff --git a/Project.toml b/Project.toml index 24b19a7..25ef3bc 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ 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/src/nca.jl b/src/nca.jl index 6db3652..e09440a 100644 --- a/src/nca.jl +++ b/src/nca.jl @@ -1138,6 +1138,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/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/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..912a87c 100644 --- a/test/pdtest.jl +++ b/test/pdtest.jl @@ -76,3 +76,54 @@ # 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 + +end From 51de38fcd61aa5cda3cdaf4238e4c6085159538c Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:47:08 +0300 Subject: [PATCH 20/22] plot dose time --- docs/src/examples.md | 16 ++++++++++++++++ src/MetidaNCA.jl | 2 ++ src/nca.jl | 4 ++-- src/plots.jl | 14 ++++++++++++++ test/tests.jl | 6 ++++++ 5 files changed, 40 insertions(+), 2 deletions(-) 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..622e6bf 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, diff --git a/src/nca.jl b/src/nca.jl index e09440a..8f766ae 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 diff --git a/src/plots.jl b/src/plots.jl index 125b609..74362f6 100644 --- a/src/plots.jl +++ b/src/plots.jl @@ -157,6 +157,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 +171,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 @@ -262,6 +266,9 @@ function pkplot(subj::AbstractSubject; ls = false, elim = false, xticksn = :auto pdhline!(p, [minimum(subj.time), maximum(subj.time)], getbl(subj), lc = :red, 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 +283,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 +335,10 @@ function pkplot!(subj; ls = false, elim = false, xticksn = :auto, yticksn = :aut end p = pkplot!(time, obs; lcd = yticksn, tcd = xticksn, kwargs...) + + 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/test/tests.jl b/test/tests.jl index 21726d4..2bcc94d 100644 --- a/test/tests.jl +++ b/test/tests.jl @@ -184,6 +184,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) From ab61866972b5770d3c84e8f6291a1bff7cca6627 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:10:38 +0300 Subject: [PATCH 21/22] tests --- src/import.jl | 8 ++++++-- src/plots.jl | 17 +++++++++++++---- test/pdtest.jl | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 6 deletions(-) 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/plots.jl b/src/plots.jl index 74362f6..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 = "" @@ -260,10 +261,10 @@ 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) @@ -336,6 +337,14 @@ function pkplot!(subj; ls = false, elim = false, xticksn = :auto, yticksn = :aut 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 diff --git a/test/pdtest.jl b/test/pdtest.jl index 912a87c..afb01f4 100644 --- a/test/pdtest.jl +++ b/test/pdtest.jl @@ -126,4 +126,19 @@ end @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 From 1b98277a7f09226cc91054b9de77d5e0a3264955 Mon Sep 17 00:00:00 2001 From: PharmCat <13901158+PharmCat@users.noreply.github.com> Date: Wed, 13 Nov 2024 02:47:32 +0300 Subject: [PATCH 22/22] minor changes --- src/MetidaNCA.jl | 1 + src/nca.jl | 7 +++++++ src/show.jl | 6 +++--- test/pdtest.jl | 3 +++ test/tests.jl | 17 +++++++++++++++++ 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/MetidaNCA.jl b/src/MetidaNCA.jl index 622e6bf..a489a28 100644 --- a/src/MetidaNCA.jl +++ b/src/MetidaNCA.jl @@ -37,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/nca.jl b/src/nca.jl index 8f766ae..bceabb1 100644 --- a/src/nca.jl +++ b/src/nca.jl @@ -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) 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/test/pdtest.jl b/test/pdtest.jl index afb01f4..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) diff --git a/test/tests.jl b/test/tests.jl index 2bcc94d..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)