diff --git a/Utilities/Generic/MATLAB/Functions/diagCorr.m b/Utilities/Generic/MATLAB/Functions/diagCorr.m deleted file mode 100644 index bcb22005e08bdc9c46242c9aa6f533a979aa2bf9..0000000000000000000000000000000000000000 --- a/Utilities/Generic/MATLAB/Functions/diagCorr.m +++ /dev/null @@ -1,81 +0,0 @@ -%% Calculate a "diagonality" measure/metric -% -------------------------------------------------- -% Author: Achilles Kappis -% e-mail: axilleaz@protonmail.com -% -% Date: 17/02/2025 (DD/MM/YYYY) -% -% Copyright: MIT -% -------------------------------------------------- -% Functionality: Calculate a "diagonality" measure. This provides a notion -% "how diagonal" a matrix is. In practice this is the -% correlation coefficient of a matrix to a diagonal matrix. -% -------------------------------------------------- -% Input -% -% mat [numeric]: The matrices to be "checked" for "diagonality". This can -% be either a 2D array (matrix) or a 3D array (stacked -% matrices), in which case the first two dimensions will be -% treated as matrices of which the "diagonality" will be -% checked. The matrices must be square. -% -% -------------------------------------------------- -% Output -% -% diagonality [numeric]: This is the diagonality correlation coefficient -% for each of the arrays provided. This will be -% either a scalar, if M is 2D, or a vector if M is -% 3D, with each element corresponing to the -% diagonality metric for each matrix. -% -% -------------------------------------------------- -% Notes -% -% - The metric is calculated as provided in the Mathematics StackExchange -% at https://math.stackexchange.com/a/1393907. -% -% -------------------------------------------------- -function [diagonality] = diagCorr(mat) - % ==================================================== - % Check for number of arguments - % ==================================================== - narginchk(1, 1); - nargoutchk(0, 1); - - % ==================================================== - % Validate input arguments - % ==================================================== - % Validate mandatory arguments - validateattributes(mat, "numeric", {'3d', 'square', 'nonempty'}, mfilename, "Matrices to be checked for diagonality", 1); - - - % ==================================================== - % Calculate auxiliary vectors - % ==================================================== - elemSum = ones(1, size(mat, 1)); - r = 1:length(elemSum); - r2 = r.^2; - - - % ==================================================== - % Calculate correlation coefficient to diagonal matrix - % ==================================================== - % Go through the matrices - for idx = size(mat, 3):-1:1 - % Get the matrix at the current index - tmpMat = mat(:, :, idx); - - % Calculate auxiliary values - n = sum(tmpMat, "all"); - sumRow = r * tmpMat * elemSum'; - sumCol = elemSum * tmpMat * r'; - sumRow2 = r2 * tmpMat * elemSum'; - sumCol2 = elemSum * tmpMat * r2'; - sumRowCol = r * tmpMat * r'; - - diagonality(idx) = (n * sumRowCol - sumRow * sumCol)/(sqrt(n * sumRow2 - (sumRow^2)) * sqrt(n * sumCol2 - (sumCol^2))); - end - - % Get rid of possible imaginary residuals - diagonality = real(diagonality); -end \ No newline at end of file diff --git a/Utilities/Generic/MATLAB/Functions/diagMetric.m b/Utilities/Generic/MATLAB/Functions/diagMetric.m new file mode 100644 index 0000000000000000000000000000000000000000..0f02f3b35b344c5d1ce9bf854693f12715aa051c --- /dev/null +++ b/Utilities/Generic/MATLAB/Functions/diagMetric.m @@ -0,0 +1,107 @@ +%% Calculate a "diagonality" measure/metric +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 18/02/2025 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: Calculate a "diagonality" measure based on the norm of the +% difference of between a matrix and the same matrix with +% its principal diagonal removed. +% -------------------------------------------------- +% Input +% +% mat [numeric]: The matrices to be "checked" for "diagonality". This can +% be either a 2D array (matrix) or a 3D array (stacked +% matrices), in which case the first two dimensions will be +% treated as matrices of which the "diagonality" will be +% checked. The matrices must be square (the first two +% dimensions must be equal). +% +% matNorm [numeric/char/string] (Optional): The norm to be used in the +% calculation of the diagonality +% metric. This can take one of +% the values 1, 2, and Inf, that +% define the L1, L2 or Linf +% norms, or be one of the strings +% "Fro", or "Frobenius" (not +% case-sensitive) to use the +% Frobenius norm. +% [Default: "Fro"]. +% +% normalise [logical] (Optional): Whether to normalise the result with the +% norm of the matrix. This will provide a +% results between 0, when all the elements +% along the diagonal are zero and 1 when +% the matrix is diagonal. +% +% -------------------------------------------------- +% Output +% +% diagonality [numeric]: This is the diagonality correlation coefficient +% for each of the arrays provided. This will be +% either a scalar, if M is 2D, or a vector if M is +% 3D, with each element corresponing to the +% diagonality metric for each matrix. +% +% -------------------------------------------------- +% Notes +% +% - The metric is calculated as norm(A - diag(diag(A))), where the +% norm used is the one defined by the argument "matNorm". If "normalise" +% is true, the metric is calculated as +% 1 - norm(A - diag(diag(A))/norm(A). +% +% -------------------------------------------------- +function diagonality = diagMetric(mat, matNorm, normalise) + % ==================================================== + % Check for number of arguments + % ==================================================== + narginchk(1, 3); + nargoutchk(0, 1); + + % ==================================================== + % Validate input arguments + % ==================================================== + % Validate mandatory arguments + validateattributes(mat, "numeric", {'3d', 'square', 'nonempty'}, mfilename, "Matrices to be checked for diagonality", 1); + + % Validate optional arguments + if nargin > 1 && ~isempty(matNorm) + % Make sure we have either a string-like object or a numeric scalar + validateattributes(matNorm, {'char', 'string', 'numeric'}, {'scalar', 'nonempty', 'real'}, mfilename, "The matrix norm to be used", 2); + + if nnz(matNorm == [1, 2, Inf]) == 0 && nnz(strcmpi(matNorm, ["Fro", "Frobenius"])) == 0 + error("The 'matNorm' argument can be either 1, 2, Inf, 'Fro', or 'Frobenius'."); + end + + if ~isnumeric(matNorm) + matNorm = lower(matNorm); + end + else + matNorm = "fro"; + end + + if nargin > 2 && ~isempty(normalise) + validateattributes(normalise, {'logical', 'numeric'}, {'scalar', 'nonempty', 'real', 'finite', 'nonnan'}, mfilename, "Normalisation flag", 3); + normalise = logical(normalise); + else + normalise = true; + end + + + % ==================================================== + % Calculate the metric + % ==================================================== + % Go through the matrices + for idx = size(mat, 3):-1:1 + tmpMat = mat(:, :, idx); + diagonality(idx) = norm(tmpMat - diag(diag(tmpMat)), matNorm); + + if normalise + diagonality(idx) = 1 - diagonality(idx)/norm(tmpMat, matNorm); + end + end +end \ No newline at end of file