Skip to content

Commit db10559

Browse files
authored
Merge pull request #128 from drbergman/development
v0.0.27
2 parents aa9a920 + 1478a18 commit db10559

26 files changed

+428
-139
lines changed

.github/workflows/CI.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ jobs:
113113
PCVCT_PUBLIC_REPO_AUTH: ${{ secrets.PUBLIC_REPO_AUTH }}
114114

115115
- uses: julia-actions/julia-processcoverage@v1
116+
with:
117+
directories: src,deps
116118

117119
- uses: codecov/codecov-action@v5
118120
with:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ test.jl
44
*.db
55
.vscode
66
studio_debug.log
7+
/temp
78

89
# from PkgTemplate.jl
910
*.jl.*.cov

Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "pcvct"
22
uuid = "3c374bc7-7384-4f83-8ca0-87b8c727e6ff"
33
authors = ["Daniel Bergman <[email protected]> and contributors"]
4-
version = "0.0.26"
4+
version = "0.0.27"
55

66
[deps]
77
AutoHashEquals = "15f4f7f2-30c1-5605-9d31-71845cf9641f"
@@ -20,6 +20,7 @@ LazyGrids = "7031d0ef-c40d-4431-b2f8-61a8d2f650db"
2020
LightXML = "9c8b4983-aa76-5018-a973-4c85ecc9e179"
2121
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
2222
MAT = "23992714-dd62-5051-b70f-ba57cb901cac"
23+
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
2324
MetaGraphsNext = "fa8bd995-216d-47f1-8a91-f3b68fbeb377"
2425
PairCorrelationFunction = "1da3c5ec-5de6-497d-83f1-8bbf7fdc92ec"
2526
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
@@ -52,6 +53,7 @@ LazyGrids = "1"
5253
LightXML = "0.9"
5354
LinearAlgebra = "1.10 - 1"
5455
MAT = "0.10"
56+
MacroTools = "0.5.16"
5557
MetaGraphsNext = "0.7.2"
5658
PairCorrelationFunction = "0.0.11"
5759
Parameters = "0.12"

README.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,49 @@ Make sure you are familiar with the [Best practices](https://drbergman.github.io
1313
See [Getting started](https://drbergman.github.io/pcvct/stable/man/getting_started/) for more details.
1414

1515
1. [Install Julia](https://julialang.org/install).
16-
2. Add the PCVCTRegistry:
16+
2. Ensure the general registry is added:
17+
```julia-repl
18+
pkg> registry add General
19+
```
20+
3. Add the PCVCTRegistry:
1721
```julia-repl
1822
pkg> registry add https://github.com/drbergman/PCVCTRegistry
1923
```
20-
3. Install pcvct:
24+
4. Install pcvct:
2125
```julia-repl
2226
pkg> add pcvct
2327
```
24-
4. Create a new project:
28+
5. Create a new project:
2529
```julia-repl
2630
julia> using pcvct
2731
julia> createProject()
2832
```
29-
5. Import a project:
33+
6. Import a project:
3034
```julia-repl
3135
julia> initializeModelManager()
3236
julia> importProject("path/to/project_folder") # replace with the path to your project folder
3337
```
34-
6. Check the output of Step 5 and record your input folders:
38+
7. Check the output of Step 5 and record your input folders:
3539
```julia-repl
3640
julia> config_folder = "my_project" # replace these with the name from the output of Step 5
3741
julia> custom_code_folder = "my_project"
3842
julia> rules_folder = "my_project"
3943
julia> inputs = InputFolders(config_folder, custom_code_folder; rulesets_collection = rules_folder) # also add ic_cell and ic_substrate if used
4044
```
41-
7. Run the model:
45+
8. Run the model:
4246
```julia-repl
4347
julia> out = run(inputs; n_replicates = 1)
4448
```
45-
8. Check the output:
49+
9. Check the output:
4650
```julia-repl
4751
julia> using Plots # make sure to install Plots first
4852
julia> plot(out)
4953
julia> plotbycelltype(out)
5054
```
51-
9. Vary parameters:
55+
10. Vary parameters:
5256
```julia-repl
5357
julia> xml_path = configPath("some_cell_type", "apoptosis", "death_rate") # replace with a cell type in your model
5458
julia> new_apoptosis_rates = [1e-5, 1e-4, 1e-3]
5559
julia> dv = DiscreteVariation(xml_path, new_apoptosis_rates)
5660
julia> out = run(inputs, dv; n_replicates = 3) # 3 replicates per apoptosis rate => 9 simulations total
57-
```
61+
```

codecov.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
ignore:
2-
- "src/public.jl"
3-
- "src/up.jl"
2+
- "src/up.jl"

deps/DeprecateKeywords.jl

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
module DeprecateKeywords
2+
3+
using MacroTools
4+
5+
"""
6+
@depkws [force=false] def
7+
8+
Macro to deprecate keyword arguments. Use by wrapping a function signature,
9+
while using `@deprecate(old_kw, new_kw)` within the function signature to deprecate.
10+
11+
# Examples
12+
13+
```julia
14+
@depkws function f(; a=2, @deprecate(b, a))
15+
a
16+
end
17+
```
18+
19+
```julia
20+
# force the deprecation warning to be emitted
21+
@depkws force=true function f(; a=2, @deprecate(b, a))
22+
a
23+
end
24+
```
25+
"""
26+
macro depkws(args...)
27+
options = parse_options(args[1:end-1])
28+
return esc(_depkws(args[end], options))
29+
end
30+
31+
function parse_options(args)
32+
options = default_options()
33+
for arg in args
34+
if isa(arg, Expr) && arg.head == :(=)
35+
@assert arg.args[1] keys(options) "Unknown option: $(arg.args[1])"
36+
options[arg.args[1]] = arg.args[2]
37+
else
38+
error("Invalid option: $arg")
39+
end
40+
end
41+
return options
42+
end
43+
44+
function default_options()
45+
return Dict{Symbol, Any}(:force => false)
46+
end
47+
48+
abstract type DeprecatedDefault end
49+
50+
function _depkws(def, options)
51+
sdef = splitdef(def)
52+
func_symbol = Expr(:quote, sdef[:name]) # Double quote for expansion
53+
54+
new_symbols = Symbol[]
55+
deprecated_symbols = Symbol[]
56+
kwargs_to_remove = Int[]
57+
for (i, param) in enumerate(sdef[:kwargs])
58+
isa(param, Symbol) && continue
59+
# Look for @deprecated macro:
60+
if param.head == :macrocall && param.args[1] == Symbol("@deprecate")
61+
# e.g., params.args[2] is the line number
62+
deprecated_symbol = param.args[end-1]
63+
new_symbol = param.args[end]
64+
if !isa(new_symbol, Symbol)
65+
# Remove line numbers nodes:
66+
clean_param = deepcopy(param)
67+
filter!(x -> !isa(x, LineNumberNode), clean_param.args)
68+
error(
69+
"The expression\n $(clean_param)\ndoes not appear to be two symbols in a `@deprecate`. This can happen if you use `@deprecate` in a function " *
70+
"definition without " *
71+
"parentheses, such as `f(; @deprecate a b, c=2)`. Instead, you should write `f(; (@deprecate a b), c=2)` or alternatively " *
72+
"`f(; @deprecate(a, b), c=2)`.)"
73+
)
74+
end
75+
push!(deprecated_symbols, deprecated_symbol)
76+
push!(new_symbols, new_symbol)
77+
push!(kwargs_to_remove, i)
78+
end
79+
end
80+
deleteat!(sdef[:kwargs], kwargs_to_remove)
81+
82+
# Add deprecated kws:
83+
for deprecated_symbol in deprecated_symbols
84+
pushfirst!(sdef[:kwargs], Expr(:kw, deprecated_symbol, DeprecatedDefault))
85+
end
86+
87+
symbol_mapping = Dict(new_symbols .=> deprecated_symbols)
88+
89+
# Update new symbols to use deprecated kws if passed:
90+
for (i, kw) in enumerate(sdef[:kwargs])
91+
no_default_type_assertion = !isa(kw, Symbol) && kw.head != :kw
92+
no_default_naked = isa(kw, Symbol)
93+
no_default = no_default_naked || no_default_type_assertion
94+
95+
(kw, type_assertion) = if no_default_type_assertion
96+
@assert kw.head == :(::)
97+
# Remove type assertion from keyword; we will
98+
# assert it later.
99+
kw.args
100+
else
101+
(kw, Nothing)
102+
end
103+
104+
new_kw, default = if no_default
105+
(kw, DeprecatedDefault)
106+
else
107+
(kw.args[1], kw.args[2])
108+
end
109+
110+
111+
_get_symbol(new_kw) in deprecated_symbols && continue
112+
!(_get_symbol(new_kw) in new_symbols) && continue
113+
114+
deprecated_symbol = symbol_mapping[_get_symbol(new_kw)]
115+
depwarn_string = "Keyword argument `$(deprecated_symbol)` is deprecated. Use `$(_get_symbol(new_kw))` instead."
116+
new_kwcall = quote
117+
if $deprecated_symbol !== $(DeprecatedDefault)
118+
Base.depwarn($depwarn_string, $func_symbol; force=$(options[:force]))
119+
$deprecated_symbol
120+
else
121+
$default
122+
end
123+
end
124+
sdef[:kwargs][i] = Expr(:kw, new_kw, new_kwcall)
125+
126+
if no_default_type_assertion
127+
pushfirst!(
128+
sdef[:body].args,
129+
Expr(:(::), _get_symbol(new_kw), type_assertion)
130+
)
131+
end
132+
133+
if no_default
134+
# Propagate UndefKeywordError
135+
pushfirst!(
136+
sdef[:body].args,
137+
Expr(:if,
138+
Expr(:call, :(===), _get_symbol(new_kw), DeprecatedDefault),
139+
Expr(:call, :throw,
140+
Expr(:call, :UndefKeywordError, QuoteNode(_get_symbol(new_kw)))
141+
)
142+
)
143+
)
144+
end
145+
end
146+
147+
return combinedef(sdef)
148+
end
149+
150+
# This is used to go from a::Int to a
151+
_get_symbol(e::Expr) = first(map(_get_symbol, e.args))
152+
_get_symbol(e::Symbol) = e
153+
154+
end

docs/src/lib/deprecate_keywords.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
```@meta
2+
CollapsedDocStrings = true
3+
```
4+
5+
# Deprecate Keywords
6+
7+
A light edit of the [DeprecateKeywords.jl](https://github.com/MilesCranmer/DeprecateKeywords.jl) package to enable the deprecation warnings for users.
8+
9+
## Public API
10+
```@autodocs
11+
Modules = [pcvct.DeprecateKeywords]
12+
Pages = ["DeprecateKeywords.jl"]
13+
Private = false
14+
```
15+
16+
## Private API
17+
```@autodocs
18+
Modules = [pcvct.DeprecateKeywords]
19+
Pages = ["DeprecateKeywords.jl"]
20+
Public = false
21+
```

docs/src/man/covariations.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ using pcvct
4444
timing_1_path = configPath("user_parameters", "event_1_time")
4545
timing_2_path = configPath("user_parameters", "event_2_time")
4646
dv1 = UniformDistributedVariation(timing_1_path, 100.0, 200.0)
47-
flip = true
48-
dv2 = UniformDistributedVariation(timing_2_path, 100.0, 200.0, flip)
47+
dv2 = UniformDistributedVariation(timing_2_path, 100.0, 200.0; flip=true)
4948
covariation = CoVariation(dv1, dv2)
5049
cdf = 0.1
5150
pcvct.variationValues.(covariation.variations, cdf) # pcvct internal for getting values for an ElementaryVariation

src/analysis/graphs.jl

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using Graphs, MetaGraphsNext
22

3+
include(joinpath(@__DIR__, "..", "..", "deps", "DeprecateKeywords.jl"))
4+
import .DeprecateKeywords: @depkws
5+
36
export connectedComponents
47

58
"""
@@ -34,25 +37,15 @@ For each key, the value is a list of connected components in the graph.
3437
Each component is represented as a vector of vertex labels.
3538
As of this writing, the vertex labels are the simple `AgentID` class that wraps the cell ID.
3639
"""
37-
function connectedComponents(snapshot::PhysiCellSnapshot, graph::Symbol=:neighbors; include_cell_type_names=:all_in_one, exclude_cell_type_names=String[], include_dead::Bool=false,
38-
include_cell_types=nothing, exclude_cell_types=nothing)
40+
@depkws force=true function connectedComponents(snapshot::PhysiCellSnapshot, graph::Symbol=:neighbors; include_cell_type_names=:all_in_one, exclude_cell_type_names=String[], include_dead::Bool=false,
41+
@deprecate(include_cell_types, include_cell_type_names), @deprecate(exclude_cell_types, exclude_cell_type_names))
3942
is_all_in_one = include_cell_type_names == :all_in_one
4043
cell_type_to_name_dict = cellTypeToNameDict(snapshot)
4144
cell_type_names = values(cell_type_to_name_dict) |> collect
4245

43-
if !isnothing(include_cell_types)
44-
@assert include_cell_type_names == :all_in_one "Do not use both `include_cell_types` and `include_cell_type_names` as keyword arguments. Use `include_cell_type_names` instead."
45-
Base.depwarn("`include_cell_types` is deprecated as a keyword. Use `include_cell_type_names` instead.", :connectedComponents, force=true)
46-
include_cell_type_names = include_cell_types
47-
end
4846
include_cell_type_names = processIncludeCellTypes(include_cell_type_names, cell_type_names)
49-
50-
if !isnothing(exclude_cell_types)
51-
@assert exclude_cell_type_names == String[] "Do not use both `exclude_cell_types` and `exclude_cell_type_names` as keyword arguments. Use `exclude_cell_type_names` instead."
52-
Base.depwarn("`exclude_cell_types` is deprecated as a keyword. Use `exclude_cell_type_names` instead.", :connectedComponents, force=true)
53-
exclude_cell_type_names = exclude_cell_types
54-
end
5547
exclude_cell_type_names = processExcludeCellTypes(exclude_cell_type_names)
48+
5649
loadGraph!(snapshot, graph)
5750
if is_all_in_one
5851
G = getfield(snapshot, graph) |> deepcopy

src/analysis/substrate.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ asts = pcvct.AverageSubstrateTimeSeries(1) # Load average substrate time series
7777
asts.time # Get the time points
7878
asts["time"] # alternative way to get the time points
7979
asts["oxygen"] # Get the oxygen concentration over time
80+
```
8081
"""
8182
struct AverageSubstrateTimeSeries
8283
simulation_id::Int

0 commit comments

Comments
 (0)