Skip to content

Commit 738ba51

Browse files
authored
Merge pull request #103 from drbergman/development
0.0.17
2 parents 8152ae7 + a2496ea commit 738ba51

File tree

8 files changed

+69
-93
lines changed

8 files changed

+69
-93
lines changed

Project.toml

Lines changed: 1 addition & 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.16"
4+
version = "0.0.17"
55

66
[deps]
77
AutoHashEquals = "15f4f7f2-30c1-5605-9d31-71845cf9641f"

docs/src/misc/renaming.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ Here are the options brainstormed thus far:
1212
- PhysiBatch.jl
1313
- PhysiCellDB.jl
1414
- PhysiDB.jl (the clear name for make the database portion a separate package)
15-
- PhysiCell.jl (kinda self-important to assume this will be all the PhysiCell stuff in Julia)
15+
- PhysiCell.jl (kinda self-important to assume this will be all the PhysiCell stuff in Julia)
16+
17+
I think I'm now leaning towards `ModelManager.jl` being the underlying framework that works across ABM (or other modeling paradigms) frameworks and then `PhysiCellModelManager.jl` is the PhysiCell-specific version.

src/VCTClasses.jl

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -284,88 +284,80 @@ struct Monad <: AbstractMonad
284284
id::Int #! integer uniquely identifying this monad
285285
n_replicates::Int #! (minimum) number of simulations belonging to this monad
286286
simulation_ids::Vector{Int} #! simulation ids belonging to this monad
287-
288287
inputs::InputFolders #! contains the folder names for the simulations in this monad
289-
290288
variation_id::VariationID
291289

292290
function Monad(n_replicates::Int, inputs::InputFolders, variation_id::VariationID, use_previous::Bool)
291+
feature_str = """
292+
(\
293+
physicell_version_id,\
294+
$(join(locationIDNames(), ",")),\
295+
$(join(locationVariationIDNames(), ","))\
296+
) \
297+
"""
298+
value_str = """
299+
(\
300+
$(physicellVersionDBEntry()),\
301+
$(join([inputs[loc].id for loc in project_locations.all], ",")),\
302+
$(join([variation_id[loc] for loc in project_locations.varied],","))\
303+
) \
304+
"""
293305
monad_id = DBInterface.execute(db,
294306
"""
295-
INSERT OR IGNORE INTO monads (\
296-
physicell_version_id,\
297-
$(join(locationIDNames(), ",")),\
298-
$(join(locationVariationIDNames(), ","))\
299-
) \
300-
VALUES(\
301-
$(physicellVersionDBEntry()),\
302-
$(join([inputs[loc].id for loc in project_locations.all], ",")),\
303-
$(join([variation_id[loc] for loc in project_locations.varied],","))\
304-
) \
305-
RETURNING monad_id;
307+
INSERT OR IGNORE INTO monads $feature_str VALUES $value_str RETURNING monad_id;
306308
"""
307309
) |> DataFrame |> x -> x.monad_id
308310
if isempty(monad_id)
309311
monad_id = constructSelectQuery(
310312
"monads",
311313
"""
312-
WHERE (\
313-
physicell_version_id,\
314-
$(join(locationIDNames(), ",")),\
315-
$(join(locationVariationIDNames(), ","))\
316-
)=\
317-
(\
318-
$(physicellVersionDBEntry()),\
319-
$(join([inputs[loc].id for loc in project_locations.all], ",")),\
320-
$(join([variation_id[loc] for loc in project_locations.varied],","))\
321-
);\
322-
""",
314+
WHERE $feature_str=$value_str
315+
""";
323316
selection="monad_id"
324317
) |> queryToDataFrame |> x -> x.monad_id[1] #! get the monad_id
325318
else
326319
monad_id = monad_id[1] #! get the monad_id
327320
end
328321
return Monad(monad_id, n_replicates, inputs, variation_id, use_previous)
329322
end
323+
330324
function Monad(id::Int, n_replicates::Int, inputs::InputFolders, variation_id::VariationID, use_previous::Bool)
331-
simulation_ids = use_previous ? readMonadSimulationIDs(id) : Int[]
332-
num_sims_to_add = n_replicates - length(simulation_ids)
325+
@assert id > 0 "id must be positive"
326+
@assert n_replicates >= 0 "n_replicates must be non-negative"
327+
328+
previous_simulation_ids = readMonadSimulationIDs(id)
329+
new_simulation_ids = Int[]
330+
num_sims_to_add = n_replicates - (use_previous ? length(previous_simulation_ids) : 0)
333331
if num_sims_to_add > 0
334332
for _ = 1:num_sims_to_add
335333
simulation = Simulation(inputs, variation_id) #! create a new simulation
336-
push!(simulation_ids, simulation.id) #! add the simulation id to the monad
334+
push!(new_simulation_ids, simulation.id)
337335
end
336+
recordSimulationIDs(id, [previous_simulation_ids; new_simulation_ids]) #! record the simulation ids in a .csv file
338337
end
339338

340-
@assert id > 0 "id must be positive"
341-
@assert n_replicates >= 0 "n_replicates must be non-negative"
342-
343-
#! this could be done when adding new simulation ids to save some fie I/O
344-
#! doing it here just to make sure it is always up to date (and for consistency across classes)
345-
recordSimulationIDs(id, simulation_ids) #! record the simulation ids in a .csv file
339+
simulation_ids = use_previous ? [previous_simulation_ids; new_simulation_ids] : new_simulation_ids
346340

347341
return new(id, n_replicates, simulation_ids, inputs, variation_id)
348342
end
349343

350344
end
351345

352-
function Monad(inputs::InputFolders, variation_id::VariationID; use_previous::Bool=true)
353-
n_replicates = 0 #! not making a monad to run if not supplying the n_replicates info
346+
function Monad(inputs::InputFolders, variation_id::VariationID; use_previous::Bool=true, n_replicates::Int=0)
354347
Monad(n_replicates, inputs, variation_id, use_previous)
355348
end
356349

357-
function getMonad(monad_id::Int, n_replicates::Int)
350+
function getMonad(monad_id::Int, n_replicates::Int, use_previous::Bool)
358351
df = constructSelectQuery("monads", "WHERE monad_id=$(monad_id);") |> queryToDataFrame
359352
if isempty(df)
360353
error("Monad $(monad_id) not in the database.")
361354
end
362355
inputs = [loc => df[1, locationIDName(loc)] for loc in project_locations.all] |> InputFolders
363356
variation_id = [loc => df[1, locationVarIDName(loc)] for loc in project_locations.varied] |> VariationID
364-
use_previous = true
365357
return Monad(monad_id, n_replicates, inputs, variation_id, use_previous)
366358
end
367359

368-
Monad(monad_id::Integer; n_replicates::Integer=0) = getMonad(monad_id, n_replicates)
360+
Monad(monad_id::Integer; n_replicates::Integer=0, use_previous::Bool=true) = getMonad(monad_id, n_replicates, use_previous)
369361

370362
function Simulation(monad::Monad)
371363
return Simulation(monad.inputs, monad.variation_id)

src/VCTDatabase.jl

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,34 +11,25 @@ function initializeDatabase(path_to_database::String; auto_upgrade::Bool=false)
1111
is_new_db = !isfile(path_to_database)
1212
global db = SQLite.DB(path_to_database)
1313
SQLite.transaction(db, "EXCLUSIVE")
14-
success = createSchema(is_new_db; auto_upgrade=auto_upgrade)
15-
SQLite.commit(db)
16-
if success
17-
global initialized = true
18-
end
19-
return success
20-
end
21-
22-
function initializeDatabase()
23-
global db = SQLite.DB()
24-
is_new_db = true
25-
success = createSchema(is_new_db)
26-
if success
14+
try
15+
createSchema(is_new_db; auto_upgrade=auto_upgrade)
16+
catch e
17+
SQLite.rollback(db)
18+
println("Error initializing database: $e")
19+
return false
20+
else
21+
SQLite.commit(db)
2722
global initialized = true
23+
return true
2824
end
29-
return success
3025
end
3126

3227
function reinitializeDatabase()
3328
if !initialized
3429
return
3530
end
3631
global initialized = false
37-
if db.file == ":memory:" #! if the database is in memory, re-initialize it
38-
initializeDatabase()
39-
else
40-
initializeDatabase(db.file; auto_upgrade=true)
41-
end
32+
return initializeDatabase(db.file; auto_upgrade=true)
4233
end
4334

4435
function createSchema(is_new_db::Bool; auto_upgrade::Bool=false)
@@ -197,7 +188,7 @@ function createPCVCTTable(table_name::String, schema::String; db::SQLite.DB=db)
197188
s *= "\n\tThis helps to normalize what the id names are for these entries."
198189
s *= "\n\tYour table $(table_name) does not end in 's'."
199190
s *= "\n\tSee retrieveID(location::Symbol, folder_name::String; db::SQLite.DB=db)."
200-
error(s)
191+
throw(ErrorException(s))
201192
end
202193
#! check that schema has PRIMARY KEY named as table_name without the s followed by _id
203194
id_name = locationIDName(Symbol(table_name[1:end-1]))
@@ -206,7 +197,7 @@ function createPCVCTTable(table_name::String, schema::String; db::SQLite.DB=db)
206197
s *= "\n\tThis helps to normalize what the id names are for these entries."
207198
s *= "\n\tYour schema $(schema) does not have \"$(id_name) INTEGER PRIMARY KEY\"."
208199
s *= "\n\tSee retrieveID(location::Symbol, folder_name::String; db::SQLite.DB=db)."
209-
error(s)
200+
throw(ErrorException(s))
210201
end
211202
SQLite.execute(db, "CREATE TABLE IF NOT EXISTS $(table_name) (
212203
$(schema)

src/VCTDeletion.jl

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,8 @@ function resetDatabase(; force_reset::Bool=false, force_continue::Bool=false)
250250
rm_hpc_safe(joinpath(locationPath(:custom_code, custom_code_folder), baseToExecutable("project")); force=true)
251251
end
252252

253-
if db.file == ":memory:"
254-
initializeDatabase()
255-
else
256-
rm_hpc_safe("$(db.file)"; force=true)
257-
initializeDatabase("$(db.file)")
258-
end
253+
rm_hpc_safe("$(db.file)"; force=true)
254+
initializeDatabase("$(db.file)")
259255
return nothing
260256
end
261257

test/test-scripts/ClassesTests.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@ n_replicates = 1
2222
config_variation_ids = [1, 2]
2323
rulesets_collection_variation_ids = [1, 1]
2424
ic_cell_variation_ids = [0, 0]
25+
location_variation_ids = Dict{Symbol,Union{Integer,AbstractArray{<:Integer}}}(
26+
:config => config_variation_ids,
27+
:rulesets_collection => rulesets_collection_variation_ids,
28+
:ic_cell => ic_cell_variation_ids
29+
)
2530
sampling = Sampling(inputs;
2631
n_replicates=n_replicates,
27-
location_variation_ids=Dict{Symbol,Union{Integer,AbstractArray{<:Integer}}}(:config => config_variation_ids,
28-
:rulesets_collection => rulesets_collection_variation_ids,
29-
:ic_cell => ic_cell_variation_ids)
32+
location_variation_ids=location_variation_ids
3033
)
3134
@test sampling isa Sampling
3235

test/test-scripts/DatabaseTests.jl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ mv(custom_code_src_folder, custom_code_dest_folder)
2323
mv(config_dest_folder, config_src_folder)
2424
mv(custom_code_dest_folder, custom_code_src_folder)
2525

26-
# test memory db
27-
pcvct.initializeDatabase()
28-
pcvct.reinitializeDatabase()
29-
pcvct.initializeDatabase(joinpath(pcvct.data_dir, "vct.db"))
30-
3126
# test bad table
3227
table_name_not_end_in_s = "test"
3328
@test_throws ErrorException pcvct.createPCVCTTable(table_name_not_end_in_s, "")
@@ -58,4 +53,13 @@ pcvct.variationIDs(:ic_ecm, Sampling(1))
5853
pcvct.variationsTable(:config, Sampling(1); remove_constants=true)
5954
pcvct.variationsTable(:rulesets_collection, Sampling(1); remove_constants=true)
6055
pcvct.variationsTable(:ic_cell, Sampling(1); remove_constants=true)
61-
pcvct.variationsTable(:ic_ecm, Sampling(1); remove_constants=true)
56+
pcvct.variationsTable(:ic_ecm, Sampling(1); remove_constants=true)
57+
58+
# test bad folder
59+
path_to_bad_folder = joinpath(pcvct.data_dir, "inputs", "configs", "bad_folder")
60+
mkdir(path_to_bad_folder)
61+
62+
@test pcvct.reinitializeDatabase() == false
63+
64+
rm(path_to_bad_folder; force=true, recursive=true)
65+
@test pcvct.initializeDatabase(pcvct.db.file) == true

test/test-scripts/RunnerTests.jl

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ filename = split(filename, "/") |> last
33
str = "TESTING WITH $(filename)"
44
hashBorderPrint(str)
55

6-
hashBorderPrint("DATABASE SUCCESSFULLY INITIALIZED!")
6+
n_sims = length(Monad(1))
7+
monad = Monad(1; n_replicates=1, use_previous=false)
8+
run(monad)
9+
@test length(monad.simulation_ids) == 1 #! how many simulations were attached to this monad when run
10+
@test length(getSimulationIDs(monad)) == n_sims+1 #! how many simulations are stored in simulations.csv
711

812
config_folder = "0_template"
913
rulesets_collection_folder = "0_template"
@@ -33,13 +37,9 @@ out2 = run(inputs, discrete_variations)
3337
@test out.trial.inputs == out2.trial.inputs
3438
@test out.trial.variation_id == out2.trial.variation_id
3539

36-
hashBorderPrint("SIMULATION SUCCESSFULLY RUN!")
37-
3840
query = pcvct.constructSelectQuery("simulations", "WHERE simulation_id=1")
3941
df = pcvct.queryToDataFrame(query; is_row=true)
4042

41-
hashBorderPrint("SIMULATION SUCCESSFULLY IN DB!")
42-
4343
cell_type = "default"
4444
discrete_variations = DiscreteVariation[]
4545
xml_path = [pcvct.cyclePath(cell_type); "phase_durations"; "duration:index:0"]
@@ -53,13 +53,9 @@ push!(discrete_variations, DiscreteVariation(xml_path, 5.0))
5353

5454
sampling = createTrial(simulation, discrete_variations; n_replicates=n_replicates)
5555

56-
hashBorderPrint("SAMPLING SUCCESSFULLY CREATED!")
57-
5856
out = run(sampling; force_recompile=false)
5957
@test out.n_success == length(sampling)
6058

61-
hashBorderPrint("SAMPLING SUCCESSFULLY RUN!")
62-
6359
out2 = run(simulation, discrete_variations; n_replicates=n_replicates, force_recompile=false)
6460
@test out2.trial isa Sampling
6561
@test out2.trial.id == sampling.id
@@ -69,8 +65,6 @@ out2 = run(simulation, discrete_variations; n_replicates=n_replicates, force_rec
6965
@test out2.n_scheduled == 0
7066
@test out2.n_success == 0
7167

72-
hashBorderPrint("SUCCESSFULLY `run` WITHOUT CREATING SAMPLING!")
73-
7468
n_simulations = length(sampling) #! number of simulations recorded (in .csvs) for this sampling
7569
n_expected_sims = n_replicates
7670
for discrete_variation in discrete_variations
@@ -83,15 +77,11 @@ n_variations = length(sampling.variation_ids)
8377
@test n_simulations == n_variations * n_replicates #! ...how many variation ids we recorded (number of rulesets_variations_ids must match variation_ids on construction of sampling)
8478
@test n_simulations == out.n_success #! ...how many simulations succeeded
8579

86-
hashBorderPrint("SAMPLING SUCCESSFULLY IN CSVS!")
87-
8880
out = run(sampling; force_recompile=false)
8981

9082
# no new simulations should have been run
9183
@test out.n_success == 0
9284

93-
hashBorderPrint("SUCCESSFULLY FOUND PREVIOUS SIMS!")
94-
9585
trial = Trial([sampling])
9686
@test trial isa Trial
9787

@@ -100,8 +90,6 @@ out = run(trial; force_recompile=false)
10090
# no new simulations should have been run
10191
@test out.n_success == 0
10292

103-
hashBorderPrint("SUCCESSFULLY RAN TRIAL!")
104-
10593
@test_warn "`runAbstractTrial` is deprecated. Use `run` instead." runAbstractTrial(trial; force_recompile=false)
10694

10795
# run a sim that will produce an error

0 commit comments

Comments
 (0)