Skip to content

Commit

Permalink
Viz: Allow combining resection options (Surface tab)
Browse files Browse the repository at this point in the history
  • Loading branch information
rcassani committed Jun 7, 2024
1 parent 2919438 commit 88d350f
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 40 deletions.
2 changes: 1 addition & 1 deletion doc/license.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<body alink="#fff000" link="#fff000" vlink="#fff000">
<h4><span style="font-family: Arial Black; color: #ffffff;"><strong>THERE IS NO UNDO BUTTON!<BR>SET UP A <FONT color=red>BACKUP</FONT> OF YOUR DATABASE</strong></span></h4>
<HR>
<!-- LICENCE_START -->Version: 3.240606 (06-Jun-2024)<br>
<!-- LICENCE_START -->Version: 3.240607 (07-Jun-2024)<br>
<span style="font-style: italic;">COPYRIGHT &copy; 2000-2024
USC &amp; McGill University.<br>
</span>
Expand Down
2 changes: 1 addition & 1 deletion doc/version.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
% Brainstorm
% v. 3.240606 (06-Jun-2024)
% v. 3.240607 (07-Jun-2024)
3 changes: 2 additions & 1 deletion toolbox/db/db_template.m
Original file line number Diff line number Diff line change
Expand Up @@ -1049,11 +1049,12 @@
'SizeThreshold', 1, ... % Threshold to apply to color coding of data values
'DataLimitValue', [], ... % Relative limits for colormapping
'CutsPosition', [0 0 0], ... % Position of the three orthogonal MRI slices
'Resect', 'none', ... % Either [x,y,z] resect values, or {'left', 'right', 'none'}
'Resect', [], ... % 2 cells: Resect values [x,y,z] and resect sections {'left', 'right', 'struct', 'none'}
'MipAnatomy', [], ... % 3 cells: Maximum intensity power in each direction (MRI amplitudes)
'MipFunctional', [], ... % 3 cells: Maximum intensity power in each direction (sources amplitudes)
'StatThreshOver', [], ...
'StatThreshUnder', []);
template.Resect = {[0,0,0], 'none'};
template.MipAnatomy = cell(3,1);
template.MipFunctional = cell(3,1);

Expand Down
28 changes: 16 additions & 12 deletions toolbox/gui/figure_3d.m
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,8 @@ function FigureMouseMoveCallback(hFig, varargin)
posXYZ = [NaN, NaN, NaN];
posXYZ(moveAxis) = newPos;
panel_surface('PlotMri', hFig, posXYZ, 1);
% Update sliders in surface panel
panel_surface('UpdateSurfaceProperties');
end
end
end
Expand Down Expand Up @@ -3382,7 +3384,7 @@ function UpdateSurfaceAlpha(hFig, iTess)
% Apply current smoothing
SmoothSurface(hFig, iTess, Surface.SurfSmoothValue);
% Apply structures selection
if isequal(Surface.Resect, 'struct')
if isequal(Surface.Resect{2}, 'struct')
SetStructLayout(hFig, iTess);
end
% Get surfaces vertices
Expand All @@ -3398,7 +3400,7 @@ function UpdateSurfaceAlpha(hFig, iTess)
FaceVertexAlphaData = ones(length(sSurf.Faces),1) * (1-Surface.SurfAlpha);

% ===== HEMISPHERE SELECTION (CHAR) =====
if ischar(Surface.Resect) && ~strcmpi(Surface.Resect, 'none')
if ischar(Surface.Resect{2}) && ~strcmpi(Surface.Resect{2}, 'none')
% Detect hemispheres
if strcmpi(Surface.Name, 'FEM')
isConnected = 1;
Expand All @@ -3408,13 +3410,15 @@ function UpdateSurfaceAlpha(hFig, iTess)
% If there is no separation between left and right: use the numeric split
if isConnected
iHideVert = [];
switch (Surface.Resect)
case 'right', Surface.Resect = [0 0.0000001 0];
case 'left', Surface.Resect = [0 -0.0000001 0];
switch (Surface.Resect{2})
case 'right'
Surface.Resect{1}(2) = max( 0.0000001, Surface.Resect{1}(2));
case 'left'
Surface.Resect{1}(2) = min(-0.0000001, Surface.Resect{1}(2));
end
% If there is a structural separation between left and right: usr
else
switch (Surface.Resect)
switch (Surface.Resect{2})
case 'right', iHideVert = lH;
case 'left', iHideVert = rH;
otherwise, iHideVert = [];
Expand All @@ -3428,20 +3432,20 @@ function UpdateSurfaceAlpha(hFig, iTess)
end

% ===== RESECT (DOUBLE) =====
if isnumeric(Surface.Resect) && (length(Surface.Resect) == 3) && (~all(Surface.Resect == 0) || strcmpi(Surface.Name, 'FEM'))
if isnumeric(Surface.Resect{1}) && (length(Surface.Resect{1}) == 3) && (~all(Surface.Resect{1} == 0) || strcmpi(Surface.Name, 'FEM'))
% Regular triangular surface
if ~strcmpi(Surface.Name, 'FEM')
iNoModif = [];
% Compute mean and max of the coordinates
meanVertx = mean(Vertices, 1);
maxVertx = max(abs(Vertices), [], 1);
% Limit values
resectVal = Surface.Resect .* maxVertx + meanVertx;
resectVal = Surface.Resect{1} .* maxVertx + meanVertx;
% Get vertices that are kept in all the cuts
for iCoord = 1:3
if Surface.Resect(iCoord) > 0
if Surface.Resect{1}(iCoord) > 0
iNoModif = union(iNoModif, find(Vertices(:,iCoord) < resectVal(iCoord)));
elseif Surface.Resect(iCoord) < 0
elseif Surface.Resect{1}(iCoord) < 0
iNoModif = union(iNoModif, find(Vertices(:,iCoord) > resectVal(iCoord)));
end
end
Expand All @@ -3466,7 +3470,7 @@ function UpdateSurfaceAlpha(hFig, iTess)
% For the projected vertices: get the distance from each cut
distToCut = abs(Vertices(iVerticesToProject, :) - repmat(resectVal, [length(iVerticesToProject), 1]));
% Set the distance to the cuts that are not required to infinite
distToCut(:,(Surface.Resect == 0)) = Inf;
distToCut(:,(Surface.Resect{1} == 0)) = Inf;
% Get the closest cut
[minDist, closestCut] = min(distToCut, [], 2);

Expand Down Expand Up @@ -3495,7 +3499,7 @@ function UpdateSurfaceAlpha(hFig, iTess)
else
% Create a surface for the outside surface of this tissue
Elements = get(Surface.hPatch, 'UserData');
Faces = tess_voledge(Vertices, Elements, Surface.Resect);
Faces = tess_voledge(Vertices, Elements, Surface.Resect{1});
% Update patch
set(Surface.hPatch, 'Faces', Faces);
end
Expand Down
4 changes: 2 additions & 2 deletions toolbox/gui/panel_scout.m
Original file line number Diff line number Diff line change
Expand Up @@ -4417,9 +4417,9 @@ function PlotScouts(iScouts, hFigSel)
continue;
end
% Skip the display of the scouts that are on a hidden half of the cortex (for struct atlas)
if isequal(sSurface.Resect, 'left') && ~isempty(sScouts(i).Region) && (sScouts(i).Region(1) == 'R')
if isequal(sSurface.Resect{2}, 'left') && ~isempty(sScouts(i).Region) && (sScouts(i).Region(1) == 'R')
continue;
elseif isequal(sSurface.Resect, 'right') && ~isempty(sScouts(i).Region) && (sScouts(i).Region(1) == 'L')
elseif isequal(sSurface.Resect{2}, 'right') && ~isempty(sScouts(i).Region) && (sScouts(i).Region(1) == 'L')
continue;
end
% Get indice of the target figure in the sScouts.Handles array
Expand Down
32 changes: 9 additions & 23 deletions toolbox/gui/panel_surface.m
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@
jToggleResectLeft = gui_component('toggle', jPanelSurfaceResect, 'br center', 'Left', {Insets(0,0,0,0), Dimension(BUTTON_WIDTH-3, DEFAULT_HEIGHT)}, '', @ButtonResectLeftToggle_Callback);
jToggleResectRight = gui_component('toggle', jPanelSurfaceResect, '', 'Right', {Insets(0,0,0,0), Dimension(BUTTON_WIDTH-3, DEFAULT_HEIGHT)}, '', @ButtonResectRightToggle_Callback);
jToggleResectStruct = gui_component('toggle', jPanelSurfaceResect, '', 'Struct', {Insets(0,0,0,0), Dimension(BUTTON_WIDTH-3, DEFAULT_HEIGHT)}, '', @ButtonResectStruct_Callback);
jButtonResectReset = gui_component('button', jPanelSurfaceResect, '', 'Reset', {Insets(0,0,0,0), Dimension(BUTTON_WIDTH-3, DEFAULT_HEIGHT)}, '', @ButtonResectResetCallback);
jButtonResectReset = gui_component('button', jPanelSurfaceResect, '', 'Reset', {Insets(0,0,0,0), Dimension(BUTTON_WIDTH-3, DEFAULT_HEIGHT)}, '', @ButtonResectResetCallback);
jPanelOptions.add(jPanelSurfaceResect);

% ===== SURFACE LABELS =====
Expand Down Expand Up @@ -308,7 +308,10 @@ function ButtonResectResetCallback(varargin)
if strcmpi(TessInfo(iSurf).Name, 'FEM')
iSurf = find(strcmpi({TessInfo.Name}, 'FEM'));
end
[TessInfo(iSurf).Resect] = deal('none');
for ix = 1 : length(iSurf)
TessInfo(iSurf(ix)).Resect{1} = [0, 0, 0];
TessInfo(iSurf(ix)).Resect{2} = 'none';
end
setappdata(hFig, 'Surface', TessInfo);
SliderCallback([], MouseEvent(jSliderResectX, 0, 0, 0, 0, 0, 1, 0), 'ResectX');
end
Expand Down Expand Up @@ -705,13 +708,9 @@ function SelectHemispheres(name)
end
% Update surface Resect field
for i = 1:length(iSurf)
TessInfo(iSurf(i)).Resect = name;
TessInfo(iSurf(i)).Resect{2} = name;
end
setappdata(hFig, 'Surface', TessInfo);
% Reset all the resect sliders
ctrl.jSliderResectX.setValue(0);
ctrl.jSliderResectY.setValue(0);
ctrl.jSliderResectZ.setValue(0);
% Display progress bar
bst_progress('start', 'Select hemisphere', 'Selecting hemisphere...');
% Update surface display
Expand Down Expand Up @@ -739,13 +738,8 @@ function ResectSurface(hFig, iSurf, resectDim, resectValue)
end
% Update all selected surfaces
for i = 1:length(iSurf)
% If previously using "Select hemispheres"
if ischar(TessInfo(iSurf(i)).Resect)
% Reset "Resect" field
TessInfo(iSurf(i)).Resect = [0 0 0];
end
% Update value in Surface array
TessInfo(iSurf(i)).Resect(resectDim) = resectValue;
TessInfo(iSurf(i)).Resect{1}(resectDim) = resectValue;
end
% Update surface
setappdata(hFig, 'Surface', TessInfo);
Expand All @@ -764,11 +758,6 @@ function ResectSurface(hFig, iSurf, resectDim, resectValue)
figure_callback(hFig, 'PlotTensorCut', hFig, resectValue, resectDim, 1);
end
end
% Deselect both Left and Right buttons
ctrl = bst_get('PanelControls', 'Surface');
ctrl.jToggleResectLeft.setSelected(0);
ctrl.jToggleResectRight.setSelected(0);
ctrl.jToggleResectStruct.setSelected(0);
% Close progress bar
if isProgress
bst_progress('text', 'Updating figure...');
Expand Down Expand Up @@ -1188,12 +1177,9 @@ function UpdateSurfaceProperties()
ResectXYZ = [0,0,0];
end
radioSelected = 'none';
elseif ischar(TessInfo(iSurface).Resect)
ResectXYZ = [0,0,0];
radioSelected = TessInfo(iSurface).Resect;
else
ResectXYZ = 100 * TessInfo(iSurface).Resect;
radioSelected = 'none';
ResectXYZ = 100 * TessInfo(iSurface).Resect{1};
radioSelected = TessInfo(iSurface).Resect{2};
end
% X, Y, Z
ctrl.jSliderResectX.setValue(ResectXYZ(1));
Expand Down

0 comments on commit 88d350f

Please sign in to comment.