Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
Given the probability distributions for stress and strength, this module will find the probability of failure due to stress-strength interference.
Failure is defined as when stress>strength.
Uses the exact formula method which is only valid for two Normal Distributions.
Inputs:
stress - a probability distribution from the Distributions module
strength - a probability distribution from the Distributions module
show_distribution_plot - True/False (default is True)
print_results - True/False (default is True)
Returns:
the probability of failure
'''
if type(stress) is not Normal_Distribution:
raise ValueError('Both stress and strength must be a Normal_Distribution. If you need another distribution then use Probability_of_failure rather than Probability_of_failure_normdist')
if type(strength) is not Normal_Distribution:
raise ValueError('Both stress and strength must be a Normal_Distribution. If you need another distribution then use Probability_of_failure rather than Probability_of_failure_normdist')
sigma_strength = strength.sigma
mu_strength = strength.mu
sigma_stress = stress.sigma
mu_stress = stress.mu
prob_of_failure = ss.norm.cdf(-(mu_strength - mu_stress) / ((sigma_strength ** 2 + sigma_stress ** 2) ** 0.5))
if print_results is True:
print('Probability of failure:', prob_of_failure)
if show_distribution_plot is True:
xmin = stress.b5
xmax = strength.b95
xvals = np.linspace(xmin, xmax, 1000)
stress_PDF = stress.PDF(xvals=xvals, show_plot=False)
plt.title('Probability Density Function')
plt.xlabel('Data')
plt.ylabel('Probability density')
plt.legend()
plt.subplot(122) # CDF
plt.bar(center, hist_cumulative * self._frac_fail, align='center', width=width, alpha=0.2, color='k', edgecolor='k')
Weibull_Distribution(alpha=self.Weibull_2P_alpha, beta=self.Weibull_2P_beta).CDF(xvals=xvals, label=r'Weibull ($\alpha , \beta$)')
Weibull_Distribution(alpha=self.Weibull_3P_alpha, beta=self.Weibull_3P_beta, gamma=self.Weibull_3P_gamma).CDF(xvals=xvals, label=r'Weibull ($\alpha , \beta , \gamma$)')
Gamma_Distribution(alpha=self.Gamma_2P_alpha, beta=self.Gamma_2P_beta).CDF(xvals=xvals, label=r'Gamma ($\alpha , \beta$)')
Gamma_Distribution(alpha=self.Gamma_3P_alpha, beta=self.Gamma_3P_beta, gamma=self.Gamma_3P_gamma).CDF(xvals=xvals, label=r'Gamma ($\alpha , \beta , \gamma$)')
Exponential_Distribution(Lambda=self.Expon_1P_lambda).CDF(xvals=xvals, label=r'Exponential ($\lambda$)')
Exponential_Distribution(Lambda=self.Expon_2P_lambda, gamma=self.Expon_2P_gamma).CDF(xvals=xvals, label=r'Exponential ($\lambda , \gamma$)')
Lognormal_Distribution(mu=self.Lognormal_2P_mu, sigma=self.Lognormal_2P_sigma).CDF(xvals=xvals, label=r'Lognormal ($\mu , \sigma$)')
Lognormal_Distribution(mu=self.Lognormal_3P_mu, sigma=self.Lognormal_3P_sigma, gamma=self.Lognormal_3P_gamma).CDF(xvals=xvals, label=r'Lognormal ($\mu , \sigma , \gamma$)')
Normal_Distribution(mu=self.Normal_2P_mu, sigma=self.Normal_2P_sigma).CDF(xvals=xvals, label=r'Normal ($\mu , \sigma$)')
if max(X) <= 1: # condition for Beta Dist to be fitted
Beta_Distribution(alpha=self.Beta_2P_alpha, beta=self.Beta_2P_beta).CDF(xvals=xvals, label=r'Beta ($\alpha , \beta$)')
plt.legend()
plt.xlim([xmin, xmax])
plt.title('Cumulative Distribution Function')
plt.xlabel('Data')
plt.ylabel('Cumulative probability density')
plt.suptitle('Histogram plot of each fitted distribution')
plt.legend()
num_bins = min(int(len(X) / 2), 30)
hist, bins = np.histogram(X, bins=num_bins, density=True)
hist_cumulative = np.cumsum(hist) / sum(hist)
width = np.diff(bins)
center = (bins[:-1] + bins[1:]) / 2
plt.bar(center, hist * self._frac_fail, align='center', width=width, alpha=0.2, color='k', edgecolor='k')
Weibull_Distribution(alpha=self.Weibull_2P_alpha, beta=self.Weibull_2P_beta).PDF(xvals=xvals, label=r'Weibull ($\alpha , \beta$)')
Weibull_Distribution(alpha=self.Weibull_3P_alpha, beta=self.Weibull_3P_beta, gamma=self.Weibull_3P_gamma).PDF(xvals=xvals, label=r'Weibull ($\alpha , \beta , \gamma$)')
Gamma_Distribution(alpha=self.Gamma_2P_alpha, beta=self.Gamma_2P_beta).PDF(xvals=xvals, label=r'Gamma ($\alpha , \beta$)')
Gamma_Distribution(alpha=self.Gamma_3P_alpha, beta=self.Gamma_3P_beta, gamma=self.Gamma_3P_gamma).PDF(xvals=xvals, label=r'Gamma ($\alpha , \beta , \gamma$)')
Exponential_Distribution(Lambda=self.Expon_1P_lambda).PDF(xvals=xvals, label=r'Exponential ($\lambda$)')
Exponential_Distribution(Lambda=self.Expon_2P_lambda, gamma=self.Expon_2P_gamma).PDF(xvals=xvals, label=r'Exponential ($\lambda , \gamma$)')
Lognormal_Distribution(mu=self.Lognormal_2P_mu, sigma=self.Lognormal_2P_sigma).PDF(xvals=xvals, label=r'Lognormal ($\mu , \sigma$)')
Lognormal_Distribution(mu=self.Lognormal_3P_mu, sigma=self.Lognormal_3P_sigma, gamma=self.Lognormal_3P_gamma).PDF(xvals=xvals, label=r'Lognormal ($\mu , \sigma , \gamma$)')
Normal_Distribution(mu=self.Normal_2P_mu, sigma=self.Normal_2P_sigma).PDF(xvals=xvals, label=r'Normal ($\mu , \sigma$)')
if max(X) <= 1: # condition for Beta Dist to be fitted
Beta_Distribution(alpha=self.Beta_2P_alpha, beta=self.Beta_2P_beta).PDF(xvals=xvals, label=r'Beta ($\alpha , \beta$)')
plt.legend()
plt.xlim([xmin, xmax])
plt.title('Probability Density Function')
plt.xlabel('Data')
plt.ylabel('Probability density')
plt.legend()
plt.subplot(122) # CDF
plt.bar(center, hist_cumulative * self._frac_fail, align='center', width=width, alpha=0.2, color='k', edgecolor='k')
Weibull_Distribution(alpha=self.Weibull_2P_alpha, beta=self.Weibull_2P_beta).CDF(xvals=xvals, label=r'Weibull ($\alpha , \beta$)')
Weibull_Distribution(alpha=self.Weibull_3P_alpha, beta=self.Weibull_3P_beta, gamma=self.Weibull_3P_gamma).CDF(xvals=xvals, label=r'Weibull ($\alpha , \beta , \gamma$)')
Gamma_Distribution(alpha=self.Gamma_2P_alpha, beta=self.Gamma_2P_beta).CDF(xvals=xvals, label=r'Gamma ($\alpha , \beta$)')
Gamma_Distribution(alpha=self.Gamma_3P_alpha, beta=self.Gamma_3P_beta, gamma=self.Gamma_3P_gamma).CDF(xvals=xvals, label=r'Gamma ($\alpha , \beta , \gamma$)')
Exponential_Distribution(Lambda=self.Expon_1P_lambda).CDF(xvals=xvals, label=r'Exponential ($\lambda$)')
self.success = False
print('WARNING: Fitting using Autograd FAILED for Normal_2P. The fit from Scipy was used instead so results may not be accurate.')
self.mu = sp[0]
self.sigma = sp[1]
params = [self.mu, self.sigma]
k = len(params)
n = len(all_data)
LL2 = 2 * Fit_Normal_2P.LL(params, failures, right_censored)
self.loglik2 = LL2
if n - k - 1 > 0:
self.AICc = 2 * k + LL2 + (2 * k ** 2 + 2 * k) / (n - k - 1)
else:
self.AICc = 'Insufficient data'
self.BIC = np.log(n) * k + LL2
self.distribution = Normal_Distribution(mu=self.mu, sigma=self.sigma)
# confidence interval estimates of parameters
Z = -ss.norm.ppf((1 - CI) / 2)
if force_sigma is None:
hessian_matrix = hessian(Fit_Normal_2P.LL)(np.array(tuple(params)), np.array(tuple(failures)), np.array(tuple(right_censored)))
covariance_matrix = np.linalg.inv(hessian_matrix)
self.mu_SE = abs(covariance_matrix[0][0]) ** 0.5
self.sigma_SE = abs(covariance_matrix[1][1]) ** 0.5
self.Cov_mu_sigma = abs(covariance_matrix[0][1])
self.mu_upper = self.mu + (Z * self.mu_SE) # these are unique to normal and lognormal mu params
self.mu_lower = self.mu + (-Z * self.mu_SE)
self.sigma_upper = self.sigma * (np.exp(Z * (self.sigma_SE / self.sigma)))
self.sigma_lower = self.sigma * (np.exp(-Z * (self.sigma_SE / self.sigma)))
else:
hessian_matrix = hessian(Fit_Normal_2P.LL_fs)(np.array(tuple([self.mu])), np.array(tuple(failures)), np.array(tuple(right_censored)), np.array(tuple([force_sigma])))
covariance_matrix = np.linalg.inv(hessian_matrix)
fitted_results = Fit_Everything(failures=RVS_filtered, print_results=False, show_probability_plot=False, show_histogram_plot=False, show_PP_plot=False) # fit all distributions to the filtered samples
ranked_distributions = list(fitted_results.results.index.values)
ranked_distributions.remove(distribution.name2) # removes the fitted version of the original distribution
ranked_distributions_objects = []
ranked_distributions_labels = []
sigfig = 2
for dist_name in ranked_distributions:
if dist_name == 'Weibull_2P':
ranked_distributions_objects.append(Weibull_Distribution(alpha=fitted_results.Weibull_2P_alpha, beta=fitted_results.Weibull_2P_beta))
ranked_distributions_labels.append(str('Weibull_2P (α=' + str(round(fitted_results.Weibull_2P_alpha, sigfig)) + ',β=' + str(round(fitted_results.Weibull_2P_beta, sigfig)) + ')'))
elif dist_name == 'Gamma_2P':
ranked_distributions_objects.append(Gamma_Distribution(alpha=fitted_results.Gamma_2P_alpha, beta=fitted_results.Gamma_2P_beta))
ranked_distributions_labels.append(str('Gamma_2P (α=' + str(round(fitted_results.Gamma_2P_alpha, sigfig)) + ',β=' + str(round(fitted_results.Gamma_2P_beta, sigfig)) + ')'))
elif dist_name == 'Normal_2P':
ranked_distributions_objects.append(Normal_Distribution(mu=fitted_results.Normal_2P_mu, sigma=fitted_results.Normal_2P_sigma))
ranked_distributions_labels.append(str('Normal_2P (μ=' + str(round(fitted_results.Normal_2P_mu, sigfig)) + ',σ=' + str(round(fitted_results.Normal_2P_sigma, sigfig)) + ')'))
elif dist_name == 'Lognormal_2P':
ranked_distributions_objects.append(Lognormal_Distribution(mu=fitted_results.Lognormal_2P_mu, sigma=fitted_results.Lognormal_2P_sigma))
ranked_distributions_labels.append(str('Lognormal_2P (μ=' + str(round(fitted_results.Lognormal_2P_mu, sigfig)) + ',σ=' + str(round(fitted_results.Lognormal_2P_sigma, sigfig)) + ')'))
elif dist_name == 'Exponential_1P':
ranked_distributions_objects.append(Exponential_Distribution(Lambda=fitted_results.Expon_1P_lambda))
ranked_distributions_labels.append(str('Exponential_1P (lambda=' + str(round(fitted_results.Expon_1P_lambda, sigfig)) + ')'))
elif dist_name == 'Beta_2P':
ranked_distributions_objects.append(Beta_Distribution(alpha=fitted_results.Beta_2P_alpha, beta=fitted_results.Beta_2P_beta))
ranked_distributions_labels.append(str('Beta_2P (α=' + str(round(fitted_results.Beta_2P_alpha, sigfig)) + ',β=' + str(round(fitted_results.Beta_2P_beta, sigfig)) + ')'))
if include_location_shifted is True:
if dist_name == 'Weibull_3P':
ranked_distributions_objects.append(Weibull_Distribution(alpha=fitted_results.Weibull_3P_alpha, beta=fitted_results.Weibull_3P_beta, gamma=fitted_results.Weibull_3P_gamma))
ranked_distributions_labels.append(str('Weibull_3P (α=' + str(round(fitted_results.Weibull_3P_alpha, sigfig)) + ',β=' + str(round(fitted_results.Weibull_3P_beta, sigfig)) + ',γ=' + str(round(fitted_results.Weibull_3P_gamma, sigfig)) + ')'))
elif dist_name == 'Gamma_3P':
elif best_dist == 'Weibull_3P':
self.best_distribution = Weibull_Distribution(alpha=self.Weibull_3P_alpha, beta=self.Weibull_3P_beta, gamma=self.Weibull_3P_gamma)
elif best_dist == 'Gamma_2P':
self.best_distribution = Gamma_Distribution(alpha=self.Gamma_2P_alpha, beta=self.Gamma_2P_beta)
elif best_dist == 'Gamma_3P':
self.best_distribution = Gamma_Distribution(alpha=self.Gamma_3P_alpha, beta=self.Gamma_3P_beta, gamma=self.Gamma_3P_gamma)
elif best_dist == 'Lognormal_2P':
self.best_distribution = Lognormal_Distribution(mu=self.Lognormal_2P_mu, sigma=self.Lognormal_2P_sigma)
elif best_dist == 'Lognormal_3P':
self.best_distribution = Lognormal_Distribution(mu=self.Lognormal_3P_mu, sigma=self.Lognormal_3P_sigma, gamma=self.Lognormal_3P_gamma)
elif best_dist == 'Exponential_1P':
self.best_distribution = Exponential_Distribution(Lambda=self.Expon_1P_lambda)
elif best_dist == 'Exponential_2P':
self.best_distribution = Exponential_Distribution(Lambda=self.Expon_2P_lambda, gamma=self.Expon_2P_gamma)
elif best_dist == 'Normal_2P':
self.best_distribution = Normal_Distribution(mu=self.Normal_2P_mu, sigma=self.Normal_2P_sigma)
elif best_dist == 'Beta_2P':
self.best_distribution = Beta_Distribution(alpha=self.Beta_2P_alpha, beta=self.Beta_2P_beta)
# print the results
if print_results is True: # printing occurs by default
pd.set_option('display.width', 200) # prevents wrapping after default 80 characters
pd.set_option('display.max_columns', 9) # shows the dataframe without ... truncation
print(self.results)
if show_histogram_plot is True:
Fit_Everything.histogram_plot(self) # plotting occurs by default
if show_PP_plot is True:
Fit_Everything.P_P_plot(self) # plotting occurs by default
if show_probability_plot is True:
from reliability.Fitters import Fit_Normal_2P
fit = Fit_Normal_2P(failures=failures, right_censored=right_censored, show_probability_plot=False, print_results=False)
mu = fit.mu
sigma = fit.sigma
if 'label' in kwargs:
label = kwargs.pop('label')
else:
label = str('Fitted Normal_2P (μ=' + str(round_to_decimals(mu, dec)) + ', σ=' + str(round_to_decimals(sigma, dec)) + ')')
if 'color' in kwargs:
color = kwargs.pop('color')
data_color = color
else:
color = 'red'
data_color = 'k'
plt.scatter(x, y, marker='.', linewidth=2, c=data_color)
nf = Normal_Distribution(mu=mu, sigma=sigma).CDF(show_plot=False, xvals=xvals)
xrange = plt.gca().get_xlim() # this ensures the previously plotted objects are considered when setting the range
xrange_min = min(min(x) - delta * 0.2, xrange[0])
xrange_max = max(max(x) + delta * 0.2, xrange[1])
plt.xlim([xrange_min, xrange_max])
plt.title('Probability plot\nNormal CDF')
plt.xlabel('Time')
plt.ylabel('Fraction failing')
plt.gcf().set_size_inches(9, 7) # adjust the figsize. This is done post figure creation so that layering is easier
if show_fitted_distribution is True:
plt.plot(xvals, nf, color=color, label=label, **kwargs)
plt.legend(loc='upper left')
return plt.gcf()
Note that the empirical CDF also accepts X_data_right_censored just as Kaplan-Meier and Nelson-Aalen will also accept right censored data.
Inputs:
X_data_failures - the failure times in an array or list
X_data_right_censored - the right censored failure times in an array or list. Optional input.
Y_dist - a probability distribution. The CDF of this distribution will be plotted along the Y-axis.
method - 'KM' or 'NA' for Kaplan-Meier and Nelson-Aalen. Default is 'KM'
show_diagonal_line - True/False. Default is True. If True the diagonal line will be shown on the plot.
Outputs:
The PP_plot is the only output. Use plt.show() to show it.
'''
if X_data_failures is None or Y_dist is None:
raise ValueError('X_data_failures and Y_dist must both be specified. X_data_failures can be an array or list of failure times. Y_dist must be a probability distribution generated using the Distributions module')
if type(Y_dist) not in [Weibull_Distribution, Normal_Distribution, Lognormal_Distribution, Exponential_Distribution, Gamma_Distribution, Beta_Distribution] or type(Y_dist) not in [Weibull_Distribution, Normal_Distribution, Lognormal_Distribution, Exponential_Distribution, Gamma_Distribution, Beta_Distribution]:
raise ValueError('Y_dist must be specified as a probability distribution generated using the Distributions module')
if type(X_data_failures) == list:
X_data_failures = np.sort(np.array(X_data_failures))
elif type(X_data_failures) == np.ndarray:
X_data_failures = np.sort(X_data_failures)
else:
raise ValueError('X_data_failures must be an array or list')
if type(X_data_right_censored) == list:
X_data_right_censored = np.sort(np.array(X_data_right_censored))
elif type(X_data_right_censored) == np.ndarray:
X_data_right_censored = np.sort(X_data_right_censored)
elif X_data_right_censored is None:
pass
else:
raise ValueError('X_data_right_censored must be an array or list')
# extract certain keyword arguments or specify them if they are not set