Skip to content

Commit 8b537f3

Browse files
committed
Merge branch 'main' of github.com:pinheiroGroup/Kinbiont.jl
2 parents e26163e + a02fb46 commit 8b537f3

5 files changed

+96
-24
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Kinbiont"
22
uuid = "3b7c519f-be5e-4159-a208-6486ce96bb37"
33
authors = ["Fabrizio Angaroni", "Edgar Zanella Alvarenga"]
4-
version = "1.0.2"
4+
version = "1.0.10"
55

66
[deps]
77
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"

README.md

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
<p align="center">
2-
<img src="https://kinbiont.fuzue.org/assets/logo.png">
3-
</p>
4-
51

62
Ecological and evolutionary processes of microbes are characterized by observables like growth rates and biomass yield, inferred from kinetics experiments.
73
Across conditions, these observables map response patterns such as antibiotic growth inhibition and yield dependence on substrate.
84
But how do we extract ecological and evolutionary insights from massive datasets of time-resolved microbial data? Here we introduce Kinbiont — an ecosystem of numerical methods combining state-of-the-art solvers for ordinary differential equations, non-linear optimization, signal processing, and interpretable machine learning algorithms.
95
Kinbiont provides a comprehensive, model-based analysis pipeline, covering all aspects of microbial kinetics data, from preprocessing to result interpretation.
10-
For the stable documentation please consult [Documentation](https://kinbiont.fuzue.org/)
6+
7+
8+
9+
For stable documentation please consult [Documentation](https://kinbiont.fuzue.org/).
10+
11+
Pre-print at [Biorxiv](https://www.biorxiv.org/content/10.1101/2024.09.09.611847v1) .
12+
13+
Data and scripts to reproduce the paper results at [Kinbiont utilities](https://github.com/pinheiroGroup/Kinbiont_utilities)

src/Fit_one_file_functions.jl

+5-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Fits a logarithmic-linear model to data from a .csv file. The function assumes t
4343
- `pt_avg=7`: Number of points used in the rolling average smoothing.
4444
- `pt_smoothing_derivative=7`: Number of points for evaluating specific growth rate. If less than 2, uses interpolation; otherwise, a sliding window approach is used.
4545
- `pt_min_size_of_win=7`: Minimum size of the exponential windows in terms of the number of smoothed points.
46-
- `type_of_win="maximum"`: Method for selecting the exponential phase window. Options are `"maximum"` or `"global_thr"`.
46+
- `type_of_win="maximum"`: Method for selecting the exponential phase window. Options are "maximum"` or `"global_thr"` "max_with_min_OD".
4747
- `threshold_of_exp=0.9`: Threshold in quantile to define the exponential windows, between 0 and 1.
4848
- `do_blank_subtraction="avg_blank"`: Method for blank subtraction. Options include `"NO"`, `"avg_subtraction"`, and `"time_avg"`.
4949
- `blank_value=0.0`: Average value of the blank, used only if `do_blank_subtraction` is not `"NO"`.
@@ -143,8 +143,11 @@ function fit_one_file_Log_Lin(
143143

144144
# excluding blank data and discarded wells
145145
if length(list_of_blank) > 0
146+
146147
names_of_cols = filter!(e -> !(e in list_of_blank), names_of_cols)
148+
147149
end
150+
148151
if length(list_of_discarded) > 0
149152

150153
names_of_cols = filter!(e -> !(e in list_of_discarded), names_of_cols)
@@ -1662,7 +1665,7 @@ function segment_gr_analysis_file(
16621665
if write_res == true
16631666

16641667
CSV.write(
1665-
string(path_to_results,results, label_exp, "_results.csv"),
1668+
string(path_to_results,label_exp, "_results.csv"),
16661669
Tables.table(Matrix(results)),
16671670
)
16681671

src/Fit_one_well_functions.jl

+79-13
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Fits a logarithmic-linear model to data from a .csv file. The function assumes t
3434
- `pt_avg=7`: Number of points used in the rolling average smoothing.
3535
- `pt_smoothing_derivative=7`: Number of points for evaluating specific growth rate. If less than 2, uses interpolation; otherwise, a sliding window approach is used.
3636
- `pt_min_size_of_win=7`: Minimum size of the exponential windows in terms of the number of smoothed points.
37-
- `type_of_win="maximum"`: Method for selecting the exponential phase window. Options are `"maximum"` or `"global_thr"`.
37+
- `type_of_win="maximum"`: Method for selecting the exponential phase window. Options are `"maximum"`, `"global_thr"` or `"max_with_min_OD"`.
3838
- `threshold_of_exp=0.9`: Threshold in quantile to define the exponential windows, between 0 and 1.
3939
- `do_blank_subtraction="avg_blank"`: Method for blank subtraction. Options include `"NO"`, `"avg_subtraction"`, and `"time_avg"`.
4040
- `blank_value=0.0`: Average value of the blank, used only if `do_blank_subtraction` is not `"NO"`.
@@ -85,7 +85,7 @@ function fitting_one_well_Log_Lin(
8585
method_multiple_scattering_correction="interpolation",
8686
calibration_OD_curve="NA",
8787
thr_lowess=0.05,
88-
start_exp_win_thr=0.05
88+
start_exp_win_thr=0.01,
8989
)
9090
if multiple_scattering_correction == true
9191

@@ -120,6 +120,10 @@ function fitting_one_well_Log_Lin(
120120
t_start = 0.0
121121

122122
if type_of_win == "maximum"
123+
124+
125+
126+
123127
for yy = 1:(index_of_max-2)
124128
if specific_gr[index_of_max-yy] >= lb_of_distib
125129
t_start = copy(specific_gr_times[index_of_max-yy])
@@ -187,17 +191,75 @@ function fitting_one_well_Log_Lin(
187191

188192
end
189193

194+
195+
if type_of_win == "max_with_min_OD"
196+
197+
index_od_over_thr = findfirst(data_smooted[2, :] .> start_exp_win_thr)
198+
199+
if isnothing(index_od_over_thr) == false && length(specific_gr[index_od_over_thr:end]) > 2
200+
201+
lb_of_distib = quantile(specific_gr[index_od_over_thr:end], threshold_of_exp)
202+
203+
index_of_max = argmax(specific_gr[index_od_over_thr:end])[1] + index_od_over_thr - 1
204+
205+
206+
207+
for yy = 1:(index_of_max-2)
208+
if specific_gr[index_of_max-yy] >= lb_of_distib
209+
t_start = copy(specific_gr_times[index_of_max-yy])
210+
else
211+
if specific_gr[(index_of_max-yy-1)] < lb_of_distib
212+
break
213+
end
214+
215+
end
216+
end
217+
218+
# index of start
219+
index_of_t_start = findfirst(x -> x > t_start, data_smooted[1, :])[1]
220+
221+
if index_od_over_thr[1] > index_of_t_start
222+
index_of_t_start = index_od_over_thr[1]
223+
t_start = specific_gr_times[index_of_t_start]
224+
end
225+
226+
# searching t_end of the exp phase
227+
t_end = specific_gr_times[end]
228+
229+
for yy = index_of_max:(eachindex(specific_gr)[end]-1)
230+
if specific_gr[yy] >= lb_of_distib
231+
t_end = copy(specific_gr_times[yy])
232+
else
233+
if specific_gr[(yy+1)] < lb_of_distib
234+
break
235+
end
236+
end
237+
end
238+
index_of_t_end = findfirst(x -> x > t_end, data_smooted[1, :])[1]
239+
240+
241+
else
242+
# the conditions are not satisfied i fix t_end and t_start to be discarded later and have all results to missing
243+
t_end = 100
244+
t_start = 200
245+
index_of_t_start = 1
246+
index_of_t_end = index_of_t_start + 2 * pt_min_size_of_win
247+
248+
end
249+
end
250+
251+
190252
# checking the minimum size of the window before fitting
191253
if (index_of_t_end - index_of_t_start) < pt_min_size_of_win
192254
index_of_t_start = convert(Int, index_of_max - floor(pt_min_size_of_win / 2))
193255
index_of_t_end = convert(Int, index_of_max + floor(pt_min_size_of_win / 2))
194256

195257
if index_of_t_start < 1
196-
index_of_t_start =1
258+
index_of_t_start =1
197259
end
198260

199261
if index_of_t_end > length(data_smooted[1, :])
200-
index_of_t_end = length(data_smooted[1, :])
262+
index_of_t_end = length(data_smooted[1, :])
201263
end
202264
end
203265

@@ -213,7 +275,7 @@ function fitting_one_well_Log_Lin(
213275

214276
sigma_a = sigma_b = r = zeros(N)
215277
Theoretical_fitting = coeff_1 .+ data_to_fit_times .* coeff_2
216-
278+
217279
Cantrell_errors = sqrt(sum((data_to_fit_values - coeff_2 * data_to_fit_times .- coeff_1) .^ 2) / (N - 2)) # goodness of fit
218280
sigma_b = sqrt(1 / sum((data_to_fit_times .- mean_x) .^ 2))
219281
sigma_a = Cantrell_errors * sqrt(1 / N + mean_x^2 * sigma_b^2)
@@ -246,6 +308,11 @@ function fitting_one_well_Log_Lin(
246308

247309
else
248310

311+
312+
data_to_fit_times = missing
313+
Theoretical_fitting = missing
314+
confidence_band = missing
315+
249316
results_lin_log_fit = [
250317
label_exp,
251318
name_well,
@@ -266,11 +333,10 @@ function fitting_one_well_Log_Lin(
266333
end
267334

268335

269-
Kinbiont_res_one_well_log_lin = ("Log-lin", results_lin_log_fit, hcat(data_to_fit_times, data_to_fit_values), data_smooted, confidence_band)
336+
Kinbiont_res_one_well_log_lin = ("Log-lin", results_lin_log_fit, hcat(data_to_fit_times, Theoretical_fitting), data_smooted, confidence_band)
270337

271338
return Kinbiont_res_one_well_log_lin
272-
end
273-
339+
end
274340

275341
"""
276342
fitting_one_well_ODE_constrained(
@@ -746,7 +812,7 @@ function ODE_Model_selection(
746812

747813
temp_start_param = param_array[mm]
748814

749-
815+
750816

751817
# generating IC
752818
# setting initial conditions
@@ -1123,7 +1189,7 @@ end
11231189
opt_params...
11241190
)
11251191
1126-
This function fits an Ordinary Differential Equation (ODE) model to segmented time-series data. Users provide fixed change points, and the function models to each segment defined by these points.
1192+
This function fits an Ordinary Differential Equation (ODE) model to segmented time-series data. Users provide fixed change points, and the function models to each segment defined by these points.
11271193
11281194
# Arguments:
11291195
@@ -1455,7 +1521,7 @@ function segmentation_ODE(
14551521
pt_avg=1, # number of the point to generate intial condition
14561522
smoothing=true, # the smoothing is done or not?
14571523
path_to_results="NA",
1458-
win_size=14, #
1524+
win_size=14, #
14591525
pt_smooth_derivative=7,
14601526
beta_smoothing_ms=2.0,
14611527
multiple_scattering_correction=false, # if true uses the given calibration curve to fix the data
@@ -1775,7 +1841,7 @@ function segment_gr_analysis(
17751841
thr_lowess=0.05, # keyword argument of lowees smoothing
17761842
type_of_detection="slinding_win",
17771843
type_of_curve="original",
1778-
win_size=14, #
1844+
win_size=14, #
17791845
n_bins=40,
17801846
method_peaks_detection="peaks_prominence"
17811847
)
@@ -1870,4 +1936,4 @@ export ODE_Model_selection
18701936
export one_well_morris_sensitivity
18711937
export selection_ODE_fixed_intervals
18721938
export segmentation_ODE
1873-
export segment_gr_analysis
1939+
export segment_gr_analysis

src/NL_fit_one_well.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ function fit_NL_model_with_sensitivity(data::Matrix{Float64}, # dataset first ro
358358

359359
best_res_param = fin_param[:, index_best+1]
360360

361-
best_fitted_model = model_function(best_res_param[3:(end-3)], data[1, :])
361+
best_fitted_model = model_function(best_res_param[4:(end-3)], data[1, :])
362362

363363
if write_res == true
364364
mkpath(path_to_results)
@@ -588,7 +588,7 @@ function fit_NL_model_bootstrap(data::Matrix{Float64}, # dataset first row times
588588
index_best = findmin(fin_param[end, 2:end])[2]
589589

590590
best_res_param = fin_param[:, index_best+1]
591-
best_fitted_model = model_function(best_res_param[3:(end-3)], data[1, :])
591+
best_fitted_model = model_function(best_res_param[4:(end-3)], data[1, :])
592592

593593
if write_res == true
594594
mkpath(path_to_results)
@@ -807,7 +807,7 @@ function NL_error_blanks(data::Matrix{Float64}, # dataset first row times second
807807
index_best = findmin(fin_param[end, 2:end])[2]
808808

809809
best_res_param = fin_param[:, index_best+1]
810-
best_fitted_model = model_function(best_res_param[3:(end-3)], data[1, :])
810+
best_fitted_model = model_function(best_res_param[4:(end-3)], data[1, :])
811811

812812
if write_res == true
813813
mkpath(path_to_results)

0 commit comments

Comments
 (0)