This code determines the limit of detection from experimental data in a linear calibration curve. See the following article for details:

Hans-Peter Loock and Peter D. Wentzell, Detection limits of chemical sensors: Applications and misapplications, Sensors and Actuators B: Chemical, 173 (2012) 157–163, https://doi.org/10.1016/j.snb.2012.06.071

% Created by: Arthur Giron Santos 
 % Date: June, 2022
% Created by: Arthur Giron Santos 
 % Date: June, 2022
 % Version: 1.0
 % Objective: to calculate the Limit of Detection of chemical sensors using the following data provided:
 % x (concentration), y (signal), t (Student t-function) and k (number of replicate measurements).
 % cite as:
 % A.G. Santos, and H-P Loock (2022) Limit of Detection source code (Version 1.0) [Source code] <link_website>
 % based on: Hans-Peter Loock and Peter D. Wentzell, Detection limits of chemical sensors: Applications and misapplications,
 % Sensors and Actuators B: Chemical, 173 (2012) 157–163, https://doi.org/10.1016/j.snb.2012.06.071
 % In the code below we refer to equation numbers in Sens. Act. B: Chem, 173, (2012) 157–163.
 % Sample data => replace those row vectors with your data
     x = [1,4,9,16,25,36,49,64,81,100];
     % y = [10.967044171877, 13.7266562041864, 21.6774325819587, 28.0501802939311, 36.0314926863133, 51.9667357806104, 55.1532263138279, 74.6573287557684, 71.9956136960292, 129.299736817629];
     y= [0.948765056,2.868444736,9.156115413,10.93922882,29.1421891,35.21056678,47.19701892,78.89101104,71.86086959,88.32222164];
     t = 3; % Value of Student T-function
     k = 1; % number of replicates for each value
     [LOD_1 LOD_2 LOD_3] = calculateLOD(x,y,t,k);
     output = "LOD_1 = "+LOD_1+ " (dashed blue line; see equation (11)"
     output = "LOD_2 = "+LOD_2+ " (solid black line; Currie and Svehla (1994); see equation (15)"
     output = "LOD_3 = "+LOD_3+ " (dashed red line; should not be used)"
function [LOD_1 LOD_2 LOD_3] = calculateLOD(x,y,t,k)
     % --------------------------------------------------------------------------
     % Calculate LOD
     % --------------------------------------------------------------------------
     % Assuming that X and Y are ROW ARRAYS
         n = length(x);
     % perform linear regression
         x_aux = ones(size(x',1),1); % auxiliary variable
         x_aux = [x_aux x'];
         % [c,~,~,~,stats] = regress(y',x_aux); % calculates: a (slope), b (intersept), R^2 (correlation coefficient)
         c = polyfit(x,y,1);
         a = c(1); % slope (=sensitivity)
         b = c(2);
         % R = stats(1);
     % Calculate determinant in the denominator of equations (4) and (5)
         sum_x = sum(x); % auxiliary variable
         sum_x2 = sum(x.^2); % auxiliary variable
         D = sum_x2*n - sum_x*sum_x; % equation (6)
         d = zeros(1,length(x));
         for i = 1:length(x) % numerator in (8)
             d(i) = (y(i) - (a*x(i) + b))^2;
         end
         sigma_y = sqrt( sum(d)/(n-2) ); % equation (8)
         aux = (n/D - ((abs(a)/t)/sigma_y)^2);
     % given for completeness, but should not be used:
         LOD_3 = t*sigma_y / a;
     % LOD_2 from equation (11):
         LOD_2 = (2/D)/aux * ( sum_x - sqrt( sum_x^2 - D^2 * aux * (sum_x2/D + 1/k) ) );
     % LOD_3 determined from equation (15), which is derived from
     % Currie and Svehla, Nomenclature for the presentation of results of chemicalanalysis, Pure and Applied Chemistry 66 (1994) 595–608
         LOD_1 = 2*t*sigma_y / ( n * (t*sigma_y)^2 - D*a^2 ) * ( t*sigma_y*sum_x - sqrt(D*a^2 * sum_x2 + (a*D)^2) );
     % --------------------------------------------------------------------------
     % PLOT GRAPHIC
     % --------------------------------------------------------------------------
         x_fit = zeros(1,length(x));
         y_fit = zeros(1,length(x));
         sigma_x = zeros(1,length(x)); % for ERROR BARS in x
         MpC_x = zeros(1,length(x)); % mean_x + conf_x
         MmC_x = zeros(1,length(x)); % mean_x - conf_x
         MpS_x = zeros(1,length(x)); % mean_x + sigma_x
         MmS_x = zeros(1,length(x)); % mean_x - sigma_x
         y_fit = [y_fit, 0]; % "y_fit" needs an extra element for the plot
         y_fit(1) = b;
         for i = 1:length(x)
             x_fit(i) = (y(i) - b)/a; % x-values of the fit line
             sigma_x(i) = sigma_y/abs(a) * sqrt( 1/k + ( x_fit(i)^2 * n + sum_x2 - 2*x_fit(i)*sum_x )/D ); % equation (9)
             MpC_x(i) = x_fit(i) + t*sigma_x(i);
             MmC_x(i) = x_fit(i) - t*sigma_x(i);
             MpS_x(i) = x_fit(i) + sigma_x(i);
             MmS_x(i) = x_fit(i) - sigma_x(i);
             y_fit(i+1) = a*x(i) + b;
         end
     %auxiliary variables
         x0 = [0, x];
         aux = b+a*LOD_2/2;
         LOD3x = [0, LOD_3, LOD_3];
         LOD3y = [aux, aux, 0];
         LOD2x = [0, LOD_2, LOD_2];
         LOD2y = [aux, aux, 0];
         aux = b+a*LOD_1/2;
         LOD1x = [0, LOD_1, LOD_1];
         LOD1y = [aux, aux, 0];
     %plots
         f = figure;
         f.Position = [10 10 960 540];
         plot(x,y,"ko")
         ylim([0 inf])
         ax = gca;
             ax.YAxisLocation = 'origin';
         title('Limit of Detection')
         xlabel("Concentration")
         ylabel("Signal")
         txt={"LOD_1 = "+LOD_1+" (dashed blue line; eq'n [11]) ", "LOD_2 = "+LOD_2+ " (solid black line; eq'n [15])","LOD_3 = "+LOD_3+ " (dashed red line; don't use)"};
         dim = [.6 .2 .1 .1];
         annotation("textbox",dim,'String',txt,'FitBoxToText','on','BackgroundColor','white')
     hold on
         %errorbars
             yerr = zeros(1,length(x)) + sigma_y;
             xerr = sigma_x;
             errorbar(x,y,yerr,yerr,xerr,xerr,'.')
         %red line - linear fit
             plot(x0,y_fit,"r-")
         %blue lines - confidence intervals
             plot(MmC_x,y,"b-",MpC_x,y,"b-")
         %LOD points
             plot(LOD3x,LOD3y,"r--",LOD2x,LOD2y,"k-",LOD1x,LOD1y,"b--")
     hold off
 end