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 #26

Merged
merged 28 commits into from
Nov 13, 2024
Merged

Dev #26

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 <[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)
3 changes: 3 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 Expand Up @@ -35,6 +37,7 @@ PKSubject, UPKSubject, PDSubject, NCAResult
function __init__()
@require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" begin
savefig = Plots.savefig
current = Plots.current
end
end

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
83 changes: 81 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 @@ -1100,7 +1100,14 @@
################################################################################
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)
Expand Down Expand Up @@ -1138,6 +1145,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 1196 in src/nca.jl

View check run for this annotation

Codecov / codecov/patch

src/nca.jl#L1196

Added line #L1196 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")
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])

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
6 changes: 3 additions & 3 deletions src/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@
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

Check warning on line 62 in src/show.jl

View check run for this annotation

Codecov / codecov/patch

src/show.jl#L62

Added line #L62 was not covered by tests
"Pharmacokinetics subject"
end
function subject_type_str(subj::Type{<:UPKSubject})
function subject_type_str(subj::Type{UPKS}) where UPKS <: UPKSubject

Check warning on line 65 in src/show.jl

View check run for this annotation

Codecov / codecov/patch

src/show.jl#L65

Added line #L65 was not covered by tests
"Pharmacokinetics subject (urine)"
end
function subject_type_str(subj::Type{<:PDSubject})
function subject_type_str(subj::Type{PDS}) where PDS <: PDSubject

Check warning on line 68 in src/show.jl

View check run for this annotation

Codecov / codecov/patch

src/show.jl#L68

Added line #L68 was not covered by tests
"Pharmacodynamics subject"
end
function Base.show(io::IO, obj::DataSet{ST}) where ST <: AbstractSubject
Expand Down
Loading
Loading