From 87d156e4188389462a81b94942e1dca6d1d5dee3 Mon Sep 17 00:00:00 2001 From: Jim Pollaro Date: Fri, 5 Apr 2024 12:56:31 -0500 Subject: [PATCH 1/5] first commit --- +nla/+gfx/+plots/MatrixPlot.m | 124 ++++++++++++------ +nla/+gfx/ProbPlotMethod.m | 2 +- .../+net/+result/+plot/NoPermutationPlotter.m | 3 +- .../+net/+result/NetworkResultPlotParameter.m | 63 ++++----- 4 files changed, 123 insertions(+), 69 deletions(-) diff --git a/+nla/+gfx/+plots/MatrixPlot.m b/+nla/+gfx/+plots/MatrixPlot.m index 034368e3..3ba10bbd 100644 --- a/+nla/+gfx/+plots/MatrixPlot.m +++ b/+nla/+gfx/+plots/MatrixPlot.m @@ -30,7 +30,7 @@ axes % The axes of the plot image_display % The actual displayed values color_bar % The colorbar - colorbar_contextmenu % The right click menu for the colorbar + plot_scale % The scale and values being plotted (Linear, log, -log10, p-value, statistic p-value) end properties (Dependent) @@ -74,6 +74,7 @@ % x_position = 0 % y_position = 0 % discrete_colorbar = false + % plot_scale = nla.gfx.ProbPlotMethod.DEFAULT import nla.gfx.createFigure matrix_input_parser = inputParser; addRequired(matrix_input_parser, 'figure'); @@ -95,11 +96,12 @@ addParameter(matrix_input_parser, 'x_position', 0, validNumberInput); addParameter(matrix_input_parser, 'y_position', 0, validNumberInput); addParameter(matrix_input_parser, 'discrete_colorbar', false, @islogical); + addParameter(matrix_input_parser, 'plot_scale', nla.gfx.ProbPlotMethod.DEFAULT, @isenum); parse(matrix_input_parser, figure, name, matrix, networks, figure_size, varargin{:}); properties = {'figure', 'name', 'matrix', 'networks', 'figure_size', 'network_clicked_callback',... 'marked_networks', 'figure_margins', 'draw_legend', 'draw_colorbar', 'color_map', 'lower_limit', 'upper_limit',... - 'x_position', 'y_position', 'discrete_colorbar'}; + 'x_position', 'y_position', 'discrete_colorbar', 'plot_scale'}; for property = properties obj.(property{1}) = matrix_input_parser.Results.(property{1}); if property{1} == "marked_networks" @@ -297,12 +299,15 @@ function addCallback(obj, x) % If there are no inputs (like initial rendering) then we use defaults % If there were inputs, that means we're scaling the colorbar. if isempty(varargin) + initial_render = true; % Controls whether or not to add the bars on the side and bottom upper_value = obj.upper_limit; lower_value = obj.lower_limit; else + initial_render = false; upper_value = str2double(varargin{2}); lower_value = str2double(varargin{1}); end + number_of_networks = obj.number_networks; dimensions = obj.image_dimensions; network_matrix = obj.network_matrix; @@ -324,8 +329,10 @@ function addCallback(obj, x) chunk_height = numel(network_indexes) * obj.elementSize(); % Left side of matrix color bars - obj.drawLeftLinesOnLabels(position_y, chunk_height, dimensions, network); - + if isequal(initial_render, true) + obj.drawLeftLinesOnLabels(position_y, chunk_height, dimensions, network); + end + position_x = dimensions("label_size") + dimensions("offset_x") + 3; starting_x = position_x; maximum_x = number_of_networks; @@ -349,45 +356,47 @@ function addCallback(obj, x) % Apply colors to chunks obj.applyColorToData(position_x, position_y, chunk_height, chunk_width, chunk_color); - % plot signifance marker - if ~isequal(obj.marked_networks, false) && isequal(obj.marked_networks(network, x), true) - obj.plotSignificanceMark(chunk_width, chunk_height, position_x, position_y); - end - - if ~isequal(obj.network_clicked_callback, false) - obj.network_dimensions(x, network, :) = [position_x, position_x + chunk_width - 1,... - position_y, position_y + chunk_height - 1]; - end - % Add callbacks to all the squares - obj.addCallback(drawLine(obj.axes, [position_x - 1, position_x - 1],... - [position_y, position_y + chunk_height + 1])); - obj.addCallback(drawLine(obj.axes, [position_x - 2, position_x + chunk_width - 1],... - [position_y + chunk_height, position_y + chunk_height])); - - if x == maximum_x && obj.matrix_type == MatrixType.TRIMATRIX && ~isequal(network_matrix, false) - obj.addCallback(drawLine(obj.axes, [position_x + chunk_width, position_x + chunk_width],... - [position_y - 1, position_y + chunk_height + 1])); - obj.addCallback(drawLine(obj.axes, [position_x - 2, position_x + chunk_width],... - [position_y - 1, position_y - 1])); - end + if isequal(initial_render, true) + % plot signifance marker + if ~isequal(obj.marked_networks, false) && isequal(obj.marked_networks(network, x), true) + obj.plotSignificanceMark(chunk_width, chunk_height, position_x, position_y); + end + + if ~isequal(obj.network_clicked_callback, false) + obj.network_dimensions(x, network, :) = [position_x, position_x + chunk_width - 1,... + position_y, position_y + chunk_height - 1]; + end + % Add callbacks to all the squares + obj.addCallback(drawLine(obj.axes, [position_x - 1, position_x - 1],... + [position_y, position_y + chunk_height + 1])); + obj.addCallback(drawLine(obj.axes, [position_x - 2, position_x + chunk_width - 1],... + [position_y + chunk_height, position_y + chunk_height])); + + if x == maximum_x && obj.matrix_type == MatrixType.TRIMATRIX && ~isequal(network_matrix, false) + obj.addCallback(drawLine(obj.axes, [position_x + chunk_width, position_x + chunk_width],... + [position_y - 1, position_y + chunk_height + 1])); + obj.addCallback(drawLine(obj.axes, [position_x - 2, position_x + chunk_width],... + [position_y - 1, position_y - 1])); + end - % Is this the last network of a TriMatrix. Then we're done and need to add the bottom - if network == number_of_networks - top = position_y + chunk_height; - bottom = position_y + chunk_height + dimensions("label_size"); - left = position_x; - right = position_x + chunk_width; + % Is this the last network of a TriMatrix. Then we're done and need to add the bottom + if network == number_of_networks + top = position_y + chunk_height; + bottom = position_y + chunk_height + dimensions("label_size"); + left = position_x; + right = position_x + chunk_width; - obj.image_display.CData(top:bottom, left:right, :) = colorChunk(obj.networks(x).color,... - dimensions("label_size") + 1, chunk_width + 1); - obj.drawBottomLabels(chunk_width, chunk_height, position_x, position_y, x); + obj.image_display.CData(top:bottom, left:right, :) = colorChunk(obj.networks(x).color,... + dimensions("label_size") + 1, chunk_width + 1); + obj.drawBottomLabels(chunk_width, chunk_height, position_x, position_y, x); + end end position_x = position_x + chunk_width + 1; end position_y = position_y + chunk_height + 1; end - if obj.matrix_type == MatrixType.TRIMATRIX && ~network_matrix + if obj.matrix_type == MatrixType.TRIMATRIX && ~network_matrix && initial_render drawLine(obj.axes, [starting_x - 1, position_x - 1],... [starting_y - 3 + obj.elementSize(), position_y - 2], 'w'); drawLine(obj.axes, [starting_x - 2, position_x - 1],... @@ -525,11 +534,10 @@ function createColorbar(obj, varargin) obj.color_bar.Title.FontSize = 7; % Enables callback for clicking on colorbar to scale data - set(obj.color_bar, 'ButtonDownFcn', @changeColorLimits) + set(obj.color_bar, 'ButtonDownFcn', @obj.openModal) caxis(obj.axes, [0, 1]); - % Callback for clicking on the colorbar. function changeColorLimits(~, ~) prompt = {"Enter Lower Limit: ", "Enter Upper Limit: "}; @@ -548,6 +556,48 @@ function changeColorLimits(~, ~) end end + function openModal(obj, source, ~) + import nla.gfx.ProbPlotMethod + % source is the colorbar, not the figure + d = figure('WindowStyle', 'normal', "Units", "pixels", 'Position', [source.Position(1), source.Position(2), source.Position(3) * 15, source.Position(4) / 2]); + % These are the boxes that are the upper and lower end of the scale + upper_limit_box = uicontrol('Style', 'edit', "Units", "pixels", 'Position', [90, 130, 100, 30], "String", obj.upper_limit); + upper_limit_box.Position(4) = upper_limit_box.FontSize * 2; + lower_limit_box = uicontrol('Style', 'edit', "Units", "pixels", 'Position', [90, 100, 100, 30], "String", obj.lower_limit); + lower_limit_box.Position(4) = lower_limit_box.FontSize * 2; + uicontrol('Style', 'text', 'String', 'Upper Limit', "Units", "pixels", 'Position', [upper_limit_box.Position(1) - 80, upper_limit_box.Position(2) - 2, 80, upper_limit_box.Position(4)]); + uicontrol('Style', 'text', 'String', 'Lower Limit', "Units", "pixels", 'Position', [lower_limit_box.Position(1) - 80, lower_limit_box.Position(2) - 2, 80, lower_limit_box.Position(4)]); + + % These are the buttons that make the scale log or linear + scaleBaseButtons = uibuttongroup(d, "Units", "pixels", "Position", [10, 60, 150, 30]); + linear_button = uicontrol(scaleBaseButtons, "Style", "radiobutton", "String", "Linear", "Units", "pixels", "Position", [10, 5, 60, 20]); + log_button = uicontrol(scaleBaseButtons, "Style", "radiobutton", "String", "Log", "Units", "pixels", "Position", [70, 5, 60, 20]); + if obj.plot_scale == ProbPlotMethod.DEFAULT || obj.plot_scale == STATISITC + selected_value = linear_button; + else + selected_value = log_button; + end + scaleBaseButtons.SelectedObject = selected_value + + apply_button_position = [10, 10, 100, 30]; + apply_button = uicontrol('String', 'Apply', 'Callback', {@obj.applyScale, upper_limit_box, lower_limit_box, scaleBaseButtons, selected_value}, "Units", "pixels", 'Position', apply_button_position); + close_button_position = [apply_button.Position(1) + apply_button.Position(3) + 10, apply_button.Position(2), apply_button.Position(3), apply_button.Position(4)]; + close_button = uicontrol('String', 'Close', 'Callback', @(~, ~)close(d), "Units", "pixels", 'Position', close_button_position); + end + + function applyScale(obj, ~, ~, upper_limit_box, lower_limit_box, button_group, initial_value) + import nla.net.result.NetworkResultPlotParameter + + discrete_colors = NetworkResultPlotParameter().default_discrete_colors; + if get(get(button_group, "SelectedObject"), "String") == "Linear" + obj.color_map = NetworkResultPlotParameter.getColormap(discrete_colors, get(upper_limit_box, "String")); + else + obj.color_map = NetworkResultPlotParameter.getLogColormap(discrete_colors, obj.matrix, get(upper_limit_box, "String")); + end + 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); diff --git a/+nla/+gfx/ProbPlotMethod.m b/+nla/+gfx/ProbPlotMethod.m index 5f149e52..4237eb53 100755 --- a/+nla/+gfx/ProbPlotMethod.m +++ b/+nla/+gfx/ProbPlotMethod.m @@ -1,5 +1,5 @@ classdef ProbPlotMethod enumeration - DEFAULT, LOG, NEG_LOG_10 + DEFAULT, LOG, NEG_LOG_10, STATISITC, LOG_STATISTIC, NEG_LOG_STATISTIC end end \ No newline at end of file diff --git a/+nla/+net/+result/+plot/NoPermutationPlotter.m b/+nla/+net/+result/+plot/NoPermutationPlotter.m index 43e23ced..d8f34d5b 100644 --- a/+nla/+net/+result/+plot/NoPermutationPlotter.m +++ b/+nla/+net/+result/+plot/NoPermutationPlotter.m @@ -18,11 +18,12 @@ 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); + '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"); diff --git a/+nla/+net/+result/NetworkResultPlotParameter.m b/+nla/+net/+result/NetworkResultPlotParameter.m index fcd52d26..5e84c64f 100644 --- a/+nla/+net/+result/NetworkResultPlotParameter.m +++ b/+nla/+net/+result/NetworkResultPlotParameter.m @@ -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,7 +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 = obj.getLogColormap(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); @@ -88,7 +88,7 @@ end significance_type = nla.gfx.SigType.INCREASING; otherwise - color_map = obj.getColormap(p_value_max); + color_map = nla.net.result.NetworkResultPlotParameter.getColormap(obj.default_discrete_colors, p_value_max); end % callback function for brain image. @@ -114,6 +114,7 @@ function brainFigureButtonCallback(network1, network2) result.significance_plot = significance_plot; result.callback = @brainFigureButtonCallback; result.significance_type = significance_type; + result.plot_scale = obj.updated_test_options.prob_plot_method; end function result = plotProbabilityVsNetworkSize(obj, test_method, plot_statistic) @@ -149,32 +150,6 @@ function brainFigureButtonCallback(network1, network2) end methods (Access = protected) - function color_map = getLogColormap(obj, probabilities_input, p_value_max) - log_minimum = log10(min(nonzeros(probabilities_input.v))); - log_minimum = max([-40, log_minimum]); - - % Relevant for BenjaminYekutieli/BenjaminHochberg fdr correction - default_color_map = [1 1 1]; - if p_value_max ~= 0 - color_map_base = parula(obj.default_discrete_colors); - color_map = flip(color_map_base(ceil(logspace(log_minimum, 0, obj.default_discrete_colors) .*... - obj.default_discrete_colors), :)); - color_map = [color_map; default_color_map]; - else - color_map = default_color_map; - end - end - - function color_map = getColormap(obj, p_value_max) - default_color_map = [1 1 1]; - if p_value_max == 0 - color_map = default_color_map; - else - color_map = flip(parula(obj.default_discrete_colors)); - color_map = [color_map; default_color_map]; - end - end - function network_size = getNetworkSizes(obj) import nla.TriMatrix nla.TriMatrixDiag ROI_pairs = TriMatrix(obj.network_atlas.numROIs(), "logical"); @@ -195,4 +170,32 @@ function brainFigureButtonCallback(network1, network2) statistic = obj.network_test_results.(test_method).(plot_statistic); end end + + methods(Static) + function color_map = getLogColormap(default_discrete_colors, probabilities_input, p_value_max) + log_minimum = log10(min(nonzeros(probabilities_input.v))); + log_minimum = max([-40, log_minimum]); + + % Relevant for BenjaminYekutieli/BenjaminHochberg fdr correction + default_color_map = [1 1 1]; + if p_value_max ~= 0 + color_map_base = parula(default_discrete_colors); + color_map = flip(color_map_base(ceil(logspace(log_minimum, 0, default_discrete_colors) .*... + default_discrete_colors), :)); + color_map = [color_map; default_color_map]; + else + color_map = default_color_map; + end + end + + function color_map = getColormap(default_discrete_colors, p_value_max) + default_color_map = [1 1 1]; + if p_value_max == 0 + color_map = default_color_map; + else + color_map = flip(parula(default_discrete_colors)); + color_map = [color_map; default_color_map]; + end + end + end end \ No newline at end of file From 0c57d2daac5d0c3713cf1260033a685b21b809a3 Mon Sep 17 00:00:00 2001 From: Jim Pollaro Date: Fri, 5 Apr 2024 12:59:59 -0500 Subject: [PATCH 2/5] remove some unneeded function and variable names --- +nla/+gfx/+plots/MatrixPlot.m | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/+nla/+gfx/+plots/MatrixPlot.m b/+nla/+gfx/+plots/MatrixPlot.m index 3ba10bbd..e42724b4 100644 --- a/+nla/+gfx/+plots/MatrixPlot.m +++ b/+nla/+gfx/+plots/MatrixPlot.m @@ -537,23 +537,6 @@ function createColorbar(obj, varargin) set(obj.color_bar, 'ButtonDownFcn', @obj.openModal) caxis(obj.axes, [0, 1]); - - % Callback for clicking on the colorbar. - function changeColorLimits(~, ~) - prompt = {"Enter Lower Limit: ", "Enter Upper Limit: "}; - upper_limit_inner = obj.color_bar.TickLabels(end); - lower_limit_inner = obj.color_bar.TickLabels(1); - current_limits = {lower_limit_inner{1}, upper_limit_inner{1}}; - new_limits = inputdlg(prompt, "Colorbar Limits", 1, current_limits); - % If "cancel" is pressed or both values deleted use defaults - if isempty(new_limits) || isempty(new_limits{1}) || isempty(new_limits{2}) - obj.embiggenMatrix(); - obj.createColorbar(); - else - obj.embiggenMatrix(new_limits{1}, new_limits{2}); - obj.createColorbar(new_limits{1}, new_limits{2}); - end - end end function openModal(obj, source, ~) @@ -577,15 +560,15 @@ function openModal(obj, source, ~) else selected_value = log_button; end - scaleBaseButtons.SelectedObject = selected_value + scaleBaseButtons.SelectedObject = selected_value; apply_button_position = [10, 10, 100, 30]; - apply_button = uicontrol('String', 'Apply', 'Callback', {@obj.applyScale, upper_limit_box, lower_limit_box, scaleBaseButtons, selected_value}, "Units", "pixels", 'Position', apply_button_position); + apply_button = uicontrol('String', 'Apply', 'Callback', {@obj.applyScale, upper_limit_box, lower_limit_box, scaleBaseButtons}, "Units", "pixels", 'Position', apply_button_position); close_button_position = [apply_button.Position(1) + apply_button.Position(3) + 10, apply_button.Position(2), apply_button.Position(3), apply_button.Position(4)]; - close_button = uicontrol('String', 'Close', 'Callback', @(~, ~)close(d), "Units", "pixels", 'Position', close_button_position); + uicontrol('String', 'Close', 'Callback', @(~, ~)close(d), "Units", "pixels", 'Position', close_button_position); end - function applyScale(obj, ~, ~, upper_limit_box, lower_limit_box, button_group, initial_value) + function applyScale(obj, ~, ~, upper_limit_box, lower_limit_box, button_group) import nla.net.result.NetworkResultPlotParameter discrete_colors = NetworkResultPlotParameter().default_discrete_colors; From 3983289a08ecbaa09ae54c3c4bff0ac0d961bb3a Mon Sep 17 00:00:00 2001 From: Jim Pollaro Date: Fri, 5 Apr 2024 14:25:37 -0500 Subject: [PATCH 3/5] formatting and comments --- +nla/+gfx/+plots/MatrixPlot.m | 66 +++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/+nla/+gfx/+plots/MatrixPlot.m b/+nla/+gfx/+plots/MatrixPlot.m index e42724b4..29b1ab65 100644 --- a/+nla/+gfx/+plots/MatrixPlot.m +++ b/+nla/+gfx/+plots/MatrixPlot.m @@ -219,7 +219,8 @@ function displayImage(obj) dimensions = [image_height image_width offset_x offset_y plot_width plot_height display_matrix_size label_size]; % Matlab does not have a python-like dictionary. This is one, or a struct. - value = containers.Map(["image_height" "image_width" "offset_x" "offset_y" "plot_width" "plot_height" "display_matrix_size" "label_size"], dimensions); + value = containers.Map(["image_height" "image_width" "offset_x" "offset_y" "plot_width" "plot_height"... + "display_matrix_size" "label_size"], dimensions); end function value = get.as_matrix(obj) @@ -256,7 +257,8 @@ function displayImage(obj) function obj = drawAxes(obj) % Creates the axes for the plot. - obj.axes = uiaxes(obj.figure, 'Position', [obj.x_position, obj.y_position, obj.image_dimensions("image_width"), obj.image_dimensions("image_height")]); + obj.axes = uiaxes(obj.figure, 'Position', [obj.x_position, obj.y_position,... + obj.image_dimensions("image_width"), obj.image_dimensions("image_height")]); axis(obj.axes, 'image'); obj.axes.XAxis.TickLabels = {}; obj.axes.YAxis.TickLabels = {}; @@ -293,7 +295,8 @@ function addCallback(obj, x) end function obj = embiggenMatrix(obj, varargin) - % Enlarges data points of matrix for easier viewing. Also adds the network colorbars to the left axis and bottom axis. + % Enlarges data points of matrix for easier viewing. + % Also adds the network colorbars to the left axis and bottom axis. import nla.gfx.colorChunk nla.gfx.MatrixType nla.gfx.drawLine % If there are no inputs (like initial rendering) then we use defaults @@ -412,7 +415,8 @@ function drawLeftLinesOnLabels(obj, position_y, chunk_height, dimensions, networ bottom = position_y + chunk_height; left = dimensions("offset_x") + 2; right = dimensions("offset_x") + dimensions("label_size") + 1; - obj.image_display.CData(top:bottom, left:right+1, :) = colorChunk(obj.networks(network).color, chunk_height + 1, dimensions("label_size") + 1); + obj.image_display.CData(top:bottom, left:right+1, :) = colorChunk(obj.networks(network).color,... + chunk_height + 1, dimensions("label_size") + 1); drawLine(obj.axes, [left - 1, right], [top - 1, top - 1]); drawLine(obj.axes, [left - 1, right], [bottom, bottom]); @@ -441,7 +445,8 @@ function plotSignificanceMark(obj, chunk_width, chunk_height, position_x, positi left = position_x; right = position_x + chunk_width; - obj.image_display.CData(top:bottom, left:right, :) = colorChunk(obj.networks(x_location).color, dimensions("label_size") + 1, chunk_width + 1); + obj.image_display.CData(top:bottom, left:right, :) = colorChunk(obj.networks(x_location).color,... + dimensions("label_size") + 1, chunk_width + 1); obj.addCallback(drawLine(obj.axes, [left - 1, left - 1], [top, bottom])); obj.addCallback(drawLine(obj.axes, [right, right], [top, bottom])); @@ -479,9 +484,11 @@ function createLegend(obj) display_legend.Units = 'pixels'; display_legend_width = display_legend.Position(3); display_legend_height = display_legend.Position(4); - display_legend.Position = [obj.x_position + dimensions("plot_width") - display_legend_width - dimensions("offset_x") - obj.legend_offset,... + display_legend.Position = [... + obj.x_position + dimensions("plot_width") - display_legend_width - dimensions("offset_x") - obj.legend_offset,... obj.y_position + dimensions("plot_height") - display_legend_height - dimensions("offset_y"),... - display_legend_width, display_legend_height]; + display_legend_width, display_legend_height... + ]; end function createColorbar(obj, varargin) @@ -540,21 +547,33 @@ function createColorbar(obj, varargin) end 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. 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 - d = figure('WindowStyle', 'normal', "Units", "pixels", 'Position', [source.Position(1), source.Position(2), source.Position(3) * 15, source.Position(4) / 2]); + d = figure('WindowStyle', 'normal', "Units", "pixels", 'Position', [source.Position(1), source.Position(2),... + source.Position(3) * 15, source.Position(4) / 2]); % These are the boxes that are the upper and lower end of the scale - upper_limit_box = uicontrol('Style', 'edit', "Units", "pixels", 'Position', [90, 130, 100, 30], "String", obj.upper_limit); + upper_limit_box = uicontrol('Style', 'edit', "Units", "pixels", 'Position', [90, 130, 100, 30], "String",... + obj.upper_limit); upper_limit_box.Position(4) = upper_limit_box.FontSize * 2; - lower_limit_box = uicontrol('Style', 'edit', "Units", "pixels", 'Position', [90, 100, 100, 30], "String", obj.lower_limit); + lower_limit_box = uicontrol('Style', 'edit', "Units", "pixels", 'Position', [90, 100, 100, 30], "String",... + obj.lower_limit); lower_limit_box.Position(4) = lower_limit_box.FontSize * 2; - uicontrol('Style', 'text', 'String', 'Upper Limit', "Units", "pixels", 'Position', [upper_limit_box.Position(1) - 80, upper_limit_box.Position(2) - 2, 80, upper_limit_box.Position(4)]); - uicontrol('Style', 'text', 'String', 'Lower Limit', "Units", "pixels", 'Position', [lower_limit_box.Position(1) - 80, lower_limit_box.Position(2) - 2, 80, lower_limit_box.Position(4)]); + uicontrol('Style', 'text', 'String', 'Upper Limit', "Units", "pixels", 'Position',... + [upper_limit_box.Position(1) - 80, upper_limit_box.Position(2) - 2, 80, upper_limit_box.Position(4)]); + uicontrol('Style', 'text', 'String', 'Lower Limit', "Units", "pixels", 'Position',... + [lower_limit_box.Position(1) - 80, lower_limit_box.Position(2) - 2, 80, lower_limit_box.Position(4)]); % These are the buttons that make the scale log or linear scaleBaseButtons = uibuttongroup(d, "Units", "pixels", "Position", [10, 60, 150, 30]); - linear_button = uicontrol(scaleBaseButtons, "Style", "radiobutton", "String", "Linear", "Units", "pixels", "Position", [10, 5, 60, 20]); - log_button = uicontrol(scaleBaseButtons, "Style", "radiobutton", "String", "Log", "Units", "pixels", "Position", [70, 5, 60, 20]); + linear_button = uicontrol(scaleBaseButtons, "Style", "radiobutton", "String", "Linear", "Units", "pixels",... + "Position", [10, 5, 60, 20]); + log_button = uicontrol(scaleBaseButtons, "Style", "radiobutton", "String", "Log", "Units", "pixels",... + "Position", [70, 5, 60, 20]); + % Here we're setting the initial setting for the linear or log button if obj.plot_scale == ProbPlotMethod.DEFAULT || obj.plot_scale == STATISITC selected_value = linear_button; else @@ -563,19 +582,28 @@ function openModal(obj, source, ~) scaleBaseButtons.SelectedObject = selected_value; apply_button_position = [10, 10, 100, 30]; - apply_button = uicontrol('String', 'Apply', 'Callback', {@obj.applyScale, upper_limit_box, lower_limit_box, scaleBaseButtons}, "Units", "pixels", 'Position', apply_button_position); - close_button_position = [apply_button.Position(1) + apply_button.Position(3) + 10, apply_button.Position(2), apply_button.Position(3), apply_button.Position(4)]; - uicontrol('String', 'Close', 'Callback', @(~, ~)close(d), "Units", "pixels", 'Position', close_button_position); + apply_button = uicontrol('String', 'Apply',... + 'Callback', {@obj.applyScale, upper_limit_box, lower_limit_box, scaleBaseButtons},... + "Units", "pixels",... + 'Position', apply_button_position); + close_button_position = [apply_button.Position(1) + apply_button.Position(3) + 10,... + apply_button.Position(2), apply_button.Position(3), apply_button.Position(4)]; + uicontrol('String', 'Close', 'Callback', @(~, ~)close(d), "Units", "pixels", 'Position',... + close_button_position); end function applyScale(obj, ~, ~, upper_limit_box, lower_limit_box, button_group) + % 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 - + discrete_colors = NetworkResultPlotParameter().default_discrete_colors; if get(get(button_group, "SelectedObject"), "String") == "Linear" obj.color_map = NetworkResultPlotParameter.getColormap(discrete_colors, get(upper_limit_box, "String")); else - obj.color_map = NetworkResultPlotParameter.getLogColormap(discrete_colors, obj.matrix, get(upper_limit_box, "String")); + obj.color_map = NetworkResultPlotParameter.getLogColormap(discrete_colors, obj.matrix,... + get(upper_limit_box, "String")); end obj.embiggenMatrix(get(lower_limit_box, "String"), get(upper_limit_box, "String")); obj.createColorbar(get(lower_limit_box, "String"), get(upper_limit_box, "String")); From dcd5269c1ed9ed8a2dce097c07cd885cb674a642 Mon Sep 17 00:00:00 2001 From: Jim Pollaro Date: Wed, 10 Apr 2024 13:52:50 -0500 Subject: [PATCH 4/5] added negative log10 ability --- +nla/+gfx/+plots/MatrixPlot.m | 34 ++++++++++++++++++++++++++-------- main_pipeline.m | 2 +- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/+nla/+gfx/+plots/MatrixPlot.m b/+nla/+gfx/+plots/MatrixPlot.m index 29b1ab65..152eba48 100644 --- a/+nla/+gfx/+plots/MatrixPlot.m +++ b/+nla/+gfx/+plots/MatrixPlot.m @@ -568,16 +568,20 @@ function openModal(obj, source, ~) [lower_limit_box.Position(1) - 80, lower_limit_box.Position(2) - 2, 80, lower_limit_box.Position(4)]); % These are the buttons that make the scale log or linear - scaleBaseButtons = uibuttongroup(d, "Units", "pixels", "Position", [10, 60, 150, 30]); + scaleBaseButtons = uibuttongroup(d, "Units", "pixels", "Position", [10, 60, 210, 30]); linear_button = uicontrol(scaleBaseButtons, "Style", "radiobutton", "String", "Linear", "Units", "pixels",... "Position", [10, 5, 60, 20]); log_button = uicontrol(scaleBaseButtons, "Style", "radiobutton", "String", "Log", "Units", "pixels",... - "Position", [70, 5, 60, 20]); + "Position", [80, 5, 60, 20]); + neg_log_button = uicontrol(scaleBaseButtons, "Style", "radiobutton", "String", "-Log10", "Units", "pixels",... + "Position", [130, 5, 80, 20]); % Here we're setting the initial setting for the linear or log button - if obj.plot_scale == ProbPlotMethod.DEFAULT || obj.plot_scale == STATISITC + if obj.plot_scale == ProbPlotMethod.DEFAULT || obj.plot_scale == ProbPlotMethod.STATISTIC selected_value = linear_button; - else + elseif obj.plot_scale == ProbPlotMethod.LOG || obj.plot_scale == ProbPlotMethod.LOG_STATISTIC selected_value = log_button; + else + selected_value = neg_log_button; end scaleBaseButtons.SelectedObject = selected_value; @@ -596,14 +600,28 @@ function applyScale(obj, ~, ~, upper_limit_box, lower_limit_box, button_group) % 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 + import nla.net.result.NetworkResultPlotParameter nla.gfx.ProbPlotMethod + + button_group_value = get(get(button_group, "SelectedObject"), "String"); + + if ismember(obj.plot_scale, [ProbPlotMethod.NEG_LOG_10, ProbPlotMethod.NEG_LOG_STATISTIC]) &&... + ismember(button_group_value, ["Linear", "Log"]) + obj.matrix.v = 10.^(-obj.matrix.v); + elseif ~ismember(obj.plot_scale, [ProbPlotMethod.NEG_LOG_10, ProbPlotMethod.NEG_LOG_STATISTIC]) &&... + ~ismember(button_group_value, ["Linear", "Log"]) + obj.matrix.v = -log10(obj.matrix.v); + end discrete_colors = NetworkResultPlotParameter().default_discrete_colors; - if get(get(button_group, "SelectedObject"), "String") == "Linear" + if button_group_value == "Linear" obj.color_map = NetworkResultPlotParameter.getColormap(discrete_colors, get(upper_limit_box, "String")); + obj.plot_scale = ProbPlotMethod.DEFAULT; + elseif button_group_value == "Log" + obj.color_map = NetworkResultPlotParameter.getLogColormap(discrete_colors, obj.matrix, get(upper_limit_box, "String")); + obj.plot_scale = ProbPlotMethod.LOG; else - obj.color_map = NetworkResultPlotParameter.getLogColormap(discrete_colors, obj.matrix,... - get(upper_limit_box, "String")); + obj.color_map = parula(discrete_colors); + obj.plot_scale = ProbPlotMethod.NEG_LOG_10; end obj.embiggenMatrix(get(lower_limit_box, "String"), get(upper_limit_box, "String")); obj.createColorbar(get(lower_limit_box, "String"), get(upper_limit_box, "String")); diff --git a/main_pipeline.m b/main_pipeline.m index 51b05a33..39c48785 100755 --- a/main_pipeline.m +++ b/main_pipeline.m @@ -101,7 +101,7 @@ net_results = tests.runNetTests(net_input_struct, edge_result, net_atlas, false); % Run test pool, permuting data n times -results = tests.runPerm(input_struct, net_input_struct, net_atlas, edge_result, net_results, 100); +results = tests.runPerm(input_struct, net_input_struct, net_atlas, edge_result, net_results, 1000); %% Visualize results % Warning: Will produce a large amount of figures. You are advised to use From e4e055b5f4e6477e525956aeed6a9b7c58921bea Mon Sep 17 00:00:00 2001 From: Jim Pollaro Date: Wed, 10 Apr 2024 13:54:22 -0500 Subject: [PATCH 5/5] fix mistake --- main_pipeline.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main_pipeline.m b/main_pipeline.m index 39c48785..51b05a33 100755 --- a/main_pipeline.m +++ b/main_pipeline.m @@ -101,7 +101,7 @@ net_results = tests.runNetTests(net_input_struct, edge_result, net_atlas, false); % Run test pool, permuting data n times -results = tests.runPerm(input_struct, net_input_struct, net_atlas, edge_result, net_results, 1000); +results = tests.runPerm(input_struct, net_input_struct, net_atlas, edge_result, net_results, 100); %% Visualize results % Warning: Will produce a large amount of figures. You are advised to use