diff --git a/.gitignore b/.gitignore index 817ce6a..607e757 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Operating system files -*.DS_Store +.DS_Store Thumbs.db .AppleDouble .LSOverride @@ -12,7 +12,4 @@ workspaces.mat src/ext/BrainNetViewer_20181219/tmp.edge src/ext/BrainNetViewer_20181219/tmp.node *.asv -src/.DS_Store -test/.DS_Store -src/.DS_Store - +develop/* diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 940ab52..25f73a6 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,4 +1,19 @@ -## [v1.0.0-beta.10] - +## [v1.0.0-beta.13] - 05.09.2024 +- Fix random seed error in newer versions of MATLAB. + +## [v1.0.0-beta.12-hotfix] - 21.04.2024 +- Add function to check if given matrix symmetric with tolerance. +- Fix minor bug in NBSPredict_predict. + +## [v1.0.0-beta.12] - 03.04.2024 +- Reintroduced LOOCV for classification problems (no LOOCV for regression yet). +- Fix minor bugs in GUI. + +## [v1.0.0-beta.11] - 21.08.2023 +- Fix minor bugs in novel data prediction function. +- Fix minor bugs in saving results. + +## [v1.0.0-beta.10] - 19.06.2023 - Refactor CPM functions. - CPM can now provide predicted and true labels, so that user can compute further performance metrics. - Prediction performance of combined network (positive and negative) is now provided. diff --git a/TangentSpace.m b/TangentSpace.m deleted file mode 100644 index 904fed8..0000000 --- a/TangentSpace.m +++ /dev/null @@ -1,194 +0,0 @@ -classdef TangentSpace < handle - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % TangentSpace Transforms positive definite covariance matrices - % into tangent space. Transforming covariance matrices - % (or positive definite correlation matrices) into tangent space - % has been shown to provide significantly higher - % prediction performance (Dadi et al., 2019; Pervaiz et al., 2020). - % - % - % - % Example: - % vectorizer = TangentSpace; - % edgeMatrix = vectorizer.transform(data); - % - % References: - % Dadi, Kamalaker, et al. "Benchmarking functional connectome-based - % predictive models for resting-state fMRI." - % NeuroImage 192 (2019): 115-134. - % Pervaiz, Usama, et al. "Optimising network modelling - % methods for fMRI." Neuroimage 211 (2020): 116604. - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - properties (Access = private) - dims % dimensions of the data - whitening % whitening matrix - ref_matrix % reference matrix - end - - properties (Access = public) - ref - end - - methods (Access = private) - function [] = check_positive_definite(~, X) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Checks whether input matrices are positive definite. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - x_dim = size(X); - n_dims = numel(x_dim); - assert(ismember(n_dims, [2,3], 'Input matrix must be 2D or 3D!')); - if numel(x_dim) == 3 - for s = 1: x_dim(3) - assert(is_positive_definite(X(:,:,s)),... - 'Input matrix is not positive definite!') - end - elseif numel(x_dim) == 2 - assert(is_positive_definite(X),... - 'Input matrix is not positive definite!') - end - end - - function [] = map_shrinkage(obj, X) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Applies shrinkage each covariance matrix in X dataset. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - switch obj.ref - case 'euclidian' - % Takes euclidian mean of input matrix. - obj.ref_matrix = squeeze(mean(X, 3)); - case 'log_euclidian' - % Computes log euclidian mean of input matrix. - obj.ref_matrix = exp(mean(log(X), 3)); - end - end - - function symMat = form_symmetric_matrix(~, X, func) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Constructs a symmetric matrix from a given X matrix - % using eigenvalues and eigenvectors computed from the input - % matrix. While constructing, it also applies a custom - % function to eigenvalues to transform the matrix space. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if nargin < 2 - func = @(x) 1./x; - end - - % Eigendecomposition - [EV,DV] = eig(X); - DV = func(DV); % transform eigenvalues using given function. - DV(isinf(DV)) = 0; - - % form matrix again. - symMat = EV*DV*EV'; - end - end - - methods - function obj = TangentSpace(varargin) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Initializes class. - % - % Args: - % ref: Method to compute mean reference matrix - % (default = 'euclidian'). - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Default parameters. - defaultVals.ref = 'euclidian'; - refOptions = {'euclidian', 'log_euclidian'}; - - % Input Parser - validationRef = @(x) any(validatestring(x,refOptions)); - p = inputParser(); p.PartialMatching = 0; % deactivate partial matching. - addParameter(p,'ref',defaultVals.ref,validationRef); - - % Parse inputs and store into the object. - parse(p,varargin{:}); - obj.ref = p.Results.ref; - obj.dims = []; - end - - function obj = fit(obj,X) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Fits the tangent space transformer to the given X matrix. - % - % Args: - % X: 3D (nodes x nodes x subject) input matrix. - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - obj.check_positive_definite(X); - obj.ref_matrix = map_shrinkage(X); % compute reference matrix. - obj.whitening = form_symmetric_matrix(obj, X); - end - - function trans_mat = transform(obj,X) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Projects the input covariance matrices into tangent space - % using computed reference mean matrix. - % - % Args: - % X: 3D (nodes x nodes x subject) or 2D (nodes x nodes) - % input matrix. - % - % Output: - % trans_mat: Transformed matrix. - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - obj.check_positive_definite(X); - x_dim = size(X); - n_dims = numel(x_dim); - assert(ismember(n_dims, [2,3], 'Input matrix must be 2D or 3D!')); - if n_dims == 3 - nSub = x_dim(3); - trans_mat = zeros(x_dim); - elseif n_dims == 2 - nSub = 1; - trans_mat = zeros([1; x_dim(:)]'); - end - - for s = 1: nSub - trans_mat(s,:,:) = obj.form_symmetric_matrix(... - obj.whitening * X(s,:,:) * obj.whitening, log); - end - trans_mat = squeeze(trans_mat); - end - - function untrans_mat = inverse_transform(obj, X) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Inverse transform from tangent space to covariance matrix - % (Riemannian space). - % - % Args: - % X: Tangent transformed input matrix. - % - % Output: - % untrans_mat: Inverse transformed, covariance matrices. - % - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - sqrt_whitening = obj.form_symmetric_matrix(obj.refMat, sqrt); - x_dim = size(X); - n_dims = numel(x_dim); - assert(ismember(n_dims, [2,3], 'Input matrix must be 2D or 3D!')); - if n_dims == 3 - nSub = x_dim(3); - untrans_mat = zeros(x_dim); - elseif n_dims == 2 - nSub = 1; - untrans_mat = zeros([1; x_dim(:)]'); - end - - for s = 1: nSub - untrans_mat(:,:,1) =... - sqrt_whitening * obj.form_symmetric_matrix(X(:,:,s), exp) *... - sqrt_whitening; - end - untrans_mat = squeeze(untrans_mat); - end - - end -end - - - diff --git a/is_positive_definite.m b/is_positive_definite.m deleted file mode 100644 index 1b30c8d..0000000 --- a/is_positive_definite.m +++ /dev/null @@ -1,20 +0,0 @@ -function [isPosDef] = is_positive_definite(X) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% is_positive_definite Checks if given matrix is positive definite. -% -% Arguments: -% X = 2D (nodes x nodes) matrix. -% -% Output: -% isPosDef = Whether given matrices are positive definite. -% -% Emin Serin - 28.02.2022 -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -try chol(X) - isPosDef = 1; -catch - isPosDef = 0; -end -end - diff --git a/src/.DS_Store b/src/.DS_Store deleted file mode 100644 index f26257b..0000000 Binary files a/src/.DS_Store and /dev/null differ diff --git a/test/.DS_Store b/test/.DS_Store deleted file mode 100644 index a218275..0000000 Binary files a/test/.DS_Store and /dev/null differ