function varargout = orthoview3d(varargin)
%ORTHOVIEW3D GUI for interactive viewing of 3D Volumes
% ORTHOVIEW3D is used to view orthographic slices of 3D volumes
%
% Type in an expression that generates a 3D array
% then press the Display button
%
% 3D expressions such as: rand(50,40,30) or
% the name or a 3D array variable in the workspace
%
% Use the scroll bars to change the number of the slice viewed
%
% Use the transpose, flipud, or fliplr to
% transpose the view, flip it vertically, or horizontally
%
% Change the Pixel Size values to the volume's physical dimensions
% so the aspect ratio is displayed properly
% (note: you can use relative values
% for example use 1,3,2 instead of 0.5,1.5,1.0
% then press "Adjust Pixel Size"
%
% Example:
% load defrise
% orthoview3d
% (Type 'defrise' in the box where 'rand(50,40,30)' appears)
% (Press 'Display')
%
% See also: VIEW3D, SLICE, MONTAGE, ISOSURFACE
%
% Jered R Wells
% 02/10/2012
% jered [dot] wells [at] gmail [dot] com
%
% Author's Note
% This file was adapted from ORTHOVIEW by Ghassan Hamarneh (see ref).
% It has been accelerated and simplified for viewing larger volumes.
% A simple window/level tool has also been added to supplement the
% viewing of medical images with familiar tools.
%
% Acknowledgement to:
% http://www.mathworks.de/matlabcentral/fileexchange/2256-orthoview
% Ghassan Hamarneh, ghamarneh@yahoo.com
%
if ~isempty(varargin) & (all(size(varargin{1})==[3 1]) | all(size(varargin{1})==[1 3]))
spanvar=varargin{1};
end
if nargin == 0 | exist('spanvar')% LAUNCH GUI
fig = openfig(mfilename,'reuse'); % Generate a structure of handles to pass to callbacks, and store it.
handles = guihandles(fig);
guidata(fig, handles);
if nargout > 0
varargout{1} = fig;
end
if exist('spanvar')
set(handles.edit2,'string',num2str(spanvar(1)))
set(handles.edit3,'string',num2str(spanvar(2)))
set(handles.edit4,'string',num2str(spanvar(3)))
end
elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK
try
if (nargout)
[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
else
feval(varargin{:}); % FEVAL switchyard
end
catch
disp(lasterr);
end
end
%| ABOUT CALLBACKS:
%| GUIDE automatically appends subfunction prototypes to this file, and
%| sets objects' callback properties to call them through the FEVAL
%| switchyard above. This comment describes that mechanism.
%|
%| Each callback subfunction declaration has the following form:
%| <SUBFUNCTION_NAME>(H, EVENTDATA, HANDLES, VARARGIN)
%|
%| The subfunction name is composed using the object's Tag and the
%| callback type separated by '_', e.g. 'slider2_Callback',
%| 'view3d_CloseRequestFcn', 'axis1_ButtondownFcn'.
%|
%| H is the callback object's handle (obtained using GCBO).
%|
%| EVENTDATA is empty, but reserved for future use.
%|
%| HANDLES is a structure containing handles of components in GUI using
%| tags as fieldnames, e.g. handles.orthoview3d, handles.slider2. This
%| structure is created at GUI startup using GUIHANDLES and stored in
%| the figure's application data using GUIDATA. A copy of the structure
%| is passed to each callback. You can store additional information in
%| this structure at GUI startup, and you can change the structure
%| during callbacks. Call guidata(h, handles) after changing your
%| copy to replace the stored original so that subsequent callbacks see
%| the updates. Type "help guihandles" and "help guidata" for more
%| information.
%|
%| VARARGIN contains any extra arguments you have passed to the
%| callback. Specify the extra arguments by editing the callback
%| property in the inspector. By default, GUIDE sets the property to:
%| <MFILENAME>('<SUBFUNCTION_NAME>', gcbo, [], guidata(gcbo))
%| Add any extra arguments after the last argument, before the final
%| closing parenthesis.
% --------------------------------------------------------------------
function varargout = slider1_Callback(h, eventdata, handles, varargin)
myplot1(handles);
% --------------------------------------------------------------------
function varargout = slider2_Callback(h, eventdata, handles, varargin)
myplot2(handles);
% --------------------------------------------------------------------
function varargout = slider3_Callback(h, eventdata, handles, varargin)
myplot3(handles);
% --------------------------------------------------------------------
function varargout = edit1_Callback(h, eventdata, handles, varargin)
% --------------------------------------------------------------------
function varargout = pushbutton1_Callback(h, eventdata, handles, varargin)
a=get(handles.edit1,'String');
handles.vol=double(squeeze(evalin('base',a)));
if ndims(handles.vol)~=3,
disp('Requested volume is not 3-D')
return
end
% Make all objects visible
set(handles.checkbox1,'Visible','on')
set(handles.checkbox2,'Visible','on')
set(handles.checkbox3,'Visible','on')
set(handles.checkbox4,'Visible','on')
set(handles.checkbox5,'Visible','on')
set(handles.checkbox6,'Visible','on')
set(handles.checkbox7,'Visible','on')
set(handles.checkbox8,'Visible','on')
set(handles.checkbox9,'Visible','on')
set(handles.checkbox11,'Visible','on')
set(handles.axes1,'Visible','on')
set(handles.axes2,'Visible','on')
set(handles.axes3,'Visible','on')
set(handles.slider1,'Visible','on')
set(handles.slider2,'Visible','on')
set(handles.slider3,'Visible','on')
set(handles.text1,'Visible','on')
set(handles.text2,'Visible','on')
set(handles.text3,'Visible','on')
set(handles.text7,'Visible','on')
set(handles.text8,'Visible','on')
set(handles.text9,'Visible','on')
set(handles.edit2,'Visible','on')
set(handles.edit3,'Visible','on')
set(handles.edit4,'Visible','on')
set(handles.pushbutton7,'Visible','on')
[handles.sx,handles.sy,handles.sz]=size(handles.vol);
set(handles.slider1,'min',1);
set(handles.slider2,'min',1);
set(handles.slider3,'min',1);
set(handles.slider1,'max',handles.sx);
set(handles.slider2,'max',handles.sy);
set(handles.slider3,'max',handles.sz);
set(handles.slider1,'SliderStep',[1/handles.sx 5/handles.sx]);
set(handles.slider2,'SliderStep',[1/handles.sy 5/handles.sy]);
set(handles.slider3,'SliderStep',[1/handles.sz 5/handles.sz]);
set(handles.slider1,'value',round(handles.sx/2)+1);
set(handles.slider2,'value',round(handles.sy/2)+1);
set(handles.slider3,'value',round(handles.sz/2)+1);
global vmx vmn sp1 sp2 sp3
vmx=max(handles.vol(:));
vmn=min(handles.vol(:));
sp1=handles.sx/str2double(get(handles.edit2,'string'));
sp2=handles.sy/str2double(get(handles.edit3,'string'));
sp3=handles.sz/str2double(get(handles.edit4,'string'));
%axes(handles.axes1);imagesc(squeeze(handles.vol(1,:,:)));axis image;
%axes(handles.axes2);imagesc(squeeze(handles.vol(:,1,:)));axis image;
%axes(handles.axes3);imagesc(squeeze(handles.vol(:,:,1)));axis image;
set(gcf,'DoubleBuffer','on');
% myplot(handles,[1 2 3]);
myplot1(handles)
myplot2(handles)
myplot3(handles)
%%% produced error in matlab 7.0
%if ~isfield(handles,'clrmnu')
% handles.clrmnu=0;
%end
%if ~handles.clrmnu;
% colormenu;
% handles.clrmnu=1;
%end
guidata(h,handles);
% --------------------------------------------------------------------
function varargout = checkbox1_Callback(h, eventdata, handles, varargin)
myplot1(handles);
% --------------------------------------------------------------------
function varargout = checkbox2_Callback(h, eventdata, handles, varargin)
myplot2(handles);
% --------------------------------------------------------------------
function varargout = checkbox3_Callback(h, eventdata, handles, varargin)
myplot3(handles);
% --------------------------------------------------------------------
function varargout = checkbox4_Callback(h, eventdata, handles, varargin)
myplot1(handles);
% --------------------------------------------------------------------
function varargout = checkbox5_Callback(h, eventdata, handles, varargin)
myplot2(handles);
% --------------------------------------------------------------------
function varargout = checkbox6_Callback(h, eventdata, handles, varargin)
myplot3(handles);
% --------------------------------------------------------------------
function varargout = checkbox7_Callback(h, eventdata, handles, varargin)
myplot1(handles);
% --------------------------------------------------------------------
function varargout = checkbox8_Callback(h, eventdata, handles, varargin)
myplot2(handles);
% --------------------------------------------------------------------
function varargout = checkbox9_Callback(h, eventdata, handles, varargin)
myplot3(handles);
% --------------------------------------------------------------------
function varargout = pushbutton2_Callback(h, eventdata, handles, varargin)
helpdlg({'3D Volume Orthoslice Viewer','Jered Wells v1.2'})
% --------------------------------------------------------------------
function myplot1(handles)
global dmx dmn sp1 sp2 sp3
% x -- y z
s1=round(get(handles.slider1,'value'));
I=squeeze(handles.vol(s1,:,:))';
if get(handles.checkbox1,'value'), I=I'; end
if get(handles.checkbox4,'value'), I=flipud(I); end
if get(handles.checkbox7,'value'), I=fliplr(I); end
% axes(handles.axes1);imagesc(I);
axes(handles.axes1);
if get(handles.checkbox11,'value');imagesc(I,[dmn,dmx]);else imagesc(I);end
colormap gray
axis off
% axis image
pbaspect('manual')
pbaspect(handles.axes1,[sp1,sp3,sp2]);
% c=get(handles.axes1,'Children'); set(c(1),'cdata',I);
set(handles.text1,'string',['x=',num2str(s1)])
% title('y-z')
function myplot2(handles)
global dmx dmn sp1 sp2 sp3
% y -- x z
s2=round(get(handles.slider2,'value'));
I=squeeze(handles.vol(:,s2,:));
if get(handles.checkbox2,'value'), I=I'; end
if get(handles.checkbox5,'value'), I=flipud(I); end
if get(handles.checkbox8,'value'), I=fliplr(I); end
% axes(handles.axes2);imagesc(I);
axes(handles.axes2);
if get(handles.checkbox11,'value');imagesc(I,[dmn,dmx]);else imagesc(I);end
colormap gray
axis off
% axis image
pbaspect('manual')
pbaspect(handles.axes2,[sp3,sp2,sp1]);
% c=get(handles.axes2,'Children'); set(c(1),'cdata',I);
set(handles.text2,'string',['y=',num2str(s2)])
% title('x-z')
function myplot3(handles)
% z -- x y
global dmx dmn sp1 sp2 sp3
s3=round(get(handles.slider3,'value'));
I=squeeze(handles.vol(:,:,s3));
if get(handles.checkbox3,'value'), I=I'; end
if get(handles.checkbox6,'value'), I=flipud(I); end
if get(handles.checkbox9,'value'), I=fliplr(I); end
% axes(handles.axes3); imagesc(I);
axes(handles.axes3);
if get(handles.checkbox11,'value');imagesc(I,[dmn,dmx]);else imagesc(I);end
colormap gray
axis off
% axis image
pbaspect('manual')
pbaspect(handles.axes3,[sp1,sp2,sp3]);
% c=get(handles.axes3,'Children'); set(c(1),'cdata',I);
set(handles.text3,'string',['z=',num2str(s3)])
% title('x-y')
% --------------------------------------------------------------------
function varargout = edit2_Callback(h, eventdata, handles, varargin)
% myplot(handles,[1 2 3]);
% myplot1(handles)
% myplot2(handles)
% myplot3(handles)
% --------------------------------------------------------------------
function varargout = edit3_Callback(h, eventdata, handles, varargin)
% myplot(handles,[1 2 3]);
% myplot1(handles)
% myplot2(handles)
% myplot3(handles)
% --------------------------------------------------------------------
function varargout = edit4_Callback(h, eventdata, handles, varargin)
% myplot(handles,[1 2 3]);
% myplot1(handles)
% myplot2(handles)
% myplot3(handles)
% --------------------------------------------------------------------
function pushbutton5_Callback(hObject, eventdata, handles)
helpdlg({'Type in an expression that generates a 3D array ',...
' then press the Load button ',...
'3D expressions such as: rand(50,40,30) or ',...
' the name or a 3D array variable in the workspace ',...
'The 3 views display orthographic projections ',...
'Use the scroll bars to change the number of the slice viewed '...
'Use the transpose, flipud, or fliplr to '...
' transpose the view, flip it vertically, or horizontally ',...
'Change the pixel sizes to adjust display dimensions ',...
' so the aspect ratio is displayed properly ',...
' (note: you can use relative values ',...
' for example use 1,3,2 instead of 0.5,1.5,1.0) ',...
' then press "Apply Pixel Values" '})
function pushbutton6_Callback(hObject, eventdata, handles)
if strcmp(questdlg('Exit OrthoView3D?','OrthoView3D','Yes','No','No'),'Yes')
close(handles.orthoview3d);
end
function pushbutton7_Callback(hObject, eventdata, handles)
global sp1 sp2 sp3
sp1=handles.sx*str2double(get(handles.edit2,'string'));
sp2=handles.sy*str2double(get(handles.edit3,'string'));
sp3=handles.sz*str2double(get(handles.edit4,'string'));
% myplot(handles,[1 2 3]);
myplot1(handles)
myplot2(handles)
myplot3(handles)
% --- Executes on button press in checkbox11.
function checkbox11_Callback(hObject, eventdata, handles)
% hObject handle to checkbox11 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: get(hObject,'Value') returns toggle state of checkbox11
global vmx vmn
if get(handles.checkbox11,'Value')
set(handles.text10,'Visible','on')
set(handles.text11,'Visible','on')
set(handles.axes6,'Visible','on')
set(handles.slider4,'Visible','on')
set(handles.slider5,'Visible','on')
set(handles.slider4,'min',vmn);
set(handles.slider5,'min',vmn);
set(handles.slider4,'max',vmx);
set(handles.slider5,'max',vmx);
set(handles.slider4,'value',vmx);
set(handles.slider5,'value',vmn);
plothist(handles)
else
set(handles.text10,'Visible','off')
set(handles.text11,'Visible','off')
axes(handles.axes6); cla
set(handles.axes6,'Visible','off')
set(handles.slider4,'Visible','off')
set(handles.slider5,'Visible','off')
end
myplot1(handles)
myplot2(handles)
myplot3(handles)
function plothist(handles)
global dmn dmx
n = numel(handles.vol(:));
axes(handles.axes6); cla
hist(handles.vol(:),100);
a = axis;
l = get(handles.slider5,'Value');
w = get(handles.slider4,'Value');
dmn = min(max(l,a(1)),a(2));
dmx = max(min(dmn+w,a(2)),dmn);
x = [a(1) dmn dmx a(2)];
axis off
hold on
y = [a(3) a(3) a(4) a(4)];
plot(x,y,'r-','LineWidth',2)
% --- Executes on slider movement.
function slider4_Callback(hObject, eventdata, handles)
plothist(handles)
myplot1(handles)
myplot2(handles)
myplot3(handles)
% --- Executes on slider movement.
function slider5_Callback(hObject, eventdata, handles)
plothist(handles)
myplot1(handles)
myplot2(handles)
myplot3(handles)
% --- Executes during object creation, after setting all properties.
function slider4_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
% --- Executes during object creation, after setting all properties.
function slider5_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end