Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #25

Merged
merged 27 commits into from
Nov 11, 2024
Merged

Dev #25

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 <v.s.arnautov@yandex.ru>"]
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 @@
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 @@
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)

Check warning on line 1189 in src/nca.jl

View check run for this annotation

Codecov / codecov/patch

src/nca.jl#L1189

Added line #L1189 was not covered by tests
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 @@
@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 @@
(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 @@
* `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 @@
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 @@
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 @@
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 @@
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")

Check warning on line 342 in src/plots.jl

View check run for this annotation

Codecov / codecov/patch

src/plots.jl#L341-L342

Added lines #L341 - L342 were not covered by tests
end
if kwargs[:drawbl] == true
plot!(p, [minimum(subj.time), maximum(subj.time)], [getbl(subj), getbl(subj)], lc = kwargs[:linecolor], ls = :dash, label = "BL")

Check warning on line 345 in src/plots.jl

View check run for this annotation

Codecov / codecov/patch

src/plots.jl#L344-L345

Added lines #L344 - L345 were not covered by tests
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])

Check warning on line 349 in src/plots.jl

View check run for this annotation

Codecov / codecov/patch

src/plots.jl#L349

Added line #L349 was not covered by tests
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
Loading