Curve Fitting
All fitting functions use LsqFit.jl (nonlinear least squares) or ordinary least squares where appropriate.
TPC fitting
Generic models
fit_thermal_performance_curve(ModelType, temperatures, rates;
initial_parameters=nothing, weights=nothing)Supported generic models: UniversalTPCModel, GaussianModel, DeutschModel. Returns a fitted instance of ModelType. Initial parameters are estimated from data heuristics if initial_parameters is nothing.
temps = [5, 10, 15, 20, 25, 30, 35, 40, 45]
rates = [0.1, 0.3, 0.6, 0.9, 1.0, 0.9, 0.5, 0.1, 0.0]
m_fit = fit_thermal_performance_curve(UniversalTPCModel, temps, rates)Sharpe-Schoolfield models
SharpSchoolFullModel and SharpSchoolDEBModel have a specialised overload with initial parameter estimates from the Schoolfield et al. (1981) graphical method (piecewise OLS on the Arrhenius plot):
fit_thermal_performance_curve(SharpSchoolFullModel, temperatures, rates;
T_ref=298.15u"K",
log_transform=true,
initial_parameters=nothing,
weights=nothing)log_transform=true (default): minimises sum of squared log-residuals $\sum(\log \hat{r}_i - \log r_i)^2$. Appropriate when rates span orders of magnitude; matches the Schoolfield et al. (1981) Marquardt fit.
log_transform=false: minimises absolute residuals; use with weights for weighted least squares (e.g. weights = 1 ./ rates for equal relative weighting of each point).
Graphical initial estimates (Schoolfield 1981, Figure 2):
The data are split into cold / middle / hot fractions. OLS is fitted to $\ln r \sim 1/T$ in each region. From the slopes:
T_A ≈ −slope_middle
T_AL ≈ −slope_cold − T_A
T_AH ≈ slope_hot + T_ATL and TH are found from the intersections of the cold / hot OLS lines with the half-Arrhenius line (middle line shifted down by ln 2).
TDT fitting
Static knockdown data
Provide group-summary mean knockdown times at each assay temperature:
data = StaticKnockdownData(temperatures=[36, 38, 40, 42, 44],
knockdown_times=[289, 72, 18, 4.5, 1.1])
m_tdt = fit_thermal_death_time_curve(data; reference_duration=60.0)Fits $\log_{10}(t) \sim T$ by OLS. Returns a LogLinearTDTModel.
Dynamic CTmax data
Provide knockdown temperatures observed at multiple ramp rates:
data = DynamicKnockdownData(ramp_rates=[0.1, 0.25, 0.5],
dynamic_ctmax_values=[40.2, 41.8, 43.1],
start_temperature=20.0)
m_tdt = fit_thermal_death_time_curve(data; reference_duration=60.0)Uses Jørgensen (2021) Eq. 7a in NLS (≥ 3 ramp rates) or a root-finding scan (2 rates).
Tolerance landscape
Requires individual-level knockdown data (one row per organism):
data = IndividualKnockdownData(temperatures=assay_temps,
knockdown_times=times_to_knockdown)
tl = fit_tolerance_landscape(data; n_bins=1000)Algorithm (Rezende et al. 2014, tolerance.landscape()):
- OLS on $\log_{10}(t) \sim T$ → z-value, T_max
- Z-shift all knockdown times to the mean assay temperature: $t_{\text{shifted}} = t \cdot 10^{(T - \bar{T}) / z}$
- Compute empirical survival function S(τ) on shifted times
- Store as
n_bins-row matrix (interpolated to regular grid)
The resulting ToleranceLandscape can then be used for dynamic_survival predictions.
Data container types
IndividualKnockdownData(; temperatures, knockdown_times)
StaticKnockdownData(; temperatures, knockdown_times)
DynamicKnockdownData(; ramp_rates, dynamic_ctmax_values, start_temperature)All temperature arguments accept Unitful quantities or bare floats (°C assumed).