diff --git a/+nla/+edge/+result/Base.m b/+nla/+edge/+result/Base.m index 0d6a18c1..2cb85374 100755 --- a/+nla/+edge/+result/Base.m +++ b/+nla/+edge/+result/Base.m @@ -40,10 +40,7 @@ function output(obj, net_atlas, flags, prob_label) matrix_plot.displayImage(); w = matrix_plot.image_dimensions("image_width"); h = matrix_plot.image_dimensions("image_height"); - - if ~isfield(flags, 'display_sig') - flags.display_sig = true; - end +% if flags.display_sig if ~exist('prob_label', 'var') prob_label = [sprintf('Edge-level Significance (P < %g)', obj.prob_max), prob_label_appended]; diff --git a/+nla/+edge/+test/Precalculated.m b/+nla/+edge/+test/Precalculated.m index 6930141f..562fd9a5 100755 --- a/+nla/+edge/+test/Precalculated.m +++ b/+nla/+edge/+test/Precalculated.m @@ -37,7 +37,7 @@ inputs = {... NumberWithoutDefault('coeff_min', 'Coeff minimum', -Inf, Inf),... NumberWithoutDefault('coeff_max', 'Coeff maximum', -Inf, Inf),... - nla.inputField.NetworkAtlas(),... + inputField.NetworkAtlas(),... EdgeLevelMatrix('precalc_obs_p', 'Precalculated observed significance (thresholded p-value)', npairs_x_1),... EdgeLevelMatrix('precalc_obs_coeff', 'Precalculated observed coeff', npairs_x_1),... EdgeLevelMatrix('precalc_perm_p', 'Precalculated permuted significance (thresholded p-value)', npairs_x_nperms),... diff --git a/+nla/+edge/+test/WelchT.m b/+nla/+edge/+test/WelchT.m index 0c0f334d..f2376612 100755 --- a/+nla/+edge/+test/WelchT.m +++ b/+nla/+edge/+test/WelchT.m @@ -29,7 +29,7 @@ x1 = input_struct.func_conn.v(:, group1); x2 = input_struct.func_conn.v(:, group2); - [p_vec, t_vec, dof_vec] = nla.welchT(x1, x2); + [p_vec, t_vec, dof_vec] = welchT(x1, x2); % Non-permuted group_names = {input_struct.group1_name, input_struct.group2_name}; diff --git a/+nla/+gfx/+plots/MatrixPlot.m b/+nla/+gfx/+plots/MatrixPlot.m index 0d91a110..65d4c49f 100644 --- a/+nla/+gfx/+plots/MatrixPlot.m +++ b/+nla/+gfx/+plots/MatrixPlot.m @@ -53,10 +53,6 @@ "Bone", "Copper", "Pink"}; % Colorbar choices end - properties (SetAccess = immutable) - original_matrix % The original matrix for scaling purposes - end - methods function obj = MatrixPlot(figure, name, matrix, networks, figure_size, varargin) % MatrixPlot constructor @@ -116,7 +112,7 @@ end end end - obj.original_matrix = matrix; + end function displayImage(obj) @@ -559,7 +555,7 @@ function createColorbar(obj, varargin) function openModal(obj, source, ~) % Callback for clicking on the colorbar. % This opens a modal with the upper and lower bounds along with a radio selector between linear and - % log. + % log. This only works for a "regular" log scale, not the -log10 scale. Still working on that one import nla.gfx.ProbPlotMethod % source is the colorbar, not the figure @@ -600,22 +596,20 @@ function openModal(obj, source, ~) uicontrol("Style", "text", "string", "Colormaps", "Units", "pixels",... "Position", [10, scaleBaseButtons.Position(2) - 45, 80, 25]); color_map_select = uicontrol('Style', 'popupmenu',... - 'Position', [100, scaleBaseButtons.Position(2) - 45, 242, 30]); + 'Position', [100, scaleBaseButtons.Position(2) - 45, 250, 30]); initial_colors = 16; colormap_html = []; for colors = 1:numel(obj.colormap_choices) colormap_function = str2func(strcat(strcat("@(x) ",lower(obj.colormap_choices{colors}), "(x)"))); CData = colormap_function(initial_colors); - new_html_start = ''; - new_html = ''; - for color_iterator = initial_colors:-1:1 + new_html = ''; + for color_iterator = 1:initial_colors hex_code = nla.gfx.rgb2hex([CData(color_iterator, 1), CData(color_iterator, 2),... CData(color_iterator, 3)]); new_html = [new_html '__']; end %new_html = new_html(1:end-2); - new_html_end = [new_html '']; - new_html = [new_html_start new_html new_html_end] + new_html = [new_html '']; colormap_html = [colormap_html; {new_html}]; end set(color_map_select, "Value", 1, "String", colormap_html); @@ -632,13 +626,12 @@ function openModal(obj, source, ~) end function applyScale(obj, ~, ~, upper_limit_box, lower_limit_box, button_group, color_map_select) + % This callback gets the colormap/scale and then applies the new bounds to the data. % Only works with APPLY button, will not work with only CLOSE import nla.net.result.NetworkResultPlotParameter nla.gfx.ProbPlotMethod - obj.matrix = obj.original_matrix; - button_group_value = get(get(button_group, "SelectedObject"), "String"); if ismember(obj.plot_scale, [ProbPlotMethod.NEG_LOG_10, ProbPlotMethod.NEG_LOG_STATISTIC]) &&... @@ -652,32 +645,29 @@ function applyScale(obj, ~, ~, upper_limit_box, lower_limit_box, button_group, c discrete_colors = NetworkResultPlotParameter().default_discrete_colors; color_map = get(color_map_select, "Value"); if button_group_value == "Linear" - new_color_map = NetworkResultPlotParameter.getColormap(discrete_colors, get(upper_limit_box, "String"),... + obj.color_map = NetworkResultPlotParameter.getColormap(discrete_colors, get(upper_limit_box, "String"),... obj.colormap_choices{color_map}); obj.plot_scale = ProbPlotMethod.DEFAULT; elseif button_group_value == "Log" - new_color_map = NetworkResultPlotParameter.getLogColormap(discrete_colors, obj.matrix, get(upper_limit_box, "String"), obj.colormap_choices{color_map}); + obj.color_map = NetworkResultPlotParameter.getLogColormap(discrete_colors, obj.matrix, get(upper_limit_box, "String"), obj.colormap_choices{color_map}); obj.plot_scale = ProbPlotMethod.LOG; else color_map_name = str2func(lower(obj.colormap_choices{color_map})); - new_color_map = color_map_name(discrete_colors); + obj.color_map = color_map_name(discrete_colors); obj.plot_scale = ProbPlotMethod.NEG_LOG_10; end - obj.color_map = new_color_map; obj.embiggenMatrix(get(lower_limit_box, "String"), get(upper_limit_box, "String")); obj.createColorbar(get(lower_limit_box, "String"), get(upper_limit_box, "String")); end function chunk_color = getChunkColor(obj, chunk_raw, upper_value, lower_value) % Get color for the chunk (square) - chunk_color = nla.gfx.valToColor(chunk_raw, lower_value, upper_value, obj.color_map); chunk_color(isnan(chunk_raw)) = NaN; % puts all NaNs back removed with valToColor end function applyColorToData(obj, position_x, position_y, chunk_height, chunk_width, chunk_color) % Fill in the chunks (squares) with color - obj.image_display.CData(position_y:position_y + chunk_height - 1, position_x:position_x + chunk_width - 1, :) =... repelem(chunk_color, obj.elementSize(), obj.elementSize()); obj.image_display.CData(position_y + chunk_height, position_x:position_x + chunk_width - 1, :) =... diff --git a/+nla/+gfx/ProbPlotMethod.m b/+nla/+gfx/ProbPlotMethod.m index dd675d32..4237eb53 100755 --- a/+nla/+gfx/ProbPlotMethod.m +++ b/+nla/+gfx/ProbPlotMethod.m @@ -1,5 +1,5 @@ classdef ProbPlotMethod enumeration - DEFAULT, LOG, NEG_LOG_10, STATISTIC, LOG_STATISTIC, NEG_LOG_STATISTIC + DEFAULT, LOG, NEG_LOG_10, STATISITC, LOG_STATISTIC, NEG_LOG_STATISTIC end end \ No newline at end of file diff --git a/+nla/+gfx/anatToMesh.m b/+nla/+gfx/anatToMesh.m index 9e78ff06..f06b7d75 100755 --- a/+nla/+gfx/anatToMesh.m +++ b/+nla/+gfx/anatToMesh.m @@ -30,7 +30,7 @@ % rotate right hemi around and move to position for visualization cmL = mean(mesh_l, 1); cmR = mean(mesh_r, 1); - rm = nla.helpers.rotationMatrix(nla.Dir.Z, pi); + rm = nla.helpers.rotationMatrix(Dir.Z, pi); % Rotate switch view_pos diff --git a/+nla/+gfx/drawBrainVis.m b/+nla/+gfx/drawBrainVis.m index b9e845bd..a38535b8 100755 --- a/+nla/+gfx/drawBrainVis.m +++ b/+nla/+gfx/drawBrainVis.m @@ -16,8 +16,7 @@ function drawBrainVis(edge_input_struct, input_struct, net_atlas, ctx, mesh_alph fc_exists = isfield(edge_input_struct, 'func_conn'); - color_fc = false; % short term fix for NET-167 - % color_fc = fc_exists; + color_fc = fc_exists; show_ROI_centroids = true; if isfield(input_struct, 'show_ROI_centroids') diff --git a/+nla/+helpers/rotationMatrix.m b/+nla/+helpers/rotationMatrix.m index e3536034..ac57cdd7 100755 --- a/+nla/+helpers/rotationMatrix.m +++ b/+nla/+helpers/rotationMatrix.m @@ -1,8 +1,6 @@ function mat = rotationMatrix(dir, theta) % Generate a rotation matrix for the direction given % an angle (in radians). - import nla.Dir - mat = zeros(3); switch dir diff --git a/+nla/+inputField/NetworkAtlas.m b/+nla/+inputField/NetworkAtlas.m index f58eb062..7aa59d97 100755 --- a/+nla/+inputField/NetworkAtlas.m +++ b/+nla/+inputField/NetworkAtlas.m @@ -24,7 +24,7 @@ end function [w, h] = draw(obj, x, y, parent, fig) - import nla.inputField.LABEL_GAP nla.inputField.LABEL_H nla.inputField.widthOfString + import nla.inputField.LABEL_GAP nla.inputField.LABEL_H nla.inputFieldwidthOfString import nla.gfx.MeshType obj.fig = fig; diff --git a/+nla/+net/+result/+chord/ChordPlotter.m b/+nla/+net/+result/+chord/ChordPlotter.m index b8a6918d..3a18f537 100644 --- a/+nla/+net/+result/+chord/ChordPlotter.m +++ b/+nla/+net/+result/+chord/ChordPlotter.m @@ -32,7 +32,7 @@ function generateChordFigure(obj, parameters, chord_type) % generateChordFigure plots chords for a network test - import nla.gfx.SigType nla.net.result.plot.PermutationTestPlotter nla.gfx.EdgeChordPlotMethod + import nla.gfx.SigType nla.net.result.plot.NoPermutationPlotter nla.gfx.EdgeChordPlotMethod coefficient_bounds = [0, parameters.p_value_plot_max]; if parameters.significance_type == SigType.INCREASING && parameters.p_value_plot_max < 1 @@ -79,7 +79,7 @@ function generateChordFigure(obj, parameters, chord_type) end % Plot Trimatrix with the chord plots - plotter = PermutationTestPlotter(obj.network_atlas); + plotter = NoPermutationPlotter(obj.network_atlas); plotter.plotProbability(plot_figure, parameters, 25, obj.bottom_text_height); obj.generatePlotText(plot_figure, chord_type); @@ -185,7 +185,7 @@ function generateEdgeChordFigure(obj, plot_figure, parameters, chord_type) end chord_plotter = nla.gfx.chord.ChordPlot(obj.network_atlas, plot_axis, 450, clipped_values, 'chord_type', chord_type,... - 'direction', significance_type, 'color_map', color_map, 'lower_limit', coefficient_min, 'upper_limit', coefficient_max); + 'direction', significance_type, 'color_map', color_map, 'lower_limit', coefficient_min, 'upper_limit', coefficient_min); chord_plotter.drawChords(); setTitle(plot_axis, main_title); diff --git a/+nla/+net/+result/+plot/PermutationTestPlotter.m b/+nla/+net/+result/+plot/PermutationTestPlotter.m deleted file mode 100644 index 2a934633..00000000 --- a/+nla/+net/+result/+plot/PermutationTestPlotter.m +++ /dev/null @@ -1,85 +0,0 @@ -classdef PermutationTestPlotter < handle - - properties - network_atlas - end - - methods - function obj = PermutationTestPlotter(network_atlas) - if nargin > 0 - obj.network_atlas = network_atlas; - end - end - - function [w, h] = plotProbability(obj, plot_figure, parameters, x_coordinate, y_coordinate) - color_map = parameters.color_map; - statistic_matrix = parameters.statistic_plot_matrix; - p_value_max = parameters.p_value_plot_max; - plot_label = parameters.name_label; - significance_plot = parameters.significance_plot; - clickCallback = parameters.callback; - plot_scale = parameters.plot_scale; - - matrix_plot = nla.gfx.plots.MatrixPlot(plot_figure, plot_label, statistic_matrix, obj.network_atlas.nets,... - nla.gfx.FigSize.SMALL, 'x_position', x_coordinate, 'y_position', y_coordinate, 'lower_limit', 0,... - 'upper_limit', p_value_max, 'color_map', color_map, 'network_clicked_callback', clickCallback,... - 'marked_networks', significance_plot, 'plot_scale', plot_scale); - matrix_plot.displayImage(); - w = matrix_plot.image_dimensions("image_width"); - h = matrix_plot.image_dimensions("image_height"); - end - - function plotProbabilityVsNetworkSize(obj, parameters, axes, plot_title) - import nla.gfx.setTitle - - network_size = parameters.network_size; - least_squares_line_coefficients = parameters.least_squares_line_coefficients; - negative_log10_statistics = parameters.negative_log10_statistics; - rho = parameters.rho; - p_values = parameters.p_values; - - % p_values vs network-pair size - plot(network_size.v, negative_log10_statistics, "ok"); - - % least-squares regression line - least_squares_line_x = linspace(axes.XLim(1), axes.XLim(2), 2); - least_squares_line_y = polyval(least_squares_line_coefficients, least_squares_line_x); - hold("on"); - plot(least_squares_line_x, least_squares_line_y, "r"); - - xlabel(axes, "Number of ROI pairs within network pair"); - ylabel(axes, "-log_1_0(Asymptotic P-value)"); - setTitle(axes, plot_title); - second_title = sprintf('Check if P-values correlate with net-pair size\n(corr: p = %.2f, r = %.2f)', p_values, rho); - setTitle(axes, second_title, true); - lims = ylim(axes); - ylim(axes, [0 lims(2)]); - end - - function plotProbabilityHistogram(obj, axes, histogram_data, statistic_input, no_permutations_network_result, test_method,... - probability_max) - import nla.HistBin - - empirical_fdr = cumsum(double(histogram_data) ./ sum(histogram_data)); - - [~, minimum_index] = min(abs(probability_max - empirical_fdr)); - - statistic_max = HistBin.EDGES(minimum_index); - - if (empirical_fdr(minimum_index) > probability_max) && minimum_index > 1 - statistic_max = HistBin.EDGES(minimum_index - 1); - end - loglog(axes, HistBin.EDGES(2:end), empirical_fdr, "k"); - hold("on"); - loglog(axes, no_permutations_network_result, statistic_input, "ok"); - axis([min(no_permutations_network_result), 1, min(statistic_input), 1]); - loglog(axes, axes.XLim, [probability_max, probability_max], "b"); - loglog(axes, [statistic_max, statistic_max], axes.YLim, "r"); - - name_label = sprintf("%s P-values", test_method); - nla.gfx.setTitle(axes, name_label); - xlabel(axes, "Asymptotic"); - ylabel(axes, "Permutation-based P-value"); - end - end -end \ No newline at end of file diff --git a/+nla/+net/+result/NetworkResultPlotParameter.m b/+nla/+net/+result/NetworkResultPlotParameter.m index a16d1f8d..5e62efc9 100644 --- a/+nla/+net/+result/NetworkResultPlotParameter.m +++ b/+nla/+net/+result/NetworkResultPlotParameter.m @@ -9,7 +9,7 @@ properties (Dependent) test_methods - noncorrelation_input_tests + noncorrelation_input_test_names number_of_networks end @@ -29,9 +29,9 @@ function result = plotProbabilityParameters(obj, edge_test_options, edge_test_result, test_method, plot_statistic,... plot_title, fdr_correction, significance_filter) % plot_title - this will be a string - % plot_statistic - this is the stat that will be plotted + % plot_statistic - this is the stat that will be plotted, string % significance filter - this will be a boolean or some sort of object (like Cohen's D > D-value) - % fdr_correction - a struct of fdr_correction (found in nla.net.mcc) + % fdr_correction - a struct of fdr_correction (found in nla.net.mcc) or None % test_method - 'no permutations', 'within network pair', 'full connectome' import nla.TriMatrix nla.TriMatrixDiag @@ -73,8 +73,7 @@ % determine colormap and operate on values if it's -log10 switch obj.updated_test_options.prob_plot_method case nla.gfx.ProbPlotMethod.LOG - color_map = nla.net.result.NetworkResultPlotParameter.getLogColormap(obj.default_discrete_colors,... - statistic_input, p_value_max); + color_map = nla.net.result.NetworkResultPlotParameter.getLogColormap(obj.default_discrete_colors, statistic_input, p_value_max); % Here we take a -log10 and change the maximum value to show on the plot case nla.gfx.ProbPlotMethod.NEG_LOG_10 color_map = parula(obj.default_discrete_colors); @@ -89,8 +88,7 @@ end significance_type = nla.gfx.SigType.INCREASING; otherwise - color_map = nla.net.result.NetworkResultPlotParameter.getColormap(obj.default_discrete_colors,... - p_value_max); + color_map = nla.net.result.NetworkResultPlotParameter.getColormap(obj.default_discrete_colors, p_value_max); end % callback function for brain image. @@ -102,7 +100,7 @@ function brainFigureButtonCallback(network1, network2) wait_popup = waitbar(0.05, wait_text); nla.gfx.drawBrainVis(edge_test_options, obj.updated_test_options, obj.network_atlas,... nla.gfx.MeshType.STD, 0.25, 3, true, edge_test_result, network1, network2,... - any(strcmp(obj.noncorrelation_input_tests, obj.network_test_results.test_name))); + any(strcmp(obj.noncorrelation_input_test_names, obj.network_test_results.test_name))); waitbar(0.95); close(wait_popup); end @@ -142,8 +140,8 @@ function brainFigureButtonCallback(network1, network2) value = obj.network_test_results.test_methods; end - function value = get.noncorrelation_input_tests(obj) - value = obj.network_test_results.noncorrelation_input_tests; + function value = get.noncorrelation_input_test_names(obj) + value = obj.network_test_results.noncorrelation_input_test_names; end function value = get.number_of_networks(obj) @@ -201,7 +199,6 @@ function brainFigureButtonCallback(network1, network2) color_map_name = str2func(lower(color_map)); color_map_base = color_map_name(default_discrete_colors); end - default_color_map = [1 1 1]; if p_value_max == 0 color_map = default_color_map; diff --git a/+nla/+net/+result/NetworkTestResult.m b/+nla/+net/+result/NetworkTestResult.m index becfe670..51565159 100644 --- a/+nla/+net/+result/NetworkTestResult.m +++ b/+nla/+net/+result/NetworkTestResult.m @@ -80,7 +80,7 @@ function output(obj, edge_test_options, updated_test_options, network_atlas, edg result_plot_parameters = NetworkResultPlotParameter(obj, network_atlas, updated_test_options); % Cohen's D results for markers - cohens_d_filter = TriMatrix(network_atlas.numNets, 'logical', TriMatrixDiag.KEEP_DIAGONAL); + cohens_d_filter = TriMatrix(network_atlas.numNets(), 'logical', TriMatrixDiag.KEEP_DIAGONAL); if ~obj.is_noncorrelation_input cohens_d_filter.v = (obj.full_connectome.d.v >= updated_test_options.d_max); end @@ -142,10 +142,9 @@ function concatenateResult(obj, other_object) obj.last_index = obj.last_index + 1; end - % I'm assuming this is Get Significance Matrix. It's used for the convergence plots button, but the naming makes zero sense - % Any help on renaming would be great. function [test_number, significance_count_matrix, names] = getSigMat(obj, network_test_options, network_atlas, flags) - + % I'm assuming this is Get Significance Matrix. It's used for the convergence plots button, but the naming makes zero sense + % Any help on renaming would be great. import nla.TriMatrix nla.TriMatrixDiag test_number = 0; @@ -172,11 +171,6 @@ function concatenateResult(obj, other_object) names, significance, name); end - %% This is taken directly from old version to maintain functionality. Not sure anyone uses it. - function table_new = generateSummaryTable(obj, table_old) - table_new = [table_old, table(obj.full_connectome.p_value.v, 'VariableNames', [obj.test_name + "P-value"])]; - end - %% % getters for dependent properties function value = get.permutation_count(obj) @@ -203,9 +197,16 @@ function concatenateResult(obj, other_object) function createResultsStorage(obj, test_options, number_of_networks, test_specific_statistics) %CREATERESULTSSTORAGE Create the substructures for the methods chosen - % We're just doing them all! The ranking is so short compared to the data collection, just do them all - setup_test_methods = ["no_permutations", "full_connectome", "within_network_pair"]; + % no_permutations always runs + setup_test_methods = ["no_permutations"]; + % if within_network_pair is being run, than full connectome is/can also be done + % if only full_connectome is being run, then we don't run within_net_pair + if isfield(test_options, "within_net_pair") && test_options.within_net_pair + setup_test_methods = [setup_test_methods, "full_connectome", "within_network_pair"]; + elseif isfield(test_options, "full_connectome") && test_options.full_connectome + setup_test_methods = [setup_test_methods, "full_connectome"]; + end % create the results containers. This replaces the false boolean with a struct of TriMatrices for test_method_index = 1:numel(setup_test_methods) obj.createPValueTriMatrices(number_of_networks, setup_test_methods(test_method_index)); @@ -260,7 +261,7 @@ function createPValueTriMatrices(obj, number_of_networks, test_method) end function noPermutationsPlotting(obj, plot_parameters, edge_test_options, edge_test_result, updated_test_options, flags) - import nla.gfx.createFigure nla.net.result.plot.PermutationTestPlotter nla.net.result.chord.ChordPlotter + import nla.gfx.createFigure nla.net.result.plot.NoPermutationPlotter nla.net.result.chord.ChordPlotter plot_test_type = "no_permutations"; @@ -277,7 +278,7 @@ function noPermutationsPlotting(obj, plot_parameters, edge_test_options, edge_te p_value_vs_network_size_parameters = plot_parameters.plotProbabilityVsNetworkSize("no_permutations",... p_value); - plotter = PermutationTestPlotter(plot_parameters.network_atlas); + plotter = NoPermutationPlotter(plot_parameters.network_atlas); % don't need to create a reference to axis since drawMatrixOrg takes a figure as a reference % plot the probability @@ -301,9 +302,9 @@ function noPermutationsPlotting(obj, plot_parameters, edge_test_options, edge_te end function fullConnectomePlotting(obj, network_atlas, edge_test_options, edge_test_result, updated_test_options, cohens_d_filter, flags) - import nla.gfx.createFigure nla.net.result.NetworkResultPlotParameter nla.net.result.plot.PermutationTestPlotter + import nla.gfx.createFigure nla.net.result.NetworkResultPlotParameter nla.net.result.plot.FullConnectomePlotter import nla.net.result.chord.ChordPlotter - + plot_test_type = "full_connectome"; plot_title = sprintf("Full Connectome Method\nNetwork vs. Connectome Significance"); @@ -335,7 +336,7 @@ function fullConnectomePlotting(obj, network_atlas, edge_test_options, edge_test % create a histogram p_value_histogram = obj.createHistogram(p_value); - plotter = PermutationTestPlotter(edge_test_options.net_atlas); + plotter = FullConnectomePlotter(edge_test_options.net_atlas); % With the way subplot works, we have to do the plotting this way. I tried assigning variables to the subplots, % but then the plots get put under different layers. @@ -381,7 +382,7 @@ function fullConnectomePlotting(obj, network_atlas, edge_test_options, edge_test end function withinNetworkPairPlotting(obj, network_atlas, edge_test_options, edge_test_result, updated_test_options, cohens_d_filter, flags) - import nla.gfx.createFigure nla.net.result.NetworkResultPlotParameter nla.net.result.plot.PermutationTestPlotter + import nla.gfx.createFigure nla.net.result.NetworkResultPlotParameter nla.net.result.plot.WithinNetworkPairPlotter import nla.net.result.chord.ChordPlotter plot_test_type = "within_network_pair"; @@ -406,7 +407,7 @@ function withinNetworkPairPlotting(obj, network_atlas, edge_test_options, edge_t if flags.plot_type == nla.PlotType.FIGURE - plotter = PermutationTestPlotter(edge_test_options.net_atlas); + plotter = WithinNetworkPairPlotter(edge_test_options.net_atlas); y_coordinate = 425; if obj.is_noncorrelation_input plot_figure = createFigure(500, 900); @@ -447,22 +448,6 @@ function withinNetworkPairPlotting(obj, network_atlas, edge_test_options, edge_t p_value = strcat("single_sample_", p_value); end end - - % I don't really know what these do and haven't really thought about it. Hence the bad naming. - function [sig, name] = singleSigMat(obj, network_atlas, edge_test_options, p_value, mcc_method, title_prefix) - p_value_max = mcc_method.correct(network_atlas, edge_test_options, p_value); - p_breakdown_labels = mcc_method.createLabel(network_atlas, edge_test_options, p_value); - - sig = nla.TriMatrix(network_atlas.numNets(), 'double', nla.TriMatrixDiag.KEEP_DIAGONAL); - sig.v = (p_value.v < p_value_max); - name = sprintf("%s %s P < %.2g (%s)", title_prefix, obj.test_display_name, p_value_max, p_breakdown_labels); - end - - function [number_of_tests, sig_count_mat, names] = appendSignificanceMatrix(obj, number_of_tests, sig_count_mat, names, sig, name) - number_of_tests = number_of_tests + 1; - sig_count_mat.v = sig_count_mat.v + sig.v; - names = [names name]; - end end methods (Static) @@ -471,11 +456,8 @@ function withinNetworkPairPlotting(obj, network_atlas, edge_test_options, edge_t % thresholds etc. for summary statistics, or generally can be % modified without requiring re-permutation) import nla.inputField.Integer nla.inputField.Number - options = {... - Integer('behavior_count', 'Test count:', 1, 1, Inf),... - Number('prob_max', 'Net-level P threshold <', 0, 0.05, 1),... - Number('d_max', "Cohen's D threshold >", 0, 0.5, 1),... - }; + options = {Integer('behavior_count', 'Test count:', 1, 1, Inf),... + Number('prob_max', 'Net-level P threshold <', 0, 0.05, 1)}; end end end \ No newline at end of file diff --git a/+nla/+net/+test/ChiSquaredTest.m b/+nla/+net/+test/ChiSquaredTest.m index 36e6c795..830a0112 100644 --- a/+nla/+net/+test/ChiSquaredTest.m +++ b/+nla/+net/+test/ChiSquaredTest.m @@ -23,7 +23,7 @@ permutation_results = "no_permutations"; chi2_statistic = "chi2_statistic"; greater_than_expected = "greater_than_expected"; - if isequal(permutations, true) + if permutations % Otherwise, add it on to the back of the 'permutation_results' structure permutation_results = "permutation_results"; chi2_statistic = strcat(chi2_statistic, "_permutations"); @@ -44,7 +44,7 @@ network_ROI_count = numel(network_pair_ROI_significance); observed_significance = sum(network_pair_ROI_significance); expected_significance = edge_test_results.avg_prob_sig * network_ROI_count; - chi2_value = ((observed_significance - expected_significance) .^ 2) .* ((expected_significance .^ -1)); %legacy style, AS 240529 + chi2_value = ((observed_significance - expected_significance) .^ 2) ./ expected_significance; result.(permutation_results).(chi2_statistic).set(network, network2, chi2_value); result.(permutation_results).(greater_than_expected).set(network, network2, observed_significance > expected_significance); end diff --git a/+nla/+net/+test/HyperGeometricTest.m b/+nla/+net/+test/HyperGeometricTest.m index 5d1e7eb2..df4b4217 100644 --- a/+nla/+net/+test/HyperGeometricTest.m +++ b/+nla/+net/+test/HyperGeometricTest.m @@ -24,7 +24,7 @@ permutation_results = "no_permutations"; greater_than_expected = "greater_than_expected"; p_value = "p_value"; - if isequal(permutations, true) + if permutations % Otherwise, add it on to the back of the 'permutation_results' structure permutation_results = "permutation_results"; greater_than_expected = strcat(greater_than_expected, "_permutations"); diff --git a/+nla/+net/+test/KolmogorovSmirnovTest.m b/+nla/+net/+test/KolmogorovSmirnovTest.m index c9edf125..224c9db0 100644 --- a/+nla/+net/+test/KolmogorovSmirnovTest.m +++ b/+nla/+net/+test/KolmogorovSmirnovTest.m @@ -27,7 +27,7 @@ ks_statistic = "ks_statistic"; single_sample_p_value = "single_sample_p_value"; single_sample_ks_statistic = "single_sample_ks_statistic"; - if isequal(permutations, true) + if permutations % Otherwise, add it on to the back of the 'permutation_results' structure permutation_results = "permutation_results"; p_value = strcat(p_value, "_permutations"); @@ -60,10 +60,9 @@ methods (Static) function inputs = requiredInputs() - inputs = {... - nla.inputField.Integer('behavior_count', 'Test count:', 1, 1, Inf),... + inputs = {nla.inputField.Integer('behavior_count', 'Test count:', 1, 1, Inf),... nla.inputField.Number('prob_max', 'Net-level P threshold <', 0, 0.05, 1),... - }; + nla.inputField.Number('d_max', "Net-level Cohen's D threshold >", 0, 0.5, 1);}; end end end \ No newline at end of file diff --git a/+nla/+net/+test/StudentTTest.m b/+nla/+net/+test/StudentTTest.m index 730a16ae..1867d5be 100644 --- a/+nla/+net/+test/StudentTTest.m +++ b/+nla/+net/+test/StudentTTest.m @@ -27,7 +27,7 @@ t_statistic = "t_statistic"; single_sample_p_value = "single_sample_p_value"; single_sample_t_statistic = "single_sample_t_statistic"; - if isequal(permutations, true) + if permutations % Otherwise, add it on to the back of the 'permutation_results' structure permutation_results = "permutation_results"; p_value = strcat(p_value, "_permutations"); @@ -60,10 +60,9 @@ methods (Static) function inputs = requiredInputs() - inputs = {... - nla.inputField.Integer('behavior_count', 'Test count:', 1, 1, Inf),... - nla.inputField.Number('prob_max', 'Net-level P threshold <', 0, 0.05, 1),... - }; + inputs = {nla.inputField.Integer('behavior_count', 'Test count:', 1, 1, Inf),... + nla.inputField.Number('prob_max', 'Net-level P threshold <', 0, 0.05, 1),... + nla.inputField.Number('d_max', "Net-level Cohen's D threshold >", 0, 0.5, 1);}; end end end \ No newline at end of file diff --git a/+nla/+net/+test/WelchTTest.m b/+nla/+net/+test/WelchTTest.m index 7f464a90..30d87cea 100644 --- a/+nla/+net/+test/WelchTTest.m +++ b/+nla/+net/+test/WelchTTest.m @@ -29,7 +29,7 @@ t_statistic = "t_statistic"; single_sample_p_value = "single_sample_p_value"; single_sample_t_statistic = "single_sample_t_statistic"; - if isequal(permutations, true) + if permutations % Otherwise, add it on to the back of the 'permutation_results' structure permutation_results = "permutation_results"; p_value = strcat(p_value, "_permutations"); @@ -47,11 +47,11 @@ network_rho = edge_test_results.coeff.get(network_atlas.nets(network).indexes,... network_atlas.nets(network2).indexes); - [p, t_stat, ~] = nla.welchT(network_rho, edge_test_results.coeff.v); + [~, p, ~, stats] = ttest2(network_rho, edge_test_results.coeff.v, "Vartype", "unequal"); [~, single_sample_p, ~, single_sample_stats] = ttest(network_rho); result.(permutation_results).(p_value).set(network, network2, p); - result.(permutation_results).(t_statistic).set(network, network2, t_stat); + result.(permutation_results).(t_statistic).set(network, network2, stats.tstat); result.(permutation_results).(single_sample_p_value).set(network, network2, single_sample_p); result.(permutation_results).(single_sample_t_statistic).set(network, network2, single_sample_stats.tstat); end @@ -62,10 +62,9 @@ methods (Static) function inputs = requiredInputs() - inputs = {... - nla.inputField.Integer('behavior_count', 'Test count:', 1, 1, Inf),... + inputs = {nla.inputField.Integer('behavior_count', 'Test count:', 1, 1, Inf),... nla.inputField.Number('prob_max', 'Net-level P threshold <', 0, 0.05, 1),... - }; + nla.inputField.Number('d_max', "Net-level Cohen's D threshold >", 0, 0.5, 1);}; end end end \ No newline at end of file diff --git a/+nla/+net/+test/WilcoxonTest.m b/+nla/+net/+test/WilcoxonTest.m index e8b33023..596f97a8 100644 --- a/+nla/+net/+test/WilcoxonTest.m +++ b/+nla/+net/+test/WilcoxonTest.m @@ -28,7 +28,7 @@ z_statistic = "z_statistic"; single_sample_p_value = "single_sample_p_value"; single_sample_ranksum_statistic = "single_sample_ranksum_statistic"; - if isequal(permutations, true) + if permutations % Otherwise, add it on to the back of the 'permutation_results' structure permutation_results = "permutation_results"; p_value = strcat(p_value, "_permutations"); @@ -63,10 +63,9 @@ methods (Static) function inputs = requiredInputs() - inputs = {... - nla.inputField.Integer('behavior_count', 'Test count:', 1, 1, Inf),... + inputs = {nla.inputField.Integer('behavior_count', 'Test count:', 1, 1, Inf),... nla.inputField.Number('prob_max', 'Net-level P threshold <', 0, 0.05, 1),... - }; + nla.inputField.Number('d_max', "Net-level Cohen's D threshold >", 0, 0.5, 1)}; end end end \ No newline at end of file diff --git a/+nla/+net/ResultRank.m b/+nla/+net/ResultRank.m index a6bf7748..b33d89d3 100644 --- a/+nla/+net/ResultRank.m +++ b/+nla/+net/ResultRank.m @@ -24,104 +24,70 @@ end function ranking_result = rank(obj) - - ranking_result = obj.permuted_network_results.copy(); - - % Ranking + % Copy the nonpermuted network results to put the permuted results into after ranking + ranking_result = obj.nonpermuted_network_results.copy(); + if ~isequal(obj.permuted_network_results.full_connectome, false) + for fieldname = fieldnames(obj.permuted_network_results.permutation_results)' + ranking_result.permutation_results.(fieldname{1}) = obj.permuted_network_results.permutation_results.(fieldname{1}); + end + end + % Experiment wide ranking if obj.permuted_network_results.test_display_name ~= "Cohen's D" ranking_result = obj.basicRank(ranking_result); end end function ranking = basicRank(obj, ranking) - ranking_statistic = false; - if obj.permuted_network_results.test_display_name ~= "Hypergeometric" % Hypergeomtric has no stat to rank + if obj.permuted_network_results.test_display_name ~= "Hypergeometric" ranking_statistic = obj.permuted_network_results.ranking_statistic; end - % Full Connectome ranking - - ranking = obj.fullConnectomeRank(ranking, ranking_statistic); + % Experiment Wide ranking + ranking = obj.experimentWideRank(ranking, ranking_statistic); % Network Pair ranking - ranking = obj.withinNetworkPairRank(ranking, ranking_statistic); + ranking = obj.networkPairRank(ranking, ranking_statistic); end - function ranking = fullConnectomeRank(obj, ranking, ranking_statistic) - + function ranking = experimentWideRank(obj, ranking, ranking_statistic) probability = "p_value"; - no_permutation_result = obj.nonpermuted_network_results.no_permutations; - permutation_results = obj.permuted_network_results.permutation_results; - - for index = 1:numel(no_permutation_result.(probability).v) + for index = 1:numel(obj.nonpermuted_network_results.no_permutations.(probability).v) % statistic ranking if obj.permuted_network_results.test_display_name ~= "Hypergeometric" - combined_statistics = [... - permutation_results.(strcat(ranking_statistic, "_permutations")).v(:);... - no_permutation_result.(ranking_statistic).v(index)... - ]; - ranking.full_connectome.statistic_p_value.v(index) = sum(... - abs(squeeze(combined_statistics)) >= abs(no_permutation_result.(ranking_statistic).v(index))... - ) / (1 + obj.permutations * obj.number_of_network_pairs); + combined_statistics = [obj.permuted_network_results.permutation_results.(strcat(ranking_statistic, "_permutations")).v(:); obj.nonpermuted_network_results.no_permutations.(ranking_statistic).v(index)]; + ranking.full_connectome.statistic_p_value.v(index) = sum(abs(squeeze(combined_statistics)) >= abs(obj.nonpermuted_network_results.no_permutations.(ranking_statistic).v(index))) / (1 + obj.permutations * obj.number_of_network_pairs); end % p-value ranking - combined_probabilities = [... - permutation_results.(strcat(probability, "_permutations")).v(:);... - no_permutation_result.(probability).v(index)... - ]; + combined_probabilities = [obj.permuted_network_results.permutation_results.(strcat(probability, "_permutations")).v(:); obj.nonpermuted_network_results.no_permutations.(probability).v(index)]; [~, sorted_combined_probabilites] = sort(combined_probabilities); - ranking.full_connectome.p_value.v(index) = find(... - squeeze(sorted_combined_probabilites) == 1 + obj.permutations * obj.number_of_network_pairs... - ) / (1 + obj.permutations * obj.number_of_network_pairs); + ranking.full_connectome.p_value.v(index) = find(squeeze(sorted_combined_probabilites) == 1 + obj.permutations * obj.number_of_network_pairs) / (1 + obj.permutations * obj.number_of_network_pairs); end - ranking.full_connectome.d.v = obj.permuted_network_results.full_connectome.d.v; end - function ranking = withinNetworkPairRank(obj, ranking, ranking_statistic) - + function ranking = networkPairRank(obj, ranking, ranking_statistic) if ~any(strcmp(obj.permuted_network_results.test_name, obj.permuted_network_results.noncorrelation_input_tests)) single_sample_probability = "single_sample_p_value"; single_sample_statistic = strcat("single_sample_", ranking_statistic); - - no_permutation_result = obj.nonpermuted_network_results.no_permutations; - permutation_results = obj.permuted_network_results.permutation_results; - if obj.permuted_network_results.test_name == "wilcoxon" single_sample_statistic = "single_sample_ranksum_statistic"; end - - for index = 1:numel(no_permutation_result.(single_sample_probability).v) + for index = 1:numel(obj.nonpermuted_network_results.no_permutations.(single_sample_probability).v) % statistic ranking - combined_statistics = [... - permutation_results.(strcat(single_sample_statistic, "_permutations")).v(index, :),... - no_permutation_result.(single_sample_statistic).v(index)... - ]; - ranking.within_network_pair.statistic_single_sample_p_value.v(index) = sum(... - abs(squeeze(combined_statistics)) >= abs(no_permutation_result.(single_sample_statistic).v(index))... - ) / (1 + obj.permutations); - - % p-value ranking - combined_probabilities = [... - permutation_results.(strcat(single_sample_probability, "_permutations")).v(index, :),... - no_permutation_result.(single_sample_probability).v(index)... - ]; + combined_statistics = [obj.permuted_network_results.permutation_results.(strcat(single_sample_statistic, "_permutations")).v(index, :), obj.nonpermuted_network_results.no_permutations.(single_sample_statistic).v(index)]; + ranking.within_network_pair.single_sample_statistic_p_value.v(index) = sum(abs(squeeze(combined_statistics)) >= abs(obj.nonpermuted_network_results.no_permutations.(single_sample_statistic).v(index))) / (1 + obj.permutations); + % p-value ranking + combined_probabilities = [obj.permuted_network_results.permutation_results.(strcat(single_sample_probability, "_permutations")).v(index, :), obj.nonpermuted_network_results.no_permutations.(single_sample_probability).v(index)]; [~, sorted_combined_probabilites] = sort(combined_probabilities); - ranking.within_network_pair.single_sample_p_value.v(index) = find(... - squeeze(sorted_combined_probabilites) == 1 + obj.permutations... - ) / (1 + obj.permutations); + ranking.within_network_pair.single_sample_p_value.v(index) = find(squeeze(sorted_combined_probabilites) == 1 + obj.permutations) / (1 + obj.permutations); end - - elseif isstruct(obj.permuted_network_results.within_network_pair) &&... - any(strcmp(obj.permuted_network_results.test_name, obj.permuted_network_results.noncorrelation_input_tests)) + elseif isstruct(obj.permuted_network_results.within_network_pair) && any(strcmp(obj.permuted_network_results.test_name, obj.permuted_network_results.noncorrelation_input_tests)) % This condition catches Chi-Squared and Hypergeometric tests. We do not do within network ranking for them, we just copy % the full connectome ranking over. - ranking.within_network_pair.single_sample_p_value = ranking.full_connectome.p_value; + ranking.permuted_network_results.within_network_pair.single_sample_p_value = ranking.permuted_network_results.full_connectome.p_value; end - ranking.within_network_pair.d.v = obj.permuted_network_results.within_network_pair.d.v; end - % This takes the above statistic and gets the property to use its size to find the number of permutations function value = get.permutations(obj) - value = size(obj.permuted_network_results.permutation_results.p_value_permutations.v, 2); + value = size(obj.permuted_network_results.permutation_results.p_value_permutations.v, 2); % This takes the above statistic and gets the property to use its size to find the number of permutations end end end \ No newline at end of file diff --git a/+nla/+net/genBaseInputs.m b/+nla/+net/genBaseInputs.m old mode 100644 new mode 100755 index 26d19d36..5ca8af44 --- a/+nla/+net/genBaseInputs.m +++ b/+nla/+net/genBaseInputs.m @@ -1,5 +1,12 @@ function inputs = genBaseInputs() %GENBASEINPUTS Generate struct of required network-level inputs with +<<<<<<< HEAD + % reasonable default values + + inputs = struct('nonpermuted', true, 'full_conn', true, 'within_net_pair', true, 'prob_plot_method',... + nla.gfx.ProbPlotMethod.DEFAULT, 'ranking_method', nla.RankingMethod.P_VALUE, 'edge_chord_plot_method',... + nla.gfx.EdgeChordPlotMethod.PROB, 'fdr_correction', nla.net.mcc.Bonferroni(), 'd_thresh_chord_plot', true); +======= % default values inputs = struct(... 'nonpermuted', true,... @@ -11,4 +18,6 @@ 'fdr_correction', nla.net.mcc.Bonferroni(),... 'd_thresh_chord_plot', true... ); -end \ No newline at end of file +>>>>>>> development +end + diff --git a/+nla/+net/unittests/ChiSquaredTestResult.mat b/+nla/+net/unittests/ChiSquaredTestResult.mat index d9840409..e74e6323 100644 Binary files a/+nla/+net/unittests/ChiSquaredTestResult.mat and b/+nla/+net/unittests/ChiSquaredTestResult.mat differ diff --git a/+nla/+net/unittests/NetworkResultPlotParameterTestCase.m b/+nla/+net/unittests/NetworkResultPlotParameterTestCase.m index 8f0299aa..824574b0 100644 --- a/+nla/+net/unittests/NetworkResultPlotParameterTestCase.m +++ b/+nla/+net/unittests/NetworkResultPlotParameterTestCase.m @@ -28,7 +28,6 @@ function loadInputData(testCase) testCase.edge_test_options = struct(); testCase.edge_test_options.coeff_max = 2; testCase.edge_test_options.coeff_min = -2; - testCase.edge_test_options.iteration = 0; precalculated_path = strcat(testCase.root_path, fullfile('examples', 'precalculated/')); @@ -46,8 +45,8 @@ function loadInputData(testCase) testCase.edge_test_options.precalc_perm_coeff = TriMatrix(testCase.network_atlas.numROIs); testCase.edge_test_options.precalc_perm_coeff.v = permutation_coefficient_file.SIM_perm_coeff; % For unit tests, we're only going to use 10 permutations so they don't take forever - testCase.edge_test_options.precalc_perm_p.v = testCase.edge_test_options.precalc_perm_p.v(:, 1:10); - testCase.edge_test_options.precalc_perm_coeff.v = testCase.edge_test_options.precalc_perm_coeff.v(:, 1:10); + testCase.edge_test_options.precalc_perm_p.v = testCase.edge_test_options.precalc_perm_p.v(1:10); + testCase.edge_test_options.precalc_perm_coeff.v = testCase.edge_test_options.precalc_perm_coeff.v(1:10); testCase.edge_test_options.net_atlas = testCase.network_atlas; testCase.edge_test_options.prob_max = 0.05; @@ -67,7 +66,6 @@ function loadInputData(testCase) testCase.edge_test_result = testCase.tests.runEdgeTest(testCase.edge_test_options); testCase.network_test_result = testCase.tests.runNetTests(testCase.network_test_options,... testCase.edge_test_result, testCase.network_atlas, false); - testCase.edge_test_options.iteration = 1; testCase.permutation_results = testCase.tests.runPerm(testCase.edge_test_options, testCase.network_test_options,... testCase.network_atlas, testCase.edge_test_result, testCase.network_test_result,... permutations); @@ -161,5 +159,56 @@ function plotProbabilityParametersNegLogTest(testCase) testCase.verifyEqual(expected_significance_type, probability_parameters.significance_type); testCase.verifyEqual(expected_color_map, probability_parameters.color_map); end + + function getColormapTest(testCase) + import nla.net.result.NetworkResultPlotParameter + + default_colors = 1000; + p_value_max = 1; + default_color_map = [1 1 1]; + parula_color_map = [flip(parula(default_colors)); default_color_map]; + + test_color_map = NetworkResultPlotParameter.getColormap(default_colors, p_value_max); + testCase.verifyEqual(parula_color_map, test_color_map); + + test_color_map = NetworkResultPlotParameter.getColormap(default_colors, 0); + testCase.verifyEqual(default_color_map, test_color_map); + + color_map_name = "cool"; + color_map_function = str2func(color_map_name); + result_color_map = [flip(color_map_function(default_colors)); default_color_map]; + + test_color_map = NetworkResultPlotParameter.getColormap(default_colors, p_value_max, color_map_name); + testCase.verifyEqual(result_color_map, test_color_map); + end + + function getLogColormapTest(testCase) + import nla.net.result.NetworkResultPlotParameter + + permutation_result = testCase.permutation_results.permutation_network_test_results{1}.full_connectome.p_value; + log_min = max([-40, log10(min(nonzeros(permutation_result.v)))]); + + default_colors = 1000; + p_value_max = 1; + default_color_map = [1 1 1]; + parula_color_map = parula(default_colors); + + result_color_map = flip(parula_color_map(ceil(logspace(log_min, 0, default_colors) .* default_colors), :)); + + test_color_map = NetworkResultPlotParameter.getLogColormap(default_colors, permutation_result, p_value_max); + testCase.verifyEqual(test_color_map, [result_color_map; default_color_map]); + + color_map_name = "cool"; + color_map_function = str2func(color_map_name); + cool_color_map = color_map_function(default_colors); + result_color_map = flip(cool_color_map(ceil(logspace(log_min, 0, default_colors) .* default_colors), :)); + + test_color_map = NetworkResultPlotParameter.getLogColormap(default_colors, permutation_result, p_value_max,... + color_map_name); + testCase.verifyEqual(test_color_map, [result_color_map; default_color_map]) + + test_color_map = NetworkResultPlotParameter.getLogColormap(default_colors, permutation_result, 0); + testCase.verifyEqual(test_color_map, default_color_map); + end end end \ No newline at end of file diff --git a/+nla/+net/unittests/ResultRankTestCase.m b/+nla/+net/unittests/ResultRankTestCase.m index d99cf649..08f66caf 100644 --- a/+nla/+net/unittests/ResultRankTestCase.m +++ b/+nla/+net/unittests/ResultRankTestCase.m @@ -102,16 +102,16 @@ function fullConnectomeRankTest(testCase) result_ranker = nla.net.ResultRank(testCase.network_test_result{1}, testCase.permuted_network_results{1},... testCase.number_of_network_pairs); ranking = testCase.permuted_network_results{1}.copy(); - ranking = result_ranker.fullConnectomeRank(ranking, testCase.permuted_network_results{1}.ranking_statistic); + ranking = result_ranker.experimentWideRank(ranking, testCase.permuted_network_results{1}.ranking_statistic); testCase.verifyEqual(ranking.full_connectome.p_value.v, testCase.ranking.full_connectome.p_value.v); end - function withinNetworkPairTest(testCase) + function networkPairTest(testCase) result_ranker = nla.net.ResultRank(testCase.network_test_result{1}, testCase.permuted_network_results{1},... testCase.number_of_network_pairs); ranking = testCase.permuted_network_results{1}.copy(); - ranking = result_ranker.withinNetworkPairRank(ranking, testCase.permuted_network_results{1}.ranking_statistic); + ranking = result_ranker.networkPairRank(ranking, testCase.permuted_network_results{1}.ranking_statistic); testCase.verifyEqual(ranking.within_network_pair.p_value.v, testCase.ranking.within_network_pair.p_value.v); end diff --git a/+nla/+tests/TestPoolTest.m b/+nla/+tests/TestPoolTest.m index 28139d64..49a23d54 100644 --- a/+nla/+tests/TestPoolTest.m +++ b/+nla/+tests/TestPoolTest.m @@ -14,6 +14,10 @@ function loadTestData(testCase) testCase.variables.edge_results_perm = edge_results_perm; load(fullfile('nla', 'tests', 'networkInputStruct'), 'net_input_struct'); testCase.variables.net_input_struct = net_input_struct; + load(fullfile('nla', 'tests', 'networkResultsNonPermuted'), 'net_results_nonperm'); + testCase.variables.net_results_nonperm = net_results_nonperm; + load(fullfile('nla', 'tests', 'networkResultsPermuted'), 'net_results_perm'); + testCase.variables.net_results_perm = net_results_perm; load(fullfile('nla', 'tests', 'networkAtlas'), 'net_atlas'); testCase.variables.net_atlas = net_atlas; end @@ -33,5 +37,93 @@ function permutationEdgeTest(testCase) permuted_edge_results = test_pool.runEdgeTestPerm(testCase.variables.input_struct, 20, 1); testCase.verifyEqual(permuted_edge_results, testCase.variables.edge_results_perm); end + + function chiSquaredPermutationTest(testCase) + import nla.TestPool nla.net.test.ChiSquared + + test_pool = TestPool(); + test_pool.net_tests{1} = ChiSquared(); + network_level_results = test_pool.runNetTestsPerm(testCase.variables.net_input_struct, testCase.variables.net_atlas, testCase.variables.edge_results_perm); + nonpermuted_network_results = {}; + nonpermuted_network_results{1} = testCase.variables.net_results_nonperm{1}; + network_results_ranked = test_pool.rankResults(testCase.variables.input_struct, nonpermuted_network_results, network_level_results, testCase.variables.net_atlas.numNetPairs()); + testCase.verifyEqual(network_results_ranked{1}, testCase.variables.net_results_perm{1}); + end + + function cohenDPermutationTest(testCase) + import nla.TestPool nla.net.test.CohenD + + test_pool = TestPool(); + test_pool.net_tests{1} = CohenD(); + network_level_results = test_pool.runNetTestsPerm(testCase.variables.net_input_struct, testCase.variables.net_atlas, testCase.variables.edge_results_perm); + nonpermuted_network_results = {}; + nonpermuted_network_results{1} = testCase.variables.net_results_nonperm{2}; + network_results_ranked = test_pool.rankResults(testCase.variables.input_struct, nonpermuted_network_results, network_level_results, testCase.variables.net_atlas.numNetPairs()); + + % The following line is due to an error in creation of CohenD results. Since this doesn't technically exist, every value is 1/(1+permutations). The permutation result sets them to zero. We set them equal to pass + testCase.variables.net_results_perm{2}.within_np_prob.v = network_results_ranked{1}.within_np_prob.v; + + testCase.verifyEqual(network_results_ranked{1}, testCase.variables.net_results_perm{2}); + end + + function hyperGeoPermutationTest(testCase) + import nla.TestPool nla.net.test.HyperGeo + + test_pool = TestPool(); + test_pool.net_tests{1} = HyperGeo(); + network_level_results = test_pool.runNetTestsPerm(testCase.variables.net_input_struct, testCase.variables.net_atlas, testCase.variables.edge_results_perm); + nonpermuted_network_results = {}; + nonpermuted_network_results{1} = testCase.variables.net_results_nonperm{3}; + network_results_ranked = test_pool.rankResults(testCase.variables.input_struct, nonpermuted_network_results, network_level_results, testCase.variables.net_atlas.numNetPairs()); + testCase.verifyEqual(network_results_ranked{1}, testCase.variables.net_results_perm{3}); + end + + function kolmogorovSmirnovPermutationTest(testCase) + import nla.TestPool nla.net.test.KolmogorovSmirnov + + test_pool = TestPool(); + test_pool.net_tests{1} = KolmogorovSmirnov(); + network_level_results = test_pool.runNetTestsPerm(testCase.variables.net_input_struct, testCase.variables.net_atlas, testCase.variables.edge_results_perm); + nonpermuted_network_results = {}; + nonpermuted_network_results{1} = testCase.variables.net_results_nonperm{4}; + network_results_ranked = test_pool.rankResults(testCase.variables.input_struct, nonpermuted_network_results, network_level_results, testCase.variables.net_atlas.numNetPairs()); + testCase.verifyEqual(network_results_ranked{1}, testCase.variables.net_results_perm{4}); + end + + function studentTPermutationTest(testCase) + import nla.TestPool nla.net.test.StudentT + + test_pool = TestPool(); + test_pool.net_tests{1} = StudentT(); + network_level_results = test_pool.runNetTestsPerm(testCase.variables.net_input_struct, testCase.variables.net_atlas, testCase.variables.edge_results_perm); + nonpermuted_network_results = {}; + nonpermuted_network_results{1} = testCase.variables.net_results_nonperm{5}; + network_results_ranked = test_pool.rankResults(testCase.variables.input_struct, nonpermuted_network_results, network_level_results, testCase.variables.net_atlas.numNetPairs()); + testCase.verifyEqual(network_results_ranked{1}, testCase.variables.net_results_perm{5}); + end + + function welchTPermutationTest(testCase) + import nla.TestPool nla.net.test.WelchT + + test_pool = TestPool(); + test_pool.net_tests{1} = WelchT(); + network_level_results = test_pool.runNetTestsPerm(testCase.variables.net_input_struct, testCase.variables.net_atlas, testCase.variables.edge_results_perm); + nonpermuted_network_results = {}; + nonpermuted_network_results{1} = testCase.variables.net_results_nonperm{6}; + network_results_ranked = test_pool.rankResults(testCase.variables.input_struct, nonpermuted_network_results, network_level_results, testCase.variables.net_atlas.numNetPairs()); + testCase.verifyEqual(network_results_ranked{1}, testCase.variables.net_results_perm{6}); + end + + function wilcoxonPermutationTest(testCase) + import nla.TestPool nla.net.test.Wilcoxon + + test_pool = TestPool(); + test_pool.net_tests{1} = Wilcoxon(); + network_level_results = test_pool.runNetTestsPerm(testCase.variables.net_input_struct, testCase.variables.net_atlas, testCase.variables.edge_results_perm); + nonpermuted_network_results = {}; + nonpermuted_network_results{1} = testCase.variables.net_results_nonperm{7}; + network_results_ranked = test_pool.rankResults(testCase.variables.input_struct, nonpermuted_network_results, network_level_results, testCase.variables.net_atlas.numNetPairs()); + testCase.verifyEqual(network_results_ranked{1}, testCase.variables.net_results_perm{7}); + end end end \ No newline at end of file diff --git a/+nla/ResultPool.m b/+nla/ResultPool.m index 96dab4c6..24c7df0c 100755 --- a/+nla/ResultPool.m +++ b/+nla/ResultPool.m @@ -38,11 +38,10 @@ function output(obj) flags.show_within_net_pair = true; %Add to display net results as nla.PlotType.FIGURE (ADE 20221121) flags.plot_type = nla.PlotType.FIGURE; - if ~islogical(obj.permutation_network_test_results) - for i = 1:numel(obj.permutation_network_test_results) - obj.network_test_results{i}.output(obj.test_options, obj.network_test_options, obj.network_atlas,... - obj.edge_test_results, flags); - obj.permutation_network_test_results{i}.output(obj.test_options, obj.network_test_options,... + if ~islogical(obj.network_test_results) + for i = 1:numel(obj.network_test_results) + obj.network_test_results{i}.output(obj.network_test_options, obj.network_atlas, obj.edge_test_results, flags); + obj.permutation_network_test_results{i}.output(obj.network_test_options,... obj.network_atlas, obj.edge_test_results, flags); end end @@ -78,7 +77,7 @@ function saveSummaryTable(obj, filename) network_pairs2 = TriMatrix(network_pairs2_matrix, TriMatrixDiag.KEEP_DIAGONAL); summary_table = table(network_pairs.v, network_pairs2.v, 'VariableNames', ["Network 1", "Network 2"]); for i = 1:numel(obj.permutation_network_test_results) - summary_table = obj.permutation_network_test_results{i}.generateSummaryTable(summary_table); + summary_table = obj.permutation_network_test_results{i}.genSummaryTable(summary_table); end writetable(summary_table, filename, 'Delimiter', '\t'); diff --git a/+nla/TestPool.m b/+nla/TestPool.m index f8f2390e..9d86b2f9 100755 --- a/+nla/TestPool.m +++ b/+nla/TestPool.m @@ -27,129 +27,156 @@ methods function obj = TestPool() + % this MUST be instantiated here it cannot be done in the + % properties field because NLA cannot be imported when setting + % things in the properties field, hence, NLA specific values + % cannot be assigned unless you want it to break if they use + % this toolbox anywhere outside of the NetworkLevelAnalysis + % folder. obj.edge_test = nla.edge.test.Pearson(); end - function result = runPerm(obj, edge_input_struct, net_input_struct, network_atlas, nonpermuted_edge_test_results,... - nonpermuted_network_test_results, num_perms, perm_seed, separate_network_and_edge_tests) - + function result = runPerm(obj, edge_input_struct, net_input_struct, net_atlas, edge_result_nonperm, net_results_nonperm, num_perms, perm_seed) if ~exist('perm_seed', 'var') perm_seed = false; end - if ~exist('separate_network_and_edge_tests', 'var') - separate_network_and_edge_tests = false; - end - - if isequal(separate_network_and_edge_tests, false) - [permuted_edge_test_results, permuted_network_test_results] = obj.runEdgeAndNetPerm(edge_input_struct,... - net_input_struct, network_atlas, nonpermuted_edge_test_results, num_perms, perm_seed); - else - [permuted_edge_test_results, permuted_network_test_results] = obj.runPermSeparateEdgeAndNet(edge_input_struct,... - net_input_struct, network_atlas, num_perms, perm_seed); - end + [edge_results_perm, net_results_perm] = obj.runEdgeAndNetPerm(edge_input_struct, net_input_struct, ... + net_atlas, edge_result_nonperm, net_results_nonperm, num_perms, perm_seed); - ranked_permuted_network_test_results = obj.collateNetworkPermutationResults(nonpermuted_edge_test_results, network_atlas,... - nonpermuted_network_test_results, permuted_network_test_results, net_input_struct); - - result = nla.ResultPool(edge_input_struct, net_input_struct, network_atlas, nonpermuted_edge_test_results,... - nonpermuted_network_test_results, permuted_edge_test_results, ranked_permuted_network_test_results); + result = nla.ResultPool(edge_input_struct, net_input_struct, net_atlas, edge_result_nonperm, net_results_nonperm, edge_results_perm, net_results_perm); end - function ranked_results = collateNetworkPermutationResults(obj, nonpermuted_edge_test_results, network_atlas, nonpermuted_network_test_results,... - permuted_network_test_results, input_struct) + function result = runPermSeparateAllEdgeAndAllNet(obj, input_struct, net_input_struct, net_atlas, edge_result_nonperm, net_results_nonperm, num_perms, perm_seed) + %This is code that first runs all edge permutations, and then + %runs all net permutations + %NOTE: This currently involves saving all edge results from all + %permutations in the working results object + if ~exist('perm_seed', 'var') + perm_seed = false; + end + edge_results_perm = obj.runEdgeTestPerm(input_struct, num_perms, perm_seed); + net_results_perm = obj.runNetTestsPerm(net_input_struct, net_atlas, net_results_nonperm, edge_results_perm, edge_result_nonperm); + result = nla.ResultPool(input_struct, net_input_struct, net_atlas, edge_result_nonperm, net_results_nonperm, edge_results_perm, net_results_perm); + end + + function [edge_results_perm, net_results_perm] = runEdgeAndNetPerm(obj, edge_input_struct, net_input_struct, net_atlas, edge_result_nonperm, net_results_nonperm, num_perms, perm_seed) + if ~exist('perm_seed', 'var') || islogical(perm_seed) + rng(posixtime(datetime())); + perm_seed = randi(intmax('uint32'), 'uint32'); + end - % Run Cohen's D - cohen_d_test = nla.net.CohenDTest(); - - % Warning: Hacky code. Because of the way non-permuted network tests and permuted are called from the front, they are stored - % in different objects. (Notice the input argument for non-permuted network results). Eventually, it should probably be done - % that we do them all here. That may be another ticket. For now, we're copying over. +[num_procs, blocks] = obj.initializeParallelPool(num_perms); + + + parfor proc = 1:num_procs + net_result_block = cell(numNetTests(obj), 1); + + for i = 1:numNetTests(obj) + net_result_block{i} = copy(net_results_nonperm{i}); + end + obj.runEdgeAndNetPermBlock(edge_input_struct, net_input_struct, net_atlas, net_result_block, blocks(proc), blocks(proc+1), perm_seed); + net_result_blocks{proc} = net_result_block; + end + + edge_results_perm = nla.edge.result.PermBase(); + edge_results_perm.perm_count = num_perms; + % and net level result chunks + net_results_perm = {}; for test_index = 1:numNetTests(obj) - permuted_network_test_results{test_index} = cohen_d_test.run(nonpermuted_edge_test_results, network_atlas,... - permuted_network_test_results{test_index}); + for proc_index = 1:num_procs + cur_proc_net_results = net_result_blocks{proc_index}; + cur_test_net_results(proc_index) = cur_proc_net_results(test_index); + end + net_results_perm{test_index} = cur_test_net_results{1}; + net_results_perm{test_index}.merge(net_input_struct, edge_result_nonperm, edge_results_perm, net_atlas, {cur_test_net_results{2:end}}); end - for test_index = 1:numNetTests(obj) - for test_index2 = 1:numNetTests(obj) - if nonpermuted_network_test_results{test_index2}.test_name == permuted_network_test_results{test_index}.test_name - permuted_network_test_results{test_index}.no_permutations = nonpermuted_network_test_results{test_index2}.no_permutations; - break - end + + end + + function net_result_block = runEdgeAndNetPermBlock(obj, edge_input_struct, net_input_struct, net_atlas, net_result_block, block_start, block_end, perm_seed) + + + for iteration = block_start:block_end - 1 + % set RNG per-iteration based on the random seed and + % iteration number, so the # of processes doesn't impact + % the result(important for repeatability if running + % permutations with the same seed intentionally) + rng(bitxor(perm_seed, iteration)); + permuted_input = edge_input_struct.permute_method.permute(edge_input_struct); + permuted_input.iteration = iteration; + + single_edge_result = obj.runEdgeTest(permuted_input); + %net_input_struct.iteration = iteration; + obj.runNetTests(net_input_struct, single_edge_result, net_atlas, net_result_block); + + if ~islogical(obj.data_queue) + send(obj.data_queue, iteration); end end - - ranked_results = obj.rankResults(input_struct, nonpermuted_network_test_results,... - permuted_network_test_results, network_atlas.numNetPairs()); + end - - function [permuted_edge_results, permuted_network_results] = runEdgeAndNetPerm(obj, edge_input_struct, net_input_struct,... - net_atlas, edge_result_nonperm, num_perms, perm_seed) + + function edge_result_perm = runEdgeTestPerm(obj, input_struct, num_perms, perm_seed) + % Optional perm_seed parameter for replicating runs. If not + % passed in, is set from current date/time and thus will + % produce different results, assuming you don't run it twice at + % the same time + if ~exist('perm_seed', 'var') || islogical(perm_seed) + rng(posixtime(datetime())); + perm_seed = randi(intmax('uint32'), 'uint32'); + end + + [num_procs, blocks] = obj.initializeParallelPool(num_perms); - % get current parallel pool or start a new one - [number_of_processes, blocks] = obj.initializeParallelPool(num_perms); - parfor process = 1:number_of_processes - network_result_block = obj.runEdgeAndNetPermBlock(edge_input_struct, net_input_struct, net_atlas,... - blocks(process), blocks(process+1), perm_seed); - network_result_blocks{process} = network_result_block; + parfor proc = 1:num_procs + net_result_block = cell(numNetTests(obj), 1); + + for i = 1:numNetTests(obj) + net_result_block{i} = copy(net_results_nonperm{i}); + end + obj.runEdgeAndNetPermBlock(edge_input_struct, net_input_struct, net_atlas, net_result_block, blocks(proc), blocks(proc+1), perm_seed); + net_result_blocks{proc} = net_result_block; end - permuted_edge_results = nla.edge.result.PermBase(); - permuted_edge_results.perm_count = num_perms; + edge_results_perm = nla.edge.result.PermBase(); + edge_results_perm.perm_count = num_perms; % and net level result chunks - permuted_network_results = network_result_blocks{1}; - for process = 2:number_of_processes - current_network_test_results = network_result_blocks{process}; - for test_index = 1:numNetTests(obj) - current_test_network_result = current_network_test_results(test_index); - permuted_network_results{test_index}.merge(current_test_network_result); + net_results_perm = {}; + for test_index = 1:numNetTests(obj) + for proc_index = 1:num_procs + cur_proc_net_results = net_result_blocks{proc_index}; + cur_test_net_results(proc_index) = cur_proc_net_results(test_index); end + net_results_perm{test_index} = cur_test_net_results{1}; + net_results_perm{test_index}.merge(net_input_struct, edge_result_nonperm, edge_results_perm, net_atlas, {cur_test_net_results{2:end}}); end + end - - function network_result_block = runEdgeAndNetPermBlock(obj, edge_input_struct, net_input_struct, net_atlas,... - block_start, block_end, perm_seed) + function net_result_block = runEdgeAndNetPermBlock(obj, edge_input_struct, net_input_struct, net_atlas, net_result_block, block_start, block_end, perm_seed) + + for iteration = block_start:block_end - 1 - rng(iteration); + % set RNG per-iteration based on the random seed and + % iteration number, so the # of processes doesn't impact + % the result(important for repeatability if running + % permutations with the same seed intentionally) + rng(bitxor(perm_seed, iteration)); permuted_input = edge_input_struct.permute_method.permute(edge_input_struct); permuted_input.iteration = iteration; single_edge_result = obj.runEdgeTest(permuted_input); - network_results = obj.runNetTests(net_input_struct, single_edge_result, net_atlas, true); + %net_input_struct.iteration = iteration; + obj.runNetTests(net_input_struct, single_edge_result, net_atlas, net_result_block); - % Ugh, this is so horrible. Have to do this due to Matlab not being able to index 2D arrays separately among - % indexes - if iteration - block_start + 1 == 1 - for test = 1:numNetTests(obj) - network_result_block{test} = copy(network_results{test}); - end - else - for test = 1:numNetTests(obj) - network_result_block{test}.merge(network_results{test}); - end - end - if ~islogical(obj.data_queue) send(obj.data_queue, iteration); end end - end - - function [permuted_edge_test_results, permuted_network_test_results] = runPermSeparateEdgeAndNet(obj, input_struct, net_input_struct,... - network_atlas, num_perms, perm_seed) - %This is code that first runs all edge permutations, and then - %runs all net permutations - %NOTE: This currently involves saving all edge results from all - %permutations in the working results object - if ~exist('perm_seed', 'var') - perm_seed = false; - end - edge_results_perm = obj.runEdgeTestPerm(input_struct, num_perms, perm_seed); - net_results_perm = obj.runNetTestsPerm(net_input_struct, net_atlas, net_results_nonperm, edge_results_perm, edge_result_nonperm); - result = nla.ResultPool(input_struct, net_input_struct, net_atlas, edge_result_nonperm, net_results_nonperm, edge_results_perm, net_results_perm); end function edge_result_perm = runEdgeTestPerm(obj, input_struct, num_perms, perm_seed) @@ -200,8 +227,8 @@ send(obj.data_queue, iteration); end end - end - + end + function edge_result = runEdgeTest(obj, input_struct) if ~isfield(input_struct, 'iteration') input_struct.iteration = 0; @@ -273,12 +300,11 @@ function ranked_results = rankResults(obj, input_options, nonpermuted_network_test_results, permuted_network_results, number_of_network_pairs) import nla.net.ResultRank - ranked_results = permuted_network_results; + ranked_results = cell(1, numNetTests(obj)); for test = 1:numNetTests(obj) ranker = ResultRank(nonpermuted_network_test_results{test}, permuted_network_results{test}, number_of_network_pairs); ranked_results_object = ranker.rank(); ranked_results{test} = ranked_results_object; - ranked_results{test}.permutation_results = permuted_network_results{test}.permutation_results; end end end diff --git a/+nla/genTests.m b/+nla/genTests.m index b2a277e4..406515df 100755 --- a/+nla/genTests.m +++ b/+nla/genTests.m @@ -3,11 +3,11 @@ % subpackage: dot-seperated subpackage name within NLA namespace, eg. % 'net.test' for net-level tests root_path = nla.findRootPath(); - relative_path = strrep(subpackage, '.', '/+'); - path_to = [root_path '+nla/+' relative_path]; - network_tests_struct = dir(path_to); - network_test_folder_contents = {network_tests_struct.name}; - network_test_filenames = network_test_folder_contents(~[network_tests_struct.isdir]); + rel_path = strrep(subpackage, '.', '/+'); + path_to = [root_path '+nla/+' rel_path]; + net_test_struct = dir(path_to); + net_test_folder_fnames = {net_test_struct.name}; + net_test_fnames = net_test_folder_fnames(~[net_test_struct.isdir]); tests = {}; for i = 1:numel(network_test_filenames) diff --git a/+nla/welchT.m b/+nla/welchT.m index d6481fd5..dcc6c4da 100755 --- a/+nla/welchT.m +++ b/+nla/welchT.m @@ -1,16 +1,8 @@ function [p_vec, t_vec, dof_vec] = welchT(x1, x2) %WELCHT 2-sample Welch T-test %% Prepare data - x1_size = size(x1); - if x1_size(end) == 1 - x1_size(end) = []; - end - - x2_size = size(x2); - if x2_size(end) == 1 - x2_size(end) = []; - end - + x1_size = size(x1); if x1_size(end) == 1, x1_size(end) = []; end + x2_size = size(x2); if x2_size(end) == 1, x2_size(end) = []; end ndim = length(x1_size); %% Means diff --git a/NLAResult.mlapp b/NLAResult.mlapp index b347128b..596f482c 100644 Binary files a/NLAResult.mlapp and b/NLAResult.mlapp differ diff --git a/NLAResult_exported.m b/NLAResult_exported.m index aa0ed10d..454ae403 100644 --- a/NLAResult_exported.m +++ b/NLAResult_exported.m @@ -2,32 +2,32 @@ % Properties that correspond to app components properties (Access = public) - UIFigure matlab.ui.Figure - FileMenu matlab.ui.container.Menu - SaveButton matlab.ui.container.Menu - ResultTree matlab.ui.container.Tree - FlipNestingButton matlab.ui.control.Button - EdgeLevelLabel matlab.ui.control.Label - ViewEdgeLevelButton matlab.ui.control.Button - NetLevelLabel matlab.ui.control.Label - RunButton matlab.ui.control.Button - DisplaySelectedButton matlab.ui.control.Button - NetlevelplottingDropDownLabel matlab.ui.control.Label - NetlevelplottingDropDown matlab.ui.control.DropDown - DisplayConvergenceButton matlab.ui.control.Button + UIFigure matlab.ui.Figure + FileMenu matlab.ui.container.Menu + SaveButton matlab.ui.container.Menu + ResultTree matlab.ui.container.Tree + FlipNestingButton matlab.ui.control.Button + EdgeLevelLabel matlab.ui.control.Label + ViewEdgeLevelButton matlab.ui.control.Button + NetLevelLabel matlab.ui.control.Label + RunButton matlab.ui.control.Button + DisplaySelectedButton matlab.ui.control.Button + NetlevelpvalueplottingDropDownLabel matlab.ui.control.Label + NetlevelpvalueplottingDropDown matlab.ui.control.DropDown + DisplayConvergenceButton matlab.ui.control.Button ConvergencecolormapDropDownLabel matlab.ui.control.Label - ColormapDropDown matlab.ui.control.DropDown - DisplayChordNet matlab.ui.control.Button - DisplayChordEdge matlab.ui.control.Button - SaveSummaryTable matlab.ui.control.Button - EdgelevelchordplottingLabel matlab.ui.control.Label - EdgeLevelTypeDropDown matlab.ui.control.DropDown - AdjustableNetParamsPanel matlab.ui.container.Panel + ColormapDropDown matlab.ui.control.DropDown + DisplayChordNet matlab.ui.control.Button + DisplayChordEdge matlab.ui.control.Button + SaveSummaryTable matlab.ui.control.Button + EdgelevelchordplottingLabel matlab.ui.control.Label + EdgeLevelTypeDropDown matlab.ui.control.DropDown + TweakNetParamsPanel matlab.ui.container.Panel MultiplecomparisonscorrectionLabel matlab.ui.control.Label - FDRCorrection matlab.ui.control.DropDown + FDRCorrection matlab.ui.control.DropDown showROIcentroidsinbrainplotsCheckBox matlab.ui.control.CheckBox CohensDthresholdchordplotsCheckBox matlab.ui.control.CheckBox - BranchLabel matlab.ui.control.Label + BranchLabel matlab.ui.control.Label end @@ -39,7 +39,7 @@ results = false nesting_by_method = true prog_bar = false - net_adjustable_fields + net_tweakable_fields cur_iter = 0 end @@ -90,57 +90,58 @@ function setNesting(app, nesting_by_method) if nesting_by_method if app.net_input_struct.nonpermuted root = app.createNode(app.ResultTree, 'Non-permuted'); - for i = 1:size(app.results.network_test_results, 2) - result = app.results.network_test_results{i}; - % All our tests have non-permuted data - flags = struct(); - flags.show_nonpermuted = true; - app.createNode(root, result.test_display_name, {result, flags}); + for i = 1:size(app.results.net_results, 2) + result = app.results.net_results{i}; + if result.has_nonpermuted + flags = struct(); + flags.show_nonpermuted = true; + app.createNode(root, result.name, {result, flags}); + end end end if app.net_input_struct.full_conn root = app.createNode(app.ResultTree, 'Full connectome'); - for i = 1:size(app.results.permutation_network_test_results, 2) - result = app.results.permutation_network_test_results{i}; - if ~isequal(result.full_connectome, false) + for i = 1:size(app.results.perm_net_results, 2) + result = app.results.perm_net_results{i}; + if result.has_full_conn flags = struct(); flags.show_full_conn = true; - app.createNode(root, result.test_display_name, {result, flags}); + app.createNode(root, result.name, {result, flags}); end end end if app.net_input_struct.within_net_pair root = app.createNode(app.ResultTree, 'Within Net-pair'); - for i = 1:size(app.results.permutation_network_test_results, 2) - result = app.results.permutation_network_test_results{i}; - if ~isequal(result.within_network_pair, false) + for i = 1:size(app.results.perm_net_results, 2) + result = app.results.perm_net_results{i}; + if result.has_within_net_pair flags = struct(); flags.show_within_net_pair = true; - app.createNode(root, result.test_display_name, {result, flags}); + app.createNode(root, result.name, {result, flags}); end end end else - for i = 1:size(app.results.network_test_results, 2) - root = app.createNode(app.ResultTree, app.results.network_test_results{i}.test_display_name); + for i = 1:size(app.results.net_results, 2) + root = app.createNode(app.ResultTree, app.results.net_results{i}.name); - result = app.results.network_test_results{i}; - if app.net_input_struct.nonpermuted + result = app.results.net_results{i}; + if app.net_input_struct.nonpermuted && result.has_nonpermuted flags = struct(); flags.show_nonpermuted = true; app.createNode(root, 'Non-permuted', {result, flags}); end if app.net_input_struct.full_conn && result.has_full_conn - perm_result = app.results.permutation_network_test_results{i}; - if app.net_input_struct.full_conn && ~isequal(result.full_connectome, false) + perm_result = app.results.perm_net_results{i}; + if app.net_input_struct.full_conn && result.has_full_conn flags = struct(); flags.show_full_conn = true; app.createNode(root, 'Full connectome', {perm_result, flags}); end - if app.net_input_struct.within_net_pair && ~isequal(result.within_network_pair, false) + if app.net_input_struct.within_net_pair && result.has_within_net_pair flags = struct(); flags.show_within_net_pair = true; app.createNode(root, 'Within Net-pair', {perm_result, flags}); @@ -152,12 +153,10 @@ function setNesting(app, nesting_by_method) function updateProgPermStats(app, ~) if ~islogical(app.prog_bar) + app.cur_iter = app.cur_iter + 1; - if app.cur_iter < app.net_input_struct.perm_count - app.prog_bar.Message = sprintf('Running edge-level statistics (%d/%d permutations)', mod(app.cur_iter, app.net_input_struct.perm_count), app.net_input_struct.perm_count); - else - app.prog_bar.Message = sprintf('Running net-level statistics (%d/%d permutations)', mod(app.cur_iter, app.net_input_struct.perm_count), app.net_input_struct.perm_count); - end + + app.prog_bar.Message = sprintf('Running permuted statistics (%d/%d permutations)', mod(app.cur_iter, app.net_input_struct.perm_count), app.net_input_struct.perm_count); app.prog_bar.Value = mod(app.cur_iter, app.net_input_struct.perm_count) ./ app.net_input_struct.perm_count; if app.prog_bar.CancelRequested @@ -168,7 +167,7 @@ function updateProgPermStats(app, ~) end end - function genadjustableNetParams(app) + function genTweakableNetParams(app) import nla.* % required due to matlab package system quirks % disgusting special case @@ -176,46 +175,46 @@ function genadjustableNetParams(app) app.net_input_struct.prob_max = app.net_input_struct.prob_max_original; end - results = app.results.network_test_results; + results = app.results.net_results; % required inputs to run these tests inputs = {}; for i = 1:numel(results) - inputs = cat(2, inputs, results{i}.editableOptions()); + inputs = cat(2, inputs, results{i}.tweakableInputs()); end - app.net_adjustable_fields = inputField.reduce(inputs); + app.net_tweakable_fields = inputField.reduce(inputs); % display input fields x = inputField.LABEL_GAP * 2; - y = app.AdjustableNetParamsPanel.InnerPosition(4); - for i = 1:numel(app.net_adjustable_fields) + y = app.TweakNetParamsPanel.InnerPosition(4); + for i = 1:numel(app.net_tweakable_fields) y = y - inputField.LABEL_GAP; - [w, h] = app.net_adjustable_fields{i}.draw(x, y, app.AdjustableNetParamsPanel, app.UIFigure); - app.net_adjustable_fields{i}.read(app.net_input_struct); + [w, h] = app.net_tweakable_fields{i}.draw(x, y, app.TweakNetParamsPanel, app.UIFigure); + app.net_tweakable_fields{i}.read(app.net_input_struct); y = y - h; end end - function readNetParamAdjustments(app) + function readNetParamTweaks(app) import nla.* % required due to matlab package system quirks - [error_str, satisfied] = validateInputStruct(app.net_adjustable_fields, 'Must satisfy fields:', true); + [error_str, satisfied] = validateInputStruct(app.net_tweakable_fields, 'Must satisfy fields:', true); if satisfied error_str = ""; errors_found = false; - % store adjustable fields - for i = 1:numel(app.net_adjustable_fields) - [app.net_input_struct, error] = app.net_adjustable_fields{i}.store(app.net_input_struct); + % store tweakable fields + for i = 1:numel(app.net_tweakable_fields) + [app.net_input_struct, error] = app.net_tweakable_fields{i}.store(app.net_input_struct); if ~islogical(error) - error_str = [error_str sprintf('\n - %s: %s', app.net_adjustable_fields{i}.disp_name, error)]; + error_str = [error_str sprintf('\n - %s: %s', app.net_tweakable_fields{i}.disp_name, error)]; errors_found = true; end end if errors_found - uialert(app.UIFigure, error_str, 'Error with adjustable field (using previous settings)'); + uialert(app.UIFigure, error_str, 'Error with tweakable field (using previous settings)'); else % disgusting special case if isfield(app.net_input_struct, 'prob_max') && isfield(app.net_input_struct, 'behavior_count') @@ -226,7 +225,7 @@ function readNetParamAdjustments(app) else % TODO ideally buttons would just stay greyed out until % all inputs were satisfied - uialert(app.UIFigure, error_str, 'adjustable field not satisfied (using previous settings)'); + uialert(app.UIFigure, error_str, 'Tweakable field not satisfied (using previous settings)'); end end @@ -282,18 +281,18 @@ function initFromResult(app, result, file_name) app.RunButton.Enable = false; app.RunButton.Visible = false; - enableNetButtons(app, ~islogical(result.network_test_results)); + enableNetButtons(app, ~islogical(result.net_results)); drawnow(); - if ~islogical(result.network_test_results) + if ~islogical(result.net_results) app.setNesting(true); else app.results = false; end - if ~islogical(result.network_test_results) - app.genadjustableNetParams(); + if ~islogical(result.net_results) + app.genTweakableNetParams(); end end @@ -310,13 +309,13 @@ function enableNetButtons(app, val) end if net_inputs_enabled - app.AdjustableNetParamsPanel.Enable = 'on'; + app.TweakNetParamsPanel.Enable = 'on'; else - app.AdjustableNetParamsPanel.Enable = 'off'; + app.TweakNetParamsPanel.Enable = 'off'; end % dropdowns that need net-level data to be used - net_dropdowns = {app.FDRCorrection, app.EdgeLevelTypeDropDown, app.NetlevelplottingDropDown}; + net_dropdowns = {app.FDRCorrection, app.EdgeLevelTypeDropDown, app.NetlevelpvalueplottingDropDown}; for i = 1:numel(net_dropdowns) net_dropdowns{i}.Enable = val; net_dropdowns{i}.ValueChangedFcn(app, true); @@ -326,7 +325,7 @@ function enableNetButtons(app, val) function displayManyPlots(app, extra_flags, plot_type) import nla.* % required due to matlab package system quirks - app.readNetParamAdjustments(); + app.readNetParamTweaks(); prog = uiprogressdlg(app.UIFigure, 'Title', sprintf('Generating %s', plot_type), 'Message', sprintf('Generating %s', plot_type)); prog.Value = 0.02; @@ -338,7 +337,7 @@ function displayManyPlots(app, extra_flags, plot_type) result = selected_nodes(i).NodeData{1}; node_flags = selected_nodes(i).NodeData{2}; - prog.Message = sprintf('Generating %s %s', result.test_display_name, plot_type); + prog.Message = sprintf('Generating %s %s', result.name, plot_type); result.output(app.input_struct, app.net_input_struct, app.input_struct.net_atlas, app.edge_result, helpers.mergeStruct(node_flags, extra_flags)); @@ -375,7 +374,7 @@ function startupFcn(app, test_pool, input_struct, net_input_struct) % Button pushed function: RunButton function RunButtonPushed(app, event) import nla.* % required due to matlab package system quirks - prog = uiprogressdlg(app.UIFigure, 'Title', 'Running statistics', 'Message', 'Running net-level statistics', 'Cancelable', 'on'); + prog = uiprogressdlg(app.UIFigure, 'Title', 'Running statistics', 'Message', 'Running permuted statistics', 'Cancelable', 'on'); prog.Value = 0.02; drawnow; @@ -387,7 +386,7 @@ function RunButtonPushed(app, event) gcp; - prog.Message = sprintf('Running net-level statistics (0/%d permutations)', app.net_input_struct.perm_count); + prog.Message = sprintf('Running permuted statistics (0/%d permutations)', app.net_input_struct.perm_count); prog.Value = 0; % Set handle reference @@ -422,7 +421,7 @@ function RunButtonPushed(app, event) drawnow(); app.setNesting(true); - app.genadjustableNetParams(); + app.genTweakableNetParams(); close(prog); end @@ -431,7 +430,7 @@ function RunButtonPushed(app, event) function SaveButtonPushed(app, event) import nla.* % required due to matlab package system quirks - app.readNetParamAdjustments(); + app.readNetParamTweaks(); if islogical(app.results) % save just edge-level results @@ -439,9 +438,9 @@ function SaveButtonPushed(app, event) else result = app.results; - result.test_options = app.input_struct; - result.network_test_options = app.net_input_struct; - result.edge_test_results = app.edge_result; + result.input_struct = app.input_struct; + result.net_input_struct = app.net_input_struct; + result.edge_result = app.edge_result; end [file, path] = uiputfile({'*.mat', 'Result (*.mat)'}, 'Save Result File', 'result.mat'); @@ -487,21 +486,19 @@ function DisplaySelectedButtonPushed(app, event) displayManyPlots(app, struct('plot_type', PlotType.FIGURE), 'figures'); end - % Value changed function: NetlevelplottingDropDown + % Value changed function: NetlevelpvalueplottingDropDown function PValModeDropDownValueChanged(app, event) import nla.* % required due to matlab package system quirks - value = app.NetlevelplottingDropDown.Value; + value = app.NetlevelpvalueplottingDropDown.Value; if strcmp(value, 'linear') % Plot p-values on linear scale app.net_input_struct.prob_plot_method = gfx.ProbPlotMethod.DEFAULT; - elseif strcmp(value, 'p-value log') + elseif strcmp(value, 'log') % Plot p-values on logarithmic scale app.net_input_struct.prob_plot_method = gfx.ProbPlotMethod.LOG; - elseif strcmp(value, 'p-value -log') + else % Plot p-values on negative logarithmic scale app.net_input_struct.prob_plot_method = gfx.ProbPlotMethod.NEG_LOG_10; - else - app.net_input_struct.prob_plot_method = gfx.ProbPlotMethod.STATISTIC; end end @@ -509,7 +506,7 @@ function PValModeDropDownValueChanged(app, event) function DisplayConvergenceButtonPushed(app, event) import nla.* % required due to matlab package system quirks - app.readNetParamAdjustments(); + app.readNetParamTweaks(); prog = uiprogressdlg(app.UIFigure, 'Title', sprintf('Generating convergence map'), 'Message', 'Generating net-level convergence map'); prog.Value = 0.02; @@ -551,7 +548,6 @@ function DisplayConvergenceButtonPushed(app, event) close(prog); app.moveCurrFigToParentLocation(); - %These mlapp files are really just the worst end % Button pushed function: DisplayChordNet @@ -685,18 +681,18 @@ function createComponents(app) app.DisplaySelectedButton.Position = [434 62 81 22]; app.DisplaySelectedButton.Text = 'View figures'; - % Create NetlevelplottingDropDownLabel - app.NetlevelplottingDropDownLabel = uilabel(app.UIFigure); - app.NetlevelplottingDropDownLabel.HorizontalAlignment = 'right'; - app.NetlevelplottingDropDownLabel.Position = [434 114 98 22]; - app.NetlevelplottingDropDownLabel.Text = 'Net-level plotting:'; + % Create NetlevelpvalueplottingDropDownLabel + app.NetlevelpvalueplottingDropDownLabel = uilabel(app.UIFigure); + app.NetlevelpvalueplottingDropDownLabel.HorizontalAlignment = 'right'; + app.NetlevelpvalueplottingDropDownLabel.Position = [434 114 141 22]; + app.NetlevelpvalueplottingDropDownLabel.Text = 'Net-level p-value plotting:'; - % Create NetlevelplottingDropDown - app.NetlevelplottingDropDown = uidropdown(app.UIFigure); - app.NetlevelplottingDropDown.Items = {'p-value linear', 'p-value log', 'p-value -log10', 'stat ranked'}; - app.NetlevelplottingDropDown.ValueChangedFcn = createCallbackFcn(app, @PValModeDropDownValueChanged, true); - app.NetlevelplottingDropDown.Position = [533 114 118 22]; - app.NetlevelplottingDropDown.Value = 'p-value linear'; + % Create NetlevelpvalueplottingDropDown + app.NetlevelpvalueplottingDropDown = uidropdown(app.UIFigure); + app.NetlevelpvalueplottingDropDown.Items = {'linear', 'log', '-log10'}; + app.NetlevelpvalueplottingDropDown.ValueChangedFcn = createCallbackFcn(app, @PValModeDropDownValueChanged, true); + app.NetlevelpvalueplottingDropDown.Position = [581 114 70 22]; + app.NetlevelpvalueplottingDropDown.Value = 'linear'; % Create DisplayConvergenceButton app.DisplayConvergenceButton = uibutton(app.UIFigure, 'push'); @@ -748,10 +744,10 @@ function createComponents(app) app.EdgeLevelTypeDropDown.Position = [581 89 69 22]; app.EdgeLevelTypeDropDown.Value = 'prob'; - % Create AdjustableNetParamsPanel - app.AdjustableNetParamsPanel = uipanel(app.UIFigure); - app.AdjustableNetParamsPanel.Title = 'Adjustable network-level parameters'; - app.AdjustableNetParamsPanel.Position = [434 170 416 427]; + % Create TweakNetParamsPanel + app.TweakNetParamsPanel = uipanel(app.UIFigure); + app.TweakNetParamsPanel.Title = 'Tweak net-level parameters'; + app.TweakNetParamsPanel.Position = [434 170 416 427]; % Create MultiplecomparisonscorrectionLabel app.MultiplecomparisonscorrectionLabel = uilabel(app.UIFigure); diff --git a/NLA_GUI.mlapp b/NLA_GUI.mlapp index 63f55bfe..75c73a5f 100755 Binary files a/NLA_GUI.mlapp and b/NLA_GUI.mlapp differ diff --git a/NLA_GUI_exported.m b/NLA_GUI_exported.m index ed5e40ee..c14d1ec2 100644 --- a/NLA_GUI_exported.m +++ b/NLA_GUI_exported.m @@ -128,7 +128,7 @@ function startupFcn(app) netLevelOptions = genTests('net.test'); netLevelNames = string; for i = 1:numel(netLevelOptions) - netLevelNames(i) = netLevelOptions{i}.display_name; + netLevelNames(i) = netLevelOptions{i}.name; end app.NetTestSelector.Items = netLevelNames; app.NetTestSelector.ItemsData = netLevelOptions;