Skip to content

Commit 48229ec

Browse files
committed
Merge branch 'develop'
2 parents 0ce7ca3 + 570c082 commit 48229ec

File tree

9 files changed

+404
-337
lines changed

9 files changed

+404
-337
lines changed

needles/@BrainAtlas/show.m

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
function h = show(self, h)
22
% display a 3D rendering of the brain
33

4-
5-
fv = isosurface(double(self.vol_labels) , 0.5);
4+
%%
5+
fv = isosurface(double(permute(self.vol_labels, [3, 2, 1])) , 0.5);
66
% in this case the volume is out in pixel unit, convert to SI
77
iorigin = self.brain_coor.iorigin;
8-
iorigin = iorigin([2 1 3]);
8+
iorigin = iorigin([2, 3, 1]);
99
fv.vertices = bsxfun( @minus, fv.vertices, iorigin);
1010
res = self.brain_coor.res;
11-
fv.vertices = fv.vertices.* res([2 1 3]);
11+
fv.vertices = fv.vertices.* res([2, 3, 1]);
1212

1313
if nargin <=1
14-
h.fig_volume = figure('Color','w'); h.ax = gca;
14+
h.fig_volume = figure('Color','w', 'name', ...
15+
'3D brain surface', 'numbertitle', 'off');
16+
h.ax = gca;
1517
end
1618
h.p = patch(fv);
17-
set(h.ax, 'DataAspectRatio',[1 1 1], 'zdir', 'reverse')
18-
xlabel(h.ax, 'x'), ylabel(h.ax, 'y'), zlabel(h.ax, 'z')
19+
set(h.ax, 'DataAspectRatio',[1 1 1], 'zdir', 'reverse', 'xdir', 'normal')
20+
xlabel(h.ax, 'ml'), ylabel(h.ax, 'ap'), zlabel(h.ax, 'dv')
1921
h.p.FaceColor = 'red';
2022
h.p.EdgeColor = 'none';
2123
h.p.FaceAlpha = 0.7;
22-
view([-5,-500,0]);
24+
view(-75, 45)
2325
camlight;
24-
26+
%%
2527
end
2628

needles/ElectrodeArray.m

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@
2121

2222
end
2323

24+
methods (Access = private)
25+
function dvmlap = dvmlap_alongprobe(E, dx)
26+
% computes the dv ml ap coordinates along the probe from tip.
27+
% maxes out at exit point
28+
dtip = E.dvmlap_entry - E.dvmlap_tip;
29+
[t, p, r] = cart2sph(dtip(:,1), dtip(:,2), dtip(:,3));
30+
[dv, ml, ap] = sph2cart(t, p, min(dx, r));
31+
dvmlap = [dv ml ap] + E.dvmlap_tip;
32+
end
33+
end
34+
2435
methods
2536
%% Constructor and adding probes methods
2637
function self = ElectrodeArray(dvmlap_entry, dvmlap_tip, varargin)
@@ -62,6 +73,7 @@ function removeAll(obj)
6273
% not enabled
6374

6475
% Z X Y is DV LR AP
76+
ELEC_LEN = 3.5e-3;
6577
a = sind(angles(2)); b = cosd(angles(2));
6678
vec = [a b 0];
6779

@@ -72,7 +84,7 @@ function removeAll(obj)
7284
entryIdx = find(lab>0,1);
7385
lastIdx = find(lab>0,1,'last');
7486
spanInBrain = sum(lab>0);
75-
if ~isempty(entryIdx) && (spanInBrain*spacing)>3.5e-3
87+
if ~isempty(entryIdx) && (spanInBrain*spacing) > ELEC_LEN
7688
entryZYX = trajThroughBrain(:,max(1,entryIdx-1))';
7789

7890
depthToLast = norm(trajThroughBrain(:,lastIdx)'-entryZYX);
@@ -91,6 +103,19 @@ function removeAll(obj)
91103
end
92104

93105
%% Geometry and computation methods
106+
function dvmlap = site_lowest(E, ind)
107+
low_end = min(E.site_coords(:,2));
108+
dvmlap = dvmlap_alongprobe(E, low_end);
109+
if nargin > 1, dvmlap = dvmlap(ind, :); end
110+
end
111+
112+
function dvmlap = site_highest(E, ind)
113+
high_end = max(E.site_coords(:,2));
114+
dvmlap = dvmlap_alongprobe(E, high_end);
115+
if nargin > 1, dvmlap = dvmlap(ind, :); end
116+
end
117+
118+
94119
function dvmlap = dvmlap_exit(obj) % out of the brain
95120

96121
end
@@ -125,8 +150,11 @@ function removeAll(obj)
125150
%% Export / Display and Plotting methods
126151
function [fig_elec, tab_elec]= show_table(obj)
127152
s = obj.to_struct;
128-
fig_elec = figure('color', 'w', 'toolbar', 'none', 'menubar', 'none', 'numbertitle',...
129-
'off', 'name', 'Electrode List');
153+
fig_elec = findobj('type', 'figure', 'tag', 'fig_electrode_table');
154+
if isempty(fig_elec)
155+
fig_elec = figure('color', 'w', 'toolbar', 'none', 'menubar', 'none', 'numbertitle',...
156+
'off', 'name', 'Electrode List', 'tag', 'fig_electrode_table');
157+
end
130158
tab_elec = uitable(fig_elec, 'Units', 'normalized', 'Position', [0 0 1 1]);
131159
tab_elec.Data = table2array(struct2table(s));
132160
tab_elec.ColumnName = fields(s);

needles/Needles.fig

1 Byte
Binary file not shown.

needles/Needles.m

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,14 @@ function Needles_OpeningFcn(hobj, evt, h, varargin)
4040
h.fcn.Update_Slices = @Update_Slices;
4141
h.fcn.Update_txt_electrodes = @Update_txt_electrodes;
4242
h.fcn.Update_Electrodes = @electrodes_update;
43-
h.fcn.Load_Atlas = @menu_file_loadatlas_Callback;
43+
h.fcn.Load_Atlas = @load_atlas;
4444
% wrap-up and save in handles
4545
guidata(hobj, h);
4646
varargout{1} = h.output;
4747

4848

4949
function load_atlas(h, atlas_label)
50+
% possible labels: 'allen50', 'ibl50', 'dsurqe', 'waxholm'
5051
cmap = 'bone';
5152
switch true
5253
case startsWith(atlas_label, 'ibl')
@@ -96,7 +97,7 @@ case strcmp(atlas_label, 'dsurqe')
9697

9798
% Create all the objects depending on the contrast axes
9899
h.im_phy = imagesc(bc.xscale, bc.zscale, D.atlas.vol_image(:,:,round(bc.y2i(0))), 'Parent', h.axes_phy);
99-
set(h.axes_phy, 'DataAspectRatio',[1 1 1], 'NextPlot', 'add')
100+
set(h.axes_phy, 'DataAspectRatio',[1 1 1], 'NextPlot', 'add', 'xdir', 'normal')
100101
h.pl_phy_origin = plot(h.axes_phy, 0,0, 'r+');
101102
h.pl_phy_xr = plot(h.axes_phy, [bc.xlim NaN 0 0], [0 0 NaN bc.ylim], 'Color', color_from_index(2));
102103
h.pl_phy_zone = plot(h.axes_phy, NaN, 0,'.','MarkerSize',4,'Color',color_from_index(5), 'ButtonDownFcn', @pl_zone_ButtonDownFcn);
@@ -109,8 +110,8 @@ case strcmp(atlas_label, 'dsurqe')
109110
xlabel(h.axes_phy, 'ML'), ylabel(h.axes_phy, 'DV')
110111
colormap(h.axes_phy, cmap)
111112
% Create all the objects depending on the label axes
112-
h.im_lab = imagesc(bc.xscale, bc.zscale, D.atlas.vol_labels(:,:,round(bc.y2i(0))), 'Parent', h.axes_label);
113-
set(h.axes_label, 'DataAspectRatio',[1 1 1], 'NextPlot', 'add')
113+
h.im_lab = imagesc(-bc.xscale, bc.zscale, D.atlas.vol_labels(:,:,round(bc.y2i(0))), 'Parent', h.axes_label);
114+
set(h.axes_label, 'DataAspectRatio',[1 1 1], 'NextPlot', 'add', 'xdir', 'normal')
114115
h.pl_lab_origin = plot(h.axes_label, 0,0, 'r+');
115116
h.pl_lab_xr = plot(h.axes_label, [bc.xlim NaN 0 0], [0 0 NaN bc.ylim], 'Color', color_from_index(2));
116117
h.pl_lab_zone = plot(h.axes_label, NaN, 0,'.','MarkerSize',4,'Color',color_from_index(5), 'ButtonDownFcn', @pl_zone_ButtonDownFcn);
@@ -126,7 +127,8 @@ case strcmp(atlas_label, 'dsurqe')
126127
set([h.pl_phy_xr, h.pl_lab_xr, h.pl_phy_zone, h.pl_lab_zone], 'Visible', 'Off')
127128
set(h.fig_main,'WindowButtonMotionFcn', {@fig_main_WindowButtonMotionFcn, h})
128129
% prevents from re-loading the Atlas for the time being
129-
set([h.menu_file_allen50, h.menu_file_dsurqe], 'Enable', 'off')
130+
set(h.menu_file, 'Enable', 'off')
131+
set(h.menu_3d_plot, 'Enable', 'on')
130132
h.txt_top_apline = text(NaN, NaN, '', 'Parent', h.axes_top, 'Color', color_from_index(2),'Fontsize',12, 'Fontweight', 'bold');
131133
guidata(h.fig_main, h)
132134
setappdata(h.fig_main, 'Data', D)
@@ -159,7 +161,6 @@ function pl_top_electrodes_ButtonDownFcn(hobj, evt, ie)
159161
set( h.pl_top_current_elec,'Visible', 'on',...
160162
'xdata', D.E.dvmlap_entry(ie,3), 'ydata', D.E.dvmlap_entry(ie,2))
161163
drawnow
162-
% get(h.fig_main, 'SelectionType')
163164
if false && ishandle(h.fig_table_elec)
164165
get(h.table_elec)
165166
jUIScrollPane = findjobj(h.table_elec);
@@ -171,11 +172,12 @@ function pl_top_electrodes_ButtonDownFcn(hobj, evt, ie)
171172
try % FIXME test for other Atlases without cmap
172173
% this will have to move to a method of Electrode Map
173174
ie = ie(1);
174-
f = findobj('Name', 'Trajectory', 'type', 'figure');
175+
f = findobj('Name', 'Trajectory', 'type', 'figure', 'tag', 'fig_trajectory');
175176
if isempty(f)
176-
f = figure('Color', 'w', 'Position', [200, 100, 380, 900], 'name', 'Trajectory', 'menubar', 'none', 'toolbar', 'none');
177-
h_.ax1 = subplot(5,1,1, 'parent', f);
178-
h_.ax2 = subplot(5,1,[2:5], 'parent', f);
177+
f = figure('Color', 'w', 'Position', [200, 100, 380, 900], 'name', 'Trajectory',...
178+
'menubar', 'none', 'toolbar', 'none', 'numbertitle', 'off', 'tag', 'fig_trajectory');
179+
h_.ax1 = subplot(5, 1, 1, 'parent', f);
180+
h_.ax2 = subplot(5, 1, [2 : 5], 'parent', f);
179181
guidata(f, h_);
180182
else
181183
h_ = guidata(f);
@@ -306,12 +308,13 @@ function Update_Labels(hobj, evt, ml_dv)
306308

307309

308310
function Update_Slices(hobj, evt, ap)
311+
NEAREST_DISTANCE_M = .00015;
309312
D = getappdata(hobj, 'Data');
310313
h = guidata(hobj);
311314
bc = D.atlas.brain_coor;
312315
% from the top axis handle line and associated text
313316
set(h.pl_top_apline, 'Xdata', ap([1 1]));
314-
ytxt = max(bc.xlim) - diff(bc.xlim)*0.05;
317+
ytxt = max(bc.xlim) - diff(bc.xlim) * 0.05;
315318
set(h.txt_top_apline, 'String', num2str(ap(1)*1e3, '%6.3f (mm) AP'), 'Position', [ap(1) ytxt 0])
316319
ap_slice = round(bc.y2i( ap(1)) );
317320
% display the coronal slices on the physio and MRI axes
@@ -329,26 +332,16 @@ function Update_Slices(hobj, evt, ap)
329332
end
330333
% Find the electrodes from the closest coronal plane
331334
[d, ie] = min(abs(ap(1) - D.E.dvmlap_entry(:,3)));
332-
i1 = abs( D.E.dvmlap_entry(:,3) - D.E.dvmlap_entry(ie,3)) < .0003;
335+
i1 = abs( D.E.dvmlap_entry(:,3) - D.E.dvmlap_entry(ie,3)) < NEAREST_DISTANCE_M;
333336
% Plot Electrodes
334337
lineplot = @(xyz0,xyz1,n) flatten([xyz0(:,n) xyz1(:,n) xyz1(:,n).*NaN]');
335-
% plot 10 degres insertions, active shank and full track
336-
% i1 = D.E.esel & ie & abs(D.E.theta) == 10*pi/180;
338+
337339
set([h.pl_phy_electrodes(1) h.pl_lab_electrodes(1)],...
338-
'xdata', lineplot(D.E.dvmlap_entry(i1,:), D.E.dvmlap_tip(i1,:),2),...
339-
'ydata', lineplot(D.E.dvmlap_entry(i1,:), D.E.dvmlap_tip(i1,:),1))
340+
'xdata', lineplot(D.E.site_lowest(i1), D.E.site_highest(i1),2),...
341+
'ydata', lineplot(D.E.site_lowest(i1), D.E.site_highest(i1),1))
340342
set([h.pl_phy_electrodes_traj(1) h.pl_lab_electrodes_traj(1)],...
341343
'xdata', lineplot(D.E.dvmlap_entry(i1,:), D.E.dvmlap_tip(i1,:),2),...
342344
'ydata', lineplot(D.E.dvmlap_entry(i1,:), D.E.dvmlap_tip(i1,:),1))
343-
% plot 20 degres insertions, active shank and full track
344-
% i2 = D.E.esel & ie & abs(D.E.theta) == 20*pi/180;
345-
% set([h.pl_phy_electrodes(2) h.pl_lab_electrodes(2)],...
346-
% 'xdata', lineplot(D.E.xyz0(i2,:), D.E.xyz_(i2,:),1),...
347-
% 'ydata', lineplot(D.E.xyz0(i2,:), D.E.xyz_(i2,:),3))
348-
% set([h.pl_phy_electrodes_traj(2) h.pl_lab_electrodes_traj(2)],...
349-
% 'xdata', lineplot(D.E.xyz_entry(i2,:), D.E.xyz_exit(i2,:),1),...
350-
% 'ydata', lineplot(D.E.xyz_entry(i2,:), D.E.xyz_exit(i2,:),3))
351-
352345

353346
function fig_main_KeyPressFcn(hobj, evt, h)
354347
h = guidata(h.fig_main);
@@ -418,3 +411,37 @@ function menu_file_dsurqe_Callback(hobj, evt, h)
418411
function menu_electrode_table_Callback(hobj, evt, h)
419412
function menu_electrode_load_Callback(hobj, evt, h)
420413
function menu_electrode_write_Callback(hobj, evt, h)
414+
415+
416+
% --------------------------------------------------------------------
417+
function menu_3d_plot_Callback(hobj, evt, h)
418+
h = guidata(h.fig_main);
419+
D = getappdata(h.fig_main, 'Data');
420+
421+
h3d = D.atlas.show();
422+
set(h3d.ax, 'NextPlot', 'add')
423+
pl3d = plot3(h3d.ax, D.E.dvmlap_entry(:,2), D.E.dvmlap_entry(:,3), D.E.dvmlap_entry(:,1), 'k*');
424+
set(h3d.p, 'FaceAlpha', 0.2)
425+
%% now display electrodes
426+
E = D.E;
427+
col = get(gca,'colororder');
428+
try delete(pl), end
429+
ie = find(E.pitch >= 0);
430+
high = E.site_highest(ie);
431+
low = E.site_lowest(ie);
432+
433+
pl(1) = plot3((flatten([high(:,2) low(:,2) ie.*NaN ]')) ,...
434+
(flatten([high(:,3) low(:,3) ie.*NaN ]')), ...
435+
(flatten([high(:,1) low(:,1) ie.*NaN ]')), ...
436+
'color', col(4,:), 'parent', h3d.ax);
437+
set(pl,'linewidth',1.5)
438+
439+
ie = find(E.pitch < 0);
440+
high = E.site_highest(ie);
441+
low = E.site_lowest(ie);
442+
443+
pl(2) = plot3((flatten([high(:,2) low(:,2) ie.*NaN ]')) ,...
444+
(flatten([high(:,3) low(:,3) ie.*NaN ]')), ...
445+
(flatten([high(:,1) low(:,1) ie.*NaN ]')), ...
446+
'color', col(5,:), 'parent', h3d.ax);
447+
set(pl,'linewidth',1.5)

0 commit comments

Comments
 (0)