Skip to content

Commit

Permalink
Dev (#25)
Browse files Browse the repository at this point in the history
* plot update (ldict)

* plotting

* docs pkg

* docs, minor fix

* docs

* show ds

* show res ds

* save plots

* version bump

* update

* update

* update

* docs, plot output

* fix plots

* export, fix docs

* fix plots

* breaking changes in plots output

* fix docs

* pd tau

* plot dose time

* tests
  • Loading branch information
PharmCat authored Nov 11, 2024
1 parent 6bdbca8 commit e380d47
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 28 deletions.
3 changes: 2 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name = "MetidaNCA"
uuid = "097c2839-c7bc-4c4b-a5f2-b4167c1b4e7c"
authors = ["PharmCat <[email protected]>"]
version = "0.5.13"
version = "0.5.14"



[deps]
Expand Down
3 changes: 3 additions & 0 deletions change.log
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
0.5.14
- pd tau

0.5.13
- breaking changes in plotting output

Expand Down
16 changes: 16 additions & 0 deletions docs/src/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 2 additions & 0 deletions src/MetidaNCA.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 6 additions & 2 deletions src/import.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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}}()
Expand All @@ -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))
Expand Down Expand Up @@ -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))
Expand Down
76 changes: 74 additions & 2 deletions src/nca.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand Down
31 changes: 27 additions & 4 deletions src/plots.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ end
@userplot PKPlot
@userplot PKElimpPlot
@userplot PKElimpDrop
@userplot PdHLine
#@userplot PdHLine

function luceil(x)
fl = Int(floor(log10(x)))
Expand Down Expand Up @@ -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 = ""
Expand Down Expand Up @@ -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...)
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down
20 changes: 10 additions & 10 deletions src/setdosetime.jl
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -24,31 +24,31 @@ 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
data
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
data
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
Expand All @@ -60,7 +60,7 @@ end
Return dosetime.
"""
function getdosetime(data::PKSubject)
function getdosetime(data::AbstractSubject)
data.dosetime
end

Expand Down
19 changes: 10 additions & 9 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
Expand Down Expand Up @@ -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

Expand Down
Loading

0 comments on commit e380d47

Please sign in to comment.