Skip to content

Commit 11c3a2c

Browse files
Add helper function to load EKP file (#190)
* Add func to load latest EKP file * Set JuliaFormatter version to match other repos * Add compat for docs
1 parent a0e493f commit 11c3a2c

File tree

6 files changed

+42
-6
lines changed

6 files changed

+42
-6
lines changed

.github/workflows/julia_formatter.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ jobs:
1212
steps:
1313
- uses: julia-actions/julia-format@v3
1414
with:
15-
version: '2' # Set `version` to '1.0.54' if you need to use JuliaFormatter.jl v1.0.54 (default: '1')
15+
version: '1' # Set `version` to '1.0.54' if you need to use JuliaFormatter.jl v1.0.54 (default: '1')
1616
suggestion-label: 'format-suggest' # leave this unset or empty to show suggestions for all PRs

docs/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
1414

1515
[compat]
1616
ClimaAtmos = "=0.28.3"
17+
EnsembleKalmanProcesses = "2"

docs/src/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,5 @@ ClimaCalibrate.path_to_model_log
6565
ClimaCalibrate.parameter_path
6666
ClimaCalibrate.minibatcher_over_samples
6767
ClimaCalibrate.observation_series_from_samples
68+
ClimaCalibrate.load_latest_ekp
6869
```

src/ekp_interface.jl

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import EnsembleKalmanProcesses.TOMLInterface as TI
88

99
export get_prior, initialize, update_ensemble, save_G_ensemble
1010
export path_to_ensemble_member,
11-
path_to_model_log, path_to_iteration, parameter_path
11+
path_to_model_log, path_to_iteration, parameter_path, load_latest_ekp
1212

1313
"""
1414
load_ekp_struct(output_dir, iteration)
@@ -18,6 +18,22 @@ Return the EnsembleKalmanProcess struct for a completed iteration.
1818
load_ekp_struct(output_dir, iteration) =
1919
JLD2.load_object(ekp_path(output_dir, iteration))
2020

21+
"""
22+
load_latest_ekp(output_dir)
23+
24+
Return the most recent EnsembleKalmanProcess struct from the given output directory.
25+
26+
Returns nothing if no EKP structs are found.
27+
"""
28+
function load_latest_ekp(output_dir)
29+
iter = -1
30+
while isfile(ekp_path(output_dir, iter + 1))
31+
iter += 1
32+
end
33+
iter == -1 && return nothing
34+
return load_ekp_struct(output_dir, iter)
35+
end
36+
2137
"""
2238
path_to_ensemble_member(output_dir, iteration, member)
2339

src/workers.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,7 @@ function Distributed.launch(
133133
output_path = get(params, :o, get(params, :output, default_output))
134134

135135
ntasks = sm.ntasks
136-
srun_cmd =
137-
`srun -J $jobname -n $ntasks -D $exehome $worker_args -o $output_path -- $exename $exeflags $(worker_cookie_arg())`
136+
srun_cmd = `srun -J $jobname -n $ntasks -D $exehome $worker_args -o $output_path -- $exename $exeflags $(worker_cookie_arg())`
138137
@info "Starting SLURM job $jobname: $srun_cmd"
139138
pid = open(addenv(srun_cmd, env))
140139

@@ -336,8 +335,7 @@ function Distributed.launch(
336335
-j oe: Send the output and error streams to the same file
337336
-J 1-ntasks: Job array
338337
-o: output file =#
339-
qsub_cmd =
340-
`qsub -V -N $jobname -j oe $job_array_option $worker_args -o $output_path -- $exename $exeflags $(worker_cookie_arg())`
338+
qsub_cmd = `qsub -V -N $jobname -j oe $job_array_option $worker_args -o $output_path -- $exename $exeflags $(worker_cookie_arg())`
341339
@info "Starting PBS job $jobname: $qsub_cmd"
342340
pid = open(addenv(qsub_cmd, env))
343341

test/ekp_interface.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,26 @@ end
6767
@test eki.u[1].stored_data == user_constructed_eki.u[1].stored_data
6868
end
6969

70+
@testset "Test loading latest EKP struct" begin
71+
# Test loading from directory with no completed iterations
72+
empty_dir = joinpath(output_dir, "empty")
73+
mkpath(empty_dir)
74+
@test isnothing(CAL.load_latest_ekp(empty_dir))
75+
76+
# Test loading from directory with completed iterations
77+
# We already have an EKP struct saved from earlier tests
78+
latest_ekp = CAL.load_latest_ekp(output_dir)
79+
@test !isnothing(latest_ekp)
80+
@test latest_ekp isa EKP.EnsembleKalmanProcess
81+
# Compare with the known EKP struct
82+
for prop in propertynames(latest_ekp)
83+
prop in [:u, :accelerator, :localizer] && continue
84+
@test getproperty(latest_ekp, prop) ==
85+
getproperty(eki_with_kwargs, prop)
86+
end
87+
@test latest_ekp.u[1].stored_data == eki_with_kwargs.u[1].stored_data
88+
end
89+
7090
override_file =
7191
joinpath(output_dir, "iteration_000", "member_001", "parameters.toml")
7292
td = CP.create_toml_dict(FT; override_file)

0 commit comments

Comments
 (0)