Source code for djura.vulnerability_modeller.fragility

# SPDX-License-Identifier: AGPL-3.0-or-later
# Copyright (C) 2025-2026 Djura | Risk - Data - Engineering S.r.l.
import numpy as np
from scipy import stats, optimize


[docs] def mlefit(param1: float, param2: float, total_count: int, count: int, data) -> float: """Maximum likelihood method Performs a lognormal cumulative distribution function fit to the data points based on maximum likelihood method Parameters ---------- param1 : float Median of the function, parameter of a statistical model to be found param2 : float Standard deviation of the function, parameter of a statistical model to be found total_count : int Number of data points count : int Number of failures data: Union[List, np.ndarray] The function, data points Returns ------- float Negative Log likelihood to be minimized """ import warnings warnings.filterwarnings("ignore", category=RuntimeWarning) try: p = stats.norm.cdf(np.log(data), loc=np.log(param1), scale=param2) likelihood = stats.binom.pmf(count, total_count, p) likelihood[likelihood == 0] = 1e-290 loglik = -sum(np.log10(likelihood)) warnings.resetwarnings() return loglik except OverflowError: warnings.resetwarnings() return 1e+8 except Exception: warnings.resetwarnings() return 1e+8
[docs] def fit_fragility(xs, counts, total_count, iml_range=None, beta=0.0): xs = xs counts = counts if xs[0] == 0: xs, counts = xs[1:], counts[1:] theta_hat_mom = np.exp(np.mean(np.log(xs))) beta_hat_mom = np.std(np.log(xs)) x0 = [theta_hat_mom, beta_hat_mom] xopt_mle = optimize.fmin( func=lambda var: mlefit( param1=var[0], param2=var[1], total_count=total_count, count=np.array(counts), data=xs ), x0=x0, maxiter=3000, maxfun=3000, disp=False) theta_mle = xopt_mle[0] beta_mle = (xopt_mle[1] ** 2 + beta ** 2) ** 0.5 probs = None if iml_range is not None: probs = stats.norm.cdf( np.log(iml_range / theta_mle) / beta_mle, loc=0, scale=1 ) return { 'median': theta_mle, 'beta': beta_mle, 'probs': probs, 'iml_range': iml_range }