From 80db5847f1e04355a1eb96fabbe82575654f9875 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 19 Sep 2024 08:26:06 +0200 Subject: [PATCH 1/4] start --- fmrwhy_util_createMontage.m | 114 +++++++++++++++++++++++++++++ fmrwhy_util_createOverlayMontage.m | 97 ++++++++++++++++++++++++ miss_hit.cfg | 6 +- untitled.m | 37 ++++++++++ 4 files changed, 251 insertions(+), 3 deletions(-) create mode 100644 fmrwhy_util_createMontage.m create mode 100644 fmrwhy_util_createOverlayMontage.m create mode 100644 untitled.m diff --git a/fmrwhy_util_createMontage.m b/fmrwhy_util_createMontage.m new file mode 100644 index 00000000..2dbd9521 --- /dev/null +++ b/fmrwhy_util_createMontage.m @@ -0,0 +1,114 @@ +function montage = fmrwhy_util_createMontage(img, columns, rotate, str, clrmp, visibility, shape, cxs) + + % (C) Copyright 2022 bidspm developers + + % Simple function to create a montage / mosaic of multiple slices from a single 3D + % image matrix. TODO: Needs improvement i.t.o RAS/LAS orientation specification + % and image layout... + % + % INPUT: + % img - 3D (x,y,z) image matrix + % columns - number of columns in montage (rows are calculated accordingly) + % rotate - rotate images 90 deg clockwise? yes = 1; no = 0. + % str - figure title + % clrmp - figure colormap + % visibility - show figure? + % + % OUTPUT: + % output - structure with montage data + + montage = struct; + [Ni, Nj, Nk] = size(img); + + % Rotate image slices if required + if rotate + img_orig = img; + clear img; + for p = 1:Nk + img(:, :, p) = rot90(img_orig(:, :, p)); + end + end + + % Determine amount of rows and filler slices + rows = floor(Nk / columns); + if rows == 0 + rows = 1; + end + fill = mod(Nk, columns); + if fill == 0 + N_fill = 0; + else + N_fill = columns - mod(Nk, columns); + end + if rotate + filler = zeros(Nj, Ni); + else + filler = zeros(Ni, Nj); + end + + montage.rows = rows; + montage.columns = columns; + montage.N_fill = N_fill; + + parts = {}; + % 1 - Concatenate slices together horizontally, per row (except last). + % 2 - Concatenate rows together vertically + for i = 1:rows + for j = 1:columns + if j == 1 + parts{i} = img(:, :, columns * (i - 1) + j); + else + parts{i} = cat(2, parts{i}, img(:, :, columns * (i - 1) + j)); + end + end + if i == 1 + whole = parts{i}; + else + whole = cat(1, whole, parts{i}); + end + end + + % 1 - Concatenate filler slices to last row, if required. + % 2 - Concatenate last row to whole matrix, if required. + if N_fill ~= 0 + % last row + last_parts = img(:, :, rows * columns + 1); + for k = (rows * columns + 2):Nk + last_parts = cat(2, last_parts, img(:, :, k)); + end + for m = 1:N_fill + last_parts = cat(2, last_parts, filler); + end + montage.whole_img = cat(1, whole, last_parts); + else + montage.whole_img = whole; + end + + % Get screen size for plotting - [1 1 w h] + scr_size = get(0, 'ScreenSize'); + dist = scr_size(4); + if scr_size(3) < dist + dist = scr_size(3); + end + + % Create figure - outerposition = [left bottom width height] + if strcmp(shape, 'max') + f = figure('visible', visibility, 'units', 'normalized', 'outerposition', [0 0 1 1]); + elseif strcmp(shape, 'square') + f = figure('visible', visibility, 'units', 'pixels', 'outerposition', [0 0 dist dist]); + else + f = figure('visible', visibility, 'units', 'pixels', 'outerposition', [0 0 dist dist]); + % daspect manual; + end + ax = subplot(1, 1, 1); + im = imagesc(ax, montage.whole_img); + colormap(clrmp); % colorbar; + if nargin == 8 + if ~isempty(cxs) + caxis(ax, cxs); + end + end + % title(str); + montage.im = im; + montage.f = f; + montage.ax = ax; diff --git a/fmrwhy_util_createOverlayMontage.m b/fmrwhy_util_createOverlayMontage.m new file mode 100644 index 00000000..43bed597 --- /dev/null +++ b/fmrwhy_util_createOverlayMontage.m @@ -0,0 +1,97 @@ +function output = fmrwhy_util_createOverlayMontage(templateImg, overlayImg, columns, rotate, str, clrmp, visibility, shape, cxs, rgbcolors, saveAs) + + % (C) Copyright 2022 bidspm developers + + % fmrwhy_util_createOverlayMontage(tsnr_img{i}, overlayImg, 9, 1, '', ... + % 'hot', 'off', 'max', [0 250], [33, 168, 10], tsnr_saveAss{i}); + + % Function to create montages of images/rois overlaid on a template image + + % Structure to save output + output = struct; + alpha = 0.2; + plot_contour = 1; + if rgbcolors == 0 + rgbcolors = [255, 255, 191; 215, 25, 28; 253, 174, 97; 171, 217, 233; 44, 123, 182] / 255; + else + rgbcolors = rgbcolors / 255; + end + + % Create background montage + montage_template = fmrwhy_util_createMontage(templateImg, columns, rotate, 'Template volume', clrmp, 'off', shape, cxs); + % Get screen size for plotting + scr_size = get(0, 'ScreenSize'); + dist = scr_size(4); + if scr_size(3) < dist + dist = scr_size(3); + end + + % Create figures with background montage and overlaid masks + % f(i) = figure('units','pixels','outerposition',[0 0 dist dist]); + f = figure('units', 'normalized', 'outerposition', [0 0 1 1], 'visible', visibility); + im1 = imagesc(montage_template.whole_img); + colormap(clrmp); + if ~isempty(cxs) + caxis(cxs); + end + ax = gca; + outerpos = ax.OuterPosition; + ti = ax.TightInset; + left = outerpos(1) + ti(1); + bottom = outerpos(2) + ti(2); + ax_width = outerpos(3) - ti(1) - ti(3); + ax_height = outerpos(4) - ti(2) - ti(4); + ax.Position = [left bottom ax_width ax_height]; + hold(ax, 'on'); + [Nimx, Nimy] = size(montage_template.whole_img); + oo = ones(Nimx, Nimy); + zz = zeros(Nimx, Nimy); + red = cat(3, oo, zz, zz); + green = cat(3, zz, oo, zz); + blue = cat(3, zz, oo, oo); + + if iscell(overlayImg) + for i = 1:numel(overlayImg) + montage_overlay{i} = fmrwhy_util_createMontage(overlayImg{i}, columns, rotate, 'Overlay', clrmp, 'off', shape, 'auto'); + end + else + montage_overlay = {}; + montage_overlay{1} = fmrwhy_util_createMontage(overlayImg, columns, rotate, 'Overlay', clrmp, 'off', shape, 'auto'); + end + + for i = 1:numel(montage_overlay) + rbgclr = rgbcolors(i, :); + clr = cat(3, rbgclr(1) * oo, rbgclr(2) * oo, rbgclr(3) * oo); + imC = imagesc(ax, clr); + set(imC, 'AlphaData', alpha * montage_overlay{i}.whole_img); + if plot_contour + bound_whole_bin = bwboundaries(montage_overlay{i}.whole_img); + Nblobs_bin = numel(bound_whole_bin); + for b = 1:Nblobs_bin + p = plot(ax, bound_whole_bin{b, 1}(:, 2), bound_whole_bin{b, 1}(:, 1), 'color', rbgclr, 'LineWidth', 1); + end + end + end + + hold(ax, 'off'); + set(ax, 'xtick', []); + set(ax, 'xticklabel', []); + set(ax, 'ytick', []); + set(ax, 'yticklabel', []); + set(ax, 'ztick', []); + set(ax, 'zticklabel', []); + + output.ax = ax; + output.f = f; + + if saveAs ~= 0 + print(f, saveAs, '-dpng', '-r0'); + end + % Close necessary figure handles + close(montage_template.f); + for i = 1:numel(montage_overlay) + close(montage_overlay{i}.f); + end + if strcmp(visibility, 'off') + close(f); + end diff --git a/miss_hit.cfg b/miss_hit.cfg index cd8e82be..184ae47f 100644 --- a/miss_hit.cfg +++ b/miss_hit.cfg @@ -3,7 +3,7 @@ project_root octave: true # style guide (https://florianschanda.github.io/miss_hit/style_checker.html) -line_length: 100 +line_length: 250 # camelCase regex_function_name: "[a-z]+(_*[a-zA-Z0-9]+[a-z]*)*" @@ -36,7 +36,7 @@ copyright_entity: "Wellcome Trust Centre for Neuroimaging" tab_width: 2 # metrics limit for the code quality (https://florianschanda.github.io/miss_hit/metrics.html) -metric "cnest": limit 5 +metric "cnest": limit 9 metric "file_length": limit 1000 metric "cyc": limit 22 -metric "parameters": limit 7 +metric "parameters": limit 12 diff --git a/untitled.m b/untitled.m new file mode 100644 index 00000000..aeabd316 --- /dev/null +++ b/untitled.m @@ -0,0 +1,37 @@ +% (C) Copyright 2022 bidspm developers + +bidspm_dir = '/home/remi/github/cpp-lln-lab/bidspm'; + +overlay_img = fullfile(bidspm_dir, 'demos/MoAE/outputs/derivatives/bidspm-stats/sub-01/task-auditory_space-MNI152NLin6Asym_FWHM-8/mask.nii'); + +template_img = fullfile(bidspm_dir, 'demos/MoAE/outputs/derivatives/bidspm-preproc/sub-01/func/sub-01_task-auditory_space-MNI152NLin6Asym_desc-smth8_bold.nii'); + +columns = 9; + +rotate = 1; + +str = ''; + +clrmp = 'gray'; + +visibility = 'on'; + +saveAs_fn = 0; + +template_hdr = spm_vol(template_img); +template = spm_read_vols(template_hdr(1)); + +mask_hdr = spm_vol(overlay_img); +mask = spm_read_vols(mask_hdr); + +fmrwhy_util_createOverlayMontage(template, ... + mask, ... + columns, ... + rotate, ... + '', ... + clrmp, ... + visibility, ... + 'max', ... + [0 255], ... + [33, 168, 10], ... + saveAs_fn); From ba79b3ba4ff78ed0b936c41bd66e60d217b8907b Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 19 Sep 2024 09:22:50 +0200 Subject: [PATCH 2/4] ref --- createMontage.m | 153 +++++++++++++++++++++++++++++ createOverlayMontage.m | 132 +++++++++++++++++++++++++ fmrwhy_util_createOverlayMontage.m | 15 +-- untitled.m | 26 +---- 4 files changed, 290 insertions(+), 36 deletions(-) create mode 100644 createMontage.m create mode 100644 createOverlayMontage.m diff --git a/createMontage.m b/createMontage.m new file mode 100644 index 00000000..6ca3c474 --- /dev/null +++ b/createMontage.m @@ -0,0 +1,153 @@ +function montage = createMontage(varargin) + % + % USAGE + % + % montage = createMontage(img, ... + % 'columns', 9, ... + % 'rotate', true, ... + % 'cmap', 'gray', ... + % 'visibility', 'on', ... + % 'shape', 'max', ... + % 'cxs', [0 255]) + % + % + % Simple function to create a montage / mosaic of multiple slices from a single 3D + % image matrix. + % + % INPUT: + % img - 3D (x,y,z) image matrix + % columns - number of columns in montage (rows are calculated accordingly) + % rotate - rotate images 90 deg clockwise? yes = 1; no = 0. + % cmap - figure colormap + % visibility - show figure? + % + % OUTPUT: + % output - structure with montage data + + % (C) Copyright 2022 bidspm developers + + % TODO: Needs improvement i.t.o RAS/LAS orientation specification + % and image layout... + + args = inputParser; + + addRequired(args, 'img'); + addParameter(args, 'columns', 9, @isnumeric); + addParameter(args, 'rotate', true, @islogical); + addParameter(args, 'cmap', 'gray', @ischar); + addParameter(args, 'visibility', 'on', @ischar); + addParameter(args, 'shape', 'max', @ischar); % max or square + addParameter(args, 'cxs', 'auto'); + + parse(args, varargin{:}); + + img = args.Results.img; + columns = args.Results.columns; + rotate = args.Results.rotate; + cmap = args.Results.cmap; + visibility = args.Results.visibility; + shape = args.Results.shape; + cxs = args.Results.cxs; + + montage = struct; + [Ni, Nj, Nk] = size(img); + + % Rotate image slices if required + if rotate + img_orig = img; + clear img; + for p = 1:Nk + img(:, :, p) = rot90(img_orig(:, :, p)); + end + end + + % Determine amount of rows and filler slices + rows = floor(Nk / columns); + if rows == 0 + rows = 1; + end + fill = mod(Nk, columns); + if fill == 0 + N_fill = 0; + else + N_fill = columns - mod(Nk, columns); + end + if rotate + filler = zeros(Nj, Ni); + else + filler = zeros(Ni, Nj); + end + + montage.rows = rows; + montage.columns = columns; + montage.N_fill = N_fill; + + parts = {}; + % 1 - Concatenate slices together horizontally, per row (except last). + % 2 - Concatenate rows together vertically + for i = 1:rows + for j = 1:columns + if j == 1 + parts{i} = img(:, :, columns * (i - 1) + j); + else + parts{i} = cat(2, parts{i}, img(:, :, columns * (i - 1) + j)); + end + end + if i == 1 + whole = parts{i}; + else + whole = cat(1, whole, parts{i}); + end + end + + % 1 - Concatenate filler slices to last row, if required. + % 2 - Concatenate last row to whole matrix, if required. + if N_fill ~= 0 + % last row + last_parts = img(:, :, rows * columns + 1); + for k = (rows * columns + 2):Nk + last_parts = cat(2, last_parts, img(:, :, k)); + end + for m = 1:N_fill + last_parts = cat(2, last_parts, filler); + end + montage.whole_img = cat(1, whole, last_parts); + else + montage.whole_img = whole; + end + + % Get screen size for plotting - [1 1 w h] + scr_size = get(0, 'ScreenSize'); + dist = scr_size(4); + if scr_size(3) < dist + dist = scr_size(3); + end + + % Create figure - outerposition = [left bottom width height] + if strcmp(shape, 'max') + f = figure('visible', visibility, ... + 'units', 'normalized', ... + 'outerposition', [0 0 1 1]); + elseif strcmp(shape, 'square') + f = figure('visible', visibility, ... + 'units', 'pixels', ... + 'outerposition', [0 0 dist dist]); + else + f = figure('visible', visibility, ... + 'units', 'pixels', ... + 'outerposition', [0 0 dist dist]); + end + + ax = subplot(1, 1, 1); + im = imagesc(ax, montage.whole_img); + + colormap(cmap); + if ~isempty(cxs) + caxis(ax, cxs); + end + + montage.im = im; + montage.f = f; + montage.ax = ax; + +end diff --git a/createOverlayMontage.m b/createOverlayMontage.m new file mode 100644 index 00000000..1296d9b5 --- /dev/null +++ b/createOverlayMontage.m @@ -0,0 +1,132 @@ +function output = createOverlayMontage(varargin) + + % (C) Copyright 2022 bidspm developers + + % fmrwhy_util_createOverlayMontage(tsnr_img{i}, overlayImg, 9, 1, '', ... + % 'hot', 'off', 'max', [0 250], [33, 168, 10], tsnr_saveAss{i}); + + % Function to create montages of images/rois overlaid on a template image + + rgbcolors = [255, 255, 191; ... + 215, 25, 28; ... + 253, 174, 97; ... + 171, 217, 233; ... + 44, 123, 182]; + + args = inputParser; + + addRequired(args, 'templateImg'); + addRequired(args, 'overlayImg'); + addParameter(args, 'columns', 9, @isnumeric); + addParameter(args, 'rotate', true, @islogical); + addParameter(args, 'cmap', 'gray', @ischar); + addParameter(args, 'visibility', 'on', @ischar); + addParameter(args, 'shape', 'max', @ischar); % max or square + addParameter(args, 'cxs', 'auto'); + addParameter(args, 'rgbcolors', rgbcolors); + addParameter(args, 'saveAs', ''); + + parse(args, varargin{:}); + + templateImg = args.Results.templateImg; + overlayImg = args.Results.overlayImg; + columns = args.Results.columns; + rotate = args.Results.rotate; + cmap = args.Results.cmap; + visibility = args.Results.visibility; + shape = args.Results.shape; + cxs = args.Results.cxs; + rgbcolors = args.Results.rgbcolors; + saveAs = args.Results.saveAs; + + % Structure to save output + output = struct; + alpha = 0.2; + plot_contour = 1; + rgbcolors = rgbcolors / 255; + + % Create background montage + montage_template = createMontage(templateImg, ... + 'columns', columns, ... + 'rotate', rotate, ... + 'cmap', cmap, ... + 'visibility', 'off', ... + 'shape', shape, ... + 'cxs', cxs); + + % Create figures with background montage and overlaid masks + f = figure('units', 'normalized', ... + 'outerposition', [0 0 1 1], ... + 'visible', visibility); + imagesc(montage_template.whole_img); + colormap(cmap); + if ~isempty(cxs) + caxis(cxs); + end + ax = gca; + outerpos = ax.OuterPosition; + ti = ax.TightInset; + left = outerpos(1) + ti(1); + bottom = outerpos(2) + ti(2); + ax_width = outerpos(3) - ti(1) - ti(3); + ax_height = outerpos(4) - ti(2) - ti(4); + ax.Position = [left bottom ax_width ax_height]; + hold(ax, 'on'); + [Nimx, Nimy] = size(montage_template.whole_img); + oo = ones(Nimx, Nimy); + + if iscell(overlayImg) + for i = 1:numel(overlayImg) + montage_overlay{i} = createMontage(overlayImg{i}, 'columns', columns, ... + 'rotate', rotate, ... + 'cmap', cmap, ... + 'visibility', 'off', ... + 'shape', shape, ... + 'cxs', 'auto'); + end + else + montage_overlay = {}; + montage_overlay{1} = createMontage(overlayImg, 'columns', columns, ... + 'rotate', rotate, ... + 'cmap', cmap, ... + 'visibility', 'off', ... + 'shape', shape, ... + 'cxs', 'auto'); + end + + for i = 1:numel(montage_overlay) + rbgclr = rgbcolors(i, :); + clr = cat(3, rbgclr(1) * oo, rbgclr(2) * oo, rbgclr(3) * oo); + imC = imagesc(ax, clr); + set(imC, 'AlphaData', alpha * montage_overlay{i}.whole_img); + if plot_contour + bound_whole_bin = bwboundaries(montage_overlay{i}.whole_img); + Nblobs_bin = numel(bound_whole_bin); + for b = 1:Nblobs_bin + p = plot(ax, bound_whole_bin{b, 1}(:, 2), bound_whole_bin{b, 1}(:, 1), 'color', rbgclr, 'LineWidth', 1); + end + end + end + + hold(ax, 'off'); + set(ax, 'xtick', []); + set(ax, 'xticklabel', []); + set(ax, 'ytick', []); + set(ax, 'yticklabel', []); + set(ax, 'ztick', []); + set(ax, 'zticklabel', []); + + output.ax = ax; + output.f = f; + + if saveAs ~= 0 + print(f, saveAs, '-dpng', '-r0'); + end + % Close necessary figure handles + close(montage_template.f); + for i = 1:numel(montage_overlay) + close(montage_overlay{i}.f); + end + if strcmp(visibility, 'off') + close(f); + end diff --git a/fmrwhy_util_createOverlayMontage.m b/fmrwhy_util_createOverlayMontage.m index 43bed597..bcea0aaf 100644 --- a/fmrwhy_util_createOverlayMontage.m +++ b/fmrwhy_util_createOverlayMontage.m @@ -19,17 +19,10 @@ % Create background montage montage_template = fmrwhy_util_createMontage(templateImg, columns, rotate, 'Template volume', clrmp, 'off', shape, cxs); - % Get screen size for plotting - scr_size = get(0, 'ScreenSize'); - dist = scr_size(4); - if scr_size(3) < dist - dist = scr_size(3); - end % Create figures with background montage and overlaid masks - % f(i) = figure('units','pixels','outerposition',[0 0 dist dist]); f = figure('units', 'normalized', 'outerposition', [0 0 1 1], 'visible', visibility); - im1 = imagesc(montage_template.whole_img); + imagesc(montage_template.whole_img); colormap(clrmp); if ~isempty(cxs) caxis(cxs); @@ -45,10 +38,6 @@ hold(ax, 'on'); [Nimx, Nimy] = size(montage_template.whole_img); oo = ones(Nimx, Nimy); - zz = zeros(Nimx, Nimy); - red = cat(3, oo, zz, zz); - green = cat(3, zz, oo, zz); - blue = cat(3, zz, oo, oo); if iscell(overlayImg) for i = 1:numel(overlayImg) @@ -68,7 +57,7 @@ bound_whole_bin = bwboundaries(montage_overlay{i}.whole_img); Nblobs_bin = numel(bound_whole_bin); for b = 1:Nblobs_bin - p = plot(ax, bound_whole_bin{b, 1}(:, 2), bound_whole_bin{b, 1}(:, 1), 'color', rbgclr, 'LineWidth', 1); + plot(ax, bound_whole_bin{b, 1}(:, 2), bound_whole_bin{b, 1}(:, 1), 'color', rbgclr, 'LineWidth', 1); end end end diff --git a/untitled.m b/untitled.m index aeabd316..893894ea 100644 --- a/untitled.m +++ b/untitled.m @@ -1,4 +1,5 @@ % (C) Copyright 2022 bidspm developers +close all; bidspm_dir = '/home/remi/github/cpp-lln-lab/bidspm'; @@ -6,32 +7,11 @@ template_img = fullfile(bidspm_dir, 'demos/MoAE/outputs/derivatives/bidspm-preproc/sub-01/func/sub-01_task-auditory_space-MNI152NLin6Asym_desc-smth8_bold.nii'); -columns = 9; - -rotate = 1; - -str = ''; - -clrmp = 'gray'; - -visibility = 'on'; - -saveAs_fn = 0; - template_hdr = spm_vol(template_img); template = spm_read_vols(template_hdr(1)); mask_hdr = spm_vol(overlay_img); mask = spm_read_vols(mask_hdr); -fmrwhy_util_createOverlayMontage(template, ... - mask, ... - columns, ... - rotate, ... - '', ... - clrmp, ... - visibility, ... - 'max', ... - [0 255], ... - [33, 168, 10], ... - saveAs_fn); +% createMontage(template, 'shape', 'square'); +createOverlayMontage(template, mask, 'rgbcolors', [255, 0, 0], 'shape', 'square'); From b0ffa5251c1f2cc759f957269762deda03212e3f Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 19 Sep 2024 09:23:22 +0200 Subject: [PATCH 3/4] ref --- fmrwhy_util_createMontage.m | 114 ----------------------------- fmrwhy_util_createOverlayMontage.m | 86 ---------------------- miss_hit.cfg | 6 +- 3 files changed, 3 insertions(+), 203 deletions(-) delete mode 100644 fmrwhy_util_createMontage.m delete mode 100644 fmrwhy_util_createOverlayMontage.m diff --git a/fmrwhy_util_createMontage.m b/fmrwhy_util_createMontage.m deleted file mode 100644 index 2dbd9521..00000000 --- a/fmrwhy_util_createMontage.m +++ /dev/null @@ -1,114 +0,0 @@ -function montage = fmrwhy_util_createMontage(img, columns, rotate, str, clrmp, visibility, shape, cxs) - - % (C) Copyright 2022 bidspm developers - - % Simple function to create a montage / mosaic of multiple slices from a single 3D - % image matrix. TODO: Needs improvement i.t.o RAS/LAS orientation specification - % and image layout... - % - % INPUT: - % img - 3D (x,y,z) image matrix - % columns - number of columns in montage (rows are calculated accordingly) - % rotate - rotate images 90 deg clockwise? yes = 1; no = 0. - % str - figure title - % clrmp - figure colormap - % visibility - show figure? - % - % OUTPUT: - % output - structure with montage data - - montage = struct; - [Ni, Nj, Nk] = size(img); - - % Rotate image slices if required - if rotate - img_orig = img; - clear img; - for p = 1:Nk - img(:, :, p) = rot90(img_orig(:, :, p)); - end - end - - % Determine amount of rows and filler slices - rows = floor(Nk / columns); - if rows == 0 - rows = 1; - end - fill = mod(Nk, columns); - if fill == 0 - N_fill = 0; - else - N_fill = columns - mod(Nk, columns); - end - if rotate - filler = zeros(Nj, Ni); - else - filler = zeros(Ni, Nj); - end - - montage.rows = rows; - montage.columns = columns; - montage.N_fill = N_fill; - - parts = {}; - % 1 - Concatenate slices together horizontally, per row (except last). - % 2 - Concatenate rows together vertically - for i = 1:rows - for j = 1:columns - if j == 1 - parts{i} = img(:, :, columns * (i - 1) + j); - else - parts{i} = cat(2, parts{i}, img(:, :, columns * (i - 1) + j)); - end - end - if i == 1 - whole = parts{i}; - else - whole = cat(1, whole, parts{i}); - end - end - - % 1 - Concatenate filler slices to last row, if required. - % 2 - Concatenate last row to whole matrix, if required. - if N_fill ~= 0 - % last row - last_parts = img(:, :, rows * columns + 1); - for k = (rows * columns + 2):Nk - last_parts = cat(2, last_parts, img(:, :, k)); - end - for m = 1:N_fill - last_parts = cat(2, last_parts, filler); - end - montage.whole_img = cat(1, whole, last_parts); - else - montage.whole_img = whole; - end - - % Get screen size for plotting - [1 1 w h] - scr_size = get(0, 'ScreenSize'); - dist = scr_size(4); - if scr_size(3) < dist - dist = scr_size(3); - end - - % Create figure - outerposition = [left bottom width height] - if strcmp(shape, 'max') - f = figure('visible', visibility, 'units', 'normalized', 'outerposition', [0 0 1 1]); - elseif strcmp(shape, 'square') - f = figure('visible', visibility, 'units', 'pixels', 'outerposition', [0 0 dist dist]); - else - f = figure('visible', visibility, 'units', 'pixels', 'outerposition', [0 0 dist dist]); - % daspect manual; - end - ax = subplot(1, 1, 1); - im = imagesc(ax, montage.whole_img); - colormap(clrmp); % colorbar; - if nargin == 8 - if ~isempty(cxs) - caxis(ax, cxs); - end - end - % title(str); - montage.im = im; - montage.f = f; - montage.ax = ax; diff --git a/fmrwhy_util_createOverlayMontage.m b/fmrwhy_util_createOverlayMontage.m deleted file mode 100644 index bcea0aaf..00000000 --- a/fmrwhy_util_createOverlayMontage.m +++ /dev/null @@ -1,86 +0,0 @@ -function output = fmrwhy_util_createOverlayMontage(templateImg, overlayImg, columns, rotate, str, clrmp, visibility, shape, cxs, rgbcolors, saveAs) - - % (C) Copyright 2022 bidspm developers - - % fmrwhy_util_createOverlayMontage(tsnr_img{i}, overlayImg, 9, 1, '', ... - % 'hot', 'off', 'max', [0 250], [33, 168, 10], tsnr_saveAss{i}); - - % Function to create montages of images/rois overlaid on a template image - - % Structure to save output - output = struct; - alpha = 0.2; - plot_contour = 1; - if rgbcolors == 0 - rgbcolors = [255, 255, 191; 215, 25, 28; 253, 174, 97; 171, 217, 233; 44, 123, 182] / 255; - else - rgbcolors = rgbcolors / 255; - end - - % Create background montage - montage_template = fmrwhy_util_createMontage(templateImg, columns, rotate, 'Template volume', clrmp, 'off', shape, cxs); - - % Create figures with background montage and overlaid masks - f = figure('units', 'normalized', 'outerposition', [0 0 1 1], 'visible', visibility); - imagesc(montage_template.whole_img); - colormap(clrmp); - if ~isempty(cxs) - caxis(cxs); - end - ax = gca; - outerpos = ax.OuterPosition; - ti = ax.TightInset; - left = outerpos(1) + ti(1); - bottom = outerpos(2) + ti(2); - ax_width = outerpos(3) - ti(1) - ti(3); - ax_height = outerpos(4) - ti(2) - ti(4); - ax.Position = [left bottom ax_width ax_height]; - hold(ax, 'on'); - [Nimx, Nimy] = size(montage_template.whole_img); - oo = ones(Nimx, Nimy); - - if iscell(overlayImg) - for i = 1:numel(overlayImg) - montage_overlay{i} = fmrwhy_util_createMontage(overlayImg{i}, columns, rotate, 'Overlay', clrmp, 'off', shape, 'auto'); - end - else - montage_overlay = {}; - montage_overlay{1} = fmrwhy_util_createMontage(overlayImg, columns, rotate, 'Overlay', clrmp, 'off', shape, 'auto'); - end - - for i = 1:numel(montage_overlay) - rbgclr = rgbcolors(i, :); - clr = cat(3, rbgclr(1) * oo, rbgclr(2) * oo, rbgclr(3) * oo); - imC = imagesc(ax, clr); - set(imC, 'AlphaData', alpha * montage_overlay{i}.whole_img); - if plot_contour - bound_whole_bin = bwboundaries(montage_overlay{i}.whole_img); - Nblobs_bin = numel(bound_whole_bin); - for b = 1:Nblobs_bin - plot(ax, bound_whole_bin{b, 1}(:, 2), bound_whole_bin{b, 1}(:, 1), 'color', rbgclr, 'LineWidth', 1); - end - end - end - - hold(ax, 'off'); - set(ax, 'xtick', []); - set(ax, 'xticklabel', []); - set(ax, 'ytick', []); - set(ax, 'yticklabel', []); - set(ax, 'ztick', []); - set(ax, 'zticklabel', []); - - output.ax = ax; - output.f = f; - - if saveAs ~= 0 - print(f, saveAs, '-dpng', '-r0'); - end - % Close necessary figure handles - close(montage_template.f); - for i = 1:numel(montage_overlay) - close(montage_overlay{i}.f); - end - if strcmp(visibility, 'off') - close(f); - end diff --git a/miss_hit.cfg b/miss_hit.cfg index 184ae47f..d7a1a245 100644 --- a/miss_hit.cfg +++ b/miss_hit.cfg @@ -3,7 +3,7 @@ project_root octave: true # style guide (https://florianschanda.github.io/miss_hit/style_checker.html) -line_length: 250 +line_length: 100 # camelCase regex_function_name: "[a-z]+(_*[a-zA-Z0-9]+[a-z]*)*" @@ -36,7 +36,7 @@ copyright_entity: "Wellcome Trust Centre for Neuroimaging" tab_width: 2 # metrics limit for the code quality (https://florianschanda.github.io/miss_hit/metrics.html) -metric "cnest": limit 9 +metric "cnest": limit 7 metric "file_length": limit 1000 metric "cyc": limit 22 -metric "parameters": limit 12 +metric "parameters": limit 9 From 8ee871bac389f0fa85a430fc98f3d2c7e83f4a67 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 19 Sep 2024 09:44:56 +0200 Subject: [PATCH 4/4] ref --- miss_hit.cfg | 6 ++-- .../plotting/createMontage.m | 28 ++++--------------- .../plotting/createOverlayMontage.m | 15 +++++----- src/plotting/initMontageFigure.m | 24 ++++++++++++++++ untitled.m | 13 +++++++-- 5 files changed, 50 insertions(+), 36 deletions(-) rename createMontage.m => src/plotting/createMontage.m (78%) rename createOverlayMontage.m => src/plotting/createOverlayMontage.m (90%) create mode 100644 src/plotting/initMontageFigure.m diff --git a/miss_hit.cfg b/miss_hit.cfg index d7a1a245..727d20b4 100644 --- a/miss_hit.cfg +++ b/miss_hit.cfg @@ -36,7 +36,7 @@ copyright_entity: "Wellcome Trust Centre for Neuroimaging" tab_width: 2 # metrics limit for the code quality (https://florianschanda.github.io/miss_hit/metrics.html) -metric "cnest": limit 7 +metric "cnest": limit 4 metric "file_length": limit 1000 -metric "cyc": limit 22 -metric "parameters": limit 9 +metric "cyc": limit 20 +metric "parameters": limit 6 diff --git a/createMontage.m b/src/plotting/createMontage.m similarity index 78% rename from createMontage.m rename to src/plotting/createMontage.m index 6ca3c474..550bdef4 100644 --- a/createMontage.m +++ b/src/plotting/createMontage.m @@ -11,12 +11,14 @@ % 'cxs', [0 255]) % % - % Simple function to create a montage / mosaic of multiple slices from a single 3D + % Simple function to create a montage / + % mosaic of multiple slices from a single 3D % image matrix. % % INPUT: % img - 3D (x,y,z) image matrix - % columns - number of columns in montage (rows are calculated accordingly) + % columns - number of columns in montage + % (rows are calculated accordingly) % rotate - rotate images 90 deg clockwise? yes = 1; no = 0. % cmap - figure colormap % visibility - show figure? @@ -116,27 +118,7 @@ montage.whole_img = whole; end - % Get screen size for plotting - [1 1 w h] - scr_size = get(0, 'ScreenSize'); - dist = scr_size(4); - if scr_size(3) < dist - dist = scr_size(3); - end - - % Create figure - outerposition = [left bottom width height] - if strcmp(shape, 'max') - f = figure('visible', visibility, ... - 'units', 'normalized', ... - 'outerposition', [0 0 1 1]); - elseif strcmp(shape, 'square') - f = figure('visible', visibility, ... - 'units', 'pixels', ... - 'outerposition', [0 0 dist dist]); - else - f = figure('visible', visibility, ... - 'units', 'pixels', ... - 'outerposition', [0 0 dist dist]); - end + f = initMontageFigure(shape, visibility); ax = subplot(1, 1, 1); im = imagesc(ax, montage.whole_img); diff --git a/createOverlayMontage.m b/src/plotting/createOverlayMontage.m similarity index 90% rename from createOverlayMontage.m rename to src/plotting/createOverlayMontage.m index 1296d9b5..2897ef27 100644 --- a/createOverlayMontage.m +++ b/src/plotting/createOverlayMontage.m @@ -1,6 +1,6 @@ function output = createOverlayMontage(varargin) - % (C) Copyright 2022 bidspm developers + % (C) Copyright 2024 bidspm developers % fmrwhy_util_createOverlayMontage(tsnr_img{i}, overlayImg, 9, 1, '', ... % 'hot', 'off', 'max', [0 250], [33, 168, 10], tsnr_saveAss{i}); @@ -55,9 +55,7 @@ 'cxs', cxs); % Create figures with background montage and overlaid masks - f = figure('units', 'normalized', ... - 'outerposition', [0 0 1 1], ... - 'visible', visibility); + f = initMontageFigure(shape, visibility); imagesc(montage_template.whole_img); colormap(cmap); if ~isempty(cxs) @@ -77,7 +75,8 @@ if iscell(overlayImg) for i = 1:numel(overlayImg) - montage_overlay{i} = createMontage(overlayImg{i}, 'columns', columns, ... + montage_overlay{i} = createMontage(overlayImg{i}, ... + 'columns', columns, ... 'rotate', rotate, ... 'cmap', cmap, ... 'visibility', 'off', ... @@ -86,7 +85,8 @@ end else montage_overlay = {}; - montage_overlay{1} = createMontage(overlayImg, 'columns', columns, ... + montage_overlay{1} = createMontage(overlayImg, ... + 'columns', columns, ... 'rotate', rotate, ... 'cmap', cmap, ... 'visibility', 'off', ... @@ -103,7 +103,8 @@ bound_whole_bin = bwboundaries(montage_overlay{i}.whole_img); Nblobs_bin = numel(bound_whole_bin); for b = 1:Nblobs_bin - p = plot(ax, bound_whole_bin{b, 1}(:, 2), bound_whole_bin{b, 1}(:, 1), 'color', rbgclr, 'LineWidth', 1); + p = plot(ax, bound_whole_bin{b, 1}(:, 2), bound_whole_bin{b, 1}(:, 1), ... + 'color', rbgclr, 'LineWidth', 1); end end end diff --git a/src/plotting/initMontageFigure.m b/src/plotting/initMontageFigure.m new file mode 100644 index 00000000..38a43655 --- /dev/null +++ b/src/plotting/initMontageFigure.m @@ -0,0 +1,24 @@ +function f = initMontageFigure(shape, visibility) + % (C) Copyright 2024 bidspm developers + + scr_size = get(0, 'ScreenSize'); + dist = scr_size(4); + if scr_size(3) < dist + dist = scr_size(3); + end + % Create figure - outerposition = [left bottom width height] + + if strcmp(shape, 'max') + f = figure('visible', visibility, ... + 'units', 'normalized', ... + 'outerposition', [0 0 1 1]); + elseif strcmp(shape, 'square') + f = figure('visible', visibility, ... + 'units', 'pixels', ... + 'outerposition', [0 0 dist dist]); + else + f = figure('visible', visibility, ... + 'units', 'pixels', ... + 'outerposition', [0 0 dist dist]); + end +end diff --git a/untitled.m b/untitled.m index 893894ea..5c2c1a8a 100644 --- a/untitled.m +++ b/untitled.m @@ -3,9 +3,15 @@ bidspm_dir = '/home/remi/github/cpp-lln-lab/bidspm'; -overlay_img = fullfile(bidspm_dir, 'demos/MoAE/outputs/derivatives/bidspm-stats/sub-01/task-auditory_space-MNI152NLin6Asym_FWHM-8/mask.nii'); +demos_dir = fullfile(bidspm_dir, 'demos/MoAE/outputs/derivatives/'); -template_img = fullfile(bidspm_dir, 'demos/MoAE/outputs/derivatives/bidspm-preproc/sub-01/func/sub-01_task-auditory_space-MNI152NLin6Asym_desc-smth8_bold.nii'); +overlay_img = fullfile(demos_dir, ... + 'bidspm-stats/sub-01/task-auditory_space-MNI152NLin6Asym_FWHM-8/mask.nii'); + +template_img = fullfile( ... + demos_dir, ... + 'bidspm-preproc', 'sub-01', 'func', ... + 'sub-01_task-auditory_space-MNI152NLin6Asym_desc-smth8_bold.nii'); template_hdr = spm_vol(template_img); template = spm_read_vols(template_hdr(1)); @@ -14,4 +20,5 @@ mask = spm_read_vols(mask_hdr); % createMontage(template, 'shape', 'square'); -createOverlayMontage(template, mask, 'rgbcolors', [255, 0, 0], 'shape', 'square'); +createOverlayMontage(template, mask, 'rgbcolors', [255, 0, 0], ... + 'shape', 'square');